/Lib/idlelib/ReplaceDialog.py
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")