codekingpro/portable-devtools
114k
1" LogiPat: Boolean logical pattern matcher2" Maintainer: This runtime file is looking for a new maintainer.3" Original Author: Charles E. Campbell4" Date: Apr 04, 20165" Version: 46" Purpose: to do Boolean-logic based regular expression pattern matching7" Copyright: Copyright (C) 1999-2011 Charles E. Campbell {{{18" Permission is hereby granted to use and distribute this code,9" with or without modifications, provided that this copyright10" notice is copied with it. Like most anything else that's free,11" LogiPat.vim is provided *as is* and comes with no warranty12" of any kind, either expressed or implied. By using this13" plugin, you agree that in no event will the copyright14" holder be liable for any damages resulting from the use15" of this software.16"17" Usage: {{{118" :LogiPat ...19"20" Boolean logic supported:21" () grouping operators22" ! not the following pattern23" | logical or24" & logical and25" "..pattern.."26" Example: {{{127" :LogiPat !("january"|"february")28" would match all strings not containing the strings january29" or february30" GetLatestVimScripts: 1290 1 :AutoInstall: LogiPat.vim31"32" Behold, you will conceive in your womb, and bring forth a son, {{{133" and will call his name Jesus. He will be great, and will be34" called the Son of the Most High. The Lord God will give him the35" throne of his father, David, and he will reign over the house of36" Jacob forever. There will be no end to his kingdom. (Luke 1:31-33 WEB)37 38" ---------------------------------------------------------------------39" Load Once: {{{140if &cp || exists("loaded_logiPat")41 finish42endif43let g:loaded_logiPat = "v4"44let s:keepcpo = &cpo45set cpo&vim46"DechoRemOn47 48" ---------------------------------------------------------------------49" Public Interface: {{{150com! -nargs=* LogiPat call LogiPat(<q-args>,1)51sil! com -nargs=* LP call LogiPat(<q-args>,1)52sil! com -nargs=* LPR call LogiPat(<q-args>,1,"r")53com! -nargs=+ LPE echomsg LogiPat(<q-args>)54com! -nargs=+ LogiPatFlags let s:LogiPatFlags="<args>"55sil! com -nargs=+ LPF let s:LogiPatFlags="<args>"56 57" =====================================================================58" Functions: {{{159 60" ---------------------------------------------------------------------61" LogiPat: this function interprets the boolean-logic pattern {{{262fun! LogiPat(pat,...)63" call Dfunc("LogiPat(pat<".a:pat.">)")64 65 " LogiPat(pat,dosearch)66 if a:0 > 067 let dosearch= a:168 else69 let dosearch= 070 endif71 if a:0 >= 372 let s:LogiPatFlags= a:373 endif74 75 let s:npatstack = 076 let s:nopstack = 077 let s:preclvl = 078 let expr = a:pat79 80 " Lexer/Parser81 while expr != ""82" call Decho("expr<".expr.">")83 84 if expr =~ '^"'85 " push a Pattern; accept "" as a single " in the pattern86 let expr = substitute(expr,'^\s*"','','')87 let pat = substitute(expr,'^\(\%([^"]\|\"\"\)\{-}\)"\([^"].*$\|$\)','\1','')88 let pat = substitute(pat,'""','"','g')89 let expr = substitute(expr,'^\(\%([^"]\|\"\"\)\{-}\)"\([^"].*$\|$\)','\2','')90 let expr = substitute(expr,'^\s*','','')91" call Decho("pat<".pat."> expr<".expr.">")92 93 call s:LP_PatPush('.*'.pat.'.*')94 95 elseif expr =~ '^[!()|&]'96 " push an operator97 let op = strpart(expr,0,1)98 let expr = strpart(expr,strlen(op))99 " allow for those who can't resist doubling their and/or operators100 if op =~ '[|&]' && expr[0] == op101 let expr = strpart(expr,strlen(op))102 endif103 call s:LP_OpPush(op)104 105 elseif expr =~ '^\s'106 " skip whitespace107 let expr= strpart(expr,1)108 109 else110 echoerr "operator<".strpart(expr,0,1)."> not supported (yet)"111 let expr= strpart(expr,1)112 endif113 114 endwhile115 116 " Final Execution117 call s:LP_OpPush('Z')118 119 let result= s:LP_PatPop(1)120" call Decho("result=".result)121 122 " sanity checks and cleanup123 if s:npatstack > 0124 echoerr s:npatstack." patterns left on stack!"125 let s:npatstack= 0126 endif127 if s:nopstack > 0128 echoerr s:nopstack." operators left on stack!"129 let s:nopstack= 0130 endif131 132 " perform the indicated search133 if dosearch134 if exists("s:LogiPatFlags") && s:LogiPatFlags != ""135" call Decho("search(result<".result."> LogiPatFlags<".s:LogiPatFlags.">)")136 call search(result,s:LogiPatFlags)137 else138" call Decho("search(result<".result.">)")139 call search(result)140 endif141 let @/= result142 endif143 144" call Dret("LogiPat ".result)145 return result146endfun147 148" ---------------------------------------------------------------------149" s:String: Vim6.4 doesn't have string() {{{2150func! s:String(str)151 return "'".escape(a:str, '"')."'"152endfunc153 154" ---------------------------------------------------------------------155" LP_PatPush: {{{2156fun! s:LP_PatPush(pat)157" call Dfunc("LP_PatPush(pat<".a:pat.">)")158 let s:npatstack = s:npatstack + 1159 let s:patstack_{s:npatstack} = a:pat160" call s:StackLook("patpush") "Decho161" call Dret("LP_PatPush : npatstack=".s:npatstack)162endfun163 164" ---------------------------------------------------------------------165" LP_PatPop: pop a number/variable from LogiPat's pattern stack {{{2166fun! s:LP_PatPop(lookup)167" call Dfunc("LP_PatPop(lookup=".a:lookup.")")168 if s:npatstack > 0169 let ret = s:patstack_{s:npatstack}170 let s:npatstack = s:npatstack - 1171 else172 let ret= "---error---"173 echoerr "(LogiPat) invalid expression"174 endif175" call s:StackLook("patpop") "Decho176" call Dret("LP_PatPop ".ret)177 return ret178endfun179 180" ---------------------------------------------------------------------181" LP_OpPush: {{{2182fun! s:LP_OpPush(op)183" call Dfunc("LP_OpPush(op<".a:op.">)")184 185 " determine new operator's precedence level186 if a:op == '('187 let s:preclvl= s:preclvl + 10188 let preclvl = s:preclvl189 elseif a:op == ')'190 let s:preclvl= s:preclvl - 10191 if s:preclvl < 0192 let s:preclvl= 0193 echoerr "too many )s"194 endif195 let preclvl= s:preclvl196 elseif a:op =~ '|'197 let preclvl= s:preclvl + 2198 elseif a:op =~ '&'199 let preclvl= s:preclvl + 4200 elseif a:op == '!'201 let preclvl= s:preclvl + 6202 elseif a:op == 'Z'203 let preclvl= -1204 else205 echoerr "expr<".expr."> not supported (yet)"206 let preclvl= s:preclvl207 endif208" call Decho("new operator<".a:op."> preclvl=".preclvl)209 210 " execute higher-precdence operators211" call Decho("execute higher-precedence operators")212 call s:LP_Execute(preclvl)213 214 " push new operator onto operator-stack215" call Decho("push new operator<".a:op."> onto stack with preclvl=".preclvl." at nopstack=".(s:nopstack+1))216 if a:op =~ '!'217 let s:nopstack = s:nopstack + 1218 let s:opprec_{s:nopstack} = preclvl219 let s:opstack_{s:nopstack} = a:op220 elseif a:op =~ '|'221 let s:nopstack = s:nopstack + 1222 let s:opprec_{s:nopstack} = preclvl223 let s:opstack_{s:nopstack} = a:op224 elseif a:op == '&'225 let s:nopstack = s:nopstack + 1226 let s:opprec_{s:nopstack} = preclvl227 let s:opstack_{s:nopstack} = a:op228 endif229 230" call s:StackLook("oppush") "Decho231" call Dret("LP_OpPush : s:preclvl=".s:preclvl)232endfun233 234" ---------------------------------------------------------------------235" LP_Execute: execute operators from opstack using pattern stack {{{2236fun! s:LP_Execute(preclvl)237" call Dfunc("LP_Execute(preclvl=".a:preclvl.") npatstack=".s:npatstack." nopstack=".s:nopstack)238 239 " execute all higher precedence operators240 while s:nopstack > 0 && a:preclvl < s:opprec_{s:nopstack}241 let op= s:opstack_{s:nopstack}242" call Decho("op<".op."> nop=".s:nopstack." [preclvl=".a:preclvl."] < [opprec_".s:nopstack."=".s:opprec_{s:nopstack}."]")243 244 let s:nopstack = s:nopstack - 1245 246 if op == '!'247 let n1= s:LP_PatPop(1)248 call s:LP_PatPush(s:LP_Not(n1))249 250 elseif op == '|'251 let n1= s:LP_PatPop(1)252 let n2= s:LP_PatPop(1)253 call s:LP_PatPush(s:LP_Or(n2,n1))254 255 elseif op =~ '&'256 let n1= s:LP_PatPop(1)257 let n2= s:LP_PatPop(1)258 call s:LP_PatPush(s:LP_And(n2,n1))259 endif260 261" call s:StackLook("execute") "Decho262 endwhile263 264" call Dret("LP_Execute")265endfun266 267" ---------------------------------------------------------------------268" LP_Not: writes a logical-not for a pattern {{{2269fun! s:LP_Not(pat)270" call Dfunc("LP_Not(pat<".a:pat.">)")271 if a:pat =~ '^\.\*' && a:pat =~ '\.\*$'272 let pat= substitute(a:pat,'^\.\*\(.*\)\.\*$','\1','')273 let ret= '^\%(\%('.pat.'\)\@!.\)*$'274 else275 let ret= '^\%(\%('.a:pat.'\)\@!.\)*$'276 endif277" call Dret("LP_Not ".ret)278 return ret279endfun280 281" ---------------------------------------------------------------------282" LP_Or: writes a logical-or branch using two patterns {{{2283fun! s:LP_Or(pat1,pat2)284" call Dfunc("LP_Or(pat1<".a:pat1."> pat2<".a:pat2.">)")285 let ret= '\%('.a:pat1.'\|'.a:pat2.'\)'286" call Dret("LP_Or ".ret)287 return ret288endfun289 290" ---------------------------------------------------------------------291" LP_And: writes a logical-and concat using two patterns {{{2292fun! s:LP_And(pat1,pat2)293" call Dfunc("LP_And(pat1<".a:pat1."> pat2<".a:pat2.">)")294 let ret= '\%('.a:pat1.'\&'.a:pat2.'\)'295" call Dret("LP_And ".ret)296 return ret297endfun298 299" ---------------------------------------------------------------------300" StackLook: {{{2301fun! s:StackLook(description)302" call Dfunc("StackLook(description<".a:description.">)")303 let iop = 1304 let ifp = 1305" call Decho("Pattern Operator")306 307 " print both pattern and operator308 while ifp <= s:npatstack && iop <= s:nopstack309 let fp = s:patstack_{ifp}310 let op = s:opstack_{iop}." (P".s:opprec_{s:nopstack}.')'311 let fplen= strlen(fp)312 if fplen < 30313 let fp= fp.strpart(" ",1,30-fplen)314 endif315" call Decho(fp.op)316 let ifp = ifp + 1317 let iop = iop + 1318 endwhile319 320 " print just pattern321 while ifp <= s:npatstack322 let fp = s:patstack_{ifp}323" call Decho(fp)324 let ifp = ifp + 1325 endwhile326 327 " print just operator328 while iop <= s:nopstack329 let op = s:opstack_{iop}." (P".s:opprec_{s:nopstack}.')'330" call Decho(" ".op)331 let iop = iop + 1332 endwhile333" call Dret("StackLook")334endfun335 336" ---------------------------------------------------------------------337" Cleanup And Modeline: {{{1338let &cpo= s:keepcpo339unlet s:keepcpo340" vim: ts=4 fdm=marker341 