diff --git a/src/env_dispatch.cpp b/src/env_dispatch.cpp index 14799cf11..21259b645 100644 --- a/src/env_dispatch.cpp +++ b/src/env_dispatch.cpp @@ -214,6 +214,13 @@ static void handle_fish_history_change(const env_stack_t &vars) { reader_change_history(history_session_id(vars)); } +static void handle_fish_cursor_selection_mode_change(const env_stack_t &vars) { + auto mode = vars.get(L"fish_cursor_selection_mode"); + reader_change_cursor_selection_mode(mode && mode->as_string() == L"inclusive" + ? cursor_selection_mode_t::inclusive + : cursor_selection_mode_t::exclusive); +} + void handle_autosuggestion_change(const env_stack_t &vars) { reader_set_autosuggestion_enabled(vars); } @@ -327,6 +334,8 @@ static std::unique_ptr create_dispatch_table() { var_dispatch_table->add(L"TZ", handle_tz_change); var_dispatch_table->add(L"fish_use_posix_spawn", handle_fish_use_posix_spawn_change); var_dispatch_table->add(L"fish_trace", handle_fish_trace); + var_dispatch_table->add(L"fish_cursor_selection_mode", + handle_fish_cursor_selection_mode_change); // This std::move is required to avoid a build error on old versions of libc++ (#5801), // but it causes a different warning under newer versions of GCC (observed under GCC 9.3.0, diff --git a/src/reader.cpp b/src/reader.cpp index ff84b2b96..9c271deb6 100644 --- a/src/reader.cpp +++ b/src/reader.cpp @@ -681,6 +681,9 @@ class reader_data_t : public std::enable_shared_from_this { /// The history search. reader_history_search_t history_search{}; + /// The cursor selection mode. + cursor_selection_mode_t cursor_selection_mode{cursor_selection_mode_t::exclusive}; + /// The selection data. If this is not none, then we have an active selection. maybe_t selection{}; @@ -780,8 +783,6 @@ class reader_data_t : public std::enable_shared_from_this { inputter(*parser_ref, conf.in), history(std::move(hist)) {} - /// Whether the selection should always include the character after the cursor. - bool select_char_after_cursor(); void update_buff_pos(editable_line_t *el, maybe_t new_pos = none_t()); void kill(editable_line_t *el, size_t begin_idx, size_t length, int mode, int newv); @@ -1048,11 +1049,6 @@ wcstring combine_command_and_autosuggestion(const wcstring &cmdline, return full_line; } -bool reader_data_t::select_char_after_cursor() { - auto val = vars().get(L"fish_cursor_selection_mode"); - return !val || val->as_string() == L"inclusive"; -} - /// Update the cursor position. void reader_data_t::update_buff_pos(editable_line_t *el, maybe_t new_pos) { if (new_pos) { @@ -1062,10 +1058,12 @@ void reader_data_t::update_buff_pos(editable_line_t *el, maybe_t new_pos if (el == &command_line && selection.has_value()) { if (selection->begin <= buff_pos) { selection->start = selection->begin; - selection->stop = buff_pos + (select_char_after_cursor() ? 1 : 0); + selection->stop = + buff_pos + (cursor_selection_mode == cursor_selection_mode_t::inclusive ? 1 : 0); } else { selection->start = buff_pos; - selection->stop = selection->begin + (select_char_after_cursor() ? 1 : 0); + selection->stop = selection->begin + + (cursor_selection_mode == cursor_selection_mode_t::inclusive ? 1 : 0); } } } @@ -2677,6 +2675,14 @@ void reader_change_history(const wcstring &name) { } } +void reader_change_cursor_selection_mode(cursor_selection_mode_t selection_mode) { + // We don't need to _change_ if we're not initialized yet. + reader_data_t *data = current_data_or_null(); + if (data) { + data->cursor_selection_mode = selection_mode; + } +} + static bool check_autosuggestion_enabled(const env_stack_t &vars) { if (auto val = vars.get(L"fish_autosuggestion_enabled")) { return val->as_string() != L"0"; @@ -3971,7 +3977,8 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat size_t pos = command_line.position(); selection->begin = pos; selection->start = pos; - selection->stop = pos + (select_char_after_cursor() ? 1 : 0); + selection->stop = + pos + (cursor_selection_mode == cursor_selection_mode_t::inclusive ? 1 : 0); break; } diff --git a/src/reader.h b/src/reader.h index d80634208..e8ef270b4 100644 --- a/src/reader.h +++ b/src/reader.h @@ -149,6 +149,18 @@ void restore_term_mode(); /// Change the history file for the current command reading context. void reader_change_history(const wcstring &name); +/// Strategy for determining how the selection behaves. +enum class cursor_selection_mode_t : uint8_t { + /// The character at/after the cursor is excluded. + /// This is most useful with a line cursor shape. + exclusive, + /// The character at/after the cursor is included. + /// This is most useful with a block or underscore cursor shape. + inclusive, +}; + +void reader_change_cursor_selection_mode(cursor_selection_mode_t selection_mode); + /// Enable or disable autosuggestions based on the associated variable. void reader_set_autosuggestion_enabled(const env_stack_t &vars);