[gtksourceview/wip/chergert/vim] add some sentence tests and specialize for text-object motion



commit 622171c019aa60cbbdcb5d0f9a391592a2969a9e
Author: Christian Hergert <chergert redhat com>
Date:   Thu Nov 4 23:45:06 2021 -0700

    add some sentence tests and specialize for text-object motion

 gtksourceview/vim/gtk-source-vim-text-object.c | 115 ++++++++++++++++++++++++-
 testsuite/test-vim-text-object.c               |  20 +++++
 2 files changed, 133 insertions(+), 2 deletions(-)
---
diff --git a/gtksourceview/vim/gtk-source-vim-text-object.c b/gtksourceview/vim/gtk-source-vim-text-object.c
index 312a3267..a91daecd 100644
--- a/gtksourceview/vim/gtk-source-vim-text-object.c
+++ b/gtksourceview/vim/gtk-source-vim-text-object.c
@@ -78,6 +78,97 @@ iter_isspace (const GtkTextIter *iter)
        return g_unichar_isspace (gtk_text_iter_get_char (iter));
 }
 
+static inline gboolean
+is_empty_line (const GtkTextIter *iter)
+{
+       return gtk_text_iter_starts_line (iter) && gtk_text_iter_ends_line (iter);
+}
+
+static inline gboolean
+can_trail_sentence (const GtkTextIter *iter)
+{
+       switch (gtk_text_iter_get_char (iter))
+       {
+       case '.': case '!': case '?':
+       case ']': case ')': case '"': case '\'':
+               return TRUE;
+
+       default:
+               return FALSE;
+       }
+}
+
+static inline gboolean
+is_end_sentence_char (const GtkTextIter *iter)
+{
+       switch (gtk_text_iter_get_char (iter))
+       {
+       case '.': case '!': case '?':
+               return TRUE;
+
+       default:
+               return FALSE;
+       }
+}
+
+static gboolean
+gtk_source_vim_iter_ends_sentence (const GtkTextIter *iter)
+{
+       GtkTextIter next, cur;
+
+       if (!can_trail_sentence (iter))
+       {
+               return FALSE;
+       }
+
+       next = *iter;
+       if (gtk_text_iter_forward_char (&next) &&
+           !gtk_text_iter_ends_line (&next) &&
+           !iter_isspace (&next))
+       {
+               return FALSE;
+       }
+
+       cur = *iter;
+       while (!is_end_sentence_char (&cur) && can_trail_sentence (&cur))
+       {
+               gtk_text_iter_backward_char (&cur);
+       }
+
+       return is_end_sentence_char (&cur);
+}
+
+static gboolean
+gtk_source_vim_iter__forward_sentence_end (GtkTextIter *iter)
+{
+       if (gtk_text_iter_is_end (iter) || !gtk_text_iter_forward_char (iter))
+       {
+               return FALSE;
+       }
+
+       do
+       {
+               if (is_empty_line (iter))
+                       return TRUE;
+
+               if (is_end_sentence_char (iter))
+               {
+                       GtkTextIter next = *iter;
+
+                       while (gtk_text_iter_forward_char (&next))
+                       {
+                               if (!can_trail_sentence (&next))
+                                       break;
+                               *iter = next;
+                       }
+
+                       return TRUE;
+               }
+       } while (gtk_text_iter_forward_char (iter));
+
+       return FALSE;
+}
+
 static void
 backward_to_first_space (GtkTextIter *iter)
 {
@@ -164,6 +255,26 @@ text_object_extend_sentence (const GtkTextIter *origin,
                              GtkTextIter       *a_begin,
                              GtkTextIter       *a_end)
 {
+       if (gtk_text_iter_starts_line (inner_begin) &&
+           gtk_text_iter_ends_line (inner_begin))
+       {
+               /* swallow up to next none empty line */
+               while (is_empty_line (a_end))
+                       gtk_text_iter_forward_line (a_end);
+       }
+       else if (!gtk_text_iter_ends_line (inner_end))
+       {
+               /* swallow trailing character */
+               gtk_text_iter_forward_char (inner_end);
+
+               *a_end = *inner_end;
+
+               /* swallow up to next sentence for a */
+               while (!gtk_text_iter_ends_line (a_end) && iter_isspace (a_end))
+               {
+                       gtk_text_iter_forward_char (a_end);
+               }
+       }
 }
 
 static GtkSourceVimState *
@@ -201,7 +312,7 @@ gtk_source_vim_text_object_new_##name (void)
 
 TEXT_OBJECT_CTOR (inner_word, ends_word, starts_word, forward_word_end, backward_word_start, word, INNER);
 TEXT_OBJECT_CTOR (inner_WORD, always_false, starts_WORD, forward_WORD_end, backward_WORD_start, word, INNER);
-TEXT_OBJECT_CTOR (inner_sentence, always_false, always_false, forward_sentence_end, backward_sentence_start, 
sentence, INNER);
+TEXT_OBJECT_CTOR (inner_sentence, ends_sentence, always_false, _forward_sentence_end, 
backward_sentence_start, sentence, INNER);
 TEXT_OBJECT_CTOR (inner_paragraph, always_false, always_false, forward_paragraph_end, 
backward_paragraph_start, paragraph, INNER);
 TEXT_OBJECT_CTOR (inner_block_paren, ends_paren, starts_paren, forward_block_paren_end, 
backward_block_paren_start, one, INNER);
 TEXT_OBJECT_CTOR (inner_block_brace, ends_brace, starts_brace, forward_block_brace_end, 
backward_block_brace_start, one, INNER);
@@ -213,7 +324,7 @@ TEXT_OBJECT_CTOR (inner_quote_grave, ends_quote_grave, always_false, forward_quo
 
 TEXT_OBJECT_CTOR (a_word, ends_word, starts_word, forward_word_end, backward_word_start, word, A);
 TEXT_OBJECT_CTOR (a_WORD, ends_WORD, starts_WORD, forward_WORD_end, backward_WORD_start, word, A);
-TEXT_OBJECT_CTOR (a_sentence, always_false, always_false, forward_sentence_end, backward_sentence_start, 
sentence, A);
+TEXT_OBJECT_CTOR (a_sentence, ends_sentence, always_false, _forward_sentence_end, backward_sentence_start, 
sentence, A);
 TEXT_OBJECT_CTOR (a_paragraph, always_false, always_false, forward_paragraph_end, backward_paragraph_start, 
paragraph, A);
 TEXT_OBJECT_CTOR (a_block_paren, ends_paren, starts_paren, forward_block_paren_end, 
backward_block_paren_start, one, A);
 TEXT_OBJECT_CTOR (a_block_brace, ends_brace, starts_brace, forward_block_brace_end, 
backward_block_brace_start, one, A);
diff --git a/testsuite/test-vim-text-object.c b/testsuite/test-vim-text-object.c
index 01d14917..d402cdbd 100644
--- a/testsuite/test-vim-text-object.c
+++ b/testsuite/test-vim-text-object.c
@@ -151,6 +151,25 @@ test_quote (void)
        run_test (gtk_source_vim_text_object_new_a_quote_double (), "\"a\"b\"", 3, "\"b\"", FALSE);
 }
 
+static void
+test_sentence (void)
+{
+       run_test (gtk_source_vim_text_object_new_inner_sentence (), "a. b! c?", 0, "a.", FALSE);
+       run_test (gtk_source_vim_text_object_new_inner_sentence (), "a. b! c?", 1, "a.", FALSE);
+       run_test (gtk_source_vim_text_object_new_inner_sentence (), "a. b! c?", 2, "b!", FALSE);
+       run_test (gtk_source_vim_text_object_new_inner_sentence (), "a. b! c?", 3, "b!", FALSE);
+       run_test (gtk_source_vim_text_object_new_inner_sentence (), "a. b! c?", 4, "b!", FALSE);
+       run_test (gtk_source_vim_text_object_new_inner_sentence (), "a. b! c?", 5, "c?", FALSE);
+       run_test (gtk_source_vim_text_object_new_inner_sentence (), "a. b! c?", 6, "c?", FALSE);
+       run_test (gtk_source_vim_text_object_new_inner_sentence (), "\n a. b! c?", 1, "a.", FALSE);
+       run_test (gtk_source_vim_text_object_new_inner_sentence (), "\n a. b! c?", 2, "a.", FALSE);
+
+       run_test (gtk_source_vim_text_object_new_a_sentence (), "a. b! c?", 0, "a. ", FALSE);
+       run_test (gtk_source_vim_text_object_new_a_sentence (), " a. b! c?", 0, " a. ", FALSE);
+       run_test (gtk_source_vim_text_object_new_a_sentence (), "\n a. b! c?", 1, "a. ", FALSE);
+       run_test (gtk_source_vim_text_object_new_a_sentence (), "\n a. b! c?", 2, "a. ", FALSE);
+}
+
 int
 main (int argc,
       char *argv[])
@@ -164,6 +183,7 @@ main (int argc,
        g_test_add_func ("/GtkSourceView/vim-text-object/WORD", test_WORD);
        g_test_add_func ("/GtkSourceView/vim-text-object/block", test_block);
        g_test_add_func ("/GtkSourceView/vim-text-object/quote", test_quote);
+       g_test_add_func ("/GtkSourceView/vim-text-object/sentence", test_sentence);
        ret = g_test_run ();
        gtk_source_finalize ();
        return ret;


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