Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.python > #83178 > unrolled thread
| Started by | ravas <ravas@outlook.com> |
|---|---|
| First post | 2015-01-03 12:28 -0800 |
| Last post | 2015-01-24 21:20 -0800 |
| Articles | 10 — 4 participants |
Back to article view | Back to comp.lang.python
apostrophe not considered with tkinter's wordstart and wordend ravas <ravas@outlook.com> - 2015-01-03 12:28 -0800
Re: apostrophe not considered with tkinter's wordstart and wordend Peter Otten <__peter__@web.de> - 2015-01-03 22:06 +0100
Re: apostrophe not considered with tkinter's wordstart and wordend Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-04 16:33 -0800
Re: apostrophe not considered with tkinter's wordstart and wordend ravas <ravas@outlook.com> - 2015-01-05 00:01 -0800
Re: apostrophe not considered with tkinter's wordstart and wordend Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-05 05:20 -0800
Re: apostrophe not considered with tkinter's wordstart and wordend Christian Gollwitzer <auriocus@gmx.de> - 2015-01-22 23:26 +0100
Re: apostrophe not considered with tkinter's wordstart and wordend Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-24 18:56 -0800
Re: apostrophe not considered with tkinter's wordstart and wordend ravas <ravas@outlook.com> - 2015-01-24 19:17 -0800
Re: apostrophe not considered with tkinter's wordstart and wordend Rick Johnson <rantingrickjohnson@gmail.com> - 2015-01-24 19:57 -0800
Re: apostrophe not considered with tkinter's wordstart and wordend ravas <ravas@outlook.com> - 2015-01-24 21:20 -0800
| From | ravas <ravas@outlook.com> |
|---|---|
| Date | 2015-01-03 12:28 -0800 |
| Subject | apostrophe not considered with tkinter's wordstart and wordend |
| Message-ID | <e6143cd5-3475-431a-b2cf-17fd9659681c@googlegroups.com> |
When I place my mouse over a word (and I press something)
I want the program to analyze the word.
Tkinter almost provides the perfect option:
self.text.get('current wordstart', 'current wordend')
Unfortunately apostrophes are not considered using wordstart and wordend.
http://infohost.nmt.edu/tcc/help/pubs/tkinter/
Says:
"For the purposes of this operation, a word is either
a string of consecutive letter, digit, or underbar (_) characters,
or a single character that is none of these types."
The easy work around is to highlight the word and use:
self.text.get('sel.first', 'sel.last')
However, it seems like it could be an easy improvement
if we could include the apostrophe in the list of word characters.
Is it possible that this could be added in an upcoming version of Python --
or is this a Tk issue?
----
Windows 7 & Python 3.4
[toc] | [next] | [standalone]
| From | Peter Otten <__peter__@web.de> |
|---|---|
| Date | 2015-01-03 22:06 +0100 |
| Message-ID | <mailman.17359.1420319198.18130.python-list@python.org> |
| In reply to | #83178 |
ravas wrote:
> When I place my mouse over a word (and I press something)
> I want the program to analyze the word.
> Tkinter almost provides the perfect option:
> self.text.get('current wordstart', 'current wordend')
>
> Unfortunately apostrophes are not considered using wordstart and wordend.
> http://infohost.nmt.edu/tcc/help/pubs/tkinter/
> Says:
> "For the purposes of this operation, a word is either
> a string of consecutive letter, digit, or underbar (_) characters,
> or a single character that is none of these types."
>
> The easy work around is to highlight the word and use:
> self.text.get('sel.first', 'sel.last')
>
> However, it seems like it could be an easy improvement
> if we could include the apostrophe in the list of word characters.
> Is it possible that this could be added in an upcoming version of Python
> -- or is this a Tk issue?
I think it is.
<http://www.tcl.tk/man/tcl8.6/TkCmd/text.htm#M41> does not mention a way to
configure the set of word chars either:
"""
?submodifier? wordstart
Adjust the index to refer to the first character of the word containing the
current index. A word consists of any number of adjacent characters that are
letters, digits, or underscores, or a single character that is not one of
these. If the display submodifier is given, this only examines non-elided
characters, otherwise all characters (elided or not) are examined.
"""
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2015-01-04 16:33 -0800 |
| Message-ID | <655cce0d-2db3-4a0d-ab3d-64d5db5e1634@googlegroups.com> |
| In reply to | #83178 |
On Saturday, January 3, 2015 2:28:18 PM UTC-6, ravas wrote:
> Is it possible that this could be added in an upcoming
> version of Python -- or is this a Tk issue?
A quick look at the Tkinter.Text.get source code will answer
that question for you:
py> import inspect
py> from Tkinter import Text
py> print inspect.getsource(Text.get)
def get(self, index1, index2=None):
"""Return the text from INDEX1 to INDEX2 (not included)."""
return self.tk.call(self._w, 'get', index1, index2)
As you can see, this method is just a dumb wrapper. There is
no "python-side" processing going on here. Which is true for
just about the entire Tkinter module.
I'm not sure if you can edit the pre-defined "word capture
patterns" that exist within TK (never had the need to find
out), but you could implement any pattern matching you want
by binding the correct events and then processing the
"target string" on the Python side.
However, i would say that not allowing customization of
patterns is a major flaw of the API, and one more reason why
Tkinter is a rusty old "Clostridium tetani infected" anchor
around Python's neck!
FOR GUIDO'S SAKE, BE SURE YOUR IMMUNIZATIONS ARE UP TO DATE!
[toc] | [prev] | [next] | [standalone]
| From | ravas <ravas@outlook.com> |
|---|---|
| Date | 2015-01-05 00:01 -0800 |
| Message-ID | <714d9211-9b50-4e62-a7dd-25ff94a32d8a@googlegroups.com> |
| In reply to | #83223 |
Thanks guys :-] Rick Johnson: > but you could implement any pattern matching you want > by binding the correct events and then processing the > "target string" on the Python side. I'm curious about what events you would use. The only work around I thought of is to create a word list and then apply tags & use tag_bind().
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2015-01-05 05:20 -0800 |
| Message-ID | <f1bcb866-b07f-478d-83a4-dcf4b2b096e5@googlegroups.com> |
| In reply to | #83225 |
On Monday, January 5, 2015 2:01:22 AM UTC-6, ravas wrote:
> I'm curious about what events you would use. The only work
> around I thought of is to create a word list and then
> apply tags & use tag_bind().
Well i'm not sure what you are doing exactly, so i'll have
to take some liberties here, but i don't foresee "tag_bind"
as helping you. In order to use the binding applied to a
tag, you'll first have to apply the tag to the range of the
text containing the "target word"... (Ahhh, the old "quid
pro quo brings back a good memory!)
https://www.youtube.com/watch?v=qr2bKXBV67o
then and only then could you expect an event to fire. I was
thinking more of binding on the "widget level". Here is what
you said earlier:
> When I place my mouse over a word (and I press something)
> I want the program to analyze the word. Tkinter almost
> provides the perfect option: but [...]
From *that* description, a simple binding of "<Button-1>" to
a callback will give you the chance to process the "word" on
the Python side. Of course, that's easier said than done my
friend!
O:-)
Because (in your case) you cannot rely on the "TK wordstart
pattern" to define the edges correctly, you'll have to
capture the entire line, THEN compute the location of the
cursor within the sub-string ("local offset in absolute
terms"), THEN back pedal until you find the first space (or
whatever defines the start of a word in your app), THEN use
the re module (or some other method) to find the end of the
word (if it exists at all), THEN if it does, do something.
*GASP*! Of course all this could be avoided if those short-
sighted TK folks would have allowed the programmer to define
the pattern!
ಠ_ಠ
One thing to consider though: left-mouse-down is a common
event for most of us --except for those few immortals among
us who have sworn to a "mouse free life"[1] and have
officially completed space cadet training-- and you don't
want Python doing all that work for nothing! So unless you
can justify all that processing for every left-mouse-down
event, i would suggest using another event.
[1]: Of which the phrase would make for interesting
satirical replacement of the chorus in: little orphan
Annie's, "it's a hard knock life".
It's a mouse free life, for us...
It's a mouse free life, for us...
Instead of clicks, WE get pecks...
It's a mouse free life!
[toc] | [prev] | [next] | [standalone]
| From | Christian Gollwitzer <auriocus@gmx.de> |
|---|---|
| Date | 2015-01-22 23:26 +0100 |
| Message-ID | <m9rtd8$15e$1@dont-email.me> |
| In reply to | #83239 |
Am 05.01.15 um 14:20 schrieb Rick Johnson:
> *GASP*! Of course all this could be avoided if those short-
> sighted TK folks would have allowed the programmer to define
> the pattern!
>
> ಠ_ಠ
Well, it turns out you actually can. We don't have Guido's time machine,
but still there is a configuration option in Tk, albeit a very obscure
one: you have to set the global Tcl variables tcl_wordchars and
tcl_nonwordchars after loading Tk to a regexp which defines the word
boundaries:
http://wiki.tcl.tk/1655
Strangely, there is a different preset for Windows and X11. The Windows
preset - consider everything besides space as part of the word - makes
more sense to me than the Unix default, which only counts letters,
numbers and underscores as part of the word. To set the Windows preset,
do this:
tk.eval('set tcl_wordchars {\S}');
tk.eval('set tcl_nonwordchars {\s}');
(untested in Python, only tested directly from a wish shell)
Christian
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2015-01-24 18:56 -0800 |
| Message-ID | <c1bc4c74-0360-4816-884a-4ebff24e2bab@googlegroups.com> |
| In reply to | #84283 |
On Thursday, January 22, 2015 at 4:26:29 PM UTC-6, Christian Gollwitzer wrote:
> Well, it turns out you actually can. We don't have Guido's
> time machine, but still there is a configuration option in
> Tk, albeit a very obscure one: you have to set the global
> Tcl variables tcl_wordchars and tcl_nonwordchars after
> loading Tk to a regexp which defines the word boundaries:
>
> http://wiki.tcl.tk/1655
>
> Strangely, there is a different preset for Windows and
> X11. The Windows preset - consider everything besides
> space as part of the word - makes more sense to me than
> the Unix default, which only counts letters, numbers and
> underscores as part of the word. To set the Windows
> preset, do this:
>
> tk.eval('set tcl_wordchars {\S}');
> tk.eval('set tcl_nonwordchars {\s}');
>
> (untested in Python, only tested directly from a wish shell)
Hmm. Thanks for posting this, but i could not get it to
work??? I tried all sorts of sensible patterns but
nothing works.
Below is a simple testing app with bindings which highlight the
word under the mouse like the OP requested. If you can modify
the word boundaries so that it captures the equivalent of this
pattern r"'\w+'", then i will write a wrapper method for the
Tkinter module for arbitrarily modifying the boundaries.
Here is the code, happy hacking ;-)
## START CODE ##
import Tkinter as tk
from Tkconstants import YES, BOTH, END
SIDX = '1.0'
STR = """
My humble dictators,
ask not what the 'boot_lickers' can do for you,
ask what *YOU* can do to for *YOUR* community!
"""
class MyText(tk.Text):
def __init__(self, master, **kw):
tk.Text.__init__(self, master, **kw)
self.bind("<Button-1>", self.evtButtonOneDown)
self.tag_add('hit', END)
self.tag_config('hit', background='red')
def evtButtonOneDown(self, event):
sLC = self.index('current wordstart')
eLC = self.index('current wordend')
print 'hitspan from {0!r} to {1!r}'.format(sLC, eLC)
self.tag_remove('hit', SIDX, 'end')
self.tag_add('hit', sLC, eLC)
if __name__ == '__main__':
root = tk.Tk()
## root.eval("set tcl_wordchars {psst: over here!}")
## root.eval("set tcl_nonwordchars {psst: and here too!}")
et = MyText(root, undo=True)
et.insert(SIDX, STR)
et.pack(fill=BOTH, expand=YES)
root.mainloop()
## END CODE ##
[toc] | [prev] | [next] | [standalone]
| From | ravas <ravas@outlook.com> |
|---|---|
| Date | 2015-01-24 19:17 -0800 |
| Message-ID | <b1ea0c95-38aa-47b8-a8a2-dd80c3dcb8a5@googlegroups.com> |
| In reply to | #84546 |
We resolved it over at the comp.lang.tcl group.
It turns out what Christian suggested affects what is selected when you double click a word. He later discovered a different method for producing what I want.
Below is my test code that implements both of these things
(tested with Python 3.4 and PyCharm).
import tkinter
import tkinter.messagebox as messagebox
class Creator(object):
def __init__(self):
root = self.root = tkinter.Tk()
# Main Frame
f_main = tkinter.Frame(root, borderwidth=6, relief='flat')
f_main.grid(row=0, column=0, sticky='nsew')
# Text widget, its font and frame
f_txt = tkinter.Frame(f_main, borderwidth=2, relief="sunken")
f_txt.config(width=768, height=768)
f_txt.grid_propagate(False) # ensures a consistent GUI size
f_txt.pack(padx=4, pady=4, side="bottom", fill="both", expand=True)
my_txt = tkinter.Text(f_txt, name='t')
my_txt.config(undo=True, wrap='word')
my_txt.grid(row=0, column=0, sticky="nsew")
self.text = my_txt
# Scrollbar and config
f_scroll = tkinter.Frame(root, borderwidth=4, relief="groove")
f_scroll.grid(row=0, column=1, sticky='nsew')
scrollbar = tkinter.Scrollbar(f_scroll, command=my_txt.yview)
scrollbar.pack(side='left', fill='y', pady=2, padx=0, expand=True)
my_txt.config(yscrollcommand=scrollbar.set)
scrollbar.columnconfigure(0, weight=1)
# Stretchable
root.columnconfigure(0, weight=1)
root.rowconfigure(0, weight=1)
f_main.columnconfigure(0, weight=1)
f_main.rowconfigure(0, weight=1)
f_txt.rowconfigure(0, weight=1)
f_txt.columnconfigure(0, weight=1)
my_txt.bind("<ButtonRelease-3>", self.test)
my_txt.focus_set()
def test(self, event=None):
txt = str(self.text)
a = "::tk::TextPrevPos {} current tcl_wordBreakBefore".format(txt)
b = "::tk::TextNextPos {} current tcl_wordBreakAfter".format(txt)
ind1 = self.root.tk.eval(a)
ind2 = self.root.tk.eval(b)
x = self.text.get(ind1, ind2)
messagebox.showinfo('info', x)
# ===========================================================================
# start up
# ===========================================================================
GUI = Creator()
GUI.root.tk.eval("catch {tcl_endOfWord}")
GUI.root.tk.eval("catch {tcl_startOfPreviousWord}")
GUI.root.tk.eval("set tcl_wordchars {[[:alnum:]']}")
GUI.root.tk.eval("set tcl_nonwordchars {[^[:alnum:]']}")
GUI.root.mainloop()
[toc] | [prev] | [next] | [standalone]
| From | Rick Johnson <rantingrickjohnson@gmail.com> |
|---|---|
| Date | 2015-01-24 19:57 -0800 |
| Message-ID | <f7664734-b001-4b56-a0cd-38c8e2125da8@googlegroups.com> |
| In reply to | #84547 |
On Saturday, January 24, 2015 at 9:17:57 PM UTC-6, ravas wrote: > We resolved it over at the comp.lang.tcl group. It turns > out what Christian suggested affects what is selected when > you double click a word. He later discovered a different > method for producing what I want. Below is my test code > that implements both of these things Great. I did not run the code so i'll take your word that it solved the issue for you. *wink* However, i must admit i did find your design a bit strange to my eyes though. It seems you may be encapsulating too much in that Creator class, whilst not exposing enough. I wonder why you did not subclass a tk.Text? Also, instead of packing multiple frames into a "master grid" you could just use the grid for everything and remove all those frames -- might help reduce some syntactical density. But hey, if you're happy, no need to change it! Working code is better than incomprehensible code. In any event, i'm happy you guys sorted it out. Posting a solution for the next guy is always a good thing to do.
[toc] | [prev] | [next] | [standalone]
| From | ravas <ravas@outlook.com> |
|---|---|
| Date | 2015-01-24 21:20 -0800 |
| Message-ID | <9b69dde6-eb25-40f3-bb00-5f21a0ec134c@googlegroups.com> |
| In reply to | #84550 |
I copied the GUI creation from my personal text editor. The scrollbar and stretchability could have been left out, for sure. You're only seeing a portion of a more complex GUI. After writing several Tkinter applications, I decided that subclassing without a clear reason only had the effect of polluting the namespace of my class. I like seeing only my attributes and methods during code completion. Thanks for your interest and help.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.python
csiph-web