1 #!/usr/bin/env python 2 3 """ 4 Moin wiki table parser. 5 6 Copyright (C) 2017, 2018, 2021 Paul Boddie <paul@boddie.org.uk> 7 8 This program is free software; you can redistribute it and/or modify it under 9 the terms of the GNU General Public License as published by the Free Software 10 Foundation; either version 3 of the License, or (at your option) any later 11 version. 12 13 This program is distributed in the hope that it will be useful, but WITHOUT 14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 15 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 16 details. 17 18 You should have received a copy of the GNU General Public License along with 19 this program. If not, see <http://www.gnu.org/licenses/>. 20 """ 21 22 from moinformat.parsers.common import get_patterns, excl, group 23 from moinformat.parsers.moin import MoinParser 24 from moinformat.tree.moin import Break, Table, TableAttrs, TableCell, \ 25 TableRow, Text 26 from moinformat.tree.table import Continuation 27 28 join = "".join 29 30 # Parser functionality. 31 32 class TableParser(MoinParser): 33 34 "A parser for improved table syntax." 35 36 formats = ["table"] 37 38 # Principal parser methods. 39 40 def parse_region_content(self, items, region): 41 42 """ 43 Parse the data provided by 'items' to populate the given 'region'. For 44 table regions, normal region handling is wrapped by management of the 45 table structure. 46 """ 47 48 self.set_region(items, region) 49 50 # Start to populate table rows. 51 52 cell = TableCell([]) 53 row = TableRow([cell]) 54 table = Table([row]) 55 self.append_node(self.region, table) 56 self.new_block(cell) 57 58 while True: 59 self.parse_region_details(cell, self.region_pattern_names) 60 61 # Detect the end of the table. 62 63 pattern = self.matching_pattern() 64 65 if not pattern or pattern == "regionend": 66 break 67 68 elif pattern == "columnsep": 69 cell = TableCell([], leading=self.match_group("leading"), 70 padding=self.match_group("padding")) 71 row.append(cell) 72 self.new_block(cell) 73 74 elif pattern == "rowsep": 75 row = TableRow([], leading=self.match_group("leading"), 76 padding=self.match_group("padding")) 77 table.append(row) 78 cell = TableCell([]) 79 row.append(cell) 80 self.new_block(cell) 81 82 # Parser handler methods. 83 84 def parse_continuation(self, cell): 85 86 "Handle continuation padding." 87 88 feature = self.match_group("feature") 89 self.append_inline(cell, Continuation(feature)) 90 91 def parse_table_attrs(self, cell): 92 93 "Handle the start of table attributes within 'cell'." 94 95 MoinParser.parse_table_attrs(self, cell) 96 97 if isinstance(cell.node(-1), TableAttrs): 98 self.new_block(cell) 99 100 # Regular expressions. 101 102 syntax = {} 103 syntax.update(MoinParser.syntax) 104 syntax.update({ 105 # At start of line: 106 107 "rowsep" : join((group("leading", r"\s*"), # ws... (optional) 108 "^==", # == 109 excl(r".*==\s*?$"), # not-heading 110 group("padding", r"\s*"))), # ws... (optional) 111 112 "continuation" : group("feature", 113 join((group("leading", r"\s*"), # ws... (optional) 114 "^", 115 group("indent", r"\s*"), # ws... (optional) 116 r"\.\.", # .. 117 excl(r"\."), # not-. 118 group("padding", r"\s*")))),# ws... (optional) 119 120 # Within text: 121 122 "columnsep" : join((group("leading", r"\s*"), # ws... (optional) 123 r"\|\|", # || 124 excl(r"\|"), # not-| 125 group("padding", r"\s*"))), # ws... (optional) 126 }) 127 128 patterns = get_patterns(syntax) 129 130 131 132 # Pattern details. 133 134 region_pattern_names = [ 135 "columnsep", "continuation", "rowsep", "tableattrs", 136 ] + MoinParser.region_without_table_pattern_names 137 138 139 140 # Pattern handlers. 141 142 end_region = MoinParser.end_region 143 parse_table_end = MoinParser.parse_region_end 144 145 handlers = {} 146 handlers.update(MoinParser.handlers) 147 handlers.update({ 148 "columnsep" : end_region, 149 "continuation" : parse_continuation, 150 "rowsep" : end_region, 151 "regionend" : parse_table_end, 152 "tableattrs" : parse_table_attrs, 153 }) 154 155 parser = TableParser 156 157 # vim: tabstop=4 expandtab shiftwidth=4