On 11/5/24 1:21 AM, David Moberg wrote:
Den ons 16 okt. 2024 17:43Chet Ramey <chet.ra...@case.edu <mailto:chet.ra...@case.edu>> skrev:On 10/13/24 12:10 PM, David Moberg wrote: > A new issue popped up with these changes. After second time of suspend and > foreground with binding, the tty will not react to control keys but instead > print them on the prompt. In general, this can't work, given a well-behaved process like vim that modifies the tty settings. > | start vim > ctrl-z (to suspend) > ctrl-a (bound to `fg` to bring to foregound) > ctrl-z (to suspend a 2nd time) > # broken state (but I dont see anything changed in the output of `stty > -a`) > # ctrl-a prints ^A (instead of executing fg) > # <UP> prints ^[[A (Instead of invoking history) > > Issue 1: control codes are printed to prompt The important thing to remember is that the shell saves the tty settings when it starts up and after each forked command exits, so it can set them for child processes. This is how it can make stty settings stick while still setting the terminal for readline. It doesn't do this if it's running a command from a readline key binding. It restores the terminal attributes to these saved settings after a process exits due to a signal or stops so a misbehaving process doesn't corrupt the terminal. Let's use the following shorthand: R = tty settings for readline (-icanon) V = tty settings for vim (-icanon) S = tty settings shell inherited or saved (icanon) Here's what happens: shell saves tty settings S readline sets tty settings R readline reads "vim ...\n" shell sets tty to S shell execs vim vim saves tty settings S vim sets tty settings V vim reads ^Z vim sets tty settings S (saved) vim sends itself SIGTSTP shell catches stopped child shell sets tty settings S (the saved tty settings because the process stopped) readline sets tty settings R readline reads ^A shell sends SIGCONT due to running `fg' from the `bind -x' binding - this is where the shell used to save the terminal settings again for later resetting, but it no longer does due to your previous report, so S is unchanged vim gets SIGCONT vim sets tty settings V vim reads ^Z vim sets tty settings S (saved) vim sends itself SIGTSTP shell catches stopped child shell sets tty settings S (saved tty settings because the process stopped) - but it wouldn't matter because vim already set them to S readline is still active because this was all a key binding Now readline thinks the settings are R, but the settings are S.
So there is no good way of solving this and therefor no way to solve it at all?
The bind -x execution code could restore the terminal settings to icanon mode before executing the command, and then set them back to what readline is using (-icanon) before returning. This is not backwards compatible and would break all the bind -x bindings that assume the terminal is the way readline set it, so I'm not inclined to do it.
I guess fish and zsh might be misbehaving in other ways, but they seem to handle this detail better. I wonder what the tradeoff is.
Historically, zsh doesn't let child processes change the terminal settings at all. Look at the `ttyctl' builtin. I don't know what fish does. -- ``The lyf so short, the craft so long to lerne.'' - Chaucer ``Ars longa, vita brevis'' - Hippocrates Chet Ramey, UTech, CWRU c...@case.edu http://tiswww.cwru.edu/~chet/
OpenPGP_signature.asc
Description: OpenPGP digital signature