diff --git a/README.md b/README.md index c8ee5c0..7d65b3b 100644 --- a/README.md +++ b/README.md @@ -138,45 +138,6 @@ let g:wordmotion_mappings['w'] = '' call wordmotion#reload() ``` -## Caveats - -There are some special cases with how Vim's word motions work.\ -E.g., -``` -Vim: - - ^foo [b]ar$ -> dw -> ^foo[ ]$ - ^ baz$ ^ baz$ - - ^[f]oo bar$ -> cw -> ^[ ]bar$ - -This plugin: - - ^foo [b]ar$ -> dw -> ^foo [b]az$ - ^ baz$ - - ^[f]oo bar$ -> cw -> ^[b]ar$ -``` -This plugin faithfully follows the motion of `w` when executing `dw` and `cw`, -while Vim replaces these two special cases with the behavior of `de` and `ce`, -respectively. - -If you want to restore Vim's special case behavior with `dw` and `cw`, you can -do this: -``` -nmap dw de -nmap cw ce -``` - -If you want the same behavior for uppercase motions (i.e., `dW` and `cW`), you -can set `g:wordmotion_uppercase_spaces`.\ -E.g., -``` -let g:wordmotion_uppercase_spaces = [' '] -``` -will enable this behavior without adding extra space characters to uppercase -motions. - ## Related [camelcasemotion][3] diff --git a/autoload/wordmotion.vim b/autoload/wordmotion.vim index 62f0b8d..a9b2eb4 100644 --- a/autoload/wordmotion.vim +++ b/autoload/wordmotion.vim @@ -46,15 +46,22 @@ endfunction call wordmotion#init() function wordmotion#motion(count, mode, flags, uppercase, extra) + let l:flags = a:flags + + if a:mode == 'o' && v:operator == 'c' && l:flags == '' + " special case (see :help cw) + let l:flags = 'ce' + endif + if a:mode == 'x' normal! gv - elseif a:mode == 'o' && a:flags =~# 'e' + elseif a:mode == 'o' && l:flags =~# 'e' " need to make this inclusive for operator pending mode normal! v endif let l:words = a:extra + [a:uppercase ? s:uS . '\+' : s:word] - if a:flags != 'e' " e does not stop in an empty line + if l:flags != 'e' " e does not stop in an empty line call add(l:words, '^$') endif @@ -64,17 +71,17 @@ function wordmotion#motion(count, mode, flags, uppercase, extra) let l:pos = getpos('.') for @_ in range(a:count) - call search(l:pattern, a:flags . 'W') + call search(l:pattern, l:flags . 'W') endfor " ugly hack for 'w' going forwards at end of file " and 'ge' going backwards at beginning of file if a:count && l:pos == getpos('.') " cursor didn't move - if a:flags == 'be' && line('.') == 1 + if l:flags == 'be' && line('.') == 1 " at first line and going backwards, let's go to the front normal! 0 - elseif a:flags == '' && line('.') == line('$') + elseif l:flags == '' && line('.') == line('$') " at last line and going forwards, let's go to the back if a:mode == 'o' " need to include last character if in operator pending mode diff --git a/doc/wordmotion.txt b/doc/wordmotion.txt index 4008fc6..c402f4d 100644 --- a/doc/wordmotion.txt +++ b/doc/wordmotion.txt @@ -178,42 +178,4 @@ then later re-enable it let g:wordmotion_mappings['w'] = '' call wordmotion#reload() < -CAVEATS *wordmotion-caveats* - -There are some special cases with how Vim's word motions work. -E.g., - -Vim: -> - ^foo [b]ar$ -> dw -> ^foo[ ]$ - ^ baz$ ^ baz$ - - ^[f]oo bar$ -> cw -> ^[ ]bar$ - -This plugin: -> - ^foo [b]ar$ -> dw -> ^foo [b]az$ - ^ baz$ - - ^[f]oo bar$ -> cw -> ^[b]ar$ -< -This plugin faithfully follows the motion of `w` when executing `dw` and `cw`, -while Vim replaces these two special cases with the behavior of `de` and `ce`, -respectively. - -If you want to restore Vim's special case behavior with `dw` and `cw`, you can -do this: -> - nmap dw de - nmap cw ce -< -If you want the same behavior for uppercase motions (i.e., `dW` and `cW`), you -can set `g:wordmotion_uppercase_spaces`. -E.g., -> - let g:wordmotion_uppercase_spaces = [' '] -< -will enable this behavior without adding extra space characters to uppercase -motions. - - vim:tw=78:ts=8:sw=8:noet:ft=help:norl: + vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/tests/custom_mappings.vader b/tests/custom_mappings.vader index 1be25a1..cd4eec9 100644 --- a/tests/custom_mappings.vader +++ b/tests/custom_mappings.vader @@ -1,4 +1,4 @@ -After: +After (Restore default options): call wordmotion#_default() Execute (Check mappings with prefix): diff --git a/tests/cwdw.vader b/tests/cwdw.vader new file mode 100644 index 0000000..edcb098 --- /dev/null +++ b/tests/cwdw.vader @@ -0,0 +1,184 @@ +# regular words + +Given (This is some text): + This is some text + +# first word of line, start of word + +Do (dw at [T]his): + dw + +Then (Assert that cursor is at [i]s): + Assert 1, col('.') + +Expect (This deleted): + is some text + +Do (cw at [T]his): + cwThat\ + +Then (Assert that cursor is at Tha[t]): + Assert 4, col('.') + +Expect (This changed to That): + That is some text + +# first word of line, middle of word + +Do (dw at T[h]is): + l + dw + +Then (Assert that cursor is at [i]s): + Assert 2, col('.') + +Expect (his deleted): + Tis some text + +Do (cw at T[h]is): + l + cwThat\ + +Then (Assert that cursor is at TTha[t]): + Assert 5, col('.') + +Expect (This changed to TThat): + TThat is some text + +# first word of line, end of word + +Do (dw at Thi[s]): + e + dw + +Then (Assert that cursor is at [i]s): + Assert 5, col('.') + +Expect (his deleted): + Thiis some text + +Do (cw at Thi[s]): + e + cwThat\ + +Then (Assert that cursor is at ThiTha[t]): + Assert 7, col('.') + +Expect (This changed to ThiThat): + ThiThat is some text + +# middle of line, start of word + +Do (dw at [s]ome): + 2w + dw + +Then (Assert that cursor is at [t]ext): + Assert 9, col('.') + +Expect (some deleted): + This is text + +Do (cw at [s]ome): + 2w + cwother\ + +Then (Assert that cursor is at othe[r]): + Assert 13, col('.') + +Expect (some changed to other): + This is other text + +# middle of line, middle of word + +Do (dw at s[o]me): + 2wl + dw + +Then (Assert that cursor is at [t]ext): + Assert 10, col('.') + +Expect (some deleted): + This is stext + +Do (cw at s[o]me): + 2wl + cwother\ + +Then (Assert that cursor is at othe[r]): + Assert 13, col('.') + +Expect (some changed to sother): + This is sother text + +# middle of line, end of word + +Do (dw at som[e]): + 3e + dw + +Then (Assert that cursor is at [t]ext): + Assert 12, col('.') + +Expect (some deleted): + This is somtext + +Do (cw at som[e]): + 3e + cwother\ + +Then (Assert that cursor is at somothe[r]): + Assert 15, col('.') + +Expect (some changed to somother): + This is somother text + +# end of line, start of word + +Do (dw at [t]ext): + 3w + dw + +Then (Assert that cursor is at some[_]): + Assert 13, col('.') + +Expect (text deleted): + This is some + +Do (cw at [t]ext): + 3w + cwchange\ + +Then (Assert that cursor is at chang[e]): + Assert 19, col('.') + +Expect (text changed to change): + This is some change + +# end of line, middle of word + +Do (dw at t[e]xt): + 3wl + dw + +Then (Assert that cursor is at _[t]): + Assert 14, col('.') + +Expect (text deleted): + This is some t + +Do (cw at t[e]xt): + 3wl + cwchange\ + +Then (Assert that cursor is at tchang[e]): + Assert 20, col('.') + +Expect (text changed to tchange): + This is some tchange + +# single character words + +Given (a b c\nd e f): + a b c + d e f diff --git a/tests/default_mappings.vader b/tests/default_mappings.vader index a420e6e..3601e12 100644 --- a/tests/default_mappings.vader +++ b/tests/default_mappings.vader @@ -1,4 +1,4 @@ -After: +After (Restore default options): call wordmotion#_default() Execute (Check default mappings): diff --git a/tests/issues.vader b/tests/issues.vader index 7006359..697293a 100644 --- a/tests/issues.vader +++ b/tests/issues.vader @@ -3,6 +3,8 @@ Given (Weird characters: https://github.com/chaoren/vim-wordmotion/issues/1): Execute (Move 2 words): normal 2w + +Then (Assert that cursor is at [g]hi): AssertEqual 'g', getline('.')[col('.') - 1] Given (Underscores: https://github.com/chaoren/vim-wordmotion/issues/5): @@ -10,6 +12,8 @@ Given (Underscores: https://github.com/chaoren/vim-wordmotion/issues/5): Execute (Move 2 words): normal 2w + +Then (Assert that cursor is at _[d]ef_): AssertEqual 'g', getline('.')[col('.') - 1] Given (CamelCase): diff --git a/tests/spaces.vader b/tests/spaces.vader index e62fef6..1198480 100644 --- a/tests/spaces.vader +++ b/tests/spaces.vader @@ -1,4 +1,4 @@ -After: +After (Restore default options): call wordmotion#_default() Given (Lorem ipsum deliminated by '_'):