The sentence text object ("is" and "as") is not consistent with the
documentation (see ":h sentence").

Take, for example, the following sentence pair:

This is a "sentence."  This is a sentence.

Position your cursor on the first 'T' and type "vis" to select the sentence.
You'll see what you might expect.  However, if you type "vas", you'll see that
the selection covers too much text.  This patch fixes this problem and provides
tests that ensure the problem remains fixed.  It works by improving the manner 
in which "findsent()" searches backward for the beginning of the previous 
sentence or for the previous non-whitespace character.

The code that drives sentence, paragraph, and section text objects is full of
opportunities for refactoring.  For example, the "findsent()" was quite
confusing to me.  It could be better written by using a regular expression
search for sentence delimiters (the "sentence" definition is strict enough to
allow a regex).  Then, "findpar()" could be used within "findsent()" to also
find paragraph delimiters (which are also sentence delimiters).  This would
make the code much cleaner.  I don't know what the Vim policy is on refactoring 
like this is... seems pretty major and I wouldn't go ahead without approval.

The refactoring described above would require more knowledge of the internal
Vim regex functions than I currently have.  It's a little more than I want to
take on right now.

Hope this helps!

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.
>From 935840a35df5b520dcb2b7d0c8d15c6072b0535e Mon Sep 17 00:00:00 2001
From: Jason Franklin <[email protected]>
Date: Sat, 19 May 2018 10:05:20 -0400
Subject: [PATCH] Add code and tests to fix the sentence text object

---
 src/search.c                     | 38 +++++++++++------------
 src/testdir/test_textobjects.vim | 67 ++++++++++++++++++++++++++++++++++++++++
 2 files changed, 85 insertions(+), 20 deletions(-)

diff --git a/src/search.c b/src/search.c
index 726013e..3f531fb 100644
--- a/src/search.c
+++ b/src/search.c
@@ -2707,10 +2707,11 @@ showmatch(
 }
 
 /*
- * findsent(dir, count) - Find the start of the next sentence in direction
- * "dir" Sentences are supposed to end in ".", "!" or "?" followed by white
- * space or a line break. Also stop at an empty line.
- * Return OK if the next sentence was found.
+ * Find the start of the next sentence, searching in the direction specified
+ * by the "dir" argument.  The cursor (cursor->w_cursor) is positioned on the
+ * start of the next sentence when found.  If the next sentence is found,
+ * return OK.  Return FAIL otherwise.  See ":h sentence" for the precise
+ * definition of a "sentence" text object.
  */
     int
 findsent(int dir, long count)
@@ -2758,26 +2759,23 @@ findsent(int dir, long count)
 	else if (dir == BACKWARD)
 	    decl(&pos);
 
-	/* go back to the previous non-blank char */
 	found_dot = FALSE;
-	while ((c = gchar_pos(&pos)) == ' ' || c == '\t' ||
-	     (dir == BACKWARD && vim_strchr((char_u *)".!?)]\"'", c) != NULL))
+	while (c = gchar_pos(&pos), VIM_ISWHITE(c) || vim_strchr((char_u *)".!?)]\"'", c) != NULL)
 	{
-	    if (vim_strchr((char_u *)".!?", c) != NULL)
-	    {
-		/* Only skip over a '.', '!' and '?' once. */
-		if (found_dot)
-		    break;
+	    tpos = pos;
+	    if (decl(&tpos) == -1 || (LINEEMPTY(tpos.lnum) && dir == FORWARD))
+		break;
+
+	    if (found_dot)
+		break;
+	    if (vim_strchr((char_u *) ".!?", c) != NULL)
 		found_dot = TRUE;
-	    }
-	    if (decl(&pos) == -1)
+
+	    if (vim_strchr((char_u *) ")]\"'", c) != NULL &&
+		vim_strchr((char_u *) ".!?)]\"'", gchar_pos(&tpos)) == NULL)
 		break;
-	    /* when going forward: Stop in front of empty line */
-	    if (LINEEMPTY(pos.lnum) && dir == FORWARD)
-	    {
-		incl(&pos);
-		goto found;
-	    }
+
+	    decl(&pos);
 	}
 
 	/* remember the line where the search started */
diff --git a/src/testdir/test_textobjects.vim b/src/testdir/test_textobjects.vim
index 17602fb..43489ac 100644
--- a/src/testdir/test_textobjects.vim
+++ b/src/testdir/test_textobjects.vim
@@ -165,3 +165,70 @@ x
   norm it
   q!
 endfunc
+
+func Test_sentence()
+  enew!
+  call setline(1, 'A sentence.  A sentence?  A sentence!')
+
+  normal yis
+  call assert_equal('A sentence.', @")
+  normal yas
+  call assert_equal('A sentence.  ', @")
+
+  normal )
+
+  normal yis
+  call assert_equal('A sentence?', @")
+  normal yas
+  call assert_equal('A sentence?  ', @")
+
+  normal )
+
+  normal yis
+  call assert_equal('A sentence!', @")
+  normal yas
+  call assert_equal('  A sentence!', @")
+
+  %delete _
+endfunc
+
+func Test_sentence_with_quotes()
+  enew!
+  call setline(1, 'A "sentence."  A sentence.')
+
+  normal yis
+  call assert_equal('A "sentence."', @")
+  normal yas
+  call assert_equal('A "sentence."  ', @")
+
+  normal )
+
+  normal yis
+  call assert_equal('A sentence.', @")
+  normal yas
+  call assert_equal('  A sentence.', @")
+
+  %delete _
+endfunc
+
+func! Test_sentence_with_cursor_on_delimiter()
+  enew!
+  call setline(1, "A '([sentence.])'  A sentence.")
+
+  normal! 15|yis
+  call assert_equal("A '([sentence.])'", @")
+  normal! 15|yas
+  call assert_equal("A '([sentence.])'  ", @")
+
+  normal! 16|yis
+  call assert_equal("A '([sentence.])'", @")
+  normal! 16|yas
+  call assert_equal("A '([sentence.])'  ", @")
+
+  normal! 17|yis
+  call assert_equal("A '([sentence.])'", @")
+  normal! 17|yas
+  call assert_equal("A '([sentence.])'  ", @")
+
+  %delete _
+endfunc
-- 
2.7.4

Raspunde prin e-mail lui