4

Often I find myself partway through writing a long command (or chain of commands) and realise I need to run another command before I can finish typing out this current one.

Examples

Sometimes, I...

  • Need to find the exact name of a network interface (wlp2s0b1 -- blargh);
  • Need to check the documentation of a command;
  • Need to start a daemon (with systemctl,service, etc) before I can communicate with it;
  • Need to sudo ls a directory if I'm performing a command with sudo and tab-completion isn't working because I don't have permission in the directory I'm operating in.

I guess the ideal solution for me would be a keyboard shortcut that pushes my current command to a stack and empties the line, and another command that pops the top command from that stack into the input line.

Kinda-sorta-solutions that I currently use:

  • Use my mouse to select the command in the terminal (if I even have a graphical terminal available) and copy it, pasting when ready (slow);
  • Press enter (hoping that the command just fails than deleting things) and use to get back up to it (dangerous);
  • Type it out again (time-consuming)

Any suggestions for how I could better accomplish this? I use zsh where I can, but a solution that works on bash as well would be appreciated.

  • 3
    I don't know how to do this with zsh, but in bash you can type alt-#, and the current line will have a # prepended and then be entered. Later you can fish the command out of the history, finish it, and delete the # – rici Mar 23 '15 at 02:16
  • @rici - I'm pretty sure that's how you do it in zsh too. In any POSIX shell you can do the same in vi mode with ESC-#. Another possibility is to the shell's kill-buffer if it offers one - CTRL+U will usually cut from cursor to head of line, CTRL+K from cursor to end, and CTRL+W from cursor back one word. zsh and bash at least save cuts like that in a kill-ring - so you can paste it back in later (several commands later if wanted) with CTRL+Y. – mikeserv Mar 23 '15 at 05:47
  • @mikeserv: I tried it with zsh, but it didn't do anything. Perhaps it's the zsh settings I'm using. I hardly ever use zsh interactively. The kill-ring is a good idea, but keeping the lines in the history is handy for searching, so I'm used to doing it that way. – rici Mar 23 '15 at 05:56
  • @rici - yeah - I often combine the two. zsh's line-editor will cuts to newline boundaries - so I can edit commands in pieces on the command-line cutting one or two lines out of one history command, pasting it into a new one, scrolling back to find a different command, cutting out of it, then forward again to paste in some more. It's almost the only reason I use zsh. – mikeserv Mar 23 '15 at 05:59
  • Sorry guys, turns out the answer is staring at me from the sidebar of this question! I need to work on my Googling skills… existing question is here: http://unix.stackexchange.com/questions/10825/remember-a-half-typed-command-while-i-check-something?rq=1 – JJJollyjim Mar 23 '15 at 06:58
  • i just leave the command half-typed and switch to a new window – Skaperen Mar 23 '15 at 09:30

2 Answers2

2

For zsh there are three widgets, which can bound to that effect: push-input, push-line and push-line-or-edit (see man 1 zshzle for more information). On the top-level prompt (PS1) they behave the same: The current buffer is pushed onto the buffer stack and then cleared. On the next promp (or when calling the widget get-line) the buffer will be popped of the stack and loadet into the editing buffer. That also means that you can put multiple commands on hold.

By default push-line is bound to ^Q (Ctrl+q, might not work), ^[Q (Alt+Shift+q or Esc,Shift+q) and ^[q (Alt+q or Esc,q). But you can easily bind it to another combination with bindkey. For example for Alt+h:

bindkey '^[h' push-line

As told, these three widget behave the same on the top-level prompt. But they do differ if it is a multiline input second-level prompt (PS2).

  • push-input

    always pushes the complete multiline construct onto the buffer. That is everything since the last top-level prompt. You are returned to the top-level prompt.

  • push-line

    only pushes the current line onto the buffer. That is everything since the last prompt. You remain at the same prompt level.

  • push-line-or-edit

    pushes the entire current multiline construct into the editor buffer (not the stack). It essentially does what push-input does but immediatelly pops the buffer from the stack again.


The counter-part to these widgets is get-line, which pops the top line from the buffer and inserts it at the cursor position. In Emacs mode it is bound to ^[G (Alt+Shift+g or Esc,Shift+g) and ^[g (Alt+g or Esc,g)


To use push-line-or-edit effectively, you should know (or want to learn) some commands needed to edit a command line (copy and paste on words and lines, insert new line (without running the command), etc.). Otherwise, I would suggest using push-line and/or push-input.

Adaephon
  • 4,456
1

Why not just use a second shell to check for details? I use screen for that, or just switch to a second desktop where I (usually) also have an open shell. This way, I only spend one extra shortcut to switch to the backup shell and one more to switch back.

Of course, this technique won't work in the last case you describe, because my second shell won't have the same working directory as the first one.