175

I switched from Bash to Zsh on Ubuntu and I'm quite happy about it. However, there is something I really miss and I did not find how to achieve the same thing.

In Bash, whenever I was typing a long command and noticed I had to run something else before, I just had to comment it out like in the following:

me@home> #mysuperlongcommand with some arguments
me@home> thecommandIhavetorunfirst #and then: up up
me@home> #mysuperlongcommand with some arguments #I just need to uncomment it!

However, this quite recurrent situation is not as easy to address as with zsh, given #mysuperlongcommand will be run as such (and resulting in: zsh: command not found: #mysuperlongcommand.

fbiville
  • 8,407
  • 7
  • 51
  • 79
  • It's also dangerous because if you put a `;` character in your comment, it will execute the proceeding commands (I just ran a rm -r operation I wasn't planning on running yet :P ). – Moshe Jonathan Gordon Radian Dec 14 '22 at 10:43

6 Answers6

248

Having just started trying out zsh, I ran into this problem too. You can do setopt interactivecomments (in your .zshrc file to make it permanent) to activate the bash-style comments.

The Z Shell Manual indicates that while this is default behavior for ksh (Korn shell) and sh (Bourne shell), and I am guessing also for bash (Bourne-again shell), it is not default for zsh (Z shell):

In the following list, options set by default in all emulations are marked <D>; those set by default only in csh, ksh, sh, or zsh emulations are marked <C>, <K>, <S>, <Z> as appropriate.

INTERACTIVE_COMMENTS (-k) <K> <S> Allow comments even in interactive shells.

user2297550
  • 3,142
  • 3
  • 28
  • 39
Lajnold
  • 3,089
  • 1
  • 18
  • 7
  • 6
    You can also do `set -k` if it's just a one off. But I'd use the `setopt` line from this answer in my zshrc – Hamish Downer Aug 25 '13 at 15:08
  • 43
    Is there a reason that this isn't the default behaviour? – naught101 Jan 27 '15 at 00:04
  • 4
    @naught101 lots of the best bits of zsh are default off. don't know why – zzapper Mar 09 '18 at 15:18
  • @naught101 maybe this should encourage people to dig down into mans and settings to make zsh their own tool as opposed to something that __just works__ – aryndin Jan 07 '21 at 12:20
  • 1
    @naught101 I like too, tho some tools don't ;) – aryndin Jan 08 '21 at 00:15
  • 1
    @aryndin, good/sane/meaningful defaults is the hallmark of usability. Besides, that argument doesn't fare well if I have to ssh into dozens of computers (where I cannot expect to find my zshrc). – sidcha Jul 08 '21 at 07:43
  • 1
    I did this at some point but the setting doesn't appear to be permanent and goes away later. Maybe if I had it to `.zshrc` it will work – Caleb Stanford Dec 30 '21 at 22:44
  • @6005 It is not permanent no. When I quite and reopen Terminal, I need to run `setopt` again. Anyone knows how to make it permanent? – Rafs Nov 07 '22 at 13:22
47

I use

bindkey "^Q" push-input

From the zsh manual:

Push the entire current multiline construct onto the buffer stack and return to the top-level (PS1) prompt. If the current parser construct is only a single line, this is exactly like push-line. Next time the editor starts up or is popped with get-line, the construct will be popped off the top of the buffer stack and loaded into the editing buffer.

So it looks like this:

> long command
Ctrl+Q => long command disappears to the stack
> forgotten command
long command reappears from stack
> long command

Also, if you set the INTERACTIVE_COMMENTS option (setopt INTERACTIVE_COMMENTS), you will be able to use comments in interactive shells like you are used to.

Michał Politowski
  • 4,288
  • 3
  • 30
  • 41
  • I like your option, but I can't make it work :( Is there a way I should write the binding in the file, or is it just two characters, ^ and Q? My command is erased, but I don't know how to make it appear again in input. – Mihnea Simian Jan 29 '14 at 10:51
  • 2
    @Mihnea if the command disappears it seems that push-input is working. It should appear back when you run the next command or just press enter. Doesn't it do that? – Michał Politowski Jan 29 '14 at 12:12
  • Silly me, i was expecting to have to press up-arrow. Thanks, great tip, ! – Mihnea Simian Jan 29 '14 at 12:23
  • Is there a way to share the stack with child processes? I often used the comment thingy with bash when I forgot to launch a screen, i.e. i did '#large command; history -a; screen' and the picked it up inside the screen from the history... – barbaz Mar 26 '14 at 18:21
  • 1
    @barbaz the stack can be manipulated with `read -z` and `print -z`, so with some scripting and temporary files you could. But then a custom zle widget for saving the command line to a temp file might be simpler, and shared history will be simpler still. – Michał Politowski Mar 27 '14 at 07:09
  • 1
    While the currently accepted answer addresses the questioner's *question*, this answer addresses the questioner's *intention*. I.e. zsh has a better way of achieving the intended result, and this is it. – wjv Apr 11 '16 at 06:52
  • 1
    This should be the accepted answer. If you use oh-my-zsh you can use Ctrl-Q for this out of the box. – Gecko Dec 01 '16 at 19:32
  • Thanks for the tip! Adding `setopt INTERACTIVE_COMMENTS` to my `~/.zshrc` file worked for me! – edlee Jul 11 '18 at 09:15
22

I find myself doing this often as well. What I do is cut the long command, execute the command that needs to go first and then paste the long command back in. This is easy: CTRL+U cuts the current command into a buffer, CTRL+Y pastes it. Works in zsh and bash.

Fredrik
  • 726
  • 4
  • 11
  • well, actually, my way is a workaround while your solution is the best fit ;) – fbiville Jul 26 '12 at 15:34
  • 4
    This shouldn't be the accepted answer. The solution below which says to use "setopt interactivecomments" should be. The reason for this is that if you just cut the current command, then it isn't in your zsh history, and also you then can't easily use cut and paste while typing in your new command without overwriting the command you were trying to save. – Douglas Mar 28 '13 at 22:36
  • 1
    Using comments and the solution in this answers are both workarounds; the push-input method posted by Michał Politowski is more correct. – Fredrik Apr 02 '13 at 12:29
11

Add the line setopt INTERACTIVE_COMMENTS to your ~/.zshrc file, save it, and relaunch the shell.

This is to clarify on @Lajnold's answer and @Hamish Downer's comment. It just took me a little bit to figure out how to make this change permanent. You probably want to add that line before exporting variables, so maybe add it toward the top of the file. I already had setopt PROMPT_SUBST in my ~/.zshrc file, so I just added it after that line. This will ensure the settings are loaded every time you launch the zsh terminal.

Juno Sprite
  • 569
  • 6
  • 12
5
: sh generate_sample.sh arg1

The addition of ":" doesn't execute the command in zsh.

sh generate_sample.sh : arg1

Now the arg1 is commented.

I am on Mac OS Big Sur and used it multiple times.

Edit: ":" procedure works with giving no spaces. ": command" is correct but ":command" isn't

Prince Patel
  • 172
  • 1
  • 4
  • 15
0

In addition to setopt interactivecomments, suggested by @Lajnold, you might also want to add something like the following to prevent certain comments from being written to history (from https://superuser.com/questions/352788/how-to-prevent-a-command-in-the-zshell-from-being-saved-into-history):

This overrides the ZSH built-in function zshaddhistory():

  • Will log comments that start in column 1 not followed by one or more spaces (i.e. #somecommand that I want to come back to)
  • Won't log comments that start in column 1 followed by one or more spaces
  • Won't log indented comments, padded by spaces from column 1
  • Won't log commands with a space in column 1 (handy shortcut for running commands that you don't want logged
setopt interactivecomments

function zshaddhistory() {
  emulate -L zsh
  if ! [[ "$1" =~ "(^#\s+|^\s+#|^ )" ]] ; then
      print -sr -- "${1%%$'\n'}"
      fc -p
  else
      return 1
  fi
}

For reference, this is the default zshaddhistory() http://zsh.sourceforge.net/Doc/Release/Functions.html

zshaddhistory() {
  print -sr -- ${1%%$'\n'}
  fc -p .zsh_local_history
}
FlakRat
  • 71
  • 1
  • 3