Why does killing IPython leave the terminal in "raw" mode? - terminal

I've noticed that when I embed IPython in a Python script with IPython.embed() and then script crashes for some reason while IPython is embedded (in my case, another library called from the script would occasionally segfault), that the terminal is then left in a "raw" mode. In particular, the command stty now shows -isig among other options that were not previously present before running the script, which means that Ctrl-C is not passed along as a signal.
I can also reproduce this behaviour more simply, by just starting IPython in the terminal and then killing it by PID from another terminal. This behaviour does not happen, however, if --simple-prompt is used.
Thus my questions:
What exactly is IPython doing under the hood to my terminal settings and why does it do this?
Is there a way to gracefully restore the original terminal settings when IPython is killed?

Related

How to correctly emulate terminal in linux/macOS using exex(go)?

I need to emulate a terminal in go. I try to do it like this:
lsCmd := exec.Command("bash", "-c", "ls")
lsOut, err := lsCmd.Output()
if err != nil {
panic(err)
}
fmt.Println(string(lsOut))
And it seems to work correctly (the native ubuntu terminal displays a horizontal list, and the result of this function goes vertically).
But if I specifically call the wrong command, for example exec.Command ("bash", "-c", "lss"), I get:
panic: exit status 127
And in the native ubuntu terminal I get the following result:
Command 'lss' not found, did you mean:
and enumeration of commands.
I need to communicate with the native terminal, and get the same thing as the result of the command if I wrote the command in the standard ubuntu terminal.
What is the best way to do this? Maybe the exec library is not suitable for this? All this is necessary for front-end communication with the OS terminal. On a simple html/css/js page, the user enters a command, after go it sends it to the native terminal of the operating system and returns the result to the front-end.
How I can get the same result of executing commands as if I were working in a native terminal?
The problem
But if I specifically call the wrong command, for example exec.Command
("bash", "-c", "lss"), I get:
panic: exit status 127
And in the native ubuntu terminal I get the following result:
Command 'lss' not found, did you mean:
and enumeration of commands.
This has nothing to do with Go, and the problem is actually two-fold:
Ubuntu ships with a special package, command-not-found, which is usually preinstalled, which tries make terminal more friently for mere mortals by employing two techniques:
It tries to suggest corrections for misspellings (your case).
It tries to suggest packages to install when the user tries to execute a program which would have been be available if the user had a specific package installed.
When the command is not found, "plain" (see below) shell fails the attempt by returning a non-zero exit code.
This is absolutely expected and normal.
I mean, panicking on it is absolutely unwise.
There's a historical difference on how a shell is run on a Unix system.
When a user logs into the system (remember that back in the days the concept of the shell was invented you'd be logging in via a hardware computer terminal which was basically what your GNOME Terminal window is but in hardware, and connected over a wire),
the so-called login shell is started.
The primary idea of a logic shell is to provide interactive environment for the user.
But as you surely know, shells are also capable of executing scripts.
When a shell executes a script, it's running in a non-interactive mode.
The modes a Unix shell can work in
Now let's dig deeper into that thing about interactive vs non-interactive shells.
In the interactive mode:
The shell is usually connected to a real terminal (either hadrware or a terminal emulator; your GNOME Terminal window is a terminal emulator).
"Connected" means that the shell's standard I/O streams are connected to the terminal, so that what the shell prints is displayed by the terminal.
It enables certain bells and whistles for the user, usually providind limited means for editing what is being input (bash, for instance, engages GNU readline.
In the non-interactive mode:
The shell's standard I/O streams are connected to some files (or to "nowhere" — like /dev/null).
No bells and whistles are enabled — as there is nobody to make use of them.
GNU bash is able to run in both modes, and which mode it runs in depends
on how it was invoked.
When initializing in different modes, bash reads different initialization scripts, and this explains why the machinery provided by the command-not-found package gets engaged in the interactive mode and does not when bash is run otherwise — like in your invocation from Go.
What do do about the problem
The simplest thing to try is to run bash with the --login command-line option or otherwise make it think it runs as an interactive shell.
This might solve the problem for your case but not necessarily.
The next possible problem is that some programs do really check whether they're running at a terminal — usually these are programs which insist on real interaction with the user, usually for security purposes, and there are programs which simply cannot run when not connected to a real terminal — these are "full-screen" text UI programs such as GNU Midnight Commander, Vim, Emacs, GNU Nano and anything like this.
To solve this problem, the only solution is to run the shell in a pseudo-terminal environment, and that's what #eudore hinted at in their comment.
The github.com/creack/pty might be a package to start looking at; golang.org/x/crypto/ssh also provides some means to wrangle PTYs.

My emacs client automagically terminates when switching applications [OSX iTerm2]

I try to be brave and switch from vi to emacs.
Now, I set up Emacs 26 on macOS via homebrew and start Emacs as daemon in the background.
I can use files using emacsclient -t. However, whenever I bring the Terminal into the background emacsclient exits within a few seconds.
See example Video here: https://cloud.familie-ganter.de/s/QwbK8cFBHnPjQ4d
I did a plain install. My init file does not contain anything except what you see in the video. The funny thing is whenever I start emacs directly in the Terminal, nothing at all happens when bringing it to the background.
What seems to be the problem?
I am lost …
I expect it to be something dumb and simple -- so please be nice, this is my first stackoverflow post.

How to save a Python 2 idle/shell/command prompt interactive session on Windows?

I run calculations on Windows for hours and would like to have the calculation report/log inside the interactive IDLE/shell window be saved to a file at the end by a command.
Would be nice to exit() and close the window too.
As much as I like Linux, this is an Unattended Windows machine, hence, some modules/commands are not available, sadly, and the ability to install other software is limited.
The fact that the developers did not think of a command to save the transactions within the IDLE/shell is surprising.
I know in some environments you can direct the output of a job, like a report to another text file by using the key -o, --o, --output, > to a text file. Surprisingly Python does not support anything like that!
Any help would be appreciated
Thanks
Windows Command Prompt supports stdout redirection and probably stderr redirection. I just tested python -c "print(test)" > F:/dev/tem/out.txt and the print out went to out.txt. Replace -c "print('test') with script.py and the same should happen. Piping stdout of one program to stdin of another might work. You might be able to chain programs with a .bat file. PowerShell likely is more powerful and flexible, but I have never used it.
I am not completely clear on what you are asking, but I hope the following answers your questions.
Python runs in 2 modes: batch and interactive. Interactive mode is intended for ephermeral interaction with a human. Batch mode is for unattended computation, with occasional screen messages, but with most results sent to a file other than the screen. Both modes are combined when you run python -i xyz.py. The file is first run in batch mode, and then Python shifts to interactive mode.
It sounds like you should be using batch mode rather than either Python's or IDLE's interactive mode. If your code runs from IDLE, you should be able to run it directly with the same python.exe that you used to run IDLE. There are exceptions, of course, if one makes one's code dependent on running within IDLE, but this is unlikely to be an accident or to be needed for unattended running.
The IDLE Shell simulates interactive Python. When a file is run from an editor window, IDLE simulates python -i file-being-edited.py, with screen output going to Shell. In either case, an interactive user can save the contents of Shell with the File => Save As menu command. So there is such a command. There are also close window and exit commands and shortcuts.
In IDLE's intended use, as an interactive python learning and program development environment, there is no need from for a program to issue these commands. To save data in a file, a program can open a file and write data directly.
Try to see if you can install Jupyter Notebook (not separate software, but just a python module)
pip install jupyter
Jupyter notebook is highly helpful for saving and sharing your code. It can be used as both a shell and as a script editor.

Cannot open multiple files with Emacs on Mac

I can open a single file with Emacs, no problem. But I'm used to Emacs on Linux, where typing emacs test.cpp & would open a new Emacs frame, leaving the terminal free. On OS X, however, when I try to open a new frame with emacs test.cpp &, the terminal shows a process was created but the window fails to pop up. If I push Ctrl+C, the terminal shows "Stopped", but I see the process is still running because I can see it in the task monitor.
How to solve this problem? Thanks!
The issue here is that the command emacs on Linux is generally just the Emacs binary itself, which opens a new frame (that's Emacs-speak for X11 or other GUI window) unless you specify -nw on the command line; in contrast, the emacs command provided by Homebrew is a shell script that calls /usr/local/Cellar/emacs/24.3/Emacs.app/Contents/MacOS/Emacs -nw "$#" (substituting the version installed for 24.3). So the Homebrew version launches as a terminal app.
You can make a shell script that just runs /usr/local/Cellar/emacs/24.3/Emacs.app/Contents/MacOS/Emacs "$#", and it would behave somewhat as you expect, except that you would be launching a brand-new instance of the Mac app, which would cause an additional Emacs icon to appear on the Dock. Such a thing isn't considered "Mac-like," but it's not the end of the world.
An alternate solution, which is used a lot across different operating systems, is to make one Emacs process a server and then use emacsclient to open files from the command line. Emacsclient can open files in the current terminal, a new frame (GUI window), or an existing instance of Emacs. For an instance of Emacs to run as a server just requires that you run M-x server-start within it, or put (server-start) inside your init file (~/.emacs or ~/.emacs.d/init.el).
My Emacs config has this snippet, which starts server mode automatically when I launch the GUI app:
(when (display-graphic-p)
(server-start))
Then, once Emacs is running (you can make it autostart upon login in System Preferences > Users & Groups > Login Items), type emacsclient -nw test.cpp to open the file in the terminal, or emacsclient test.cpp & to open it in an existing frame, or emacsclient -c test.cpp & to open a new frame. (Note that if you open it in an existing frame, you use C-x # to close the buffer without closing the frame, as opposed to C-x C-c.)
Note that the terminal emacsclient command I gave just now didn't use & but the GUI ones did. & at the end of a command line puts the process in the background, meaning it's not monopolizing your terminal. For whatever reason (probably because it wouldn't be sensible to have a full-screen terminal app running in the background), when you invoke the terminal version of Emacs with &, it just suspends itself. The same thing would happen if you pressed C-z within Emacs. To get it back into the foreground, type fg (actually you can have multiple background processes, in which case fg would just pick the most recent one unless you specified a job specifier; see bash's man page (man bash) and search for JOB CONTROL if you're interested in the details).

Can't paste into MacVim

I copy text from outside of Vim. ⌘V in other apps pastes text without problem. In MacVim, it doesn't work.
In Insert Mode, nothing appears. In Normal Mode, I get E353: Nothing in register +. This happens when set clipboard=unnamed is on or off.
Oddly enough, this was working before. What's wrong?
If you are using tmux and sometimes you initially launch MacVim via the mvim command-line program, then you might be encountering the problem that prompted me to write the reattach-to-user-namespace command.
My guess is that clipboard access worked on prior occasions because you happened to have launched MacVim via a “normal” GUI method (e.g. the dock, Finder, Spotlight, etc.). The clipboard later became inaccessible after you had quit the prior instance of MacVim and relaunched it through (e.g.) mvim from inside a tmux session.
The core problem is that programs launched in certain contexts (i.e. inside a tmux session) end up with an environment that denies them access to certain services (e.g. the OS X pasteboard).
The initial launch is the important one here. New windows started by mvim-in-tmux (even without the above-linked wrapper program) should have access to the clipboard as long as MacVim was previously started “via the GUI” (maybe there are still some MacVim windows open, or maybe you have MacVim configured to keep running even when there are no windows open). Correspondingly, to regain access to the clipboard you will need to close all your existing MacVim windows, quit the application, then restart it in a way that has access to the clipboard (e.g. via the GUI, or “inside” the wrapper).
Once you have the above-linked wrapper program installed (it is also available through MacPorts and Homebrew), you can use a command like reattach-to-user-namespace mvim to ensure that if it ends up starting a new MacVim instance, then that new instance will have access to the clipboard. You might use an alias, shell function, or a script to make sure you always “wrap” mvim.
Several other commands also benefit from “wrapping” (pbpaste, pbcopy, nohup, launchctl (depending on which subcommand you are using)), so you may want to “wrap” your whole shell instead of the individual commands. The bit of the process environment that the “wrapper” modifies is inherited by child processes, so “wrapping” your shell will affect most commands you run from it. If you are using tmux, you could configure your default-command to automatically “wrap” your default tmux shells:
set-option -g default-command "reattach-to-user-namespace -l zsh"

Resources