183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom Tkinter import * 283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib import SearchEngine 483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehfrom idlelib.SearchDialogBase import SearchDialogBase 583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehimport re 683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehdef replace(text): 983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh root = text._root() 1083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh engine = SearchEngine.get(root) 1183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not hasattr(engine, "_replacedialog"): 1283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh engine._replacedialog = ReplaceDialog(root, engine) 1383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dialog = engine._replacedialog 1483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh dialog.open(text) 1583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 1683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 1783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsiehclass ReplaceDialog(SearchDialogBase): 1883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 1983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh title = "Replace Dialog" 2083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh icon = "Replace" 2183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def __init__(self, root, engine): 2383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh SearchDialogBase.__init__(self, root, engine) 2483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.replvar = StringVar(root) 2583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 2683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def open(self, text): 2783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh SearchDialogBase.open(self, text) 2883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 2983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh first = text.index("sel.first") 3083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except TclError: 3183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh first = None 3283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 3383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh last = text.index("sel.last") 3483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except TclError: 3583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh last = None 3683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh first = first or text.index("insert") 3783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh last = last or first 3883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.show_hit(first, last) 3983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.ok = 1 4083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 4183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def create_entries(self): 4283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh SearchDialogBase.create_entries(self) 4383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.replent = self.make_entry("Replace with:", self.replvar) 4483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 4583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def create_command_buttons(self): 4683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh SearchDialogBase.create_command_buttons(self) 4783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.make_button("Find", self.find_it) 4883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.make_button("Replace", self.replace_it) 4983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.make_button("Replace+Find", self.default_command, 1) 5083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.make_button("Replace All", self.replace_all) 5183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def find_it(self, event=None): 5383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.do_find(0) 5483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def replace_it(self, event=None): 5683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self.do_find(self.ok): 5783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.do_replace() 5883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 5983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def default_command(self, event=None): 6083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self.do_find(self.ok): 6183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self.do_replace(): # Only find next match if replace succeeded. 6283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # A bad re can cause a it to fail. 6383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.do_find(0) 6483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 6583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def _replace_expand(self, m, repl): 6683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh """ Helper function for expanding a regular expression 6783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh in the replace field, if needed. """ 6883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self.engine.isre(): 6983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 7083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh new = m.expand(repl) 7183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except re.error: 7283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.engine.report_error(repl, 'Invalid Replace Expression') 7383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh new = None 7483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 7583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh new = repl 7683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return new 7783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 7883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def replace_all(self, event=None): 7983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh prog = self.engine.getprog() 8083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not prog: 8183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 8283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh repl = self.replvar.get() 8383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text = self.text 8483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh res = self.engine.search_text(text, prog) 8583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not res: 8683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.bell() 8783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return 8883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.tag_remove("sel", "1.0", "end") 8983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.tag_remove("hit", "1.0", "end") 9083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh line = res[0] 9183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh col = res[1].start() 9283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if self.engine.iswrap(): 9383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh line = 1 9483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh col = 0 9583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ok = 1 9683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh first = last = None 9783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh # XXX ought to replace circular instead of top-to-bottom when wrapping 9883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.undo_block_start() 9983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh while 1: 10083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh res = self.engine.search_forward(text, prog, line, col, 0, ok) 10183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not res: 10283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh break 10383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh line, m = res 10483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh chars = text.get("%d.0" % line, "%d.0" % (line+1)) 10583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh orig = m.group() 10683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh new = self._replace_expand(m, repl) 10783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if new is None: 10883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh break 10983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh i, j = m.span() 11083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh first = "%d.%d" % (line, i) 11183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh last = "%d.%d" % (line, j) 11283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if new == orig: 11383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.mark_set("insert", last) 11483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 11583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.mark_set("insert", first) 11683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if first != last: 11783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.delete(first, last) 11883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if new: 11983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.insert(first, new) 12083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh col = i + len(new) 12183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh ok = 0 12283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.undo_block_stop() 12383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if first and last: 12483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.show_hit(first, last) 12583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.close() 12683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 12783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def do_find(self, ok=0): 12883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not self.engine.getprog(): 12983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return False 13083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text = self.text 13183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh res = self.engine.search_text(text, None, ok) 13283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not res: 13383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.bell() 13483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return False 13583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh line, m = res 13683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh i, j = m.span() 13783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh first = "%d.%d" % (line, i) 13883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh last = "%d.%d" % (line, j) 13983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.show_hit(first, last) 14083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.ok = 1 14183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return True 14283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 14383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def do_replace(self): 14483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh prog = self.engine.getprog() 14583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not prog: 14683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return False 14783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text = self.text 14883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh try: 14983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh first = pos = text.index("sel.first") 15083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh last = text.index("sel.last") 15183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh except TclError: 15283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh pos = None 15383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not pos: 15483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh first = last = pos = text.index("insert") 15583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh line, col = SearchEngine.get_line_col(pos) 15683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh chars = text.get("%d.0" % line, "%d.0" % (line+1)) 15783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh m = prog.match(chars, col) 15883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if not prog: 15983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return False 16083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh new = self._replace_expand(m, self.replvar.get()) 16183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if new is None: 16283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return False 16383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.mark_set("insert", first) 16483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.undo_block_start() 16583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if m.group(): 16683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.delete(first, last) 16783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if new: 16883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.insert(first, new) 16983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.undo_block_stop() 17083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.show_hit(first, text.index("insert")) 17183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.ok = 0 17283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh return True 17383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 17483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def show_hit(self, first, last): 17583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text = self.text 17683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.mark_set("insert", first) 17783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.tag_remove("sel", "1.0", "end") 17883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.tag_add("sel", first, last) 17983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.tag_remove("hit", "1.0", "end") 18083760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh if first == last: 18183760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.tag_add("hit", first) 18283760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh else: 18383760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.tag_add("hit", first, last) 18483760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.see("insert") 18583760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh text.update_idletasks() 18683760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh 18783760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh def close(self, event=None): 18883760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh SearchDialogBase.close(self, event) 18983760d213fb3bec7b4117d266fcfbf6fe2ba14abAndrew Hsieh self.text.tag_remove("hit", "1.0", "end") 190