Launching Programs (example: Vim) from Haskell - haskell

Using the Turtle shell scripting library I am trying to launch a program, i.e:
shell "vim" empty
The problem is that this yields the warning Warning: Input is not from a terminal and causes Vim to lag for a few seconds before finally launching.
Questions:
Is shell the best Turtle function to launch an external program from haskell?
If so, is there any way to get around errors like the above?

You want to use functions from the process library, specifically createProcess or runProcess.
Relevant turtle thread on the issue here.
Example usage.

You could try manually setting up I/O to the vty. E.g. in bash: vim < $TTY > $TTY. I guess turtle is doing that with its own file descriptors under the hood, based on the warning, so you should be able to manually set up those redirects (or just use the command I gave via shell). You just need to make sure you've got a TTY environment var around.

Related

Linux - Open terminal for input/output

I'm coding a Rust app and since it's fairly small and there don't appear to be any stable UI frameworks, I've made it run in the console using println! and whatnot for input/output. However since this program is intended to be used by people directly after downloading from the internet (due to its use case), they're likely to just double click on it instead of navigating to their downloads directory in a terminal and running it from there.
This is a problem because on Linux, it runs in the background waiting for input and looks like it's not working. On Windows, Rust programs do open in CMD by default. (and in fact many of the search results for my question were about disabling this behavior - the exact opposite of what I want!).
So is it possible to somehow make my application open in the system's default terminal? My preferred way would be to somehow embed in the executable to open in terminal (similar to the -mconsole compiler flag on MinGW). Otherwise would it be possible to detect it's in the background and fork it into a terminal? If that's not possible then is it at least possible to detect that the app is not running in a terminal and throw up a message box telling the user to run in a terminal?
My app is cross-platform but I'm OK with writing code conditionally compiled on one OS.
One typical way would be to distribute a program.sh along with your executable. If .sh extension is bound to opening a terminal in their window manager of choice, it would open automatically. If not - it is enough of a hint for running it from the shell.
Without this file you could:
Detect if the program is already running inside a terminal can be done with isatty(). There's a crate for it.
If not, spawn the terminal app process (see process::Command) and relaunch the program with it by passing its path to the terminal command line options. As #Caesar mentioned there's a bunch of popular terminals that you might want to check for presence on Linux. If nothing is found, xterm could sometimes be a fallback.

Launch interactive shell programmatically

I need to do a interactive shell programmatically (in Node.js, but any language will do).
The most important is that I want to start a REPL of any language (node, ruby, erlang etc.) and be able to get autocompletion
pri\t
which I want to get output in stderr (for instance)
print() println() printf()
And because it's in language REPL compgen cannot be used.
I've tried many ways but it seems that it fails because shell can't be interactive while opened programmatically.
Launchin /bin/sh -i just yeilds errors like:
bash: cannot set terminal process group (XXXX): Inappropriate ioctl for device
I've heard that I can't start interactive shell without the terminal, but when doing SSH autocompletion does work which means it can be emulated in some way.
I'd appreciate Your help. I can't continue my work without finding a solution to this.
You can emulate a terminal using a pseudoterminal. This is how ssh does it. There's a lot to using a pseudoterminal though and the SO answer box isn't big enough for all of it. So check the man page for pty(7).

Temporarily quitting Gvim starts over the shell

I am on windows machine, when I temporarily change to console using :sh then back to vim with exit command and then again back to console and it starts over. this causes me to lose my previous directory. Is there other way returning back to vim won't start the shell over?
Not really
https://stackoverflow.com/a/12089631/1427295
GVIM does not retain a "handle" to the shell that launched it in a way
that allows it to send commands back to it. Because of they
synchronous execution, you also cannot launch a shell from GVIM, keep
feeding it commands while also continue working in GVIM.
I'm afraid you have to use the functionality of your window manager to
launch (and then later re-activate) a shell window, and send the
commands as keystrokes to it. On Windows, this can be done (e.g. in
VBScript) via WshShell's Run(), AppActivate() and SendKeys() methods;
there are probably similar mechanisms for window control on Linux,
too.
If you don't mind having that shell inside your GVIM (emulated, with
all its drawbacks), though, there are plugins that enable that.
https://serverfault.com/a/95405
The Windows command interpreter ("cmd.exe") doesn't provide any
support for saving/exporting/keeping history, of, if it does,
Microsoft didn't document it and nobody was ever able to find it. You
can of course try to work around that, like Sean suggested, but
there's (or does appear to be) no built-in support for this
You may be able to output your command history using echo %cd% > prev_dir.txt then create a script that cds to the directory in prev_dir.txt, but you'd still have to remember to save your directory to the file before you exit the shell each time.

starting program in new terminal window

I have a program that needs to start another program. On my mac I did this using system("open path"), but on linux that doesn't work. and using system(./path) is not what I want since than it overtakes the running program.
So is there any way to get the same behaviour as the mac 'open path' command on linux?
(linux noob btw:p)
If you're running the application in a GUI environment, this should be possible but the approach is different. You need to start a new terminal instance explicitly.
Determine the path to your terminal application. This depends on the linux distribution.
Next, check the documentation of that particular terminal application and find out how it can be started to run an application (your application) instead of a shell. This probably involves using some application-specific command line options. Test that in a terminal window, until you have a command line that gives you the desired result. Things could get a little tricky if your application needs command line arguments as well. Use the -- option where necessary.
Then, all you need to do is run that command line from your "parent" application. I would advise however to not use system(). The exec... family functions (using fork and wait) provide better control.

getting a program to return immediately at the command line so it's not tied to the shell that launched it

Some programs return immediately when launched from the command line, Firefox for example. Most utilities (and all the programs I've written) are tied to the shell that created them. If you control-c the command line, the program's dead.
What do you have to add to a program or a shell script to get the return-immediately behavior? I guess I'm asking two questions there, one for shell scripts and one for general, if they're different. I would be particularly interested to know if there's a way to get an executable jar to do it.
I'm almost embarrassed to ask that one but I can't find the answer myself.
Thanks!
start cmd
on Windows,
cmd &
on *nux
Here substitute
cmd = java -jar JarFile.jar
On *nux the fg and bg commands are your friends as well ...
You need to basically need to fork a process or create a new thread (or pretend to)
in *nux you can do this with an & after the command like this /long/script & or in windows you can create a BATCH file that executes your processes then exits (it does this naturally).
NOTE: there's no particularly good way to reference this process after you're forked it, basically only ps for the process list. if you want to be able to see what the process is doing, check out using screen (another linux command) that will start a session for you and let you "re-attach" to the screen.
to do this, install screen (sudo apt-get install screen or yum install screen). then type screen to create a new session (note, it will look like you didn't do anything). then, run your /long/command (without the &), then press CTRL + A + D (at the same time) to detach from it (it's still running!). then, when you want to re-attach, type screen -r.
Additionally, look for flags in any help message that allow you do this without using the above options (for instance in synergy you can say synergy --background)
A wrapper script consisting of nothing but:
your_prog_or_script &
Will launch the target and exit immediately. You can add nohup to the beginning of that line so it will continue running if the shell is exited.
For an executable program (as opposed to a shell script), on Linux/Unix use fork() and exec() and then exit the parent process, which will return to the shell. For details see the man pages, or some page like http://www.yolinux.com/TUTORIALS/ForkExecProcesses.html.

Resources