Skip to content

Commit 94ee964

Browse files
committed
add python code editor tutorial
1 parent 54888a1 commit 94ee964

File tree

3 files changed

+124
-0
lines changed

3 files changed

+124
-0
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -236,5 +236,6 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
236236
- [How to Detect Gender by Name using Python](https://www.thepythoncode.com/article/gender-predictor-gui-app-tkinter-genderize-api-python). ([code](gui-programming/genderize-app))
237237
- [How to Build a Spreadsheet App with Tkinter in Python](https://www.thepythoncode.com/article/spreadsheet-app-using-tkinter-in-python). ([code](gui-programming/spreadsheet-app))
238238
- [How to Make a Rich Text Editor with Tkinter in Python](https://www.thepythoncode.com/article/create-rich-text-editor-with-tkinter-python). ([code](gui-programming/rich-text-editor))
239+
- [How to Make a Python Code Editor using Tkinter in Python](https://www.thepythoncode.com/article/python-code-editor-using-tkinter-python). ([code](gui-programming/python-code-editor/))
239240

240241
For any feedback, please consider pulling requests.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# [How to Make a Python Code Editor using Tkinter in Python](https://www.thepythoncode.com/article/python-code-editor-using-tkinter-python)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
from tkinter import *
2+
import ctypes
3+
import re
4+
import os
5+
6+
# Increas Dots Per inch so it looks sharper
7+
ctypes.windll.shcore.SetProcessDpiAwareness(True)
8+
9+
# Setup Tkinter
10+
root = Tk()
11+
root.geometry('500x500')
12+
13+
14+
# Execute the Programm
15+
def execute(event=None):
16+
17+
# Write the Content to the Temporary File
18+
with open('run.py', 'w', encoding='utf-8') as f:
19+
f.write(editArea.get('1.0', END))
20+
21+
# Start the File in a new CMD Window
22+
os.system('start cmd /K "python run.py"')
23+
24+
# Register Changes made to the Editor Content
25+
def changes(event=None):
26+
global previousText
27+
28+
# If actually no changes have been made stop / return the function
29+
if editArea.get('1.0', END) == previousText:
30+
return
31+
32+
# Remove all tags so they can be redrawn
33+
for tag in editArea.tag_names():
34+
editArea.tag_remove(tag, "1.0", "end")
35+
36+
# Add tags where the search_re function found the pattern
37+
i = 0
38+
for pattern, color in repl:
39+
for start, end in search_re(pattern, editArea.get('1.0', END)):
40+
editArea.tag_add(f'{i}', start, end)
41+
editArea.tag_config(f'{i}', foreground=color)
42+
43+
i+=1
44+
45+
previousText = editArea.get('1.0', END)
46+
47+
def search_re(pattern, text, groupid=0):
48+
matches = []
49+
50+
text = text.splitlines()
51+
for i, line in enumerate(text):
52+
for match in re.finditer(pattern, line):
53+
54+
matches.append(
55+
(f"{i + 1}.{match.start()}", f"{i + 1}.{match.end()}")
56+
)
57+
58+
return matches
59+
60+
61+
def rgb(rgb):
62+
return "#%02x%02x%02x" % rgb
63+
64+
65+
previousText = ''
66+
67+
# Define colors for the variouse types of tokens
68+
normal = rgb((234, 234, 234))
69+
keywords = rgb((234, 95, 95))
70+
comments = rgb((95, 234, 165))
71+
string = rgb((234, 162, 95))
72+
function = rgb((95, 211, 234))
73+
background = rgb((42, 42, 42))
74+
font = 'Consolas 15'
75+
76+
77+
# Define a list of Regex Pattern that should be colored in a certain way
78+
repl = [
79+
['(^| )(False|None|True|and|as|assert|async|await|break|class|continue|def|del|elif|else|except|finally|for|from|global|if|import|in|is|lambda|nonlocal|not|or|pass|raise|return|try|while|with|yield)($| )', keywords],
80+
['".*?"', string],
81+
['\'.*?\'', string],
82+
['#.*?$', comments],
83+
]
84+
85+
# Make the Text Widget
86+
# Add a hefty border width so we can achieve a little bit of padding
87+
editArea = Text(
88+
root,
89+
background=background,
90+
foreground=normal,
91+
insertbackground=normal,
92+
relief=FLAT,
93+
borderwidth=30,
94+
font=font
95+
)
96+
97+
# Place the Edit Area with the pack method
98+
editArea.pack(
99+
fill=BOTH,
100+
expand=1
101+
)
102+
103+
# Insert some Standard Text into the Edit Area
104+
editArea.insert('1.0', """from argparse import ArgumentParser
105+
from random import shuffle, choice
106+
import string
107+
108+
# Setting up the Argument Parser
109+
parser = ArgumentParser(
110+
prog='Password Generator.',
111+
description='Generate any number of passwords with this tool.'
112+
)
113+
""")
114+
115+
# Bind the KeyRelase to the Changes Function
116+
editArea.bind('<KeyRelease>', changes)
117+
118+
# Bind Control + R to the exec function
119+
root.bind('<Control-r>', execute)
120+
121+
changes()
122+
root.mainloop()

0 commit comments

Comments
 (0)