1.1 --- a/moinconvert Mon Nov 26 22:59:52 2018 +0100
1.2 +++ b/moinconvert Tue Nov 27 22:50:43 2018 +0100
1.3 @@ -78,6 +78,10 @@
1.4 dirname, progname = split(sys.argv[0])
1.5 args = sys.argv[1:]
1.6
1.7 + if "--help" in args:
1.8 + show_help(progname)
1.9 + sys.exit(0)
1.10 +
1.11 # Option values.
1.12
1.13 l = filenames = []
1.14 @@ -307,6 +311,53 @@
1.15 if theme:
1.16 theme.install_resources()
1.17
1.18 +def show_help(progname):
1.19 +
1.20 + "Show the help text."
1.21 +
1.22 + print >>sys.stderr, help_text % progname
1.23 +
1.24 +help_text = """\
1.25 +Usage: %s [ <options> ] ( --all | <filename>... )
1.26 +
1.27 +Input options:
1.28 +
1.29 +--all Detect all document files in the specified input directory
1.30 +--input-dir Indicate an input directory containing document files
1.31 +--input-dir-type Indicate the type of input directory involved
1.32 + (default: directory)
1.33 +--input-encoding Indicate the character encoding used in document files
1.34 +--input-page-sep Indicate the separator used in filenames to encode
1.35 + hierarchical relationships (subpages and descendant pages)
1.36 +--pagename Indicate the page name corresponding to an indicated
1.37 + filename, with each successive instance of this option
1.38 + corresponding to each successive filename instance
1.39 +
1.40 +Output options:
1.41 +
1.42 +--format Indicate the format to be used for serialised documents
1.43 + (default: html)
1.44 +--fragment Indicates that an output fragment, not an entire document,
1.45 + is to be generated, skipping any theming activities
1.46 +--output-dir Indicate an output directory to contain serialised document
1.47 + files
1.48 +--output-encoding Indicate the character encoding used in serialised document
1.49 + files
1.50 +--theme Indicate a theme for serialised documents, typically
1.51 + requiring an output directory to be useful
1.52 +--tree Produce a document tree representation on standard output
1.53 + instead of generating output files
1.54 +
1.55 +Configuration options:
1.56 +
1.57 +--macros Perform macro evaluation/expansion before serialising
1.58 + documents
1.59 +--mapping Indicate a name and corresponding URL to be used to
1.60 + translate interwiki links
1.61 +--root Indicate the root page name to be used
1.62 + (default: FrontPage)
1.63 +"""
1.64 +
1.65 if __name__ == "__main__":
1.66 main()
1.67
2.1 --- a/moinformat/input/directory.py Mon Nov 26 22:59:52 2018 +0100
2.2 +++ b/moinformat/input/directory.py Tue Nov 27 22:50:43 2018 +0100
2.3 @@ -25,7 +25,7 @@
2.4
2.5 class DirectoryInput(Input):
2.6
2.7 - "A directory output context."
2.8 + "A directory input context."
2.9
2.10 name = "directory"
2.11
3.1 --- a/moinformat/parsers/common.py Mon Nov 26 22:59:52 2018 +0100
3.2 +++ b/moinformat/parsers/common.py Tue Nov 27 22:50:43 2018 +0100
3.3 @@ -356,6 +356,11 @@
3.4
3.5 self.set_region(items, region)
3.6
3.7 + # Only parse directives if the region is transparent.
3.8 +
3.9 + if region.transparent:
3.10 + self.parse_region_directives(region)
3.11 +
3.12 # Parse inline and opaque regions.
3.13
3.14 if not region.transparent:
3.15 @@ -410,11 +415,6 @@
3.16 region.transparent = False
3.17 parser = parser or self.get_parser("moin")
3.18
3.19 - # Only parse directives if the region is transparent.
3.20 -
3.21 - if region.transparent:
3.22 - self.parse_region_directives(region)
3.23 -
3.24 parser.parse_region_content(self.items, region)
3.25
3.26 def parse_region_header(self, region):
4.1 --- a/moinformat/parsers/graphviz.py Mon Nov 26 22:59:52 2018 +0100
4.2 +++ b/moinformat/parsers/graphviz.py Tue Nov 27 22:50:43 2018 +0100
4.3 @@ -20,7 +20,8 @@
4.4 this program. If not, see <http://www.gnu.org/licenses/>.
4.5 """
4.6
4.7 -from moinformat.parsers.common import ParserBase, get_patterns, group, optional
4.8 +from moinformat.parsers.common import ParserBase, choice, get_patterns, group, \
4.9 + optional
4.10 from moinformat.parsers.moin import MoinParser
4.11 from moinformat.tree.graphviz import Directive
4.12 from moinformat.tree.moin import Text
4.13 @@ -41,9 +42,11 @@
4.14
4.15 "Handle format directives."
4.16
4.17 + directive = self.match_group("directive")
4.18 key = self.match_group("key")
4.19 value = self.match_group("value")
4.20 - self.add_node(region, Directive(key, value))
4.21 +
4.22 + self.add_node(region, Directive(key, value, directive))
4.23 self.new_block(region)
4.24
4.25
4.26 @@ -53,11 +56,17 @@
4.27 syntax = {
4.28 # At start of line:
4.29
4.30 - "directive" : join(("^//", # //
4.31 - group("key", ".*?"), # text-excl-eq-nl
4.32 - optional(join(("=", # eq (optional)
4.33 - group("value", ".*?")))), # text-excl-nl (optional)
4.34 - "\n")), # nl
4.35 + "directive" : choice((join((r"^#", # #
4.36 + group("directive", r".*?$"), # rest of line
4.37 + optional(group("extra", r"\n")))), # nl (optional)
4.38 +
4.39 + # Legacy GraphvizParser directive syntax:
4.40 +
4.41 + join(("^//", # //
4.42 + group("key", ".*?"), # text-excl-eq-nl
4.43 + optional(join(("=", # eq (optional)
4.44 + group("value", ".*?")))), # text-excl-nl (optional)
4.45 + "\n")))), # nl
4.46
4.47 "regionend" : MoinParser.syntax["regionend"],
4.48 }
5.1 --- a/moinformat/serialisers/html/graphviz.py Mon Nov 26 22:59:52 2018 +0100
5.2 +++ b/moinformat/serialisers/html/graphviz.py Tue Nov 27 22:50:43 2018 +0100
5.3 @@ -57,7 +57,7 @@
5.4 def end_block(self):
5.5 pass
5.6
5.7 - def directive(self, key, value):
5.8 + def directive(self, key, value, directive):
5.9 if not self.directives.has_key(key):
5.10 self.directives[key] = []
5.11 self.directives[key].append(value)
5.12 @@ -97,27 +97,36 @@
5.13 format = self.directives.get("format", ["svg"])[0]
5.14 transforms = self.directives.get("transform", [])
5.15
5.16 - # Graph output is stored for a known page only.
5.17 + inline = format == "svg"
5.18 +
5.19 + # Non-inline graph output is stored for a known page only.
5.20
5.21 pagename = self.metadata.get("pagename")
5.22 - if not pagename:
5.23 - return
5.24 +
5.25 + if not inline:
5.26 + if not pagename:
5.27 + return
5.28
5.29 - # Get an identifier and usable filename to store the output.
5.30 + # Get an identifier and usable filename to store the output.
5.31
5.32 - identifier = get_output_identifier(text)
5.33 - attachment = "%s.%s" % (identifier, format)
5.34 - filename = self.output.get_attachment_filename(pagename, attachment)
5.35 + identifier = get_output_identifier(text)
5.36 + attachment = "%s.%s" % (identifier, format)
5.37 + filename = self.output.get_attachment_filename(pagename, attachment)
5.38 +
5.39 + # Handle situations where no independent output is permitted.
5.40
5.41 - # Handle situations where no independent output is permitted.
5.42 + if not filename:
5.43 + return
5.44
5.45 - if not filename:
5.46 - return
5.47 + # Make sure that page attachments can be stored.
5.48
5.49 - # Make sure that page attachments can be stored.
5.50 + self.output.ensure_attachments(pagename)
5.51 + target, _label = self.linker.translate("attachment:%s" % attachment)
5.52
5.53 - self.output.ensure_attachments(pagename)
5.54 - target, label = self.linker.translate("attachment:%s" % attachment)
5.55 + # No filename is defined for inline output.
5.56 +
5.57 + else:
5.58 + filename = None
5.59
5.60 # Permit imagemaps only for image formats.
5.61
5.62 @@ -126,7 +135,7 @@
5.63
5.64 # Configure Graphviz and invoke it.
5.65
5.66 - graphviz = Graphviz(filter, text, identifier)
5.67 + graphviz = Graphviz(filter, text)
5.68 graphviz.call(format, transforms, filename)
5.69
5.70 # Obtain any metadata.
5.71 @@ -151,8 +160,13 @@
5.72
5.73 # For other output, create a file and embed the object.
5.74
5.75 + elif not inline:
5.76 + self.object(target, attributes)
5.77 +
5.78 + # Or for inline output, emit it in the document itself.
5.79 +
5.80 else:
5.81 - self.object(target, attributes)
5.82 + self.out(graphviz.get_inline_output())
5.83
5.84 serialiser = HTMLGraphvizSerialiser
5.85
6.1 --- a/moinformat/serialisers/moin/graphviz.py Mon Nov 26 22:59:52 2018 +0100
6.2 +++ b/moinformat/serialisers/moin/graphviz.py Tue Nov 27 22:50:43 2018 +0100
6.3 @@ -31,8 +31,11 @@
6.4 def end_block(self):
6.5 pass
6.6
6.7 - def directive(self, key, value):
6.8 - self.out("//%s%s\n" % (value and "%s=" % key or key, value or ""))
6.9 + def directive(self, key, value, directive):
6.10 + if directive:
6.11 + self.out("#%s\n" % directive)
6.12 + else:
6.13 + self.out("//%s%s\n" % (value and "%s=" % key or key, value or ""))
6.14
6.15 def text(self, text):
6.16 self.out(text)
7.1 --- a/moinformat/tree/graphviz.py Mon Nov 26 22:59:52 2018 +0100
7.2 +++ b/moinformat/tree/graphviz.py Tue Nov 27 22:50:43 2018 +0100
7.3 @@ -25,17 +25,24 @@
7.4
7.5 "Format directive for Graphviz output."
7.6
7.7 - def __init__(self, key=None, value=None):
7.8 - self.key = key
7.9 - self.value = value
7.10 + def __init__(self, key=None, value=None, directive=None):
7.11 + self.directive = directive
7.12 +
7.13 + if key or value:
7.14 + self.key = key
7.15 + self.value = value
7.16 + else:
7.17 + t = directive.split(None, 1)
7.18 + self.key = t[0]
7.19 + self.value = len(t) > 1 and t[1] or None
7.20
7.21 def __repr__(self):
7.22 - return "Directive(%r, %r)" % (self.key, self.value)
7.23 + return "Directive(%r, %r, %r)" % (self.key, self.value, self.directive)
7.24
7.25 def prettyprint(self, indent=""):
7.26 - return "%sDirective: key=%r value=%r" % (indent, self.key, self.value)
7.27 + return "%sDirective: key=%r value=%r directive=%r" % (indent, self.key, self.value, self.directive)
7.28
7.29 def to_string(self, out):
7.30 - out.directive(self.key, self.value)
7.31 + out.directive(self.key, self.value, self.directive)
7.32
7.33 # vim: tabstop=4 expandtab shiftwidth=4
8.1 --- a/moinformat/utils/graphviz.py Mon Nov 26 22:59:52 2018 +0100
8.2 +++ b/moinformat/utils/graphviz.py Tue Nov 27 22:50:43 2018 +0100
8.3 @@ -22,6 +22,7 @@
8.4 from os.path import exists, join
8.5 from StringIO import StringIO
8.6 from subprocess import Popen, PIPE
8.7 +from xml.sax.saxutils import XMLGenerator
8.8 import gzip
8.9 import sha
8.10 import xml.sax
8.11 @@ -63,16 +64,9 @@
8.12 else:
8.13 return s
8.14
8.15 -class MetadataParser(xml.sax.handler.ContentHandler):
8.16 -
8.17 - "Parse metadata from the svg element."
8.18 +class Parser(xml.sax.handler.ContentHandler):
8.19
8.20 - def __init__(self):
8.21 - self.attrs = {}
8.22 -
8.23 - def startElement(self, name, attrs):
8.24 - if name == self.tagname:
8.25 - self.attrs = dict(attrs)
8.26 + "Common XML parsing functionality."
8.27
8.28 def parse(self, f):
8.29
8.30 @@ -87,11 +81,9 @@
8.31 finally:
8.32 f.close()
8.33
8.34 - def get_metadata(self, data, tagname):
8.35 + def parse_data(self, data):
8.36
8.37 - "Process 'data', returning attributes from 'tagname'."
8.38 -
8.39 - self.tagname = tagname
8.40 + "Parse the given 'data'."
8.41
8.42 f = StringIO(data)
8.43 try:
8.44 @@ -99,8 +91,32 @@
8.45 finally:
8.46 f.close()
8.47
8.48 +class MetadataParser(Parser):
8.49 +
8.50 + "Parse metadata from the svg element."
8.51 +
8.52 + def __init__(self):
8.53 + self.attrs = {}
8.54 +
8.55 + def startElement(self, name, attrs):
8.56 + if name == self.tagname:
8.57 + self.attrs = dict(attrs)
8.58 +
8.59 + def get_metadata(self, data, tagname):
8.60 +
8.61 + "Process 'data', returning attributes from 'tagname'."
8.62 +
8.63 + self.tagname = tagname
8.64 + self.parse_data(data)
8.65 return self.attrs
8.66
8.67 +class DocumentSelector(XMLGenerator, Parser):
8.68 +
8.69 + "Parse a document and obtain the serialisation of the document node."
8.70 +
8.71 + def startDocument(self):
8.72 + pass
8.73 +
8.74 def get_output_identifier(text):
8.75
8.76 "Return an output identifier for the given 'text'."
8.77 @@ -179,17 +195,14 @@
8.78
8.79 "A Graphviz configuration for single or repeated invocation."
8.80
8.81 - def __init__(self, filter, text, identifier):
8.82 + def __init__(self, filter, text):
8.83
8.84 """
8.85 - Employ the given 'filter' to produce a graph from the given 'text'. The
8.86 - output 'identifier' for the text is used to provide a filename, if
8.87 - required.
8.88 + Employ the given 'filter' to produce a graph from the given 'text'.
8.89 """
8.90
8.91 self.filter = filter
8.92 self.text = text
8.93 - self.identifier = identifier
8.94
8.95 def call(self, format, transforms=None, filename=None):
8.96
8.97 @@ -264,4 +277,20 @@
8.98 def get_output(self):
8.99 return self.output
8.100
8.101 + def get_inline_output(self):
8.102 +
8.103 + """
8.104 + Return a string containing the document element, excluding XML
8.105 + boilerplate.
8.106 + """
8.107 +
8.108 + f = StringIO()
8.109 + parser = DocumentSelector(f, "utf-8")
8.110 +
8.111 + try:
8.112 + parser.parse_data(self.output)
8.113 + return f.getvalue()
8.114 + finally:
8.115 + f.close()
8.116 +
8.117 # vim: tabstop=4 expandtab shiftwidth=4
9.1 --- a/tests/test_regions_opaque.txt Mon Nov 26 22:59:52 2018 +0100
9.2 +++ b/tests/test_regions_opaque.txt Tue Nov 27 22:50:43 2018 +0100
9.3 @@ -1,5 +1,6 @@
9.4 Hello
9.5 {{{{#!xxx
9.6 +# Not a directive
9.7 A region
9.8 {{{
9.9 Another