42

Sometimes I use multiline commands in zsh:

❯ echo \
> a \
> multiline \
> command

When editing the command after pulling it from a history search, I can change the content of individual lines. However, I can't figure out how to insert another line:

# I want to insert another line after "multiline"...
❯ echo \
> a \
> multiline \  # but hitting <return> here just runs the command, even though there's a backslash at the end of the line
> command

How can I insert a newline in the middle of a multiline command pulled from history?

paulmelnikow
  • 16,895
  • 8
  • 63
  • 114
Sean Mackesey
  • 10,701
  • 11
  • 40
  • 66

7 Answers7

53

You can use ESC-Return.

FWIW, I tested it on Debian Jessie, zsh 5.0.7 and it works there.

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
Kamaraju Kusumanchi
  • 1,809
  • 19
  • 12
42

You can use self-insert-unmeta to bind Alt+Return to insert a literal newline without accepting the command:

bindkey '^[^M' self-insert-unmeta

To use your example: Hitting Alt+Return at the cursor position (#)

% echo \
a \
multiline \#
command

will get you this:

% echo \
a \
multiline \
#
command

This works not only when editing history, but also when typing commands. So you can prepare several commands in a script like fashion and accept them with a single Return.

For example pressing Alt+Return instead of # in this example:

% echo command 1#
echo command 2#
echo command 3

will do the same thing as the command echo command 1; echo command 2; echo command 3 and produce this output:

command 1
command 2
command 3
Adaephon
  • 16,929
  • 1
  • 54
  • 71
  • 3
    I know we shouldn't thank people on Stack Overflow but I feel compelled to. Thank you :D I can now create a zsh keybinding that creates a multi-line command (with a here document) and make execution-time changes to it without it printing `heredoc>` and preventing me from editing it, like so: `bindkey -s "^[t" 'sh < – Sridhar Sarnobat Dec 02 '16 at 19:31
  • For some reason this already works for me without doing anything. (Using Ubuntu 18.04+oh-my-zsh) – Michael Jan 23 '19 at 08:42
  • 1
    This didn't work for me on MacOS 10.12.6, iTerm 3.2.7beta4 – JamieJag Mar 13 '19 at 10:23
  • When using the zsh-vi-mode plugin with oh-my-zsh, this key binding seems to be getting clobbered/deleted after being set in my startup file. (After starting a new terminal, it fails to show up in `bindkey`, but still works if I type `bindkey '^[^M' self-insert-unmeta` directly into the command line.) One workaround that works is to only make this key binding available in the vi insert mode keymap: `bindkey -M viins '^[^M' self-insert-unmeta`. @adaephon, thanks for getting me 90% of the way there. – Jonathan Wheeler May 11 '23 at 19:35
7

(A summary of answers from https://unix.stackexchange.com/questions/6620/how-to-edit-command-line-in-full-screen-editor-in-zsh)

zsh comes with a function that can be used to open the current command line in your favorite editor. Add the following lines to your .zshrc:

autoload -z edit-command-line
zle -N edit-command-line
bindkey "^X^E" edit-command-line

The first line loads the function. The second line creates a new widget for the Z shell line editor (zle) from the function of the same name. The third line binds the widget to Control-X Control-E. If you use the vi bindings rather than emacs key bindings, use something like

bindkey -M vicmd v edit-command-line

instead (which binds the widget to v in vicmd mode).

Community
  • 1
  • 1
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Your answer is really good, but I have to change the accepted answer since @Adaephon answers it more directly. – Sean Mackesey Oct 20 '14 at 17:19
  • This commands has completely messed up my terminal. Please provide commands how to undo these settings? – saumilsdk May 03 '21 at 05:29
  • @saumilsdk You may use `stty sane` any time your terminal has messed up capabilities. I do believe it might fix your problem. – Diti Apr 07 '22 at 12:47
  • Nothing here affects terminal settings. This is purely configuration of `zsh`'s line editor. – chepner Apr 07 '22 at 12:54
4

If using bindkey -v mode, you can also use the default o/O commands from vicmd mode to add a newline line and enter insert mode in it, respectively above or below the current line.

John Gliksberg
  • 122
  • 2
  • 6
2

Just to note, if you want to comment in a multiline command, you could use:

❯ echo `#first comment` \
 a `#second comment` \
 multiline \
 command
Alter Lagos
  • 12,090
  • 1
  • 70
  • 92
0

CTRL + Enter (Return) for Windows/WSL CTRL +X CTRL+E for Mac

Edited as per the comment below

Agrover112
  • 461
  • 5
  • 9
  • 1
    What actually worked for me on MacOS was `Ctr+X Ctr+E` - so holding the `Ctr` button press `X` and then `E` keys. – vasigorc Jan 03 '23 at 21:45
-1

Sounds like an appropriate place to use a shell script file instead no?

#!/bin/zsh
my
commands
here
I can even add a new line at a later time.
Stephen
  • 4,041
  • 22
  • 39
  • Thanks, but I disagree. If you are running many variations of a program with a complex command line interface, the shell's history search provides an excellent way to search through and fork off of your previous runs. You don't get this if you store each configuration in a file. – Sean Mackesey Oct 16 '14 at 17:31