Add repaint-mode bind function

If we switch the bind mode, we add a "force-repaint" there just to
redraw the mode indicator.

That's quite wasteful and annoying, considering that sometimes the prompt can take
half a second.

So we add a "repaint-mode" function that just reexecutes the
mode-prompt and uses the cached values for the others.

Fixes #5783.
This commit is contained in:
Fabian Homborg 2019-04-01 15:52:21 +02:00
parent da1b32f0ad
commit 8ff866b26b
5 changed files with 73 additions and 50 deletions

View file

@ -63,7 +63,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
# Add a way to switch from insert to normal (command) mode.
# Note if we are paging, we want to stay in insert mode
# See #2871
bind -s --preset -M insert \e "if commandline -P; commandline -f cancel; else; set fish_bind_mode default; commandline -f backward-char force-repaint; end"
bind -s --preset -M insert \e "if commandline -P; commandline -f cancel; else; set fish_bind_mode default; commandline -f backward-char repaint-mode; end"
# Default (command) mode
bind -s --preset :q exit
@ -72,14 +72,14 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind -s --preset -M default l forward-char
bind -s --preset -m insert \n execute
bind -s --preset -m insert \r execute
bind -s --preset -m insert i force-repaint
bind -s --preset -m insert I beginning-of-line force-repaint
bind -s --preset -m insert a forward-char force-repaint
bind -s --preset -m insert A end-of-line force-repaint
bind -s --preset -m visual v begin-selection force-repaint
bind -s --preset -m insert i repaint-mode
bind -s --preset -m insert I beginning-of-line repaint-mode
bind -s --preset -m insert a forward-char repaint-mode
bind -s --preset -m insert A end-of-line repaint-mode
bind -s --preset -m visual v begin-selection repaint-mode
#bind -s --preset -m insert o "commandline -a \n" down-line force-repaint
#bind -s --preset -m insert O beginning-of-line "commandline -i \n" up-line force-repaint # doesn't work
#bind -s --preset -m insert o "commandline -a \n" down-line repaint-mode
#bind -s --preset -m insert O beginning-of-line "commandline -i \n" up-line repaint-mode # doesn't work
bind -s --preset gg beginning-of-buffer
bind -s --preset G end-of-buffer
@ -154,24 +154,24 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind -s --preset dF begin-selection backward-jump kill-selection end-selection
bind -s --preset dT begin-selection backward-jump forward-char kill-selection end-selection
bind -s --preset -m insert s delete-char force-repaint
bind -s --preset -m insert S kill-whole-line force-repaint
bind -s --preset -m insert cc kill-whole-line force-repaint
bind -s --preset -m insert C kill-line force-repaint
bind -s --preset -m insert c\$ kill-line force-repaint
bind -s --preset -m insert c\^ backward-kill-line force-repaint
bind -s --preset -m insert cw kill-word force-repaint
bind -s --preset -m insert cW kill-bigword force-repaint
bind -s --preset -m insert ciw forward-char forward-char backward-word kill-word force-repaint
bind -s --preset -m insert ciW forward-char forward-char backward-bigword kill-bigword force-repaint
bind -s --preset -m insert caw forward-char forward-char backward-word kill-word force-repaint
bind -s --preset -m insert caW forward-char forward-char backward-bigword kill-bigword force-repaint
bind -s --preset -m insert ce kill-word force-repaint
bind -s --preset -m insert cE kill-bigword force-repaint
bind -s --preset -m insert cb backward-kill-word force-repaint
bind -s --preset -m insert cB backward-kill-bigword force-repaint
bind -s --preset -m insert cge backward-kill-word force-repaint
bind -s --preset -m insert cgE backward-kill-bigword force-repaint
bind -s --preset -m insert s delete-char repaint-mode
bind -s --preset -m insert S kill-whole-line repaint-mode
bind -s --preset -m insert cc kill-whole-line repaint-mode
bind -s --preset -m insert C kill-line repaint-mode
bind -s --preset -m insert c\$ kill-line repaint-mode
bind -s --preset -m insert c\^ backward-kill-line repaint-mode
bind -s --preset -m insert cw kill-word repaint-mode
bind -s --preset -m insert cW kill-bigword repaint-mode
bind -s --preset -m insert ciw forward-char forward-char backward-word kill-word repaint-mode
bind -s --preset -m insert ciW forward-char forward-char backward-bigword kill-bigword repaint-mode
bind -s --preset -m insert caw forward-char forward-char backward-word kill-word repaint-mode
bind -s --preset -m insert caW forward-char forward-char backward-bigword kill-bigword repaint-mode
bind -s --preset -m insert ce kill-word repaint-mode
bind -s --preset -m insert cE kill-bigword repaint-mode
bind -s --preset -m insert cb backward-kill-word repaint-mode
bind -s --preset -m insert cB backward-kill-bigword repaint-mode
bind -s --preset -m insert cge backward-kill-word repaint-mode
bind -s --preset -m insert cgE backward-kill-bigword repaint-mode
bind -s --preset '~' capitalize-word
bind -s --preset gu downcase-word
@ -215,9 +215,9 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
#
# Lowercase r, enters replace_one mode
#
bind -s --preset -m replace_one r force-repaint
bind -s --preset -M replace_one -m default '' delete-char self-insert backward-char force-repaint
bind -s --preset -M replace_one -m default \e cancel force-repaint
bind -s --preset -m replace_one r repaint-mode
bind -s --preset -M replace_one -m default '' delete-char self-insert backward-char repaint-mode
bind -s --preset -M replace_one -m default \e cancel repaint-mode
#
# visual mode
@ -236,7 +236,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind -s --preset -M visual W forward-bigword
bind -s --preset -M visual e forward-word
bind -s --preset -M visual E forward-bigword
bind -s --preset -M visual o swap-selection-start-stop force-repaint
bind -s --preset -M visual o swap-selection-start-stop repaint-mode
bind -s --preset -M visual f forward-jump
bind -s --preset -M visual t forward-jump-till
@ -250,15 +250,15 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
bind -s --preset -M visual $key beginning-of-line
end
bind -s --preset -M visual -m insert c kill-selection end-selection force-repaint
bind -s --preset -M visual -m default d kill-selection end-selection force-repaint
bind -s --preset -M visual -m default x kill-selection end-selection force-repaint
bind -s --preset -M visual -m default X kill-whole-line end-selection force-repaint
bind -s --preset -M visual -m default y kill-selection yank end-selection force-repaint
bind -s --preset -M visual -m default '"*y' "commandline -s | xsel -p; commandline -f end-selection force-repaint"
bind -s --preset -M visual -m insert c kill-selection end-selection repaint-mode
bind -s --preset -M visual -m default d kill-selection end-selection repaint-mode
bind -s --preset -M visual -m default x kill-selection end-selection repaint-mode
bind -s --preset -M visual -m default X kill-whole-line end-selection repaint-mode
bind -s --preset -M visual -m default y kill-selection yank end-selection repaint-mode
bind -s --preset -M visual -m default '"*y' "commandline -s | xsel -p; commandline -f end-selection repaint-mode"
bind -s --preset -M visual -m default \cc end-selection force-repaint
bind -s --preset -M visual -m default \e end-selection force-repaint
bind -s --preset -M visual -m default \cc end-selection repaint-mode
bind -s --preset -M visual -m default \e end-selection repaint-mode
# Make it easy to turn an unexecuted command into a comment in the shell history. Also, remove
# the commenting chars so the command can be further edited then executed.

View file

@ -136,6 +136,10 @@ The following special input functions are available:
- ``pager-toggle-search``, toggles the search field if the completions pager is visible.
- ``repaint`` reexecutes the prompt functions and redraws the prompt. Multiple successive repaints are coalesced.
- ``repaint-mode`` reexecutes the fish_mode_prompt function and redraws the prompt. This is useful for vi-mode.
- ``suppress-autosuggestion``, remove the current autosuggestion
- ``swap-selection-start-stop``, go to the other end of the highlighted text without changing the selection

View file

@ -112,6 +112,7 @@ static const input_function_metadata_t input_function_metadata[] = {
{readline_cmd_t::execute, L"execute"},
{readline_cmd_t::beginning_of_buffer, L"beginning-of-buffer"},
{readline_cmd_t::end_of_buffer, L"end-of-buffer"},
{readline_cmd_t::repaint_mode, L"repaint-mode"},
{readline_cmd_t::repaint, L"repaint"},
{readline_cmd_t::force_repaint, L"force-repaint"},
{readline_cmd_t::up_line, L"up-line"},

View file

@ -50,6 +50,7 @@ enum class readline_cmd_t {
execute,
beginning_of_buffer,
end_of_buffer,
repaint_mode,
repaint,
force_repaint,
up_line,

View file

@ -357,6 +357,7 @@ class reader_data_t : public std::enable_shared_from_this<reader_data_t> {
wcstring right_prompt;
/// The output of the last evaluation of the prompt command.
wcstring left_prompt_buff;
wcstring mode_prompt_buff;
/// The output of the last evaluation of the right prompt command.
wcstring right_prompt_buff;
/// Completion support.
@ -461,6 +462,7 @@ class reader_data_t : public std::enable_shared_from_this<reader_data_t> {
void highlight_search();
void highlight_complete(highlight_result_t result);
void exec_mode_prompt();
void exec_prompt();
bool jump(jump_direction_t dir, jump_precision_t precision, editable_line_t *el,
@ -641,7 +643,8 @@ void reader_data_t::repaint() {
bool focused_on_pager = active_edit_line() == &pager.search_field_line;
size_t cursor_position = focused_on_pager ? pager.cursor_position() : cmd_line->position;
s_write(&screen, left_prompt_buff, right_prompt_buff, full_line, cmd_line->size(), colors,
// Prepend the mode prompt to the left prompt.
s_write(&screen, mode_prompt_buff + left_prompt_buff, right_prompt_buff, full_line, cmd_line->size(), colors,
indents, cursor_position, current_page_rendering, focused_on_pager);
repaint_needed = false;
@ -904,6 +907,20 @@ void reader_write_title(const wcstring &cmd, bool reset_cursor_position) {
}
}
void reader_data_t::exec_mode_prompt() {
mode_prompt_buff.clear();
if (function_exists(MODE_PROMPT_FUNCTION_NAME)) {
wcstring_list_t mode_indicator_list;
exec_subshell(MODE_PROMPT_FUNCTION_NAME, parser(), mode_indicator_list,
false);
// We do not support multiple lines in the mode indicator, so just concatenate all of
// them.
for (size_t i = 0; i < mode_indicator_list.size(); i++) {
mode_prompt_buff += mode_indicator_list.at(i);
}
}
}
/// Reexecute the prompt command. The output is inserted into prompt_buff.
void reader_data_t::exec_prompt() {
// Clear existing prompts.
@ -921,17 +938,7 @@ void reader_data_t::exec_prompt() {
if (left_prompt.size() || right_prompt.size()) {
proc_push_interactive(0);
// Prepend any mode indicator to the left prompt (issue #1988).
if (function_exists(MODE_PROMPT_FUNCTION_NAME)) {
wcstring_list_t mode_indicator_list;
exec_subshell(MODE_PROMPT_FUNCTION_NAME, parser(), mode_indicator_list,
apply_exit_status);
// We do not support multiple lines in the mode indicator, so just concatenate all of
// them.
for (size_t i = 0; i < mode_indicator_list.size(); i++) {
left_prompt_buff += mode_indicator_list.at(i);
}
}
exec_mode_prompt();
if (!left_prompt.empty()) {
wcstring_list_t prompt_list;
@ -2503,6 +2510,16 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
// The only thing we can cancel right now is paging, which we handled up above.
break;
}
case rl::repaint_mode: {
// Repaint the mode-prompt only if it exists.
// This is an optimization basically exclusively for vi-mode, since the prompt
// may sometimes take a while but when switching the mode all we care about is the mode-prompt.
exec_mode_prompt();
s_reset(&screen, screen_reset_current_line_and_prompt);
screen_reset_needed = false;
repaint();
break;
}
case rl::force_repaint:
case rl::repaint: {
if (!rls.coalescing_repaints) {