Consider integrating the following code:
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# Ctrl+Z
# βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# - On an empty command line, runs bg (so that Ctrl+Z Ctrl+Z suspends a program and immediately resumes it in the background).
# - On a non-empty command line, suspend the current command edition: let me type another command, and when that second command line finished, I get back the first command to edit.
fancy-ctrl-z() {
if [[ $#BUFFER -eq 0 ]]; then
bg
zle redisplay
else
zle push-input
fi
}
zle -N fancy-ctrl-z
I believe that there is something like this available mapped to CTRL+Q.
@sorin-ionescu Is CTRL+Q still mapped to this function? I can't get it to work.
I have tried this from Vim and nothing happened (expected Vim to suspend) and from zsh after suspending Vim (expected Vim to resume).
This is what I currently have in my zshrc:
function fancy-ctrl-z()
{
if [[ $#BUFFER -eq 0 ]]
then
bg
zle redisplay
else
zle push-line-or-edit
fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
Only significant difference is that I've chosen to use zle push-line-or-edit instead or push-input and have the bindkey operation at the bottom. Haven't used this in a while (primarily used to use it for vim but since switching to MacVim it's gathered dust) but I tried it out on my setup.
The function does work if I run sleep 10 but from some reason it doesn't not work for vim. I'm not sure why. The function will exit vim to the command line but I must use fg to get back into vim.
Also, the CTRL+Q is (was?) located here:
prezto/modules/editor/init.zsh
291: for key in "$key_info[Control]Q" "$key_info[Escape]"{q,Q}
I see. I had similar code in my zshrc until I reverted to stock prezto earlier today:
# Allow returning to Vim by pressing Ctrl+Z
fancy-ctrl-z () {
if [[ $#BUFFER -eq 0 ]]; then
BUFFER="fg"
zle accept-line
else
zle push-input
zle clear-screen
fi
}
zle -N fancy-ctrl-z
bindkey '^Z' fancy-ctrl-z
I know it's not on topic, but would you mind explaining the differences between push-input and push-line-or-edit? And why does mine use BUFFER="FG", while yours uses bg? bg (which I assume means 'background') makes a lot more sense there. I'm a beginner and didn't write the code myself, but rather blindly copied it from a blog post, so I don't understand it all. And I'm assuming the bindkey line is just binding CTRL+Z to the function method. Would the original post work as intended without that line?
As I still primarily use Vim in the terminal, getting this to work would be very nice. Of course, CTRL+Z to suspend and fg to resume isn't such a hassle, it's just not nearly as convenient as pressing the same keys twice.
I guess the point is if Ctrl+Q does not work as intended, we should make it work or provide an alternative. It doesn't really matter if the we call it "fancy-ctrl-z" or "fancy-ctrl-q" as long as one of them works.
For reference, here is the Ctrl+Q line (it's still there and still the same as the line you posted, just moved up). I know I'm a beginner and all, but I don't see how this has the suspend and resume function of fancy-ctrl-z. It seems to me like it's only one way because it only does push-line-or-edit.
@ethanmad Sorry for the (very) late reply but I hope this helps!
I think I can clear some of this up. Let's walk through the logic:
Create a new function that can be called by the shell:
function fancy-ctrl-z()
{
...
}
Make the function into a widget that can be used by the editor:
zle -N fancy-ctrl-z
Assign a shortcut to the widget so that it can be called:
bindkey '^Z' fancy-ctrl-z
Now, let's look at the function's logic:
function fancy-ctrl-z()
{
if [[ $#BUFFER -eq 0 ]]
then
... # I'm currently in a program like vim
else
... # I'm currently editing the command line
fi
}
If I'm in vim (or similar) and I press Ctrl + z, two things happen:
bg sends vim to backgroundzle redisplay brings you back to the zsh line editorIf I'm on the command line, zle push-line-or-edit executes. As described by the manual:
At the top-level (PS1) prompt, equivalent to push-line. At a secondary (PS2) prompt, move the entire current multiline construct into the editor buffer. The latter is equivalent to push-input followed by get-line.
In effect, this means that if I start to run command foo (and haven't executed it) but remember that I need to run bar first, calling our widget with Ctrl + z will save what I've typed, give me a clean line to execute bar, and upon completion, place the unexecuted text that I started to type for the command foo back on the line editor. Very useful!
Hope this helps!
@chauncey-garrett Thank you! Makes sense now.
I like that this (CTRL+Z) suspends vim unlike the current implementation (CTRL+Q).
@leoj3n That's what I end up using it for the most! :)
@sorin-ionescu Please consider reopening this enhancement or please explain why not.
As @ethanmad pointed out, it would be nice if pressing CTRL+Z undid the backgrounding.
Yes, that's the goal of the function. I think CTRL + Q only quits the
current application. The function as described by Chauncey is probably what
should be implemented, though my posted code works as well.
CTRL+Q does not quit the current application. It copies the currently written command into a buffer, blanks the command line to allow the user to write another command then pastes the original command back on the command line after execution.
When is it useful? Let us say that you wrote a command that you are about to execute only to realise that you are in the wrong directory. Press CTRL+Q, change directories, then your command will be ready for execution.
I see, CTRL + Q is actually really useful. Having now tried it, it will definitely become one of my more common shortcuts.
CTRL + Z is similar in purpose, but for applications rather than commands.
@ethanmad CTRL+Z is functionally the same as CTRL+Q but with the added functionality of backgrounding the current process if one is running.
Yep, that's correct:
# Use a more flexible push-line.
for key in "$key_info[Control]Q" "$key_info[Escape]"{q,Q}
bindkey -M "$keymap" "$key" push-line-or-edit
For what it's worth, when I originally opened this issue, I was unaware that the CTRL+Q functionality existed.
While I do find my CTRL+Z very useful, it may be too hacky for prezto (which, as @sorin-ionescu has specifically stated, is to contain _sane_ defaultsβwhich I greatly appreciate). At this point the issue here boils down to whether or not allowing the current process to be sent to the background with a global keyboard shortcut is a _sane_ idea.
I haven't come across an occurrence where doing so has been an issue for me but I can imagine the keybinding could cause problems _somewhere_.
Overriding CTRL+Z, one of the most used commands does not seem wise.
On Wed, Apr 15, 2015 at 22:16 Joel Kuzmarski [email protected]
wrote:
@ethanmad https://github.com/ethanmad CTRL+Z is functionally the same
as CTRL+Q but with the added functionality of backgrounding the current
process if one is running.β
Reply to this email directly or view it on GitHub
https://github.com/sorin-ionescu/prezto/issues/438#issuecomment-93618928
.
@chauncey-garrett, @leoj3n, @sorin-ionescu Now that I understand what Ctrl-Z does, I want to use this command as-is without overloading it to do the unbackgrounding. The command fg to bring a task back into the foreground makes more sense to me. Thanks