mirror of
https://github.com/fish-shell/fish-shell.git
synced 2026-05-31 20:31:19 -03:00
Change vi-mode tilde to toggle character case
This updates the behavior of tilde to match the behavior found in vim. In vim, tilde toggles the case of the character under the cursor and advances one character. In visual mode, the case of each selected character is toggled, the cursor position moves to the beginning of the selection, and the mode is changed to normal. In fish, tilde capitalizes the current letter and advances one word. There is no current tilde command for visual mode in fish. This patch adds the readline commands `togglecase-letter` and `togglecase-selection` to match the behavior of vim more closely. The only difference is that in visual mode, the cursor is not modified. Modifying the cursor in visual mode would require either moving it in `togglecase-selection`, which seems outside its scope or adding something like a `move-to-selection-start` readline command.
This commit is contained in:
committed by
Johannes Altmanninger
parent
93b86bbe63
commit
a3dfa21737
@@ -187,7 +187,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
|
||||
bind -s --preset -m insert ci backward-jump-till and repeat-jump-reverse and begin-selection repeat-jump kill-selection end-selection repaint-mode
|
||||
bind -s --preset -m insert ca backward-jump and repeat-jump-reverse and begin-selection repeat-jump kill-selection end-selection repaint-mode
|
||||
|
||||
bind -s --preset '~' capitalize-word
|
||||
bind -s --preset '~' togglecase-char forward-char
|
||||
bind -s --preset gu downcase-word
|
||||
bind -s --preset gU upcase-word
|
||||
|
||||
@@ -291,6 +291,7 @@ function fish_vi_key_bindings --description 'vi-like key bindings for fish'
|
||||
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 '~' togglecase-selection end-selection repaint-mode
|
||||
|
||||
bind -s --preset -M visual -m default \cc end-selection repaint-mode
|
||||
bind -s --preset -M visual -m default \e end-selection repaint-mode
|
||||
|
||||
@@ -123,6 +123,8 @@ static const input_function_metadata_t input_function_metadata[] = {
|
||||
{readline_cmd_t::upcase_word, L"upcase-word"},
|
||||
{readline_cmd_t::downcase_word, L"downcase-word"},
|
||||
{readline_cmd_t::capitalize_word, L"capitalize-word"},
|
||||
{readline_cmd_t::togglecase_char, L"togglecase-char"},
|
||||
{readline_cmd_t::togglecase_selection, L"togglecase-selection"},
|
||||
{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"},
|
||||
|
||||
@@ -48,6 +48,8 @@ enum class readline_cmd_t {
|
||||
upcase_word,
|
||||
downcase_word,
|
||||
capitalize_word,
|
||||
togglecase_char,
|
||||
togglecase_selection,
|
||||
execute,
|
||||
beginning_of_buffer,
|
||||
end_of_buffer,
|
||||
|
||||
@@ -3219,6 +3219,72 @@ void reader_data_t::handle_readline_command(readline_cmd_t c, readline_loop_stat
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rl::togglecase_char: {
|
||||
editable_line_t *el = active_edit_line();
|
||||
size_t buff_pos = el->position();
|
||||
|
||||
// Check that the cursor is on a character
|
||||
if (buff_pos < el->size()) {
|
||||
wchar_t chr = el->text().at(buff_pos);
|
||||
wcstring replacement;
|
||||
|
||||
// Toggle the case of the current character
|
||||
bool make_uppercase = iswlower(chr);
|
||||
if (make_uppercase) {
|
||||
chr = towupper(chr);
|
||||
} else {
|
||||
chr = tolower(chr);
|
||||
}
|
||||
|
||||
replacement.push_back(chr);
|
||||
el->replace_substring(buff_pos, (size_t)1, std::move(replacement));
|
||||
|
||||
// Restore the buffer position since replace_substring moves
|
||||
// the buffer position ahead of the replaced text.
|
||||
update_buff_pos(el, buff_pos);
|
||||
|
||||
command_line_changed(el);
|
||||
super_highlight_me_plenty();
|
||||
reader_repaint_needed();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rl::togglecase_selection: {
|
||||
editable_line_t *el = active_edit_line();
|
||||
|
||||
// Check that we have an active selection and get the bounds.
|
||||
size_t start, len;
|
||||
if (reader_get_selection(&start, &len)) {
|
||||
size_t buff_pos = el->position();
|
||||
wcstring replacement;
|
||||
|
||||
// Loop through the selected characters and toggle their case.
|
||||
for (size_t pos = start; pos < start + len && pos < el->size(); pos++) {
|
||||
wchar_t chr = el->text().at(pos);
|
||||
|
||||
// Toggle the case of the current character.
|
||||
bool make_uppercase = iswlower(chr);
|
||||
if (make_uppercase) {
|
||||
chr = towupper(chr);
|
||||
} else {
|
||||
chr = tolower(chr);
|
||||
}
|
||||
|
||||
replacement.push_back(chr);
|
||||
}
|
||||
|
||||
el->replace_substring(start, len, std::move(replacement));
|
||||
|
||||
// Restore the buffer position since replace_substring moves
|
||||
// the buffer position ahead of the replaced text.
|
||||
update_buff_pos(el, buff_pos);
|
||||
|
||||
command_line_changed(el);
|
||||
super_highlight_me_plenty();
|
||||
reader_repaint_needed();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case rl::upcase_word:
|
||||
case rl::downcase_word:
|
||||
case rl::capitalize_word: {
|
||||
|
||||
Reference in New Issue
Block a user