Line numbers and Syntax Highlighting don't work on different tabs
Question: I am trying to resolve the issue in which `line numbers` don't work properly
in `multiple tabs`. The issue is that when I create a new tab, the `line
numbers` for the other tabs don't work, but the `line numbers for the current
tab` does. Same goes for `syntax highlighting`.

I think the issue is in using the same variables when creating a new tab, but
I have no idea how to resolve this issue and I am not sure if this is truly
the problem. I was also thinking about redefining the text box, and the
bindings associated with it everytime a tab is clicked.

Below is my code:

    
    
    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
    
    class TextLineNumbers(tk.Canvas):
        def __init__(self, *args, **kwargs):
            tk.Canvas.__init__(self, *args, **kwargs)
            self.textwidget = None
    
        def attach(self, text_widget):
            self.textwidget = text_widget
    
        def redraw(self, *args):
            '''redraw line numbers'''
            self.delete("all")
    
            i = self.textwidget.index("@0,0")
            while True:
                dline= self.textwidget.dlineinfo(i)
                if dline is None: break
                y = dline[1]
                linenum = str(i).split(".")[0]
                self.create_text(5,y,anchor="nw", text=linenum, font=("Courier", 9))
                i = self.textwidget.index("%s+1line" % i)
    
    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
    
    class Arshi(tk.Frame):
        def __init__(self, *args, **kwargs):
            tk.Frame.__init__(self, *args, **kwargs)
            self.fileName = "Untitled Document"
            self.content = ""
            self.previousContent = ""
            self.language = "Python"
            self.row = "0"
            self.column = "0"
            self.startCol = 0
    
            self.notebook = ttk.Notebook(self)
    
            self.menubar()
            self.bottomLabel()
            self.createtext()
    
        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.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 keypress(self, argument):
            self.updateBottomLabel()
            self.deafultHighlight("argument")
    
        def configureTags(self, text):
            text.tag_configure("Token.Keyword", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Constant", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Declaration", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Namespace", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Pseudo", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Reserved", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Type", foreground="#CC7A00")
    
            text.tag_configure("Token.Name.Class", foreground="#003D99")
            text.tag_configure("Token.Name.Exception", foreground="#003D99")
            text.tag_configure("Token.Name.Function", foreground="#003D99")
    
            text.tag_configure("Token.Operator.Word", foreground="#CC7A00")
    
            text.tag_configure("Token.Comment", foreground="#B80000")
    
            text.tag_configure("Token.Literal.String", foreground="#248F24")
    
        def createtext(self):
            self.notebook.pack(fill=tk.BOTH, expand=True)
    
            self.tab1 = ttk.Frame(self.notebook)
            self.text = CustomText(self.tab1, bd=0, font=("Courier", 9))  
    
            self.configureTags(self.text)
    
            self.vsb = tk.Scrollbar(self.tab1, orient=tk.VERTICAL)
            self.text.configure(yscrollcommand=self.vsb.set)
            self.vsb.configure(command=self.text.yview)
    
            self.linenumbers = TextLineNumbers(self.tab1, width=55)
            self.linenumbers.attach(self.text)
    
            self.vsb.pack(side=tk.RIGHT, fill=tk.Y)
            self.linenumbers.pack(side="left", fill="y")
            self.text.pack(side="right", fill="both", expand=True)
    
            self.notebook.add(self.tab1, text=self.fileName)
    
            self.text.bind("<<Change>>", self._on_change)
            self.text.bind("<Configure>", self._on_change)
            self.text.bind("<KeyRelease>", self.keypress)
            self.text.bind("<Button-1>", self.keypress)
    
        def addtab(self):
            self.newTab = ttk.Frame(self.notebook)
            self.text = CustomText(self.newTab, bd=0, font=("Courier", 9))
    
            self.configureTags(self.text)
    
            self.vsb = tk.Scrollbar(self.newTab, orient=tk.VERTICAL)
            self.text.configure(yscrollcommand=self.vsb.set)
            self.vsb.configure(command=self.text.yview)
    
            self.linenumbers = TextLineNumbers(self.newTab, width=55)
            self.linenumbers.attach(self.text)
    
            self.vsb.pack(side=tk.RIGHT, fill=tk.Y)
            self.linenumbers.pack(side="left", fill="y")
            self.text.pack(side="right", fill="both", expand=True)
    
            self.notebook.add(self.newTab, text="Untitled Document")
    
            self.text.bind("<<Change>>", self._on_change)
            self.text.bind("<Configure>", self._on_change)
            self.text.bind("<KeyRelease>", self.keypress)
            self.text.bind("<Button-1>", self.keypress)
    
        def removetab(self):
            numberOfTabs = self.notebook.index("end")
    
            if numberOfTabs > 1:
                tabIndex = self.notebook.index(self.notebook.select())
                self.notebook.forget(tabIndex)
    
        def run(self):
            pass
    
        def menubar(self):
            self.menu = tk.Menu(self)
            self.master.config(menu=self.menu)
    
            self.fileMenu = tk.Menu(self.menu, font=("Courier", 9))
            self.fileMenu.add_command(label="New             Ctrl+N", command=self.newFile)
            self.fileMenu.add_command(label="Open            Ctrl+O", command=self.openFile)
            self.fileMenu.add_command(label="Save            Ctrl+S", command=self.saveFile)
            self.fileMenu.add_command(label="Save As         Ctrl+Shift+S", command=self.saveAsFile)
            self.fileMenu.add_separator()
            self.fileMenu.add_command(label="New Window", command=self.addtab)
            self.fileMenu.add_command(label="Close Window", command=self.removetab)
            self.fileMenu.add_separator()
            self.fileMenu.add_command(label="Exit            Alt+F4", command=self.close)
            self.menu.add_cascade(label="File", menu=self.fileMenu)
    
            self.runMenu = tk.Menu(self.menu, font=("Courier", 9))
            self.runMenu.add_command(label="Run", command=self.run)
            self.menu.add_cascade(label="Run", menu=self.runMenu)
    
        def bottomLabel(self):
            self.positionAndLanguage = tk.Label(self, text=" Ln: 1, Col: 0, Lang: Plain", anchor=tk.W, bg="#E7E7E7", font=("Courier New", 8))
            self.positionAndLanguage.pack(fill=tk.X, side=tk.BOTTOM)
    
        def updateBottomLabel(self):
            self.row = self.text.index(tk.INSERT).split(".")[0]
            self.column = self.text.index(tk.INSERT).split(".")[1]
            self.positionAndLanguage["text"] = " Ln: {0}, Col: {1}, Lang: {2}".format(self.row, self.column, self.language)
    
        def newFile(self):
            self.fileName = "Untitled"
            self.previousContent = ""
            self.text.delete(0.0, tk.END)
    
        def openFile(self):
            try:
                self.fileName = tk.filedialog.askopenfilename() #Asks user to open file
                with open(self.fileName, 'r') as file:
                    self.content = file.read() #Reads content typed
                self.text.delete(0.0, tk.END) 
                self.text.insert(0.0, self.content)
                self.highlight(self)
            except IOError as e:
                print("Error reading file.")
            except:
                print("Unexpected error occured.")
    
        def deleteContent(self, file):
            file.seek(0)
            file.truncate()
    
        def saveFile(self):
            self.content = self.text.get(0.0, tk.END)
    
            try:
                with open(self.fileName, 'w') as file:
                    self.deleteContent(file)
                    file.write(self.content)
            except IOError as e:
                print("Error reading file.")
            except:
                print("Unexpected error occured.")
    
        def saveAsFile(self):
            self.content = self.text.get(0.0, tk.END)
    
            try:
                self.fileName = tk.filedialog.asksaveasfilename()
                if self.fileName != None:
                    with open(self.fileName, 'w') as file:
                        file.write(self.content)
            except IOError as e:
                print("Error reading file.")
            except:
                print("Unexcepted error occured.")
    
        def close(self):
            try:
                os._exit(0)
            except:
                print(sys.exc_info()[0])
    
        def _on_change(self, event):
            self.linenumbers.redraw()
    
    if __name__ == "__main__":
        root = tk.Tk()
        root.title("Arshi")
        root.geometry("1024x600")
        window = Arshi(root).pack(side="top", fill="both", expand=True)
        root.mainloop()
    


Answer: Yes, as you observed, the issue is because you are always changing the
`linenumbers` to the linenumber of the latest tab, so for old tabs , even if
the `_on_change()` is called, it would call redraw only on the new line
number, not on the old ones.

I believe the correct way to go forward for your application would be to have
another level of abstraction, where `Tab` is a complete object by itself, and
each tab should be a different object and should keep store the
linenumber/text in itself.

Example -

    
    
    import tkinter as tk
    import tkinter.ttk as ttk
    
    class TextLineNumbers(tk.Canvas):
        def __init__(self, *args, **kwargs):
            tk.Canvas.__init__(self, *args, **kwargs)
            self.textwidget = None
    
        def attach(self, text_widget):
            self.textwidget = text_widget
    
        def redraw(self, *args):
            '''redraw line numbers'''
            self.delete("all")
    
            i = self.textwidget.index("@0,0")
            while True:
                dline= self.textwidget.dlineinfo(i)
                if dline is None: break
                y = dline[1]
                linenum = str(i).split(".")[0]
                self.create_text(5,y,anchor="nw", text=linenum, font=("Courier", 9))
                i = self.textwidget.index("%s+1line" % i)
    
    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
    
    class Tab:
        def __init__(self, parent, filename):
            self.parent = parent
            self.filename = filename
            self.tab1 = ttk.Frame(parent)
            self.text = CustomText(self.tab1, bd=0, font=("Courier", 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.linenumbers = TextLineNumbers(self.tab1, width=55)
            self.linenumbers.attach(self.text)
    
            self.vsb.pack(side=tk.RIGHT, fill=tk.Y)
            self.linenumbers.pack(side="left", fill="y")
            self.text.pack(side="right", fill="both", expand=True)
    
            parent.add(self.tab1, text=filename)
    
            self.text.bind("<<Change>>", self._on_change)
            self.text.bind("<Configure>", self._on_change)
    
        def _on_change(self, event):
            self.linenumbers.redraw()
    
    
    class Window(tk.Frame):
        def __init__(self, *args, **kwargs):
            tk.Frame.__init__(self, *args, **kwargs)
            self.fileName = "Untitled Document"
            self.content = ""
            self.previousContent = ""
            self.language = "Python"
            self.row = "0"
            self.column = "0"
            self.startCol = 0
    
            self.notebook = ttk.Notebook(self)
            self.tabs = []
            self.menubar()
            self.createtext()
    
        def createtext(self):
            self.notebook.pack(fill=tk.BOTH, expand=True)
            t = Tab(self.notebook, self.fileName)
            self.tabs.append(t)
    
        def addtab(self):
            t = Tab(self.notebook, self.fileName)
            self.tabs.append(t)
    
        def removetab(self):
            numberOfTabs = self.notebook.index("end")
    
            if numberOfTabs > 1:
                tabIndex = self.notebook.index(self.notebook.select())
                self.notebook.forget(tabIndex)
                del self.tabs[tabIndex]
    
        def menubar(self):
            self.menu = tk.Menu(self)
            self.master.config(menu=self.menu)
    
            self.fileMenu = tk.Menu(self.menu, font=("Courier", 9))
            self.fileMenu.add_command(label="New Window", command=self.addtab)
            self.fileMenu.add_command(label="Close Window", command=self.removetab)
            self.menu.add_cascade(label="File", menu=self.fileMenu)
    
    if __name__ == "__main__":
        root = tk.Tk()
        root.title("Window")
        root.geometry("1024x600")
        window = Window(root).pack(side="top", fill="both", expand=True)
        root.mainloop()
    

I created a new class `Tab` and copied code from previous methods like
`createtext` into it, and now when creating a new tab, we just need to
instantiate object of `Tab` class.

* * *

Partially working code , for your case -

    
    
    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
    
    class TextLineNumbers(tk.Canvas):
        def __init__(self, *args, **kwargs):
            tk.Canvas.__init__(self, *args, **kwargs)
            self.textwidget = None
    
        def attach(self, text_widget):
            self.textwidget = text_widget
    
        def redraw(self, *args):
            '''redraw line numbers'''
            self.delete("all")
    
            i = self.textwidget.index("@0,0")
            while True:
                dline= self.textwidget.dlineinfo(i)
                if dline is None: break
                y = dline[1]
                linenum = str(i).split(".")[0]
                self.create_text(5,y,anchor="nw", text=linenum, font=("Courier", 9))
                i = self.textwidget.index("%s+1line" % i)
    
    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
    
    class Tab:
        def __init__(self, parent, filename, parentwindow):
            self.fileName = "Untitled Document"
            self.content = ""
            self.previousContent = ""
            self.parentwindow = parentwindow
            self.language = "Python"
            self.parent = parent
            self.filename = filename
            self.tab1 = ttk.Frame(parent)
            self.text = CustomText(self.tab1, bd=0, font=("Courier", 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.linenumbers = TextLineNumbers(self.tab1, width=55)
            self.linenumbers.attach(self.text)
    
            self.vsb.pack(side=tk.RIGHT, fill=tk.Y)
            self.linenumbers.pack(side="left", fill="y")
            self.text.pack(side="right", fill="both", expand=True)
    
            parent.add(self.tab1, text=filename)
            self.bottomLabel()
    
            self.text.bind("<<Change>>", self._on_change)
            self.text.bind("<Configure>", self._on_change)
            self.text.bind("<KeyRelease>", self.keypress)
            self.text.bind("<Button-1>", self.keypress)
    
        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.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 keypress(self, argument):
            self.updateBottomLabel()
            self.deafultHighlight("argument")
    
        def _on_change(self, event):
            self.linenumbers.redraw()
    
        def bottomLabel(self):
            self.positionAndLanguage = tk.Label(self.parentwindow, text=" Ln: 1, Col: 0, Lang: Plain", anchor=tk.W, bg="#E7E7E7", font=("Courier New", 8))
            self.positionAndLanguage.pack(fill=tk.X, side=tk.BOTTOM)
    
        def updateBottomLabel(self):
            self.row = self.text.index(tk.INSERT).split(".")[0]
            self.column = self.text.index(tk.INSERT).split(".")[1]
            self.positionAndLanguage["text"] = " Ln: {0}, Col: {1}, Lang: {2}".format(self.row, self.column, self.language)
    
    class Arshi(tk.Frame):
        def __init__(self, *args, **kwargs):
            tk.Frame.__init__(self, *args, **kwargs)
            self.fileName = "Untitled Document"
            self.content = ""
            self.previousContent = ""
            self.language = "Python"
            self.row = "0"
            self.column = "0"
            self.startCol = 0
            self.tabs = []
            self.notebook = ttk.Notebook(self)
    
            self.menubar()
            #self.bottomLabel()
            self.createtext()
    
        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.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 keypress(self, argument):
            self.updateBottomLabel()
            self.deafultHighlight("argument")
    
        def configureTags(self, text):
            text.tag_configure("Token.Keyword", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Constant", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Declaration", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Namespace", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Pseudo", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Reserved", foreground="#CC7A00")
            text.tag_configure("Token.Keyword.Type", foreground="#CC7A00")
    
            text.tag_configure("Token.Name.Class", foreground="#003D99")
            text.tag_configure("Token.Name.Exception", foreground="#003D99")
            text.tag_configure("Token.Name.Function", foreground="#003D99")
    
            text.tag_configure("Token.Operator.Word", foreground="#CC7A00")
    
            text.tag_configure("Token.Comment", foreground="#B80000")
    
            text.tag_configure("Token.Literal.String", foreground="#248F24")
    
        def createtext(self):
            self.notebook.pack(fill=tk.BOTH, expand=True)
            t = Tab(self.notebook, self.fileName, self)
            self.tabs.append(t)
    
        def addtab(self):
            t = Tab(self.notebook, self.fileName, self)
            self.tabs.append(t)
    
        def removetab(self):
            numberOfTabs = self.notebook.index("end")
    
            if numberOfTabs > 1:
                tabIndex = self.notebook.index(self.notebook.select())
                self.notebook.forget(tabIndex)
    
        def run(self):
            pass
    
        def menubar(self):
            self.menu = tk.Menu(self)
            self.master.config(menu=self.menu)
    
            self.fileMenu = tk.Menu(self.menu, font=("Courier", 9))
            self.fileMenu.add_command(label="New             Ctrl+N", command=self.newFile)
            self.fileMenu.add_command(label="Open            Ctrl+O", command=self.openFile)
            self.fileMenu.add_command(label="Save            Ctrl+S", command=self.saveFile)
            self.fileMenu.add_command(label="Save As         Ctrl+Shift+S", command=self.saveAsFile)
            self.fileMenu.add_separator()
            self.fileMenu.add_command(label="New Window", command=self.addtab)
            self.fileMenu.add_command(label="Close Window", command=self.removetab)
            self.fileMenu.add_separator()
            self.fileMenu.add_command(label="Exit            Alt+F4", command=self.close)
            self.menu.add_cascade(label="File", menu=self.fileMenu)
    
            self.runMenu = tk.Menu(self.menu, font=("Courier", 9))
            self.runMenu.add_command(label="Run", command=self.run)
            self.menu.add_cascade(label="Run", menu=self.runMenu)
    
        def bottomLabel(self):
            self.positionAndLanguage = tk.Label(self, text=" Ln: 1, Col: 0, Lang: Plain", anchor=tk.W, bg="#E7E7E7", font=("Courier New", 8))
            self.positionAndLanguage.pack(fill=tk.X, side=tk.BOTTOM)
    
        def updateBottomLabel(self):
            self.row = self.text.index(tk.INSERT).split(".")[0]
            self.column = self.text.index(tk.INSERT).split(".")[1]
            self.positionAndLanguage["text"] = " Ln: {0}, Col: {1}, Lang: {2}".format(self.row, self.column, self.language)
    
        def newFile(self):
            self.addtab()
    
        def openFile(self):
            try:
                self.fileName = tk.filedialog.askopenfilename() #Asks user to open file
                with open(self.fileName, 'r') as file:
                    self.content = file.read() #Reads content typed
                self.text.delete(0.0, tk.END) 
                self.text.insert(0.0, self.content)
                self.highlight(self)
            except IOError as e:
                print("Error reading file.")
            except:
                print("Unexpected error occured.")
    
        def deleteContent(self, file):
            file.seek(0)
            file.truncate()
    
        def saveFile(self):
            self.content = self.text.get(0.0, tk.END)
    
            try:
                with open(self.fileName, 'w') as file:
                    self.deleteContent(file)
                    file.write(self.content)
            except IOError as e:
                print("Error reading file.")
            except:
                print("Unexpected error occured.")
    
        def saveAsFile(self):
            self.content = self.text.get(0.0, tk.END)
    
            try:
                self.fileName = tk.filedialog.asksaveasfilename()
                if self.fileName != None:
                    with open(self.fileName, 'w') as file:
                        file.write(self.content)
            except IOError as e:
                print("Error reading file.")
            except:
                print("Unexcepted error occured.")
    
        def close(self):
            try:
                os._exit(0)
            except:
                print(sys.exc_info()[0])
    
        def _on_change(self, event):
            self.linenumbers.redraw()
    
    if __name__ == "__main__":
        root = tk.Tk()
        root.title("Arshi")
        root.geometry("1024x600")
        window = Arshi(root).pack(side="top", fill="both", expand=True)
        root.mainloop()
    

Currently, `open()` would not work , and the bottom labels come up duplicated
for each tab, you should think about how to work those out. The bottom label
one can move out of `Tab` class back to `Arshi` , and then have some
communication between `Tab` class and `Arshi` when tabs are changed to change
the bottom label accordingly.

Also, open should open a new tab, so you can easily work on that. I would also
advice you to understand the complete code and then use it in your code ,
rather than just copy-paste.

