xref: /vim-8.2.3635/runtime/plugin/logiPat.vim (revision 939a1abe)
1*939a1abeSBram Moolenaar" LogiPat: Boolean logical pattern matcher
2e2db6c97SBram Moolenaar"   Author:  Charles E. Campbell
3*939a1abeSBram Moolenaar"   Date:    Apr 04, 2016
4*939a1abeSBram Moolenaar"   Version: 4
5e2db6c97SBram Moolenaar"   Purpose: to do Boolean-logic based regular expression pattern matching
6e2db6c97SBram Moolenaar" Copyright:    Copyright (C) 1999-2011 Charles E. Campbell {{{1
7e2db6c97SBram Moolenaar"               Permission is hereby granted to use and distribute this code,
8e2db6c97SBram Moolenaar"               with or without modifications, provided that this copyright
9e2db6c97SBram Moolenaar"               notice is copied with it. Like most anything else that's free,
10e2db6c97SBram Moolenaar"               LogiPat.vim is provided *as is* and comes with no warranty
11e2db6c97SBram Moolenaar"               of any kind, either expressed or implied. By using this
12e2db6c97SBram Moolenaar"               plugin, you agree that in no event will the copyright
13e2db6c97SBram Moolenaar"               holder be liable for any damages resulting from the use
14e2db6c97SBram Moolenaar"               of this software.
15e2db6c97SBram Moolenaar"
16e2db6c97SBram Moolenaar"   Usage: {{{1
17e2db6c97SBram Moolenaar"       :LogiPat ...
18e2db6c97SBram Moolenaar"
19e2db6c97SBram Moolenaar"         Boolean logic supported:
20e2db6c97SBram Moolenaar"            () grouping operators
21e2db6c97SBram Moolenaar"            !  not the following pattern
22e2db6c97SBram Moolenaar"            |  logical or
23e2db6c97SBram Moolenaar"            &  logical and
24e2db6c97SBram Moolenaar"            "..pattern.."
25e2db6c97SBram Moolenaar"	Example: {{{1
26e2db6c97SBram Moolenaar"		:LogiPat !("january"|"february")
27e2db6c97SBram Moolenaar"		  would match all strings not containing the strings january
28e2db6c97SBram Moolenaar"		  or february
29e2db6c97SBram Moolenaar"	GetLatestVimScripts: 1290 1 :AutoInstall: LogiPat.vim
30e2db6c97SBram Moolenaar"
31e2db6c97SBram Moolenaar"  Behold, you will conceive in your womb, and bring forth a son, {{{1
32e2db6c97SBram Moolenaar"  and will call his name Jesus. He will be great, and will be
33e2db6c97SBram Moolenaar"  called the Son of the Most High. The Lord God will give him the
34e2db6c97SBram Moolenaar"  throne of his father, David, and he will reign over the house of
35e2db6c97SBram Moolenaar"  Jacob forever. There will be no end to his kingdom. (Luke 1:31-33 WEB)
36e2db6c97SBram Moolenaar
37e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
38e2db6c97SBram Moolenaar" Load Once: {{{1
39*939a1abeSBram Moolenaarif &cp || exists("loaded_logiPat")
40e2db6c97SBram Moolenaar finish
41e2db6c97SBram Moolenaarendif
42*939a1abeSBram Moolenaarlet g:loaded_logiPat = "v4"
43e2db6c97SBram Moolenaarlet s:keepcpo        = &cpo
44e2db6c97SBram Moolenaarset cpo&vim
45e2db6c97SBram Moolenaar"DechoRemOn
46e2db6c97SBram Moolenaar
47e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
48e2db6c97SBram Moolenaar" Public Interface: {{{1
49e2db6c97SBram Moolenaarcom!     -nargs=* LogiPat		call   LogiPat(<q-args>,1)
50*939a1abeSBram Moolenaarsil! com -nargs=* LP			call   LogiPat(<q-args>,1)
51*939a1abeSBram Moolenaarsil! com -nargs=* LPR			call   LogiPat(<q-args>,1,"r")
52*939a1abeSBram Moolenaarcom!     -nargs=+ LPE			echomsg LogiPat(<q-args>)
53e2db6c97SBram Moolenaarcom!     -nargs=+ LogiPatFlags	let  s:LogiPatFlags="<args>"
54*939a1abeSBram Moolenaarsil! com -nargs=+ LPF			let  s:LogiPatFlags="<args>"
55e2db6c97SBram Moolenaar
56e2db6c97SBram Moolenaar" =====================================================================
57e2db6c97SBram Moolenaar" Functions: {{{1
58e2db6c97SBram Moolenaar
59e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
60e2db6c97SBram Moolenaar" LogiPat: this function interprets the boolean-logic pattern {{{2
61e2db6c97SBram Moolenaarfun! LogiPat(pat,...)
62e2db6c97SBram Moolenaar"  call Dfunc("LogiPat(pat<".a:pat.">)")
63e2db6c97SBram Moolenaar
64e2db6c97SBram Moolenaar  " LogiPat(pat,dosearch)
65e2db6c97SBram Moolenaar  if a:0 > 0
66e2db6c97SBram Moolenaar   let dosearch= a:1
67e2db6c97SBram Moolenaar  else
68e2db6c97SBram Moolenaar   let dosearch= 0
69e2db6c97SBram Moolenaar  endif
70*939a1abeSBram Moolenaar  if a:0 >= 3
71*939a1abeSBram Moolenaar   let s:LogiPatFlags= a:3
72*939a1abeSBram Moolenaar  endif
73e2db6c97SBram Moolenaar
74e2db6c97SBram Moolenaar  let s:npatstack = 0
75e2db6c97SBram Moolenaar  let s:nopstack  = 0
76e2db6c97SBram Moolenaar  let s:preclvl   = 0
77e2db6c97SBram Moolenaar  let expr        = a:pat
78e2db6c97SBram Moolenaar
79e2db6c97SBram Moolenaar  " Lexer/Parser
80e2db6c97SBram Moolenaar  while expr != ""
81e2db6c97SBram Moolenaar"   call Decho("expr<".expr.">")
82e2db6c97SBram Moolenaar
83e2db6c97SBram Moolenaar   if expr =~ '^"'
84e2db6c97SBram Moolenaar	" push a Pattern; accept "" as a single " in the pattern
85e2db6c97SBram Moolenaar    let expr = substitute(expr,'^\s*"','','')
86e2db6c97SBram Moolenaar    let pat  = substitute(expr,'^\(\%([^"]\|\"\"\)\{-}\)"\([^"].*$\|$\)','\1','')
87e2db6c97SBram Moolenaar	let pat  = substitute(pat,'""','"','g')
88e2db6c97SBram Moolenaar    let expr = substitute(expr,'^\(\%([^"]\|\"\"\)\{-}\)"\([^"].*$\|$\)','\2','')
89e2db6c97SBram Moolenaar    let expr = substitute(expr,'^\s*','','')
90e2db6c97SBram Moolenaar"    call Decho("pat<".pat."> expr<".expr.">")
91e2db6c97SBram Moolenaar
92e2db6c97SBram Moolenaar    call s:LP_PatPush('.*'.pat.'.*')
93e2db6c97SBram Moolenaar
94e2db6c97SBram Moolenaar   elseif expr =~ '^[!()|&]'
95e2db6c97SBram Moolenaar    " push an operator
96e2db6c97SBram Moolenaar    let op   = strpart(expr,0,1)
97e2db6c97SBram Moolenaar    let expr = strpart(expr,strlen(op))
98e2db6c97SBram Moolenaar	" allow for those who can't resist doubling their and/or operators
99e2db6c97SBram Moolenaar	if op =~ '[|&]' && expr[0] == op
100e2db6c97SBram Moolenaar     let expr = strpart(expr,strlen(op))
101e2db6c97SBram Moolenaar	endif
102e2db6c97SBram Moolenaar    call s:LP_OpPush(op)
103e2db6c97SBram Moolenaar
104e2db6c97SBram Moolenaar   elseif expr =~ '^\s'
105e2db6c97SBram Moolenaar    " skip whitespace
106e2db6c97SBram Moolenaar    let expr= strpart(expr,1)
107e2db6c97SBram Moolenaar
108e2db6c97SBram Moolenaar   else
109e2db6c97SBram Moolenaar    echoerr "operator<".strpart(expr,0,1)."> not supported (yet)"
110e2db6c97SBram Moolenaar    let expr= strpart(expr,1)
111e2db6c97SBram Moolenaar   endif
112e2db6c97SBram Moolenaar
113e2db6c97SBram Moolenaar  endwhile
114e2db6c97SBram Moolenaar
115e2db6c97SBram Moolenaar  " Final Execution
116e2db6c97SBram Moolenaar  call s:LP_OpPush('Z')
117e2db6c97SBram Moolenaar
118e2db6c97SBram Moolenaar  let result= s:LP_PatPop(1)
119e2db6c97SBram Moolenaar"  call Decho("result=".result)
120e2db6c97SBram Moolenaar
121e2db6c97SBram Moolenaar  " sanity checks and cleanup
122e2db6c97SBram Moolenaar  if s:npatstack > 0
123e2db6c97SBram Moolenaar   echoerr s:npatstack." patterns left on stack!"
124e2db6c97SBram Moolenaar   let s:npatstack= 0
125e2db6c97SBram Moolenaar  endif
126e2db6c97SBram Moolenaar  if s:nopstack > 0
127e2db6c97SBram Moolenaar   echoerr s:nopstack." operators left on stack!"
128e2db6c97SBram Moolenaar   let s:nopstack= 0
129e2db6c97SBram Moolenaar  endif
130e2db6c97SBram Moolenaar
131e2db6c97SBram Moolenaar  " perform the indicated search
132e2db6c97SBram Moolenaar  if dosearch
133*939a1abeSBram Moolenaar   if exists("s:LogiPatFlags") && s:LogiPatFlags != ""
134e2db6c97SBram Moolenaar"  call Decho("search(result<".result."> LogiPatFlags<".s:LogiPatFlags.">)")
135e2db6c97SBram Moolenaar    call search(result,s:LogiPatFlags)
136e2db6c97SBram Moolenaar   else
137e2db6c97SBram Moolenaar"  call Decho("search(result<".result.">)")
138e2db6c97SBram Moolenaar    call search(result)
139e2db6c97SBram Moolenaar   endif
140e2db6c97SBram Moolenaar   let @/= result
141e2db6c97SBram Moolenaar  endif
142e2db6c97SBram Moolenaar
143e2db6c97SBram Moolenaar"  call Dret("LogiPat ".result)
144e2db6c97SBram Moolenaar  return result
145e2db6c97SBram Moolenaarendfun
146e2db6c97SBram Moolenaar
147e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
148e2db6c97SBram Moolenaar" s:String: Vim6.4 doesn't have string() {{{2
149e2db6c97SBram Moolenaarfunc! s:String(str)
150e2db6c97SBram Moolenaar  return "'".escape(a:str, '"')."'"
151e2db6c97SBram Moolenaarendfunc
152e2db6c97SBram Moolenaar
153e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
154e2db6c97SBram Moolenaar" LP_PatPush: {{{2
155e2db6c97SBram Moolenaarfun! s:LP_PatPush(pat)
156e2db6c97SBram Moolenaar"  call Dfunc("LP_PatPush(pat<".a:pat.">)")
157e2db6c97SBram Moolenaar  let s:npatstack              = s:npatstack + 1
158e2db6c97SBram Moolenaar  let s:patstack_{s:npatstack} = a:pat
159e2db6c97SBram Moolenaar"  call s:StackLook("patpush") "Decho
160e2db6c97SBram Moolenaar"  call Dret("LP_PatPush : npatstack=".s:npatstack)
161e2db6c97SBram Moolenaarendfun
162e2db6c97SBram Moolenaar
163e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
164e2db6c97SBram Moolenaar" LP_PatPop: pop a number/variable from LogiPat's pattern stack {{{2
165e2db6c97SBram Moolenaarfun! s:LP_PatPop(lookup)
166e2db6c97SBram Moolenaar"  call Dfunc("LP_PatPop(lookup=".a:lookup.")")
167e2db6c97SBram Moolenaar  if s:npatstack > 0
168e2db6c97SBram Moolenaar   let ret         = s:patstack_{s:npatstack}
169e2db6c97SBram Moolenaar   let s:npatstack = s:npatstack - 1
170e2db6c97SBram Moolenaar  else
171e2db6c97SBram Moolenaar   let ret= "---error---"
172e2db6c97SBram Moolenaar   echoerr "(LogiPat) invalid expression"
173e2db6c97SBram Moolenaar  endif
174e2db6c97SBram Moolenaar"  call s:StackLook("patpop") "Decho
175e2db6c97SBram Moolenaar"  call Dret("LP_PatPop ".ret)
176e2db6c97SBram Moolenaar  return ret
177e2db6c97SBram Moolenaarendfun
178e2db6c97SBram Moolenaar
179e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
180e2db6c97SBram Moolenaar" LP_OpPush: {{{2
181e2db6c97SBram Moolenaarfun! s:LP_OpPush(op)
182e2db6c97SBram Moolenaar"  call Dfunc("LP_OpPush(op<".a:op.">)")
183e2db6c97SBram Moolenaar
184e2db6c97SBram Moolenaar  " determine new operator's precedence level
185e2db6c97SBram Moolenaar  if a:op == '('
186e2db6c97SBram Moolenaar  	let s:preclvl= s:preclvl + 10
187e2db6c97SBram Moolenaar	let preclvl  = s:preclvl
188e2db6c97SBram Moolenaar  elseif a:op == ')'
189e2db6c97SBram Moolenaar  	let s:preclvl= s:preclvl - 10
190e2db6c97SBram Moolenaar   if s:preclvl < 0
191e2db6c97SBram Moolenaar    let s:preclvl= 0
192e2db6c97SBram Moolenaar    echoerr "too many )s"
193e2db6c97SBram Moolenaar   endif
194e2db6c97SBram Moolenaar   let preclvl= s:preclvl
195e2db6c97SBram Moolenaar  elseif a:op =~ '|'
196e2db6c97SBram Moolenaar   let preclvl= s:preclvl + 2
197e2db6c97SBram Moolenaar  elseif a:op =~ '&'
198e2db6c97SBram Moolenaar   let preclvl= s:preclvl + 4
199e2db6c97SBram Moolenaar  elseif a:op == '!'
200e2db6c97SBram Moolenaar   let preclvl= s:preclvl + 6
201e2db6c97SBram Moolenaar  elseif a:op == 'Z'
202e2db6c97SBram Moolenaar   let preclvl= -1
203e2db6c97SBram Moolenaar  else
204e2db6c97SBram Moolenaar   echoerr "expr<".expr."> not supported (yet)"
205e2db6c97SBram Moolenaar   let preclvl= s:preclvl
206e2db6c97SBram Moolenaar  endif
207e2db6c97SBram Moolenaar"  call Decho("new operator<".a:op."> preclvl=".preclvl)
208e2db6c97SBram Moolenaar
209e2db6c97SBram Moolenaar  " execute higher-precdence operators
210e2db6c97SBram Moolenaar"  call Decho("execute higher-precedence operators")
211e2db6c97SBram Moolenaar  call s:LP_Execute(preclvl)
212e2db6c97SBram Moolenaar
213e2db6c97SBram Moolenaar  " push new operator onto operator-stack
214e2db6c97SBram Moolenaar"  call Decho("push new operator<".a:op."> onto stack with preclvl=".preclvl." at nopstack=".(s:nopstack+1))
215e2db6c97SBram Moolenaar  if a:op =~ '!'
216e2db6c97SBram Moolenaar   let s:nopstack             = s:nopstack + 1
217e2db6c97SBram Moolenaar   let s:opprec_{s:nopstack}  = preclvl
218e2db6c97SBram Moolenaar   let s:opstack_{s:nopstack} = a:op
219e2db6c97SBram Moolenaar  elseif a:op =~ '|'
220e2db6c97SBram Moolenaar   let s:nopstack             = s:nopstack + 1
221e2db6c97SBram Moolenaar   let s:opprec_{s:nopstack}  = preclvl
222e2db6c97SBram Moolenaar   let s:opstack_{s:nopstack} = a:op
223e2db6c97SBram Moolenaar  elseif a:op == '&'
224e2db6c97SBram Moolenaar   let s:nopstack             = s:nopstack + 1
225e2db6c97SBram Moolenaar   let s:opprec_{s:nopstack}  = preclvl
226e2db6c97SBram Moolenaar   let s:opstack_{s:nopstack} = a:op
227e2db6c97SBram Moolenaar  endif
228e2db6c97SBram Moolenaar
229e2db6c97SBram Moolenaar"  call s:StackLook("oppush") "Decho
230e2db6c97SBram Moolenaar"  call Dret("LP_OpPush : s:preclvl=".s:preclvl)
231e2db6c97SBram Moolenaarendfun
232e2db6c97SBram Moolenaar
233e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
234e2db6c97SBram Moolenaar" LP_Execute: execute operators from opstack using pattern stack {{{2
235e2db6c97SBram Moolenaarfun! s:LP_Execute(preclvl)
236e2db6c97SBram Moolenaar"  call Dfunc("LP_Execute(preclvl=".a:preclvl.") npatstack=".s:npatstack." nopstack=".s:nopstack)
237e2db6c97SBram Moolenaar
238e2db6c97SBram Moolenaar  " execute all higher precedence operators
239e2db6c97SBram Moolenaar  while s:nopstack > 0 && a:preclvl < s:opprec_{s:nopstack}
240e2db6c97SBram Moolenaar   let op= s:opstack_{s:nopstack}
241e2db6c97SBram Moolenaar"   call Decho("op<".op."> nop=".s:nopstack." [preclvl=".a:preclvl."] < [opprec_".s:nopstack."=".s:opprec_{s:nopstack}."]")
242e2db6c97SBram Moolenaar
243e2db6c97SBram Moolenaar   let s:nopstack = s:nopstack - 1
244e2db6c97SBram Moolenaar
245e2db6c97SBram Moolenaar   if     op == '!'
246e2db6c97SBram Moolenaar    let n1= s:LP_PatPop(1)
247e2db6c97SBram Moolenaar	call s:LP_PatPush(s:LP_Not(n1))
248e2db6c97SBram Moolenaar
249e2db6c97SBram Moolenaar   elseif op == '|'
250e2db6c97SBram Moolenaar    let n1= s:LP_PatPop(1)
251e2db6c97SBram Moolenaar    let n2= s:LP_PatPop(1)
252e2db6c97SBram Moolenaar    call s:LP_PatPush(s:LP_Or(n2,n1))
253e2db6c97SBram Moolenaar
254e2db6c97SBram Moolenaar   elseif op =~ '&'
255e2db6c97SBram Moolenaar    let n1= s:LP_PatPop(1)
256e2db6c97SBram Moolenaar    let n2= s:LP_PatPop(1)
257e2db6c97SBram Moolenaar    call s:LP_PatPush(s:LP_And(n2,n1))
258e2db6c97SBram Moolenaar   endif
259e2db6c97SBram Moolenaar
260e2db6c97SBram Moolenaar"   call s:StackLook("execute") "Decho
261e2db6c97SBram Moolenaar  endwhile
262e2db6c97SBram Moolenaar
263e2db6c97SBram Moolenaar"  call Dret("LP_Execute")
264e2db6c97SBram Moolenaarendfun
265e2db6c97SBram Moolenaar
266e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
267e2db6c97SBram Moolenaar" LP_Not: writes a logical-not for a pattern {{{2
268e2db6c97SBram Moolenaarfun! s:LP_Not(pat)
269e2db6c97SBram Moolenaar"  call Dfunc("LP_Not(pat<".a:pat.">)")
270e2db6c97SBram Moolenaar  if a:pat =~ '^\.\*' && a:pat =~ '\.\*$'
271e2db6c97SBram Moolenaar   let pat= substitute(a:pat,'^\.\*\(.*\)\.\*$','\1','')
272e2db6c97SBram Moolenaar   let ret= '^\%(\%('.pat.'\)\@!.\)*$'
273e2db6c97SBram Moolenaar  else
274e2db6c97SBram Moolenaar   let ret= '^\%(\%('.a:pat.'\)\@!.\)*$'
275e2db6c97SBram Moolenaar  endif
276e2db6c97SBram Moolenaar"  call Dret("LP_Not ".ret)
277e2db6c97SBram Moolenaar  return ret
278e2db6c97SBram Moolenaarendfun
279e2db6c97SBram Moolenaar
280e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
281e2db6c97SBram Moolenaar" LP_Or: writes a logical-or branch using two patterns {{{2
282e2db6c97SBram Moolenaarfun! s:LP_Or(pat1,pat2)
283e2db6c97SBram Moolenaar"  call Dfunc("LP_Or(pat1<".a:pat1."> pat2<".a:pat2.">)")
284e2db6c97SBram Moolenaar  let ret= '\%('.a:pat1.'\|'.a:pat2.'\)'
285e2db6c97SBram Moolenaar"  call Dret("LP_Or ".ret)
286e2db6c97SBram Moolenaar  return ret
287e2db6c97SBram Moolenaarendfun
288e2db6c97SBram Moolenaar
289e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
290e2db6c97SBram Moolenaar" LP_And: writes a logical-and concat using two patterns {{{2
291e2db6c97SBram Moolenaarfun! s:LP_And(pat1,pat2)
292e2db6c97SBram Moolenaar"  call Dfunc("LP_And(pat1<".a:pat1."> pat2<".a:pat2.">)")
293e2db6c97SBram Moolenaar  let ret= '\%('.a:pat1.'\&'.a:pat2.'\)'
294e2db6c97SBram Moolenaar"  call Dret("LP_And ".ret)
295e2db6c97SBram Moolenaar  return ret
296e2db6c97SBram Moolenaarendfun
297e2db6c97SBram Moolenaar
298e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
299e2db6c97SBram Moolenaar" StackLook: {{{2
300e2db6c97SBram Moolenaarfun! s:StackLook(description)
301e2db6c97SBram Moolenaar"  call Dfunc("StackLook(description<".a:description.">)")
302e2db6c97SBram Moolenaar  let iop = 1
303e2db6c97SBram Moolenaar  let ifp = 1
304e2db6c97SBram Moolenaar"  call Decho("Pattern                       Operator")
305e2db6c97SBram Moolenaar
306e2db6c97SBram Moolenaar  " print both pattern and operator
307e2db6c97SBram Moolenaar  while ifp <= s:npatstack && iop <= s:nopstack
308e2db6c97SBram Moolenaar   let fp = s:patstack_{ifp}
309e2db6c97SBram Moolenaar   let op = s:opstack_{iop}." (P".s:opprec_{s:nopstack}.')'
310e2db6c97SBram Moolenaar   let fplen= strlen(fp)
311e2db6c97SBram Moolenaar   if fplen < 30
312e2db6c97SBram Moolenaar   	let fp= fp.strpart("                              ",1,30-fplen)
313e2db6c97SBram Moolenaar   endif
314e2db6c97SBram Moolenaar"   call Decho(fp.op)
315e2db6c97SBram Moolenaar   let ifp = ifp + 1
316e2db6c97SBram Moolenaar   let iop = iop + 1
317e2db6c97SBram Moolenaar  endwhile
318e2db6c97SBram Moolenaar
319e2db6c97SBram Moolenaar  " print just pattern
320e2db6c97SBram Moolenaar  while ifp <= s:npatstack
321e2db6c97SBram Moolenaar   let fp  = s:patstack_{ifp}
322e2db6c97SBram Moolenaar"   call Decho(fp)
323e2db6c97SBram Moolenaar   let ifp = ifp + 1
324e2db6c97SBram Moolenaar  endwhile
325e2db6c97SBram Moolenaar
326e2db6c97SBram Moolenaar  " print just operator
327e2db6c97SBram Moolenaar  while iop <= s:nopstack
328e2db6c97SBram Moolenaar   let op  = s:opstack_{iop}." (P".s:opprec_{s:nopstack}.')'
329e2db6c97SBram Moolenaar"   call Decho("                              ".op)
330e2db6c97SBram Moolenaar   let iop = iop + 1
331e2db6c97SBram Moolenaar  endwhile
332e2db6c97SBram Moolenaar"  call Dret("StackLook")
333e2db6c97SBram Moolenaarendfun
334e2db6c97SBram Moolenaar
335e2db6c97SBram Moolenaar" ---------------------------------------------------------------------
336e2db6c97SBram Moolenaar"  Cleanup And Modeline: {{{1
337e2db6c97SBram Moolenaarlet &cpo= s:keepcpo
338e2db6c97SBram Moolenaarunlet s:keepcpo
339e2db6c97SBram Moolenaar" vim: ts=4 fdm=marker
340