def parse_block(self, text, begin): try: index = parse_brackets(text, begin)[0] except ClosingBracketError: raise SkoolKitError("No closing ')' on parameter list: {}...".format(text[begin:begin + 15])) try: index, flag = parse_brackets(text, index, '', '<', '>') except ClosingBracketError: raise SkoolKitError("No closing '>' on flags: {}...".format(text[index:index + 15])) wrap_flag = 1 if flag == 'nowrap': wrap_flag = 0 elif flag == 'wrapalign': wrap_flag = 2 indexes = [(index, 1)] # Parse the table rows or list items while True: start = text.find('{ ', index) if start < 0: break try: end = text.index(' }', start) except ValueError: raise SkoolKitError("No closing ' }}' on row/item: {}...".format(text[start:start + 15])) index = end + 2 indexes.append((index, wrap_flag)) indexes.append((len(text), 1)) return indexes
def parse_list(self, writer, list_def, *cwd): text = list_def for ws_char in '\n\r\t': text = text.replace(ws_char, ' ') try: index, params = parse_brackets(text, default='') except ClosingBracketError: raise SkoolParsingError("Cannot find closing ')' in parameter list:\n{}".format(list_def)) css_class = writer.expand(params, *cwd).strip() list_obj = List(css_class) text = writer.expand(text[index:], *cwd) index = 0 while text.find('{', index) >= 0: item_start = text.find('{ ', index) if item_start < 0: raise SkoolParsingError("Cannot find opening '{{ ' in list item:\n{0}".format(list_def)) item_end = text.find(' }', item_start) if item_end < 0: raise SkoolParsingError("Cannot find closing ' }}' in list item:\n{0}".format(list_def)) list_obj.add_item(text[item_start + 1:item_end].strip()) index = item_end + 2 return list_obj
def test_parse_brackets_with_custom_delimiters(self): self.assertEqual((0, None), parse_brackets('', opening='<', closing='>')) self.assertEqual((0, None), parse_brackets('xxx', opening='<', closing='>')) self.assertEqual((0, None), parse_brackets('()', opening='<', closing='>')) self.assertEqual((0, None), parse_brackets('(foo)', opening='<', closing='>')) self.assertEqual((2, ''), parse_brackets('<>', opening='<', closing='>')) self.assertEqual((5, 'foo'), parse_brackets('<foo>', opening='<', closing='>')) self.assertEqual((5, 'bar'), parse_brackets('[bar]', opening='[', closing=']'))
def test_parse_brackets_with_default_value_and_custom_delimiters(self): self.assertEqual((0, 'bar'), parse_brackets('', 0, 'bar', '<', '>')) self.assertEqual((1, 'bar'), parse_brackets('xxx', 1, 'bar', '<', '>')) self.assertEqual((0, 'bar'), parse_brackets('()', 0, 'bar', '<', '>')) self.assertEqual((0, 'bar'), parse_brackets('(foo)', 0, 'bar', '<', '>')) self.assertEqual((2, ''), parse_brackets('<>', 0, 'bar', '<', '>')) self.assertEqual((5, 'foo'), parse_brackets('<foo>', 0, 'bar', '<', '>'))
def parse_s(text, index): sep = text[index] end, s = parse_brackets(text, index, '', sep, sep) return end, '#IF({{case}}==1){0}{0}{1}{0}{2}{0}{0}'.format(sep, s.lower(), s)
def parse_lesson(text, index): end, lesson = parse_ints(text, index, 1) end, link_text = parse_brackets(text, end, '#N({},,,1)(0x)'.format(lesson)) return end, lesson, link_text
def parse_as(text, index): end, state = parse_ints(text, index, 1, (None,)) end, link_text = parse_brackets(text, end, '#N({},,,1)(0x)'.format(state)) return end, state, link_text
def test_parse_brackets_with_default_value(self): self.assertEqual((0, 'bar'), parse_brackets('', default='bar')) self.assertEqual((0, 'bar'), parse_brackets('xxx', default='bar')) self.assertEqual((2, ''), parse_brackets('()', default='bar')) self.assertEqual((5, 'foo'), parse_brackets('(foo)', default='bar'))
def expand_sysvar(self, text, index, cwd=None): # #SYSVAR(varname) varname = parse_brackets(text, index)[1] if varname.endswith(('-lo', '-hi')): varname = varname[:-3] return index, '#R{}'.format(SYSVARS[varname])
def test_parse_brackets(self): self.assertEqual((0, None), parse_brackets('')) self.assertEqual((0, None), parse_brackets('xxx')) self.assertEqual((5, ''), parse_brackets('...()...', 3)) self.assertEqual((5, 'foo'), parse_brackets('(foo)'))
def parse_table(self, writer, table_def, *cwd): text = table_def for ws_char in '\n\r\t': text = text.replace(ws_char, ' ') try: index, params = parse_brackets(text, default='') except ClosingBracketError: raise SkoolParsingError("Cannot find closing ')' in table CSS class list:\n{}".format(table_def)) classes = [c.strip() for c in writer.expand(params, *cwd).split(',')] table_class = classes[0] column_classes = classes[1:] wrap_columns = [] for i, column_class in enumerate(column_classes): if column_class.endswith(COLUMN_WRAP_MARKER): column_classes[i] = column_class[:-len(COLUMN_WRAP_MARKER)] wrap_columns.append(i) table = Table(table_class, wrap_columns) text = writer.expand(text[index:], *cwd) index = 0 prev_spans = {} while text.find('{', index) >= 0: row = [] row_start = text.find('{ ', index) if row_start < 0: raise SkoolParsingError("Cannot find opening '{{ ' in table row:\n{0}".format(table_def)) row_end = text.find(' }', row_start) if row_end < 0: raise SkoolParsingError("Cannot find closing ' }}' in table row:\n{0}".format(table_def)) col_index = 0 for cell in text[row_start + 1:row_end + 1].split(' | '): prev_rowspan, prev_colspan = prev_spans.get(col_index, (1, 1)) while prev_rowspan > 1: prev_spans[col_index] = (prev_rowspan - 1, prev_colspan) col_index += prev_colspan prev_rowspan, prev_colspan = prev_spans.get(col_index, (1, 1)) header, transparent = False, False rowspan, colspan = 1, 1 if len(column_classes) > col_index: cell_class = column_classes[col_index] else: cell_class = '' cell = cell.strip() if cell.startswith('='): end = cell.find(' ') if end < 0: end = len(cell) for span in cell[1:end].split(','): if span[0] == 'c': try: colspan = int(span[1:]) except ValueError: raise SkoolParsingError("Invalid colspan indicator: '{}'".format(span)) elif span[0] == 'r': try: rowspan = int(span[1:]) except ValueError: raise SkoolParsingError("Invalid rowspan indicator: '{}'".format(span)) elif span[0] == 'h': header = True elif span[0] == 't': transparent = True cell = cell[end:].lstrip() row.append(Cell(cell, transparent, colspan, rowspan, header, cell_class)) prev_spans[col_index] = (rowspan, colspan) col_index += colspan # Deal with the case where the previous row contains one or more # cells at the end with rowspan > 1 while col_index in prev_spans: prev_rowspan, prev_colspan = prev_spans[col_index] if prev_rowspan > 1: prev_spans[col_index] = (prev_rowspan - 1, prev_colspan) col_index += prev_colspan table.add_row(row) index = row_end + 1 return table
def expand_s(self, text, index, cwd=None): # #S/text/ sep = text[index] end, s = parse_brackets(text, index, '', sep, sep) return end, s.lower() if self.case == 1 else s
def parse_s(text, index, case): sep = text[index] end, s = parse_brackets(text, index, '', sep, sep) return end, s.lower() if case == 1 else s