Patterns

When you create a new text widget, it has no contents. To insert text into the widget, use the insert method and insert text at the INSERT or END indexes:

    text.insert(END, "hello, ")
    text.insert(END, "world")

You can use an optional third argument to the insert method to attach one or more tags to the newly inserted text:

    text.insert(END, "this is a ")
    text.insert(END, "link", ("a", "href"+href))

To insert embedded objects, use the window_create or image_create methods:

    button = Button(text, text="Click", command=click)
    text.window_create(INSERT, window=button)

To delete text, use the delete method. Here's how to delete all text from the widget (this also deletes embedded windows and images, but not marks):

    text.delete(1.0, END)

To delete a single character (or an embedded window or image), you can use delete with only one argument:

    text.delete(INSERT)
    text.delete(button)

To make the widget read-only, you can change the state option from NORMAL to DISABLED:

    text.config(state=NORMAL)
    text.delete(1.0, END)
    text.insert(END, text)
    text.config(state=DISABLED)

Note that you must change the state back to NORMAL before you can modify the widget contents from within the program. Otherwise, calls to insert and delete will be silently ignored.

To fetch the text contents of the widget, use the get method:

    contents = text.get(1.0, END)

FIXME: add material on the dump method, and how to use it on 1.5.2 and earlier

Here's a simple way to keep track of changes to the text widget:

    import md5
    def getsignature(contents):
        return md5.md5(contents).digest()
    
    text.insert(END, contents) # original contents
    signature = getsignature(contents)
    
    ...
    
    contents = text.get(1.0, END)
    if signature != getsignature(contents):
        print "contents have changed!"

FIXME: modify to handle ending linefeed added by text widget

The index method converts an index given in any of the supported formats to a line/column index. Use this if you need to store an "absolute" index.

    index = text.index(index)

However, if you need to keep track of positions in the text even after other text is inserted or deleted, you should use marks instead.

    text.mark_set("here", index)
    text.mark_unset("here")

The following function converts any kind of index to a (line, column)-tuple. Note that you can directly compare positions represented by such tuples.

    def getindex(text, index):
        return tuple(map(int, string.split(text.index(index), ".")))
    
    if getindex(text, INSERT) < getindex(text, "sentinel"):
        text.mark_set(INSERT, "sentinel")

The following example shows how to enumerate all regions in the text that has a given tag.

    ranges = text.tag_ranges(tag)
    for i in range(0, len(ranges), 2):
        start = ranges[i]
        stop = ranges[i+1]
        print tag, repr(text.get(start, stop))

The search method allows you to search for text. You can search for an exact match (default), or use a Tcl-style regular expression (call with the regexp option set to true).

    text.insert(END, "hello, world")
    
    start = 1.0
    while 1:
        pos = text.search("o", start, stopindex=END)
        if not pos:
            break
        print pos
        start = pos + "+1c"

Given an empty text widget, the above example prints 1.4 and 1.8 before it stops. If you omit the stopindex option, the search wraps around if it reaches the end of the text.

To search backwards, set the backwards option to true (to find all occurences, start at END, set stopindex to 1.0 to avoid wrapping, and use "-1c" to move the start position).