1.1 --- a/moinformat/__init__.py Mon May 01 00:29:59 2017 +0200
1.2 +++ b/moinformat/__init__.py Mon May 01 18:24:22 2017 +0200
1.3 @@ -19,8 +19,8 @@
1.4 this program. If not, see <http://www.gnu.org/licenses/>.
1.5 """
1.6
1.7 -from moinformat.tree import Block, Break, DefItem, DefTerm, Emphasis, Heading, \
1.8 - ListItem, Region, Rule, Strong, Text
1.9 +from moinformat.tree import Block, Break, DefItem, DefTerm, FontStyle, Heading, \
1.10 + ListItem, Monospace, Region, Rule, Text
1.11 import re
1.12
1.13 # Regular expressions.
1.14 @@ -54,13 +54,12 @@
1.15
1.16 # Region contents:
1.17 # Inline patterns:
1.18 - "em" : r"''(?!')", # '' expecting not '
1.19 + "fontstyle" : r"('{2,6})",
1.20 + "monospace" : r"`",
1.21 "rule" : r"(-----*)", # ----...
1.22 - "strong" : r"'''", # '''
1.23
1.24 # Inline contents:
1.25 - "emend" : r"''(?!')|''(?='')",
1.26 - "strongend" : r"'''",
1.27 + "monospaceend" : r"`",
1.28
1.29 # Heading contents:
1.30 "headingend" : r"(\s+)(=+)(\s*\n)", # ws... =... [ws...] nl
1.31 @@ -91,6 +90,12 @@
1.32 self.match = None
1.33 self.matching = None
1.34
1.35 + def rewind(self, length):
1.36 +
1.37 + "Rewind in the string by 'length'."
1.38 +
1.39 + self.pos -= min(length, self.pos)
1.40 +
1.41 def read_until(self, pattern_names, remaining=True):
1.42
1.43 """
1.44 @@ -191,12 +196,13 @@
1.45 parse_region_details(items, region, [
1.46 "break", "heading",
1.47 "defterm", "defterm_empty",
1.48 - "em",
1.49 + "fontstyle",
1.50 "listitem", "listitem_alpha", "listitem_dot", "listitem_num",
1.51 "listitem_roman",
1.52 + "monospace",
1.53 "regionstart", "regionend",
1.54 "rule",
1.55 - "strong"])
1.56 + ])
1.57
1.58 def parse_region_opaque(items, region):
1.59
1.60 @@ -281,12 +287,43 @@
1.61 parse_region_details(items, region, ["deftermsep"])
1.62 parse_defitem(items, region, extra)
1.63
1.64 -def parse_em(items, region):
1.65 +def parse_fontstyle(items, region):
1.66 +
1.67 + "Handle emphasis and strong styles."
1.68 +
1.69 + n = len(items.read_match(1))
1.70 +
1.71 + # Handle endings.
1.72 +
1.73 + if isinstance(region, FontStyle):
1.74 + emphasis = n in (2, 4, 5)
1.75 + strong = n in (3, 5, 6)
1.76 + active = True
1.77
1.78 - "Handle emphasis."
1.79 + if region.emphasis and emphasis:
1.80 + active = region.close_emphasis()
1.81 + n -= 2
1.82 + if region.strong and strong:
1.83 + active = region.close_strong()
1.84 + n -= 3
1.85 +
1.86 + if not active:
1.87 + if n:
1.88 + items.rewind(n)
1.89 + raise StopIteration
1.90
1.91 - span = Emphasis([])
1.92 - parse_region_details(items, span, ["emend", "strong"])
1.93 + elif not n:
1.94 + return
1.95 +
1.96 + # Handle new styles.
1.97 +
1.98 + emphasis = n in (2, 4, 5)
1.99 + strong = n in (3, 5, 6)
1.100 + double = n in (4, 6)
1.101 +
1.102 + span = FontStyle([], emphasis, strong)
1.103 + if not double:
1.104 + parse_region_details(items, span, ["fontstyle", "monospace"])
1.105 region.append_inline(span)
1.106
1.107 def parse_heading(items, region):
1.108 @@ -323,6 +360,14 @@
1.109 region.append(item)
1.110 new_block(region)
1.111
1.112 +def parse_monospace(items, region):
1.113 +
1.114 + "Handle monospace."
1.115 +
1.116 + span = Monospace([])
1.117 + parse_region_details(items, span, ["fontstyle", "monospaceend"])
1.118 + region.append_inline(span)
1.119 +
1.120 def parse_rule(items, region):
1.121
1.122 "Handle a horizontal rule within 'region'."
1.123 @@ -353,14 +398,6 @@
1.124 else:
1.125 region.append_inline(Text(feature))
1.126
1.127 -def parse_strong(items, region):
1.128 -
1.129 - "Handle emboldened text."
1.130 -
1.131 - span = Strong([])
1.132 - parse_region_details(items, span, ["em", "strongend"])
1.133 - region.append_inline(span)
1.134 -
1.135 # Pattern handlers.
1.136
1.137 handlers = {
1.138 @@ -370,8 +407,7 @@
1.139 "defterm_empty" : parse_defterm_empty,
1.140 "deftermend" : end_region,
1.141 "deftermsep" : end_region,
1.142 - "em" : parse_em,
1.143 - "emend" : end_region,
1.144 + "fontstyle" : parse_fontstyle,
1.145 "heading" : parse_heading,
1.146 "headingend" : parse_heading_end,
1.147 "listitemend" : end_region,
1.148 @@ -380,11 +416,11 @@
1.149 "listitem_dot" : parse_listitem,
1.150 "listitem_num" : parse_listitem,
1.151 "listitem_roman" : parse_listitem,
1.152 + "monospace" : parse_monospace,
1.153 + "monospaceend" : end_region,
1.154 "regionstart" : parse_section,
1.155 "regionend" : parse_section_end,
1.156 "rule" : parse_rule,
1.157 - "strong" : parse_strong,
1.158 - "strongend" : end_region,
1.159 }
1.160
1.161 def new_block(region):
3.1 --- a/moinformat/tree.py Mon May 01 00:29:59 2017 +0200
3.2 +++ b/moinformat/tree.py Mon May 01 18:24:22 2017 +0200
3.3 @@ -187,21 +187,46 @@
3.4 self._to_string(out)
3.5 out.end_defterm(self.pad)
3.6
3.7 -class Emphasis(Container):
3.8 +class FontStyle(Container):
3.9 +
3.10 + "Emphasised and/or strong text."
3.11 +
3.12 + def __init__(self, nodes, emphasis=False, strong=False):
3.13 + Container.__init__(self, nodes)
3.14 + self.emphasis = emphasis
3.15 + self.strong = strong
3.16
3.17 - "Emphasised text."
3.18 + def close_emphasis(self):
3.19 + if self.strong:
3.20 + span = FontStyle(self.nodes, emphasis=True)
3.21 + self.nodes = [span]
3.22 + self.emphasis = False
3.23 + return self.strong
3.24 +
3.25 + def close_strong(self):
3.26 + if self.emphasis:
3.27 + span = FontStyle(self.nodes, strong=True)
3.28 + self.nodes = [span]
3.29 + self.strong = False
3.30 + return self.emphasis
3.31
3.32 def __repr__(self):
3.33 - return "Emphasis(%r)" % self.nodes
3.34 + return "FontStyle(%r, %r, %r)" % (self.nodes, self.emphasis, self.strong)
3.35
3.36 def prettyprint(self, indent=""):
3.37 - l = ["%sEmphasis" % indent]
3.38 + l = ["%sFontStyle: emphasis=%r strong=%r" % (indent, self.emphasis, self.strong)]
3.39 return self._prettyprint(l, indent)
3.40
3.41 def to_string(self, out):
3.42 - out.start_emphasis()
3.43 + if self.emphasis:
3.44 + out.start_emphasis()
3.45 + elif self.strong:
3.46 + out.start_strong()
3.47 self._to_string(out)
3.48 - out.end_emphasis()
3.49 + if self.emphasis:
3.50 + out.end_emphasis()
3.51 + elif self.strong:
3.52 + out.end_strong()
3.53
3.54 class Heading(Container):
3.55
3.56 @@ -251,21 +276,21 @@
3.57 self._to_string(out)
3.58 out.end_listitem(self.indent, self.marker)
3.59
3.60 -class Strong(Container):
3.61 +class Monospace(Container):
3.62
3.63 - "Emboldened text."
3.64 + "Monospace text."
3.65
3.66 def __repr__(self):
3.67 - return "Strong(%r)" % self.nodes
3.68 + return "Monospace(%r)" % self.nodes
3.69
3.70 def prettyprint(self, indent=""):
3.71 - l = ["%sStrong" % indent]
3.72 + l = ["%sMonospace" % indent]
3.73 return self._prettyprint(l, indent)
3.74
3.75 def to_string(self, out):
3.76 - out.start_strong()
3.77 + out.start_monospace()
3.78 self._to_string(out)
3.79 - out.end_strong()
3.80 + out.end_monospace()
3.81
3.82
3.83