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

发布于 2024-11-02 15:04:48 字数 2136 浏览 0 评论 0原文

下面给出了重现我的问题的代码。我将文件命名为 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 ->测试...-> OK 这让我

% hello world!

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

% hello world!
puts "hi"
hi
%

返回提示。

我的问题: 如何在 tcl/tk 执行打印 hello world!eval 命令后恢复提示符 %

The code to reproduce my problem is given below. I named the file as 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

When I type

% wish
% source test.tcl
%

and then I click Command -> Test ... -> OK which gives me

% hello world!

I don't get the prompt % back after it prints hello world!. Though I can still execute tcl commands in that space. For example:

% hello world!
puts "hi"
hi
%

which returns the prompt.

My question:
How to get the prompt % back after tcl/tk executes the eval command which prints hello world!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

软的没边 2024-11-09 15:04:48

提示符 % 来自 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 执行后调用此函数,您就会得到自己的提示。
但即使在这个例子中,如果文本从其他过程打印到终端,提示也不会被重新绘制。

The prompt % came from tcl interpreter and shown in the terminal just because it's in interactive mode. If you run your script as wish test.tcl you will never get %.

You can implement your own interactive mode and call it after all initialization steps of your app. Here the example how it can be done:

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
    }
  }
}

Just call this function after Gui::test execution and you;ll get your own prompt.
But even with this example the prompt will not be redrawn if a text will be printed to the terminal from some other procedure.

疯狂的代价 2024-11-09 15:04:48

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

您有一个提示:

%

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

% hello world!

您的“当前”提示仍然是同一件事。以下命令是该提示符的“on”:

puts "hi"

由于它在 tclsh 中运行并且您刚刚插入了一个换行符,因此出现在下一行:

hi

并且您会得到另一个提示:

%

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

也许更好的解释方法是:如果您的 puts“hello world” 打印到文件,那么您仍然会拥有 % 提示。但是有人拿走了这些字符并将它们推到您的显示器上(包括换行符)。

You never lost the % prompt. Here's what's happening:

You have a prompt:

%

Then you print a string on that same line:

% hello world!

Your "current" prompt is still that same thing. The following command is "on" that prompt:

puts "hi"

Which, because it is running in tclsh and because you just inserted a newline, comes on the next line:

hi

And you get another prompt:

%

You didn't get "another" prompt from your GUI thing because puts "hello world" wasn't processed by tclsh directly. Basically, as far as tclsh is concerned, the "hello world" came from Mars and screwed up your terminal. It doesn't even know that is there.

Maybe a better way to explain it is this: If your puts "hello world" was printing to a file, then you would still have your % prompt. But someone took those characters and shoved them onto your display (including the newline).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文