我正在尝试将我的一个小python脚本移植到nim。核心是对 fzf 的调用:
fzf = subprocess.Popen(["fzf"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
stdout, stderr = fzf.communicate(some_data)
据我了解,fzf 开放/dev/tty
与用户进行交互,并使用 stdin/stdout 与调用它的程序进行通信。腐蚀性尼姆密码:
var p = startProcess(path_to_fzf)
var stream = p.inputStream()
stream.write(some_data)
stream.flush()
但是在我的 nim 版本中,fzf TUI 没有出现。但是会读取终端的输入,因为根据我的输入选择了正确的项目。
我不知道为什么会这样。我想也许 nim 会创建一个带有startProcess
的 PTY,但/proc/sys/kernel/pty/nr
不会增加,所以我认为情况并非如此。我尝试用-d:useFork
编译,因为..好吧,不知道为什么应该解决它,但它没有。据我了解 fzf/terminal/tty 不应该真的可以做些什么来阻止 fzf 写入/dev/tty
。或者也许 python 做了一些我不知道的事情,触发 fzf 显示它的 TUI?
所以我的问题是如何说服 fzf 从 nim 展示其 TUI(以及为什么/如何还没有(。
作为一个正确的答案,我在osproc
模块中找到了poParentStreams
的选项。可以这样使用它来启动 TUI:
import osproc
let process = startProcess("htop", options = {poParentStreams, poUsePath})
let eCode = process.waitForExit()
if eCode == 0:
echo "htop completed successfully"
else:
echo "htop aborted with error code: " & $eCode
@syntonym评论中指出,fzf
打开/dev/tty
是为了在不中断标准/标准输出流的情况下显示 TUI。我不完全确定为什么这在 Nim 中不起作用,但解决方案当然是将结果写入命名管道并从中读出,如下所示:
import osproc
import posix
import streams
discard mkfifo("/tmp/fzfoutput", 0o644)
let process = startProcess("echo "hellonworld" | fzf > /tmp/fzfoutput", options = {poUsePath, poEvalCommand, poParentStreams})
var f: File
discard f.open("/tmp/fzfoutput")
echo "Output of fzf:" & f.readLine()
let eCode = process.waitForExit()
if eCode == 0:
echo "fzf completed successfully"
else:
echo "fzf aborted with error code: " & $eCode
discard execCmd("rm /tmp/fzfoutput")