On 22:07:19 2019-01-21, Jani Nikula wrote:
On Sat, 19 Jan 2019, Bruno Santos <brunomanuelsantos@xxxxxxxxxxxxxxxxxx>
wrote:
As with doccompat, this moves away code unrelated to the parsing out
into its own module. This doesn't look like much at this point, but a
lot more can be abstracted and consolidated with some breaking changes
later on.
---
hawkmoth/hawkmoth.py | 55 +++++++++++++----------------------------
hawkmoth/util/docstr.py | 45 +++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 38 deletions(-)
create mode 100644 hawkmoth/util/docstr.py
diff --git a/hawkmoth/hawkmoth.py b/hawkmoth/hawkmoth.py
index b188b21..8d5c5e6 100755
--- a/hawkmoth/hawkmoth.py
+++ b/hawkmoth/hawkmoth.py
@@ -35,7 +35,6 @@
import argparse
import itertools
-import re
import sys
from clang.cindex import CursorKind
@@ -43,27 +42,7 @@
from clang.cindex import SourceLocation, SourceRange
from clang.cindex import TokenKind, TokenGroup
-from hawkmoth.util import doccompat
-
-def is_doc_comment(comment):
- return comment.startswith('/**') and comment != '/**/'
-
-def strip_comment(comment):
- comment = re.sub(r"^/\*\*[ \t]?", "", comment)
- comment = re.sub(r"\*/$", "", comment)
- # could look at first line of comment, and remove the leading stuff
there from the rest
- comment = re.sub(r"(?m)^[ \t]*\*?[ \t]?", "", comment)
- # Strip leading blank lines.
- comment = re.sub(r"^[\n]*", "", comment)
- # End in exactly one newline.
- comment = re.sub(r"[\n]*$", "", comment) + "\n"
- return comment
-
-def indent(string, prefix):
- return re.sub('(?m)^', prefix, string)
-
-def wrap_blank_lines(string):
- return '\n' + string + '\n'
+from hawkmoth.util import docstr, doccompat
def comment_extract(tu):
@@ -154,7 +133,7 @@ def parse(filename, **options):
top_level_comments, comments = comment_extract(tu)
- # FIXME: strip_comment, doccompat.convert, and the C Domain directive
all
+ # FIXME: docstr.strip, doccompat.convert, and the C Domain directive
all
# change the number of lines in output. This impacts the error
reporting via
# meta['line']. Adjust meta to take this into account.
@@ -162,12 +141,12 @@ def parse(filename, **options):
compat = lambda x: doccompat.convert(x, options.get('compat'))
for comment in top_level_comments:
- if not is_doc_comment(comment.spelling):
+ if not docstr.is_doc(comment.spelling):
continue
- doc_comment = strip_comment(comment.spelling)
+ doc_comment = docstr.strip(comment.spelling)
doc_comment = compat(doc_comment)
- doc_comment = wrap_blank_lines(doc_comment)
+ doc_comment = docstr.wrap_blank_lines(doc_comment)
meta = { 'line': comment.extent.start.line }
result.append((doc_comment, meta))
@@ -176,10 +155,10 @@ def parse(filename, **options):
if cursor.hash not in comments:
continue
comment = comments[cursor.hash]
- if not is_doc_comment(comment.spelling):
+ if not docstr.is_doc(comment.spelling):
continue
- doc_comment = strip_comment(comment.spelling)
+ doc_comment = docstr.strip(comment.spelling)
if cursor.kind == CursorKind.MACRO_DEFINITION:
args = _get_macro_args(cursor)
@@ -224,8 +203,8 @@ def parse(filename, **options):
name=cursor.spelling)
doc_comment = compat(doc_comment)
- doc_comment = indent(doc_comment, ' ')
- doc_comment = wrap_blank_lines(doc_comment)
+ doc_comment = docstr.nest(doc_comment, 1)
+ doc_comment = docstr.wrap_blank_lines(doc_comment)
cdom += doc_comment
@@ -249,9 +228,9 @@ def parse(filename, **options):
if c.hash not in comments:
continue
comment = comments[c.hash]
- if not is_doc_comment(comment.spelling):
+ if not docstr.is_doc(comment.spelling):
continue
- doc_comment = strip_comment(comment.spelling)
+ doc_comment = docstr.strip(comment.spelling)
# FIXME: this is sooo ugly, handles unnamed vs. named
structs
# in typedefs
@@ -267,8 +246,8 @@ def parse(filename, **options):
member=c.spelling)
doc_comment = compat(doc_comment)
- doc_comment = indent(doc_comment, ' ')
- doc_comment = wrap_blank_lines(doc_comment)
+ doc_comment = docstr.nest(doc_comment, 1)
+ doc_comment = docstr.wrap_blank_lines(doc_comment)
cdom += doc_comment
@@ -283,16 +262,16 @@ def parse(filename, **options):
if c.hash not in comments:
continue
comment = comments[c.hash]
- if not is_doc_comment(comment.spelling):
+ if not docstr.is_doc(comment.spelling):
continue
- doc_comment = strip_comment(comment.spelling)
+ doc_comment = docstr.strip(comment.spelling)
# FIXME: parent enum name?
cdom = '.. c:macro:: {name}\n'.format(name=c.spelling)
doc_comment = compat(doc_comment)
- doc_comment = indent(doc_comment, ' ')
- doc_comment = wrap_blank_lines(doc_comment)
+ doc_comment = docstr.nest(doc_comment, 1)
+ doc_comment = docstr.wrap_blank_lines(doc_comment)
cdom += doc_comment
diff --git a/hawkmoth/util/docstr.py b/hawkmoth/util/docstr.py
new file mode 100644
index 0000000..c281a4a
--- /dev/null
+++ b/hawkmoth/util/docstr.py
@@ -0,0 +1,45 @@
+# Copyright (c) 2016-2017 Jani Nikula <jani@xxxxxxxxxx>
+# Licensed under the terms of BSD 2-Clause, see LICENSE for details.
+"""
+Documentation strings manipulation library
+==========================================
+
+This module allows a generic way of generating reST documentation for each
C
+construct.
+"""
+
+import re
+
+def strip(comment):
+ """Strip comment from comment markers."""
+ comment = re.sub(r'^/\*\*[ \t]?', '', comment)
+ comment = re.sub(r'\*\s*/$', '', comment)
I removed the added \s* while applying, preserving the old regex. I'm
not sure it even makes sense here. If it's needed, it should be added
with an explanation in a separate patch.
+ # Could look at first line of comment, and remove the leading stuff
there
+ # from the rest.
+ comment = re.sub(r'(?m)^[ \t]*\*?[ \t]?', '', comment)
+ # Strip leading blank lines.
+ comment = re.sub(r'^[\n]*', '', comment)
+ # End in exactly one newline.
+ comment = re.sub(r"[\n]*$", "", comment) + "\n"
Changed the double quotes to single quotes while applying, though this
gets removed in a later patch.
BR,
Jani.
+ return comment
+
+def wrap_blank_lines(string):
+ return '\n' + string + '\n'
+
+def is_doc(comment):
+ """Test if comment is a C documentation comment."""
+ return comment.startswith('/**') and comment != '/**/'
+
+def nest(text, nest):
+ """
+ Indent documentation block for nesting.
+
+ Args:
+ text (str): Documentation body.
+ nest (int): Nesting level. For each level, the final block is
indented
+ one level. Useful for (e.g.) declaring structure members.
+
+ Returns:
+ str: Indented reST documentation string.
+ """
+ return re.sub('(?m)^', ' ' * nest, text)
--
2.20.1