背景: 我有一个 python 程序,它导入并使用 readline 模块来构建一个自制的命令行界面。我有第二个 python 程序(围绕 bottle 构建,一个 web 微框架)充当该 CLI 的前端。第二个 python 程序打开一个类似于管道的接口(interface)到第一个,实质上是在两者之间来回传递用户输入和 CLI 输出。
问题:在外部包装程序(Web 界面)中,每当最终用户按下 TAB 键(或我绑定(bind) readline completer 函数的任何其他键)时,都会插入该键进入 CLI 的 stdin without 触发 readline completer 函数。我需要它来触发 readline 的命令完成功能,这通常发生在交互式 CLI session 期间。
可能的解决方案#1:是否有某种方法可以将 TAB 键发送到子进程的标准输入,以便批处理使用与交互式使用一样?
可能的解决方案 #2: 或者,如果有某种方法可以手动触发整个完成过程(包括匹配生成 和显示) ,我可以插入并扫描一个特殊的文本序列,比如 "<TAB_KEY_HERE>" , 手动触发可能的完成匹配 display 功能。 (我编写了 completer 函数,它生成可能的匹配项,所以我真正需要的是访问 readline 的函数来显示可能的匹配项。)
可能的解决方案 #3: 我想,如果我无法访问 readline 的 matches-display 函数,最后一个选择是重写 readline 的内置显示完成函数,这样我就可以直接调用它。 :(
有更好的解决方案吗?关于遵循上述任何解决方案提出的路径有什么建议吗?我被困在 #1 和 #2 上,我试图避免 #3。
谢谢!
请您参考如下方法:
解决方案 #1 被证明是一种可行的方法。关键是不将网络套接字直接连接到 CLI 应用程序。显然,readline 正在退回到一些更简单的模式,过滤掉所有 TAB,因为它没有连接到真正的 PTY/TTY。 (我可能记不太清了。许多蜘蛛网已经形成。)相反,需要打开 PTY/TTY 对并将其插入 CLI 应用程序和网络套接字应用程序之间,这会诱使 CLI 应用程序认为它已连接到一个真正的基于键盘的终端,像这样:
import pty
masterPTY, slaveTTY = pty.openpty()
appHandle = subprocess.Popen(
['/bin/python', 'myapp.py'],
shell=False,
stdin=slaveTTY,
stdout=slaveTTY,
stderr=slaveTTY,
)
...
while True
# read output from CLI app
output = os.read(masterPTY, 1024)
...
# write output to CLI app
while input_data:
chars_written = os.write(masterPTY, input_data)
input_data = input_data[chars_written:]
...
appHandle.terminate()
os.close(masterPTY)
os.close(slaveTTY)
HTH 别人。 :)
有关更多背景信息,请参阅相关问题的答案:
