[gtksourceview/wip/chergert/vim] improve backward sentence start



commit c233226ce2d697c35a8da7b9b627cdab4667f15d
Author: Christian Hergert <chergert redhat com>
Date:   Sun Oct 24 19:23:49 2021 -0700

    improve backward sentence start

 gtksourceview/vim/gtk-source-vim-motion.c | 211 ++++++++++++++++++++++--------
 1 file changed, 156 insertions(+), 55 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-motion.c b/gtksourceview/vim/gtk-source-vim-motion.c
index bd19ff12..ae4d8860 100644
--- a/gtksourceview/vim/gtk-source-vim-motion.c
+++ b/gtksourceview/vim/gtk-source-vim-motion.c
@@ -461,21 +461,6 @@ motion_prev_line (GtkTextIter        *iter,
        return FALSE;
 }
 
-static gboolean
-motion_next_line (GtkTextIter        *iter,
-                  GtkSourceVimMotion *state)
-{
-       GtkTextIter before = *iter;
-
-       if (gtk_text_iter_forward_to_line_end (iter))
-               gtk_text_iter_forward_char (iter);
-
-       if (gtk_text_iter_is_end (iter))
-               gtk_text_iter_backward_char (iter);
-
-       return !gtk_text_iter_equal (&before, iter);
-}
-
 static gboolean
 motion_next_line_first_char (GtkTextIter        *iter,
                              GtkSourceVimMotion *state)
@@ -781,86 +766,202 @@ motion_backward_paragraph_start (GtkTextIter        *iter,
        GtkTextIter before = *iter;
 
        /* Work our way past the current empty lines */
-       if (line_is_empty (iter))
+       while (line_is_empty (iter))
        {
-               while (line_is_empty (iter))
-               {
-                       if (!gtk_text_iter_backward_line (iter))
-                               return FALSE;
-               }
+               if (!gtk_text_iter_backward_line (iter))
+                       goto finish;
        }
 
        /* Now find first line that is empty */
        while (!line_is_empty (iter))
        {
                if (!gtk_text_iter_backward_line (iter))
-                       return FALSE;
+                       goto finish;
        }
 
+finish:
        return !gtk_text_iter_equal (&before, iter);
 }
 
-static gboolean
-motion_backward_sentence_start (GtkTextIter        *iter,
-                                GtkSourceVimMotion *state)
-{
-       return gtk_text_iter_backward_sentence_start (iter);
-}
-
 static gboolean
 motion_forward_sentence_start (GtkTextIter        *iter,
                                GtkSourceVimMotion *state)
 {
        GtkTextIter before = *iter;
-       gboolean last_was_newline = FALSE;
+       guint newline_count = 0;
 
-       do
+       /* If we're at the end of a sentence, then walk past any trailing
+        * characters after the punctuation, and then skip space up until
+        * another non-space character.
+        */
+       switch (gtk_text_iter_get_char (iter))
        {
-               if (!gtk_text_iter_forward_char (iter))
+               case '.':
+               case '!':
+               case '?':
+               case '\n':
+                       while (!g_unichar_isspace (gtk_text_iter_get_char (iter)))
+                       {
+                               if (!gtk_text_iter_forward_char (iter))
+                                       goto finish;
+                       }
+                       while (g_unichar_isspace (gtk_text_iter_get_char (iter)))
+                       {
+                               if (!gtk_text_iter_forward_char (iter))
+                                       goto finish;
+                       }
+                       return TRUE;
+
+               default:
                        break;
+       }
 
+       while (gtk_text_iter_forward_char (iter))
+       {
                switch (gtk_text_iter_get_char (iter))
                {
                        case '\n':
-                               /* \n\n or more is a paragraph break */
-                               if (last_was_newline)
+                               newline_count++;
+                               if (newline_count == 1)
+                                       break;
+                               G_GNUC_FALLTHROUGH;
+                       case '.':
+                       case '!':
+                       case '?':
+                               while (!g_unichar_isspace (gtk_text_iter_get_char (iter)))
                                {
-                                       while (gtk_text_iter_ends_line (iter) &&
-                                              gtk_text_iter_forward_char (iter)) { /* do nothing */ }
+                                       if (!gtk_text_iter_forward_char (iter))
+                                               goto finish;
+                               }
+                               while (g_unichar_isspace (gtk_text_iter_get_char (iter)))
+                               {
+                                       if (!gtk_text_iter_forward_char (iter))
+                                               goto finish;
+                               }
+                               return TRUE;
 
-                                       while (!gtk_text_iter_ends_line (iter) &&
-                                              g_unichar_isspace (gtk_text_iter_get_char (iter)))
-                                       {
-                                               if (!gtk_text_iter_forward_char (iter))
-                                                       break;
-                                       }
+                       default:
+                               break;
+               }
+       }
 
-                                       return TRUE;
-                               }
+finish:
+       if (gtk_text_iter_is_end (iter) && !gtk_text_iter_starts_line (iter))
+               gtk_text_iter_backward_char (iter);
 
-                               last_was_newline = TRUE;
+       return !gtk_text_iter_equal (&before, iter);
+}
+
+static gboolean
+backward_sentence_end (GtkTextIter *iter)
+{
+       GtkTextIter before = *iter;
+
+       if (line_is_empty (iter))
+       {
+               while (gtk_text_iter_backward_char (iter))
+               {
+                       if (!g_unichar_isspace (gtk_text_iter_get_char (iter)))
                                break;
+               }
 
+               goto finish;
+       }
+
+       while (gtk_text_iter_backward_char (iter))
+       {
+               switch (gtk_text_iter_get_char (iter))
+               {
                        case '.':
                        case '!':
                        case '?':
-                               do
-                               {
-                                       if (!gtk_text_iter_forward_char (iter))
-                                               return TRUE;
+                               goto finish;
 
-                                       if (g_unichar_isspace (gtk_text_iter_get_char (iter)))
-                                               continue;
+                       case '\n':
+                               if (gtk_text_iter_starts_line (iter))
+                               {
+                                       while (gtk_text_iter_backward_char (iter))
+                                       {
+                                               if (!g_unichar_isspace (gtk_text_iter_get_char (iter)))
+                                                       break;
+                                       }
 
-                                       return TRUE;
-                               } while (TRUE);
+                                       goto finish;
+                               }
                                break;
 
                        default:
-                               last_was_newline = FALSE;
                                break;
                }
-       } while (TRUE);
+       }
+
+finish:
+       if (gtk_text_iter_is_end (iter) && !gtk_text_iter_starts_line (iter))
+               gtk_text_iter_backward_char (iter);
+
+       return !gtk_text_iter_equal (&before, iter);
+}
+
+static gboolean
+motion_backward_sentence_start (GtkTextIter        *iter,
+                                GtkSourceVimMotion *state)
+{
+       GtkTextIter *winner = NULL;
+       GtkTextIter before = *iter;
+       GtkTextIter para;
+       GtkTextIter sentence;
+       GtkTextIter two_sentence;
+       int distance = G_MAXINT;
+
+       para = *iter;
+       motion_backward_paragraph_start (&para, state);
+
+       sentence = *iter;
+       backward_sentence_end (&sentence);
+       motion_forward_sentence_start (&sentence, state);
+
+       two_sentence = *iter;
+       backward_sentence_end (&two_sentence);
+       backward_sentence_end (&two_sentence);
+       motion_forward_sentence_start (&two_sentence, state);
+
+       if (gtk_text_iter_compare (&para, iter) < 0)
+       {
+               int diff = (int)gtk_text_iter_get_offset (iter) - (int)gtk_text_iter_get_offset (&para);
+
+               if (diff < distance)
+               {
+                       distance = diff;
+                       winner = &para;
+               }
+       }
+
+       if (gtk_text_iter_compare (&sentence, iter) < 0)
+       {
+               int diff = (int)gtk_text_iter_get_offset (iter) - (int)gtk_text_iter_get_offset (&sentence);
+
+               if (diff < distance)
+               {
+                       distance = diff;
+                       winner = &sentence;
+               }
+       }
+
+       if (gtk_text_iter_compare (&two_sentence, iter) < 0)
+       {
+               int diff = (int)gtk_text_iter_get_offset (iter) - (int)gtk_text_iter_get_offset 
(&two_sentence);
+
+               if (diff < distance)
+               {
+                       distance = diff;
+                       winner = &two_sentence;
+               }
+       }
+
+       if (winner != NULL)
+               *iter = *winner;
+       else
+               gtk_text_iter_set_offset (iter, 0);
 
        return !gtk_text_iter_equal (&before, iter);
 }


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