how to create find, find_all, replace and replace_all features in tkinter text widget - Python MagicStick Text Editor - Part 10

Namaste Friends,



                        As i described in my previous tutorial, In text Editors, find, find_all, replace and replace_all functions provides us special facilities to handle big text data easily and with this functions, we can save our time from typing repeated things and also, with these features, we can find and replace any words or line between the paragraph in text editor directly. So, This features really help User to do work in easy way. As In my Previous Tutorial, I demonstrate how to binding keyboard shortcut keys with any function and how to create find and find_all functions. Now, In this Post, I will show you how to completely setup find, find_all, replace, replace_all function and their shortcut key in Tkinter Text Widget.


Friends, This Is our 10th Tutorial Of Python MagicStick Project But,  if you are a new visitor, Then I will suggest you to read our tutorials number wise. because in these tutorial series i am showing how to use python tkinter module to create a real life application.

Links For Tutorials

MagicStick Text Editor Part 3
MagicStick Text Editor Part 4
MagicStick Text Editor Part 5
MagicStick Text Editor Part 6
MagicStick Text Editor Part 7
MagicStick Text Editor Part 8
MagicStick Text Editor Part 9
Or You Can Also Download Our Updated Example Codes Of Python MagicStick Text Editor Project For Understanding This Project More Clearly.

Check Here Our Github Repo




Now, let's focus to our main topic.

For These Types of function, First we will take tkinter text widget object as class argument input. After Taking Tkinter Text Object as an argument, we will create new find, find_all, replace and replace_all functions in that class to perform our operation with Text Object. And In the End, Bind all Functions with there shortcut keys.


To make this script easy to understand we will create a separate empty script "FindAndReplace.py" in "magicsticklibs/" folder and write our codes  in it.

So, let's do some practical coding's.

1. FindAndReplace.py



  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
##
##
## ################################################
## ###### Please Don't Remove Author Name #########
## ############# Thanks ###########################
## ################################################
##
##
__author__='''

######################################################
                By S.S.B Group                          
######################################################

    Suraj Singh
    Admin
    S.S.B Group
    surajsinghbisht054@gmail.com
    http://bitforestinfo.blogspot.com/

    Note: We Feel Proud To Be Indian
######################################################
'''


from Graphics import Tkinter

def FindAsk(parent,*args):
 root = Tkinter.Toplevel(parent)
 root.title("Find And Replace")
 root.transient(parent)
 root.focus_force()
 root.resizable(width=0, height=0)
 root['padx']=20
 fields = {}
 field={}
 for r, label in enumerate(args):
  store_label = Tkinter.Label(root, text=label)
  store_label.grid(row=r, column = 0, ipady=5, ipadx=20)
  store_entry = Tkinter.Entry(root)
  store_entry.grid(row=r, column=1)
  field[label]=store_entry
 fields['submit']=False
 def sub():
  for l,t in field.iteritems():
   fields[l]=t.get()
  fields['submit']=True
  root.destroy()
  return
 submit=Tkinter.Button(root,text="Ok", command=sub)
 submit.grid(row=r+1, column=2)
 root.wait_window()
 return fields


class FindReplaceFunctions:
 def __init__(self,text):
  self.text = text
  self.key_binding_functions()
  self.binding_functions_configuration()

 def binding_functions_configuration(self):
  self.text.storeobj['Find'] = self.find_
  self.text.storeobj['FindAll'] = self.find_all
  self.text.storeobj['Replace'] = self.replace
  self.text.storeobj['ReplaceAll'] = self.replace_all
  self.text.storeobj['ResetTags']=self.reset_tags
  return


 def key_binding_functions(self):
  for key in ['<Control-F>',"<Control-f>"]:
   self.text.bind(key, self.find_)
  for key in ['<Control-Shift-F>',"<Control-Shift-f>"]:
   self.text.bind(key, self.find_all)
  for key in ['<Control-Shift-H>',"<Control-Shift-h>"]:
   self.text.bind(key, self.replace_all)
  for key in ['<Control-H>',"<Control-h>"]:
   self.text.bind(key, self.replace)
  for key in ['<Any-Button>']:
   self.text.bind(key, self.reset_tags)
  return

 def _search_(self, word):
  if word:
   countvar = Tkinter.StringVar()
   f = self.text.search(word, "1.0", count=countvar)
   starting_index = f
   ending_index = "{}+{}c".format(starting_index, countvar.get())
   self.text.tag_add("search", starting_index, ending_index)
   self.text.tag_configure("search", background="skyblue", foreground="red")
   return True
  else:
   return None

 def reset_tags(self, event=None):
  self.text.tag_delete("search")
  return

 def _search_all_(self, word):
  index="1.0"
  if word:
   while True:
    f = self.text.search(word, index, stopindex=Tkinter.END)
    if not f:
     break
    starting_index =int(f.split(".")[0])
    ending_index  = len(word)+int(f.split(".")[1])
    coordinates = "{}.{}".format(starting_index, ending_index)
    self.text.tag_add("search", f, coordinates)
    self.text.tag_configure("search", background="skyblue", foreground="red")
    index = coordinates
   return True
  else:
   return None

 def _replace_(self, word):
  if word:
   coordinates=[]
   l=list(self.text.tag_ranges("search"))
   l.reverse()
   while l:
    coordinates.append([l.pop(),l.pop()])
   for start, end in coordinates:
    self.text.delete(start, end)
    self.text.insert(start, word)
  return

 def _replace_all_(self, word):
  if word:
   coordinates=[]
   l=list(self.text.tag_ranges("search"))
   l.reverse()
   while l:
    coordinates.append([l.pop(),l.pop()])
   for start, end in coordinates:
    self.text.delete(start, end)
    self.text.insert(start, word)
   
  return


 def find_(self, event=None):
  t = FindAsk(self.text.master, "Find")
  if t['submit']:
   self._search_(t['Find'])
  return

 def find_all(self, event=None):
  t = FindAsk(self.text.master, "FindAll")
  if t['submit']:
   self._search_all_(t['FindAll'])
  return

 def replace(self, event=None):
  t = FindAsk(self.text.master, "Find", "Replace")
  if t['submit']:
   self._search_(t['Find'])
   self._replace_all_(t['Replace'])
  return

 def replace_all(self, event=None):
  t = FindAsk(self.text.master, "FindAll", "ReplaceAll")
  if t['submit']:
   self._search_all_(t['FindAll'])
   self._replace_all_(t['ReplaceAll'])
  return


if __name__ == '__main__':
 root = Tkinter.Tk()
 pad = Tkinter.Text(root)
 pad.pack()
 pad.storeobj={}
 FindReplaceFunctions(pad)
 #print FindAsk(root,"a","b",1)
 root.mainloop()



To Run These Script Codes alone, Just Change line 26 from

"from Graphics import Tkinter"

To  "import Tkinter"

Or

To Run This Codes as MagicStick Script. Don't Do Any Changes in this codes.


 Now, let's join this script in MagicStick Text Editor Project ( Follow Below Steps only, when you have not Connected this script with MagicScript Main Stream).

To Connect This Script With MagicStick project, we need to do only two steps.


1. first, Place This Script In Our "MagicStick/magicsticklibs" Project Directory.


2. Add Function Of This Script in Our "ConfigSettings.py".



Let me explain you these steps in more details.


Step 1.
 Place "FindAndReplace.py" In Our "MagicStick/magicsticklibs" Project Directory.



Then Our MagicStick Project Directory Structure will look like this.



MagicStick_Editor_Part_9
 |
 |---> About.txt  
 |
 |---> magicsticklibs
 |  |
 |  |---> __init__.py
 |  |     
 |  |---> Main.py
 |  |            
 |  |---> TextPad.py
 |  |
 |  |---> Graphics.py
 |  |
 |  |---> ConfigSettings.py 
 |  |
 |  |---> ScrollBar.py
 |  |
 |  |---> LineNumber.py
 |  |
 |  |---> StationeryFunctions.py
 |  |
 |  |---> PopupMenu.py
 |  |
 |  |---> FindAndReplace.py
 |
 |---> main.py


Step 2.
          Add "FindAndReplace.py" Function in Our "ConfigSettings.py" because in this project, "ConfigSettings.py" is responsible for joining libs in main stream.

ConfigSettings.py Modified Codes




 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
##
##
## ################################################
## ###### Please Don't Remove Author Name #########
## ############# Thanks ###########################
## ################################################
##
##
__author__='''

######################################################
                By S.S.B Group                          
######################################################

    Suraj Singh
    Admin
    S.S.B Group
    surajsinghbisht054@gmail.com
    http://bitforestinfo.blogspot.com/

    Note: We Feel Proud To Be Indian
######################################################
'''

from LineNumber import LineMain
from ScrollBar import Scrollbar
from StationeryFunctions import StationeryFunctions
from PopupMenu import Popup
from FIndAndReplace import FindReplaceFunctions

class Connect:
 def __init__(self, pad):
  self.pad = pad
  self.modules_connections()


 def modules_connections(self):
  LineMain(self.pad)
  Scrollbar(self.pad)
  StationeryFunctions(self.pad)
  Popup(self.pad)
  FindReplaceFunctions(self.pad)
  return


Boom! Our FindAndReplace.py script is now ready to use and also, this script is now connected with MagicStick Project Main stream. To run this script in main stream of project. just run "main.py" script or you can also run this script alone and parallel without touching project main stream just run "FindAndReplace.py".



This Tutorial Ends Here,


In My Next Tutorial, We will Continue This project.


Written By
        SSB



Share this

Related Posts

Previous
Next Post »