PageRenderTime 62ms CodeModel.GetById 45ms app.highlight 13ms RepoModel.GetById 1ms app.codeStats 0ms

/Lib/idlelib/ReplaceDialog.py

http://unladen-swallow.googlecode.com/
Python | 167 lines | 151 code | 15 blank | 1 comment | 32 complexity | 07aa7c62e7f62454dd7df82857851a00 MD5 | raw file
  1from Tkinter import *
  2import SearchEngine
  3from SearchDialogBase import SearchDialogBase
  4
  5def replace(text):
  6    root = text._root()
  7    engine = SearchEngine.get(root)
  8    if not hasattr(engine, "_replacedialog"):
  9        engine._replacedialog = ReplaceDialog(root, engine)
 10    dialog = engine._replacedialog
 11    dialog.open(text)
 12
 13class ReplaceDialog(SearchDialogBase):
 14
 15    title = "Replace Dialog"
 16    icon = "Replace"
 17
 18    def __init__(self, root, engine):
 19        SearchDialogBase.__init__(self, root, engine)
 20        self.replvar = StringVar(root)
 21
 22    def open(self, text):
 23        SearchDialogBase.open(self, text)
 24        try:
 25            first = text.index("sel.first")
 26        except TclError:
 27            first = None
 28        try:
 29            last = text.index("sel.last")
 30        except TclError:
 31            last = None
 32        first = first or text.index("insert")
 33        last = last or first
 34        self.show_hit(first, last)
 35        self.ok = 1
 36
 37    def create_entries(self):
 38        SearchDialogBase.create_entries(self)
 39        self.replent = self.make_entry("Replace with:", self.replvar)
 40
 41    def create_command_buttons(self):
 42        SearchDialogBase.create_command_buttons(self)
 43        self.make_button("Find", self.find_it)
 44        self.make_button("Replace", self.replace_it)
 45        self.make_button("Replace+Find", self.default_command, 1)
 46        self.make_button("Replace All", self.replace_all)
 47
 48    def find_it(self, event=None):
 49        self.do_find(0)
 50
 51    def replace_it(self, event=None):
 52        if self.do_find(self.ok):
 53            self.do_replace()
 54
 55    def default_command(self, event=None):
 56        if self.do_find(self.ok):
 57            self.do_replace()
 58            self.do_find(0)
 59
 60    def replace_all(self, event=None):
 61        prog = self.engine.getprog()
 62        if not prog:
 63            return
 64        repl = self.replvar.get()
 65        text = self.text
 66        res = self.engine.search_text(text, prog)
 67        if not res:
 68            text.bell()
 69            return
 70        text.tag_remove("sel", "1.0", "end")
 71        text.tag_remove("hit", "1.0", "end")
 72        line = res[0]
 73        col = res[1].start()
 74        if self.engine.iswrap():
 75            line = 1
 76            col = 0
 77        ok = 1
 78        first = last = None
 79        # XXX ought to replace circular instead of top-to-bottom when wrapping
 80        text.undo_block_start()
 81        while 1:
 82            res = self.engine.search_forward(text, prog, line, col, 0, ok)
 83            if not res:
 84                break
 85            line, m = res
 86            chars = text.get("%d.0" % line, "%d.0" % (line+1))
 87            orig = m.group()
 88            new = m.expand(repl)
 89            i, j = m.span()
 90            first = "%d.%d" % (line, i)
 91            last = "%d.%d" % (line, j)
 92            if new == orig:
 93                text.mark_set("insert", last)
 94            else:
 95                text.mark_set("insert", first)
 96                if first != last:
 97                    text.delete(first, last)
 98                if new:
 99                    text.insert(first, new)
100            col = i + len(new)
101            ok = 0
102        text.undo_block_stop()
103        if first and last:
104            self.show_hit(first, last)
105        self.close()
106
107    def do_find(self, ok=0):
108        if not self.engine.getprog():
109            return False
110        text = self.text
111        res = self.engine.search_text(text, None, ok)
112        if not res:
113            text.bell()
114            return False
115        line, m = res
116        i, j = m.span()
117        first = "%d.%d" % (line, i)
118        last = "%d.%d" % (line, j)
119        self.show_hit(first, last)
120        self.ok = 1
121        return True
122
123    def do_replace(self):
124        prog = self.engine.getprog()
125        if not prog:
126            return False
127        text = self.text
128        try:
129            first = pos = text.index("sel.first")
130            last = text.index("sel.last")
131        except TclError:
132            pos = None
133        if not pos:
134            first = last = pos = text.index("insert")
135        line, col = SearchEngine.get_line_col(pos)
136        chars = text.get("%d.0" % line, "%d.0" % (line+1))
137        m = prog.match(chars, col)
138        if not prog:
139            return False
140        new = m.expand(self.replvar.get())
141        text.mark_set("insert", first)
142        text.undo_block_start()
143        if m.group():
144            text.delete(first, last)
145        if new:
146            text.insert(first, new)
147        text.undo_block_stop()
148        self.show_hit(first, text.index("insert"))
149        self.ok = 0
150        return True
151
152    def show_hit(self, first, last):
153        text = self.text
154        text.mark_set("insert", first)
155        text.tag_remove("sel", "1.0", "end")
156        text.tag_add("sel", first, last)
157        text.tag_remove("hit", "1.0", "end")
158        if first == last:
159            text.tag_add("hit", first)
160        else:
161            text.tag_add("hit", first, last)
162        text.see("insert")
163        text.update_idletasks()
164
165    def close(self, event=None):
166        SearchDialogBase.close(self, event)
167        self.text.tag_remove("hit", "1.0", "end")