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
.