[geany/geany-plugins] b77774: vimode: Don't use word navigation from Scintilla

Jiří Techet git-noreply at xxxxx
Mon Oct 7 12:34:19 UTC 2019


Branch:      refs/heads/master
Author:      Jiří Techet <techet at gmail.com>
Committer:   Jiří Techet <techet at gmail.com>
Date:        Mon, 07 Oct 2019 12:34:19 UTC
Commit:      b77774eb46833aba061f537cef5ffb5c8b45eaab
             https://github.com/geany/geany-plugins/commit/b77774eb46833aba061f537cef5ffb5c8b45eaab

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 at 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 at 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).


More information about the Plugins-Commits mailing list