I'm making an HTML editor application with Python tkinter. This application uses autocomplete so users can write HTML code more easily. Example: if a user types <h1>
, the script will add </h1>
right after it. The issue is when I click "enter" and then "backspace". The scripts adds another end tag after the previous one. How can I fix this? My code:
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
from tkinter import messagebox
import webbrowser
import os
window = tk.Tk()
window.title("HTML Editor")
window.configure(bg="grey")
window.state("zoomed")
title = tk.Label(window, text="HTML Editor", font=("Arial Rounded MT Bold", 40, "underline"), bg="grey")
title.place(x=400, y=20)
copy_path = 0
count2 = 0
def open_file():
file_path = askopenfilename(filetypes=[("HTML Files", "*.html"), ("All Files", "*.*")])
if not file_path:
return
text_box.delete("1.0", tk.END)
file_func()
with open(file_path, "r") as file_read:
text = file_read.read()
text_box.insert(tk.END, text)
window.title(f"HTML Editor - {file_path}")
def save_file():
file_path = asksaveasfilename(defaultextension="txt", filetypes=[("HTML Files", "*.html"), ("All Files", "*.*")])
if not file_path:
return
with open(file_path, "w") as file_write:
text = text_box.get(1.0, tk.END)
file_write.write(text)
window.title(f"HTML Editor - {file_path}")
file_func()
def run_code():
window_title = window.title()
index = window_title.index("-") + 2
window_title = window_title[index::]
with open(window_title, "w") as path:
content = text_box.get("1.0", tk.END)
path.write(content)
basename = os.path.basename(window_title)
new_file = open(basename, "w")
new_file.write(content)
new_file.close()
webbrowser.open_new_tab("file:///" + os.getcwd() + "/" + basename)
def get_stringvar(event):
global count2
sv.set(text_box.get("1.0", tk.END))
content = sv.get()
keys = ["Return", "Up", "Down", "Left", "Right"]
count2 = len(content.splitlines())
if event.keysym in keys:
return
for line in content.splitlines():
if "/" not in line and line != "<!DOCTYPE html>":
if ("<" and ">" in line) and line.index(">") + 1 == len(line):
index = line.index("<")
index2 = line.index(">") + 1
new_line = "<" + "/" + line[index + 1:index2 - 1] + ">"
text_box.insert(tk.END, new_line)
line2 = content.splitlines().index(line) + 1
text_box.mark_set("insert", "%d.%d" % (line2, index2))
def on_closing():
if window.title() != "HTML Editor":
window_title = window.title()
index = window_title.index("-") + 2
window_title = window_title[index::]
file = open(window_title, "w")
file.write(text_box.get("1.0", tk.END))
quit()
def file_func():
frame.pack(side="left", fill="y")
text_box.pack(side="left", fill="both", expand=True)
scroll_bar.pack(side="left", fill="y")
run_b.pack(padx=50, pady=(100, 5), anchor="n")
sv = tk.StringVar()
create = tk.Button(window, text="Create a new file", width=17, height=3, font=("Arial Rounded MT Bold", 20),
command=save_file)
create.place(x=420, y=200)
open_e = tk.Button(window, text="Open an existing file", width=17, height=3, font=("Arial Rounded MT Bold", 20),
command=open_file)
open_e.place(x=420, y=350)
window.protocol("WM_DELETE_WINDOW", on_closing)
frame = tk.Frame(window, bd=2, relief="raised")
text_box = tk.Text(window, font=("Courier New", 10), fg="black")
text_box.bind("<KeyRelease>", get_stringvar)
scroll_bar = tk.Scrollbar(window, command=text_box.yview)
run_b = tk.Button(frame, text="Run", width=6, height=2, bg="white", command=run_code)
text_box.configure(yscrollcommand=scroll_bar.set)
window.mainloop()
Updated code (Thanks, @Matiiss!):
import tkinter as tk
from tkinter.filedialog import askopenfilename, asksaveasfilename
from tkinter import messagebox
import webbrowser
import os
window = tk.Tk()
window.title("HTML Editor")
window.configure(bg="grey")
window.state("zoomed")
title = tk.Label(window, text="HTML Editor", font=("Arial Rounded MT Bold", 40, "underline"), bg="grey")
title.place(x=400, y=20)
copy_path = 0
def open_file():
file_path = askopenfilename(filetypes=[("HTML Files", "*.html"), ("All Files", "*.*")])
if not file_path:
return
text_box.delete("1.0", tk.END)
file_func()
with open(file_path, "r") as file_read:
text = file_read.read()
text_box.insert(tk.END, text)
window.title(f"HTML Editor - {file_path}")
def save_file():
file_path = asksaveasfilename(defaultextension="txt", filetypes=[("HTML Files", "*.html"), ("All Files", "*.*")])
if not file_path:
return
with open(file_path, "w") as file_write:
text = text_box.get(1.0, tk.END)
file_write.write(text)
window.title(f"HTML Editor - {file_path}")
file_func()
def run_code():
window_title = window.title()
index = window_title.index("-") + 2
window_title = window_title[index::]
with open(window_title, "w") as path:
content = text_box.get("1.0", tk.END)
path.write(content)
basename = os.path.basename(window_title)
new_file = open(basename, "w")
new_file.write(content)
new_file.close()
webbrowser.open_new_tab("file:///" + os.getcwd() + "/" + basename)
def get_stringvar(event):
sv.set(text_box.get("1.0", tk.END))
content = sv.get()
keys = ["Return", "Up", "Down", "Left", "Right"]
if event.keysym in keys:
return
line = content.splitlines()[-1]
if "/" not in line and line != "<!DOCTYPE html>":
if ("<" in line and ">" in line) and line.index(">") + 1 == len(line):
index = line.index("<")
index2 = line.index(">") + 1
new_line = "<" + "/" + line[index + 1:index2 - 1] + ">"
text_box.insert(tk.END, new_line)
line2 = content.splitlines().index(line) + 1
text_box.mark_set("insert", "%d.%d" % (line2, index2))
def on_closing():
if window.title() != "HTML Editor":
window_title = window.title()
index = window_title.index("-") + 2
window_title = window_title[index::]
file = open(window_title, "w")
file.write(text_box.get("1.0", tk.END))
quit()
def file_func():
frame.pack(side="left", fill="y")
text_box.pack(side="left", fill="both", expand=True)
scroll_bar.pack(side="left", fill="y")
run_b.pack(padx=50, pady=(100, 5), anchor="n")
sv = tk.StringVar()
create = tk.Button(window, text="Create a new file", width=17, height=3, font=("Arial Rounded MT Bold", 20),
command=save_file)
create.place(x=420, y=200)
open_e = tk.Button(window, text="Open an existing file", width=17, height=3, font=("Arial Rounded MT Bold", 20),
command=open_file)
open_e.place(x=420, y=350)
window.protocol("WM_DELETE_WINDOW", on_closing)
frame = tk.Frame(window, bd=2, relief="raised")
text_box = tk.Text(window, font=("Courier New", 10), fg="black")
text_box.bind("<KeyRelease>", get_stringvar)
scroll_bar = tk.Scrollbar(window, command=text_box.yview)
run_b = tk.Button(frame, text="Run", width=6, height=2, bg="white", command=run_code)
text_box.configure(yscrollcommand=scroll_bar.set)
window.mainloop()
The changes I've made:
I replaced for line in content.splitlines()
with line = content.splitlines()[-1]
and changed if ("<" in line and ">" in line)
to if ("<" in line and ">" in line)
. Both of these changes were made in the get_stringvar
function.