我正在尝试为我的文本编辑器开发Find and Replace
。不幸的是regex
似乎不起作用。这很奇怪,因为我在Python中使用Text
搜索搜索regex
窗口小部件。我怀疑问题在于正则表达式的错误长度。
我收到以下错误:
_tkinter.TclError: bad text index ""
以下是我的Python
代码:
import tkinter as tk
import tkinter.filedialog
import traceback
import tkinter.ttk as ttk
from pygments import lex
from pygments.lexers import PythonLexer
import sys
import os
import re
import time
class CustomText(tk.Text):
def __init__(self, *args, **kwargs):
tk.Text.__init__(self, *args, **kwargs)
self.tk.eval('''
proc widget_proxy {widget widget_command args} {
# call the real tk widget command with the real args
set result [uplevel [linsert $args 0 $widget_command]]
# generate the event for certain types of commands
if {([lindex $args 0] in {insert replace delete}) ||
([lrange $args 0 2] == {mark set insert}) ||
([lrange $args 0 1] == {xview moveto}) ||
([lrange $args 0 1] == {xview scroll}) ||
([lrange $args 0 1] == {yview moveto}) ||
([lrange $args 0 1] == {yview scroll})} {
event generate $widget <<Change>> -when tail
}
# return the result from the real widget command
return $result
}
''')
self.tk.eval('''
rename {widget} _{widget}
interp alias {{}} ::{widget} {{}} widget_proxy {widget} _{widget}
'''.format(widget=str(self)))
self.comment = False
def highlight_pattern(self, pattern, tag, regex, start="1.0", end="end"):
'''Apply the given tag to all text that matches the given pattern
If 'regexp' is set to True, pattern will be treated as a regular
expression.
'''
print(regex)
start = self.index(start)
end = self.index(end)
self.mark_set("matchStart", start)
self.mark_set("matchEnd", start)
self.mark_set("searchLimit", end)
count = tk.IntVar()
while True:
index = self.search(pattern, "matchEnd","searchLimit",
count=count, regexp=regex)
if index == "": break
self.mark_set("matchStart", index)
self.mark_set("matchEnd", "%s+%sc" % (index, count.get()))
self.tag_add(tag, "matchStart", "matchEnd")
class Tab:
def __init__(self, parent, filename, parentwindow):
self.fileName = "Untitled Document"
self.content = ""
self.previousContent = ""
self.parentwindow = parentwindow
self.language = "Python"
self.row = "0"
self.column = "0"
self.startCol = 0
self.parent = parent
self.filename = filename
self.tab1 = ttk.Frame(parent)
self.text = CustomText(self.tab1, bd=0, font=("Tahoma", 9))
self.vsb = tk.Scrollbar(self.tab1, orient=tk.VERTICAL)
self.text.configure(yscrollcommand=self.vsb.set)
self.vsb.configure(command=self.text.yview)
self.vsb.pack(side=tk.RIGHT, fill=tk.Y)
self.text.pack(side="right", fill="both", expand=True)
parent.add(self.tab1, text=filename)
self.text.bind("<KeyRelease>", self.keypress)
self.text.bind("<Button-1>", self.keypress)
self.parent = parent
self.configureTags()
def configureTags(self):
self.text.tag_configure("Token.Keyword", foreground="#CC7A00")
self.text.tag_configure("Token.Keyword.Constant", foreground="#CC7A00")
self.text.tag_configure("Token.Keyword.Declaration", foreground="#CC7A00")
self.text.tag_configure("Token.Keyword.Namespace", foreground="#CC7A00")
self.text.tag_configure("Token.Keyword.Pseudo", foreground="#CC7A00")
self.text.tag_configure("Token.Keyword.Reserved", foreground="#CC7A00")
self.text.tag_configure("Token.Keyword.Type", foreground="#CC7A00")
self.text.tag_configure("Token.Name.Class", foreground="#003D99")
self.text.tag_configure("Token.Name.Exception", foreground="#003D99")
self.text.tag_configure("Token.Name.Function", foreground="#003D99")
self.text.tag_configure("Token.Operator.Word", foreground="#CC7A00")
self.text.tag_configure("Token.Comment", foreground="#B80000")
self.text.tag_configure("Token.Literal.String", foreground="#248F24")
def deafultHighlight(self, argument):
self.content = self.text.get("1.0", tk.END)
self.lines = self.content.split("\n")
if (self.previousContent != self.content):
self.row = self.text.index(tk.INSERT).split(".")[0]
self.column = self.text.index(tk.INSERT).split(".")[1]
self.text.mark_set("range_start", self.row + ".0")
data = self.text.get(self.row + ".0", self.row + "." + str(len(self.lines[int(self.row) - 1])))
for token, content in lex(data, PythonLexer()):
self.text.mark_set("range_end", "range_start + %dc" % len(content))
self.text.tag_add(str(token), "range_start", "range_end")
self.text.mark_set("range_start", "range_end")
self.previousContent = self.text.get("1.0", tk.END)
def highlight(self, argument):
self.content = self.text.get("1.0", tk.END)
if (self.previousContent != self.content):
self.text.mark_set("range_start", "1.0")
data = self.text.get("1.0", self.text.index(tk.INSERT))
for token, content in lex(data, PythonLexer()):
self.text.mark_set("range_end", "range_start + %dc" % len(content))
self.text.tag_add(str(token), "range_start", "range_end")
self.text.mark_set("range_start", "range_end")
self.previousContent = self.text.get("1.0", tk.END)
def searchHighlight(self, term, color, regexOrNot):
self.text.tag_configure("highlight", background=color)
self.text.highlight_pattern(term, "highlight", regexOrNot)
def individualHighlight(self, startPos, endPos, color):
self.text.tag_configure("highlightedWord", background=color)
self.text.tag_add("highlightedWord", startPos, endPos)
def clearPreviousHighlight(self, startPos, endPos, color):
self.text.tag_configure("clearHighlight", background=color)
self.text.tag_add("clearHighlight", startPos, endPos)
def clearAll(self, color):
self.text.tag_delete("highlight")
self.text.tag_delete("clearHighlight")
self.text.tag_delete("highlightedWord")
def getContent(self):
return self.text.get(0.0, tk.END)
def keypress(self, argument):
self.deafultHighlight("argument")
def replace(self, content):
self.text.delete(1.0, tk.END)
self.text.insert(1.0, content)
class Arshi(tk.Frame):
def __init__(self, *args, **kwargs):
tk.Frame.__init__(self, *args, **kwargs)
self.tabs = []
self.notebook = ttk.Notebook(self)
self.fileName = ""
self.content = ""
self.highlightColor = "#D2D2D2"
self.standardSearchColor = "#ADDEAD"
self.createtext()
self.menubar()
self.instance = 0
self.bind_all("<Control-f>", self.search)
def createtext(self):
self.notebook.pack(fill=tk.BOTH, expand=True)
t = Tab(self.notebook, "Untitled Document", self)
self.tabs.append(t)
def menubar(self):
self.menu = tk.Menu(self)
self.master.config(menu=self.menu)
self.editMenu = tk.Menu(self.menu, font=("Tahoma", 9))
self.editMenu.add_command(label="Find and Replace Ctrl+F", command=lambda: self.search("arg"))
self.menu.add_cascade(label="Edit", menu=self.editMenu)
def getColor(self):
self.color = tkinter.colorchooser.askcolor(parent=self.searchMenu)[1]
self.highlightLineEntry.insert(0, self.color)
self.highlightColor = self.color
def searchProtocol(self):
self.instance = 0
tabIndex = self.notebook.index(self.notebook.select())
self.pos = '1.0'
self.finalPos = '1.0'
self.previousPos = self.pos
self.previousFinalPos = self.finalPos
self.tabs[tabIndex].clearAll("#FFFFFF")
self.searchMenu.destroy()
def search(self, arg):
self.searchMenu = tk.Toplevel()
self.searchMenu.title("Search and Replace")
self.searchMenu.geometry("545x240")
self.searchMenu.resizable(0, 0)
self.searchDirection = tk.Label(self.searchMenu, text=" String to search:", anchor=tk.W, font=("Tahoma", 9))
self.entry = tk.Entry(self.searchMenu, width=30, font=("Tahoma", 9))
self.replaceDirection = tk.Label(self.searchMenu, text=" String to replace:", anchor=tk.W, font=("Tahoma", 9))
self.replace = tk.Entry(self.searchMenu, width=30, font=("Tahoma", 9))
self.searchOptions = tk.Label(self.searchMenu, text=" Search options:", anchor=tk.W, font=("Tahoma", 9))
self.regex = tk.IntVar()
self.regularExpression = tk.Checkbutton(self.searchMenu, text="Regex", variable=self.regex, anchor=tk.W, font=("Tahoma", 9))
self.matchcase = tk.IntVar()
self.matchCase = tk.Checkbutton(self.searchMenu, text="Match Case", variable=self.matchcase, anchor=tk.W, font=("Tahoma", 9))
self.searchWay = tk.Label(self.searchMenu, text=" Search direction:", anchor = tk.W, font=("Tahoma", 9))
self.direction = tk.IntVar()
self.up = tk.Radiobutton(self.searchMenu, text="Up", variable=self.direction, value=1).place(x=175, y=75, width=140)
self.down = tk.Radiobutton(self.searchMenu, text="Down", variable=self.direction, value=2).place(x=340, y=75, width=140)
self.searchButton = tk.Button(self.searchMenu, text="Search", font=("Tahoma", 9), command=lambda: self.continueSearch(self.entry.get()))
self.searchClose = tk.Button(self.searchMenu, text="Replace", font=("Tahoma", 9), command=lambda: self.replaceAll(self.entry.get(), self.replace.get()))
self.searchRange = tk.Label(self.searchMenu, text=" Search range (line):", anchor = tk.W, font=("Tahoma", 9))
self.rangeEntry = tk.Entry(self.searchMenu, width=30, font=("Tahoma", 9))
self.highlightLine = tk.Label(self.searchMenu, text=" Search color (hex):", anchor=tk.W, font=("Tahoma", 9))
self.highlightLineButton = tk.Button(self.searchMenu, text="Select", anchor=tk.W, font=("Tahoma", 9), command=self.getColor)
self.highlightLineEntry = tk.Entry(self.searchMenu, width=30, font=("Tahoma", 9))
self.occurenceLabel = tk.Label(self.searchMenu, text=" Search: {0} occurences, at occurence {1}".format("0", "0"), anchor=tk.CENTER, font=("Tahoma", 9))
self.searchMenu.protocol("WM_DELETE_WINDOW", self.searchProtocol)
self.searchDirection.place(x=0, y=0, width=200)
self.replaceDirection.place(x=0, y=25, width=200)
self.searchOptions.place(x=0, y=50, width=200)
self.searchWay.place(x=0, y=75, width=200)
self.searchRange.place(x=0, y=100, width=140)
self.rangeEntry.place(x=220, y=100, width=325)
self.highlightLine.place(x=0, y=125, width=145)
self.highlightLineButton.place(x=145, y=125)
self.highlightLineEntry.place(x=220, y=125, width=325)
self.occurenceLabel.place(x =0, y=160)
self.searchButton.place(x=20, y=195, width=200)
self.searchClose.place(x=325, y=195, width=200)
self.entry.place(x=220, y=0, width=325)
self.replace.place(x=220, y=25, width=325)
self.matchCase.place(x=220, y=50, width=140)
self.regularExpression.place(x=375, y=50, width=140)
def replaceAll(self, replaceTerm, newTerm):
if len(replaceTerm) > 0:
tabIndex = self.notebook.index(self.notebook.select())
self.content = self.tabs[tabIndex].getContent().replace(replaceTerm, newTerm)
self.tabs[tabIndex].replace(self.content)
self.tabs[tabIndex].highlight("argument")
def continueSearch(self, term):
self.regexIndex = self.regex.get()
self.regexOrNot = False
if self.regexIndex == 1:
self.regexOrNot = True
self.hex = self.highlightLineEntry.get()
self.validHex = re.search(r'^#(?:[0-9a-fA-F]{3}){1,2}$', self.highlightColor)
if len(self.hex) == 0:
self.validHex = False
if len(term) > 0:
tabIndex = self.notebook.index(self.notebook.select())
if self.validHex:
self.tabs[tabIndex].searchHighlight(term, self.hex, self.regexOrNot)
else:
self.tabs[tabIndex].searchHighlight(term, self.highlightColor, self.regexOrNot)
numberOfInstances = self.tabs[tabIndex].text.get(0.0, tk.END).count(term)
self.instance += 1
if self.instance == 1:
if self.regexOrNot == False:
self.pos = self.tabs[tabIndex].text.search(term, '1.0')
self.finalPos = '{}+{}c'.format(self.pos, len(term))
else:
self.pos = self.tabs[tabIndex].text.search(term, '1.0', regexp=True)
self.finalPos = '{}+{}c'.format(self.pos, len(term))
self.tabs[tabIndex].individualHighlight(self.pos, self.finalPos, "#ADDEAD")
elif self.instance <= numberOfInstances:
self.previousPos = self.pos
self.previousFinalPos = self.finalPos
self.pos = self.finalPos
if self.regexOrNot == False:
self.pos = self.tabs[tabIndex].text.search(term, self.pos)
self.finalPos = '{}+{}c'.format(self.pos, len(term))
else:
self.pos = self.tabs[tabIndex].text.search(term, '1.0', regexp=True)
self.finalPos = '{}+{}c'.format(self.pos, len(term))
self.tabs[tabIndex].clearPreviousHighlight(self.previousPos, self.previousFinalPos, self.highlightColor)
self.tabs[tabIndex].individualHighlight(self.pos, self.finalPos, "#ADDEAD")
self.occurenceLabel["text"] = " Search: {0} occurences, selecting occurence {1}".format(self.tabs[tabIndex].getContent().count(term), str(min(self.tabs[tabIndex].getContent().count(term), self.instance)))
if __name__ == "__main__":
root = tk.Tk()
root.title("Arshi")
root.geometry("1024x600")
window = Arshi(root).pack(side="top", fill="both", expand=True)
root.mainloop()
答案 0 :(得分:0)
尝试查看How to use a regular expression in Tkinter text search method?。问题可能在于您使用Text小部件的text.search功能
的方式