Permalink
Browse files

Version 1.70

- ENH: Check for searches wrapping around the buffer and issue a corresponding warning, like the built-in searches do. Though the mappings that can be made with CountJump currently do not use 'wrapscan', other plugins that define their own jump functions and use the CountJump#CountJump() function for it may use it. Create function overloads CountJump#CountJumpWithWrapMessage() and CountJump#CountSearchWithWrapMessage().
  • Loading branch information...
1 parent 660d37b commit ebae8c2bf8bca038d2e2525ed4b14414eba850a9 Ingo Karkat committed with Sep 3, 2012
Showing with 132 additions and 70 deletions.
  1. +1 −1 README
  2. +113 −66 autoload/CountJump.vim
  3. +18 −3 doc/CountJump.txt
View
2 README
@@ -31,7 +31,7 @@ mail_movement (vimscript #3182): Movement over email quotes with ]] etc.
JumpToTrailingWhitespace (vimscript #3968): Motions to locate unwanted
whitespace at the end of lines.
TaskMotion (vimscript #3990): Motions to task and TODO markers.
-ConflictMotion (vimscript #3991): Motions to and inside SCM conflict markers.
+ConflictMotions (vimscript #3991): Motions to and inside SCM conflict markers.
vim_movement (vimscript #4002): Movement over Vim functions with ]m etc.
vbs_movement (vimscript #4003): Movement over VBScript classes /
functions / properties / subs with ]m etc.
View
179 autoload/CountJump.vim
@@ -1,83 +1,107 @@
-" CountJump.vim: Move to a buffer position via repeated jumps (or searches).
+" CountJump.vim: Move to a buffer position via repeated jumps (or searches).
"
" DEPENDENCIES:
"
" Copyright: (C) 2009-2011 Ingo Karkat
-" The VIM LICENSE applies to this script; see ':help copyright'.
+" The VIM LICENSE applies to this script; see ':help copyright'.
"
" Maintainer: Ingo Karkat <ingo@karkat.de>
"
-" REVISION DATE REMARKS
+" REVISION DATE REMARKS
+" 1.70.013 17-Aug-2012 ENH: Check for searches wrapping around the
+" buffer and issue a corresponding warning, like
+" the built-in searches do. Though the mappings
+" that can be made with CountJump currently do not
+" use 'wrapscan', other plugins that define their
+" own jump functions and use the
+" CountJump#CountJump() function for it may use
+" it. Create function overloads
+" CountJump#CountJumpWithWrapMessage() and
+" CountJump#CountSearchWithWrapMessage().
" 1.41.012 13-Jun-2011 FIX: Directly ring the bell to avoid problems
-" when running under :silent!.
+" when running under :silent!.
" 1.30.011 19-Dec-2010 Removed return value of jump position from
" CountJump#CountJump() and CountJump#JumpFunc();
" it isn't needed, as these functions are
-" typically used directly in motion mappings.
+" typically used directly in motion mappings.
" CountJump#JumpFunc() now uses cursor position
" after invoking jump function, and doesn't
" require a returned position any more. This is
" only a special case for CountJump#TextObject,
" and should not be generally required of a jump
" function. The jump function is now also expected
-" to beep, so removed that here.
+" to beep, so removed that here.
" 1.30.010 18-Dec-2010 Moved CountJump#Region#Jump() here as
" CountJump#JumpFunc(). It fits here much better
" because of the similarity to
" CountJump#CountJump(), and actually has nothing
-" to do with regions.
+" to do with regions.
" 1.20.009 30-Jul-2010 FIX: CountJump#CountJump() with mode "O" didn't
" add original position to jump list. Simplified
-" conditional.
+" conditional.
" 1.10.008 15-Jul-2010 Changed behavior if there aren't [count]
" matches: Instead of jumping to the last
" available match (and ringing the bell), the
" cursor stays at the original position, like with
-" the old vi-compatible motions.
+" the old vi-compatible motions.
" ENH: Only adding to jump list if there actually
" is a match. This is like the built-in Vim
-" motions work.
+" motions work.
" 1.00.007 22-Jun-2010 Added special mode 'O' for
" CountJump#CountJump() with special correction
-" for a pattern to end in operator-pending mode.
-" Reviewed for use in operator-pending mode.
+" for a pattern to end in operator-pending mode.
+" Reviewed for use in operator-pending mode.
" 006 03-Oct-2009 Now returning [lnum, col] like searchpos(), not
-" just line number.
+" just line number.
" 005 02-Oct-2009 CountJump#CountSearch() now handles 'c' search()
" flag; it is cleared on subsequent iterations to
-" avoid staying put at the current match.
+" avoid staying put at the current match.
" 004 14-Feb-2009 Renamed from 'custommotion.vim' to
" 'CountJump.vim' and split off motion and
-" text object parts.
+" text object parts.
" 003 13-Feb-2009 Added functionality to create inner/outer text
" objects delimited by the same begin and end
-" patterns.
+" patterns.
" 002 13-Feb-2009 Now also allowing end match for the
-" patternToEnd.
+" patternToEnd.
" 001 12-Feb-2009 file creation
-function! CountJump#CountSearch( count, searchArguments )
+function! s:WrapMessage( searchName, isBackward )
+ if &shortmess !~# 's'
+ let v:warningmsg = a:searchName . ' ' . (a:isBackward ? 'hit TOP, continuing at BOTTOM' : 'hit BOTTOM, continuing at TOP')
+ echohl WarningMsg
+ echomsg v:warningmsg
+ echohl None
+ endif
+endfunction
+function! CountJump#CountSearchWithWrapMessage( count, searchName, searchArguments )
"*******************************************************************************
"* PURPOSE:
" Search for the <count>th occurrence of the passed search() pattern and
-" arguments.
+" arguments.
"
"* ASSUMPTIONS / PRECONDITIONS:
-" None.
+" None.
"
"* EFFECTS / POSTCONDITIONS:
-" Jumps to the <count>th occurrence and opens any closed folds there.
-" If the pattern doesn't match (<count> times), a beep is emitted.
+" Jumps to the <count>th occurrence and opens any closed folds there.
+" If the pattern doesn't match (<count> times), a beep is emitted.
"
"* INPUTS:
-" a:count Number of occurrence to jump to.
+" a:count Number of occurrence to jump to.
+" a:searchName Object to be searched; used as the subject in the message
+" when the search wraps: "a:searchName hit BOTTOM, continuing
+" at TOP". When empty, no wrap message is issued.
" a:searchArguments Arguments to search() as a List [{pattern}, {flags}, ...]
"
-"* RETURN VALUES:
-" List with the line and column position, or [0, 0], like searchpos().
+"* RETURN VALUES:
+" List with the line and column position, or [0, 0], like searchpos().
"*******************************************************************************
let l:save_view = winsaveview()
let l:searchArguments = copy(a:searchArguments)
+ let l:isWrapped = 0
+ let l:isBackward = (get(a:searchArguments, 1, '') =~# 'b')
+ let [l:prevLine, l:prevCol] = [line('.'), col('.')]
for l:i in range(1, a:count)
let l:matchPosition = call('searchpos', l:searchArguments)
@@ -87,11 +111,11 @@ function! CountJump#CountSearch( count, searchArguments )
" match. Undo that to behave like the old vi-compatible
" motions. (Only the ]s motion has different semantics; it obeys
" the 'wrapscan' setting and stays at the last possible match if
- " the setting is off.)
+ " the setting is off.)
call winrestview(l:save_view)
endif
- " Ring the bell to indicate that no further match exists.
+ " Ring the bell to indicate that no further match exists.
execute "normal! \<C-\>\<C-n>\<Esc>"
return l:matchPosition
@@ -101,107 +125,130 @@ function! CountJump#CountSearch( count, searchArguments )
" In case the search accepts a match at the cursor position
" (i.e. search(..., 'c')), the flag must only be active on the very
" first iteration; otherwise, all subsequent iterations will just
- " stay put at the current match.
+ " stay put at the current match.
let l:searchArguments[1] = substitute(l:searchArguments[1], 'c', '', 'g')
endif
+
+ " Note: No need to check s:searchArguments and 'wrapscan'; the wrapping
+ " can only occur if 'wrapscan' is actually on.
+ if ! l:isBackward && (l:prevLine > l:matchPosition[0] || l:prevLine == l:matchPosition[0] && l:prevCol >= l:matchPosition[1])
+ let l:isWrapped = 1
+ elseif l:isBackward && (l:prevLine < l:matchPosition[0] || l:prevLine == l:matchPosition[0] && l:prevCol <= l:matchPosition[1])
+ let l:isWrapped = 1
+ endif
+ let [l:prevLine, l:prevCol] = l:matchPosition
endfor
" Open the fold at the final search result. This makes the search work like
" the built-in motions, and avoids that some visual selections get stuck at
- " a match inside a closed fold.
+ " a match inside a closed fold.
normal! zv
+ if l:isWrapped && ! empty(a:searchName)
+ redraw
+ call s:WrapMessage(a:searchName, l:isBackward)
+ endif
+
return l:matchPosition
endfunction
-function! CountJump#CountJump( mode, ... )
+function! CountJump#CountSearch( count, searchArguments )
+ return CountJump#CountSearchWithWrapMessage(a:count, '', a:searchArguments)
+endfunction
+function! CountJump#CountJumpWithWrapMessage( mode, searchName, ... )
"*******************************************************************************
"* PURPOSE:
" Implement a custom motion by jumping to the <count>th occurrence of the
-" passed pattern.
+" passed pattern.
"
"* ASSUMPTIONS / PRECONDITIONS:
-" None.
+" None.
"
"* EFFECTS / POSTCONDITIONS:
-" Normal mode: Jumps to the <count>th occurrence.
-" Visual mode: Extends the selection to the <count>th occurrence.
-" If the pattern doesn't match (<count> times), a beep is emitted.
+" Normal mode: Jumps to the <count>th occurrence.
+" Visual mode: Extends the selection to the <count>th occurrence.
+" If the pattern doesn't match (<count> times), a beep is emitted.
"
"* INPUTS:
-" a:mode Mode in which the search is invoked. Either 'n', 'v' or 'o'.
+" a:mode Mode in which the search is invoked. Either 'n', 'v' or 'o'.
" With 'O': Special additional treatment for operator-pending mode
-" with a pattern to end.
-" ... Arguments to search().
+" with a pattern to end.
+" a:searchName Object to be searched; used as the subject in the message
+" when the search wraps: "a:searchName hit BOTTOM, continuing
+" at TOP". When empty, no wrap message is issued.
+" ... Arguments to search().
"
-"* RETURN VALUES:
-" None.
+"* RETURN VALUES:
+" None.
"*******************************************************************************
let l:save_view = winsaveview()
if a:mode ==# 'v'
normal! gv
endif
- let l:matchPosition = CountJump#CountSearch(v:count1, a:000)
+ let l:matchPosition = CountJump#CountSearchWithWrapMessage(v:count1, a:searchName, a:000)
if l:matchPosition != [0, 0]
- " Add the original cursor position to the jump list.
+ " Add the original cursor position to the jump list.
call winrestview(l:save_view)
normal! m'
call setpos('.', [0] + l:matchPosition + [0])
if a:mode ==# 'O'
" Special additional treatment for operator-pending mode with a pattern
- " to end.
- " The difference between normal mode, visual and operator-pending
+ " to end.
+ " The difference between normal mode, visual and operator-pending
" mode is that in the latter, the motion must go _past_ the final
" character, so that all characters are selected. This is done by
- " appending a 'l' motion after the search.
+ " appending a 'l' motion after the search.
"
" In operator-pending mode, the 'l' motion only works properly
" at the end of the line (i.e. when the moved-over "word" is at
" the end of the line) when the 'l' motion is allowed to move
" over to the next line. Thus, the 'l' motion is added
- " temporarily to the global 'whichwrap' setting.
+ " temporarily to the global 'whichwrap' setting.
" Without this, the motion would leave out the last character in
" the line. I've also experimented with temporarily setting
- " "set virtualedit=onemore", but that didn't work.
+ " "set virtualedit=onemore", but that didn't work.
let l:save_ww = &whichwrap
set whichwrap+=l
normal! l
let &whichwrap = l:save_ww
endif
endif
endfunction
+function! CountJump#CountJump( mode, ... )
+ return call('CountJump#CountJumpWithWrapMessage', [a:mode, ''] + a:000)
+endfunction
function! CountJump#JumpFunc( mode, JumpFunc, ... )
"*******************************************************************************
"* PURPOSE:
" Implement a custom motion by invoking a jump function that is passed the
-" <count> and the optional arguments.
+" <count> and the optional arguments.
"
"* ASSUMPTIONS / PRECONDITIONS:
-" None.
+" None.
"
"* EFFECTS / POSTCONDITIONS:
-" Normal mode: Jumps to the <count>th occurrence.
-" Visual mode: Extends the selection to the <count>th occurrence.
-" If the jump doesn't work, a beep is emitted.
+" Normal mode: Jumps to the <count>th occurrence.
+" Visual mode: Extends the selection to the <count>th occurrence.
+" If the jump doesn't work, a beep is emitted.
"
"* INPUTS:
-" a:mode Mode in which the search is invoked. Either 'n', 'v' or 'o'.
+" a:mode Mode in which the search is invoked. Either 'n', 'v' or 'o'.
" With 'O': Special additional treatment for operator-pending mode
-" with a characterwise jump.
-" a:JumpFunc Function which is invoked to jump.
+" with a characterwise jump.
+" a:JumpFunc Function which is invoked to jump.
" The jump function must take at least one argument:
-" a:count Number of matches to jump to.
-" It can take more arguments which must then be passed in here:
+" a:count Number of matches to jump to.
+" It can take more arguments which must then be passed in here:
" ... Arguments to the passed a:JumpFunc
" The jump function should position the cursor to the appropriate position in
" the current window, and open any folds there. It is expected to beep and
" keep the cursor at its original position when no appropriate position can be
-" found.
+" found.
"
-"* RETURN VALUES:
-" None.
+"* RETURN VALUES:
+" None.
"*******************************************************************************
let l:save_view = winsaveview()
let l:originalPosition = getpos('.')
@@ -213,27 +260,27 @@ function! CountJump#JumpFunc( mode, JumpFunc, ... )
call call(a:JumpFunc, [v:count1] + a:000)
let l:matchPosition = getpos('.')
if l:matchPosition != l:originalPosition
- " Add the original cursor position to the jump list.
+ " Add the original cursor position to the jump list.
call winrestview(l:save_view)
normal! m'
call setpos('.', l:matchPosition)
if a:mode ==# 'O'
" Special additional treatment for operator-pending mode with a
- " characterwise jump.
- " The difference between normal mode, visual and operator-pending
+ " characterwise jump.
+ " The difference between normal mode, visual and operator-pending
" mode is that in the latter, the motion must go _past_ the final
" character, so that all characters are selected. This is done by
- " appending a 'l' motion after the search.
+ " appending a 'l' motion after the search.
"
" In operator-pending mode, the 'l' motion only works properly
" at the end of the line (i.e. when the moved-over "word" is at
" the end of the line) when the 'l' motion is allowed to move
" over to the next line. Thus, the 'l' motion is added
- " temporarily to the global 'whichwrap' setting.
+ " temporarily to the global 'whichwrap' setting.
" Without this, the motion would leave out the last character in
" the line. I've also experimented with temporarily setting
- " "set virtualedit=onemore", but that didn't work.
+ " "set virtualedit=onemore", but that didn't work.
let l:save_ww = &whichwrap
set whichwrap+=l
normal! l
View
21 doc/CountJump.txt
@@ -45,6 +45,13 @@ help_movement (vimscript #3179): Movement over Vim help sections with ]] etc
mail_movement (vimscript #3182): Movement over email quotes with ]] etc.
JumpToTrailingWhitespace (vimscript #3968): Motions to locate unwanted
whitespace at the end of lines.
+TaskMotion (vimscript #3990): Motions to task and TODO markers.
+ConflictMotions (vimscript #3991): Motions to and inside SCM conflict markers.
+vim_movement (vimscript #4002): Movement over Vim functions with ]m etc.
+vbs_movement (vimscript #4003): Movement over VBScript classes /
+ functions / properties / subs with ]m etc.
+dosbatch_movement (vimscript #4004): Movement over MSDOS batch file functions
+ / labels with ]m etc.
RELATED WORKS *
@@ -168,10 +175,10 @@ above calls in a ~/.vim/ftplugin/pascal_movement.vim script and are done.
INSTALLATION *CountJump-installation*
This script is packaged as a |vimball|. If you have the "gunzip" decompressor
-in your PATH, simply edit the *.vba.gz package in Vim; otherwise, decompress
+in your PATH, simply edit the *.vmb.gz package in Vim; otherwise, decompress
the archive first, e.g. using WinZip. Inside Vim, install by sourcing the
vimball or via the |:UseVimball| command. >
- vim CountJump.vba.gz
+ vim CountJump*.vmb.gz
:so %
To uninstall, use the |:RmVimball| command.
@@ -235,6 +242,14 @@ IDEAS *CountJump-ideas*
==============================================================================
HISTORY *CountJump-history*
+1.70 03-Sep-2012
+- ENH: Check for searches wrapping around the buffer and issue a corresponding
+ warning, like the built-in searches do. Though the mappings that can be made
+ with CountJump currently do not use 'wrapscan', other plugins that define
+ their own jump functions and use the CountJump#CountJump() function for it
+ may use it. Create function overloads CountJump#CountJumpWithWrapMessage()
+ and CountJump#CountSearchWithWrapMessage().
+
1.60 27-Mar-2012
- ENH: Allow motions that do not start with [ / ] and text objects that do not
start with i / a by passing keys that begin with <Plug>. With this, plugins
@@ -330,7 +345,7 @@ Started development.
==============================================================================
Copyright: (C) 2009-2012 Ingo Karkat
-The VIM LICENSE applies to this script; see|copyright|.
+The VIM LICENSE applies to this script; see |copyright|.
Maintainer: Ingo Karkat <ingo@karkat.de>
==============================================================================

0 comments on commit ebae8c2

Please sign in to comment.