From 153c3aaab23ec97436c53f6a35d9e82862bd44d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ji=C5=99=C3=AD=20Techet?= Date: Wed, 1 Sep 2021 12:49:13 -0700 Subject: [PATCH] vimode: Add special handling to include destination char for some commands For abcde; simple 't;' does the right thing and places the cursor on top of character 'e' just before ';'. However, for composed commands such as 'dt;', vim also deletes the character 'e' which vimode currently doesn't. Vim behaves in a bit inconsistent way regarding this behavior - while for 'dw' (delete all until next word) it doesn't delete the first character of the next word onto which the cursor is placed, for 'de' (delete until next word end) it includes the final character of the deleted word. This behavior makes sense from the use case point of view but makes handling of such situations inconsistent. This patch lists functions which behave this way and includes the destination character to the selection. Fixes #1052. --- vimode/src/cmd-runner.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/vimode/src/cmd-runner.c b/vimode/src/cmd-runner.c index 2dc315402..d56324b50 100644 --- a/vimode/src/cmd-runner.c +++ b/vimode/src/cmd-runner.c @@ -167,6 +167,21 @@ typedef struct { /* END */ +/* From the above commands, these commands also include the character + * where the destionation movement ends for motion commands (e.g. 'de' will + * delete the word including the last character) */ +CmdDef include_dest_char_movement_cmds[] = { + {cmd_goto_next_char, GDK_KEY_f, 0, 0, 0, TRUE, FALSE}, + {cmd_goto_next_char_before, GDK_KEY_t, 0, 0, 0, TRUE, FALSE}, + {cmd_goto_next_word_end, GDK_KEY_e, 0, 0, 0, FALSE, FALSE}, + {cmd_goto_next_word_end_space, GDK_KEY_E, 0, 0, 0, FALSE, FALSE}, + {cmd_goto_previous_word, GDK_KEY_b, 0, 0, 0, FALSE, FALSE}, + {cmd_goto_previous_word_space, GDK_KEY_B, 0, 0, 0, FALSE, FALSE}, + {cmd_goto_matching_brace, GDK_KEY_percent, 0, 0, 0, FALSE, FALSE}, + {NULL, 0, 0, 0, 0, FALSE, FALSE} +}; + + CmdDef movement_cmds[] = { MOVEMENT_CMDS {NULL, 0, 0, 0, 0, FALSE, FALSE} @@ -567,7 +582,8 @@ static void perform_cmd(CmdDef *def, CmdContext *ctx) if (VI_IS_COMMAND(vi_get_mode())) { gboolean is_text_object_cmd = is_in_cmd_group(text_object_cmds, def); - if (is_text_object_cmd ||is_in_cmd_group(movement_cmds, def)) + gboolean is_include_dest_char_movement_cmd = is_in_cmd_group(include_dest_char_movement_cmds, def); + if (is_text_object_cmd || is_in_cmd_group(movement_cmds, def)) { def = get_cmd_to_run(top, operator_cmds, TRUE); if (def) @@ -585,6 +601,12 @@ static void perform_cmd(CmdDef *def, CmdContext *ctx) { sel_start = MIN(new_pos, orig_pos); sel_len = ABS(new_pos - orig_pos); + if (sel_len > 0 && is_include_dest_char_movement_cmd) + { + sel_len++; + if (new_pos < orig_pos) + sel_start--; + } } cmd_params_init(¶m, ctx->sci, 1, FALSE, top, TRUE,