scdoc2mdoc

A fork of scdoc to output mdoc(7)
git clone git://git.sgregoratto.me/scdoc2mdoc
Log | Files | Refs | README | LICENSE

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:
Mscdoc.1.scd | 6+++++-
Msrc/main.c | 45++++++++++++++++++++++++++++++++++++++++++++-
Mtest/preamble | 18++++++++++++++++++
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