commit 0fabc9bb0c15c25df5ba10958efd2d71fe64e0e8
parent 71191da8362e81e3d4688ae1823dc68037998bca
Author: Richard Bradfield <bradfier@fstab.me>
Date: Fri, 13 Jul 2018 12:54:53 +0000
Support extra2 and extra3 in title section
The groff .TH title/section macro additionally supports extra arguments:
.TH title section [extra1 [extra2 [extra3]]]
Extra2 and Extra3 allow changing the left footer and central header
respectively.
Here we allow the user to specify these fields through an optional
extension to the preamble:
test(8) "LeftFooter"
test(8) "LeftFooter" "CenterHeader"
test(8) "" "CenterHeader"
Diffstat:
3 files changed, 67 insertions(+), 2 deletions(-)
diff --git a/scdoc.1.scd b/scdoc.1.scd
@@ -22,11 +22,15 @@ Input files must use the UTF-8 encoding.
Each scdoc file must begin with the following preamble:
- *name*(_section_)
+ *name*(_section_) ["left\_footer" ["center\_header"]]
The *name* is the name of the man page you are writing, and _section_ is the
section you're writing for (see *man*(1) for information on manual sections).
+_left\_footer_ and _center\_header_ are optional arguments which set the text
+positioned at those locations in the generated man page, and *must* be surrounded
+with double quotes.
+
## SECTION HEADERS
Each section of your man page should begin with something similar to the
diff --git a/src/main.c b/src/main.c
@@ -37,8 +37,31 @@ static int parse_section(struct parser *p) {
return -1;
}
+static str_t *parse_extra(struct parser *p) {
+ str_t *extra = str_create();
+ int ret = str_append_ch(extra, '"');
+ assert(ret != -1);
+ uint32_t ch;
+ while ((ch = parser_getch(p)) != UTF8_INVALID) {
+ if (ch == '"') {
+ ret = str_append_ch(extra, ch);
+ assert(ret != -1);
+ return extra;
+ } else if (ch == '\n') {
+ parser_fatal(p, "Unclosed extra preamble field");
+ break;
+ } else {
+ ret = str_append_ch(extra, ch);
+ assert(ret != -1);
+ }
+ }
+ return NULL;
+}
+
static void parse_preamble(struct parser *p) {
str_t *name = str_create();
+ int ex = 0;
+ str_t *extras[2] = { NULL };
int section = -1;
uint32_t ch;
char date[256];
@@ -51,6 +74,11 @@ static void parse_preamble(struct parser *p) {
assert(str_append_ch(name, ch) != -1);
} else if (ch == '(') {
section = parse_section(p);
+ } else if (ch == '"') {
+ if (ex == 2) {
+ parser_fatal(p, "Too many extra preamble fields");
+ }
+ extras[ex++] = parse_extra(p);
} else if (ch == '\n') {
if (name->len == 0) {
parser_fatal(p, "Expected preamble");
@@ -59,11 +87,26 @@ static void parse_preamble(struct parser *p) {
parser_fatal(p, "Expected manual section");
}
char sec[2] = { '0' + section, 0 };
- roff_macro(p, "TH", name->str, sec, date, NULL);
+ char *ex2 = extras[0] != NULL ? extras[0]->str : NULL;
+ char *ex3 = extras[1] != NULL ? extras[1]->str : NULL;
+ fprintf(p->output, ".TH \"%s\" \"%s\" \"%s\"", name->str, sec, date);
+ /* ex2 and ex3 are already double-quoted */
+ if (ex2) {
+ fprintf(p->output, " %s", ex2);
+ }
+ if (ex3) {
+ fprintf(p->output, " %s", ex3);
+ }
+ fprintf(p->output, "\n");
break;
}
}
str_free(name);
+ for (int i = 0; i < 2; ++i) {
+ if (extras[i] != NULL) {
+ str_free(extras[i]);
+ }
+ }
}
static void parse_format(struct parser *p, enum formatting fmt) {
diff --git a/test/preamble b/test/preamble
@@ -48,3 +48,21 @@ scdoc <<EOF | grep '^\.TH "test-manual" "8" "'"$(date +'%F')"'"' >/dev/null
test-manual(8)
EOF
end 0
+
+begin "Handles extra footer field"
+scdoc <<EOF | grep '^\.TH "test-manual" "8" "'"$(date +'%F')"'" "Footer"' >/dev/null
+test-manual(8) "Footer"
+EOF
+end 0
+
+begin "Handles both extra fields"
+scdoc <<EOF | grep '^\.TH "test-manual" "8" "'"$(date +'%F')"'" "Footer" "Header"' >/dev/null
+test-manual(8) "Footer" "Header"
+EOF
+end 0
+
+begin "Emits empty footer correctly"
+scdoc <<EOF | grep '^\.TH "test-manual" "8" "'"$(date +'%F')"'" "" "Header"' >/dev/null
+test-manual(8) "" "Header"
+EOF
+end 0