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"
master 1.4.0
Richard Bradfield 7 years ago committed by Drew DeVault
parent 71191da836
commit 0fabc9bb0c
  1. 6
      scdoc.1.scd
  2. 45
      src/main.c
  3. 18
      test/preamble

@ -22,11 +22,15 @@ Input files must use the UTF-8 encoding.
Each scdoc file must begin with the following preamble: 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 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). 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 ## SECTION HEADERS
Each section of your man page should begin with something similar to the Each section of your man page should begin with something similar to the

@ -37,8 +37,31 @@ static int parse_section(struct parser *p) {
return -1; 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) { static void parse_preamble(struct parser *p) {
str_t *name = str_create(); str_t *name = str_create();
int ex = 0;
str_t *extras[2] = { NULL };
int section = -1; int section = -1;
uint32_t ch; uint32_t ch;
char date[256]; char date[256];
@ -51,6 +74,11 @@ static void parse_preamble(struct parser *p) {
assert(str_append_ch(name, ch) != -1); assert(str_append_ch(name, ch) != -1);
} else if (ch == '(') { } else if (ch == '(') {
section = parse_section(p); 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') { } else if (ch == '\n') {
if (name->len == 0) { if (name->len == 0) {
parser_fatal(p, "Expected preamble"); parser_fatal(p, "Expected preamble");
@ -59,11 +87,26 @@ static void parse_preamble(struct parser *p) {
parser_fatal(p, "Expected manual section"); parser_fatal(p, "Expected manual section");
} }
char sec[2] = { '0' + section, 0 }; 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; break;
} }
} }
str_free(name); 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) { static void parse_format(struct parser *p, enum formatting fmt) {

@ -48,3 +48,21 @@ scdoc <<EOF | grep '^\.TH "test-manual" "8" "'"$(date +'%F')"'"' >/dev/null
test-manual(8) test-manual(8)
EOF EOF
end 0 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

Loading…
Cancel
Save