summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-04-28 20:29:07 +0200
committerBram Moolenaar <Bram@vim.org>2020-04-28 20:29:07 +0200
commit224a5f17c6ec9e98322a4c6792ce4f9bb31a4cce (patch)
treeb538807dd799fbbbbdf2b5eae28831eb0da86fe0
parenta14bb7e1132377af60910402f1a9e4796297f5df (diff)
patch 8.2.0655: search code not sufficiently testedv8.2.0655
Problem: Search code not sufficiently tested. Solution: Add more tests. (Yegappan Lakshmanan, closes #5999)
-rw-r--r--src/testdir/test_charsearch.vim23
-rw-r--r--src/testdir/test_gn.vim18
-rw-r--r--src/testdir/test_goto.vim59
-rw-r--r--src/testdir/test_ins_complete.vim20
-rw-r--r--src/testdir/test_normal.vim139
-rw-r--r--src/testdir/test_search.vim93
-rw-r--r--src/testdir/test_textformat.vim26
-rw-r--r--src/testdir/test_textobjects.vim251
-rw-r--r--src/testdir/test_visual.vim23
-rw-r--r--src/version.c2
10 files changed, 551 insertions, 103 deletions
diff --git a/src/testdir/test_charsearch.vim b/src/testdir/test_charsearch.vim
index e6301a5c05..0a20eafe0b 100644
--- a/src/testdir/test_charsearch.vim
+++ b/src/testdir/test_charsearch.vim
@@ -30,6 +30,15 @@ func Test_charsearch()
normal! ;;p
call assert_equal('ZabcdeZfghijkZZemnokqretkZvwxyz', getline(3))
+ " check that repeating a search before and after a line fails
+ normal 3Gfv
+ call assert_beeps('normal ;')
+ call assert_beeps('normal ,')
+
+ " clear the character search
+ call setcharsearch({'char' : ''})
+ call assert_equal('', getcharsearch().char)
+
call assert_fails("call setcharsearch([])", 'E715:')
enew!
endfunc
@@ -75,4 +84,18 @@ func Test_csearch_virtualedit()
close!
endfunc
+" Test for character search failure in latin1 encoding
+func Test_charsearch_latin1()
+ new
+ let save_enc = &encoding
+ set encoding=latin1
+ call setline(1, 'abcdefghijk')
+ call assert_beeps('normal fz')
+ call assert_beeps('normal tx')
+ call assert_beeps('normal $Fz')
+ call assert_beeps('normal $Tx')
+ let &encoding = save_enc
+ close!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_gn.vim b/src/testdir/test_gn.vim
index 098fc3db4d..c72da925a3 100644
--- a/src/testdir/test_gn.vim
+++ b/src/testdir/test_gn.vim
@@ -154,8 +154,24 @@ func Test_gn_command()
norm! gg0f2vf7gNd
call assert_equal(['1678'], getline(1,'$'))
sil! %d _
-
set wrapscan&vim
+
+ " Without 'wrapscan', in visual mode, running gn without a match should fail
+ " but the visual mode should be kept.
+ set nowrapscan
+ call setline('.', 'one two')
+ let @/ = 'one'
+ call assert_beeps('normal 0wvlgn')
+ exe "normal y"
+ call assert_equal('tw', @")
+
+ " with exclusive selection, run gn and gN
+ set selection=exclusive
+ normal 0gny
+ call assert_equal('one', @")
+ normal 0wgNy
+ call assert_equal('one', @")
+ set selection&
endfu
func Test_gn_multi_line()
diff --git a/src/testdir/test_goto.vim b/src/testdir/test_goto.vim
index 1248de3f01..aeca0b4361 100644
--- a/src/testdir/test_goto.vim
+++ b/src/testdir/test_goto.vim
@@ -333,21 +333,24 @@ endfunc
func Test_motion_if_elif_else_endif()
new
- a
-/* Test pressing % on #if, #else #elsif and #endif,
- * with nested #if
- */
-#if FOO
-/* ... */
-# if BAR
-/* ... */
-# endif
-#elif BAR
-/* ... */
-#else
-/* ... */
-#endif
-.
+ let lines =<< trim END
+ /* Test pressing % on #if, #else #elsif and #endif,
+ * with nested #if
+ */
+ #if FOO
+ /* ... */
+ # if BAR
+ /* ... */
+ # endif
+ #elif BAR
+ /* ... */
+ #else
+ /* ... */
+ #endif
+
+ #define FOO 1
+ END
+ call setline(1, lines)
/#if FOO
norm %
call assert_equal([9, 1], getpos('.')[1:2])
@@ -363,6 +366,30 @@ func Test_motion_if_elif_else_endif()
norm $%
call assert_equal([6, 1], getpos('.')[1:2])
+ " Test for [# and ]# command
+ call cursor(5, 1)
+ normal [#
+ call assert_equal([4, 1], getpos('.')[1:2])
+ call cursor(5, 1)
+ normal ]#
+ call assert_equal([9, 1], getpos('.')[1:2])
+ call cursor(10, 1)
+ normal [#
+ call assert_equal([9, 1], getpos('.')[1:2])
+ call cursor(10, 1)
+ normal ]#
+ call assert_equal([11, 1], getpos('.')[1:2])
+
+ " Finding a match before the first line or after the last line should fail
+ normal gg
+ call assert_beeps('normal [#')
+ normal G
+ call assert_beeps('normal ]#')
+
+ " Finding a match for a macro definition (#define) should fail
+ normal G
+ call assert_beeps('normal %')
+
bw!
endfunc
@@ -392,3 +419,5 @@ func Test_motion_c_comment()
bw!
endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 7ae263909c..cec4acf3f2 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -515,4 +515,24 @@ func Test_complete_func_error()
call assert_fails('call complete_info({})', 'E714:')
endfunc
+" Test for completing words following a completed word in a line
+func Test_complete_wrapscan()
+ " complete words from another buffer
+ new
+ call setline(1, ['one two', 'three four'])
+ new
+ setlocal complete=w
+ call feedkeys("itw\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>", 'xt')
+ call assert_equal('two three four', getline(1))
+ close!
+ " complete words from the current buffer
+ setlocal complete=.
+ %d
+ call setline(1, ['one two', ''])
+ call cursor(2, 1)
+ call feedkeys("ion\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>\<C-X>\<C-N>", 'xt')
+ call assert_equal('one two one two', getline(2))
+ close!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_normal.vim b/src/testdir/test_normal.vim
index 08c0e07713..e75cb7183b 100644
--- a/src/testdir/test_normal.vim
+++ b/src/testdir/test_normal.vim
@@ -1451,11 +1451,27 @@ func Test_normal28_parenthesis()
norm! $d(
call assert_equal(['With some sentences!', '', ' ', '', 'This is a long sentence', ''], getline(1, '$'))
+ " Move to the next sentence from a paragraph macro
+ %d
+ call setline(1, ['.LP', 'blue sky!. blue sky.', 'blue sky. blue sky.'])
+ call cursor(1, 1)
+ normal )
+ call assert_equal([2, 1], [line('.'), col('.')])
+ normal )
+ call assert_equal([2, 12], [line('.'), col('.')])
+ normal ((
+ call assert_equal([1, 1], [line('.'), col('.')])
+
" It is an error if a next sentence is not found
%d
call setline(1, '.SH')
call assert_beeps('normal )')
+ " If only dot is present, don't treat that as a sentence
+ call setline(1, '. This is a sentence.')
+ normal $((
+ call assert_equal(3, col('.'))
+
" Jumping to a fold should open the fold
call setline(1, ['', '', 'one', 'two', 'three'])
set foldenable
@@ -2334,92 +2350,6 @@ func Test_normal42_halfpage()
bw!
endfunc
-" Tests for text object aw
-func Test_normal43_textobject1()
- new
- call append(0, ['foobar,eins,foobar', 'foo,zwei,foo '])
- " diw
- norm! 1gg0diw
- call assert_equal([',eins,foobar', 'foo,zwei,foo ', ''], getline(1,'$'))
- " daw
- norm! 2ggEdaw
- call assert_equal([',eins,foobar', 'foo,zwei,', ''], getline(1, '$'))
- %d
- call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "])
- " diW
- norm! 2ggwd2iW
- call assert_equal(['foo eins foobar', 'foo foo ', ''], getline(1,'$'))
- " daW
- norm! 1ggd2aW
- call assert_equal(['foobar', 'foo foo ', ''], getline(1,'$'))
-
- %d
- call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "])
- " aw in visual line mode switches to characterwise mode
- norm! 2gg$Vawd
- call assert_equal(['foo eins foobar', 'foo zwei foo'], getline(1,'$'))
- norm! 1gg$Viwd
- call assert_equal(['foo eins ', 'foo zwei foo'], getline(1,'$'))
-
- " clean up
- bw!
-endfunc
-
-" Test for is and as text objects
-func Test_normal44_textobjects2()
- new
- call append(0, ['This is a test. With some sentences!', '', 'Even with a question? And one more. And no sentence here'])
- " Test for dis - does not remove trailing whitespace
- norm! 1gg0dis
- call assert_equal([' With some sentences!', '', 'Even with a question? And one more. And no sentence here', ''], getline(1,'$'))
- " Test for das - removes leading whitespace
- norm! 3ggf?ldas
- call assert_equal([' With some sentences!', '', 'Even with a question? And no sentence here', ''], getline(1,'$'))
- " when used in visual mode, is made characterwise
- norm! 3gg$Visy
- call assert_equal('v', visualmode())
- " reset visualmode()
- norm! 3ggVy
- norm! 3gg$Vasy
- call assert_equal('v', visualmode())
- " basic testing for textobjects a< and at
- %d
- call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' '])
- " a<
- norm! 1gg0da<
- call assert_equal([' ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
- norm! 1pj
- call assert_equal([' <div>', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
- " at
- norm! d2at
- call assert_equal([' '], getline(1,'$'))
- %d
- call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' '])
- " i<
- norm! 1gg0di<
- call assert_equal(['<> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
- norm! 1Pj
- call assert_equal(['<div> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
- norm! d2it
- call assert_equal(['<div></div>',' '], getline(1,'$'))
- " basic testing for a[ and i[ text object
- %d
- call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
- norm! 3gg0di[
- call assert_equal([' ', '[', ']'], getline(1,'$'))
- call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
- norm! 3gg0ftd2a[
- call assert_equal([' '], getline(1,'$'))
- %d
- " Test for i" when cursor is in front of a quoted object
- call append(0, 'foo "bar"')
- norm! 1gg0di"
- call assert_equal(['foo ""', ''], getline(1,'$'))
-
- " clean up
- bw!
-endfunc
-
func Test_normal45_drop()
if !has('dnd')
" The ~ register does not exist
@@ -3065,4 +2995,41 @@ func Test_empty_region_error()
close!
endfunc
+" Test for 'w' and 'b' commands
+func Test_normal_word_move()
+ new
+ call setline(1, ['foo bar a', '', 'foo bar b'])
+ " copy a single character word at the end of a line
+ normal 1G$yw
+ call assert_equal('a', @")
+ " copy a single character word at the end of a file
+ normal G$yw
+ call assert_equal('b', @")
+ " check for a word movement handling an empty line properly
+ normal 1G$vwy
+ call assert_equal("a\n\n", @")
+
+ " copy using 'b' command
+ %d
+ " non-empty blank line at the start of file
+ call setline(1, [' ', 'foo bar'])
+ normal 2Gyb
+ call assert_equal(" \n", @")
+ " try to copy backwards from the start of the file
+ call setline(1, ['one two', 'foo bar'])
+ call assert_beeps('normal ggyb')
+ " 'b' command should stop at an empty line
+ call setline(1, ['one two', '', 'foo bar'])
+ normal 3Gyb
+ call assert_equal("\n", @")
+ normal 3Gy2b
+ call assert_equal("two\n", @")
+ " 'b' command should not stop at a non-empty blank line
+ call setline(1, ['one two', ' ', 'foo bar'])
+ normal 3Gyb
+ call assert_equal("two\n ", @")
+
+ close!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim
index 7aaf8db52d..a3b67055ce 100644
--- a/src/testdir/test_search.vim
+++ b/src/testdir/test_search.vim
@@ -1638,6 +1638,12 @@ func Test_search_smartcase()
exe "normal /\\a\\_.\\(.*\\)o\<CR>"
call assert_equal([2, 1], [line('.'), col('.')])
+ " Test for using special atoms with 'smartcase'
+ call setline(1, ['', ' Hello\ '])
+ call cursor(1, 1)
+ call feedkeys('/\_.\%(\uello\)\' .. "\<CR>", 'xt')
+ call assert_equal([2, 4], [line('.'), col('.')])
+
set ignorecase& smartcase&
close!
endfunc
@@ -1651,4 +1657,91 @@ func Test_search_past_eof()
close!
endfunc
+" Test for various search offsets
+func Test_search_offset()
+ " With /e, for a match in the first column of a line, the cursor should be
+ " placed at the end of the previous line.
+ new
+ call setline(1, ['one two', 'three four'])
+ call search('two\_.', 'e')
+ call assert_equal([1, 7], [line('.'), col('.')])
+
+ " with cursor at the beginning of the file, use /s+1
+ call cursor(1, 1)
+ exe "normal /two/s+1\<CR>"
+ call assert_equal([1, 6], [line('.'), col('.')])
+
+ " with cursor at the end of the file, use /e-1
+ call cursor(2, 10)
+ exe "normal ?three?e-1\<CR>"
+ call assert_equal([2, 4], [line('.'), col('.')])
+
+ " line offset - after the last line
+ call cursor(1, 1)
+ exe "normal /three/+1\<CR>"
+ call assert_equal([2, 1], [line('.'), col('.')])
+
+ " line offset - before the first line
+ call cursor(2, 1)
+ exe "normal ?one?-1\<CR>"
+ call assert_equal([1, 1], [line('.'), col('.')])
+
+ " character offset - before the first character in the file
+ call cursor(2, 1)
+ exe "normal ?one?s-1\<CR>"
+ call assert_equal([1, 1], [line('.'), col('.')])
+ call cursor(2, 1)
+ exe "normal ?one?e-3\<CR>"
+ call assert_equal([1, 1], [line('.'), col('.')])
+
+ " character offset - after the last character in the file
+ call cursor(1, 1)
+ exe "normal /four/s+4\<CR>"
+ call assert_equal([2, 10], [line('.'), col('.')])
+ call cursor(1, 1)
+ exe "normal /four/e+1\<CR>"
+ call assert_equal([2, 10], [line('.'), col('.')])
+
+ close!
+endfunc
+
+" Test for searching for matching parenthesis using %
+func Test_search_match_paren()
+ new
+ call setline(1, "abc(def')'ghi'('jk'\\t'lm)no")
+ " searching for a matching parenthesis should skip single quoted characters
+ call cursor(1, 4)
+ normal %
+ call assert_equal([1, 25], [line('.'), col('.')])
+ normal %
+ call assert_equal([1, 4], [line('.'), col('.')])
+ call cursor(1, 5)
+ normal ])
+ call assert_equal([1, 25], [line('.'), col('.')])
+ call cursor(1, 24)
+ normal [(
+ call assert_equal([1, 4], [line('.'), col('.')])
+
+ " matching parenthesis in 'virtualedit' mode with cursor after the eol
+ call setline(1, 'abc(defgh)')
+ set virtualedit=all
+ normal 20|%
+ call assert_equal(4, col('.'))
+ set virtualedit&
+ close!
+endfunc
+
+" Test for searching a pattern and stopping before a specified line
+func Test_search_stopline()
+ new
+ call setline(1, ['', '', '', 'vim'])
+ call assert_equal(0, search('vim', 'n', 3))
+ call assert_equal(4, search('vim', 'n', 4))
+ call setline(1, ['vim', '', '', ''])
+ call cursor(4, 1)
+ call assert_equal(0, search('vim', 'bn', 2))
+ call assert_equal(1, search('vim', 'bn', 1))
+ close!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_textformat.vim b/src/testdir/test_textformat.vim
index 90c95aeb26..49c1f06d38 100644
--- a/src/testdir/test_textformat.vim
+++ b/src/testdir/test_textformat.vim
@@ -882,7 +882,7 @@ func Test_tw_2_fo_tm_replace()
endfunc
" Test for 'matchpairs' with multibyte chars
-func Test_mps()
+func Test_mps_multibyte()
new
let t =<< trim END
{
@@ -906,6 +906,30 @@ func Test_mps()
bwipe!
endfunc
+" Test for 'matchpairs' in latin1 encoding
+func Test_mps_latin1()
+ new
+ let save_enc = &encoding
+ set encoding=latin1
+ call setline(1, 'abc(def)ghi')
+ normal %
+ call assert_equal(8, col('.'))
+ normal %
+ call assert_equal(4, col('.'))
+ call cursor(1, 6)
+ normal [(
+ call assert_equal(4, col('.'))
+ normal %
+ call assert_equal(8, col('.'))
+ call cursor(1, 6)
+ normal ])
+ call assert_equal(8, col('.'))
+ normal %
+ call assert_equal(4, col('.'))
+ let &encoding = save_enc
+ close!
+endfunc
+
" Test for ra on multi-byte characters
func Test_ra_multibyte()
new
diff --git a/src/testdir/test_textobjects.vim b/src/testdir/test_textobjects.vim
index 042c534218..eed84e3853 100644
--- a/src/testdir/test_textobjects.vim
+++ b/src/testdir/test_textobjects.vim
@@ -151,6 +151,24 @@ func Test_string_html_objects()
normal! dit
call assert_equal('-<b></b>', getline('.'))
+ " copy the tag block from leading indentation before the start tag
+ let t = " <b>\ntext\n</b>"
+ $put =t
+ normal! 2kvaty
+ call assert_equal("<b>\ntext\n</b>", @")
+
+ " copy the tag block from the end tag
+ let t = "<title>\nwelcome\n</title>"
+ $put =t
+ normal! $vaty
+ call assert_equal("<title>\nwelcome\n</title>", @")
+
+ " copy the outer tag block from a tag without an end tag
+ let t = "<html>\n<title>welcome\n</html>"
+ $put =t
+ normal! k$vaty
+ call assert_equal("<html>\n<title>welcome\n</html>", @")
+
set quoteescape&
enew!
endfunc
@@ -169,6 +187,10 @@ func Test_empty_html_tag()
normal 0f<vitsaaa
call assert_equal('aaa', getline(1))
+ " selecting a tag block in an non-empty blank line should fail
+ call setline(1, ' ')
+ call assert_beeps('normal $vaty')
+
bwipe!
endfunc
@@ -291,3 +313,232 @@ func Test_sentence_with_cursor_on_delimiter()
%delete _
endfunc
+
+" Test for the paragraph (ap) text object
+func Test_paragraph()
+ new
+ call setline(1, ['First line.', 'Second line.', 'Third line.'])
+ call cursor(2, 1)
+ normal vapy
+ call assert_equal("First line.\nSecond line.\nThird line.\n", @")
+
+ call cursor(2, 1)
+ call assert_beeps('normal vapapy')
+
+ call setline(1, ['First line.', 'Second line.', ' ', ''])
+ call cursor(1, 1)
+ normal vapy
+ call assert_equal("First line.\nSecond line.\n \n\n", @")
+
+ call setline(1, ['', '', '', 'First line.', 'Second line.'])
+ call cursor(2, 1)
+ normal yap
+ call assert_equal("\n\n\nFirst line.\nSecond line.\n", @")
+ call assert_beeps('normal 3yap')
+ exe "normal \<C-C>"
+
+ %d
+ call setline(1, [' ', ' ', ' '])
+ call cursor(2, 1)
+ normal Vipy
+ call assert_equal(" \n \n \n", @")
+ call cursor(2, 1)
+ call assert_beeps("normal Vipip")
+ exe "normal \<C-C>"
+
+ close!
+endfunc
+
+" Tests for text object aw
+func Test_textobj_a_word()
+ new
+ call append(0, ['foobar,eins,foobar', 'foo,zwei,foo '])
+ " diw
+ norm! 1gg0diw
+ call assert_equal([',eins,foobar', 'foo,zwei,foo ', ''], getline(1,'$'))
+ " daw
+ norm! 2ggEdaw
+ call assert_equal([',eins,foobar', 'foo,zwei,', ''], getline(1, '$'))
+ " daw the last word in a line
+ call setline(1, ['foo bar', 'foo bar', ''])
+ call cursor(1, 5)
+ normal daw
+ call assert_equal('foo', getline(1))
+ " aw in visual mode
+ call cursor(2, 5)
+ normal! vawx
+ call assert_equal('foo', getline(2))
+ %d
+ call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "])
+ " diW
+ norm! 2ggwd2iW
+ call assert_equal(['foo eins foobar', 'foo foo ', ''], getline(1,'$'))
+ " daW
+ norm! 1ggd2aW
+ call assert_equal(['foobar', 'foo foo ', ''], getline(1,'$'))
+
+ %d
+ call append(0, ["foo\teins\tfoobar", "foo\tzwei\tfoo "])
+ " aw in visual line mode switches to characterwise mode
+ norm! 2gg$Vawd
+ call assert_equal(['foo eins foobar', 'foo zwei foo'], getline(1,'$'))
+ norm! 1gg$Viwd
+ call assert_equal(['foo eins ', 'foo zwei foo'], getline(1,'$'))
+
+ " visually selecting a tab before a word with 'selection' set to 'exclusive'
+ set selection=exclusive
+ normal gg3lvlawy
+ call assert_equal("\teins", @")
+ " visually selecting a tab before a word with 'selection' set to 'inclusive'
+ set selection=inclusive
+ normal gg3lvlawy
+ call assert_equal("\teins\t", @")
+ set selection&
+
+ " selecting a word with no non-space characters in a buffer fails
+ %d
+ call setline(1, ' ')
+ call assert_beeps('normal 3lyaw')
+
+ " visually selecting words backwards with no more words to select
+ call setline(1, 'one two')
+ call assert_beeps('normal 2lvh2aw')
+ exe "normal \<C-C>"
+ call assert_beeps('normal $vh3aw')
+ exe "normal \<C-C>"
+ call setline(1, ['', 'one two'])
+ call assert_beeps('normal 2G2lvh3aw')
+ exe "normal \<C-C>"
+
+ " selecting words forward with no more words to select
+ %d
+ call setline(1, 'one a')
+ call assert_beeps('normal 0y3aw')
+ call setline(1, 'one two ')
+ call assert_beeps('normal 0y3aw')
+ call assert_beeps('normal 03ly2aw')
+
+ " clean up
+ bw!
+endfunc
+
+" Test for is and as text objects
+func Test_textobj_sentence()
+ new
+ call append(0, ['This is a test. With some sentences!', '',
+ \ 'Even with a question? And one more. And no sentence here'])
+ " Test for dis - does not remove trailing whitespace
+ norm! 1gg0dis
+ call assert_equal([' With some sentences!', '',
+ \ 'Even with a question? And one more. And no sentence here', ''],
+ \ getline(1,'$'))
+ " Test for das - removes leading whitespace
+ norm! 3ggf?ldas
+ call assert_equal([' With some sentences!', '',
+ \ 'Even with a question? And no sentence here', ''], getline(1,'$'))
+ " when used in visual mode, is made characterwise
+ norm! 3gg$Visy
+ call assert_equal('v', visualmode())
+ " reset visualmode()
+ norm! 3ggVy
+ norm! 3gg$Vasy
+ call assert_equal('v', visualmode())
+ " basic testing for textobjects a< and at
+ %d
+ call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' '])
+ " a<
+ norm! 1gg0da<
+ call assert_equal([' ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
+ norm! 1pj
+ call assert_equal([' <div>', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
+ " at
+ norm! d2at
+ call assert_equal([' '], getline(1,'$'))
+ %d
+ call setline(1, ['<div> ','<a href="foobar" class="foo">xyz</a>',' </div>', ' '])
+ " i<
+ norm! 1gg0di<
+ call assert_equal(['<> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
+ norm! 1Pj
+ call assert_equal(['<div> ', '<a href="foobar" class="foo">xyz</a>', ' </div>', ' '], getline(1,'$'))
+ norm! d2it
+ call assert_equal(['<div></div>',' '], getline(1,'$'))
+ " basic testing for a[ and i[ text object
+ %d
+ call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
+ norm! 3gg0di[
+ call assert_equal([' ', '[', ']'], getline(1,'$'))
+ call setline(1, [' ', '[', 'one [two]', 'thre', ']'])
+ norm! 3gg0ftd2a[
+ call assert_equal([' '], getline(1,'$'))
+
+ " clean up
+ bw!
+endfunc
+
+" Test for quote (', " and `) textobjects
+func Test_textobj_quote()
+ new
+
+ " Test for i" when cursor is in front of a quoted object
+ call append(0, 'foo "bar"')
+ norm! 1gg0di"
+ call assert_equal(['foo ""', ''], getline(1,'$'))
+
+ " Test for visually selecting an inner quote
+ %d
+ " extend visual selection from one quote to the next
+ call setline(1, 'color "red" color "blue"')
+ call cursor(1, 7)
+ normal v4li"y
+ call assert_equal('"red" color "blue', @")
+
+ " try to extend visual selection from one quote to a non-existing quote
+ call setline(1, 'color "red" color blue')
+ call cursor(1, 7)
+ call feedkeys('v4li"y', 'xt')
+ call assert_equal('"red"', @")
+
+ " try to extend visual selection from one quote to a next partial quote
+ call setline(1, 'color "red" color "blue')
+ call cursor(1, 7)
+ normal v4li"y
+ call assert_equal('"red" color ', @")
+
+ " select a quote backwards in visual mode
+ call cursor(1, 12)
+ normal vhi"y
+ call assert_equal('red" ', @")
+ call assert_equal(8, col('.'))
+
+ " select a quote backwards in visual mode from outside the quote
+ call cursor(1, 17)
+ normal v2hi"y
+ call assert_equal('red', @")
+ call assert_equal(8, col('.'))
+
+ " visually selecting a quote with 'selection' set to 'exclusive'
+ call setline(1, 'He said "How are you?"')
+ set selection=exclusive
+ normal 012lv2li"y
+ call assert_equal('How are you?', @")
+ set selection&
+
+ " try copy a quote object with a single quote in the line
+ call setline(1, "Smith's car")
+ call cursor(1, 6)
+ call assert_beeps("normal yi'")
+ call assert_beeps("normal 2lyi'")
+
+ " selecting space before and after a quoted string
+ call setline(1, "some 'special' string")
+ normal 0ya'
+ call assert_equal("'special' ", @")
+ call setline(1, "some 'special'string")
+ normal 0ya'
+ call assert_equal(" 'special'", @")
+
+ close!
+endfunc
+
+" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
index 143b140bae..87cf2a7ade 100644
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -890,4 +890,27 @@ func Test_AAA_start_visual_mode_with_count()
close!
endfunc
+" Test for visually selecting an inner block (iB)
+func Test_visual_inner_block()
+ new
+ call setline(1, ['one', '{', 'two', '{', 'three', '}', 'four', '}', 'five'])
+ call cursor(5, 1)
+ " visually select all the lines in the block and then execute iB
+ call feedkeys("ViB\<C-C>", 'xt')
+ call assert_equal([0, 5, 1, 0], getpos("'<"))
+ call assert_equal([0, 5, 6, 0], getpos("'>"))
+ " visually select two inner blocks
+ call feedkeys("ViBiB\<C-C>", 'xt')
+ call assert_equal([0, 3, 1, 0], getpos("'<"))
+ call assert_equal([0, 7, 5, 0], getpos("'>"))
+ " try to select non-existing inner block
+ call cursor(5, 1)
+ call assert_beeps('normal ViBiBiB')
+ " try to select a unclosed inner block
+ 8,9d
+ call cursor(5, 1)
+ call assert_beeps('normal ViBiB')
+ close!
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index b99f9bedda..8e08363333 100644
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 655,
+/**/
654,
/**/
653,