I have a text entry where I want to be able to enter an arbitrary command to execute at global level with both the input command and the result written out using puts. The string to execute is sent as an arg to a procedure.
I've tried several methods, using [after 0] and also [uplevel #0] and I'm stumped. I've resorted to trial and error hoping it would eventually work without success.
Any ideas?
In my tests, arg is
$foobar + 5
and foobar is global and 10, I want to have it output the result: 15
Here are several attempts, to no avail:
% set foobar 10
10
------------------------
% proc test {arg} {
uplevel #0 [list puts "result of $arg is\n [list eval $arg]"]
}
% test {$foobar + 5}
result of $foobar + 5 is
eval {$foobar + 5}
------------------------
% proc test {arg} {
uplevel #0 [list puts "result of $arg is\n [eval $arg]"]
}
% test {$foobar + 5}
can't read "foobar": no such variable
------------------------
% proc test {arg} {
uplevel #0 [list puts "result of $arg is\n [$arg]"]
}
% test {$foobar + 5}
invalid command name "$foobar + 5"
--------------------------
% proc test {arg} {
uplevel #0 [list puts "result of $arg is\n \[list $arg\]"]
}
% test {$foobar + 5}
result of $foobar + 5 is
[list $foobar + 5]
On 9/24/2022 5:34 PM, et4 wrote:
I have a text entry where I want to be able to enter an arbitrary command to execute at global level with both the input command and the result written out using puts. The string to execute is sent as an arg to a procedure.
I've tried several methods, using [after 0] and also [uplevel #0] and I'm stumped. I've resorted to trial and error hoping it would eventually work without success.
Any ideas?
In my tests, arg is
$foobar + 5
and foobar is global and 10, I want to have it output the result: 15
Here are several attempts, to no avail:
% set foobar 10
10
------------------------
% proc test {arg} {
uplevel #0 [list puts "result of $arg is\n [list eval $arg]"]
}
% test {$foobar + 5}
result of $foobar + 5 is
eval {$foobar + 5}
------------------------
% proc test {arg} {
uplevel #0 [list puts "result of $arg is\n [eval $arg]"]
}
% test {$foobar + 5}
can't read "foobar": no such variable
------------------------
% proc test {arg} {
uplevel #0 [list puts "result of $arg is\n [$arg]"]
}
% test {$foobar + 5}
invalid command name "$foobar + 5"
--------------------------
% proc test {arg} {In all these tests, I should have been trying:
uplevel #0 [list puts "result of $arg is\n \[list $arg\]"]
}
% test {$foobar + 5}
result of $foobar + 5 is
[list $foobar + 5]
test {expr $foobar + 5}
but it doesn't seem to work with all my attempts
On 9/24/2022 5:34 PM, et4 wrote:
I have a text entry where I want to be able to enter an arbitrary
command to execute at global level with both the input command and
the result written out using puts. The string to execute is sent as
an arg to a procedure.
I've tried several methods, using [after 0] and also [uplevel #0]
and I'm stumped. I've resorted to trial and error hoping it would
eventually work without success.
Any ideas?
In my tests, arg is
$foobar + 5
and foobar is global and 10, I want to have it output the result: 15
In all these tests, I should have been trying:
test {expr $foobar + 5}
but it doesn't seem to work with all my attempts
et4 <[email protected]> wrote:
On 9/24/2022 5:34 PM, et4 wrote:
I have a text entry where I want to be able to enter an arbitrary
command to execute at global level with both the input command and
the result written out using puts. The string to execute is sent as
an arg to a procedure.
I've tried several methods, using [after 0] and also [uplevel #0]
and I'm stumped. I've resorted to trial and error hoping it would
eventually work without success.
Any ideas?
In my tests, arg is
$foobar + 5
and foobar is global and 10, I want to have it output the result: 15
In all these tests, I should have been trying:
test {expr $foobar + 5}
but it doesn't seem to work with all my attempts
$ rlwrap tclsh
% proc test {args} {
uplevel #0 eval {*}$args
}
% set foobar 10
10
% test {expr $foobar + 5}
15
%
But, note, you are currently walking down a path that will eventually
lead to you directly to "quoting hell" (https://wiki.tcl-lang.org/page/Quoting+hell).
I have a text entry where I want to be able to enter an arbitrary
command to execute at global level with both the input command and the
result written out using puts. The string to execute is sent as an arg
to a procedure.
I've tried several methods, using [after 0] and also [uplevel #0] and
I'm stumped. I've resorted to trial and error hoping it would eventually
work without success.
Any ideas?
In my tests, arg is
$foobar + 5
and foobar is global and 10, I want to have it output the result: 15
I believe this is what you want:
proc xx {args} {
set x [uplevel #0 $args]
puts "Command: $args"
puts "Result: $x"
return $x
}
Normally the script argument to uplevel is a list to avoid "quoting hell".
In this case $args is already a list. Do not expand it using {*}.
Dave B
On 9/24/2022 7:17 PM, Rich wrote:
et4 <[email protected]> wrote:
On 9/24/2022 5:34 PM, et4 wrote:
I have a text entry where I want to be able to enter an arbitrary
command to execute at global level with both the input command and
the result written out using puts. The string to execute is sent as
an arg to a procedure.
This has to be do-able, since the windows console and linux
interactive mode can run any arbitrary commands.
et4 <[email protected]> wrote:
On 9/24/2022 7:17 PM, Rich wrote:
et4 <[email protected]> wrote:
On 9/24/2022 5:34 PM, et4 wrote:
I have a text entry where I want to be able to enter an arbitrary
command to execute at global level with both the input command and
the result written out using puts. The string to execute is sent as >>>>> an arg to a procedure.
This has to be do-able, since the windows console and linux
interactive mode can run any arbitrary commands.
When building commands, use [list]. You should almost always use [list]
for building up commands.
Plus, with an entry (or other Tk widget) you don't have the problem of
the Tcl code parser also 'interpreting' the code, before your eval
thereof, which is what starts to generate quoting hell situations.
I.e.:
#!/usr/bin/wish
entry .e
button .b -text run -command [list button-pushed .e]
pack .e .b -side top
proc button-pushed {w} {
set cmd [$w get]
set result [run $cmd]
puts result=$result
$w delete 0 end
}
proc run {cmd} {
return [uplevel #0 [list eval $cmd]]
}
set foo 10
Then, putting this into the entry and pressing the 'run' button gives:
puts "hello foo + 5 = [expr {$foo+5}]"
this result in my rxvt window:
hello foo + 5 = 15
result=
**************************
On 9/25/2022 5:35 AM, Rich wrote:
et4 <[email protected]> wrote:
On 9/24/2022 7:17 PM, Rich wrote:
et4 <[email protected]> wrote:
On 9/24/2022 5:34 PM, et4 wrote:
I have a text entry where I want to be able to enter an
arbitrary command to execute at global level with both the
input command and the result written out using puts. The
string to execute is sent as an arg to a procedure.
This has to be do-able, since the windows console and linux
interactive mode can run any arbitrary commands.
When building commands, use [list]. You should almost always use
[list] for building up commands.
Plus, with an entry (or other Tk widget) you don't have the problem
of the Tcl code parser also 'interpreting' the code, before your
eval thereof, which is what starts to generate quoting hell
I don't understand the many suggestions of using [list] and upvar.
I have this code that works just fine:
entry $::w.frame0.aliasbox
$::w.frame0.aliasbox configure -takefocus 1
$::w.frame0.aliasbox configure -width $::ALIASWIDTH
$::w.frame0.aliasbox configure -background $::ALIASBG
$::w.frame0.aliasbox configure -foreground $::ALIASFG
$::w.frame0.aliasbox configure -textvariable ::INPUT
later on,
eval {*}$::INPUT
Note that $::INPUT may be an alias that will be resolved
by an external list... or a proc (also defined externally),
which seems to be what you want.
I never needed upvar and [list] definitely does not work
for me because it causes the entire proc and arguments
to be treated like a single block of text, as if
proc arguments were "proc arguments".
* Rich <[email protected]d>
| return [uplevel #0 [list eval $cmd]]
Since [uplevel] does an eval on it's own, wouldn't
return [uplevel #0 $cmd]
be the same?
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 714 |
| Nodes: | 16 (2 / 14) |
| Uptime: | 135:51:42 |
| Calls: | 12,087 |
| Files: | 14,997 |
| Messages: | 6,517,370 |