]> git.madduck.net Git - etc/vim.git/blob - autoload/nwo/magic.vim

madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Version 0.5
[etc/vim.git] / autoload / nwo / magic.vim
1 " File:         makemagic.vim
2 " Created:      2011 Apr 18
3 " Last Change:  2013 Mar 06
4 " Rev Days:     6
5 " Author:       Andy Wokula <anwoku@yahoo.de>
6 " License:      Vim License, see :h license
7 " Version:      0.3
8
9 "" Comments {{{
10
11 " nwo#magic#MakeMagic({pat})
12 "
13 "   remove embedded switches (\v, \m, \M and \V) from pattern {pat} by
14 "   converting {pat} into a purely magic pattern.  Return the converted
15 "   pattern.
16 "
17
18 " TODO
19 " - recognize [#-\\]], with spaces: [ #-\ \] ]
20 "   (collection ends at second ']')
21 " + \v\z( => \z(
22
23 " 2011 Nov 01   copied from asneeded\makemagic.vim
24 "               now asneeded\nwo\makemagic.vim (comments there!)
25 "}}}
26
27 " Init Folklore {{{
28 let s:cpo_save = &cpo
29 set cpo&vim
30 let g:nwo#magic#loaded = 1
31 "}}}
32
33 func! nwo#magic#MakeMagic(pat, ...) "{{{
34     " {pat}     (string)
35     " {a:1}     (boolean) initial magic mode (default follows the 'magic' option)
36
37     if a:0>=1 ? a:1 : &magic
38         let magic_mode = 'm'
39         let bracket_is_magic = 1
40     else
41         let magic_mode = 'M'
42         let bracket_is_magic = 0
43     endif
44     let result_pat = ''
45     let endpos = strlen(a:pat)
46
47     let spos = 0
48     while spos >= 0 && spos < endpos
49         let mc1 = a:pat[spos]
50         let mc2 = a:pat[spos+1]
51
52         let collection = 0
53         if mc1 == '\'
54             if mc2 == '[' && !bracket_is_magic
55                 let collection = 1
56                 let spos += 1
57             elseif mc2 =~ '[vmMV]'
58                 let magic_mode = mc2
59                 let bracket_is_magic = mc2 =~# '[vm]'
60                 let spos += 2
61             elseif mc2 == '_'
62                 let mc3 = a:pat[spos+2]
63                 if mc3 == '['
64                     let collection = 1
65                 endif
66             endif
67         elseif mc1 == '[' && bracket_is_magic
68             let collection = 1
69         endif
70
71         if collection
72             let nextpos = matchend(a:pat, s:collection_skip_pat, spos)
73             if nextpos >= 0
74                 let magpart = strpart(a:pat, spos, nextpos-spos)
75             else
76                 let magpart = strpart(a:pat, spos)
77             endif
78         else
79             let nextpos = match(a:pat, s:switchpat[magic_mode], spos)
80             if nextpos >= 0
81                 if nextpos == spos
82                     continue " optional
83                 endif
84                 let part = strpart(a:pat, spos, nextpos-spos)
85             else
86                 let part = strpart(a:pat, spos)
87             endif
88             if magic_mode ==# 'v'
89                 let magpart = substitute(part, s:vmagic_items_pat, '\=s:ToggleVmagicBslash(submatch(0))', 'g')
90             elseif magic_mode ==# 'm'
91                 let magpart = part
92             elseif magic_mode ==# 'M'
93                 let s:rem_bslash_before = '.*[~'
94                 " the first two branches are only to eat the matches:
95                 let magpart = substitute(part, '\\%\[\|\\_\\\=.\|\\.\|[.*[~]', '\=s:ToggleBslash(submatch(0))', 'g')
96             elseif magic_mode ==# 'V'
97                 let s:rem_bslash_before = '^$.*[~'
98                 let magpart = substitute(part, '\\%\[\|\\_\\\=.\|\\.\|[\^$.*[~]', '\=s:ToggleBslash(submatch(0))', 'g')
99             endif
100         endif
101
102         let result_pat .= magpart
103         let spos = nextpos
104     endwhile
105
106     return result_pat
107 endfunc "}}}
108
109 " s:variables {{{
110
111 " pattern to match very magic items:
112 let s:vmagic_items_pat = '\C\\\%(z(\|.\)\|%\%([#$(UV[\^cdlouvx]\|[<>]\=\%(''.\|\d\+[clv]\)\)\|[&()+<=>?|]\|@\%([!=>]\|<[!=]\)\|{'
113
114 " not escaped - require an even number of '\' (zero or more) to the left:
115 let s:not_escaped  = '\%(\%(^\|[^\\]\)\%(\\\\\)*\)\@<='
116
117 " prohibit an unescaped match for '%' before what follows (used when trying
118 " to find '[', but not '%[', :h /\%[ )
119 let s:not_vmagic_opt_atoms = '\%(\%(^\|[^\\]\)\%(\\\\\)*%\)\@<!'
120
121 " not opt atoms - (used when trying to find '[', but not '\%[')
122 let s:not_opt_atoms = '\%(\%(^\|[^\\]\)\%(\\\\\)*\\%\)\@<!'
123
124 " match a switch (\V,\M,\m,\v) or the start of a collection:
125 let s:switchpat = {
126     \ "v": s:not_escaped.'\%('.s:not_vmagic_opt_atoms.'\[\|\\[vmMV]\)',
127     \ "m": s:not_escaped.'\%('.s:not_opt_atoms . '\[\|\\[vmMV]\)',
128     \ "M": s:not_escaped.'\%(\\_\=\[\|\\[vmMV]\)',
129     \ "V": s:not_escaped.'\%(\\_\=\[\|\\[vmMV]\)'}
130
131 " skip over a collection (starting at '[' (same for all magic modes) or
132 " starting at '\_[' (same for all modes))
133 let s:collection_skip_pat = '^\%(\\_\)\=\[\^\=]\=\%(\%(\\[\^\]\-\\bertn]\|\[:\w\+:]\|\[=.=]\|\[\..\.]\|[^\]]\)\@>\)*]'
134
135 " }}}
136
137 " for magic modes 'V' and 'M'
138 func! s:ToggleBslash(patitem) "{{{
139     " {patitem}     magic char or '\'.char
140     if a:patitem =~ '^.$'
141         return '\'.a:patitem
142     else
143         let mchar = matchstr(a:patitem, '^\\\zs.')
144         if stridx(s:rem_bslash_before, mchar) >= 0
145             return mchar
146         else
147             return a:patitem
148         endif
149     endif
150 endfunc "}}}
151
152 func! s:ToggleVmagicBslash(patitem) "{{{
153     " {patitem}     magic char or '\'.char
154     if a:patitem =~ '^\\'
155         let mchar = a:patitem[1]
156         if mchar =~ '[\^$.*[\]~\\[:alnum:]_]'
157             return a:patitem
158         else
159             return mchar
160         endif
161     else
162         return '\'.a:patitem
163     endif
164 endfunc "}}}
165
166 " Modeline: {{{1
167 let &cpo = s:cpo_save
168 unlet s:cpo_save
169 " vim:ts=8:fdm=marker: