Tcl / Tk - 如何在使用eval执行命令后获得提示?

时间:2011-04-22 17:55:51

标签: tcl tk

下面给出了重现我的问题的代码。我将文件命名为test.tcl

#-------------------------------------------------------------------
# test.tcl
#-------------------------------------------------------------------

namespace eval Gui {
}

proc Gui::test {} {
  toplevel .test
  wm title .test "Test"
  wm resizable .test 0 0 ;# not resizable

  # create a frame to hold the check widgets
  set f [frame .test.boolean -borderwidth 10] 
  pack $f -side top

  # OK and Cancel buttons
  button .test.ok -text "OK" -command [list Gui::Ok .test ]
  button .test.cancel -text "Cancel" -command [list Gui::cancel .test ]
  pack   .test.cancel .test.ok -side right

  bind .test <Return> {Gui::Ok .test ; break}
  bind .test <Escape> {Gui::cancel .test ; break}
}

proc Gui::Ok { arg } {
  set x [list puts "hello world!"]
  eval $x
  destroy $arg
}

proc Gui::cancel { arg } {
  destroy $arg
}

#-------------------------------------------------------------------
# Gui main window 
#-------------------------------------------------------------------
proc Gui::initialize { } {

  # build the frame which contains menu options
  frame .mbar -relief raised -bd 2
  frame .mdummy -width 200 -height 240
  pack .mbar .mdummy -side top -fill x

  # menu options
  menubutton .mbar.command -text Command -underline 0 -menu .mbar.command.menu
  pack .mbar.command -side left

  # menu under command options
  menu .mbar.command.menu -tearoff 0
  .mbar.command.menu add command -label "Test..." -command [list Gui::test]
}

#-------------------------------------------------------------------
# main code
#-------------------------------------------------------------------
Gui::initialize

当我输入

% wish
% source test.tcl
%

然后点击Command -> Test ... -> OK给我

% hello world!

打印%后,我没有收到提示hello world!。虽然我仍然可以在该空间中执行tcl命令。例如:

% hello world!
puts "hi"
hi
%

返回提示。

我的问题: 如何在tcl / tk执行打印%

eval命令后返回提示hello world!

2 个答案:

答案 0 :(得分:3)

您永远不会丢失%提示。这是正在发生的事情:

您有提示:

%

然后在同一行打印一个字符串:

% hello world!

你的“当前”提示仍然是同样的事情。以下命令是“on”提示符:

puts "hi"

其中,因为它在tclsh中运行,并且因为您刚刚插入了换行符,所以请到下一行:

hi

你得到另一个提示:

%

您没有从GUI中获得“另一个”提示,因为tclsh没有直接处理puts "hello world"。基本上,就tclsh而言,“你好世界”来自火星,搞砸了你的终端。它甚至不知道那里有。

也许更好的解释方法是:如果您的puts "hello world"正在打印到文件,那么您仍然会收到%提示。但是有人把这些角色拿到你的显示器上(包括换行符)。

答案 1 :(得分:3)

提示符%来自tcl解释器并在终端中显示,因为它处于交互模式。如果您将脚本作为wish test.tcl运行,则永远不会获得%

您可以实现自己的交互模式,并在应用的所有初始化步骤后调用它。这里是一个如何完成的例子:

proc Gui::interactive {} {
  set prompt1 "tcl>"
  set prompt2 "?"
  set cmd {}
  set prompt "$prompt1 "
  fconfigure stdin -blocking false -buffering line
  fileevent stdin readable {set Gui::stdinReady 1}
  while true {
    puts -nonewline $prompt
    flush stdout
    vwait Gui::stdinReady
    set str [gets stdin]
    lappend cmd $str
    set cmdStr [join $cmd "\n"]
    if {[info complete $cmdStr]} {
      set cmd {}
      if {$cmdStr != ""} {
        if {[catch {eval $cmdStr} result]} {
          puts stderr "ERROR: $result"
        } elseif {$result != ""} {
          puts $result
        }
      }
      set prompt "$prompt1 "
    } else {
      set prompt "$prompt2 "
    }
    if {[eof stdin]} {
      puts ""
      break
    }
  }
}

只需在执行Gui::test之后调用此函数,您就会得到自己的提示。 但即使使用此示例,如果文本将从其他一些过程打印到终端,则不会重新绘制提示。