Subject: Re: Quoting questions - Is there a better way? - DN [1]
James Ingham <jingham@leda.cygnus.com> - 01 Dec 1999 - comp.lang.tcl
Jeff,
There are a couple of things to worry about here. One is convenience
& readability of the command, the other is safety against subsequent
parsing.
1) Readability:
When you are building up a complicated statement, with both
delayed and immediate substitutions, getting the backslashing right
can make the code unreadable.
In these cases, I usually use either format, or regsub to build up the
command. In your case, for example, I would do:
set cmd [format {editSelection [%s get [%s curselection]]} $lb $lb]
If there is just one immediate variable that is substituted more than once,
it is easier to use regsub:
regsub -all LIST {editSelection [LIST get [LIST curselection]]} $lb cmd
then do:
bind $lb <ButtonRelease-1> $cmd
Actually, in your case it is even easier, since you can use the bind's
%W tag:
bind $lb <ButtonRelease-1> {editSelection [%W get [%W curselection]]}
but there are many cases where you actually do need to substitute into
the command...
2) Safety:
This code suffers from the problem that if the substituted strings
have embedded spaces or funny characters, then you will get errors.
It is, in fact, possible to create buttons named ".t b" and ".f}",
so you are not safe even with tk widget names - though it is arguable
that people who create widgets with spaces in their names deserve to
have their code break...
To protect against errors caused by this sort of oddity, you have to
use the list command to build up the command string. This will protect
against possible errors of this sort. However, list by itself is
perhaps even more inconvenient, in many cases, than just "". To get
around this, you can combine the two to just protect the words you
care about, as in:
set cmd [format {editSelection [%s get [%s curselection]]} [list $lb] \
[list $lb]
So for instance, you have:
% set lb ".b t"
.b t
% set cmd [format {editSelection [%s get [%s curselection]]} [list $lb] \
[list $lb]]
editSelection [{.b t} get [{.b t} curselection]]
This is not too bad.
However, whenever you find yourself formatting up a complex command
string in this way, you are either doing something really tricky and
cool - like auto-genning procs on the fly for some special purpose -
or you probably just cut the boundry for your procs wrong, and can do
something like:
proc editSelection {w} {
set sel [$w get [$w curselection]]
puts $sel
}
bind $lb <ButtonRelease-1> [list editSelection $lb]
to make your life a lot easier...
Jim
> Hi all,
>
> I continue to find myself backed into the same corner regarding quoting,
> substitution, and scope. Almost always, my problem revolves around getting
> the substitution correct for a "command" attached to a widget or binding.
> The example below is contrived, but it does serve to illustrate my point.
> The problem is with the "bind" command in "proc makeLB". First, what I have
> written is the best I have come up with and it does work, but it seems
> messy. Basically, I want the widget name ($lb) to be expanded immediately,
> but I don't want the actual command to execute until the binding fires.
>
> My logic for the existing solution is as follows:
>
> - don't put the command in braces, so the widget name can be substituted
> - escape the brackets so the command is not executed during the first round
> of substitution
>
> I know that in this simple case I could just use ".lb" in the command
> instead of "$lb", but there are times (I think??) when I can't (the
> situation escapes me...). It also seems that "lb" could be made global and
> then it would not have to be substituted early - but this seems like
> overkill...
>
> My problem with the solution
>
> - I thought it was generally not good to surround a command with quotes
> because arguments
> with spaces could break the command (not true here, but as a general rule)
> - I know that [list] can be employed to correct the above problem, but I
> can't seem to make it work in this context.
> - Using quotes and escaping all command braces just seems "messy"
>
> My questions (finally...):
>
> Is my solution acceptable and/or safe?
> Is there a better/safer way to quote the binding (with [list] and/or {})?
> Is this case typical? I seem to run into this often. Is there a different
> way to code the example so the quoting problem doesn't exist in the first
> place?
>
> Thanks for any advice,
>
> Jeff Godfrey
>
> ======= Code Below ==========
>
> proc makeLB {} {
>
> set lb [listbox .lb -width 20 -height 10]
>
> foreach elem {elem1 elem2 elem3 elem4} {
> $lb insert 0 $elem
> }
>
> bind $lb <ButtonRelease-1> "editSelection \[$lb get \[$lb
> curselection\]\]"
> pack $lb
> }
>
> proc editSelection {selection} {
> puts $selection
> }
>
> console show
> makeLB
>
>
--
++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++==++
Jim Ingham jingham@cygnus.com
Cygnus Solutions Inc.
Last modified
1999-12-10
1999-12-10
(195.108.246.50)
Note: you are looking at
the snapshot of an old wiki
- much of this information
is likely to be very outdated
