[gtksourceview/wip/chergert/vim] sentence movements



commit 986d43faa031035dd24c95c941eb058f77df2671
Author: Christian Hergert <chergert redhat com>
Date:   Sun Oct 24 11:36:55 2021 -0700

    sentence movements

 gtksourceview/vim/gtk-source-vim-motion.c | 201 +++++++++++++++++++++++++++---
 1 file changed, 186 insertions(+), 15 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-motion.c b/gtksourceview/vim/gtk-source-vim-motion.c
index 130afbbc..2821ea5b 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.c
+++ b/gtksourceview/vim/gtk-source-vim-motion.c
@@ -741,20 +741,6 @@ motion_F_char (GtkTextIter        *iter,
        return FALSE;
 }
 
-static gboolean
-motion_forward_sentence_start (GtkTextIter        *iter,
-                               GtkSourceVimMotion *state)
-{
-       return FALSE;
-}
-
-static gboolean
-motion_backward_sentence_start (GtkTextIter        *iter,
-                                GtkSourceVimMotion *state)
-{
-       return FALSE;
-}
-
 static gboolean
 motion_forward_paragraph_end (GtkTextIter        *iter,
                               GtkSourceVimMotion *state)
@@ -813,6 +799,190 @@ motion_backward_paragraph_start (GtkTextIter        *iter,
        return !gtk_text_iter_equal (&before, iter);
 }
 
+typedef enum
+{
+  SENTENCE_OK,
+  SENTENCE_PARA,
+  SENTENCE_FAILED,
+} SentenceStatus;
+
+static gboolean
+sentence_end_chars (gunichar ch,
+                    gpointer user_data)
+{
+       switch (ch)
+       {
+               case '!':
+               case '.':
+               case '?':
+                       return TRUE;
+
+               default:
+                       return FALSE;
+       }
+}
+
+static SentenceStatus
+backward_sentence_end (GtkTextIter        *iter,
+                       GtkSourceVimMotion *state)
+{
+       GtkTextIter end_bounds;
+       GtkTextIter start_bounds;
+       gboolean found_para;
+
+       end_bounds = *iter;
+       start_bounds = *iter;
+       found_para = motion_backward_paragraph_start (&start_bounds, state);
+
+       if (!found_para)
+       {
+               gtk_text_buffer_get_start_iter (gtk_text_iter_get_buffer (iter),
+                                               &start_bounds);
+       }
+
+       while ((gtk_text_iter_compare (iter, &start_bounds) > 0) &&
+              gtk_text_iter_backward_char (iter))
+       {
+               if (gtk_text_iter_backward_find_char (iter, sentence_end_chars, NULL, &end_bounds))
+               {
+                       GtkTextIter copy = *iter;
+
+                       while (gtk_text_iter_forward_char (&copy) &&
+                              gtk_text_iter_compare (&copy, &end_bounds) < 0)
+                       {
+                               gunichar ch = gtk_text_iter_get_char (&copy);
+
+                               switch (ch)
+                               {
+                                       case ']':
+                                       case ')':
+                                       case '"':
+                                       case '\'':
+                                               continue;
+
+                                       case ' ':
+                                       case '\n':
+                                               *iter = copy;
+                                               return SENTENCE_OK;
+
+                                       default:
+                                               break;
+                               }
+                       }
+               }
+       }
+
+       *iter = start_bounds;
+
+       if (found_para)
+               return SENTENCE_PARA;
+
+       return SENTENCE_FAILED;
+}
+
+static gboolean
+motion_forward_sentence_end (GtkTextIter        *iter,
+                             GtkSourceVimMotion *state)
+{
+       GtkTextIter end_bounds;
+       gboolean found_para;
+
+       end_bounds = *iter;
+       found_para = motion_forward_paragraph_end (&end_bounds, state);
+
+       if (!found_para)
+       {
+               gtk_text_buffer_get_end_iter (gtk_text_iter_get_buffer (iter),
+                                             &end_bounds);
+       }
+
+       while ((gtk_text_iter_compare (iter, &end_bounds) < 0) &&
+              gtk_text_iter_forward_char (iter))
+       {
+               if (gtk_text_iter_forward_find_char (iter, sentence_end_chars, NULL, &end_bounds))
+               {
+                       GtkTextIter copy = *iter;
+
+                       while (gtk_text_iter_forward_char (&copy) &&
+                              gtk_text_iter_compare (&copy, &end_bounds) < 0)
+                       {
+                               gunichar ch = gtk_text_iter_get_char (&copy);
+                               gboolean invalid = FALSE;
+
+                               switch (ch)
+                               {
+                                       case ']':
+                                       case ')':
+                                       case '"':
+                                       case '\'':
+                                               continue;
+
+                                       case ' ':
+                                       case '\n':
+                                               *iter = copy;
+                                               return SENTENCE_OK;
+
+                                       default:
+                                               invalid = TRUE;
+                                               break;
+                               }
+
+                               if (invalid)
+                                       break;
+                       }
+               }
+       }
+
+       *iter = end_bounds;
+
+       if (found_para)
+               return SENTENCE_PARA;
+
+       return SENTENCE_FAILED;
+}
+
+static gboolean
+motion_backward_sentence_start (GtkTextIter        *iter,
+                                GtkSourceVimMotion *state)
+{
+       GtkTextIter tmp;
+       SentenceStatus status;
+
+       tmp = *iter;
+       status = backward_sentence_end (&tmp, state);
+
+       switch (status)
+       {
+               case SENTENCE_PARA:
+               case SENTENCE_OK:
+               {
+                       GtkTextIter copy = tmp;
+
+                       /*
+                        * try to work forward to first non-whitespace char.
+                        * if we land where we started, discard the walk.
+                        */
+                       while (g_unichar_isspace (gtk_text_iter_get_char (&copy)))
+                       {
+                               if (!gtk_text_iter_forward_char (&copy))
+                                       break;
+                       }
+
+                       if (gtk_text_iter_compare (&copy, iter) < 0)
+                               tmp = copy;
+
+                       *iter = tmp;
+
+                       return TRUE;
+               }
+
+               case SENTENCE_FAILED:
+               default:
+                       gtk_text_buffer_get_start_iter (gtk_text_iter_get_buffer (iter), iter);
+                       return FALSE;
+       }
+}
+
 GtkSourceVimState *
 gtk_source_vim_motion_new (void)
 {
@@ -997,7 +1167,8 @@ gtk_source_vim_motion_handle_keypress (GtkSourceVimState *state,
                        return gtk_source_vim_motion_complete (self, motion_backward_sentence_start);
 
                case GDK_KEY_parenright:
-                       return gtk_source_vim_motion_complete (self, motion_forward_sentence_start);
+                       /* this needs to be chagned to sentence start */
+                       return gtk_source_vim_motion_complete (self, motion_forward_sentence_end);
 
                case GDK_KEY_braceleft:
                        return gtk_source_vim_motion_complete (self, motion_backward_paragraph_start);


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