" Copyright 2015-present Greg Hurrell. All rights reserved.
" Licensed under the terms of the BSD 2-clause license.
""
"
" @plugin loupe Loupe plug-in for Vim
"
" # Intro
"
" > "loupe (noun)
" > a small magnifying glass used by jewelers and watchmakers."
"
" *loupe-features*
" Loupe enhances Vim's |search-commands| in four ways:
"
" ## 1. Makes the currently selected match easier to see
"
" When searching using |/|, |?|, |star|, |#|, |n|, |N| or similar, it can be
" hard to see the "current" match from among all the matches that 'hlsearch'
" highlights. Loupe makes the currently selected match easier to see by:
"
" - Applying a different |:highlight| group (by default, |hl-IncSearch|) to the
" match under the cursor.
" - Keeping the matching line centered within the window when jumping between
" matches with |n| and |N|.
"
" ## 2. Applies sane pattern syntax by default
"
" Loupe makes "very magic" (|/\v|) syntax apply by default when searching. This
" is true even if you initiate a search via a novel means, such as from a visual
" selection or with a complicated |:range| prefix.
"
" This means that you can use a pattern syntax closer to the familiar regular
" expression syntax from languages such as Perl, Ruby, JavaScript (indeed, most
" other modern languages that support regular expressions).
"
" ## 3. Provides a shortcut to remove search highlighting
"
" Loupe maps n to quickly remove all 'hlsearch' highlighting (although
" you can provide an alternative mapping of your choosing or suppress the
" feature entirely).
"
" ## 4. Sensible defaults for search-related features
"
" Loupe provides reasonable defaults for most search-related Vim settings to
" provide a good "out of the box" experience. For more details, or to see how to
" override Loupe's settings, see |loupe-overrides|.
"
"
" # Installation
"
" To install Loupe, use your plug-in management system of choice.
"
" If you don't have a "plug-in management system of choice", I recommend
" Pathogen (https://github.com/tpope/vim-pathogen) due to its simplicity and
" robustness. Assuming that you have Pathogen installed and configured, and that
" you want to install Loupe into `~/.vim/bundle`, you can do so with:
"
" ```
" git clone https://github.com/wincent/loupe.git ~/.vim/bundle/loupe
" ```
"
" Alternatively, if you use a Git submodule for each Vim plug-in, you could do
" the following after `cd`-ing into the top-level of your Git superproject:
"
" ```
" git submodule add https://github.com/wincent/loupe.git ~/vim/bundle/loupe
" git submodule init
" ```
"
" To generate help tags under Pathogen, you can do so from inside Vim with:
"
" ```
" :call pathogen#helptags()
" ```
"
" @footer
"
" # Overrides
"
" Loupe sets a number of search-related Vim settings to reasonable defaults in
" order to provide a good "out of the box" experience:
"
" @indent
" *loupe-history-override*
" 'history'
"
" Increased to 1000, to increase the number of previous searches remembered.
" Note that Loupe only applies this setting if the current value of 'history'
" is less than 1000.
"
" *loupe-hlsearch-override*
" 'hlsearch'
"
" Turned on (when there is a previous search pattern, highlight all its
" matches).
"
" *loupe-incsearch-override*
" 'incsearch'
"
" Turned on (while typing a search command, show where the pattern matches, as
" it was typed so far).
"
" *loupe-ignorecase-override*
" 'ignorecase'
"
" Turned on (to ignore case in search patterns).
"
" *loupe-shortmess-override*
" 'shortmess'
"
" Adds "s", which suppresses the display of "search hit BOTTOM, continuing at
" TOP" and "search hit TOP, continuing at BOTTOM" messages.
"
" *loupe-smartcase-override*
" 'smartcase'
"
" Turned on (overrides 'ignorecase', making the search pattern case-sensitive
" whenever it containers uppercase characters).
"
" @dedent
"
" To override any of these choices, you can place overrides in an
" |after-directory| (ie. `~/.vim/after/plugin/loupe.vim`). For example:
"
" ```
" " Override Loupe's 'history' setting from 1000 to 10000.
" set history=10000
"
" " Reset Loupe's 'incsearch' back to Vim default.
" set incsearch&vim
"
" " Remove unwanted 's' from 'shortmess'.
" set shortmess-=s
" ```
"
" # Related
"
" Just as Loupe aims to improve the within-file search experience, Ferret does
" the same for multi-file searching and replacing:
"
" - https://github.com/wincent/ferret
"
" # Website
"
" The official Loupe source code repo is at:
"
" - http://git.wincent.com/loupe.git
"
" A mirror exists at:
"
" - https://github.com/wincent/loupe
"
" Official releases are listed at:
"
" - http://www.vim.org/scripts/script.php?script_id=5215
"
"
" # License
"
" Copyright 2015-present Greg Hurrell. All rights reserved.
"
" Redistribution and use in source and binary forms, with or without
" modification, are permitted provided that the following conditions are met:
"
" 1. Redistributions of source code must retain the above copyright notice,
" this list of conditions and the following disclaimer.
"
" 2. Redistributions in binary form must reproduce the above copyright notice,
" this list of conditions and the following disclaimer in the documentation
" and/or other materials provided with the distribution.
"
" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
" ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
" POSSIBILITY OF SUCH DAMAGE.
"
"
" # Development
"
" ## Contributing patches
"
" Patches can be sent via mail to greg@hurrell.net, or as GitHub pull requests
" at: https://github.com/wincent/loupe/pulls
"
" ## Cutting a new release
"
" At the moment the release process is manual:
"
" - Perform final sanity checks and manual testing
" - Update the |loupe-history| section of the documentation
" - Verify clean work tree:
"
" ```
" git status
" ```
"
" - Tag the release:
"
" ```
" git tag -s -m "$VERSION release" $VERSION
" ```
"
" - Publish the code:
"
" ```
" git push origin master --follow-tags
" git push github master --follow-tags
" ```
"
" - Produce the release archive:
"
" ```
" git archive -o loupe-$VERSION.zip HEAD -- .
" ```
"
" - Upload to http://www.vim.org/scripts/script.php?script_id=5215
"
" # Authors
"
" Loupe is written and maintained by Greg Hurrell .
"
" The original idea for the |g:LoupeHighlightGroup| feature was taken from
" Damian Conway's Vim set-up:
"
" - https://github.com/thoughtstream/Damian-Conway-s-Vim-Setup/blob/master/plugin/hlnext.vim
"
" Which he discussed in his "More Instantly Better Vim" presentation at OSCON
" 2013:
"
" - https://www.youtube.com/watch?v=aHm36-na4-4
"
" # History
"
" ## 1.0 (28 December 2015)
"
" - Renamed the |LoupeClearHighlight| mapping to
" |(LoupeClearHighlight)|.
"
" ## 0.1 (5 July 2015)
"
" - Initial release, extracted from my dotfiles
" (https://github.com/wincent/wincent).
""
" @option g:LoupeLoaded any
"
" To prevent Loupe from being loaded, set |g:LoupeLoaded| to any value in your
" |.vimrc|. For example:
"
" ```
" let g:LoupeLoaded=1
" ```
if exists('g:LoupeLoaded') || &compatible || v:version < 700
finish
endif
let g:LoupeLoaded=1
" Temporarily set 'cpoptions' to Vim default as per `:h use-cpo-save`.
let s:cpoptions=&cpoptions
set cpoptions&vim
" Reasonable defaults for search-related settings.
if &history < 1000
set history=1000 " Longer search and command history (default is 50).
endif
if has('extra_search')
set hlsearch " Highlight search strings.
set incsearch " Incremental search ("find as you type").
endif
set ignorecase " Ignore case when searching.
set shortmess+=s " Don't echo search wrap messages.
set smartcase " Case-sensitive search if search string includes a capital letter.
""
" @option g:LoupeClearHighlightMap boolean 1
"
" Controls whether to set up the |(LoupeClearHighlight)| mapping. To
" prevent any mapping from being configured, set to 0:
"
" ```
" let g:LoupeClearHighlightMap=0
" ```
let s:map=get(g:, 'LoupeClearHighlightMap', 1)
if s:map
if !hasmapto('(LoupeClearHighlight)') && maparg('n', 'n') ==# ''
nmap n (LoupeClearHighlight)
endif
endif
""
" @mapping (LoupeClearHighlight)
"
" Loupe maps n to |(LoupeClearHighlight)|, which clears all
" visible highlights (like |:nohighlight| does). To use an alternative mapping
" instead, create a different one in your |.vimrc| instead using |:nmap|:
"
" ```
" " Instead of n, use x.
" nmap x (LoupeClearHighlight)
" ```
"
" Note that Loupe will not try to set up its n mapping if any of the
" following are true:
"
" - A mapping for n already exists.
" - An alternative mapping for |(LoupeClearHighlight)| has already been set
" up from a |.vimrc|.
" - The mapping has been suppressed by setting |g:LoupeClearHighlightMap| to 1
" in your |.vimrc|.
nnoremap (LoupeClearHighlight)
\ :nohlsearch
\ :call loupe#private#clear_highlight()
" Make `:nohlsearch` behave like (LoupeClearHighlight).
cabbrev noh (getcmdtype() == ':' && getcmdpos() == 4 ? 'noh call loupe#private#clear_highlight()' : 'noh')
cabbrev nohl (getcmdtype() == ':' && getcmdpos() == 5 ? 'nohl call loupe#private#clear_highlight()' : 'nohl')
cabbrev nohls (getcmdtype() == ':' && getcmdpos() == 6 ? 'nohls call loupe#private#clear_highlight()' : 'nohls')
cabbrev nohlse (getcmdtype() == ':' && getcmdpos() == 7 ? 'nohlse call loupe#private#clear_highlight()' : 'nohlse')
cabbrev nohlsea (getcmdtype() == ':' && getcmdpos() == 8 ? 'nohlsea call loupe#private#clear_highlight()' : 'nohlsea')
cabbrev nohlsear (getcmdtype() == ':' && getcmdpos() == 9 ? 'nohlsear call loupe#private#clear_highlight()' : 'nohlsear')
cabbrev nohlsearc (getcmdtype() == ':' && getcmdpos() == 10 ? 'nohlsearc call loupe#private#clear_highlight()' : 'nohlsearc')
cabbrev nohlsearch (getcmdtype() == ':' && getcmdpos() == 11 ? 'nohlsearch call loupe#private#clear_highlight()' : 'nohlsearch')
""
" @option g:LoupeVeryMagic boolean 1
"
" Controls whether "very magic" pattern syntax (|/\v|) is applied by default.
" To disable, set to 0:
"
" ```
" let g:LoupeVeryMagic=0
" ```
function s:MagicString()
let s:magic=get(g:, 'LoupeVeryMagic', 1)
return s:magic ? '\v' : ''
endfunction
nnoremap / loupe#private#prepare_highlight('/' . MagicString())
nnoremap ? loupe#private#prepare_highlight('?' . MagicString())
xnoremap / loupe#private#prepare_highlight('/' . MagicString())
xnoremap ? loupe#private#prepare_highlight('?' . MagicString())
if !empty(s:MagicString())
cnoremap / loupe#private#very_magic_slash()
endif
""
" @option g:LoupeCenterResults boolean 1
"
" Controls whether the match's line is vertically centered within the window
" when jumping (via |n|, |N| etc). To disable, set to 0:
"
" ```
" let g:LoupeCenterResults=0
" ```
let s:center=get(g:, 'LoupeCenterResults', 1)
let s:center_string=s:center ? 'zz' : ''
execute 'nnoremap # #' . s:center_string . ':call loupe#private#hlmatch()'
execute 'nnoremap * *' . s:center_string . ':call loupe#private#hlmatch()'
execute 'nnoremap N N' . s:center_string . ':call loupe#private#hlmatch()'
execute 'nnoremap g# g#' . s:center_string . ':call loupe#private#hlmatch()'
execute 'nnoremap g* g*' . s:center_string . ':call loupe#private#hlmatch()'
execute 'nnoremap n n' . s:center_string . ':call loupe#private#hlmatch()'
" Clean-up stray `matchadd()` vestiges.
if has('autocmd') && has('extra_search')
augroup LoupeCleanUp
autocmd!
autocmd WinEnter * :call loupe#private#cleanup()
augroup END
endif
" Restore 'cpoptions' to its former value.
let &cpoptions=s:cpoptions
unlet s:cpoptions