Vim Tips Wiki
(Move categories to tip template)
(Change <tt> to <code>, perhaps also minor tweak.)
(2 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{review}}
 
 
{{TipImported
 
{{TipImported
 
|id=528
 
|id=528
 
|previous=527
 
|previous=527
 
|next=529
 
|next=529
|created=August 10, 2003
+
|created=2003
|complexity=intermediate
+
|complexity=basic
|author=Yada
+
|author=
|version=5.7
+
|version=6.0
 
|rating=88/31
 
|rating=88/31
 
|category1=Searching
 
|category1=Searching
 
|category2=
 
|category2=
 
}}
 
}}
  +
When searching in Vim, it can be useful to have the text scroll so that the line with the next search hit is in the middle of the screen. That's easy with the built in commands: type <code>n</code> to jump to the next search hit, then <code>zz</code> to vertically center the line. In addition, the <code>'scrolloff'</code> option can be used to automatically scroll text into view, so that search hits always have some "context" lines before and after.
Some useful mappings to make search results appear in the middle of the screen.
 
   
  +
This tip describes <code>'scrolloff'</code>, and shows some mappings to vertically center search hits automatically. There is also a script with more features.
<pre>
 
nmap n nmzz.`z
 
nmap N Nmzz.`z
 
nmap * *mzz.`z
 
nmap # #mzz.`z
 
nmap g* g*mzz.`z
 
nmap g# g#mzz.`z
 
</pre>
 
   
  +
==Scrolloff option==
==Comments==
 
  +
The <code>'scrolloff'</code> (scroll offset) option determines the minimum number of screen lines that you would like above and below the cursor. By default, <code>'scrolloff'</code> is <code>0</code> which means that you can move the cursor to any line in the window without causing scrolling.
You can always make the cursor stay at the center of the screen. See {{help|'scrolloff'}}.
 
   
  +
The following command scrolls the text so that (when possible) there are always at least five lines visible above the cursor, and five lines visible below the cursor:
----
 
Why set the marks? The following works without messing up existing marks:
 
 
<pre>
 
<pre>
  +
:set scrolloff=5
nmap n nzz
 
nmap N Nzz
 
nmap * *zz
 
nmap # #zz
 
nmap g* g*zz
 
nmap g# g#zz
 
 
</pre>
 
</pre>
   
  +
This option applies to all commands, including searching. After entering the above command (which can be abbreviated as <code>:set so=5</code>), the next search hit will have at least five visible lines of text above and below (except when near the beginning or the end of the buffer).
----
 
Yes, you are right. The mark is not needed. I reserved my z mark for last search result.
 
   
  +
Entering <code>:set so=999</code> will keep the [[VimTip182|cursor vertically centered]].
----
 
Problem: If you use 'nmap n nzz' then the message "search hit BOTTOM, continuing at TOP" does not appear.
 
   
  +
==Simple mappings==
----
 
 
Following are some useful mappings to make search results appear in the middle of the screen:
I don't have that problem.
 
 
<pre>
  +
:nnoremap n nzz
  +
:nnoremap N Nzz
  +
:nnoremap * *zz
  +
:nnoremap # #zz
 
:nnoremap g* g*zz
 
:nnoremap g# g#zz
 
</pre>
  +
  +
==Script==
  +
An alternative to the simple mappings is to use a script that can cycle between different states (only <code>n</code> and <code>N</code> are mapped):
  +
*''Normal'' – No mappings: search next and search previous work as normal (default).
  +
*''Scroll hit to middle if not on same page'' – No scrolling occurs if the next hit is after the first line and before the last line of the window; otherwise, the search hit is scrolled to the middle.
  +
*''Scroll hit to middle'' – The search hit is always scrolled to the middle (when possible).
   
  +
With the following script in your [[vimrc]], press F4 to cycle the behavior of <code>n</code> and <code>N</code>:
----
 
I'm using
 
 
<pre>
 
<pre>
  +
nnoremap <silent> <F4> :call <SID>SearchMode()<CR>
nmap n nzzzv
 
  +
function s:SearchMode()
nmap N Nzzzv
 
  +
if !exists('s:searchmode') || s:searchmode == 0
nmap * *zzzv
 
  +
echo 'Search next: scroll hit to middle if not on same page'
nmap # #zzzv
 
  +
nnoremap <silent> n n:call <SID>MaybeMiddle()<CR>
nmap g* g*zzzv
 
  +
nnoremap <silent> N N:call <SID>MaybeMiddle()<CR>
nmap g# g#zzzv
 
  +
let s:searchmode = 1
  +
elseif s:searchmode == 1
  +
echo 'Search next: scroll hit to middle'
  +
nnoremap n nzz
  +
nnoremap N Nzz
  +
let s:searchmode = 2
  +
else
  +
echo 'Search next: normal'
  +
nunmap n
  +
nunmap N
  +
let s:searchmode = 0
  +
endif
  +
endfunction
  +
  +
" If cursor is in first or last line of window, scroll to middle line.
  +
function s:MaybeMiddle()
  +
if winline() == 1 || winline() == winheight(0)
  +
normal! zz
  +
endif
  +
endfunction
 
</pre>
 
</pre>
so that jumping to the next/previous search result opens the associated fold.
 
   
  +
==See also==
The above mappings preserve the "search hit BOTTOM, continuing at TOP" message under Vim 6.3.
 
  +
*[[Searching]] for basic search information
  +
*[[VimTip182|Keep cursor vertically centered]] to keep the cursor line in the middle
   
 
==Comments==
----
 

Revision as of 05:34, 13 July 2012

Tip 528 Printable Monobook Previous Next

created 2003 · complexity basic · version 6.0


When searching in Vim, it can be useful to have the text scroll so that the line with the next search hit is in the middle of the screen. That's easy with the built in commands: type n to jump to the next search hit, then zz to vertically center the line. In addition, the 'scrolloff' option can be used to automatically scroll text into view, so that search hits always have some "context" lines before and after.

This tip describes 'scrolloff', and shows some mappings to vertically center search hits automatically. There is also a script with more features.

Scrolloff option

The 'scrolloff' (scroll offset) option determines the minimum number of screen lines that you would like above and below the cursor. By default, 'scrolloff' is 0 which means that you can move the cursor to any line in the window without causing scrolling.

The following command scrolls the text so that (when possible) there are always at least five lines visible above the cursor, and five lines visible below the cursor:

:set scrolloff=5

This option applies to all commands, including searching. After entering the above command (which can be abbreviated as :set so=5), the next search hit will have at least five visible lines of text above and below (except when near the beginning or the end of the buffer).

Entering :set so=999 will keep the cursor vertically centered.

Simple mappings

Following are some useful mappings to make search results appear in the middle of the screen:

:nnoremap n nzz
:nnoremap N Nzz
:nnoremap * *zz
:nnoremap # #zz
:nnoremap g* g*zz
:nnoremap g# g#zz

Script

An alternative to the simple mappings is to use a script that can cycle between different states (only n and N are mapped):

  • Normal – No mappings: search next and search previous work as normal (default).
  • Scroll hit to middle if not on same page – No scrolling occurs if the next hit is after the first line and before the last line of the window; otherwise, the search hit is scrolled to the middle.
  • Scroll hit to middle – The search hit is always scrolled to the middle (when possible).

With the following script in your vimrc, press F4 to cycle the behavior of n and N:

nnoremap <silent> <F4> :call <SID>SearchMode()<CR>
function s:SearchMode()
  if !exists('s:searchmode') || s:searchmode == 0
    echo 'Search next: scroll hit to middle if not on same page'
    nnoremap <silent> n n:call <SID>MaybeMiddle()<CR>
    nnoremap <silent> N N:call <SID>MaybeMiddle()<CR>
    let s:searchmode = 1
  elseif s:searchmode == 1
    echo 'Search next: scroll hit to middle'
    nnoremap n nzz
    nnoremap N Nzz
    let s:searchmode = 2
  else
    echo 'Search next: normal'
    nunmap n
    nunmap N
    let s:searchmode = 0
  endif
endfunction

" If cursor is in first or last line of window, scroll to middle line.
function s:MaybeMiddle()
  if winline() == 1 || winline() == winheight(0)
    normal! zz
  endif
endfunction

See also

Comments