I already posted this on reddit https://www.reddit.com/r/nim/comments/9x641g/how_to_run_vim_and_get_output/
I was trying to use osproc to run vim and grab the text the user entered but it just crashes.
let (output, err) = osproc.execCmdEx("vim", options = { poParentStreams })
Any pointers?
Maybe you want something like:
import os, osproc, posix, strutils
proc userEditString(content = "", editor = "vim"): string =
let tmpPath = getTempDir() / "userEditString"
let tmpFile = tmpPath / $getpid()
createDir tmpPath
writeFile tmpFile, content
let err = execCmd(editor & " " & tmpFile)
return tmpFile.readFile
when isMainModule:
var s = "Vim him Nim, Jim?"
echo "\n\n(Press `i` for insert mode, edit, then <esc> and `ZZ`.)\n\n"
echo "Original: ", s
s = s.userEditString
echo "Modified: ", s.strip
Having a conversation in two places at once is annoying, and I think this forum is much more valuable than Reddit, so I'll reply here:
Oh. Awesome! Thank you. I have been traveling with the family for the holidays so haven’t been checking. I’ll test it as soon as I can. Knew I should have been using a tempfile, but I didn’t bother since I figured the issue with the Error was unrelated.
Do you know what is different about ‘execCmd’ that makes this work?
It's first important to understand how Unix terminals and pipes operate. A pipe is a simple one-directional stream of text, mainly designed for programs that dump output and exit, like dmesg | less. Running vim | less gives you a warning, "output not to a terminal", and then it's a mess until you exit.
Vim is an interactive program that clears the screen, moves the cursor around, and interacts with the user until s\he exits. Vim can even let you edit multiple files, split the screen, show auto-suggest drop-downs, run other programs, etc. (Same for emacs, nano, mc, etc.) What it sends to stdout is a hodgepodge of strings and ANSI / control characters. Vim doesn't dump the full file(s) to stdout, but to the filesystem when you save.
Nim's execCmdEx runs the process as a pipe, captures any output it sends, and waits for it to terminate - which Vim, being an interactive program, doesn't do until it gets user keystrokes for quitting.
execCmd runs the program normally (manual says: "standard input, output, error streams are inherited from the calling process"), so that it can interact with the screen until it terminates.
Thanks for following up to the reddit question here. I have two children under three and no brain power right or free time right now so I lose track of things often.
With regards to vim, I am a daily user so I should have immediately realized it doesn't write the file to stdout rather just its UI when I wrote that. But I was in hurry so I wrote it assuming it would be wrong but not crash the program. The option I used above poParentStreams sounds like it should make the process inherit stdin/out/error from the parent process so I was assuming that It would work. Which it did partly, vim was able to display its interface. That was why it was a little confusing that it crashed when I pressed any key in vim. I'm sure there is a good explanation for why the process spawned couldn't access whatever stream the error referred too (it was ambiguous in the error message though I'm assuming it meant stdin or stdout) However it doesn't help me to know why at this point. If you happen to have an idea, I am very curious, either way I appreciate the help and explanations given here.