John,

Thank you for the tips.
I was changing the line-column index to a FLOAT because the search would return the starting position (pos) of the string, then by making it a FLOAT and adding the string length I was able to get the end position.
If "red" was on line 1 column 0..
         Tbox.tag_add("red", pos, float(pos)+.03)
      =
         Tbox.tag_add("red", 1.0, 1.3)
It was all I could come up with.

You have convinced me about the re.finditer for this, I think... Still in the prototyping mode:

      def get_position(event):
               pos = Tbox.get(1.0, END)
match = [ matchobj.span() for matchobj in re.finditer("red", pos) ]
               print "match ",match  #debug to shell

Gives all of START,END pairs just fine. It is the last hint about line-column indexes that I am have problems with. All of the documentation I can find about "text.tag_add()" uses line-column for coordinates. If I count characters from the beginning how do I know what line the text is on?
Would you mind making your last hint a bit stronger...

Thanks again!
Dave



John Posner wrote:
On Wed, 30 Dec 2009 12:58:06 -0500, Dave McCormick <mackrac...@gmail.com> wrote:

Hi All,

I am new to Python and the list so I hope I am posting this correctly...

I am working on a way to have text automatically formated in a Tkiniter Text widget and would like some input on my code. Currently I am using Python 2.5 because the server I use has that installed. Tkinter is tk8.4.

Most of the time when I type red, blue, or green the code works as expected. When I copy paste text into the widget the last line is parsed with part of the previous lines
So I guess the problem is in the "looping"?

Here is my code:
from Tkinter import *
root = Tk()
def get_position(event):
    start = 1.0

A couple of problems here: you define "start", but then never use it. Worse, it looks like you don't understand that a line-column index into a Tkinter Text widget is a STRING, not a FLOAT.


    while 1:               pos = Tbox.search("red",END,backwards=TRUE)

I suggest that you use Tbox.get() instead of Tbox.search(), and then use Python's more powerful text-search tools. More on this below.


        if not pos:
            break
        red = pos + "-1c"
        Tbox.tag_add("red", pos, float(pos)+.03)
        Tbox.tag_config("red", foreground="red")

You don't want to define the "red" tag every time get_position() is executed -- that is, every time the user presses a key. Define the red/green/blue tags just once, right after you create the Text widget.


             pos = Tbox.search("blue",END,backwards=TRUE)
        if not pos:
            break
        blue = pos + "-1c"
        Tbox.tag_add("blue", pos, float(pos)+.04)
        Tbox.tag_config("blue", foreground="blue")

        pos = Tbox.search("green",END,backwards=TRUE)
        if not pos:
            break
        green = pos + "-1c"
        Tbox.tag_add("green", pos, float(pos)+.05)
        Tbox.tag_config("green", foreground="green")

The previous 6 lines are almost identical to the 6 lines that precede them. This is fine for prototyping, but when you find yourself writing code like this, think about using a loop or a parameterized function call. For example, you might write this function:

  def insert_color_markup(color):
      ...

... and then call it as many times as you need to:

  insert_color_markup("red")
  insert_color_markup("green")
  insert_color_markup("blue")

Now, about those text-search tools: the "re" (regular expression) module include the function "finditer". This is a real power tool, combining regular expressions and Python iterators -- both of which can be intimidating to newcomers. But it's just what you want, IMHO. I hope the following annotated IDLE transcript convinces you:

Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on win32
import re

text = """The red ball is red, not green. On other other
... hand, the green ball has both red and blue highlights.
... Thank you.
... """

re.finditer("red", text)
<callable-iterator object at 0x00CC46D0>

    ... not too exciting, but this is better:

list(re.finditer("red", text))
[<_sre.SRE_Match object at 0x00C01F70>, <_sre.SRE_Match object at 0x00C06E20>, <_sre.
SRE_Match object at 0x00C06E58>]

    ... this list indicates that we got three hits on the word "red"

[ matchobj.span() for matchobj in re.finditer("red", text) ]
[(4, 7), (16, 19), (77, 80)]

... paydirt: a list of (start,end) pairs for an invocation of Text.tag_add()

One more hint: forget about the line-column indexes into the contexts of a Text widget. Just count characters from the beginning, e.g.:

   "1.0 + %d chars" % start_position

        break

Tbox = Text(root,width=40, height=15, wrap=CHAR)
Tbox.grid(column=0, row=0, sticky=(N+W+E+S))
root.grid_columnconfigure(0, weight=1)
root.grid_rowconfigure(0, weight=1)
Tbox.bind("<KeyRelease>", get_position)
Tbox.focus()
root.mainloop()

Thank you,
Dave

I hope this set of hints is helpful, and not too disjointed, terse, or cryptic. I think this is a cute little app!

-John
--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to