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