aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn MacFarlane <jgm@berkeley.edu>2014-11-30 12:14:37 -0800
committerJohn MacFarlane <jgm@berkeley.edu>2014-11-30 12:14:37 -0800
commit75be85f77f02c8185e8fff607bf3ccf3c8fe3a11 (patch)
treec55fa6651047afc37548e570e2bcb57a9cfc9702
parent7686b7dad5c80d494b993158def220aa8b61ac6e (diff)
Create man 3 page without markdown intermediary.
Use proper man style, marking function types, arguments, etc. See #224.
-rw-r--r--Makefile5
-rw-r--r--man/make_man_page.py68
-rw-r--r--man/man3/cmark.3428
-rw-r--r--src/cmark.h28
4 files changed, 329 insertions, 200 deletions
diff --git a/Makefile b/Makefile
index 6fcc956..a39eb2e 100644
--- a/Makefile
+++ b/Makefile
@@ -74,10 +74,7 @@ $(PROG): all
man/man1/cmark.1: man/cmark.1.md
mkdir -p man/man1 && pandoc -t man -s $< -o $@
-man/man3/cmark.3: man/cmark.3.md
- mkdir -p man/man3 && pandoc -t man -s $< -o $@
-
-man/cmark.3.md: src/cmark.h
+man/man3/cmark.3: src/cmark.h
python man/make_man_page.py $< > $@
# We include html_unescape.h in the repository, so this shouldn't
diff --git a/man/make_man_page.py b/man/make_man_page.py
index 5ed5b0c..3183397 100644
--- a/man/make_man_page.py
+++ b/man/make_man_page.py
@@ -2,71 +2,91 @@
# Creates a man page from a C file.
-# Comments beginning with `/**` are treated as Markdown.
+# Comments beginning with `/**` are treated as Groff man.
-# Non-blank lines immediately following a Markdown comment are treated
-# as function signatures or examples and included verbatim. The
-# immediately preceding markdown chunk is printed after the example
+# Non-blank lines immediately following a man page comment are treated
+# as function signatures or examples and parsed into .Ft, .Fo, .Fa, .Fc. The
+# immediately preceding man documentation chunk is printed after the example
# as a comment on it.
# That's about it!
-import sys
-import re
-
-if len(sys.argv) > 1:
- sourcefile = sys.argv[1]
-else:
- print("Usage: make_man_page.py sourcefile")
- exit(1)
+import sys, re, os
+from datetime import date
comment_start_re = re.compile('^\/\*\* ?')
comment_delim_re = re.compile('^[/ ]\** ?')
comment_end_re = re.compile('^ \**\/')
+function_re = re.compile('^ *(?:CMARK_EXPORT\s+)?(?P<type>(?:const\s+)?\w+(?:\s*[*])?)\s*(?P<name>\w+)\s*\((?P<args>[^)]*)\)')
blank_re = re.compile('^\s*$')
macro_re = re.compile('CMARK_EXPORT *')
+typedef_start_re = re.compile('typedef.*{$')
+typedef_end_re = re.compile('}')
+typedef = False
mdlines = []
chunk = []
sig = []
+if len(sys.argv) > 1:
+ sourcefile = sys.argv[1]
+else:
+ print("Usage: make_man_page.py sourcefile")
+ exit(1)
+
with open(sourcefile, 'r') as cmarkh:
state = 'default'
for line in cmarkh:
# state transition
oldstate = state
if comment_start_re.match(line):
- state = 'markdown'
- elif comment_end_re.match(line) and state == 'markdown':
+ state = 'man'
+ elif comment_end_re.match(line) and state == 'man':
continue
- elif comment_delim_re.match(line) and state == 'markdown':
- state = 'markdown'
- elif blank_re.match(line):
+ elif comment_delim_re.match(line) and state == 'man':
+ state = 'man'
+ elif not typedef and blank_re.match(line):
state = 'default'
- elif state == 'markdown':
+ elif typedef and typedef_end_re.match(line):
+ typedef = False
+ elif state == 'man':
state = 'signature'
+ typedef = typedef_start_re.match(line)
# handle line
- if state == 'markdown':
+ if state == 'man':
chunk.append(re.sub(comment_delim_re, '', line))
elif state == 'signature':
ln = re.sub(macro_re, '', line)
- if not re.match(blank_re, ln):
- sig.append(' ' + ln)
+ if typedef or not re.match(blank_re, ln):
+ sig.append(ln)
elif oldstate == 'signature' and state != 'signature':
if len(mdlines) > 0 and mdlines[-1] != '\n':
mdlines.append('\n')
- mdlines += sig # add sig, then prepended markdown comment
+ rawsig = ''.join(sig)
+ m = function_re.match(rawsig)
+ if m:
+ mdlines.append('.Ft ' + m.group('type') + '\n')
+ mdlines.append('.Fo ' + m.group('name') + '\n')
+ for argument in re.split('/s*,/s*', m.group('args')):
+ mdlines.append('.Fa ' + argument + '\n')
+ mdlines.append('.Fc\n')
+ else:
+ mdlines.append('.Bd -literal\n')
+ mdlines += sig
+ mdlines.append('.Ed\n')
if len(mdlines) > 0 and mdlines[-1] != '\n':
mdlines.append('\n')
mdlines += chunk
chunk = []
sig = []
- elif oldstate == 'markdown' and state != 'signature':
+ elif oldstate == 'man' and state != 'signature':
if len(mdlines) > 0 and mdlines[-1] != '\n':
mdlines.append('\n')
- mdlines += chunk # add markdown chunk
+ mdlines += chunk # add man chunk
chunk = []
mdlines.append('\n')
+sys.stdout.write('.Dd ' + date.today().isoformat() + '\n')
+sys.stdout.write('.Dt ' + os.path.basename(sourcefile) + '\n')
sys.stdout.write(''.join(mdlines))
diff --git a/man/man3/cmark.3 b/man/man3/cmark.3
index ded9860..9d24f73 100644
--- a/man/man3/cmark.3
+++ b/man/man3/cmark.3
@@ -1,233 +1,341 @@
-.TH "" "" "" "" ""
-.SH NAME
-.PP
-cmark \- CommonMark parsing, manipulating, and rendering
-.SH SIMPLE INTERFACE
-.IP
-.nf
-\f[C]
-#define\ CMARK_VERSION\ "0.1"
-\f[]
-.fi
-.PP
+.Dd 2014-11-30
+.Dt cmark.h
+.Sh NAME
+
+.Nm cmark
+.Nd CommonMark parsing, manipulating, and rendering
+
+.Sh SIMPLE INTERFACE
+
+.Bd -literal
+#define CMARK_VERSION "0.1"
+.Ed
+
Current version of library.
-.IP
-.nf
-\f[C]
-char\ *cmark_markdown_to_html(const\ char\ *text,\ int\ len);
-\f[]
-.fi
-.PP
-Convert \f[C]text\f[] (assumed to be a UTF\-8 encoded string with length
-\f[C]len\f[]) from CommonMark Markdown to HTML, returning a
-null\-terminated, UTF\-8\-encoded string.
-.SH NODE STRUCTURE
-.IP
-.nf
-\f[C]
-typedef\ enum\ {
-\ \ \ \ /*\ Block\ */
-\ \ \ \ CMARK_NODE_DOCUMENT,
-\ \ \ \ CMARK_NODE_BLOCK_QUOTE,
-\ \ \ \ CMARK_NODE_LIST,
-\ \ \ \ CMARK_NODE_LIST_ITEM,
-\ \ \ \ CMARK_NODE_CODE_BLOCK,
-\ \ \ \ CMARK_NODE_HTML,
-\ \ \ \ CMARK_NODE_PARAGRAPH,
-\ \ \ \ CMARK_NODE_HEADER,
-\ \ \ \ CMARK_NODE_HRULE,
-\ \ \ \ CMARK_NODE_REFERENCE_DEF,
+
+.Ft char *
+.Fo cmark_markdown_to_html
+.Fa const char *text, int len
+.Fc
+
+Convert
+.Fa text
+(assumed to be a UTF-8 encoded string with length
+.Fa len )
+from CommonMark Markdown to HTML, returning a null-terminated,
+UTF-8-encoded string.
+
+.Sh NODE STRUCTURE
+
+.Bd -literal
+typedef enum {
+ /* Block */
+ CMARK_NODE_DOCUMENT,
+ CMARK_NODE_BLOCK_QUOTE,
+ CMARK_NODE_LIST,
+ CMARK_NODE_LIST_ITEM,
+ CMARK_NODE_CODE_BLOCK,
+ CMARK_NODE_HTML,
+ CMARK_NODE_PARAGRAPH,
+ CMARK_NODE_HEADER,
+ CMARK_NODE_HRULE,
+ CMARK_NODE_REFERENCE_DEF,
+
+ CMARK_NODE_FIRST_BLOCK = CMARK_NODE_DOCUMENT,
+ CMARK_NODE_LAST_BLOCK = CMARK_NODE_REFERENCE_DEF,
+
+ /* Inline */
+ CMARK_NODE_TEXT,
+ CMARK_NODE_SOFTBREAK,
+ CMARK_NODE_LINEBREAK,
+ CMARK_NODE_INLINE_CODE,
+ CMARK_NODE_INLINE_HTML,
+ CMARK_NODE_EMPH,
+ CMARK_NODE_STRONG,
+ CMARK_NODE_LINK,
+ CMARK_NODE_IMAGE,
+
+ CMARK_NODE_FIRST_INLINE = CMARK_NODE_TEXT,
+ CMARK_NODE_LAST_INLINE = CMARK_NODE_IMAGE,
+} cmark_node_type;
+.Ed
+
+
+.Bd -literal
+typedef enum {
+ CMARK_NO_LIST,
+ CMARK_BULLET_LIST,
+ CMARK_ORDERED_LIST
+} cmark_list_type;
+.Ed
+
+
+.Bd -literal
+typedef enum {
+ CMARK_PERIOD_DELIM,
+ CMARK_PAREN_DELIM
+} cmark_delim_type;
+.Ed
+
+
+
+.Sh CREATING AND DESTORYING NODES
+
+.Ft cmark_node*
+.Fo cmark_node_new
+.Fa cmark_node_type type
+.Fc
+
+
+.Ft void
+.Fo cmark_node_free
+.Fa cmark_node *node
+.Fc
+
+
+.Ft cmark_node*
+.Fo cmark_node_next
+.Fa cmark_node *node
+.Fc
+
+
+.Sh TREE TRAVERSAL
+
+.Ft cmark_node*
+.Fo cmark_node_previous
+.Fa cmark_node *node
+.Fc
+
+
+.Ft cmark_node*
+.Fo cmark_node_parent
+.Fa cmark_node *node
+.Fc
+
+
+.Ft cmark_node*
+.Fo cmark_node_first_child
+.Fa cmark_node *node
+.Fc
+
+
+.Ft cmark_node*
+.Fo cmark_node_last_child
+.Fa cmark_node *node
+.Fc
+
+
+
+.Sh ACCESSORS
+
+.Ft cmark_node_type
+.Fo cmark_node_get_type
+.Fa cmark_node *node
+.Fc
+
+
+.Ft const char*
+.Fo cmark_node_get_string_content
+.Fa cmark_node *node
+.Fc
-typedef\ enum\ {
-\ \ \ \ CMARK_NO_LIST,
-\ \ \ \ CMARK_BULLET_LIST,
-\ \ \ \ CMARK_ORDERED_LIST
-}\ \ cmark_list_type;
+.Ft int
+.Fo cmark_node_set_string_content
+.Fa cmark_node *node, const char *content
+.Fc
-typedef\ enum\ {
-\ \ \ \ CMARK_PERIOD_DELIM,
-\ \ \ \ CMARK_PAREN_DELIM
-}\ cmark_delim_type;
-\f[]
-.fi
-.SH CREATING AND DESTORYING NODES
-.IP
-.nf
-\f[C]
-cmark_node*
-cmark_node_new(cmark_node_type\ type);
+.Ft int
+.Fo cmark_node_get_header_level
+.Fa cmark_node *node
+.Fc
-void
-cmark_node_free(cmark_node\ *node);
+.Ft int
+.Fo cmark_node_set_header_level
+.Fa cmark_node *node, int level
+.Fc
-cmark_node*
-cmark_node_next(cmark_node\ *node);
-\f[]
-.fi
-.SH TREE TRAVERSAL
-.IP
-.nf
-\f[C]
-cmark_node*
-cmark_node_previous(cmark_node\ *node);
+.Ft cmark_list_type
+.Fo cmark_node_get_list_type
+.Fa cmark_node *node
+.Fc
-cmark_node*
-cmark_node_parent(cmark_node\ *node);
+.Ft int
+.Fo cmark_node_set_list_type
+.Fa cmark_node *node, cmark_list_type type
+.Fc
-cmark_node*
-cmark_node_first_child(cmark_node\ *node);
+.Ft int
+.Fo cmark_node_get_list_start
+.Fa cmark_node *node
+.Fc
-cmark_node*
-cmark_node_last_child(cmark_node\ *node);
-\f[]
-.fi
-.SH ACCESSORS
-.IP
-.nf
-\f[C]
-cmark_node_type
-cmark_node_get_type(cmark_node\ *node);
+.Ft int
+.Fo cmark_node_set_list_start
+.Fa cmark_node *node, int start
+.Fc
-const\ char*
-cmark_node_get_string_content(cmark_node\ *node);
+.Ft int
+.Fo cmark_node_get_list_tight
+.Fa cmark_node *node
+.Fc
-int
-cmark_node_set_string_content(cmark_node\ *node,\ const\ char\ *content);
+.Ft int
+.Fo cmark_node_set_list_tight
+.Fa cmark_node *node, int tight
+.Fc
-int
-cmark_node_get_header_level(cmark_node\ *node);
+.Ft const char*
+.Fo cmark_node_get_fence_info
+.Fa cmark_node *node
+.Fc
-int
-cmark_node_set_header_level(cmark_node\ *node,\ int\ level);
+.Ft int
+.Fo cmark_node_set_fence_info
+.Fa cmark_node *node, const char *info
+.Fc
-cmark_list_type
-cmark_node_get_list_type(cmark_node\ *node);
+.Ft const char*
+.Fo cmark_node_get_url
+.Fa cmark_node *node
+.Fc
-int
-cmark_node_set_list_type(cmark_node\ *node,\ cmark_list_type\ type);
+.Ft int
+.Fo cmark_node_set_url
+.Fa cmark_node *node, const char *url
+.Fc
-int
-cmark_node_get_list_start(cmark_node\ *node);
+.Ft const char*
+.Fo cmark_node_get_title
+.Fa cmark_node *node
+.Fc
-int
-cmark_node_set_list_start(cmark_node\ *node,\ int\ start);
+.Ft int
+.Fo cmark_node_set_title
+.Fa cmark_node *node, const char *title
+.Fc
-int
-cmark_node_get_list_tight(cmark_node\ *node);
+.Ft int
+.Fo cmark_node_get_start_line
+.Fa cmark_node *node
+.Fc
-int
-cmark_node_set_list_tight(cmark_node\ *node,\ int\ tight);
+.Ft int
+.Fo cmark_node_get_start_column
+.Fa cmark_node *node
+.Fc
-const\ char*
-cmark_node_get_fence_info(cmark_node\ *node);
+.Ft int
+.Fo cmark_node_get_end_line
+.Fa cmark_node *node
+.Fc
-int
-cmark_node_set_fence_info(cmark_node\ *node,\ const\ char\ *info);
+.Sh TREE MANIPULATION
-const\ char*
-cmark_node_get_url(cmark_node\ *node);
+.Ft void
+.Fo cmark_node_unlink
+.Fa cmark_node *node
+.Fc
-int
-cmark_node_set_url(cmark_node\ *node,\ const\ char\ *url);
+.Ft int
+.Fo cmark_node_insert_before
+.Fa cmark_node *node, cmark_node *sibling
+.Fc
-const\ char*
-cmark_node_get_title(cmark_node\ *node);
+.Ft int
+.Fo cmark_node_insert_after
+.Fa cmark_node *node, cmark_node *sibling
+.Fc
-int
-cmark_node_set_title(cmark_node\ *node,\ const\ char\ *title);
+.Ft int
+.Fo cmark_node_prepend_child
+.Fa cmark_node *node, cmark_node *child
+.Fc
-int
-cmark_node_get_start_line(cmark_node\ *node);
+.Ft int
+.Fo cmark_node_append_child
+.Fa cmark_node *node, cmark_node *child
+.Fc
-int
-cmark_node_get_start_column(cmark_node\ *node);
+.Sh PARSING
-int
-cmark_node_get_end_line(cmark_node\ *node);
-\f[]
-.fi
-.SH TREE MANIPULATION
-.IP
-.nf
-\f[C]
-void
-cmark_node_unlink(cmark_node\ *node);
+.Ft cmark_parser *
+.Fo cmark_parser_new
+.Fa
+.Fc
-int
-cmark_node_insert_before(cmark_node\ *node,\ cmark_node\ *sibling);
+.Ft void
+.Fo cmark_parser_free
+.Fa cmark_parser *parser
+.Fc
-int
-cmark_node_insert_after(cmark_node\ *node,\ cmark_node\ *sibling);
+.Ft cmark_node *
+.Fo cmark_parser_finish
+.Fa cmark_parser *parser
+.Fc
-int
-cmark_node_prepend_child(cmark_node\ *node,\ cmark_node\ *child);
+.Ft void
+.Fo cmark_parser_feed
+.Fa cmark_parser *parser, const char *buffer, size_t len
+.Fc
-int
-cmark_node_append_child(cmark_node\ *node,\ cmark_node\ *child);
-\f[]
-.fi
-.SH PARSING
-.IP
-.nf
-\f[C]
-cmark_parser\ *cmark_parser_new();
+.Ft cmark_node *
+.Fo cmark_parse_document
+.Fa const char *buffer, size_t len
+.Fc
-void\ cmark_parser_free(cmark_parser\ *parser);
+.Ft cmark_node *
+.Fo cmark_parse_file
+.Fa FILE *f
+.Fc
-cmark_node\ *cmark_parser_finish(cmark_parser\ *parser);
+.Sh RENDERING
-void\ cmark_parser_feed(cmark_parser\ *parser,\ const\ char\ *buffer,\ size_t\ len);
+.Ft char *
+.Fo cmark_render_ast
+.Fa cmark_node *root
+.Fc
-cmark_node\ *cmark_parse_document(const\ char\ *buffer,\ size_t\ len);
+.Ft char *
+.Fo cmark_render_html
+.Fa cmark_node *root
+.Fc
-cmark_node\ *cmark_parse_file(FILE\ *f);
-\f[]
-.fi
-.SH RENDERING
-.IP
-.nf
-\f[C]
-char\ *cmark_render_ast(cmark_node\ *root);
+.Sh AUTHORS
+John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer.
-char\ *cmark_render_html(cmark_node\ *root);
-\f[]
-.fi
-.SH AUTHORS
-.PP
-John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer.
diff --git a/src/cmark.h b/src/cmark.h
index 9e38500..3b789cf 100644
--- a/src/cmark.h
+++ b/src/cmark.h
@@ -8,26 +8,30 @@
extern "C" {
#endif
-/** # NAME
+/** .Sh NAME
*
- * cmark - CommonMark parsing, manipulating, and rendering
+ * .Nm cmark
+ * .Nd CommonMark parsing, manipulating, and rendering
*/
-/** # SIMPLE INTERFACE
+/** .Sh SIMPLE INTERFACE
*/
/** Current version of library.
*/
#define CMARK_VERSION "0.1"
-/** Convert `text` (assumed to be a UTF-8 encoded string with length `len`)
+/** Convert
+ * .Fa text
+ * (assumed to be a UTF-8 encoded string with length
+ * .Fa len )
* from CommonMark Markdown to HTML, returning a null-terminated,
* UTF-8-encoded string.
*/
CMARK_EXPORT
char *cmark_markdown_to_html(const char *text, int len);
-/** # NODE STRUCTURE
+/** .Sh NODE STRUCTURE
*/
/**
@@ -83,7 +87,7 @@ typedef struct cmark_node cmark_node;
typedef struct cmark_parser cmark_parser;
/**
- * # CREATING AND DESTORYING NODES
+ * .Sh CREATING AND DESTORYING NODES
*/
/**
@@ -97,7 +101,7 @@ CMARK_EXPORT void
cmark_node_free(cmark_node *node);
/**
- * # TREE TRAVERSAL
+ * .Sh TREE TRAVERSAL
*/
CMARK_EXPORT cmark_node*
cmark_node_next(cmark_node *node);
@@ -123,7 +127,7 @@ CMARK_EXPORT cmark_node*
cmark_node_last_child(cmark_node *node);
/**
- * # ACCESSORS
+ * .Sh ACCESSORS
*/
/**
@@ -227,7 +231,7 @@ CMARK_EXPORT int
cmark_node_get_end_line(cmark_node *node);
/**
- * # TREE MANIPULATION
+ * .Sh TREE MANIPULATION
*/
/**
@@ -256,7 +260,7 @@ CMARK_EXPORT int
cmark_node_append_child(cmark_node *node, cmark_node *child);
/**
- * # PARSING
+ * .Sh PARSING
*/
/**
@@ -290,7 +294,7 @@ CMARK_EXPORT
cmark_node *cmark_parse_file(FILE *f);
/**
- * # RENDERING
+ * .Sh RENDERING
*/
/**
@@ -303,7 +307,7 @@ char *cmark_render_ast(cmark_node *root);
CMARK_EXPORT
char *cmark_render_html(cmark_node *root);
-/** # AUTHORS
+/** .Sh AUTHORS
*
* John MacFarlane, Vicent Marti, Kārlis Gaņģis, Nick Wellnhofer.
*/