Commit | Line | Data |
---|---|---|
920dae64 AT |
1 | from Tkinter import * |
2 | import SearchEngine | |
3 | from SearchDialogBase import SearchDialogBase | |
4 | ||
5 | def 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 | ||
13 | class 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") |