title: Using Tkinter Text indexing expressions to delete last line of text
body: <p>I have a text widget which displays information as my program runs. I want to add functionality which will allow me to overwrite the last line of the text widget with a new line. My code looks like this:</p>
  
  <pre><code>class TextRedirector(object):
     def __init__(self, text_widget):
        self.text_widget = text_widget
     def write(self, the_string):
        self.text_widget.configure(state="normal")
        self.text_widget.insert("end", the_string)
        self.text_widget.see(END)
        self.text_widget.configure(state="disabled")
     def overwrite(self, the_string):
        self.text_widget.configure(state="normal")
        self.text_widget.delete("end-1l linestart+1c", "end")
        self.text_widget.insert("end", the_string)
        self.text_widget.see(END)
        self.text_widget.configure(state="disabled")
  </code></pre>
  
  <p><a href="https://stackoverflow.com/questions/19477106/how-do-i-get-the-line-and-column-of-the-end-position-of-text-in-tkinter">How do I get the line and column of the end position of text in Tkinter?</a> -- I have seen this post, where Bryan Oakley appears to answer my question with <code>textwidget.delete("end-1c linestart", "end")</code>, but when I use this, the text alternates between being placed at the end of the last line, and actually overwriting the last line. That is to say, it works half of the time, and half of the time the new text is slapped on the end of the old text. My understanding of the index expressions for the Text widget (covered tersely at <a href="http://effbot.org/tkinterbook/text.htm" rel="nofollow noreferrer">http://effbot.org/tkinterbook/text.htm</a>) is that "end-1c linestart" means something like "end, back one character, beginning of line" so I don't understand why it would go to the end of a line of text, and only every other time. The result looks something like this at each step (each part is an updated version of the whole text widget, only the last lines are being modified):</p>
  
  <pre><code>!!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iteration: 1 / 42
  -----
  
  !!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iteration: 1 / 42iteration: 2 / 42
  -----
  
  !!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  iteration: 3 / 42
  -----
  
  !!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.iteration: 4 / 42
  -----
  </code></pre>
  
  <p>I tried using <code>self.text_widget.delete("end-1l linestart+1c", "end")</code>. This almost works, but I end up with </p>
  
  <pre><code>!!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iteration: 1 / 42
  -----
  
  !!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iteration: 1 / 42
  iteration: 2 / 42
  -----
  
  !!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iteration: 1 / 42
  iiteration: 3 / 42
  -----
  
  !!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iteration: 1 / 42
  iiteration: 4 / 42
  </code></pre>
  
  <p>I have tried a few other things, using these indexing expressions to the best of my understanding, but I haven't solved the problem yet. I tried adding if statements in the overwrite function to handle different scenarios for text that might be at the end of the widget, for example if it ends in an empty line, or two empty lines, etc. I did not succeed with that either.</p>
  
  <p>For full disclosure, I might mention I am using this Text widget as a sort of substitute for the printouts to the command line. Hence the name of the class, TextRedirector. I don't think this makes any difference to the issue at hand, but faulty assumptions are probably what got me here in the first place... The line after the class is this: </p>
  
  <p><code>sys.stdout = TextRedirector(self.textbox)</code></p>
  
  <p>And self.textbox is a Text widget created before the class is defined.</p>
  
  <p>UPDATE: I tried saving the index from before the last insertion of text, and building a string expression based on that to delete the last line. The result still wasn't perfect. </p>
  
  <pre><code>class TextRedirector(object):
     def __init__(self, text_widget):
        self.text_widget = text_widget
        self.index_before_last_print = ""
     def write(self, the_string):
        self.index_before_last_print = self.text_widget.index("end")
        self.text_widget.configure(state="normal")
        self.text_widget.insert("end", the_string)
        self.text_widget.see(END)
        self.text_widget.configure(state="disabled")
     def overwrite(self, the_string):
        self.text_widget.configure(state="normal")
        self.text_widget.delete(self.index_before_last_print + "-1c linestart+1c", "end")
        self.index_before_last_print = self.text_widget.index("end")
        self.text_widget.insert("end", the_string)
        self.text_widget.see(END)
        self.text_widget.configure(state="disabled")
  </code></pre>
  
  <p>Here was the result</p>
  
  <pre><code>!!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iteration: 1 / 42
  -----
  
  !!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iiteration: 2 / 42
  -----
  
  !!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iiteration: 3 / 42
  -----
  
  !!!!! Settings Have Been Backed Up !!!!!
  
  Computing coordinates...
  
  Coordinates have been computed.
  
  iiteration: 4 / 42
  </code></pre>