tcl プロシージャが puts を使用して stdout に書き込んでいる場合は、puts を再定義するだけです。これをコーディングした後、入力変数をグローバルにする必要がある場合はさらに簡単になります。ただし、そのままでは、スタックフレームによって正しい変数が変更されます。
proc stdout2var { var } {
set level [ info level ]
# we may have called stdout2var before so this allows only one variable at a time
# and preserves tcls original puts in putsorig
if { [ string length [info commands "putsorig" ] ] == 0 } {
rename ::puts ::putsorig
}
eval [subst -nocommands {proc ::puts { args } {
set fd stdout
# args check
switch -exact -- [llength \$args ] {
1 {
set fd stdout
}
2 {
if { ![string equal \"-nonewline\" [lindex \$args 0 ] ] } {
set fd [lindex \$args 0 ]
}
}
3 {
set fd [lindex \$args 1 ]
}
default {
error \"to many or too few args to puts must be at most 3 ( -nonewline fd message )\"
}
}
# only put stdout to the var
if { [string equal \"stdout\" \$fd ] } {
# just level and var are subst
set message [lindex \$args end ]
uplevel [expr { [info level ] - $level + 1 } ] set $var \\\"\$message\\\"
} else {
# otherwise evaluate with tcls puts
eval ::putsorig \$args
}
} } ]
}
proc restorestdout { } {
# only do rename if putsorig exists incase restorestdout is call before stdout2var or
# if its called multiple times
if { [ string length [ info commands "putsorig"] ] != 0 } {
rename ::puts ""
rename ::putsorig ::puts
}
}
# so for some test code . because we cannot write to stdout we need to write to stderr.
# puts on level 1
proc myproc { a b } {
puts "$a $b "
}
# example with some deeper levels now puts is on level 2
proc myUberProc { c } {
myproc "a" $c
}
# this prints Ya Hoo to stdout
myproc "Ya" "Hoo"
set x ""
stdout2var x
#puts "====\n[ info body putter ]\n===="
puts stdout " Hello"
puts stderr "x = $x"; # x = Hello\n
puts -nonewline stdout " Hello"
puts stderr "x = $x"; # x = Hello
myproc "Ya" "Hoo"
puts stderr "x = $x" ; # x = Ya Hoo\n
set y ""
stdout2var y
myUberProc "Zip"
puts stderr "y = $y , x = $x" ; # y = a Zip , x = Ya Hoo\n
restorestdout
# now writes to stdout
puts "y = $y , x = $x" ; # y = a Zip , x = Ya Hoo\n
出力は次のようになります。
Ya Hoo
x = Hello
x = Hello
x = Ya Hoo
y = a Zip , x = Ya Hoo
y = a Zip , x = Ya Hoo