7 if not hasattr(root
, "_searchengine"):
8 root
._searchengine
= SearchEngine(root
)
9 # XXX This will never garbage-collect -- who cares
10 return root
._searchengine
14 def __init__(self
, root
):
16 # State shared by search, replace, and grep;
17 # the search dialogs bind these to UI elements.
18 self
.patvar
= StringVar(root
) # search pattern
19 self
.revar
= BooleanVar(root
) # regular expression?
20 self
.casevar
= BooleanVar(root
) # match case?
21 self
.wordvar
= BooleanVar(root
) # match whole word?
22 self
.wrapvar
= BooleanVar(root
) # wrap around buffer?
23 self
.wrapvar
.set(1) # (on by default)
24 self
.backvar
= BooleanVar(root
) # search backwards?
29 return self
.patvar
.get()
31 def setpat(self
, pat
):
35 return self
.revar
.get()
38 return self
.casevar
.get()
41 return self
.wordvar
.get()
44 return self
.wrapvar
.get()
47 return self
.backvar
.get()
49 # Higher level access methods
51 def getcookedpat(self
):
62 self
.report_error(pat
, "Empty regular expression")
64 pat
= self
.getcookedpat()
67 flags
= flags | re
.IGNORECASE
69 prog
= re
.compile(pat
, flags
)
70 except re
.error
, what
:
76 self
.report_error(pat
, msg
, col
)
80 def report_error(self
, pat
, msg
, col
=-1):
81 # Derived class could overrid this with something fancier
82 msg
= "Error: " + str(msg
)
84 msg
= msg
+ "\np\Pattern: " + str(pat
)
86 msg
= msg
+ "\nOffset: " + str(col
)
87 tkMessageBox
.showerror("Regular expression error",
88 msg
, master
=self
.root
)
90 def setcookedpat(self
, pat
):
95 def search_text(self
, text
, prog
=None, ok
=0):
96 """Search a text widget for the pattern.
98 If prog is given, it should be the precompiled pattern.
99 Return a tuple (lineno, matchobj); None if not found.
101 This obeys the wrap and direction (back) settings.
103 The search starts at the selection (if there is one) or
104 at the insert mark (otherwise). If the search is forward,
105 it starts at the right of the selection; for a backward
106 search, it starts at the left end. An empty match exactly
107 at either end of the selection (or at the insert mark if
108 there is no selection) is ignored unless the ok flag is true
109 -- this is done to guarantee progress.
111 If the search is allowed to wrap around, it will return the
112 original selection if (and only if) it is the only match.
116 prog
= self
.getprog()
118 return None # Compilation failed -- stop
119 wrap
= self
.wrapvar
.get()
120 first
, last
= get_selection(text
)
126 line
, col
= get_line_col(start
)
127 res
= self
.search_backward(text
, prog
, line
, col
, wrap
, ok
)
133 line
, col
= get_line_col(start
)
134 res
= self
.search_forward(text
, prog
, line
, col
, wrap
, ok
)
137 def search_forward(self
, text
, prog
, line
, col
, wrap
, ok
=0):
140 chars
= text
.get("%d.0" % line
, "%d.0" % (line
+1))
142 m
= prog
.search(chars
[:-1], col
)
144 if ok
or m
.end() > col
:
147 if wrapped
and line
> startline
:
151 chars
= text
.get("%d.0" % line
, "%d.0" % (line
+1))
152 if not chars
and wrap
:
156 chars
= text
.get("1.0", "2.0")
159 def search_backward(self
, text
, prog
, line
, col
, wrap
, ok
=0):
162 chars
= text
.get("%d.0" % line
, "%d.0" % (line
+1))
164 m
= search_reverse(prog
, chars
[:-1], col
)
166 if ok
or m
.start() < col
:
169 if wrapped
and line
< startline
:
177 pos
= text
.index("end-1c")
178 line
, col
= map(int, string
.split(pos
, "."))
179 chars
= text
.get("%d.0" % line
, "%d.0" % (line
+1))
183 # Helper to search backwards in a string.
184 # (Optimized for the case where the pattern isn't found.)
186 def search_reverse(prog
, chars
, col
):
187 m
= prog
.search(chars
)
192 while i
< col
and j
<= col
:
196 m
= prog
.search(chars
, j
)
202 # Helper to get selection end points, defaulting to insert mark.
203 # Return a tuple of indices ("line.col" strings).
205 def get_selection(text
):
207 first
= text
.index("sel.first")
208 last
= text
.index("sel.last")
212 first
= text
.index("insert")
217 # Helper to parse a text index into a (line, col) tuple.
219 def get_line_col(index
):
220 line
, col
= map(int, string
.split(index
, ".")) # Fails on invalid index