Example #1
0
    def do_replace(self, alo, ahi, blo, bhi):
        lsb, lcb = self.left_insert(alo, ahi)
        rsb, rcb = self.right_insert(blo, bhi)
        self.changes.append(Change(
            rtop=rsb, rbot=rcb, ltop=lsb, lbot=lcb, kind='replace'))

        l, r = '\n'.join(self.left_lines[alo:ahi]), '\n'.join(self.right_lines[blo:bhi])
        ll, rl = self.split_words.findall(l), self.split_words.findall(r)
        cruncher = get_sequence_matcher()(None, ll, rl)
        lsb, rsb = self.left.document().findBlockByNumber(lsb), self.right.document().findBlockByNumber(rsb)

        def do_tag(block, words, lo, hi, pos, fmts):
            for word in words[lo:hi]:
                if word == '\n':
                    if fmts:
                        block.layout().setAdditionalFormats(fmts)
                    pos, block, fmts = 0, block.next(), []
                    continue

                if tag in {'replace', 'insert', 'delete'}:
                    fmt = getattr(self.left, '%s_format' % ('replacereplace' if tag == 'replace' else tag))
                    f = QTextLayout.FormatRange()
                    f.start, f.length, f.format = pos, len(word), fmt
                    fmts.append(f)
                pos += len(word)
            return block, pos, fmts

        lfmts, rfmts, lpos, rpos = [], [], 0, 0
        for tag, llo, lhi, rlo, rhi in cruncher.get_opcodes():
            lsb, lpos, lfmts = do_tag(lsb, ll, llo, lhi, lpos, lfmts)
            rsb, rpos, rfmts = do_tag(rsb, rl, rlo, rhi, rpos, rfmts)
        for block, fmts in ((lsb, lfmts), (rsb, rfmts)):
            if fmts:
                block.layout().setAdditionalFormats(fmts)
Example #2
0
    def do_replace(self, alo, ahi, blo, bhi):
        lsb, lcb = self.left_insert(alo, ahi)
        rsb, rcb = self.right_insert(blo, bhi)
        self.changes.append(Change(
            rtop=rsb, rbot=rcb, ltop=lsb, lbot=lcb, kind='replace'))

        l, r = '\n'.join(self.left_lines[alo:ahi]), '\n'.join(self.right_lines[blo:bhi])
        ll, rl = self.split_words.findall(l), self.split_words.findall(r)
        cruncher = get_sequence_matcher()(None, ll, rl)
        lsb, rsb = self.left.document().findBlockByNumber(lsb), self.right.document().findBlockByNumber(rsb)

        def do_tag(block, words, lo, hi, pos, fmts):
            for word in words[lo:hi]:
                if word == '\n':
                    if fmts:
                        block.layout().setAdditionalFormats(fmts)
                    pos, block, fmts = 0, block.next(), []
                    continue

                if tag in {'replace', 'insert', 'delete'}:
                    fmt = getattr(self.left, '%s_format' % ('replacereplace' if tag == 'replace' else tag))
                    f = QTextLayout.FormatRange()
                    f.start, f.length, f.format = pos, len(word), fmt
                    fmts.append(f)
                pos += len(word)
            return block, pos, fmts

        lfmts, rfmts, lpos, rpos = [], [], 0, 0
        for tag, llo, lhi, rlo, rhi in cruncher.get_opcodes():
            lsb, lpos, lfmts = do_tag(lsb, ll, llo, lhi, lpos, lfmts)
            rsb, rpos, rfmts = do_tag(rsb, rl, rlo, rhi, rpos, rfmts)
        for block, fmts in ((lsb, lfmts), (rsb, rfmts)):
            if fmts:
                block.layout().setAdditionalFormats(fmts)
Example #3
0
    def add_text_diff(self, left_text, right_text, context, syntax, beautify=False):
        left_text = unicodedata.normalize('NFC', left_text)
        right_text = unicodedata.normalize('NFC', right_text)
        if beautify and syntax in {'xml', 'html', 'css'}:
            left_text, right_text = beautify_text(left_text, syntax), beautify_text(right_text, syntax)
            if len(left_text) == len(right_text) and left_text == right_text:
                for v in (self.left, self.right):
                    c = v.textCursor()
                    c.movePosition(c.End)
                    c.insertText('[%s]\n\n' % _('The files are identical after beautifying'))
                return

        left_lines = self.left_lines = left_text.splitlines()
        right_lines = self.right_lines = right_text.splitlines()

        cruncher = get_sequence_matcher()(None, left_lines, right_lines)

        left_highlight, right_highlight = get_highlighter(self.left, left_text, syntax), get_highlighter(self.right, right_text, syntax)
        cl, cr = self.left_cursor, self.right_cursor = self.left.textCursor(), self.right.textCursor()
        cl.beginEditBlock(), cr.beginEditBlock()
        cl.movePosition(cl.End), cr.movePosition(cr.End)
        self.left_insert = partial(self.do_insert, cl, left_highlight, self.left.line_number_map)
        self.right_insert = partial(self.do_insert, cr, right_highlight, self.right.line_number_map)

        self.changes = []

        if context is None:
            for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
                getattr(self, tag)(alo, ahi, blo, bhi)
                QApplication.processEvents(QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers)
        else:
            def insert_boundary():
                self.changes.append(Change(
                    ltop=cl.block().blockNumber()-1, lbot=cl.block().blockNumber(),
                    rtop=cr.block().blockNumber()-1, rbot=cr.block().blockNumber(), kind='boundary'))
                self.left.line_number_map[self.changes[-1].ltop] = '-'
                self.right.line_number_map[self.changes[-1].rtop] = '-'

            ahi = bhi = 0
            for i, group in enumerate(cruncher.get_grouped_opcodes(context)):
                for j, (tag, alo, ahi, blo, bhi) in enumerate(group):
                    if j == 0 and (i > 0 or min(alo, blo) > 0):
                        insert_boundary()
                    getattr(self, tag)(alo, ahi, blo, bhi)
                    QApplication.processEvents(QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers)
                cl.insertBlock(), cr.insertBlock()
            if ahi < len(left_lines) - 1 or bhi < len(right_lines) - 1:
                insert_boundary()

        cl.endEditBlock(), cr.endEditBlock()
        del self.left_lines
        del self.right_lines
        del self.left_insert
        del self.right_insert

        self.coalesce_changes()

        for ltop, lbot, rtop, rbot, kind in self.changes:
            if kind != 'equal':
                self.left.changes.append((ltop, lbot, kind))
                self.right.changes.append((rtop, rbot, kind))

        del self.changes
Example #4
0
    def add_text_diff(self, left_text, right_text, context, syntax, beautify=False):
        left_text = unicodedata.normalize('NFC', left_text)
        right_text = unicodedata.normalize('NFC', right_text)
        if beautify and syntax in {'xml', 'html', 'css'}:
            left_text, right_text = beautify_text(left_text, syntax), beautify_text(right_text, syntax)
            if len(left_text) == len(right_text) and left_text == right_text:
                for v in (self.left, self.right):
                    c = v.textCursor()
                    c.movePosition(c.End)
                    c.insertText('[%s]\n\n' % _('The files are identical after beautifying'))
                return

        left_lines = self.left_lines = left_text.splitlines()
        right_lines = self.right_lines = right_text.splitlines()

        cruncher = get_sequence_matcher()(None, left_lines, right_lines)

        left_highlight, right_highlight = get_highlighter(self.left, left_text, syntax), get_highlighter(self.right, right_text, syntax)
        cl, cr = self.left_cursor, self.right_cursor = self.left.textCursor(), self.right.textCursor()
        cl.beginEditBlock(), cr.beginEditBlock()
        cl.movePosition(cl.End), cr.movePosition(cr.End)
        self.left_insert = partial(self.do_insert, cl, left_highlight, self.left.line_number_map)
        self.right_insert = partial(self.do_insert, cr, right_highlight, self.right.line_number_map)

        self.changes = []

        if context is None:
            for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
                getattr(self, tag)(alo, ahi, blo, bhi)
                QApplication.processEvents(QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers)
        else:
            def insert_boundary():
                self.changes.append(Change(
                    ltop=cl.block().blockNumber()-1, lbot=cl.block().blockNumber(),
                    rtop=cr.block().blockNumber()-1, rbot=cr.block().blockNumber(), kind='boundary'))
                self.left.line_number_map[self.changes[-1].ltop] = '-'
                self.right.line_number_map[self.changes[-1].rtop] = '-'

            ahi = bhi = 0
            for i, group in enumerate(cruncher.get_grouped_opcodes(context)):
                for j, (tag, alo, ahi, blo, bhi) in enumerate(group):
                    if j == 0 and (i > 0 or min(alo, blo) > 0):
                        insert_boundary()
                    getattr(self, tag)(alo, ahi, blo, bhi)
                    QApplication.processEvents(QEventLoop.ExcludeUserInputEvents | QEventLoop.ExcludeSocketNotifiers)
                cl.insertBlock(), cr.insertBlock()
            if ahi < len(left_lines) - 1 or bhi < len(right_lines) - 1:
                insert_boundary()

        cl.endEditBlock(), cr.endEditBlock()
        del self.left_lines
        del self.right_lines
        del self.left_insert
        del self.right_insert

        self.coalesce_changes()

        for ltop, lbot, rtop, rbot, kind in self.changes:
            if kind != 'equal':
                self.left.changes.append((ltop, lbot, kind))
                self.right.changes.append((rtop, rbot, kind))

        del self.changes