Created
June 14, 2014 05:18
-
-
Save nefigah/8270187bcb9ddfb5e9e3 to your computer and use it in GitHub Desktop.
Magic sub wrappers!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
" | |
" Functions/Commands | |
" | |
" <SID>ShouldAbbreviateCmd() is a helper function for determining whether or | |
" not a cabbrev should be performed. It returns 1 (true) if: | |
" * The context is an ex command (as opposed to search mode), and either: | |
" * The abbreviation would occur at the beginning of the commandline, or | |
" * The abbreviation would occur following a simple :range specification. | |
function! s:ShouldAbbreviateCmd() | |
" Ensure we are in command mode, not search mode | |
if getcmdtype() != ":" | |
return 0 | |
" No range case | |
elseif getcmdpos() == 1 | |
return 1 | |
else | |
let text = getcmdline() | |
" For efficiency, check the most common ranges directly | |
if text is "'<,'>" || text is '%' || text is '.' | |
return 1 | |
endif | |
" Try to match the more straightforward line specifications. | |
" The /, ?, \/, \?, and \& specifiers are purposely omitted, as are | |
" multiple addition/subtraction clauses occuring in the same spec segment. | |
let text = strpart(text, 0, getcmdpos() - 1) | |
let lineSpec = '\v^%(\d+|\.|\$|\' . "'" . '\a)%([+-]\d*)?' | |
let sepOrEnd = '%($|[,;])' | |
let firstSpec = strlen(matchstr(text, lineSpec . sepOrEnd)) | |
" Exit if we've already determined no match or exact match | |
if firstSpec == 0 | |
return 0 | |
elseif firstSpec == strlen(text) | |
return 1 | |
endif | |
return strlen(matchstr(text, lineSpec . '$', firstSpec)) > 0 | |
endif | |
endfunction | |
" <SID>MakeCmdAbbrev() is a helper function for creating guarded command | |
" aliases (cabbrevs). You don't want those buggers to be expanded just | |
" anywhere, especially if you want to use a nice short abbreviation. | |
function! s:MakeCmdAbbrev(abbreviation, expansion) | |
execute 'cnoreabbrev ' . a:abbreviation . " <C-R>=<SID>ShouldAbbreviateCmd()" . | |
\ ' ? "' . a:expansion . '" : "' . a:abbreviation . '"<CR>' | |
endfunction | |
" <SID>SubWrap is a function wrapper around the built-in :substitute command. | |
" It will interpret the provided search pattern in the context of the given | |
" 'magic' specifier (one of \m, \M, \v, or \V). The replacement will always be | |
" interpreted with 'nomagic'. | |
function! s:SubWrap(magicmode, startline, endline, argstring) | |
let delim = strpart(a:argstring, 0, 1) | |
let withmode = delim . a:magicmode . strpart(a:argstring, 1) | |
" Silly Vim doesn't allow a 'magic' specifier for the replacement | |
set nomagic | |
execute a:startline . ',' . a:endline . 'substitute' . withmode | |
set magic | |
endfunction | |
" Custom commands: | |
" VeryMagicSub (alias: :ss) (mnemonic: twice as good as :s) | |
" LiteralSub (alias :ssl) (for when you really need to search for [ and *) | |
" If you want the commands to default to the cursor line (like :s), instead of | |
" the whole file (like :g), replace -range=% with just -range in the commands | |
" below. In either case, you can always provide your own range on use. | |
command! -nargs=1 -range=% VeryMagicSub call s:SubWrap('\v', <line1>, <line2>, <q-args>) | |
call s:MakeCmdAbbrev('ss', 'VeryMagicSub') | |
command! -nargs=1 -range=% LiteralSub call s:SubWrap('\V', <line1>, <line2>, <q-args>) | |
call s:MakeCmdAbbrev('ssl', 'LiteralSub') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment