Branch: refs/heads/master Author: Jiří Techet techet@gmail.com Committer: Jiří Techet techet@gmail.com Date: Mon, 07 Oct 2019 12:34:19 UTC Commit: b77774eb46833aba061f537cef5ffb5c8b45eaab https://github.com/geany/geany-plugins/commit/b77774eb46833aba061f537cef5ffb...
Log Message: ----------- vimode: Don't use word navigation from Scintilla
Scintilla does different things when using SCI_WORDRIGHT, SCI_WORDLEFT, SCI_WORDRIGHTEND and SCI_WORDLEFTEND than what we want for commands like "w", "b", "W", "B", "e", "E", "ge", "gE". For instance, for
ident1 = id|ent2+ident3;
where | represents the cursor, SCI_WORDRIGHT does
ident1 = ident2+|ident3;
while Vim's "w" does
ident1 = ident2|+ident3;
For this reason we have to reimplement all the word navigation by ourselves to better emulate the behavior of Vim. This patch tries to do that.
Modified Paths: -------------- vimode/src/Makefile.am vimode/src/cmd-runner.c vimode/src/cmds/motion-word.c vimode/src/cmds/motion-word.h vimode/src/cmds/motion.c vimode/src/cmds/motion.h
Modified: vimode/src/Makefile.am 2 lines changed, 2 insertions(+), 0 deletions(-) =================================================================== @@ -26,6 +26,8 @@ vi_srcs = \ excmd-prompt.c \ cmds/motion.h \ cmds/motion.c \ + cmds/motion-word.h \ + cmds/motion-word.c \ cmds/txtobjs.h \ cmds/txtobjs.c \ cmds/changemode.h \
Modified: vimode/src/cmd-runner.c 1 lines changed, 1 insertions(+), 0 deletions(-) =================================================================== @@ -20,6 +20,7 @@ #include "utils.h"
#include "cmds/motion.h" +#include "cmds/motion-word.h" #include "cmds/txtobjs.h" #include "cmds/changemode.h" #include "cmds/edit.h"
Modified: vimode/src/cmds/motion-word.c 266 lines changed, 266 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,266 @@ +/* + * Copyright 2019 Jiri Techet techet@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "cmds/motion-word.h" + +typedef gboolean (*CharacterPredicate)(gchar c); + + +static void get_current(ScintillaObject *sci, gchar *ch, gint *pos) +{ + *pos = SSM(sci, SCI_GETCURRENTPOS, 0, 0); + *ch = SSM(sci, SCI_GETCHARAT, *pos, 0); +} + + +static void move_left(ScintillaObject *sci, gchar *ch, gint *pos) +{ + *pos = PREV(sci, *pos); + *ch = SSM(sci, SCI_GETCHARAT, *pos, 0); +} + + +static void move_right(ScintillaObject *sci, gchar *ch, gint *pos) +{ + *pos = NEXT(sci, *pos); + *ch = SSM(sci, SCI_GETCHARAT, *pos, 0); +} + + +static gboolean is_wordchar(gchar c) +{ + return g_ascii_isalnum(c) || c == '_' || (c >= 192 && c <= 255); +} + + +static gboolean is_space(gchar c) +{ + return g_ascii_isspace(c); +} + + +static gboolean is_nonspace(gchar c) +{ + return !is_space(c); +} + + +static gboolean is_nonwordchar(gchar c) +{ + return !is_wordchar(c) && !is_space(c); +} + + +static gboolean skip_to_left(CharacterPredicate is_in_group, ScintillaObject *sci, gchar *ch, gint *pos) +{ + gboolean moved = FALSE; + while (is_in_group(*ch) && *pos > 0) + { + move_left(sci, ch, pos); + moved = TRUE; + } + return moved; +} + + +static gboolean skip_to_right(CharacterPredicate is_in_group, ScintillaObject *sci, gchar *ch, gint *pos, gint len) +{ + gboolean moved = FALSE; + while (is_in_group(*ch) && *pos < len) + { + move_right(sci, ch, pos); + moved = TRUE; + } + return moved; +} + + +void cmd_goto_next_word(CmdContext *c, CmdParams *p) +{ + gint i; + gint len = SSM(p->sci, SCI_GETLENGTH, 0, 0); + + for (i = 0; i < p->num; i++) + { + gint pos; + gchar ch; + + get_current(p->sci, &ch, &pos); + + if (!skip_to_right(is_wordchar, p->sci, &ch, &pos, len)) + skip_to_right(is_nonwordchar, p->sci, &ch, &pos, len); + skip_to_right(is_space, p->sci, &ch, &pos, len); + + if (!is_space(ch)) + SET_POS(p->sci, pos, TRUE); + } +} + + +void cmd_goto_previous_word(CmdContext *c, CmdParams *p) +{ + gint i; + for (i = 0; i < p->num; i++) + { + gint pos; + gchar ch; + + get_current(p->sci, &ch, &pos); + move_left(p->sci, &ch, &pos); + + skip_to_left(is_space, p->sci, &ch, &pos); + if (!skip_to_left(is_wordchar, p->sci, &ch, &pos)) + skip_to_left(is_nonwordchar, p->sci, &ch, &pos); + + if (pos != 0 || is_space(ch)) + move_right(p->sci, &ch, &pos); + if (!is_space(ch)) + SET_POS(p->sci, pos, TRUE); + } +} + + +void cmd_goto_next_word_end(CmdContext *c, CmdParams *p) +{ + gint i; + gint len = SSM(p->sci, SCI_GETLENGTH, 0, 0); + + for (i = 0; i < p->num; i++) + { + gint pos; + gchar ch; + + get_current(p->sci, &ch, &pos); + move_right(p->sci, &ch, &pos); + + skip_to_right(is_space, p->sci, &ch, &pos, len); + if (!skip_to_right(is_wordchar, p->sci, &ch, &pos, len)) + skip_to_right(is_nonwordchar, p->sci, &ch, &pos, len); + + if (pos < len - 1 || is_space(ch)) + move_left(p->sci, &ch, &pos); + if (!is_space(ch)) + SET_POS(p->sci, pos, TRUE); + } +} + + +void cmd_goto_previous_word_end(CmdContext *c, CmdParams *p) +{ + gint i; + for (i = 0; i < p->num; i++) + { + gint pos; + gchar ch; + + get_current(p->sci, &ch, &pos); + + if (!skip_to_left(is_wordchar, p->sci, &ch, &pos)) + skip_to_left(is_nonwordchar, p->sci, &ch, &pos); + skip_to_left(is_space, p->sci, &ch, &pos); + + if (!is_space(ch)) + SET_POS(p->sci, pos, TRUE); + } +} + + +void cmd_goto_next_word_space(CmdContext *c, CmdParams *p) +{ + gint i; + gint len = SSM(p->sci, SCI_GETLENGTH, 0, 0); + + for (i = 0; i < p->num; i++) + { + gint pos; + gchar ch; + + get_current(p->sci, &ch, &pos); + + skip_to_right(is_nonspace, p->sci, &ch, &pos, len); + skip_to_right(is_space, p->sci, &ch, &pos, len); + + if (!is_space(ch)) + SET_POS(p->sci, pos, TRUE); + } +} + + +void cmd_goto_previous_word_space(CmdContext *c, CmdParams *p) +{ + gint i; + for (i = 0; i < p->num; i++) + { + gint pos; + gchar ch; + + get_current(p->sci, &ch, &pos); + move_left(p->sci, &ch, &pos); + + skip_to_left(is_space, p->sci, &ch, &pos); + skip_to_left(is_nonspace, p->sci, &ch, &pos); + + if (pos != 0 || is_space(ch)) + move_right(p->sci, &ch, &pos); + if (!is_space(ch)) + SET_POS(p->sci, pos, TRUE); + } +} + + +void cmd_goto_next_word_end_space(CmdContext *c, CmdParams *p) +{ + gint i; + gint len = SSM(p->sci, SCI_GETLENGTH, 0, 0); + + for (i = 0; i < p->num; i++) + { + gint pos; + gchar ch; + + get_current(p->sci, &ch, &pos); + move_right(p->sci, &ch, &pos); + + skip_to_right(is_space, p->sci, &ch, &pos, len); + skip_to_right(is_nonspace, p->sci, &ch, &pos, len); + + if (pos < len - 1 || is_space(ch)) + move_left(p->sci, &ch, &pos); + if (!is_space(ch)) + SET_POS(p->sci, pos, TRUE); + } +} + + +void cmd_goto_previous_word_end_space(CmdContext *c, CmdParams *p) +{ + gint i; + for (i = 0; i < p->num; i++) + { + gint pos; + gchar ch; + + get_current(p->sci, &ch, &pos); + + skip_to_left(is_nonspace, p->sci, &ch, &pos); + skip_to_left(is_space, p->sci, &ch, &pos); + + if (!is_space(ch)) + SET_POS(p->sci, pos, TRUE); + } +}
Modified: vimode/src/cmds/motion-word.h 34 lines changed, 34 insertions(+), 0 deletions(-) =================================================================== @@ -0,0 +1,34 @@ +/* + * Copyright 2019 Jiri Techet techet@gmail.com + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __VIMODE_CMDS_MOTION_WORD_H__ +#define __VIMODE_CMDS_MOTION_WORD_H__ + +#include "context.h" +#include "cmd-params.h" + +void cmd_goto_next_word(CmdContext *c, CmdParams *p); +void cmd_goto_previous_word(CmdContext *c, CmdParams *p); +void cmd_goto_next_word_end(CmdContext *c, CmdParams *p); +void cmd_goto_previous_word_end(CmdContext *c, CmdParams *p); +void cmd_goto_next_word_space(CmdContext *c, CmdParams *p); +void cmd_goto_previous_word_space(CmdContext *c, CmdParams *p); +void cmd_goto_next_word_end_space(CmdContext *c, CmdParams *p); +void cmd_goto_previous_word_end_space(CmdContext *c, CmdParams *p); + +#endif
Modified: vimode/src/cmds/motion.c 138 lines changed, 0 insertions(+), 138 deletions(-) =================================================================== @@ -214,144 +214,6 @@ void cmd_goto_doc_percentage(CmdContext *c, CmdParams *p) }
-static void goto_word_end(CmdContext *c, CmdParams *p, gboolean forward) -{ - gint i; - - if (VI_IS_COMMAND(vi_get_mode())) - SSM(p->sci, SCI_CHARRIGHT, 0, 0); - - for (i = 0; i < p->num; i++) - { - gint orig_pos = SSM(p->sci, SCI_GETCURRENTPOS, 0, 0); - gint pos; - gint line_start_pos; - - SSM(p->sci, forward ? SCI_WORDRIGHTEND : SCI_WORDLEFTEND, 0, 0); - line_start_pos = SSM(p->sci, SCI_POSITIONFROMLINE, GET_CUR_LINE(p->sci), 0); - pos = SSM(p->sci, SCI_GETCURRENTPOS, 0, 0); - if (pos == orig_pos) - break; - /* For some reason, Scintilla treats newlines as word parts and cursor - * is left before/after newline. Repeat again in this case. */ - if (pos == line_start_pos) - SSM(p->sci, forward ? SCI_WORDRIGHTEND : SCI_WORDLEFTEND, 0, 0); - } - - if (VI_IS_COMMAND(vi_get_mode())) - SSM(p->sci, SCI_CHARLEFT, 0, 0); -} - - -static void goto_word_start(CmdContext *c, CmdParams *p, gboolean forward) -{ - gint i; - for (i = 0; i < p->num; i++) - { - gint orig_pos = SSM(p->sci, SCI_GETCURRENTPOS, 0, 0); - gint pos; - gint line_end_pos; - - SSM(p->sci, forward ? SCI_WORDRIGHT : SCI_WORDLEFT, 0, 0); - line_end_pos = SSM(p->sci, SCI_GETLINEENDPOSITION, GET_CUR_LINE(p->sci), 0); - pos = SSM(p->sci, SCI_GETCURRENTPOS, 0, 0); - if (pos == orig_pos) - break; - /* For some reason, Scintilla treats newlines as word parts and cursor - * is left before/after newline. Repeat again in this case. */ - if (pos == line_end_pos) - SSM(p->sci, forward ? SCI_WORDRIGHT : SCI_WORDLEFT, 0, 0); - } -} - - -void cmd_goto_next_word(CmdContext *c, CmdParams *p) -{ - goto_word_start(c, p, TRUE); -} - - -void cmd_goto_previous_word(CmdContext *c, CmdParams *p) -{ - goto_word_start(c, p, FALSE); -} - - -void cmd_goto_next_word_end(CmdContext *c, CmdParams *p) -{ - goto_word_end(c, p, TRUE); -} - - -void cmd_goto_previous_word_end(CmdContext *c, CmdParams *p) -{ - goto_word_end(c, p, FALSE); -} - - -static void use_all_wordchars(ScintillaObject *sci) -{ - guchar wc[512]; - gint i; - gint j = 0; - for (i = 0; i < 256; i++) - { - if (g_ascii_isprint(i) && !g_ascii_isspace(i)) - wc[j++] = i; - } - wc[j] = '\0'; - SSM(sci, SCI_SETWORDCHARS, 0, (sptr_t)wc); -} - - -void cmd_goto_next_word_space(CmdContext *c, CmdParams *p) -{ - guchar wc[512]; - SSM(p->sci, SCI_GETWORDCHARS, 0, (sptr_t)wc); - use_all_wordchars(p->sci); - - goto_word_start(c, p, TRUE); - - SSM(p->sci, SCI_SETWORDCHARS, 0, (sptr_t)wc); -} - - -void cmd_goto_previous_word_space(CmdContext *c, CmdParams *p) -{ - guchar wc[512]; - SSM(p->sci, SCI_GETWORDCHARS, 0, (sptr_t)wc); - use_all_wordchars(p->sci); - - goto_word_start(c, p, FALSE); - - SSM(p->sci, SCI_SETWORDCHARS, 0, (sptr_t)wc); -} - - -void cmd_goto_next_word_end_space(CmdContext *c, CmdParams *p) -{ - guchar wc[512]; - SSM(p->sci, SCI_GETWORDCHARS, 0, (sptr_t)wc); - use_all_wordchars(p->sci); - - goto_word_end(c, p, TRUE); - - SSM(p->sci, SCI_SETWORDCHARS, 0, (sptr_t)wc); -} - - -void cmd_goto_previous_word_end_space(CmdContext *c, CmdParams *p) -{ - guchar wc[512]; - SSM(p->sci, SCI_GETWORDCHARS, 0, (sptr_t)wc); - use_all_wordchars(p->sci); - - goto_word_end(c, p, FALSE); - - SSM(p->sci, SCI_SETWORDCHARS, 0, (sptr_t)wc); -} - - void cmd_goto_line_start(CmdContext *c, CmdParams *p) { SSM(p->sci, SCI_HOME, 0, 0);
Modified: vimode/src/cmds/motion.h 9 lines changed, 0 insertions(+), 9 deletions(-) =================================================================== @@ -41,15 +41,6 @@ void cmd_goto_screen_middle(CmdContext *c, CmdParams *p); void cmd_goto_screen_bottom(CmdContext *c, CmdParams *p); void cmd_goto_doc_percentage(CmdContext *c, CmdParams *p);
-void cmd_goto_next_word(CmdContext *c, CmdParams *p); -void cmd_goto_previous_word(CmdContext *c, CmdParams *p); -void cmd_goto_next_word_end(CmdContext *c, CmdParams *p); -void cmd_goto_previous_word_end(CmdContext *c, CmdParams *p); -void cmd_goto_next_word_space(CmdContext *c, CmdParams *p); -void cmd_goto_previous_word_space(CmdContext *c, CmdParams *p); -void cmd_goto_next_word_end_space(CmdContext *c, CmdParams *p); -void cmd_goto_previous_word_end_space(CmdContext *c, CmdParams *p); - void cmd_goto_line_start(CmdContext *c, CmdParams *p); void cmd_goto_line_start_nonempty(CmdContext *c, CmdParams *p); void cmd_goto_line_end(CmdContext *c, CmdParams *p);
-------------- This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).
plugins-commits@lists.geany.org