" File: makemagic.vim " Created: 2011 Apr 18 " Last Change: 2013 Mar 06 " Rev Days: 6 " Author: Andy Wokula " License: Vim License, see :h license " Version: 0.3 "" Comments {{{ " nwo#magic#MakeMagic({pat}) " " remove embedded switches (\v, \m, \M and \V) from pattern {pat} by " converting {pat} into a purely magic pattern. Return the converted " pattern. " " TODO " - recognize [#-\\]], with spaces: [ #-\ \] ] " (collection ends at second ']') " + \v\z( => \z( " 2011 Nov 01 copied from asneeded\makemagic.vim " now asneeded\nwo\makemagic.vim (comments there!) "}}} " Init Folklore {{{ let s:cpo_save = &cpo set cpo&vim let g:nwo#magic#loaded = 1 "}}} func! nwo#magic#MakeMagic(pat, ...) "{{{ " {pat} (string) " {a:1} (boolean) initial magic mode (default follows the 'magic' option) if a:0>=1 ? a:1 : &magic let magic_mode = 'm' let bracket_is_magic = 1 else let magic_mode = 'M' let bracket_is_magic = 0 endif let result_pat = '' let endpos = strlen(a:pat) let spos = 0 while spos >= 0 && spos < endpos let mc1 = a:pat[spos] let mc2 = a:pat[spos+1] let collection = 0 if mc1 == '\' if mc2 == '[' && !bracket_is_magic let collection = 1 let spos += 1 elseif mc2 =~ '[vmMV]' let magic_mode = mc2 let bracket_is_magic = mc2 =~# '[vm]' let spos += 2 elseif mc2 == '_' let mc3 = a:pat[spos+2] if mc3 == '[' let collection = 1 endif endif elseif mc1 == '[' && bracket_is_magic let collection = 1 endif if collection let nextpos = matchend(a:pat, s:collection_skip_pat, spos) if nextpos >= 0 let magpart = strpart(a:pat, spos, nextpos-spos) else let magpart = strpart(a:pat, spos) endif else let nextpos = match(a:pat, s:switchpat[magic_mode], spos) if nextpos >= 0 if nextpos == spos continue " optional endif let part = strpart(a:pat, spos, nextpos-spos) else let part = strpart(a:pat, spos) endif if magic_mode ==# 'v' let magpart = substitute(part, s:vmagic_items_pat, '\=s:ToggleVmagicBslash(submatch(0))', 'g') elseif magic_mode ==# 'm' let magpart = part elseif magic_mode ==# 'M' let s:rem_bslash_before = '.*[~' " the first two branches are only to eat the matches: let magpart = substitute(part, '\\%\[\|\\_\\\=.\|\\.\|[.*[~]', '\=s:ToggleBslash(submatch(0))', 'g') elseif magic_mode ==# 'V' let s:rem_bslash_before = '^$.*[~' let magpart = substitute(part, '\\%\[\|\\_\\\=.\|\\.\|[\^$.*[~]', '\=s:ToggleBslash(submatch(0))', 'g') endif endif let result_pat .= magpart let spos = nextpos endwhile return result_pat endfunc "}}} " s:variables {{{ " pattern to match very magic items: let s:vmagic_items_pat = '\C\\\%(z(\|.\)\|%\%([#$(UV[\^cdlouvx]\|[<>]\=\%(''.\|\d\+[clv]\)\)\|[&()+<=>?|]\|@\%([!=>]\|<[!=]\)\|{' " not escaped - require an even number of '\' (zero or more) to the left: let s:not_escaped = '\%(\%(^\|[^\\]\)\%(\\\\\)*\)\@<=' " prohibit an unescaped match for '%' before what follows (used when trying " to find '[', but not '%[', :h /\%[ ) let s:not_vmagic_opt_atoms = '\%(\%(^\|[^\\]\)\%(\\\\\)*%\)\@\)*]' " }}} " for magic modes 'V' and 'M' func! s:ToggleBslash(patitem) "{{{ " {patitem} magic char or '\'.char if a:patitem =~ '^.$' return '\'.a:patitem else let mchar = matchstr(a:patitem, '^\\\zs.') if stridx(s:rem_bslash_before, mchar) >= 0 return mchar else return a:patitem endif endif endfunc "}}} func! s:ToggleVmagicBslash(patitem) "{{{ " {patitem} magic char or '\'.char if a:patitem =~ '^\\' let mchar = a:patitem[1] if mchar =~ '[\^$.*[\]~\\[:alnum:]_]' return a:patitem else return mchar endif else return '\'.a:patitem endif endfunc "}}} " Modeline: {{{1 let &cpo = s:cpo_save unlet s:cpo_save " vim:ts=8:fdm=marker: