Вызов fzf из nim не показывает fzfs TUI
Я пытаюсь перенести небольшой скрипт на python в nim. Ядро - это вызов fzf:
fzf = subprocess.Popen(["fzf"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
stdout, stderr = fzf.communicate(some_data)
Насколько я понимаю фзф открытый /dev/tty
чтобы взаимодействовать с пользователем и использует stdin/stdout для связи с вызывающей его программой. Соответствующий код NIM:
var p = startProcess(path_to_fzf)
var stream = p.inputStream()
stream.write(some_data)
stream.flush()
Но в моей версии NIM FZF TUI не появляется. Но ввод в терминал читается, потому что на основании моего ввода выбран правильный пункт.
Я понятия не имею, почему это может иметь место. Я думал, может быть, Ним создает PTY с startProcess
но /proc/sys/kernel/pty/nr
не увеличивается, так что я думаю, что это не так. Я попытался скомпилировать с -d:useFork
потому что.. ну не знаю, почему это должно это исправить, и это не так. Насколько я понимаю, fzf/terminal/tty на самом деле не должно быть чего-то такого, что nim мог бы сделать, чтобы fzf не мог писать в /dev/tty
, Или, может быть, python делает что-то, о чем я не знаю, что fzf вызывает его TUI?
Поэтому мой вопрос заключается в том, как убедить fzf показать свой TUI из nim (и почему / как он этого не делает).
1 ответ
В качестве правильного ответа я нашел вариант poParentStreams
в osproc
модуль. Его можно использовать для запуска 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, не нарушая поток stdin / stdout. Я не совсем уверен, почему это не работает в 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")