mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-25 00:57:25 +08:00
Switch readline commands to readline_cmd_t enum class
This commit is contained in:
parent
0841072462
commit
2c56e27d37
|
@ -2999,9 +2999,8 @@ static void test_input() {
|
||||||
auto evt = input_readch();
|
auto evt = input_readch();
|
||||||
if (!evt.is_readline()) {
|
if (!evt.is_readline()) {
|
||||||
err(L"Event is not a readline");
|
err(L"Event is not a readline");
|
||||||
} else if (evt.get_readline() != R_DOWN_LINE) {
|
} else if (evt.get_readline() != readline_cmd_t::R_DOWN_LINE) {
|
||||||
err(L"Expected to read char R_DOWN_LINE, but instead got %ls\n",
|
err(L"Expected to read char R_DOWN_LINE");
|
||||||
describe_char(evt.get_readline()).c_str());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
139
src/input.cpp
139
src/input.cpp
|
@ -67,68 +67,69 @@ static constexpr size_t input_function_count = R_END_INPUT_FUNCTIONS - R_BEGIN_I
|
||||||
/// Input function metadata. This list should be kept in sync with the key code list in
|
/// Input function metadata. This list should be kept in sync with the key code list in
|
||||||
/// input_common.h.
|
/// input_common.h.
|
||||||
struct input_function_metadata_t {
|
struct input_function_metadata_t {
|
||||||
wchar_t code;
|
readline_cmd_t code;
|
||||||
const wchar_t *name;
|
const wchar_t *name;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const input_function_metadata_t input_function_metadata[] = {
|
static const input_function_metadata_t input_function_metadata[] = {
|
||||||
{R_BEGINNING_OF_LINE, L"beginning-of-line"},
|
{readline_cmd_t::R_BEGINNING_OF_LINE, L"beginning-of-line"},
|
||||||
{R_END_OF_LINE, L"end-of-line"},
|
{readline_cmd_t::R_END_OF_LINE, L"end-of-line"},
|
||||||
{R_FORWARD_CHAR, L"forward-char"},
|
{readline_cmd_t::R_FORWARD_CHAR, L"forward-char"},
|
||||||
{R_BACKWARD_CHAR, L"backward-char"},
|
{readline_cmd_t::R_BACKWARD_CHAR, L"backward-char"},
|
||||||
{R_FORWARD_WORD, L"forward-word"},
|
{readline_cmd_t::R_FORWARD_WORD, L"forward-word"},
|
||||||
{R_BACKWARD_WORD, L"backward-word"},
|
{readline_cmd_t::R_BACKWARD_WORD, L"backward-word"},
|
||||||
{R_FORWARD_BIGWORD, L"forward-bigword"},
|
{readline_cmd_t::R_FORWARD_BIGWORD, L"forward-bigword"},
|
||||||
{R_BACKWARD_BIGWORD, L"backward-bigword"},
|
{readline_cmd_t::R_BACKWARD_BIGWORD, L"backward-bigword"},
|
||||||
{R_HISTORY_SEARCH_BACKWARD, L"history-search-backward"},
|
{readline_cmd_t::R_HISTORY_SEARCH_BACKWARD, L"history-search-backward"},
|
||||||
{R_HISTORY_SEARCH_FORWARD, L"history-search-forward"},
|
{readline_cmd_t::R_HISTORY_SEARCH_FORWARD, L"history-search-forward"},
|
||||||
{R_DELETE_CHAR, L"delete-char"},
|
{readline_cmd_t::R_DELETE_CHAR, L"delete-char"},
|
||||||
{R_BACKWARD_DELETE_CHAR, L"backward-delete-char"},
|
{readline_cmd_t::R_BACKWARD_DELETE_CHAR, L"backward-delete-char"},
|
||||||
{R_KILL_LINE, L"kill-line"},
|
{readline_cmd_t::R_KILL_LINE, L"kill-line"},
|
||||||
{R_YANK, L"yank"},
|
{readline_cmd_t::R_YANK, L"yank"},
|
||||||
{R_YANK_POP, L"yank-pop"},
|
{readline_cmd_t::R_YANK_POP, L"yank-pop"},
|
||||||
{R_COMPLETE, L"complete"},
|
{readline_cmd_t::R_COMPLETE, L"complete"},
|
||||||
{R_COMPLETE_AND_SEARCH, L"complete-and-search"},
|
{readline_cmd_t::R_COMPLETE_AND_SEARCH, L"complete-and-search"},
|
||||||
{R_PAGER_TOGGLE_SEARCH, L"pager-toggle-search"},
|
{readline_cmd_t::R_PAGER_TOGGLE_SEARCH, L"pager-toggle-search"},
|
||||||
{R_BEGINNING_OF_HISTORY, L"beginning-of-history"},
|
{readline_cmd_t::R_BEGINNING_OF_HISTORY, L"beginning-of-history"},
|
||||||
{R_END_OF_HISTORY, L"end-of-history"},
|
{readline_cmd_t::R_END_OF_HISTORY, L"end-of-history"},
|
||||||
{R_BACKWARD_KILL_LINE, L"backward-kill-line"},
|
{readline_cmd_t::R_BACKWARD_KILL_LINE, L"backward-kill-line"},
|
||||||
{R_KILL_WHOLE_LINE, L"kill-whole-line"},
|
{readline_cmd_t::R_KILL_WHOLE_LINE, L"kill-whole-line"},
|
||||||
{R_KILL_WORD, L"kill-word"},
|
{readline_cmd_t::R_KILL_WORD, L"kill-word"},
|
||||||
{R_KILL_BIGWORD, L"kill-bigword"},
|
{readline_cmd_t::R_KILL_BIGWORD, L"kill-bigword"},
|
||||||
{R_BACKWARD_KILL_WORD, L"backward-kill-word"},
|
{readline_cmd_t::R_BACKWARD_KILL_WORD, L"backward-kill-word"},
|
||||||
{R_BACKWARD_KILL_PATH_COMPONENT, L"backward-kill-path-component"},
|
{readline_cmd_t::R_BACKWARD_KILL_PATH_COMPONENT, L"backward-kill-path-component"},
|
||||||
{R_BACKWARD_KILL_BIGWORD, L"backward-kill-bigword"},
|
{readline_cmd_t::R_BACKWARD_KILL_BIGWORD, L"backward-kill-bigword"},
|
||||||
{R_HISTORY_TOKEN_SEARCH_BACKWARD, L"history-token-search-backward"},
|
{readline_cmd_t::R_HISTORY_TOKEN_SEARCH_BACKWARD, L"history-token-search-backward"},
|
||||||
{R_HISTORY_TOKEN_SEARCH_FORWARD, L"history-token-search-forward"},
|
{readline_cmd_t::R_HISTORY_TOKEN_SEARCH_FORWARD, L"history-token-search-forward"},
|
||||||
{R_SELF_INSERT, L"self-insert"},
|
{readline_cmd_t::R_SELF_INSERT, L"self-insert"},
|
||||||
{R_TRANSPOSE_CHARS, L"transpose-chars"},
|
{readline_cmd_t::R_TRANSPOSE_CHARS, L"transpose-chars"},
|
||||||
{R_TRANSPOSE_WORDS, L"transpose-words"},
|
{readline_cmd_t::R_TRANSPOSE_WORDS, L"transpose-words"},
|
||||||
{R_UPCASE_WORD, L"upcase-word"},
|
{readline_cmd_t::R_UPCASE_WORD, L"upcase-word"},
|
||||||
{R_DOWNCASE_WORD, L"downcase-word"},
|
{readline_cmd_t::R_DOWNCASE_WORD, L"downcase-word"},
|
||||||
{R_CAPITALIZE_WORD, L"capitalize-word"},
|
{readline_cmd_t::R_CAPITALIZE_WORD, L"capitalize-word"},
|
||||||
{R_VI_ARG_DIGIT, L"vi-arg-digit"},
|
{readline_cmd_t::R_VI_ARG_DIGIT, L"vi-arg-digit"},
|
||||||
{R_VI_DELETE_TO, L"vi-delete-to"},
|
{readline_cmd_t::R_VI_DELETE_TO, L"vi-delete-to"},
|
||||||
{R_EXECUTE, L"execute"},
|
{readline_cmd_t::R_EXECUTE, L"execute"},
|
||||||
{R_BEGINNING_OF_BUFFER, L"beginning-of-buffer"},
|
{readline_cmd_t::R_BEGINNING_OF_BUFFER, L"beginning-of-buffer"},
|
||||||
{R_END_OF_BUFFER, L"end-of-buffer"},
|
{readline_cmd_t::R_END_OF_BUFFER, L"end-of-buffer"},
|
||||||
{R_REPAINT, L"repaint"},
|
{readline_cmd_t::R_REPAINT, L"repaint"},
|
||||||
{R_FORCE_REPAINT, L"force-repaint"},
|
{readline_cmd_t::R_FORCE_REPAINT, L"force-repaint"},
|
||||||
{R_UP_LINE, L"up-line"},
|
{readline_cmd_t::R_UP_LINE, L"up-line"},
|
||||||
{R_DOWN_LINE, L"down-line"},
|
{readline_cmd_t::R_DOWN_LINE, L"down-line"},
|
||||||
{R_SUPPRESS_AUTOSUGGESTION, L"suppress-autosuggestion"},
|
{readline_cmd_t::R_SUPPRESS_AUTOSUGGESTION, L"suppress-autosuggestion"},
|
||||||
{R_ACCEPT_AUTOSUGGESTION, L"accept-autosuggestion"},
|
{readline_cmd_t::R_ACCEPT_AUTOSUGGESTION, L"accept-autosuggestion"},
|
||||||
{R_BEGIN_SELECTION, L"begin-selection"},
|
{readline_cmd_t::R_BEGIN_SELECTION, L"begin-selection"},
|
||||||
{R_SWAP_SELECTION_START_STOP, L"swap-selection-start-stop"},
|
{readline_cmd_t::R_SWAP_SELECTION_START_STOP, L"swap-selection-start-stop"},
|
||||||
{R_END_SELECTION, L"end-selection"},
|
{readline_cmd_t::R_END_SELECTION, L"end-selection"},
|
||||||
{R_KILL_SELECTION, L"kill-selection"},
|
{readline_cmd_t::R_KILL_SELECTION, L"kill-selection"},
|
||||||
{R_FORWARD_JUMP, L"forward-jump"},
|
{readline_cmd_t::R_FORWARD_JUMP, L"forward-jump"},
|
||||||
{R_BACKWARD_JUMP, L"backward-jump"},
|
{readline_cmd_t::R_BACKWARD_JUMP, L"backward-jump"},
|
||||||
{R_FORWARD_JUMP_TILL, L"forward-jump-till"},
|
{readline_cmd_t::R_FORWARD_JUMP_TILL, L"forward-jump-till"},
|
||||||
{R_BACKWARD_JUMP_TILL, L"backward-jump-till"},
|
{readline_cmd_t::R_BACKWARD_JUMP_TILL, L"backward-jump-till"},
|
||||||
{R_REPEAT_JUMP, L"repeat-jump"},
|
{readline_cmd_t::R_REPEAT_JUMP, L"repeat-jump"},
|
||||||
{R_REVERSE_REPEAT_JUMP, L"repeat-jump-reverse"},
|
{readline_cmd_t::R_REVERSE_REPEAT_JUMP, L"repeat-jump-reverse"},
|
||||||
{R_AND, L"and"},
|
{readline_cmd_t::R_AND, L"and"},
|
||||||
{R_CANCEL, L"cancel"}};
|
{readline_cmd_t::R_CANCEL, L"cancel"}};
|
||||||
|
|
||||||
static_assert(sizeof(input_function_metadata) / sizeof(input_function_metadata[0]) ==
|
static_assert(sizeof(input_function_metadata) / sizeof(input_function_metadata[0]) ==
|
||||||
input_function_count,
|
input_function_count,
|
||||||
|
@ -182,12 +183,12 @@ void input_set_bind_mode(const wcstring &bm) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the arity of a given input function.
|
/// Returns the arity of a given input function.
|
||||||
static int input_function_arity(int function) {
|
static int input_function_arity(readline_cmd_t function) {
|
||||||
switch (function) {
|
switch (function) {
|
||||||
case R_FORWARD_JUMP:
|
case readline_cmd_t::R_FORWARD_JUMP:
|
||||||
case R_BACKWARD_JUMP:
|
case readline_cmd_t::R_BACKWARD_JUMP:
|
||||||
case R_FORWARD_JUMP_TILL:
|
case readline_cmd_t::R_FORWARD_JUMP_TILL:
|
||||||
case R_BACKWARD_JUMP_TILL:
|
case readline_cmd_t::R_BACKWARD_JUMP_TILL:
|
||||||
return 1;
|
return 1;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -302,7 +303,7 @@ void input_function_push_arg(wchar_t arg) {
|
||||||
|
|
||||||
wchar_t input_function_pop_arg() { return input_function_args[--input_function_args_index]; }
|
wchar_t input_function_pop_arg() { return input_function_args[--input_function_args_index]; }
|
||||||
|
|
||||||
void input_function_push_args(int code) {
|
void input_function_push_args(readline_cmd_t code) {
|
||||||
int arity = input_function_arity(code);
|
int arity = input_function_arity(code);
|
||||||
std::vector<char_event_t> skipped;
|
std::vector<char_event_t> skipped;
|
||||||
|
|
||||||
|
@ -360,7 +361,7 @@ static void input_mapping_execute(const input_mapping_t &m, bool allow_commands)
|
||||||
for (wcstring_list_t::const_reverse_iterator it = m.commands.rbegin(),
|
for (wcstring_list_t::const_reverse_iterator it = m.commands.rbegin(),
|
||||||
end = m.commands.rend();
|
end = m.commands.rend();
|
||||||
it != end; ++it) {
|
it != end; ++it) {
|
||||||
wchar_t code = input_function_get_code(*it).value();
|
readline_cmd_t code = input_function_get_code(*it).value();
|
||||||
input_function_push_args(code);
|
input_function_push_args(code);
|
||||||
input_common_next_ch(code);
|
input_common_next_ch(code);
|
||||||
}
|
}
|
||||||
|
@ -480,12 +481,12 @@ char_event_t input_readch(bool allow_commands) {
|
||||||
|
|
||||||
if (evt.is_readline()) {
|
if (evt.is_readline()) {
|
||||||
switch (evt.get_readline()) {
|
switch (evt.get_readline()) {
|
||||||
case R_SELF_INSERT: {
|
case readline_cmd_t::R_SELF_INSERT: {
|
||||||
// Issue #1595: ensure we only insert characters, not readline functions. The
|
// Issue #1595: ensure we only insert characters, not readline functions. The
|
||||||
// common case is that this will be empty.
|
// common case is that this will be empty.
|
||||||
return input_read_characters_no_readline();
|
return input_read_characters_no_readline();
|
||||||
}
|
}
|
||||||
case R_AND: {
|
case readline_cmd_t::R_AND: {
|
||||||
if (input_function_status) {
|
if (input_function_status) {
|
||||||
return input_readch();
|
return input_readch();
|
||||||
}
|
}
|
||||||
|
@ -794,7 +795,7 @@ wcstring_list_t input_function_get_names() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
maybe_t<wchar_t> input_function_get_code(const wcstring &name) {
|
maybe_t<readline_cmd_t> input_function_get_code(const wcstring &name) {
|
||||||
for (const auto &md : input_function_metadata) {
|
for (const auto &md : input_function_metadata) {
|
||||||
if (name == md.name) {
|
if (name == md.name) {
|
||||||
return md.code;
|
return md.code;
|
||||||
|
|
|
@ -95,7 +95,7 @@ bool input_terminfo_get_name(const wcstring &seq, wcstring *out_name);
|
||||||
wcstring_list_t input_terminfo_get_names(bool skip_null);
|
wcstring_list_t input_terminfo_get_names(bool skip_null);
|
||||||
|
|
||||||
/// Returns the input function code for the given input function name.
|
/// Returns the input function code for the given input function name.
|
||||||
maybe_t<wchar_t> input_function_get_code(const wcstring &name);
|
maybe_t<readline_cmd_t> input_function_get_code(const wcstring &name);
|
||||||
|
|
||||||
/// Returns a list of all existing input function names.
|
/// Returns a list of all existing input function names.
|
||||||
wcstring_list_t input_function_get_names(void);
|
wcstring_list_t input_function_get_names(void);
|
||||||
|
|
|
@ -9,10 +9,8 @@
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "maybe.h"
|
#include "maybe.h"
|
||||||
|
|
||||||
enum {
|
enum class readline_cmd_t {
|
||||||
R_MIN = INPUT_COMMON_BASE,
|
R_BEGINNING_OF_LINE = INPUT_COMMON_BASE,
|
||||||
|
|
||||||
R_BEGINNING_OF_LINE = R_MIN,
|
|
||||||
R_END_OF_LINE,
|
R_END_OF_LINE,
|
||||||
R_FORWARD_CHAR,
|
R_FORWARD_CHAR,
|
||||||
R_BACKWARD_CHAR,
|
R_BACKWARD_CHAR,
|
||||||
|
@ -70,15 +68,16 @@ enum {
|
||||||
R_CANCEL,
|
R_CANCEL,
|
||||||
R_REPEAT_JUMP,
|
R_REPEAT_JUMP,
|
||||||
R_REVERSE_REPEAT_JUMP,
|
R_REVERSE_REPEAT_JUMP,
|
||||||
|
};
|
||||||
|
|
||||||
// The range of key codes for inputrc-style keyboard functions that are passed on to the caller
|
// The range of key codes for inputrc-style keyboard functions.
|
||||||
// of input_read().
|
enum {
|
||||||
R_BEGIN_INPUT_FUNCTIONS = R_BEGINNING_OF_LINE,
|
R_BEGIN_INPUT_FUNCTIONS = static_cast<int>(readline_cmd_t::R_BEGINNING_OF_LINE),
|
||||||
R_END_INPUT_FUNCTIONS = R_REVERSE_REPEAT_JUMP + 1
|
R_END_INPUT_FUNCTIONS = static_cast<int>(readline_cmd_t::R_REVERSE_REPEAT_JUMP) + 1
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Represents an event on the character input stream.
|
/// Represents an event on the character input stream.
|
||||||
enum class char_event_type_t {
|
enum class char_event_type_t : uint8_t {
|
||||||
/// A character was entered.
|
/// A character was entered.
|
||||||
charc,
|
charc,
|
||||||
|
|
||||||
|
@ -97,8 +96,13 @@ enum class char_event_type_t {
|
||||||
};
|
};
|
||||||
|
|
||||||
class char_event_t {
|
class char_event_t {
|
||||||
/// Set if the type is charc or readline.
|
union {
|
||||||
wchar_t c_;
|
/// Set if the type is charc.
|
||||||
|
wchar_t c;
|
||||||
|
|
||||||
|
/// Set if the type is readline.
|
||||||
|
readline_cmd_t rl;
|
||||||
|
} v_{};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
char_event_type_t type;
|
char_event_type_t type;
|
||||||
|
@ -115,21 +119,21 @@ class char_event_t {
|
||||||
|
|
||||||
wchar_t get_char() const {
|
wchar_t get_char() const {
|
||||||
assert(type == char_event_type_t::charc && "Not a char type");
|
assert(type == char_event_type_t::charc && "Not a char type");
|
||||||
return c_;
|
return v_.c;
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t get_readline() const {
|
readline_cmd_t get_readline() const {
|
||||||
assert(type == char_event_type_t::readline && "Not a readline type");
|
assert(type == char_event_type_t::readline && "Not a readline type");
|
||||||
return c_;
|
return v_.rl;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* implicit */ char_event_t(wchar_t c)
|
/* implicit */ char_event_t(wchar_t c) : type(char_event_type_t::charc) { v_.c = c; }
|
||||||
: c_(c),
|
|
||||||
type(R_BEGIN_INPUT_FUNCTIONS <= c && c < R_END_INPUT_FUNCTIONS
|
|
||||||
? char_event_type_t::readline
|
|
||||||
: char_event_type_t::charc) {}
|
|
||||||
|
|
||||||
/* implicit */ char_event_t(char_event_type_t type) : c_(0), type(type) {
|
/* implicit */ char_event_t(readline_cmd_t rl) : type(char_event_type_t::readline) {
|
||||||
|
v_.rl = rl;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* implicit */ char_event_t(char_event_type_t type) : type(type) {
|
||||||
assert(type != char_event_type_t::charc && type != char_event_type_t::readline &&
|
assert(type != char_event_type_t::charc && type != char_event_type_t::readline &&
|
||||||
"Cannot create a char event with this constructor");
|
"Cannot create a char event with this constructor");
|
||||||
}
|
}
|
||||||
|
|
|
@ -203,6 +203,12 @@ class maybe_t : private maybe_detail::conditionally_copyable_t<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator!=(const maybe_t &rhs) const { return !(*this == rhs); }
|
bool operator!=(const maybe_t &rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
|
bool operator==(const T &rhs) const { return this->has_value() && this->value() == rhs; }
|
||||||
|
|
||||||
|
bool operator!=(const T &rhs) const { return !(*this == rhs); }
|
||||||
|
|
||||||
|
~maybe_t() { reset(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
365
src/reader.cpp
365
src/reader.cpp
|
@ -1027,67 +1027,83 @@ void reader_force_exit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Indicates if the given command char ends paging.
|
/// Indicates if the given command char ends paging.
|
||||||
static bool command_ends_paging(wchar_t c, bool focused_on_search_field) {
|
static bool command_ends_paging(readline_cmd_t c, bool focused_on_search_field) {
|
||||||
|
using rl = readline_cmd_t;
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case R_HISTORY_SEARCH_BACKWARD:
|
case rl::R_HISTORY_SEARCH_BACKWARD:
|
||||||
case R_HISTORY_SEARCH_FORWARD:
|
case rl::R_HISTORY_SEARCH_FORWARD:
|
||||||
case R_HISTORY_TOKEN_SEARCH_BACKWARD:
|
case rl::R_HISTORY_TOKEN_SEARCH_BACKWARD:
|
||||||
case R_HISTORY_TOKEN_SEARCH_FORWARD:
|
case rl::R_HISTORY_TOKEN_SEARCH_FORWARD:
|
||||||
case R_ACCEPT_AUTOSUGGESTION:
|
case rl::R_ACCEPT_AUTOSUGGESTION:
|
||||||
case R_CANCEL: {
|
case rl::R_CANCEL: {
|
||||||
// These commands always end paging.
|
// These commands always end paging.
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
case R_COMPLETE:
|
case rl::R_COMPLETE:
|
||||||
case R_COMPLETE_AND_SEARCH:
|
case rl::R_COMPLETE_AND_SEARCH:
|
||||||
case R_BACKWARD_CHAR:
|
case rl::R_BACKWARD_CHAR:
|
||||||
case R_FORWARD_CHAR:
|
case rl::R_FORWARD_CHAR:
|
||||||
case R_UP_LINE:
|
case rl::R_UP_LINE:
|
||||||
case R_DOWN_LINE:
|
case rl::R_DOWN_LINE:
|
||||||
case R_REPAINT:
|
case rl::R_REPAINT:
|
||||||
case R_SUPPRESS_AUTOSUGGESTION:
|
case rl::R_SUPPRESS_AUTOSUGGESTION:
|
||||||
case R_BEGINNING_OF_HISTORY:
|
case rl::R_BEGINNING_OF_HISTORY:
|
||||||
case R_END_OF_HISTORY: {
|
case rl::R_END_OF_HISTORY: {
|
||||||
// These commands never end paging.
|
// These commands never end paging.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case R_EXECUTE: {
|
case rl::R_EXECUTE: {
|
||||||
// R_EXECUTE does end paging, but only executes if it was not paging. So it's handled
|
// R_EXECUTE does end paging, but only executes if it was not paging. So it's handled
|
||||||
// specially.
|
// specially.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
case R_BEGINNING_OF_LINE:
|
case rl::R_BEGINNING_OF_LINE:
|
||||||
case R_END_OF_LINE:
|
case rl::R_END_OF_LINE:
|
||||||
case R_FORWARD_WORD:
|
case rl::R_FORWARD_WORD:
|
||||||
case R_BACKWARD_WORD:
|
case rl::R_BACKWARD_WORD:
|
||||||
case R_FORWARD_BIGWORD:
|
case rl::R_FORWARD_BIGWORD:
|
||||||
case R_BACKWARD_BIGWORD:
|
case rl::R_BACKWARD_BIGWORD:
|
||||||
case R_DELETE_CHAR:
|
case rl::R_DELETE_CHAR:
|
||||||
case R_BACKWARD_DELETE_CHAR:
|
case rl::R_BACKWARD_DELETE_CHAR:
|
||||||
case R_KILL_LINE:
|
case rl::R_KILL_LINE:
|
||||||
case R_YANK:
|
case rl::R_YANK:
|
||||||
case R_YANK_POP:
|
case rl::R_YANK_POP:
|
||||||
case R_BACKWARD_KILL_LINE:
|
case rl::R_BACKWARD_KILL_LINE:
|
||||||
case R_KILL_WHOLE_LINE:
|
case rl::R_KILL_WHOLE_LINE:
|
||||||
case R_KILL_WORD:
|
case rl::R_KILL_WORD:
|
||||||
case R_KILL_BIGWORD:
|
case rl::R_KILL_BIGWORD:
|
||||||
case R_BACKWARD_KILL_WORD:
|
case rl::R_BACKWARD_KILL_WORD:
|
||||||
case R_BACKWARD_KILL_PATH_COMPONENT:
|
case rl::R_BACKWARD_KILL_PATH_COMPONENT:
|
||||||
case R_BACKWARD_KILL_BIGWORD:
|
case rl::R_BACKWARD_KILL_BIGWORD:
|
||||||
case R_SELF_INSERT:
|
case rl::R_SELF_INSERT:
|
||||||
case R_TRANSPOSE_CHARS:
|
case rl::R_TRANSPOSE_CHARS:
|
||||||
case R_TRANSPOSE_WORDS:
|
case rl::R_TRANSPOSE_WORDS:
|
||||||
case R_UPCASE_WORD:
|
case rl::R_UPCASE_WORD:
|
||||||
case R_DOWNCASE_WORD:
|
case rl::R_DOWNCASE_WORD:
|
||||||
case R_CAPITALIZE_WORD:
|
case rl::R_CAPITALIZE_WORD:
|
||||||
case R_VI_ARG_DIGIT:
|
case rl::R_VI_ARG_DIGIT:
|
||||||
case R_VI_DELETE_TO:
|
case rl::R_VI_DELETE_TO:
|
||||||
case R_BEGINNING_OF_BUFFER:
|
case rl::R_BEGINNING_OF_BUFFER:
|
||||||
case R_END_OF_BUFFER: {
|
case rl::R_END_OF_BUFFER:
|
||||||
// These commands operate on the search field if that's where the focus is.
|
// These commands operate on the search field if that's where the focus is.
|
||||||
return !focused_on_search_field;
|
return !focused_on_search_field;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
default: { return false; }
|
}
|
||||||
|
|
||||||
|
/// Indicates if the given command ends the history search.
|
||||||
|
static bool command_ends_history_search(readline_cmd_t c) {
|
||||||
|
switch (c) {
|
||||||
|
case readline_cmd_t::R_HISTORY_SEARCH_BACKWARD:
|
||||||
|
case readline_cmd_t::R_HISTORY_SEARCH_FORWARD:
|
||||||
|
case readline_cmd_t::R_HISTORY_TOKEN_SEARCH_BACKWARD:
|
||||||
|
case readline_cmd_t::R_HISTORY_TOKEN_SEARCH_FORWARD:
|
||||||
|
case readline_cmd_t::R_REPAINT:
|
||||||
|
case readline_cmd_t::R_FORCE_REPAINT:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2389,7 +2405,8 @@ static bool event_is_normal_char(const char_event_t &evt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
int last_char = 0;
|
using rl = readline_cmd_t;
|
||||||
|
maybe_t<readline_cmd_t> last_cmd{};
|
||||||
size_t yank_len = 0;
|
size_t yank_len = 0;
|
||||||
bool comp_empty = true;
|
bool comp_empty = true;
|
||||||
std::vector<completion_t> comp;
|
std::vector<completion_t> comp;
|
||||||
|
@ -2459,7 +2476,6 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
|
|
||||||
wchar_t arr[READAHEAD_MAX + 1] = {};
|
wchar_t arr[READAHEAD_MAX + 1] = {};
|
||||||
arr[0] = evt.get_char();
|
arr[0] = evt.get_char();
|
||||||
last_char = arr[0];
|
|
||||||
|
|
||||||
for (size_t i = 1; i < limit; ++i) {
|
for (size_t i = 1; i < limit; ++i) {
|
||||||
if (!can_read(0)) {
|
if (!can_read(0)) {
|
||||||
|
@ -2471,7 +2487,6 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
auto next_event = input_readch(false);
|
auto next_event = input_readch(false);
|
||||||
if (event_is_normal_char(next_event)) {
|
if (event_is_normal_char(next_event)) {
|
||||||
arr[i] = next_event.get_char();
|
arr[i] = next_event.get_char();
|
||||||
last_char = arr[i];
|
|
||||||
} else {
|
} else {
|
||||||
// We need to process this in the outer loop.
|
// We need to process this in the outer loop.
|
||||||
assert(!event_needing_handling && "Should not have an unhandled event");
|
assert(!event_needing_handling && "Should not have an unhandled event");
|
||||||
|
@ -2487,6 +2502,9 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
if (el == &command_line) {
|
if (el == &command_line) {
|
||||||
clear_pager();
|
clear_pager();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Since we handled a normal character, we don't have a last command.
|
||||||
|
last_cmd.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// If there's still an event that we were unable to handle, then end the coalescing
|
// If there's still an event that we were unable to handle, then end the coalescing
|
||||||
|
@ -2508,29 +2526,38 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
assert((event_needing_handling->is_char() || event_needing_handling->is_readline()) &&
|
assert((event_needing_handling->is_char() || event_needing_handling->is_readline()) &&
|
||||||
"Should have a char or readline");
|
"Should have a char or readline");
|
||||||
wchar_t c = event_needing_handling->is_char() ? event_needing_handling->get_char()
|
maybe_t<readline_cmd_t> readline_cmd{};
|
||||||
: event_needing_handling->get_readline();
|
maybe_t<wchar_t> ordinary_char{};
|
||||||
|
if (event_needing_handling->is_readline()) {
|
||||||
|
readline_cmd = event_needing_handling->get_readline();
|
||||||
|
} else {
|
||||||
|
ordinary_char = event_needing_handling->get_char();
|
||||||
|
}
|
||||||
|
|
||||||
// If we get something other than a repaint, then stop coalescing them.
|
// If we get something other than a repaint, then stop coalescing them.
|
||||||
if (c != R_REPAINT) coalescing_repaints = false;
|
if (readline_cmd != rl::R_REPAINT) coalescing_repaints = false;
|
||||||
|
|
||||||
if (last_char != R_YANK && last_char != R_YANK_POP) yank_len = 0;
|
if (last_cmd != rl::R_YANK && last_cmd != rl::R_YANK_POP) {
|
||||||
|
yank_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
// Restore the text.
|
// Restore the text.
|
||||||
if (c == R_CANCEL && is_navigating_pager_contents()) {
|
if (readline_cmd) {
|
||||||
|
if (*readline_cmd == rl::R_CANCEL && is_navigating_pager_contents()) {
|
||||||
set_command_line_and_position(&command_line, cycle_command_line, cycle_cursor_pos);
|
set_command_line_and_position(&command_line, cycle_command_line, cycle_cursor_pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clear the pager if necessary.
|
// Clear the pager if necessary.
|
||||||
bool focused_on_search_field = (active_edit_line() == &pager.search_field_line);
|
bool focused_on_search_field = (active_edit_line() == &pager.search_field_line);
|
||||||
if (command_ends_paging(c, focused_on_search_field)) {
|
if (command_ends_paging(*readline_cmd, focused_on_search_field)) {
|
||||||
clear_pager();
|
clear_pager();
|
||||||
}
|
}
|
||||||
// std::fwprintf(stderr, L"\n\nchar: %ls\n\n", describe_char(c).c_str());
|
}
|
||||||
|
|
||||||
|
readline_cmd_t c = readline_cmd ? *readline_cmd : static_cast<readline_cmd_t>(0);
|
||||||
switch (c) {
|
switch (c) {
|
||||||
// Go to beginning of line.
|
// Go to beginning of line.
|
||||||
case R_BEGINNING_OF_LINE: {
|
case rl::R_BEGINNING_OF_LINE: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
while (el->position > 0 && el->text.at(el->position - 1) != L'\n') {
|
while (el->position > 0 && el->text.at(el->position - 1) != L'\n') {
|
||||||
update_buff_pos(el, el->position - 1);
|
update_buff_pos(el, el->position - 1);
|
||||||
|
@ -2539,7 +2566,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_END_OF_LINE: {
|
case rl::R_END_OF_LINE: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
if (el->position < el->size()) {
|
if (el->position < el->size()) {
|
||||||
const wchar_t *buff = el->text.c_str();
|
const wchar_t *buff = el->text.c_str();
|
||||||
|
@ -2553,22 +2580,22 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_BEGINNING_OF_BUFFER: {
|
case rl::R_BEGINNING_OF_BUFFER: {
|
||||||
update_buff_pos(&command_line, 0);
|
update_buff_pos(&command_line, 0);
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_END_OF_BUFFER: {
|
case rl::R_END_OF_BUFFER: {
|
||||||
update_buff_pos(&command_line, command_line.size());
|
update_buff_pos(&command_line, command_line.size());
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_CANCEL: {
|
case rl::R_CANCEL: {
|
||||||
// The only thing we can cancel right now is paging, which we handled up above.
|
// The only thing we can cancel right now is paging, which we handled up above.
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_FORCE_REPAINT:
|
case rl::R_FORCE_REPAINT:
|
||||||
case R_REPAINT: {
|
case rl::R_REPAINT: {
|
||||||
if (!coalescing_repaints) {
|
if (!coalescing_repaints) {
|
||||||
coalescing_repaints = true;
|
coalescing_repaints = true;
|
||||||
exec_prompt();
|
exec_prompt();
|
||||||
|
@ -2578,20 +2605,20 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_COMPLETE:
|
case rl::R_COMPLETE:
|
||||||
case R_COMPLETE_AND_SEARCH: {
|
case rl::R_COMPLETE_AND_SEARCH: {
|
||||||
if (!complete_func) break;
|
if (!complete_func) break;
|
||||||
|
|
||||||
// Use the command line only; it doesn't make sense to complete in any other line.
|
// Use the command line only; it doesn't make sense to complete in any other line.
|
||||||
editable_line_t *el = &command_line;
|
editable_line_t *el = &command_line;
|
||||||
if (is_navigating_pager_contents() || (!comp_empty && last_char == R_COMPLETE)) {
|
if (is_navigating_pager_contents() || (!comp_empty && last_cmd == rl::R_COMPLETE)) {
|
||||||
// The user typed R_COMPLETE more than once in a row. If we are not yet fully
|
// The user typed R_COMPLETE more than once in a row. If we are not yet fully
|
||||||
// disclosed, then become so; otherwise cycle through our available completions.
|
// disclosed, then become so; otherwise cycle through our available completions.
|
||||||
if (current_page_rendering.remaining_to_disclose > 0) {
|
if (current_page_rendering.remaining_to_disclose > 0) {
|
||||||
pager.set_fully_disclosed(true);
|
pager.set_fully_disclosed(true);
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
} else {
|
} else {
|
||||||
select_completion_in_direction(c == R_COMPLETE ? direction_next
|
select_completion_in_direction(c == rl::R_COMPLETE ? direction_next
|
||||||
: direction_prev);
|
: direction_prev);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -2651,11 +2678,11 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
cycle_command_line = el->text;
|
cycle_command_line = el->text;
|
||||||
cycle_cursor_pos = el->position;
|
cycle_cursor_pos = el->position;
|
||||||
|
|
||||||
bool cont_after_prefix_insertion = (c == R_COMPLETE_AND_SEARCH);
|
bool cont_after_prefix_insertion = (c == rl::R_COMPLETE_AND_SEARCH);
|
||||||
comp_empty = handle_completions(comp, cont_after_prefix_insertion);
|
comp_empty = handle_completions(comp, cont_after_prefix_insertion);
|
||||||
|
|
||||||
// Show the search field if requested and if we printed a list of completions.
|
// Show the search field if requested and if we printed a list of completions.
|
||||||
if (c == R_COMPLETE_AND_SEARCH && !comp_empty && !pager.empty()) {
|
if (c == rl::R_COMPLETE_AND_SEARCH && !comp_empty && !pager.empty()) {
|
||||||
pager.set_search_field_shown(true);
|
pager.set_search_field_shown(true);
|
||||||
select_completion_in_direction(direction_next);
|
select_completion_in_direction(direction_next);
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
|
@ -2663,7 +2690,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_PAGER_TOGGLE_SEARCH: {
|
case rl::R_PAGER_TOGGLE_SEARCH: {
|
||||||
if (!pager.empty()) {
|
if (!pager.empty()) {
|
||||||
// Toggle search, and begin navigating if we are now searching.
|
// Toggle search, and begin navigating if we are now searching.
|
||||||
bool sfs = pager.is_search_field_shown();
|
bool sfs = pager.is_search_field_shown();
|
||||||
|
@ -2676,7 +2703,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_KILL_LINE: {
|
case rl::R_KILL_LINE: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
const wchar_t *buff = el->text.c_str();
|
const wchar_t *buff = el->text.c_str();
|
||||||
const wchar_t *begin = &buff[el->position];
|
const wchar_t *begin = &buff[el->position];
|
||||||
|
@ -2688,11 +2715,11 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
|
|
||||||
size_t len = end - begin;
|
size_t len = end - begin;
|
||||||
if (len) {
|
if (len) {
|
||||||
kill(el, begin - buff, len, KILL_APPEND, last_char != R_KILL_LINE);
|
kill(el, begin - buff, len, KILL_APPEND, last_cmd != rl::R_KILL_LINE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_BACKWARD_KILL_LINE: {
|
case rl::R_BACKWARD_KILL_LINE: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
if (el->position <= 0) {
|
if (el->position <= 0) {
|
||||||
break;
|
break;
|
||||||
|
@ -2711,10 +2738,10 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
assert(end >= begin);
|
assert(end >= begin);
|
||||||
size_t len = std::max<size_t>(end - begin, 1);
|
size_t len = std::max<size_t>(end - begin, 1);
|
||||||
begin = end - len;
|
begin = end - len;
|
||||||
kill(el, begin - buff, len, KILL_PREPEND, last_char != R_BACKWARD_KILL_LINE);
|
kill(el, begin - buff, len, KILL_PREPEND, last_cmd != rl::R_BACKWARD_KILL_LINE);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_KILL_WHOLE_LINE: {
|
case rl::R_KILL_WHOLE_LINE: {
|
||||||
// We match the emacs behavior here: "kills the entire line including the following
|
// We match the emacs behavior here: "kills the entire line including the following
|
||||||
// newline".
|
// newline".
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
|
@ -2740,17 +2767,17 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
assert(end >= begin);
|
assert(end >= begin);
|
||||||
|
|
||||||
if (end > begin) {
|
if (end > begin) {
|
||||||
kill(el, begin, end - begin, KILL_APPEND, last_char != R_KILL_WHOLE_LINE);
|
kill(el, begin, end - begin, KILL_APPEND, last_cmd != rl::R_KILL_WHOLE_LINE);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_YANK: {
|
case rl::R_YANK: {
|
||||||
wcstring yank_str = kill_yank();
|
wcstring yank_str = kill_yank();
|
||||||
insert_string(active_edit_line(), yank_str);
|
insert_string(active_edit_line(), yank_str);
|
||||||
yank_len = yank_str.size();
|
yank_len = yank_str.size();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_YANK_POP: {
|
case rl::R_YANK_POP: {
|
||||||
if (yank_len) {
|
if (yank_len) {
|
||||||
for (size_t i = 0; i < yank_len; i++) remove_backward();
|
for (size_t i = 0; i < yank_len; i++) remove_backward();
|
||||||
|
|
||||||
|
@ -2760,21 +2787,11 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Escape was pressed.
|
case rl::R_BACKWARD_DELETE_CHAR: {
|
||||||
case L'\x1B': {
|
|
||||||
if (history_search.active()) {
|
|
||||||
history_search.go_to_end();
|
|
||||||
update_command_line_from_history_search();
|
|
||||||
history_search.reset();
|
|
||||||
}
|
|
||||||
assert(!history_search.active());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case R_BACKWARD_DELETE_CHAR: {
|
|
||||||
remove_backward();
|
remove_backward();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_DELETE_CHAR: {
|
case rl::R_DELETE_CHAR: {
|
||||||
// Remove the current character in the character buffer and on the screen using
|
// Remove the current character in the character buffer and on the screen using
|
||||||
// syntax highlighting, etc.
|
// syntax highlighting, etc.
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
|
@ -2784,9 +2801,9 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Evaluate. If the current command is unfinished, or if the charater is escaped using a
|
// Evaluate. If the current command is unfinished, or if the charater is escaped
|
||||||
// backslash, insert a newline.
|
// using a backslash, insert a newline.
|
||||||
case R_EXECUTE: {
|
case rl::R_EXECUTE: {
|
||||||
// If the user hits return while navigating the pager, it only clears the pager.
|
// If the user hits return while navigating the pager, it only clears the pager.
|
||||||
if (is_navigating_pager_contents()) {
|
if (is_navigating_pager_contents()) {
|
||||||
clear_pager();
|
clear_pager();
|
||||||
|
@ -2870,14 +2887,14 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case R_HISTORY_SEARCH_BACKWARD:
|
case rl::R_HISTORY_SEARCH_BACKWARD:
|
||||||
case R_HISTORY_TOKEN_SEARCH_BACKWARD:
|
case rl::R_HISTORY_TOKEN_SEARCH_BACKWARD:
|
||||||
case R_HISTORY_SEARCH_FORWARD:
|
case rl::R_HISTORY_SEARCH_FORWARD:
|
||||||
case R_HISTORY_TOKEN_SEARCH_FORWARD: {
|
case rl::R_HISTORY_TOKEN_SEARCH_FORWARD: {
|
||||||
if (history_search.is_at_end()) {
|
if (history_search.is_at_end()) {
|
||||||
const editable_line_t *el = &command_line;
|
const editable_line_t *el = &command_line;
|
||||||
bool by_token = (c == R_HISTORY_TOKEN_SEARCH_BACKWARD) ||
|
bool by_token = (c == rl::R_HISTORY_TOKEN_SEARCH_BACKWARD) ||
|
||||||
(c == R_HISTORY_TOKEN_SEARCH_FORWARD);
|
(c == rl::R_HISTORY_TOKEN_SEARCH_FORWARD);
|
||||||
if (by_token) {
|
if (by_token) {
|
||||||
// Searching by token.
|
// Searching by token.
|
||||||
const wchar_t *begin, *end;
|
const wchar_t *begin, *end;
|
||||||
|
@ -2904,8 +2921,8 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (history_search.active()) {
|
if (history_search.active()) {
|
||||||
history_search_direction_t dir =
|
history_search_direction_t dir = (c == rl::R_HISTORY_SEARCH_BACKWARD ||
|
||||||
(c == R_HISTORY_SEARCH_BACKWARD || c == R_HISTORY_TOKEN_SEARCH_BACKWARD)
|
c == rl::R_HISTORY_TOKEN_SEARCH_BACKWARD)
|
||||||
? history_search_direction_t::backward
|
? history_search_direction_t::backward
|
||||||
: history_search_direction_t::forward;
|
: history_search_direction_t::forward;
|
||||||
history_search.move_in_direction(dir);
|
history_search.move_in_direction(dir);
|
||||||
|
@ -2913,7 +2930,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_BACKWARD_CHAR: {
|
case rl::R_BACKWARD_CHAR: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
if (is_navigating_pager_contents()) {
|
if (is_navigating_pager_contents()) {
|
||||||
select_completion_in_direction(direction_west);
|
select_completion_in_direction(direction_west);
|
||||||
|
@ -2923,7 +2940,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_FORWARD_CHAR: {
|
case rl::R_FORWARD_CHAR: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
if (is_navigating_pager_contents()) {
|
if (is_navigating_pager_contents()) {
|
||||||
select_completion_in_direction(direction_east);
|
select_completion_in_direction(direction_east);
|
||||||
|
@ -2935,51 +2952,54 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_BACKWARD_KILL_WORD:
|
case rl::R_BACKWARD_KILL_WORD:
|
||||||
case R_BACKWARD_KILL_PATH_COMPONENT:
|
case rl::R_BACKWARD_KILL_PATH_COMPONENT:
|
||||||
case R_BACKWARD_KILL_BIGWORD: {
|
case rl::R_BACKWARD_KILL_BIGWORD: {
|
||||||
move_word_style_t style =
|
move_word_style_t style =
|
||||||
(c == R_BACKWARD_KILL_BIGWORD
|
(c == rl::R_BACKWARD_KILL_BIGWORD
|
||||||
? move_word_style_whitespace
|
? move_word_style_whitespace
|
||||||
: c == R_BACKWARD_KILL_PATH_COMPONENT ? move_word_style_path_components
|
: c == rl::R_BACKWARD_KILL_PATH_COMPONENT ? move_word_style_path_components
|
||||||
: move_word_style_punctuation);
|
: move_word_style_punctuation);
|
||||||
// Is this the same killring item as the last kill?
|
// Is this the same killring item as the last kill?
|
||||||
bool newv = (last_char != R_BACKWARD_KILL_WORD &&
|
bool newv = (last_cmd != rl::R_BACKWARD_KILL_WORD &&
|
||||||
last_char != R_BACKWARD_KILL_PATH_COMPONENT &&
|
last_cmd != rl::R_BACKWARD_KILL_PATH_COMPONENT &&
|
||||||
last_char != R_BACKWARD_KILL_BIGWORD);
|
last_cmd != rl::R_BACKWARD_KILL_BIGWORD);
|
||||||
move_word(active_edit_line(), MOVE_DIR_LEFT, true /* erase */, style, newv);
|
move_word(active_edit_line(), MOVE_DIR_LEFT, true /* erase */, style, newv);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_KILL_WORD:
|
case rl::R_KILL_WORD:
|
||||||
case R_KILL_BIGWORD: {
|
case rl::R_KILL_BIGWORD: {
|
||||||
// The "bigword" functions differ only in that they move to the next whitespace, not punctuation.
|
// The "bigword" functions differ only in that they move to the next whitespace, not
|
||||||
auto move_style = (c == R_KILL_WORD) ? move_word_style_punctuation : move_word_style_whitespace;
|
// punctuation.
|
||||||
|
auto move_style = (c == rl::R_KILL_WORD) ? move_word_style_punctuation
|
||||||
|
: move_word_style_whitespace;
|
||||||
move_word(active_edit_line(), MOVE_DIR_RIGHT, true /* erase */, move_style,
|
move_word(active_edit_line(), MOVE_DIR_RIGHT, true /* erase */, move_style,
|
||||||
last_char != c /* same kill item if same movement */);
|
last_cmd != c /* same kill item if same movement */);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_BACKWARD_WORD:
|
case rl::R_BACKWARD_WORD:
|
||||||
case R_BACKWARD_BIGWORD: {
|
case rl::R_BACKWARD_BIGWORD: {
|
||||||
auto move_style = (c == R_BACKWARD_WORD) ? move_word_style_punctuation : move_word_style_whitespace;
|
auto move_style = (c == rl::R_BACKWARD_WORD) ? move_word_style_punctuation
|
||||||
|
: move_word_style_whitespace;
|
||||||
move_word(active_edit_line(), MOVE_DIR_LEFT, false /* do not erase */, move_style,
|
move_word(active_edit_line(), MOVE_DIR_LEFT, false /* do not erase */, move_style,
|
||||||
false);
|
false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_FORWARD_WORD:
|
case rl::R_FORWARD_WORD:
|
||||||
case R_FORWARD_BIGWORD: {
|
case rl::R_FORWARD_BIGWORD: {
|
||||||
auto move_style = (c == R_FORWARD_WORD) ? move_word_style_punctuation : move_word_style_whitespace;
|
auto move_style = (c == rl::R_FORWARD_WORD) ? move_word_style_punctuation
|
||||||
|
: move_word_style_whitespace;
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
if (el->position < el->size()) {
|
if (el->position < el->size()) {
|
||||||
move_word(el, MOVE_DIR_RIGHT, false /* do not erase */,
|
move_word(el, MOVE_DIR_RIGHT, false /* do not erase */, move_style, false);
|
||||||
move_style, false);
|
|
||||||
} else {
|
} else {
|
||||||
accept_autosuggestion(false, move_style);
|
accept_autosuggestion(false, move_style);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_BEGINNING_OF_HISTORY:
|
case rl::R_BEGINNING_OF_HISTORY:
|
||||||
case R_END_OF_HISTORY: {
|
case rl::R_END_OF_HISTORY: {
|
||||||
bool up = (c == R_BEGINNING_OF_HISTORY);
|
bool up = (c == rl::R_BEGINNING_OF_HISTORY);
|
||||||
if (is_navigating_pager_contents()) {
|
if (is_navigating_pager_contents()) {
|
||||||
select_completion_in_direction(up ? direction_page_north
|
select_completion_in_direction(up ? direction_page_north
|
||||||
: direction_page_south);
|
: direction_page_south);
|
||||||
|
@ -2993,12 +3013,12 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_UP_LINE:
|
case rl::R_UP_LINE:
|
||||||
case R_DOWN_LINE: {
|
case rl::R_DOWN_LINE: {
|
||||||
if (is_navigating_pager_contents()) {
|
if (is_navigating_pager_contents()) {
|
||||||
// We are already navigating pager contents.
|
// We are already navigating pager contents.
|
||||||
selection_direction_t direction;
|
selection_direction_t direction;
|
||||||
if (c == R_DOWN_LINE) {
|
if (c == rl::R_DOWN_LINE) {
|
||||||
// Down arrow is always south.
|
// Down arrow is always south.
|
||||||
direction = direction_south;
|
direction = direction_south;
|
||||||
} else if (selection_is_at_top()) {
|
} else if (selection_is_at_top()) {
|
||||||
|
@ -3013,7 +3033,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
select_completion_in_direction(direction);
|
select_completion_in_direction(direction);
|
||||||
} else if (!pager.empty()) {
|
} else if (!pager.empty()) {
|
||||||
// We pressed a direction with a non-empty pager, begin navigation.
|
// We pressed a direction with a non-empty pager, begin navigation.
|
||||||
select_completion_in_direction(c == R_DOWN_LINE ? direction_south
|
select_completion_in_direction(c == rl::R_DOWN_LINE ? direction_south
|
||||||
: direction_north);
|
: direction_north);
|
||||||
} else {
|
} else {
|
||||||
// Not navigating the pager contents.
|
// Not navigating the pager contents.
|
||||||
|
@ -3021,7 +3041,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
int line_old = parse_util_get_line_from_offset(el->text, el->position);
|
int line_old = parse_util_get_line_from_offset(el->text, el->position);
|
||||||
int line_new;
|
int line_new;
|
||||||
|
|
||||||
if (c == R_UP_LINE)
|
if (c == rl::R_UP_LINE)
|
||||||
line_new = line_old - 1;
|
line_new = line_old - 1;
|
||||||
else
|
else
|
||||||
line_new = line_old + 1;
|
line_new = line_old + 1;
|
||||||
|
@ -3055,17 +3075,17 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_SUPPRESS_AUTOSUGGESTION: {
|
case rl::R_SUPPRESS_AUTOSUGGESTION: {
|
||||||
suppress_autosuggestion = true;
|
suppress_autosuggestion = true;
|
||||||
autosuggestion.clear();
|
autosuggestion.clear();
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_ACCEPT_AUTOSUGGESTION: {
|
case rl::R_ACCEPT_AUTOSUGGESTION: {
|
||||||
accept_autosuggestion(true);
|
accept_autosuggestion(true);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_TRANSPOSE_CHARS: {
|
case rl::R_TRANSPOSE_CHARS: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
if (el->size() < 2) {
|
if (el->size() < 2) {
|
||||||
break;
|
break;
|
||||||
|
@ -3085,7 +3105,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_TRANSPOSE_WORDS: {
|
case rl::R_TRANSPOSE_WORDS: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
size_t len = el->size();
|
size_t len = el->size();
|
||||||
const wchar_t *buff = el->text.c_str();
|
const wchar_t *buff = el->text.c_str();
|
||||||
|
@ -3126,9 +3146,9 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_UPCASE_WORD:
|
case rl::R_UPCASE_WORD:
|
||||||
case R_DOWNCASE_WORD:
|
case rl::R_DOWNCASE_WORD:
|
||||||
case R_CAPITALIZE_WORD: {
|
case rl::R_CAPITALIZE_WORD: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
// For capitalize_word, whether we've capitalized a character so far.
|
// For capitalize_word, whether we've capitalized a character so far.
|
||||||
bool capitalized_first = false;
|
bool capitalized_first = false;
|
||||||
|
@ -3142,10 +3162,10 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
// We always change the case; this decides whether we go uppercase (true) or
|
// We always change the case; this decides whether we go uppercase (true) or
|
||||||
// lowercase (false).
|
// lowercase (false).
|
||||||
bool make_uppercase;
|
bool make_uppercase;
|
||||||
if (c == R_CAPITALIZE_WORD)
|
if (c == rl::R_CAPITALIZE_WORD)
|
||||||
make_uppercase = !capitalized_first && iswalnum(chr);
|
make_uppercase = !capitalized_first && iswalnum(chr);
|
||||||
else
|
else
|
||||||
make_uppercase = (c == R_UPCASE_WORD);
|
make_uppercase = (c == rl::R_UPCASE_WORD);
|
||||||
|
|
||||||
// Apply the operation and then record what we did.
|
// Apply the operation and then record what we did.
|
||||||
if (make_uppercase)
|
if (make_uppercase)
|
||||||
|
@ -3161,11 +3181,11 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_BEGIN_SELECTION:
|
case rl::R_BEGIN_SELECTION:
|
||||||
case R_END_SELECTION: {
|
case rl::R_END_SELECTION: {
|
||||||
sel_start_pos = command_line.position;
|
sel_start_pos = command_line.position;
|
||||||
sel_stop_pos = command_line.position;
|
sel_stop_pos = command_line.position;
|
||||||
if (c == R_BEGIN_SELECTION) {
|
if (c == rl::R_BEGIN_SELECTION) {
|
||||||
sel_active = true;
|
sel_active = true;
|
||||||
sel_begin_pos = command_line.position;
|
sel_begin_pos = command_line.position;
|
||||||
} else {
|
} else {
|
||||||
|
@ -3174,7 +3194,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_SWAP_SELECTION_START_STOP: {
|
case rl::R_SWAP_SELECTION_START_STOP: {
|
||||||
if (!sel_active) break;
|
if (!sel_active) break;
|
||||||
size_t tmp = sel_begin_pos;
|
size_t tmp = sel_begin_pos;
|
||||||
sel_begin_pos = command_line.position;
|
sel_begin_pos = command_line.position;
|
||||||
|
@ -3183,22 +3203,24 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
update_buff_pos(el, tmp);
|
update_buff_pos(el, tmp);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_KILL_SELECTION: {
|
case rl::R_KILL_SELECTION: {
|
||||||
bool newv = (last_char != R_KILL_SELECTION);
|
bool newv = (last_cmd != rl::R_KILL_SELECTION);
|
||||||
size_t start, len;
|
size_t start, len;
|
||||||
if (reader_get_selection(&start, &len)) {
|
if (reader_get_selection(&start, &len)) {
|
||||||
kill(&command_line, start, len, KILL_APPEND, newv);
|
kill(&command_line, start, len, KILL_APPEND, newv);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_FORWARD_JUMP:
|
case rl::R_FORWARD_JUMP:
|
||||||
case R_BACKWARD_JUMP:
|
case rl::R_BACKWARD_JUMP:
|
||||||
case R_FORWARD_JUMP_TILL:
|
case rl::R_FORWARD_JUMP_TILL:
|
||||||
case R_BACKWARD_JUMP_TILL: {
|
case rl::R_BACKWARD_JUMP_TILL: {
|
||||||
auto direction = (c == R_FORWARD_JUMP || c == R_FORWARD_JUMP_TILL) ?
|
auto direction = (c == rl::R_FORWARD_JUMP || c == rl::R_FORWARD_JUMP_TILL)
|
||||||
jump_direction_t::forward : jump_direction_t::backward;
|
? jump_direction_t::forward
|
||||||
auto precision = (c == R_FORWARD_JUMP || c == R_BACKWARD_JUMP) ?
|
: jump_direction_t::backward;
|
||||||
jump_precision_t::to : jump_precision_t::till;
|
auto precision = (c == rl::R_FORWARD_JUMP || c == rl::R_BACKWARD_JUMP)
|
||||||
|
? jump_precision_t::to
|
||||||
|
: jump_precision_t::till;
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
wchar_t target = input_function_pop_arg();
|
wchar_t target = input_function_pop_arg();
|
||||||
bool success = jump(direction, precision, el, target);
|
bool success = jump(direction, precision, el, target);
|
||||||
|
@ -3207,7 +3229,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_REPEAT_JUMP: {
|
case rl::R_REPEAT_JUMP: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
|
@ -3219,7 +3241,7 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case R_REVERSE_REPEAT_JUMP: {
|
case rl::R_REVERSE_REPEAT_JUMP: {
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
bool success = false;
|
bool success = false;
|
||||||
jump_direction_t original_dir, dir;
|
jump_direction_t original_dir, dir;
|
||||||
|
@ -3241,9 +3263,20 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
reader_repaint_needed();
|
reader_repaint_needed();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default: {
|
}
|
||||||
// Other, if a normal character, we add it to the command.
|
|
||||||
if (!fish_reserved_codepoint(c) && (c >= L' ' || c == L'\n' || c == L'\r') &&
|
if (ordinary_char) {
|
||||||
|
wchar_t c = *ordinary_char;
|
||||||
|
|
||||||
|
if (c == L'\x1B') {
|
||||||
|
// Escape was pressed.
|
||||||
|
if (history_search.active()) {
|
||||||
|
history_search.go_to_end();
|
||||||
|
update_command_line_from_history_search();
|
||||||
|
history_search.reset();
|
||||||
|
}
|
||||||
|
assert(!history_search.active());
|
||||||
|
} else if (!fish_reserved_codepoint(c) && (c >= L' ' || c == L'\n' || c == L'\r') &&
|
||||||
c != 0x7F) {
|
c != 0x7F) {
|
||||||
// Regular character.
|
// Regular character.
|
||||||
editable_line_t *el = active_edit_line();
|
editable_line_t *el = active_edit_line();
|
||||||
|
@ -3259,18 +3292,12 @@ maybe_t<wcstring> reader_data_t::readline(int nchars) {
|
||||||
// reason to report this to the user unless they've enabled debugging output.
|
// reason to report this to the user unless they've enabled debugging output.
|
||||||
debug(2, _(L"Unknown key binding 0x%X"), c);
|
debug(2, _(L"Unknown key binding 0x%X"), c);
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((c != R_HISTORY_SEARCH_BACKWARD) && (c != R_HISTORY_SEARCH_FORWARD) &&
|
if (!readline_cmd || command_ends_history_search(*readline_cmd)) {
|
||||||
(c != R_HISTORY_TOKEN_SEARCH_BACKWARD) && (c != R_HISTORY_TOKEN_SEARCH_FORWARD) &&
|
|
||||||
(c != R_REPAINT) && (c != R_FORCE_REPAINT)) {
|
|
||||||
history_search.reset();
|
history_search.reset();
|
||||||
}
|
}
|
||||||
|
last_cmd = readline_cmd;
|
||||||
last_char = c;
|
|
||||||
|
|
||||||
repaint_if_needed();
|
repaint_if_needed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user