2

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

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

据我了解,fzf open/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 可能会创建一个 PTYstartProcess/proc/sys/kernel/pty/nr不会增加,所以我认为情况并非如此。我尝试编译,-d:useFork因为.. 不知道为什么要修复它,但它没有。据我了解 fzf/terminal/tty 不应该真的有 nim 可以做的事情来阻止 fzf 写入/dev/tty. 或者也许 python 做了一些我不知道的事情会触发 fzf 来显示它的 TUI?

所以我的问题是如何说服 fzf 从 nim 显示其 TUI(以及为什么/如何还没有)。

4

1 回答 1

1

作为正确答案,我poParentStreamsosproc模块中找到了该选项。可以像这样使用它来启动 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

fzf@syntonym 在打开的评论中指出/dev/tty,以便在不中断标准输入/标准输出流程的情况下显示 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")
于 2018-08-20T21:43:24.560 回答