⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 filediff.py

📁 LINUX下的文件比较工具
💻 PY
📖 第 1 页 / 共 4 页
字号:
                    for o in matcher.get_opcodes():                        if o[0] == "equal":                            if (o[2]-o[1] < 3) or (o[4]-o[3] < 3):                                back = o[4]-o[3], o[2]-o[1]                            continue                        for i in range(2):                            s,e = starts[i].copy(), starts[i].copy()                            s.forward_chars( o[1+2*i] - back[i] )                            e.forward_chars( o[2+2*i] )                            bufs[i].apply_tag(tags[i], s, e)                        back = (0,0)                    yield 1    def on_textview_expose_event(self, textview, event):        if self.num_panes == 1:            return        if event.window != textview.get_window(gtk.TEXT_WINDOW_TEXT) \            and event.window != textview.get_window(gtk.TEXT_WINDOW_LEFT):            return        if not hasattr(textview, "meldgc"):            self._setup_gcs(textview)        visible = textview.get_visible_rect()        pane = self.textview.index(textview)        start_line = self._pixel_to_line(pane, visible.y)        end_line = 1+self._pixel_to_line(pane, visible.y+visible.height)        gc = lambda x : getattr(textview.meldgc, "gc_"+x)        #gcdark = textview.get_style().black_gc        gclight = textview.get_style().bg_gc[gtk.STATE_ACTIVE]        #curline = textview.get_buffer().get_iter_at_mark( textview.get_buffer().get_insert() ).get_line()                       def draw_change(change): # draw background and thin lines            ypos0 = self._line_to_pixel(pane, change[1]) - visible.y            width = event.window.get_size()[0]            #gcline = (gclight, gcdark)[change[1] <= curline and curline < change[2]]            gcline = gclight            event.window.draw_line(gcline, 0,ypos0-1, width,ypos0-1)            if change[2] != change[1]:                ypos1 = self._line_to_pixel(pane, change[2]) - visible.y                event.window.draw_line(gcline, 0,ypos1, width,ypos1)                event.window.draw_rectangle(gc(change[0]), 1, 0,ypos0, width,ypos1-ypos0)        last_change = None        for change in self.linediffer.single_changes(pane, self._get_texts()):            if change[2] < start_line: continue            if change[1] > end_line: break            if last_change and change[1] <= last_change[2]:                last_change = ("conflict", last_change[1], max(last_change[2],change[2]))            else:                if last_change:                    draw_change(last_change)                last_change = change        if last_change:            draw_change(last_change)            def _get_filename_for_saving(self, title ):        dialog = gtk.FileChooserDialog(title,            parent=self.widget.get_toplevel(),            action=gtk.FILE_CHOOSER_ACTION_SAVE,            buttons = (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK) )        response = dialog.run()        filename = None        if response == gtk.RESPONSE_OK:            filename = dialog.get_filename()        dialog.destroy()        if filename:            if os.path.exists(filename):                response = misc.run_dialog(                    _('"%s" exists!\nOverwrite?') % os.path.basename(filename),                    parent = self,                    buttonstype = gtk.BUTTONS_YES_NO)                if response == gtk.RESPONSE_NO:                    return None            return filename        return None    def _save_text_to_filename(self, filename, text):        try:            open(filename, "w").write(text)        except IOError, e:            misc.run_dialog(                _("Error writing to %s\n\n%s.") % (filename, e),                self, gtk.MESSAGE_ERROR, gtk.BUTTONS_OK)            return False        return True    def save_file(self, pane, saveas=0):        buf = self.textview[pane].get_buffer()        bufdata = self.bufferdata[pane]        if saveas or not bufdata.filename:            filename = self._get_filename_for_saving( _("Choose a name for buffer %i.") % (pane+1) )            if filename:                bufdata.filename = os.path.abspath(filename)                self.fileentry[pane].set_filename( bufdata.filename)            else:                return melddoc.RESULT_ERROR        text = buf.get_text(buf.get_start_iter(), buf.get_end_iter(), 0)        if bufdata.newlines:            if type(bufdata.newlines) == type(""):                if(bufdata.newlines) != '\n':                    text = text.replace("\n", bufdata.newlines)            elif type(bufdata.newlines) == type(()):                buttons = {'\n':("UNIX (LF)",0), '\r\n':("DOS (CR-LF)", 1), '\r':("MAC (CR)",2) }                newline = misc.run_dialog( _("This file '%s' contains a mixture of line endings.\n\nWhich format would you like to use?") % bufdata.filename,                    self, gtk.MESSAGE_WARNING, buttonstype=gtk.BUTTONS_CANCEL,                    extrabuttons=[ buttons[b] for b in bufdata.newlines ] )                if newline < 0:                    return                for k,v in buttons.items():                    if v[1] == newline:                        bufdata.newlines = k                        if k != '\n':                            text = text.replace('\n', k)                        break        if bufdata.encoding and self.prefs.save_encoding==0:            try:                text = text.encode(bufdata.encoding)            except UnicodeEncodeError:                if misc.run_dialog(                    _("'%s' contains characters not encodable with '%s'\nWould you like to save as UTF-8?") % (bufdata.filename, bufdata.encoding),                    self, gtk.MESSAGE_ERROR, gtk.BUTTONS_YES_NO) != gtk.RESPONSE_YES:                    return melddoc.RESULT_ERROR        if self._save_text_to_filename(bufdata.filename, text):            self.emit("file-changed", bufdata.filename)            self.undosequence.clear()            self.set_buffer_modified(buf, 0)            return melddoc.RESULT_OK        else:            return melddoc.RESULT_ERROR    def make_patch(self, pane):        fontdesc = pango.FontDescription(self.prefs.get_current_font())        dialog = gnomeglade.Component( paths.share_dir("glade2/filediff.glade"), "patchdialog")        dialog.widget.set_transient_for( self.widget.get_toplevel() )        bufs = [t.get_buffer() for t in self.textview]        texts = [b.get_text(*b.get_bounds()).split("\n") for b in bufs]        texts[0] = [l+"\n" for l in texts[0]]        texts[1] = [l+"\n" for l in texts[1]]        names = [self._get_filename(i) for i in range(2)]        dialog.textview.modify_font(fontdesc)        buf = dialog.textview.get_buffer()        lines = []        for line in difflib.unified_diff(texts[0], texts[1], names[0], names[1]):            buf.insert( buf.get_end_iter(), line )            lines.append(line)        result = dialog.widget.run()        dialog.widget.destroy()        if result >= 0:            txt = "".join(lines)            if result == 1: # copy                clip = gtk.clipboard_get()                clip.set_text(txt)                clip.store()            else:# save as                filename = self._get_filename_for_saving( _("Save patch as...") )                if filename:                    self._save_text_to_filename(filename, txt)    def set_buffer_writable(self, buf, yesno):        pane = self.textview.index(buf.textview)        self.bufferdata[pane].writable = yesno        self.recompute_label()    def set_buffer_modified(self, buf, yesno):        pane = self.textview.index(buf.textview)        self.bufferdata[pane].modified = yesno        self.recompute_label()    def save(self):        pane = self._get_focused_pane()        if pane >= 0:            self.save_file(pane)    def save_all(self):        for i in range(self.num_panes):            if self.bufferdata[i].modified:                self.save_file(i)    def on_fileentry_activate(self, entry):        if self.on_delete_event() == gtk.RESPONSE_OK:            files = [ e.get_full_path(0) for e in self.fileentry[:self.num_panes] ]            self.set_files(files)        return 1    def _get_focused_pane(self):        for i in range(self.num_panes):            if self.textview[i].is_focus():                return i        return -1    def copy_selected(self, direction):        assert direction in (-1,1)        src_pane = self._get_focused_pane()        dst_pane = src_pane + direction        assert dst_pane in range(self.num_panes)        buffers = [t.get_buffer() for t in self.textview]        text = buffers[src_pane].get_text( buffers[src_pane].get_start_iter(), buffers[src_pane].get_end_iter() )        self.on_text_begin_user_action()        buffers[dst_pane].set_text( text )        self.on_text_end_user_action()        self.scheduler.add_task( lambda : self._sync_vscroll( self.scrolledwindow[src_pane].get_vadjustment() ) and None )        #        # refresh and reload        #    def on_reload_activate(self, *extra):        modified = [b.filename for b in self.bufferdata if b.modified]        if len(modified):            message = _("Reloading will discard changes in:\n%s\n\nYou cannot undo this operation.") % "\n".join(modified)            response = misc.run_dialog( message, parent=self, messagetype=gtk.MESSAGE_WARNING, buttonstype=gtk.BUTTONS_OK_CANCEL)            if response != gtk.RESPONSE_OK:                return        files = [b.filename for b in self.bufferdata[:self.num_panes] ]        self.set_files(files)    def on_refresh_activate(self, *extra):        files = [None for b in self.bufferdata[:self.num_panes] ]        self.set_files(files)    def queue_draw(self, junk=None):        for i in range(self.num_panes-1):            self.linkmap[i].queue_draw()        self.diffmap0.queue_draw()        self.diffmap1.queue_draw()        #        # scrollbars        #    def _sync_hscroll(self, adjustment):        if not hasattr(self,"_sync_hscroll_lock"):            self._sync_hscroll_lock = 0        if not self._sync_hscroll_lock:            self._sync_hscroll_lock = 1            adjs = map( lambda x: x.get_hadjustment(), self.scrolledwindow)            adjs.remove(adjustment)            val = adjustment.get_value()            for a in adjs:                a.set_value(val)            self._sync_hscroll_lock = 0    def _sync_vscroll(self, adjustment):        # only allow one scrollbar to be here at a time        if not hasattr(self,"_sync_vscroll_lock"):            self._sync_vscroll_lock = 0        if not self._sync_vscroll_lock:            self._sync_vscroll_lock = 1            syncpoint = 0.5            adjustments = map( lambda x: x.get_vadjustment(), self.scrolledwindow)            adjustments = adjustments[:self.num_panes]            master = adjustments.index(adjustment)            # scrollbar influence 0->1->2 or 0<-1<-2 or 0<-1->2            others = zip( range(self.num_panes), adjustments)            del others[master]            if master == 2:                others.reverse()            # the line to search for in the 'master' text            master_y = adjustment.value + adjustment.page_size * syncpoint            it = self.textview[master].get_line_at_y(master_y)[0]            line_y, height = self.textview[master].get_line_yrange(it)            line = it.get_line() + ((master_y-line_y)/height)            for (i,adj) in others:                mbegin,mend, obegin,oend = 0, self._get_line_count(master), 0, self._get_line_count(i)                # look for the chunk containing 'line'                for c in self.linediffer.pair_changes(master, i, self._get_texts()):                    c = c[1:]                    if c[0] >= line:                        mend = c[0]                        oend = c[2]                        break                    elif c[1] >= line:                        mbegin,mend = c[0],c[1]                        obegin,oend = c[2],c[3]                        break                    else:                        mbegin = c[1]                        obegin = c[3]                fraction = (line - mbegin) / ((mend - mbegin) or 1)                other_line = (obegin + fraction * (oend - obegin))                it = self.textview[i].get_buffer().get_iter_at_line(other_line)                val, height = self.textview[i].get_line_yrange(it)                val -= (adj.page_size) * syncpoint                val += (other_line-int(other_line)) * height                val = misc.clamp(val, 0, adj.upper - adj.page_size)                adj.set_value( val )                # scrollbar influence 0->1->2 or 0<-1<-2 or 0<-1->2                if master != 1:                    line = other_line                    master = 1            self.on_linkmap_expose_event(self.linkmap0, None)            self.on_linkmap_expose_event(self.linkmap1, None)            self._sync_vscroll_lock = 0        #        # diffmap drawing        #    def on_diffmap_expose_event(self, area, event):        diffmapindex = self.diffmap.index(area)        textindex = (0, self.num_panes-1)[diffmapindex]        #TODO need height of arrow button on scrollbar - how do we get that?        size_of_arrow = 14        hperline = float( self.scrolledwindow[textindex].get_allocation().height - 4*size_of_arrow) / self._get_line_count(textindex)        if hperline > self.pixels_per_line:            hperline = self.pixels_per_line        scaleit = lambda x,s=hperline,o=size_of_arrow: x*s+o        x0 = 4        x1 = area.get_allocation().width - 2*x0        window = area.window        window.clear()        gctext = area.get_style().text_gc[0]        if not hasattr(area, "meldgc"):            self._setup_gcs(area)        gc = area.meldgc.get_gc        for c in self.linediffer.single_changes(textindex, self._get_texts()):            assert c[0] != "equal"            s,e = [int(x) for x in ( math.floor(scaleit(c[1])), math.ceil(scaleit(c[2]+(c[1]==c[2]))) ) ]            window.draw_rectangle( gc(c[0]), 1, x0, s, x1, e-s)            window.draw_rectangle( gctext, 0, x0, s, x1, e-s)    def on_diffmap_button_press_event(self, area, event):        #TODO need gutter of scrollbar - how do we get that?        if event.button == 1:            size_of_arrow = 14            diffmapindex = self.diffmap.index(area)            index = (0, self.num_panes-1)[diffmapindex]            height = area.get_allocation().height            fraction = (event.y - size_of_arrow) / (height - 3.75*size_of_arrow)            adj = self.scrolledwindow[index].get_vadjustment()            val = fraction * adj.upper - adj.page_size/2            upper = adj.upper - adj.page_size            adj.set_value( max( min(upper, val), 0) )            return 1        return 0    def _get_line_count(self, index):        """Return the number of lines in the buffer of textview 'text'"""        return self.textview[index].get_buffer().get_line_count()    def set_num_panes(self, n):        if n != self.num_panes and n in (1,2,3):            self.num_panes = n            toshow =  self.scrolledwindow[:n] + self.fileentry[:n]            toshow += self.linkmap[:n-1] + self.diffmap[:n]            map( lambda x: x.show(), toshow )            tohide =  self.statusimage + self.scrolledwindow[n:] + self.fileentry[n:]

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -