scdoc2mdoc

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

commit a4c7cc6187134c6d916b72d02c2f21b65a31aece
parent 10e1cf68bc6d451ef957c3008d9879655f4e1c63
Author: Drew DeVault <sir@cmpwn.com>
Date:   Sun, 10 Dec 2017 00:24:56 -0500

Implement lists

Diffstat:
Ascdoc.1.scd | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Dscdoc.5.scd | 80-------------------------------------------------------------------------------
Msrc/main.c | 76+++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
3 files changed, 154 insertions(+), 103 deletions(-)

diff --git a/scdoc.1.scd b/scdoc.1.scd @@ -0,0 +1,101 @@ +scdoc(1) + +# NAME + +scdoc - tool for generating *roff*(7) manual pages + +# SYNOPSIS + +*scdoc* < _input_ > _output_ + +# DESCRIPTION + +scdoc is a tool designed to make the process of writing man pages more +friendly. It reads scdoc syntax from stdin and writes roff to stdout, suitable +for reading with *man*(1). + +# SYNTAX + +Input files must use the UTF-8 encoding. + +## PREAMBLE + +Each scdoc file must begin with the following preamble: + + *name*(_section_) + +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 HEADERS + +Each section of your man page should begin with something similar to the +following: + + # HEADER NAME + +Subsection headers are also understood - use two hashes. Each header must have +an empty line on either side. + +## PARAGRAPHS + +Begin a new paragraph with an empty line. + +## FORMATTING + +Text can be made *bold* or _underlined_ with asterisks and underscores: \*bold\* +or \_underlined\_. + +## INDENTATION + +You may indent lines with tab characters (*\\t*) to indent them by 4 spaces in +the output. Indented lines may not contain headers. + + The result looks something like this. + + You may use multiple lines and most _formatting_. + +Deindent to return to normal. + +## LISTS + +You may start bulleted lists with dashes, like so: + +``` +- Item 1 +- Item 2 + - Subitem 1 + - Subitem 2 +- Item 3 +``` + +The result looks like this: + +- Item 1 +- Item 2 + - Subitem 1 + - Subitem 2 +- Item 3 + +## LITERAL TEXT + +You may turn off scdoc formatting and output literal text with escape codes and +literal blocks. Inserting a \\ into your source will cause the subsequent symbol +to be treated as a literal and copied directly to the output. You may also make +blocks of literal syntax like so: + +``` +\`\`\` +_This formatting_ will *not* be interpreted by scdoc. +\`\`\` +``` + +These blocks will be indented one level. Note that literal text is shown +literally in the man viewer - that is, it's not a means for inserting your own +roff macros into the output. + +# AUTHORS + +Maintained by Drew DeVault <sir@cmpwn.com>. Up-to-date sources can be found at +https://git.sr.ht/~sircmpwn/scdoc and bugs/patches can be submitted by email to +sir@cmpwn.com. diff --git a/scdoc.5.scd b/scdoc.5.scd @@ -1,80 +0,0 @@ -scdoc(5) - -# NAME - -scdoc - syntax description for scdoc markup language - -# DESCRIPTION - -scdoc is a tool designed to make the process of writing man pages more -friendly. It converts scdoc files into roff macros, which can then be converted -to man pages or a number of other formats. The syntax is inspired by, but not -directly taken from, markdown. Input files *must* use the UTF-8 encoding. - -# PREAMBLE - -Each scdoc file must begin with the following preamble: - - *name*(_section_) - -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 HEADERS - -Each section of your man page should begin with something similar to the -following: - - # HEADER NAME - -Subsection headers are also understood - use two hashes. Each header must have -an empty line on either side. - -# PARAGRAPHS - -Begin a new paragraph with an empty line. - -# FORMATTING - -Text can be made *bold* or _underlined_ with asterisks and underscores: \*bold\* -or \_underlined\_. - -# INDENTATION - -You may indent lines with tab characters (*\\t*) to indent them by 4 spaces in -the output. Indented lines may not contain headers. - -# LISTS - -You may start bulleted lists with dashes, like so: - -``` -- Item 1 -- Item 2 -- Item 3 -``` - -You may also use numbered lists like so: - -``` -1. Item 1 -2. Item 2 -3. Item 3 -``` - -# LITERAL TEXT - -You may turn off scdoc formatting and output literal text with escape codes and -literal blocks. Inserting a \\ into your source will cause the subsequent symbol -to be treated as a literal and copied directly to the output. You may also make -blocks of literal syntax like so: - -``` -\`\`\` -_This formatting_ will *not* be interpreted by scdoc. -\`\`\` -``` - -These blocks will be indented one level. Note that literal text is shown -literally in the man viewer - that is, it's not a means for inserting your own -roff macros into the output. diff --git a/src/main.c b/src/main.c @@ -1,5 +1,6 @@ #include <assert.h> #include <ctype.h> +#include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <time.h> @@ -97,6 +98,9 @@ static void parse_text(struct parser *p) { case '_': parse_format(p, FORMAT_UNDERLINE); break; + case '\n': + utf8_fputch(p->output, ch); + return; case '.': if (!i) { // Escape . if it's the first character @@ -108,9 +112,6 @@ static void parse_text(struct parser *p) { utf8_fputch(p->output, ch); break; } - if (ch == '\n') { - break; - } ++i; } } @@ -146,46 +147,75 @@ static void parse_heading(struct parser *p) { } } -static int parse_indent(struct parser *p) { +static int parse_indent(struct parser *p, int *indent) { int i = 0; uint32_t ch; while ((ch = parser_getch(p)) == '\t') { ++i; } parser_pushch(p, ch); + if (i == *indent - 1) { + roff_macro(p, "RE", NULL); + } else if (i == *indent + 1) { + roff_macro(p, "RS", "4", NULL); + } else if (i != *indent && ch == '\t') { + parser_fatal(p, "(De)indented by an amount greater than 1"); + } + *indent = i; return i; } -static void parse_document(struct parser *p) { +static void parse_list(struct parser *p, int *indent) { uint32_t ch; - int indent = 0; + if ((ch = parser_getch(p)) != ' ') { + parser_fatal(p, "Expected space before start of list entry"); + } + roff_macro(p, "IP", "\\(bu", "4", NULL); + parse_text(p); do { - int i = parse_indent(p); - if (i == indent - 1) { - roff_macro(p, "RE", NULL); - } else if (i == indent + 1) { - roff_macro(p, "RS", "4", NULL); - } else if (i != indent && ch == '\t') { - parser_fatal(p, "(De)indented by an amount greater than 1"); - } - indent = i; - - ch = parser_getch(p); - if (ch == UTF8_INVALID) { + parse_indent(p, indent); + if ((ch = parser_getch(p)) == UTF8_INVALID) { break; } - - if (indent != 0) { - // Only text is allowed at this point - parser_pushch(p, ch); + switch (ch) { + case ' ': + break; + case '-': + if ((ch = parser_getch(p)) != ' ') { + parser_fatal(p, "Expected space before start of list entry"); + } + fprintf(p->output, ".sp -1\n"); + roff_macro(p, "IP", "\\(bu", "4", NULL); parse_text(p); - continue; + break; + default: + fprintf(p->output, "\n"); + parser_pushch(p, ch); + return; } + } while (ch != UTF8_INVALID); +} +static void parse_document(struct parser *p) { + uint32_t ch; + int indent = 0; + do { + parse_indent(p, &indent); + if ((ch = parser_getch(p)) == UTF8_INVALID) { + break; + } switch (ch) { case '#': + if (indent != 0) { + parser_pushch(p, ch); + parse_text(p); + break; + } parse_heading(p); break; + case '-': + parse_list(p, &indent); + break; case ' ': parser_fatal(p, "Tabs are required for indentation"); break;