How to do it
Bash doesn't seem to provide builtin support for this in form of a readline function like it does for editing and executing. However, there is bind -x command to invoke arbitrary shell function and $READLINE_* variables which can be combined to perform command-line editing, one just needs to call Vim to do the job:
function _editcommandline() { local tmp_file="$(mktemp "/tmp/bash-editinplace.XXXXXX")" echo "$READLINE_LINE" >| "$tmp_file" vim +"call cursor(1, $READLINE_POINT + 1)" "$tmp_file" READLINE_LINE="$(< "$tmp_file")" READLINE_POINT="${#READLINE_LINE}" rm -f "$tmp_file" } # bind to Ctrl-X+e combination bind -x '"\C-Xe": _editcommandline'
How it works
Here we define function _editcommandline() and use bind to tell bash to invoke it when C-Xe combination is pressed.
Inside the function:
- Temporary file is created.
- The file is filled with current input line.
- Vim is called to edit the line, positioning the cursor appropriately.
- Current line is replaced with contents of the temporary file, which is later removed.
- Cursor is positioned at the end of input line.
Limitation
The limitation of this approach is that you can edit only current input line, not whole command-line, but this is important only for multi-line commands.
Possible improvements
The function was written for demonstration purposes and can be further improved by:
- Correctly positioning cursor in bash instead of moving it to the end.
- Checking exit code of Vim to be able to discard saved changes with
:cquit.