def format(self, text, width): lines = [] for index, block in enumerate(self.expand(text).split(BLOCK_SEP)): if index % 2 == 0: if block: lines.extend(wrap(block, width)) elif block.startswith(TABLE_MARKER): table_lines = self.table_writer.format_table( block[len(TABLE_MARKER):].lstrip()) if table_lines: table_width = max([len(line) for line in table_lines]) if table_width > width: self.warn( 'Table in entry at {0} is {1} characters wide'. format(self.entry.address, table_width)) lines.extend(table_lines) elif block.startswith(LIST_MARKER): list_obj = self.list_parser.parse_list( self, block[len(LIST_MARKER):].lstrip()) for item in list_obj.items: item_lines = [] if list_obj.bullet: prefix = list_obj.bullet + ' ' indent = ' ' * len(prefix) else: prefix = indent = '' for line in wrap(item, width - len(prefix)): item_lines.append(prefix + line) prefix = indent lines.extend(item_lines) return lines
def format(self, text, width): lines = [] for block in self.extract_blocks(text): if block.startswith(TABLE_MARKER): table_lines = self.table_writer.format_table( block[len(TABLE_MARKER):].lstrip()) if table_lines: table_width = max([len(line) for line in table_lines]) if table_width > width: self.warn( 'Table in entry at {0} is {1} characters wide'. format(self.entry.address, table_width)) lines.extend(table_lines) elif block.startswith(LIST_MARKER): list_obj = self.list_parser.parse_list( self, block[len(LIST_MARKER):].lstrip()) for item in list_obj.items: item_lines = [] bullet = self.bullet indent = ' ' * len(bullet) for line in wrap(item, width - len(bullet) - 1): item_lines.append('{0} {1}'.format(bullet, line)) bullet = indent lines.extend(item_lines) else: lines.extend(wrap(self.expand(block), width)) return lines
def _write_registers(self, entry, wrote_desc): registers = [] for spec in entry.registers: if len(spec) == 1: if spec[0]: delimiters, reg, desc = parse_register(spec[0]) registers.append((reg.join(delimiters), desc)) elif self._trim_lines(spec): registers.append(('', spec)) entry.registers = registers if registers: max_indent = max(r[0].find(':') for r in registers) if not wrote_desc: self._write_empty_paragraph() wrote_desc = True self.write_comment('') self.write_asm_directives(entry.get_ignoreua_directive(REGISTERS)) for reg, desc in registers: if reg: reg = reg.rjust(max_indent + len(reg) - reg.find(':')) desc_indent = len(reg) + 1 desc_lines = wrap( desc, max(self.comment_width - desc_indent, MIN_COMMENT_WIDTH)) or [''] desc_prefix = '.'.ljust(desc_indent) write_line('; {} {}'.format(reg, desc_lines[0]).rstrip()) for line in desc_lines[1:]: write_line('; {}{}'.format(desc_prefix, line).rstrip()) else: for line in desc: write_line('; {}'.format(line).rstrip()) return wrote_desc
def print_registers(self): self.write_line(';') prefix_len = max([len(reg.prefix) for reg in self.entry.registers]) if prefix_len: prefix_len += 1 indent = ''.ljust(prefix_len) for reg in self.entry.registers: if reg.prefix: prefix = '{}:'.format(reg.prefix).rjust(prefix_len) else: prefix = indent reg_label = prefix + reg.name reg_desc = self.expand(reg.contents) if not self.entry.ignoreua['r']: uaddress = self.find_unconverted_address(reg_desc) if uaddress: line = '; {} {}'.format(reg_label, reg_desc) self.warn('Register description contains address ({}) not converted to a label:\n{}'.format(uaddress, line)) if reg_desc: desc_indent = len(reg_label) + 1 desc_lines = wrap(reg_desc, self.desc_width - desc_indent) self.write_line('; {} {}'.format(reg_label, desc_lines[0])) desc_prefix = ''.ljust(desc_indent) for line in desc_lines[1:]: self.write_line('; {}{}'.format(desc_prefix, line)) else: self.write_line('; {}'.format(reg_label))
def _format_instruction_comments(self, block, width, show_text): comment = ''.join(t[1] for t in block.comment) multi_line = len(block.instructions) > 1 and (comment or len(block.comment) > 1) opening = closing = '' if multi_line and len(block.comment) == 1 and not comment.replace('.', ''): comment = comment[1:] block.comment[0] = (0, comment) if multi_line or comment.startswith('{'): balance = comment.count('{') - comment.count('}') if multi_line and balance < 0: opening = '{' * (1 - balance) else: opening = '{' if comment.startswith('{'): opening = opening + ' ' closing = '}' * max(1 + balance, 1) if comment.endswith('}'): closing = ' ' + closing if len(block.comment) == 1: block.comment[:] = [(0, t) for t in wrap(opening + block.comment[0][1], width)] elif block.comment: if not block.comment[0][1]: block.comment.pop(0) block.comment[0] = (0, opening + block.comment[0][1]) self._set_instruction_comments(block, width, closing, show_text)
def _write_registers(self, entry, wrote_desc): registers = [] for spec in entry.registers: if len(spec) == 1: reg, desc = spec[0].partition(' ')[::2] if reg: registers.append((reg, desc)) elif self._trim_lines(spec): registers.append(('', spec)) entry.registers = registers if registers: max_indent = max(r[0].find(':') for r in registers) if not wrote_desc: self._write_empty_paragraph() wrote_desc = True self.write_comment('') if entry.has_ignoreua_directive(REGISTERS): self.write_asm_directives(AD_IGNOREUA) for reg, desc in registers: if reg: reg = reg.rjust(max_indent + len(reg) - reg.find(':')) desc_indent = len(reg) + 1 desc_lines = wrap(desc, max(self.comment_width - desc_indent, MIN_COMMENT_WIDTH)) or [''] desc_prefix = '.'.ljust(desc_indent) write_line('; {} {}'.format(reg, desc_lines[0]).rstrip()) for line in desc_lines[1:]: write_line('; {}{}'.format(desc_prefix, line).rstrip()) else: for line in desc: write_line('; {}'.format(line).rstrip()) return wrote_desc
def _format_instruction_comments(self, block, width, show_text): comment = ''.join(t[1] for t in block.comment) multi_line = len(block.instructions) > 1 and (comment or len(block.comment) > 1) opening = closing = '' if multi_line and len( block.comment) == 1 and not comment.replace('.', ''): comment = comment[1:] block.comment[0] = (0, comment) if multi_line or comment.startswith('{'): balance = comment.count('{') - comment.count('}') if multi_line and balance < 0: opening = '{' * (1 - balance) else: opening = '{' if comment.startswith('{'): opening = opening + ' ' closing = '}' * max(1 + balance, 1) if comment.endswith('}'): closing = ' ' + closing if len(block.comment) == 1: block.comment[:] = [ (0, t) for t in wrap(opening + block.comment[0][1], width) ] elif block.comment: if not block.comment[0][1]: block.comment.pop(0) block.comment[0] = (0, opening + block.comment[0][1]) self._set_instruction_comments(block, width, closing, show_text)
def print_instructions(self): i = 0 rows = 0 lines = [] instructions = self.entry.instructions while i < len(instructions) or lines: if i < len(instructions): instruction = instructions[i] else: instruction = None # Deal with remaining comment lines or rowspan on the previous # instruction if lines or rows: if rows: self.print_instruction_prefix(instruction, i) operation = instruction.operation rows -= 1 i += 1 else: operation = '' if lines: line_comment = lines.pop(0) oline = '{0}{1} ; {2}'.format(self.indent, operation.ljust(instr_width), line_comment) if not ignoreua: uaddress = self.find_unconverted_address(line_comment) if uaddress: self.warn( 'Comment at {} contains address ({}) not converted to a label:\n{}' .format(iaddress, uaddress, oline)) elif rowspan > 1: oline = '{}{} ;'.format(self.indent, operation.ljust(instr_width)) else: oline = self.indent + operation self.write_line(oline) if len(oline) > self.line_width: self.warn('Line is {0} characters long:\n{1}'.format( len(oline), oline)) continue # pragma: no cover ignoreua = instruction.ignoreua iaddress = instruction.address rowspan = rows = instruction.comment.rowspan instr_width = max( [len(i.operation) for i in instructions[i:i + rowspan]] + [self.instr_width]) comment_width = self.line_width - 3 - instr_width - self.indent_width lines = wrap(self.expand(instruction.comment.text), max((comment_width, self.min_comment_width)))
def wrap(self, text): lines = [] for line, wrap_flag in self.parse_blocks(text): if wrap_flag == 0: lines.append(line) elif wrap_flag == 1: lines.extend(wrap(line, self.comment_width)) else: block = wrap(line, self.comment_width) lines.append(block[0]) if len(block) > 1: if block[0].endswith(' |'): indent = 2 else: indent = block[0].rfind(' | ') + 3 while indent < len(block[0]) and block[0][indent] == ' ': indent += 1 pad = ' ' * indent lines.extend(pad + line for line in wrap(' '.join(block[1:]), self.comment_width - indent)) return lines
def format(self, text, width): lines = [] for block in self.extract_blocks(text): if block.startswith(TABLE_MARKER): table_lines = self.table_writer.format_table(block[len(TABLE_MARKER):].lstrip()) if table_lines: table_width = max([len(line) for line in table_lines]) if table_width > width: self.warn('Table in entry at {0} is {1} characters wide'.format(self.entry.address, table_width)) lines.extend(table_lines) elif block.startswith(LIST_MARKER): list_obj = self.list_parser.parse_list(self, block[len(LIST_MARKER):].lstrip()) for item in list_obj.items: item_lines = [] bullet = self.bullet indent = ' ' * len(bullet) for line in wrap(item, width - len(bullet) - 1): item_lines.append('{0} {1}'.format(bullet, line)) bullet = indent lines.extend(item_lines) else: lines.extend(wrap(self.expand(block), width)) return lines
def _write_registers(self, entry): self.write_comment('') if entry.has_ignoreua_directive(REGISTERS): self.write_asm_directive(AD_IGNOREUA) max_indent = max([reg.find(':') for reg, desc in entry.registers]) for reg, desc in entry.registers: reg = reg.rjust(max_indent + len(reg) - reg.find(':')) if desc: desc_indent = len(reg) + 1 desc_lines = wrap(desc, max(self.comment_width - desc_indent, MIN_COMMENT_WIDTH)) write_line('; {} {}'.format(reg, desc_lines[0])) desc_prefix = '.'.ljust(desc_indent) for line in desc_lines[1:]: write_line('; {}{}'.format(desc_prefix, line)) else: write_line('; {}'.format(reg))
def _write_registers(self, entry): self.write_comment('') if entry.has_ignoreua_directive(REGISTERS): self.write_asm_directives(AD_IGNOREUA) max_indent = max([reg.find(':') for reg, desc in entry.registers]) for reg, desc in entry.registers: reg = reg.rjust(max_indent + len(reg) - reg.find(':')) if desc: desc_indent = len(reg) + 1 desc_lines = wrap(desc, max(self.comment_width - desc_indent, MIN_COMMENT_WIDTH)) write_line('; {} {}'.format(reg, desc_lines[0])) desc_prefix = '.'.ljust(desc_indent) for line in desc_lines[1:]: write_line('; {}{}'.format(desc_prefix, line)) else: write_line('; {}'.format(reg))
def print_instructions(self): i = 0 rowspan = 0 lines = [] instructions = self.entry.instructions while i < len(instructions) or lines: if i < len(instructions): instruction = instructions[i] else: instruction = None # Deal with remaining comment lines or rowspan on the previous # instruction if lines or rowspan > 0: if rowspan > 0: self.print_instruction_prefix(instruction, i) operation = instruction.operation rowspan -= 1 i += 1 else: operation = '' if lines: line_comment = lines.pop(0) oline = '{0}{1} ; {2}'.format(self.indent, operation.ljust(instr_width), line_comment) else: line_comment = '' oline = '{0}{1}'.format(self.indent, operation) self.write_line(oline) if not ignoreua: uaddress = self.find_unconverted_address(line_comment) if uaddress: self.warn('Comment at {0} contains address ({1}) not converted to a label:\n{2}'.format(iaddress, uaddress, oline)) if len(oline) > self.line_width: self.warn('Line is {0} characters long:\n{1}'.format(len(oline), oline)) continue # pragma: no cover ignoreua = instruction.ignoreua iaddress = instruction.address rowspan = instruction.comment.rowspan instr_width = max(len(instruction.operation), self.instr_width) comment_width = self.line_width - 3 - instr_width - self.indent_width lines = wrap(self.expand(instruction.comment.text), max((comment_width, self.min_comment_width)))
def reduce_width(self, max_table_width, min_col_width): # Reduce the width of the wrappable columns until either the table is # narrow enough or all the wrappable columns are the minimum width done = False while self.get_width() > max_table_width and not done: done = True for wrap_col in self.wrap_columns: if self.col_widths[wrap_col] > min_col_width: self.col_widths[wrap_col] -= 1 done = False # Wrap the contents of the cells in the wrappable columns for cell in [c for c in self.cells if c.col_index in self.wrap_columns]: width = self.get_cell_width(cell.col_index, cell.colspan) cell.contents = wrap(cell.contents[0], width) or [''] # The column widths need to be recalculated now self._calculate_col_widths()
def _format_block_comment(self, block, width): rowspan = len(block.instructions) comment = block.comment multi_line = rowspan > 1 and comment if multi_line and not comment.replace('.', ''): comment = comment[1:] if multi_line or comment.startswith('{'): balance = comment.count('{') - comment.count('}') if multi_line and balance < 0: opening = '{' * (1 - balance) else: opening = '{' if comment.startswith('{'): opening = opening + ' ' closing = '}' * max(1 + balance, 1) if comment.endswith('}'): closing = ' ' + closing comment = opening + comment + closing comment_lines = wrap(comment, width) if multi_line and len(comment_lines) < rowspan: comment_lines[-1] = comment_lines[-1][:-len(closing)] comment_lines.extend([''] * (rowspan - len(comment_lines) - 1)) comment_lines.append(closing.lstrip()) return comment_lines
def wrap(self, text): lines = [] for line in self.parse_blocks(text): lines.extend(wrap(line, self.comment_width)) return lines