blob: d713e61db09889c669c8026ff9c84a60889cf410 [file] [log] [blame]
Georg Brandl14fc4272008-05-17 18:39:55 +00001from tkinter import *
Guido van Rossum36e0a922007-07-20 04:05:57 +00002
Kurt B. Kaiser2d7f6a02007-08-22 23:01:33 +00003from idlelib import SearchEngine
4from idlelib.SearchDialogBase import SearchDialogBase
David Scherer7aced172000-08-15 01:13:23 +00005
6def replace(text):
7 root = text._root()
8 engine = SearchEngine.get(root)
9 if not hasattr(engine, "_replacedialog"):
10 engine._replacedialog = ReplaceDialog(root, engine)
11 dialog = engine._replacedialog
12 dialog.open(text)
13
14class ReplaceDialog(SearchDialogBase):
15
16 title = "Replace Dialog"
17 icon = "Replace"
18
19 def __init__(self, root, engine):
20 SearchDialogBase.__init__(self, root, engine)
21 self.replvar = StringVar(root)
22
23 def open(self, text):
24 SearchDialogBase.open(self, text)
25 try:
26 first = text.index("sel.first")
27 except TclError:
28 first = None
29 try:
30 last = text.index("sel.last")
31 except TclError:
32 last = None
33 first = first or text.index("insert")
34 last = last or first
35 self.show_hit(first, last)
36 self.ok = 1
37
38 def create_entries(self):
39 SearchDialogBase.create_entries(self)
40 self.replent = self.make_entry("Replace with:", self.replvar)
41
42 def create_command_buttons(self):
43 SearchDialogBase.create_command_buttons(self)
44 self.make_button("Find", self.find_it)
45 self.make_button("Replace", self.replace_it)
46 self.make_button("Replace+Find", self.default_command, 1)
47 self.make_button("Replace All", self.replace_all)
48
49 def find_it(self, event=None):
50 self.do_find(0)
51
52 def replace_it(self, event=None):
53 if self.do_find(self.ok):
54 self.do_replace()
55
56 def default_command(self, event=None):
57 if self.do_find(self.ok):
58 self.do_replace()
59 self.do_find(0)
60
61 def replace_all(self, event=None):
62 prog = self.engine.getprog()
63 if not prog:
64 return
65 repl = self.replvar.get()
66 text = self.text
67 res = self.engine.search_text(text, prog)
68 if not res:
69 text.bell()
70 return
71 text.tag_remove("sel", "1.0", "end")
72 text.tag_remove("hit", "1.0", "end")
73 line = res[0]
74 col = res[1].start()
75 if self.engine.iswrap():
76 line = 1
77 col = 0
78 ok = 1
79 first = last = None
80 # XXX ought to replace circular instead of top-to-bottom when wrapping
81 text.undo_block_start()
82 while 1:
83 res = self.engine.search_forward(text, prog, line, col, 0, ok)
84 if not res:
85 break
86 line, m = res
87 chars = text.get("%d.0" % line, "%d.0" % (line+1))
88 orig = m.group()
Kurt B. Kaiser2def78b2002-09-14 02:53:05 +000089 new = m.expand(repl)
David Scherer7aced172000-08-15 01:13:23 +000090 i, j = m.span()
91 first = "%d.%d" % (line, i)
92 last = "%d.%d" % (line, j)
93 if new == orig:
94 text.mark_set("insert", last)
95 else:
96 text.mark_set("insert", first)
97 if first != last:
98 text.delete(first, last)
99 if new:
100 text.insert(first, new)
101 col = i + len(new)
102 ok = 0
103 text.undo_block_stop()
104 if first and last:
105 self.show_hit(first, last)
106 self.close()
107
108 def do_find(self, ok=0):
109 if not self.engine.getprog():
Kurt B. Kaiserce86b102002-09-18 02:56:10 +0000110 return False
David Scherer7aced172000-08-15 01:13:23 +0000111 text = self.text
112 res = self.engine.search_text(text, None, ok)
113 if not res:
114 text.bell()
Kurt B. Kaiserce86b102002-09-18 02:56:10 +0000115 return False
David Scherer7aced172000-08-15 01:13:23 +0000116 line, m = res
117 i, j = m.span()
118 first = "%d.%d" % (line, i)
119 last = "%d.%d" % (line, j)
120 self.show_hit(first, last)
121 self.ok = 1
Kurt B. Kaiserce86b102002-09-18 02:56:10 +0000122 return True
David Scherer7aced172000-08-15 01:13:23 +0000123
124 def do_replace(self):
125 prog = self.engine.getprog()
126 if not prog:
Kurt B. Kaiserce86b102002-09-18 02:56:10 +0000127 return False
David Scherer7aced172000-08-15 01:13:23 +0000128 text = self.text
129 try:
130 first = pos = text.index("sel.first")
131 last = text.index("sel.last")
132 except TclError:
133 pos = None
134 if not pos:
135 first = last = pos = text.index("insert")
136 line, col = SearchEngine.get_line_col(pos)
137 chars = text.get("%d.0" % line, "%d.0" % (line+1))
138 m = prog.match(chars, col)
139 if not prog:
Kurt B. Kaiserce86b102002-09-18 02:56:10 +0000140 return False
Kurt B. Kaiser2def78b2002-09-14 02:53:05 +0000141 new = m.expand(self.replvar.get())
David Scherer7aced172000-08-15 01:13:23 +0000142 text.mark_set("insert", first)
143 text.undo_block_start()
144 if m.group():
145 text.delete(first, last)
146 if new:
147 text.insert(first, new)
148 text.undo_block_stop()
149 self.show_hit(first, text.index("insert"))
150 self.ok = 0
Kurt B. Kaiserce86b102002-09-18 02:56:10 +0000151 return True
David Scherer7aced172000-08-15 01:13:23 +0000152
David Scherer7aced172000-08-15 01:13:23 +0000153 def show_hit(self, first, last):
154 text = self.text
155 text.mark_set("insert", first)
156 text.tag_remove("sel", "1.0", "end")
157 text.tag_add("sel", first, last)
158 text.tag_remove("hit", "1.0", "end")
159 if first == last:
160 text.tag_add("hit", first)
161 else:
162 text.tag_add("hit", first, last)
163 text.see("insert")
164 text.update_idletasks()
165
166 def close(self, event=None):
167 SearchDialogBase.close(self, event)
168 self.text.tag_remove("hit", "1.0", "end")