mirror of
https://github.com/fish-shell/fish-shell.git
synced 2024-11-22 05:01:07 +08:00
Improve newline behavior of kill-whole-line
Previously, `kill-whole-line` kills the line and its following newline. This is insufficient when we are on the last line, because it would not actually clear the line. The cursor would stay on the line, which is not the correct behavior for bindings like `dd`. Also, `cc` in vi-mode used `kill-whole-line`, which is not correct because it should not remove any newlines. We have to introduce another special input function (`kill-inner-line`) to fix this.
This commit is contained in:
parent
025acfe45a
commit
cf620c829b
|
@ -93,6 +93,8 @@ Interactive improvements
|
|||
New or improved bindings
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
- Keyboard shortcut :kbd:`Alt-S` (previously: toggle ``sudo`` prepended to current commandline contents) now supports ``doas`` on systems without ``sudo`` (:issue:`8942`).
|
||||
- The ``kill-whole-line`` special input function now kills the newline preceeding the last line. This makes ``dd`` in vi-mode clear the last line properly.
|
||||
- Introduce the ``kill-inner-line`` special input function, which kills the line without any newlines, allowing ``cc`` in vi-mode to clear the line while preserving newlines.
|
||||
|
||||
Improved prompts
|
||||
^^^^^^^^^^^^^^^^
|
||||
|
|
|
@ -230,7 +230,10 @@ The following special input functions are available:
|
|||
move the selected text to the killring
|
||||
|
||||
``kill-whole-line``
|
||||
move the line to the killring
|
||||
move the line (including the following newline) to the killring. If the line is the last line, its preceeding newline is also removed
|
||||
|
||||
``kill-inner-line``
|
||||
move the line (without the following newline) to the killring
|
||||
|
||||
``kill-word``
|
||||
move the next word to the killring
|
||||
|
|
|
@ -153,8 +153,8 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
|
|||
bind -s --preset 'd,' begin-selection repeat-jump-reverse kill-selection end-selection
|
||||
|
||||
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 S kill-inner-line repaint-mode
|
||||
bind -s --preset -m insert cc kill-inner-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
|
||||
|
|
|
@ -139,6 +139,7 @@ static constexpr const input_function_metadata_t input_function_metadata[] = {
|
|||
{L"insert-line-over", readline_cmd_t::insert_line_over},
|
||||
{L"insert-line-under", readline_cmd_t::insert_line_under},
|
||||
{L"kill-bigword", readline_cmd_t::kill_bigword},
|
||||
{L"kill-inner-line", readline_cmd_t::kill_inner_line},
|
||||
{L"kill-line", readline_cmd_t::kill_line},
|
||||
{L"kill-selection", readline_cmd_t::kill_selection},
|
||||
{L"kill-whole-line", readline_cmd_t::kill_whole_line},
|
||||
|
|
|
@ -37,6 +37,7 @@ enum class readline_cmd_t {
|
|||
end_of_history,
|
||||
backward_kill_line,
|
||||
kill_whole_line,
|
||||
kill_inner_line,
|
||||
kill_word,
|
||||
kill_bigword,
|
||||
backward_kill_word,
|
||||
|
|
|
@ -1479,6 +1479,7 @@ static bool command_ends_paging(readline_cmd_t c, bool focused_on_search_field)
|
|||
case rl::yank_pop:
|
||||
case rl::backward_kill_line:
|
||||
case rl::kill_whole_line:
|
||||
case rl::kill_inner_line:
|
||||
case rl::kill_word:
|
||||
case rl::kill_bigword:
|
||||
case rl::backward_kill_word:
|
||||
|
@ -3295,9 +3296,10 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
|
|||
kill(el, begin - buff, len, KILL_PREPEND, rls.last_cmd != rl::backward_kill_line);
|
||||
break;
|
||||
}
|
||||
case rl::kill_whole_line: {
|
||||
// We match the emacs behavior here: "kills the entire line including the following
|
||||
// newline".
|
||||
case rl::kill_whole_line: // We match the emacs behavior here: "kills the entire line
|
||||
// including the following newline".
|
||||
case rl::kill_inner_line: // Do not kill the following newline
|
||||
{
|
||||
editable_line_t *el = active_edit_line();
|
||||
const wchar_t *buff = el->text().c_str();
|
||||
|
||||
|
@ -3312,16 +3314,27 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
|
|||
|
||||
// Push end forwards to just past the next newline, or just past the last char.
|
||||
size_t end = el->position();
|
||||
while (buff[end] != L'\0') {
|
||||
end++;
|
||||
if (buff[end - 1] == L'\n') {
|
||||
for (;; end++) {
|
||||
if (buff[end] == L'\0') {
|
||||
if (c == rl::kill_whole_line && begin > 0) {
|
||||
// We are on the last line. Delete the newline in the beginning to clear
|
||||
// this line.
|
||||
begin--;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (buff[end] == L'\n') {
|
||||
if (c == rl::kill_whole_line) {
|
||||
end++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(end >= begin);
|
||||
|
||||
if (end > begin) {
|
||||
kill(el, begin, end - begin, KILL_APPEND, rls.last_cmd != rl::kill_whole_line);
|
||||
kill(el, begin, end - begin, KILL_APPEND, rls.last_cmd != c);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user