1

In a multiline command, there is a difference between

  • Start of the line
  • Start of the command

using the vim keybindings set -o vi FOR READLINE (ex., bash, psql etc), how do I go to the start of the line and not the start of the command.

This question is not on VIM. It's on the vi keybinidngs for readline applications.

Copy this... all of it (the multiline block quote below)

In a multiline command, there is a difference between

  • Start of the line
  • Start of the command

using the vim keybindings set -o vi, how do I go to the start of the line and not the start of the command.

Now follow these instructions..

  1. Type echo "
  2. Paste the above.
  3. Type " to finish the command and press Enter.

Now press the up-arrow to get that into the command buffer.

  1. How do you now go to the start and end of a line, not the command?
  2. How do you go up a line in a multi-line command, not to a different command?
  • 2
    Bash does not have “vim” key bindings, it has vi-like key bindings. Don't expect any of the Vim extensions to Vi and don't expect perfect compatibility even with basic Vi. – Gilles Apr 3 '17 at 21:59
2
  • Start of the line
  • Start of the command

It is easy to prove that the distinction between these two (in a multiline command) things inside readline/bash cannot be performed. And since the distinction cannot be performed there can not be keybindings for each.

Everything below assumes set -o vi

Let us say that I type the following in a bash prompt (I also press Return and the output is generated):

[~]$ echo "yay
> yep
> yup"
yay
yep
yup

Next I press Esc, k and get the following ({.} is the location of the cursor):

[~]$ {e}cho "yay
yep
yup"

Note a couple of things:

  1. PS2 (> on my machine) was not printed as when I typed it directly.
  2. If I keep pressing k and/or j I scroll through previous commands, not lines in command.

Therefore let's make a hypothesis that we are actually editing not several lines but a single line which contains newline characters (Yes, there is a huge difference there. The command history (in memory) is stored as a linked list, not as text separated by newlines.).

And let's try to find a way to prove that the line becomes several commands only when the interpreter parses it. Here is a command from the readline section of man bash:

comment-begin (``#'')
              The  string that is inserted when the readline insert-comment command is executed.  This command is bound to
              M-# in emacs mode and to # in vi command mode.

Basically, if we hit # the line should be commented out and passed to the interpreter (not sure why it is passed to the interpreter, to appear in the history I guess). Anyhow, we know that, if we hit # a readline command will execute, i.e. it is not an editing biding (which should actually be "search next" in Vi).

Let's first more the cursor to the end by pressing $:

[~]$ echo "yay
yep
yup{"}

And now we hit #, things happen, and this is how the shell session looks:

[~]$ #echo "yay
yep
yup"
bash: yep: command not found
> { }

That seems strange, right? But it is exactly what we asked, readline commented the line and passed it to the parser. echo "yay got commented out, the shell attempted to run yep and we see PS2 because we have an unfinished quote from yup". Type "Return to get out.

So, what we can conclude is that readline does not distinguish between the lines in the multiline command we did input above. If readline does not make a distinction then the Vi mode, which is on top of it, can't make the distinction either.

If you need to edit multiple lines separately from each other follow @BartonChittenden's answer (+1) and enter the editor. An editor separates lines into different entities, so you can navigate between them.

2

I'm not sure that this does exactly what you're asking for, but I suspect that it may be the closest thing that you're going to get.

escv

Will open the current command in your editor of choice (e.g. $EDITOR, or the editor set in /etc/alternatives in debian). Presumably, you'll have this set to vi or vim, and you can navigate from line to line using j, k, 0, $ etc.

As a bonus,

shopt -s lithist

will keep the formatting of lines in history, rather than concatenating commands separated by semi-colons.

As noted by Evan Carroll, this only works for bash, but a lot of other programs that use readline also have external editors... e.g. psql allows command editing using \e.

  • <kbd>v</kbd> only works in bash (for me), but it's still a workaround for bash. It doesn't work in the rest of readline apps. Yet, this is still some kind of limited work around, I'll grant you. – Evan Carroll Apr 4 '17 at 2:29
1

bash simply doesn't do what's requested: it sticks fairly close to ksh's imitation of vi. The feature requested here is not a vi feature, but an extension provided by vim.

  • I don't think it's an extension provided by vim. I think it's a feature of readline and that it has nothing to do with bash. – Evan Carroll Apr 3 '17 at 21:30
0

The sequence Shift ^ seems to work for me.

  • That doesn't work, check out the updated copy of the question. – Evan Carroll Apr 3 '17 at 21:03
  • Using gnome terminal, screen and bash, and following your instructions, I'm not able to navigate at all (in vim's command mode), unless I first press v and then Shift ^ works fine. Can you describe what you actually see. – jah Apr 3 '17 at 21:09
  • This isn't vim. This is bash with vim keybindings. – Evan Carroll Apr 3 '17 at 21:10
  • s/vim's/vi's/ I'm aware that you're talking about readline's vi-like edit mode! – jah Apr 3 '17 at 21:17
  • What Shift+^ does depends on the keyboard layout. For example, on a US layout, ^ is Shift+6. What character does Shift+^ produce on your keyboard? – Gilles Apr 3 '17 at 21:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.