[gtksourceview/wip/chergert/vim] handle numbers, . and $ when parsing range



commit 599de1d8f43ef65dabc3b9b8d45728e9e0a4b619
Author: Christian Hergert <chergert redhat com>
Date:   Mon Nov 8 14:51:27 2021 -0800

    handle numbers, . and $ when parsing range

 gtksourceview/vim/gtk-source-vim-command.c | 134 +++++++++++++++++++++--------
 1 file changed, 99 insertions(+), 35 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-command.c b/gtksourceview/vim/gtk-source-vim-command.c
index 85d59cc0..0975481f 100644
--- a/gtksourceview/vim/gtk-source-vim-command.c
+++ b/gtksourceview/vim/gtk-source-vim-command.c
@@ -1113,59 +1113,123 @@ gtk_source_vim_command_set_text_object (GtkSourceVimCommand    *self,
 }
 
 static gboolean
-parse_mark_range (GtkSourceVimState  *current,
-                  const char        **cmdline_inout,
-                  GtkTextIter        *begin,
-                  GtkTextIter        *end)
+parse_position (GtkSourceVimState  *current,
+                const char        **str,
+                GtkTextIter        *iter)
 {
-       GtkSourceBuffer *buffer = gtk_source_vim_state_get_buffer (current, NULL, NULL);
-       const char *cmdline = *cmdline_inout;
-       gunichar mark1 = 0;
-       gunichar mark2 = 0;
-       char str[16];
+       GtkTextBuffer *buffer;
+       const char *c;
 
-       if (cmdline[0] == '%')
+       g_assert (GTK_SOURCE_IS_VIM_STATE (current));
+       g_assert (str != NULL);
+       g_assert (*str != NULL);
+       g_assert (iter != NULL);
+
+       buffer = GTK_TEXT_BUFFER (gtk_source_vim_state_get_buffer (current, NULL, NULL));
+       c = *str;
+
+       if (*c == '\'')
        {
-               gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), begin, end);
-               *cmdline_inout = ++cmdline;
+               GtkTextMark *mark;
+               char name[2];
+
+               c++;
+               name[0] = *c;
+               name[1] = 0;
+
+               if (!(mark = gtk_source_vim_state_get_mark (current, name)))
+                       return FALSE;
+
+               gtk_text_buffer_get_iter_at_mark (buffer, iter, mark);
+               *str = ++c;
                return TRUE;
        }
-
-       /* Look for something like '<,'> */
-       if (*cmdline == '\'')
+       else if (*c == '.')
        {
-               ++cmdline;
-               mark1 = *cmdline;
-               if (!mark1)
-                       return FALSE;
+               gtk_text_buffer_get_iter_at_mark (buffer, iter, gtk_text_buffer_get_insert (buffer));
+               gtk_text_iter_set_line_offset (iter, 0);
+               *str = ++c;
+               return TRUE;
+       }
+       else if (*c == '$')
+       {
+               gtk_text_buffer_get_end_iter (buffer, iter);
+               *str = ++c;
+               return TRUE;
+       }
+       else if (*c == '+' && g_ascii_isdigit (c[1]))
+       {
+               int number = 0;
 
-               ++cmdline;
-               if (*cmdline != ',')
-                       return FALSE;
+               for (++c; *c; c = g_utf8_next_char (c))
+               {
+                       if (!g_ascii_isdigit (*c))
+                               break;
+                       number = number * 10 + *c - '0';
+               }
 
-               ++cmdline;
-               if (*cmdline != '\'')
-                       return FALSE;
+               gtk_text_buffer_get_iter_at_mark (buffer, iter, gtk_text_buffer_get_insert (buffer));
+               gtk_text_iter_forward_lines (iter, number);
+               if (!gtk_text_iter_ends_line (iter))
+                       gtk_text_iter_forward_to_line_end (iter);
 
-               ++cmdline;
-               mark2 = *cmdline;
-               if (!mark2)
-                       return FALSE;
+               *str = c;
 
-               str[g_unichar_to_utf8 (mark1, str)] = 0;
-               gtk_source_vim_state_get_iter_at_mark (current, str, begin);
+               return TRUE;
+       }
+       else if (g_ascii_isdigit (*c))
+       {
+               int number = 0;
 
-               str[g_unichar_to_utf8 (mark2, str)] = 0;
-               gtk_source_vim_state_get_iter_at_mark (current, str, end);
+               for (; *c; c = g_utf8_next_char (c))
+               {
+                       if (!g_ascii_isdigit (*c))
+                               break;
+                       number = number * 10 + *c - '0';
+               }
 
-               *cmdline_inout = cmdline;
+               if (number > 0)
+                       number--;
 
+               gtk_text_buffer_get_iter_at_line (buffer, iter, number);
+               *str = c;
                return TRUE;
        }
 
        return FALSE;
 }
 
+static gboolean
+parse_range (GtkSourceVimState  *current,
+             const char        **cmdline_inout,
+             GtkTextIter        *begin,
+             GtkTextIter        *end)
+{
+       GtkSourceBuffer *buffer = gtk_source_vim_state_get_buffer (current, NULL, NULL);
+       const char *cmdline = *cmdline_inout;
+
+       if (cmdline[0] == '%')
+       {
+               gtk_text_buffer_get_bounds (GTK_TEXT_BUFFER (buffer), begin, end);
+               *cmdline_inout = ++cmdline;
+               return TRUE;
+       }
+
+       if (!parse_position (current, &cmdline, begin))
+               return FALSE;
+
+       if (*cmdline != ',')
+               return FALSE;
+
+       cmdline++;
+       if (!parse_position (current, &cmdline, end))
+               return FALSE;
+
+       *cmdline_inout = cmdline;
+
+       return TRUE;
+}
+
 GtkSourceVimState *
 gtk_source_vim_command_new_parsed (GtkSourceVimState *current,
                                    const char        *command_line)
@@ -1194,7 +1258,7 @@ gtk_source_vim_command_new_parsed (GtkSourceVimState *current,
                command_line++;
        }
 
-       if (parse_mark_range (current, &command_line, &begin, &end))
+       if (parse_range (current, &command_line, &begin, &end))
        {
                GtkSourceBuffer *buffer;
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]