0

我已经编写了许多 bash/bind 工具来简化我的命令行存在,并且最近想让其中一个工具具有交互性。如果我尝试在这些脚本之一中从标准输入读取,执行会在读取时锁定。我的示例是在 python 中,但是当调用的脚本是用 ruby​​ 编写时,我看到了完全相同的行为:

~> cat tmp.py
import sys
sys.stdout.write(">>>")
sys.stdout.flush()
foo = sys.stdin.readline()
print "foo: %s" % foo,


~> python tmp.py
>>>yodeling yoda
foo: yodeling yoda

所以脚本有效。当我调用它时,我可以给它输入并打印我输入的内容。

~> bind -x '"\eh":"echo yodeling yoda"'
[output deleted]

~> [Alt-H]
yodeling yoda

bind按预期工作。绑定的击键调用命令。我一直在使用这些东西,但直到现在,我只调用了不需要读取标准输入的脚本。

让我们将 [Alt-H] 绑定到脚本:

~> bind -x '"\eh":"python tmp.py"'
[output deleted]

现在我们配置为让脚本在被绑定击键调用时从标准输入读取。点击 [Alt-H] 启动脚本,但没有回显任何键入的内容。即使按下 [Crl-D] 也不会结束它。退出的唯一方法是点击 [Crl-C],杀死 readline 中的进程。(sys.stdin.read() 遭受同样的命运。)

~> [Alt-H]
>>>Traceback (most recent call last):
  File "tmp.py", line 7, in <module>
    foo = sys.stdin.readline()
KeyboardInterrupt

正如我在顶部提到的,我看到了与 ruby​​ 相同的问题,所以我知道这与我使用的语言无关。(我省略了脚本。)

~> bind -x '"\eh":"ruby tmp.rb"'
[Output deleted]

~> [Alt-H]
>>>tmp.rb:3:in `gets': Interrupt
    from tmp.rb:3

我已经查看了 Bash 参考手册关于 bind 的条目,它没有说明输入限制。有什么想法吗?

编辑:

如果我在进程卡住时 cat /proc/[PID]/fd/0 ,我会看到正在显示脚本的输入。(奇怪的是,相当数量的字符 - 似乎是随机的 - 没有出现在这里。这个症状只有在我输入了几百字节后才会出现。)

找到了这个,描述了终端如何以及何时在熟模式和生模式之间切换。呼叫stty cookedstty echo在提示开始时,然后stty sanestty raw之后触发一系列新的问题;主要与如何处理绑定字符有关,但只要说它破坏了大多数 alt 绑定(以及更多)就足够了,直到 return 被击中几次。

4

2 回答 2

1

最后,最好的答案被证明是烹饪 tty 并手动打开 echo,然后将 tty 设置恢复到我开始时的位置:

def _get_terminal_settings():                                                      
  proc = subprocess.Popen(['/bin/stty', '-g'], stdout=subprocess.PIPE)             
  settings = proc.communicate()[0]                                                 
  os.system('stty cooked echo')                                                    
  return settings                                                                  

def _set_terminal_settings(settings):                                              
  os.system('stty %s' % settings)    

...
...
settings = _get_terminal_settings()
user_input = sys.stdin.readline()
_set_terminal_settings(settings)
...
...

您应该能够以您选择的任何语言执行此操作。

如果您对为什么需要这种精神错乱感到好奇,我鼓励您阅读上面我添加的链接(在 EDIT 下)。这篇文章没有涵盖任何足够的细节,但你至少会比我刚开始时了解的更多。

于 2013-06-06T23:01:58.500 回答
0

嗯,我的猜测是,当您按下 [Alt-H] 时,python 脚本正在运行并等待来自标准输入的输入,但它的标准输入范围与调用脚本的标准输入范围不同。当您输入某些内容时,它会转到 Bash 脚本标准输入,而不是 python。也许寻找一种“反向管道”或将标准输入从 bash shell 转发到被调用脚本的标准输入的方法?

编辑:

好的,我研究了一下,看起来管道可能会起作用。这是一个非常有用的链接: bash - 将第二个脚本的特定输出重定向回第一个程序的标准输入?

于 2013-06-04T22:55:29.370 回答