Thanks for that tip - clever! I got it to work using System.cmd("terminator", ["-x", "vim", "/path/to/file"]) But this approach doesn’t work over ssh, and requires the script to know what terminal program is installed.
Still looking for an exec solution that launches the editor in the console. This is simple in bash or ruby - can it be done in elixir/erlang?
I spent a while playing with this and couldn’t find a way to make it work - I can really understand the need for this so it’s sad it doesn’t seem possible. I deleted my previous post as it turned out to be unhelpful
Maybe someone more experienced with elixir internals will come and offer you a holy grail .
You can do something else if you really want. You can run the vim in tmux in background detached mode, and then attach it into different console/ssh conection like:
$ tmux new -d -s foo vim # convert this to System.cmd from elixir
$ tmux attach -t foo # execute this from different console as the same user
Can confirm System.cmd "tmux" ["split-window"] works. Given that, we have many tmux scripting options - nice idea!!
You can detect that you are running under a tmux session using System.get_env("TMUX"). So if running under tmux, launch the editor, otherwise show an error message. That will work.
Still - it would be nicer to drop the tmux dependency and just exec vim like you can do in Bash or Ruby. Can anyone confirm if this is possible in Elixir? Or if not possible, explain why?
Ok–see “output is not to a terminal”, “input is not from a
terminal”–that’s the more specific I was thinking of. I don’t have an
ubuntu image handy to test this but I did just try this with emacs on
Windows and it works just fine.
System.cmd “/usr/bin/emacs/bin/runemacs”, []
Yes I know I’m discussing Windows vs Ubuntu and vim vs. emacs- but since
you seemed to be asking how to open the editor in general this does seem an
appropriate test. If on the other hand you’re asking for more than simply
opening up the editor then again please add more detail to your question.
My point is that I don’t think the problem is System.cmd; System.cmd works
just fine. I think the issue is that you’re trying to do more than just
fire up vim and that’s fine but that seems to be an issue with Vim–not
Elixir. Check this link
for that “Output is not to a terminal” message. And here
for more on “Input is not from a terminal”.
Basically it looks as if you’re trying to do more than simply start Vim
(perhaps unintentionally) and if that’s the case then you need to spell out
what it is that you’re trying to do. At any rate I don’t think this is an
Elixir issue.
You’re showing your windows bias. There is actually a real problem here; processes run by System.cmd on unix based systems don’t have a tty attached to stdin/stdout. You can’t run anything that needs “editor like” access to the tty.( at least with the default settings).
There are a bunch of ways to get around this ( xterm -c , tmux, etc… ), but System.cmd has some real limitations on unix compared to languages like Ruby. You can easily open an editor in a windowing environment (tmux is ascii windows more or less ), but in the classic glass tty mode, you can’t.
To be honest, wanting to do this kind of seems like a screwhammer approach, but regardless there isn’t a straightforward way to open a tty based editor on unix on the BEAM. We aren’t doing any favors to anybody in pretending that the problem doesn’t exist.
Even if the tty was accessible System.cmd doesn’t have the correct semantics to work with an editor. It doesn’t work with ed for example, because System.cmd is meant to run a command and capture stdout. It swallows all stdout until the process exits.
The other issue I can think off the top of my head is that by default I/O is line based from STDIN. (i.e. the stdin I/O handler does not send input to a process until \n is entered). There are ways to enable char based input to do curses like apps. (Does anyone out there remember line-mode telnet?)
There is no direct interface to fork/exec available on the BEAM. Ports come close, but they use stdin/out of the sub-process to communicate. I’m not sure there’s any way access the tty of the controlling BEAM process.
If you REALLY need to use an editor, I’d suggest running the escript as a subprocess of another scripting language and capture the output of the escript using various expect style libraries.
Have the escript output “edit filename”, and the wrapper script edit the file. The escript should wait for input like “edit filename done” and the wrapper will need to send that when finished.
Does all that feel like pounding screws with a hammer? 'Cause as much as I really like using Elixir for cli type stuff, there are some problems that it just doesn’t match up well with.
Thanks for your feedback. Seems like launching an editor or any type of curses interface isn’t going to happen direct from Escript.
Besides this I/O issue, I find Elixir to be very nice for building CLI. My Escripts tend to have a very thin ‘CLI’ layer, very decoupled from the app. It would be simple to write a CLI layer in another language, at the cost of extra complexity in distribution & installation.
James Smith (not sure if he’s on the forum) gave a talk at the first ElixirConf in which he drove a rogue-like game via Elixir. I think it was with ports. That might give you some more ideas to try.
Not really my windows bias Booker–my ignorance of behavior on *nix. I
just assumed that if Windows was capable of handling this then surely *nix
would be. My bad for making an assumption.
As ex_top demonstrates, https://github.com/utkarshkukreti/ex_top, you can certainly use curses from within Elixir. So I guess you could port a minimal editor environment to Elixir.
I’m not sure NIFS would help all that much. You need to dup stdin/out or somehow grab access to the process groups ttys.
The question of it becomes “how do you launch an editor when you don’t have stdin/stdout?” in essence.
Being that, do you prefer a GUI editor, or a terminal editor? And if a terminal editor do you want a new tab? Or if a console editor would another tmux session be fine?
A terminal editor is fine. My issue is that this tool that I am making will be available and used by all the devs in my organization. I can’t be sure that everyone has and is running a tmux session.