如何在 tcl 提示中抑制 proc 的返回值 [英] How to suppress a proc's return value in tcl prompt

查看:128
本文介绍了如何在 tcl 提示中抑制 proc 的返回值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对TCL比较新,在TCL提示下,当我们调用一个带有返回值的proc时,proc的返回值被tcl回显了.有没有办法阻止它(不影响看跌期权或类似功能)作为例子

I'm relatively new in TCL, in TCL prompt, when we invoke a proc with some return value, the proc's return value is echoed back by tcl. Is there a way to stop it (without affecting puts or similar functionality) as an example

bash$ tclsh
% proc a {} { puts  "hello"; return 34; }
% a
hello
34
%

现在如何抑制出现在屏幕上的 34?任何帮助表示赞赏.

Now how do i suppress the 34 coming to the screen? Any help is appreciated.

更新:实际上proc是另一个工具的一部分,之前它没有任何返回值,但现在它可以有条件地返回一个值.它可以从脚本中调用,不会有任何问题(正如 Bryan 指出的那样).并且可以从交互式提示中调用它,然后在所有必要的输出之后,不必要地打印返回值.所以 1) 我没有改变用户的 tclshrc 的设施 2) 现有的脚本应该继续工作.每次调用 proc 时,在所有必要的输出之后,都会打印一个数字,这似乎很奇怪.对于用户来说,这是一个不必要的信息,除非他已经抓住了价值并想做点什么.所以我希望将价值交付给用户,但不会打印到提示/用户界面(希望我很清楚)

Update: Actually the proc is a part of another tool, earlier it did not have any return value, but now conditionally it can return a value. it can be called from a script and there won't be any problem (as Bryan pointed out). and it can be called from interactive prompt, then after all the necessary outputs, the return value is getting printed unnecessarily. So 1) I don't have the facility of changing a user's tclshrc 2) existing scripts should continue to work. And it seems strange that every time the proc is called, after all the necessary outputs, a number gets printed. To a user, this is a needless information unless he has caught the value and wants to do something. So i wanted the value to be delivered to user, but without getting printed to prompt/UI (hope i'm clear )

推荐答案

tclshwish 中的交互式 shell 代码将打印任何非空结果.为了不打印任何内容,您必须让行"上的最后一个命令产生一个空结果.但是使用哪个命令?

The interactive shell code in tclsh and wish will print any non-empty result. To get nothing printed, you have to have the last command on the "line" produce an empty result. But which command to use?

许多命令会产生一个空的结果:

Many commands will produce an empty result:

if 1 {}
subst ""
format ""

不过,最短的大概是:

list

因此,您可以编写如下代码:

Thus, you could write your code like:

a;list

当然,只有当您的命令实际上产生一个您不想看到的大结果时,这才真正有用.在这些情况下,我经常发现使用衡量结果大小的东西最有用,例如:

Of course, this only really becomes useful when your command actually produces a large result that you don't want to see. In those cases, I often find that it is most useful to use something that measures the size of the result, such as:

set tmp [something_which_produces a_gigantic result]; string length $tmp

我找到的最有用的命令是 string lengthllengthdict size.

The most useful commands I find for that are string length, llength and dict size.

如果您绝对必须不打印命令的结果,则必须编写自己的交互式循环.有两种方法可以做到这一点,具体取决于您是否在事件循环内运行:

If you absolutely must not print the result of the command, you have to write your own interactive loop. There are two ways to do this, depending on whether you are running inside the event loop or not:

这个简单的版本只是检查命令名称是否在用户键入的内容中.否则随意丢弃结果可能不是一个好主意!

This simplistic version just checks to see if the command name is in what the user typed. It's probably not a good idea to arbitrarily throw away results otherwise!

set accum ""
while {[gets stdin line] >= 0} {
    append accum $line "\n"
    if {[info complete $accum]} {
        if {[catch $accum msg]} {
            puts stderr $msg
        } elseif {$msg ne "" && ![string match *TheSpecialCommand* $accum]} {
            puts $msg
        }
        set accum ""
    }
}

使用事件循环

这只是处理阻塞IO的情况;当输入来自熟终端(即默认)时,这是正确的事情

With the event loop

This is just handling the blocking IO case; that's the correct thing when input is from a cooked terminal (i.e., the default)

fileevent stdin readable handleInput
set accum ""
proc handleInput {} {
    global accum
    if {[gets stdin line] < 0} {
        exit; # Or whatever
    }
    append accum $line "\n"
    if {[info complete $accum]} {
        if {[catch {uplevel "#0" $accum} msg]} {
            puts stderr $msg
        } elseif {$msg ne "" && ![string match *TheSpecialCommand* $accum]} {
            puts $msg
        }
        set accum ""
    }
}
vwait forever; # Assuming you're not in wish or have some other event loop...

如何检测正在执行的命令

上面的代码使用了![string match *TheSpecialCommand* $accum] 来决定是否丢弃命令结果,但这很丑陋.利用 Tcl 自己的内置钩子的更优雅的方法是使用 execution trace 来检测命令是否已被调用(为简洁起见,我将在此处仅显示非事件循环版本).这样做的另一个优点是扩展到抑制多个命令的输出很简单:只需将跟踪添加到每个命令即可.

How to detect the command is being executed

The code above uses ![string match *TheSpecialCommand* $accum] to decide whether to throw away the command results, but this is very ugly. A more elegant approach that leverages Tcl's own built-in hooks is to use an execution trace to detect whether the command has been called (I'll just show the non-event-loop version here, for brevity). The other advantage of this is that it is simple to extend to suppressing the output from multiple commands: just add the trace to each of them.

trace add execution TheSpecialCommand enter SuppressOutput
proc SuppressOutput args {
    # Important; do not suppress when it is called inside another command
    if {[info level] == 1} {
        set ::SuppressTheOutput 1
    }
}

# Mostly very similar from here on
set accum ""
while {[gets stdin line] >= 0} {
    append accum $line "\n"
    if {[info complete $accum]} {
        set SuppressTheOutput 0;                       # <<<<<< Note this!
        if {[catch $accum msg]} {
            puts stderr $msg
        } elseif {$msg ne "" && !$SuppressTheOutput} { # <<<<<< Note this!
            puts $msg
        }
        set accum ""
    }
}

明确地说,我不会永远在我自己的代码中这样做!如果重要的话,我只会手动抑制输出.

To be clear, I wouldn't ever do this in my own code! I'd just suppress the output manually if it mattered.

这篇关于如何在 tcl 提示中抑制 proc 的返回值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆