从 nim 调用 fzf 不显示 fzfs TUI

Calling fzf from nim doesn't show fzfs TUI

我正在尝试将我的 python 小脚本移植到 nim。核心是调用fzf:

fzf = subprocess.Popen(["fzf"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
stdout, stderr = fzf.communicate(some_data)

据我了解,fzf 打开 /dev/tty 与用户进行交互,并使用 stdin/stdout 与调用它的程序进行通信。对应的nim代码:

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,nim 真的不应该做些什么来阻止 fzf 写入 /dev/tty。或者 python 做了一些我不知道的事情会触发 fzf 显示它的 TUI?

所以我的问题是如何说服 fzf 从 nim 显示它的 TUI(why/how 它还没有)。

作为正确答案,我在 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 是为了在不中断 stdin/stdout 流程的情况下显示 TUI。我不完全确定为什么这在 Nim 中不起作用,但解决方案当然是将结果写入命名管道并从中读出,如下所示:

import osproc
import posix
import streams

discard mkfifo("/tmp/fzfoutput", 0o644)
let process = startProcess("echo \"hello\nworld\" | 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")