changeset 6855:ee45d3b0579b

Add the logiPat plugin to the distribution.
author Bram Moolenaar <bram@vim.org>
date Fri, 19 Jun 2015 18:48:41 +0200
parents bc2d0a3279e7
children 566e193323ce
files runtime/doc/Makefile runtime/doc/options.txt runtime/doc/pi_logipat.txt runtime/doc/tags runtime/doc/todo.txt runtime/keymap/russian-jcukenwintype.vim runtime/plugin/README.txt runtime/plugin/logiPat.vim
diffstat 8 files changed, 593 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/doc/Makefile
+++ b/runtime/doc/Makefile
@@ -75,6 +75,7 @@ DOCS = \
 	pattern.txt \
 	pi_getscript.txt \
 	pi_gzip.txt \
+	pi_logipat.txt \
 	pi_netrw.txt \
 	pi_paren.txt \
 	pi_spec.txt \
@@ -207,6 +208,7 @@ HTMLS = \
 	pattern.html \
 	pi_getscript.html \
 	pi_gzip.html \
+	pi_logipat.html \
 	pi_netrw.html \
 	pi_paren.html \
 	pi_spec.html \
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -1,4 +1,4 @@
-*options.txt*	For Vim version 7.4.  Last change: 2015 May 04
+*options.txt*	For Vim version 7.4.  Last change: 2015 Jun 19
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
new file mode 100644
--- /dev/null
+++ b/runtime/doc/pi_logipat.txt
@@ -0,0 +1,117 @@
+*pi_logipat.txt*	Logical Patterns				Mar 13, 2013
+
+Author:  Charles E. Campbell  <NdrOchip@ScampbellPfamily.AbizM>
+Copyright: (c) 2004-2013 by Charles E. Campbell	*logipat-copyright*
+           The VIM LICENSE applies to LogiPat.vim and LogiPat.txt
+           (see |copyright|) except use "LogiPat" instead of "Vim"
+	   No warranty, express or implied.  Use At-Your-Own-Risk.
+
+==============================================================================
+1. Contents					*logipat* *logipat-contents*
+
+	1. Contents.................: |logipat-contents|
+	2. LogiPat Manual...........: |logipat-manual|
+	3. LogiPat Examples.........: |logipat-examples|
+	4. Caveat...................: |logipat-caveat|
+	5. LogiPat History..........: |logipat-history|
+
+==============================================================================
+2. LogiPat Manual			*logipat-manual* *logipat-man*
+
+
+	*logipat-arg* *logipat-input* *logipat-pattern* *logipat-operators*
+	Boolean logic patterns are composed of
+
+			operators  ! = not
+			           | = logical-or
+			           & = logical-and
+			grouping   ( ... )
+			patterns   "pattern"
+
+	:LogiPat {boolean-logic pattern}		*:LogiPat*
+		:LogiPat is a command which takes a boolean-logic
+		argument (|logipat-arg|).
+
+	:LP {boolean-logic pattern}			*:LP*
+		:LP is a shorthand command version of :LogiPat
+		(|:LogiPat|).
+
+	:ELP {boolean-logic pattern}			*:ELP*
+		No search is done, but the conversion from the
+		boolean logic pattern to the regular expression
+		is performed and echoed onto the display.
+
+	:LogiPatFlags {search flags}			*LogiPat-flags*
+		:LogiPatFlags {search flags}
+		LogiPat uses the |search()| command.  The flags
+		passed to that call to search() may be specified
+		by the :LogiPatFlags command.
+
+	:LPF {search flags}				*:LPF*
+		:LPF is a shorthand version of :LogiPatFlags.
+
+	:let pat=LogiPat({boolean-logic pattern})	*LogiPat()*
+		If one calls LogiPat() directly, no search
+		is done, but the transformation from the boolean
+		logic pattern into a regular expression pattern
+		is performed and returned.
+
+	To get a " inside a pattern, as opposed to having it delimit
+	the pattern, double it.
+
+==============================================================================
+3. LogiPat Examples					*logipat-examples*
+
+	LogiPat takes Boolean logic arguments and produces a regular
+	expression which implements the choices.  A series of examples
+	follows:
+>
+	:LogiPat "abc"
+<		will search for lines containing the string  :abc:
+>
+	:LogiPat "ab""cd"
+<		will search for lines containing the string  :ab"c:
+>
+	:LogiPat !"abc"
+<		will search for lines which don't contain the string  :abc:
+>
+	:LogiPat "abc"|"def"
+<		will search for lines which contain either the string
+		:abc:  or the string  :def:
+>
+	:LogiPat !("abc"|"def")
+<		will search for lines which don't contain either
+		of the strings  :abc:  or  :def:
+>
+	:LogiPat "abc"&"def"
+<		will search for lines which contain both of the strings
+		:abc:  and  :def:
+>
+	:let pat= LogiPat('!"abc"')
+<		will return the regular expression which will match
+		all lines not containing  :abc: .  The double quotes
+		are needed to pass normal patterns to LogiPat, and
+		differentiate such patterns from boolean logic
+		operators.
+
+
+==============================================================================
+4. Caveat						*logipat-caveat*
+
+	The "not" operator may be fragile; ie. it may not always play well
+	with the & (logical-and) and | (logical-or) operators.  Please try out
+	your patterns, possibly with :set hls, to insure that what is matching
+	is what you want.
+
+==============================================================================
+3. LogiPat History					*logipat-history*
+
+	v3 Sep 25, 2006 * LP_Or() fixed; it now encapsulates its output
+	                  in \%(...\) parentheses
+	   Dec 12, 2011 * |:ELP| added
+			* "" is mapped to a single " and left inside patterns
+	v2 May 31, 2005	* LPF and LogiPatFlags commands weren't working
+	v1 May 23, 2005	* initial release
+
+==============================================================================
+vim:tw=78:ts=8:ft=help
--- a/runtime/doc/tags
+++ b/runtime/doc/tags
@@ -1837,6 +1837,7 @@ 90.5	usr_90.txt	/*90.5*
 :CompilerSet	usr_41.txt	/*:CompilerSet*
 :DiffOrig	diff.txt	/*:DiffOrig*
 :DoMatchParen	pi_paren.txt	/*:DoMatchParen*
+:ELP	pi_logipat.txt	/*:ELP*
 :Explore	pi_netrw.txt	/*:Explore*
 :GLVS	pi_getscript.txt	/*:GLVS*
 :GetLatestVimScripts_dat	pi_getscript.txt	/*:GetLatestVimScripts_dat*
@@ -1844,7 +1845,10 @@ 90.5	usr_90.txt	/*90.5*
 :GnatPretty	ft_ada.txt	/*:GnatPretty*
 :GnatTags	ft_ada.txt	/*:GnatTags*
 :Hexplore	pi_netrw.txt	/*:Hexplore*
+:LP	pi_logipat.txt	/*:LP*
+:LPF	pi_logipat.txt	/*:LPF*
 :Lexplore	pi_netrw.txt	/*:Lexplore*
+:LogiPat	pi_logipat.txt	/*:LogiPat*
 :Man	filetype.txt	/*:Man*
 :MkVimball	pi_vimball.txt	/*:MkVimball*
 :N	editing.txt	/*:N*
@@ -4421,6 +4425,8 @@ L	motion.txt	/*L*
 Linux-backspace	options.txt	/*Linux-backspace*
 List	eval.txt	/*List*
 Lists	eval.txt	/*Lists*
+LogiPat()	pi_logipat.txt	/*LogiPat()*
+LogiPat-flags	pi_logipat.txt	/*LogiPat-flags*
 Lua	if_lua.txt	/*Lua*
 M	motion.txt	/*M*
 MDI	starting.txt	/*MDI*
@@ -6733,6 +6739,7 @@ lcs-eol	options.txt	/*lcs-eol*
 lcs-extends	options.txt	/*lcs-extends*
 lcs-nbsp	options.txt	/*lcs-nbsp*
 lcs-precedes	options.txt	/*lcs-precedes*
+lcs-space	options.txt	/*lcs-space*
 lcs-tab	options.txt	/*lcs-tab*
 lcs-trail	options.txt	/*lcs-trail*
 left-right-motions	motion.txt	/*left-right-motions*
@@ -6780,6 +6787,18 @@ location-list	quickfix.txt	/*location-li
 location-list-window	quickfix.txt	/*location-list-window*
 log()	eval.txt	/*log()*
 log10()	eval.txt	/*log10()*
+logipat	pi_logipat.txt	/*logipat*
+logipat-arg	pi_logipat.txt	/*logipat-arg*
+logipat-caveat	pi_logipat.txt	/*logipat-caveat*
+logipat-contents	pi_logipat.txt	/*logipat-contents*
+logipat-copyright	pi_logipat.txt	/*logipat-copyright*
+logipat-examples	pi_logipat.txt	/*logipat-examples*
+logipat-history	pi_logipat.txt	/*logipat-history*
+logipat-input	pi_logipat.txt	/*logipat-input*
+logipat-man	pi_logipat.txt	/*logipat-man*
+logipat-manual	pi_logipat.txt	/*logipat-manual*
+logipat-operators	pi_logipat.txt	/*logipat-operators*
+logipat-pattern	pi_logipat.txt	/*logipat-pattern*
 long-lines	version5.txt	/*long-lines*
 love	intro.txt	/*love*
 lowercase	change.txt	/*lowercase*
@@ -7423,6 +7442,7 @@ php3.vim	syntax.txt	/*php3.vim*
 phtml.vim	syntax.txt	/*phtml.vim*
 pi_getscript.txt	pi_getscript.txt	/*pi_getscript.txt*
 pi_gzip.txt	pi_gzip.txt	/*pi_gzip.txt*
+pi_logipat.txt	pi_logipat.txt	/*pi_logipat.txt*
 pi_netrw.txt	pi_netrw.txt	/*pi_netrw.txt*
 pi_paren.txt	pi_paren.txt	/*pi_paren.txt*
 pi_spec.txt	pi_spec.txt	/*pi_spec.txt*
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -74,10 +74,6 @@ More info Jul 24.  Not clear why.
 Better .ico file for Windows. (Pat Suwalski, 2015 Feb 13)
 Waiting for response on remark from Edward Fox.
 
-Patch to make getregtype() return the right size for non-linux systems.
-(Yasuhiro Matsumoto, 2014 Jul 8)
-Breaks test_eval.  Inefficient, can we only compute y_width when needed?
-
 Problem that a previous silent ":throw" causes a following try/catch not to
 work. (ZyX, 2013 Sep 28)
 
@@ -88,27 +84,6 @@ Regression for v_b_A. (Ingo Karkat, 2015
 ":cd C:\Windows\System32\drivers\etc*" does not work, even though the
 directory exists. (Sergio Gallelli, 2013 Dec 29)
 
-Patch on issue 365.
-
-Patch to add "vsplit" to 'switchbuf'. (Brook Hong, 2015 Jun 4)
-
-patch to fix that "p" in Visual mode does not break line in expected place.
-(Yukihiro Nakadaira, 2015 May 23)
-
-Patch to fix that wide characters do not work properly after exiting.
-(Yasuhiro Matsumoto, 2015 May 24) Better patch to come.
-
-Patch to add grepfile(). (Scott Prager, 2015 May 26)
-
-keymap for Russian typewriter layout. (Danwerspb, 2015 May 15)
-
-Patch for man.vim. (SungHyun Nam, 2015 May 20)
-Doesn't work completely (Dominique Orban)
-
-The entries added by matchaddpos() are returned by getmatches() but can't be
-set with setmatches(). (lcd47, 2014 Jun 29)
-Patch by Christian, 2015 Jun 16.
-
 Invalid memory access in regexp.c. (Dominique Pelle, 2015 May 23)
 
 Using ":windo" to set options in all windows has the side effect that it
@@ -116,15 +91,6 @@ changes the window layout and the curren
 and restores.  Use in the matchparen plugin.
 Perhaps we can use ":silent window"?
 
-Patch for :[count]tag" not always working. (Hirohito Higashi, 2015 May 19)
-
-Include the LogiPat plugin in the distribution?
-
-Patch to fix that ":cnext" jumps to the wrong column. (Hirohito Higashi, 2015
-May 17, second patch)
-
-Pull request for jcukenwintype.vim. (Denis Proskurin, 2015 May 15)
-
 Patch for appending in Visual mode with 'linebreak' set.
 (Christian Brabandt, 2015 Jun 1)
 
@@ -177,6 +143,13 @@ Is this the right solution?
 Patch for langmap not working properly with mapping in Command-line mode.
 Issue 376.
 
+Patch to add grepfile(). (Scott Prager, 2015 May 26)
+Work in progress.
+
+Patch to make getregtype() return the right size for non-linux systems.
+(Yasuhiro Matsumoto, 2014 Jul 8)
+Breaks test_eval.  Inefficient, can we only compute y_width when needed?
+
 Value returned by virtcol() changes depending on how lines wrap.  This is
 inconsistent with the documentation.
 
@@ -210,6 +183,12 @@ 2014 Sep 11)
 Patch to use different terminal mode settings for system(). (Hayaki Saito)
 Does this work for everybody?
 
+Patch to fix that wide characters do not work properly after exiting.
+(Yasuhiro Matsumoto, 2015 May 24) Better patch to come.
+
+Patch for man.vim. (SungHyun Nam, 2015 May 20)
+Doesn't work completely (Dominique Orban)
+
 When a session file is created and there are "nofile" buffers, these are not
 filled.  Need to trigger BufReadCmd autocommands.  Also handle deleting the
 initial empty buffer better. (ZyX, 2015 March 8)
new file mode 100644
--- /dev/null
+++ b/runtime/keymap/russian-jcukenwintype.vim
@@ -0,0 +1,104 @@
+" Vim Keymap file for russian characters, layout 'jcuken', MS Windows variant
+" (slightly incompatible with XFree86 'ru' keymap - makes use of NUMERO SIGN)
+" Useful mainly with utf-8 but may work with other encodings
+
+" Derived from russian-jcuken.vim by Artem Chuprina <ran@ran.pp.ru>
+" Typewriter variant of standart russian layout
+" Maintainer:   Denis Proskurin <danwerspb@gmail.com>
+" Last Changed: 2015 May 15
+
+" All characters are given literally, conversion to another encoding (e.g.,
+" UTF-8) should work.
+
+scriptencoding utf-8
+
+let b:keymap_name = "ru"
+
+loadkeymap
+~	+	CYRILLIC CAPITAL LETTER IO
+`	|	CYRILLIC SMALL LETTER IO	
+F	А	CYRILLIC CAPITAL LETTER A
+<	Б	CYRILLIC CAPITAL LETTER BE
+D	В	CYRILLIC CAPITAL LETTER VE
+U	Г	CYRILLIC CAPITAL LETTER GHE
+L	Д	CYRILLIC CAPITAL LETTER DE
+T	Е	CYRILLIC CAPITAL LETTER IE
+:	Ж	CYRILLIC CAPITAL LETTER ZHE
+P	З	CYRILLIC CAPITAL LETTER ZE
+B	И	CYRILLIC CAPITAL LETTER I
+Q	Й	CYRILLIC CAPITAL LETTER SHORT I
+R	К	CYRILLIC CAPITAL LETTER KA
+K	Л	CYRILLIC CAPITAL LETTER EL
+V	М	CYRILLIC CAPITAL LETTER EM
+Y	Н	CYRILLIC CAPITAL LETTER EN
+J	О	CYRILLIC CAPITAL LETTER O
+G	П	CYRILLIC CAPITAL LETTER PE
+H	Р	CYRILLIC CAPITAL LETTER ER
+C	С	CYRILLIC CAPITAL LETTER ES
+N	Т	CYRILLIC CAPITAL LETTER TE
+E	У	CYRILLIC CAPITAL LETTER U
+A	Ф	CYRILLIC CAPITAL LETTER EF
+{	Х	CYRILLIC CAPITAL LETTER HA
+W	Ц	CYRILLIC CAPITAL LETTER TSE
+X	Ч	CYRILLIC CAPITAL LETTER CHE
+I	Ш	CYRILLIC CAPITAL LETTER SHA
+O	Щ	CYRILLIC CAPITAL LETTER SHCHA
+}	Ъ	CYRILLIC CAPITAL LETTER HARD SIGN
+S	Ы	CYRILLIC CAPITAL LETTER YERU
+M	Ь	CYRILLIC CAPITAL LETTER SOFT SIGN
+\"	Э	CYRILLIC CAPITAL LETTER E
+>	Ю	CYRILLIC CAPITAL LETTER YU
+Z	Я	CYRILLIC CAPITAL LETTER YA
+f	а	CYRILLIC SMALL LETTER A
+,	б	CYRILLIC SMALL LETTER BE
+d	в	CYRILLIC SMALL LETTER VE
+u	г	CYRILLIC SMALL LETTER GHE
+l	д	CYRILLIC SMALL LETTER DE
+t	е	CYRILLIC SMALL LETTER IE
+;	ж	CYRILLIC SMALL LETTER ZHE
+p	з	CYRILLIC SMALL LETTER ZE
+b	и	CYRILLIC SMALL LETTER I
+q	й	CYRILLIC SMALL LETTER SHORT I
+r	к	CYRILLIC SMALL LETTER KA
+k	л	CYRILLIC SMALL LETTER EL
+v	м	CYRILLIC SMALL LETTER EM
+y	н	CYRILLIC SMALL LETTER EN
+j	о	CYRILLIC SMALL LETTER O
+g	п	CYRILLIC SMALL LETTER PE
+h	р	CYRILLIC SMALL LETTER ER
+c	с	CYRILLIC SMALL LETTER ES
+n	т	CYRILLIC SMALL LETTER TE
+e	у	CYRILLIC SMALL LETTER U
+a	ф	CYRILLIC SMALL LETTER EF
+[	х	CYRILLIC SMALL LETTER HA
+w	ц	CYRILLIC SMALL LETTER TSE
+x	ч	CYRILLIC SMALL LETTER CHE
+i	ш	CYRILLIC SMALL LETTER SHA
+o	щ	CYRILLIC SMALL LETTER SHCHA
+]	ъ	CYRILLIC SMALL LETTER HARD SIGN
+s	ы	CYRILLIC SMALL LETTER YERU
+m	ь	CYRILLIC SMALL LETTER SOFT SIGN
+'	э	CYRILLIC SMALL LETTER E
+.	ю	CYRILLIC SMALL LETTER YU
+z	я	CYRILLIC SMALL LETTER YA
+@	"
+#	№	NUMERO SIGN
+$	;
+^	:
+&	?
+/	ё
+?	Ё
+1	№
+2	-
+3	/
+4	"
+5	:
+6	,
+7	.
+8	_
+9	?
+0	%
+-	!
+=	;
+\\	)
+\|	(
--- a/runtime/plugin/README.txt
+++ b/runtime/plugin/README.txt
@@ -5,6 +5,7 @@ Look in the file for hints on how it can
 
 getscriptPlugin.vim  get latest version of Vim scripts
 gzip.vim	     edit compressed files
+logiPat.vim	     logical operators on patterns
 matchparen.vim	     highlight paren matching the one under the cursor
 netrwPlugin.vim	     edit files over a network and browse (remote) directories
 rrhelper.vim	     used for --remote-wait editing
new file mode 100644
--- /dev/null
+++ b/runtime/plugin/logiPat.vim
@@ -0,0 +1,335 @@
+" LogiPat:
+"   Author:  Charles E. Campbell
+"   Date:    Mar 13, 2013
+"   Version: 3
+"   Purpose: to do Boolean-logic based regular expression pattern matching
+" Copyright:    Copyright (C) 1999-2011 Charles E. Campbell {{{1
+"               Permission is hereby granted to use and distribute this code,
+"               with or without modifications, provided that this copyright
+"               notice is copied with it. Like most anything else that's free,
+"               LogiPat.vim is provided *as is* and comes with no warranty
+"               of any kind, either expressed or implied. By using this
+"               plugin, you agree that in no event will the copyright
+"               holder be liable for any damages resulting from the use
+"               of this software.
+"
+"   Usage: {{{1
+"       :LogiPat ...
+"
+"         Boolean logic supported:
+"            () grouping operators
+"            !  not the following pattern
+"            |  logical or
+"            &  logical and
+"            "..pattern.."
+"	Example: {{{1
+"		:LogiPat !("january"|"february")
+"		  would match all strings not containing the strings january
+"		  or february
+"	GetLatestVimScripts: 1290 1 :AutoInstall: LogiPat.vim
+"
+"  Behold, you will conceive in your womb, and bring forth a son, {{{1
+"  and will call his name Jesus. He will be great, and will be
+"  called the Son of the Most High. The Lord God will give him the
+"  throne of his father, David, and he will reign over the house of
+"  Jacob forever. There will be no end to his kingdom. (Luke 1:31-33 WEB)
+
+" ---------------------------------------------------------------------
+" Load Once: {{{1
+if &cp || exists("loaded_logipat")
+ finish
+endif
+let g:loaded_LogiPat = "v3"
+let s:keepcpo        = &cpo
+set cpo&vim
+"DechoRemOn
+
+" ---------------------------------------------------------------------
+" Public Interface: {{{1
+com!        -nargs=* LogiPat		call   LogiPat(<q-args>,1)
+silent! com -nargs=* LP				call   LogiPat(<q-args>,1)
+com!        -nargs=+ ELP			echomsg   LogiPat(<q-args>)
+com!        -nargs=+ LogiPatFlags	let  s:LogiPatFlags="<args>"
+silent! com -nargs=+ LPF			let  s:LogiPatFlags="<args>"
+
+" =====================================================================
+" Functions: {{{1
+
+" ---------------------------------------------------------------------
+" LogiPat: this function interprets the boolean-logic pattern {{{2
+fun! LogiPat(pat,...)
+"  call Dfunc("LogiPat(pat<".a:pat.">)")
+
+  " LogiPat(pat,dosearch)
+  if a:0 > 0
+   let dosearch= a:1
+  else
+   let dosearch= 0
+  endif
+
+  let s:npatstack = 0
+  let s:nopstack  = 0
+  let s:preclvl   = 0
+  let expr        = a:pat
+
+  " Lexer/Parser
+  while expr != ""
+"   call Decho("expr<".expr.">")
+
+   if expr =~ '^"'
+	" push a Pattern; accept "" as a single " in the pattern
+    let expr = substitute(expr,'^\s*"','','')
+    let pat  = substitute(expr,'^\(\%([^"]\|\"\"\)\{-}\)"\([^"].*$\|$\)','\1','')
+	let pat  = substitute(pat,'""','"','g')
+    let expr = substitute(expr,'^\(\%([^"]\|\"\"\)\{-}\)"\([^"].*$\|$\)','\2','')
+    let expr = substitute(expr,'^\s*','','')
+"    call Decho("pat<".pat."> expr<".expr.">")
+
+    call s:LP_PatPush('.*'.pat.'.*')
+
+   elseif expr =~ '^[!()|&]'
+    " push an operator
+    let op   = strpart(expr,0,1)
+    let expr = strpart(expr,strlen(op))
+	" allow for those who can't resist doubling their and/or operators
+	if op =~ '[|&]' && expr[0] == op
+     let expr = strpart(expr,strlen(op))
+	endif
+    call s:LP_OpPush(op)
+
+   elseif expr =~ '^\s'
+    " skip whitespace
+    let expr= strpart(expr,1)
+
+   else
+    echoerr "operator<".strpart(expr,0,1)."> not supported (yet)"
+    let expr= strpart(expr,1)
+   endif
+
+  endwhile
+
+  " Final Execution
+  call s:LP_OpPush('Z')
+
+  let result= s:LP_PatPop(1)
+"  call Decho("result=".result)
+
+  " sanity checks and cleanup
+  if s:npatstack > 0
+   echoerr s:npatstack." patterns left on stack!"
+   let s:npatstack= 0
+  endif
+  if s:nopstack > 0
+   echoerr s:nopstack." operators left on stack!"
+   let s:nopstack= 0
+  endif
+
+  " perform the indicated search
+  if dosearch
+   if exists("s:LogiPatFlags")
+"  call Decho("search(result<".result."> LogiPatFlags<".s:LogiPatFlags.">)")
+    call search(result,s:LogiPatFlags)
+   else
+"  call Decho("search(result<".result.">)")
+    call search(result)
+   endif
+   let @/= result
+  endif
+
+"  call Dret("LogiPat ".result)
+  return result
+endfun
+
+" ---------------------------------------------------------------------
+" s:String: Vim6.4 doesn't have string() {{{2
+func! s:String(str)
+  return "'".escape(a:str, '"')."'"
+endfunc
+
+" ---------------------------------------------------------------------
+" LP_PatPush: {{{2
+fun! s:LP_PatPush(pat)
+"  call Dfunc("LP_PatPush(pat<".a:pat.">)")
+  let s:npatstack              = s:npatstack + 1
+  let s:patstack_{s:npatstack} = a:pat
+"  call s:StackLook("patpush") "Decho
+"  call Dret("LP_PatPush : npatstack=".s:npatstack)
+endfun
+
+" ---------------------------------------------------------------------
+" LP_PatPop: pop a number/variable from LogiPat's pattern stack {{{2
+fun! s:LP_PatPop(lookup)
+"  call Dfunc("LP_PatPop(lookup=".a:lookup.")")
+  if s:npatstack > 0
+   let ret         = s:patstack_{s:npatstack}
+   let s:npatstack = s:npatstack - 1
+  else
+   let ret= "---error---"
+   echoerr "(LogiPat) invalid expression"
+  endif
+"  call s:StackLook("patpop") "Decho
+"  call Dret("LP_PatPop ".ret)
+  return ret
+endfun
+
+" ---------------------------------------------------------------------
+" LP_OpPush: {{{2
+fun! s:LP_OpPush(op)
+"  call Dfunc("LP_OpPush(op<".a:op.">)")
+
+  " determine new operator's precedence level
+  if a:op == '('
+  	let s:preclvl= s:preclvl + 10
+	let preclvl  = s:preclvl
+  elseif a:op == ')'
+  	let s:preclvl= s:preclvl - 10
+   if s:preclvl < 0
+    let s:preclvl= 0
+    echoerr "too many )s"
+   endif
+   let preclvl= s:preclvl
+  elseif a:op =~ '|'
+   let preclvl= s:preclvl + 2
+  elseif a:op =~ '&'
+   let preclvl= s:preclvl + 4
+  elseif a:op == '!'
+   let preclvl= s:preclvl + 6
+  elseif a:op == 'Z'
+   let preclvl= -1
+  else
+   echoerr "expr<".expr."> not supported (yet)"
+   let preclvl= s:preclvl
+  endif
+"  call Decho("new operator<".a:op."> preclvl=".preclvl)
+
+  " execute higher-precdence operators
+"  call Decho("execute higher-precedence operators")
+  call s:LP_Execute(preclvl)
+
+  " push new operator onto operator-stack
+"  call Decho("push new operator<".a:op."> onto stack with preclvl=".preclvl." at nopstack=".(s:nopstack+1))
+  if a:op =~ '!'
+   let s:nopstack             = s:nopstack + 1
+   let s:opprec_{s:nopstack}  = preclvl
+   let s:opstack_{s:nopstack} = a:op
+  elseif a:op =~ '|'
+   let s:nopstack             = s:nopstack + 1
+   let s:opprec_{s:nopstack}  = preclvl
+   let s:opstack_{s:nopstack} = a:op
+  elseif a:op == '&'
+   let s:nopstack             = s:nopstack + 1
+   let s:opprec_{s:nopstack}  = preclvl
+   let s:opstack_{s:nopstack} = a:op
+  endif
+
+"  call s:StackLook("oppush") "Decho
+"  call Dret("LP_OpPush : s:preclvl=".s:preclvl)
+endfun
+
+" ---------------------------------------------------------------------
+" LP_Execute: execute operators from opstack using pattern stack {{{2
+fun! s:LP_Execute(preclvl)
+"  call Dfunc("LP_Execute(preclvl=".a:preclvl.") npatstack=".s:npatstack." nopstack=".s:nopstack)
+
+  " execute all higher precedence operators
+  while s:nopstack > 0 && a:preclvl < s:opprec_{s:nopstack}
+   let op= s:opstack_{s:nopstack}
+"   call Decho("op<".op."> nop=".s:nopstack." [preclvl=".a:preclvl."] < [opprec_".s:nopstack."=".s:opprec_{s:nopstack}."]")
+
+   let s:nopstack = s:nopstack - 1
+ 
+   if     op == '!'
+    let n1= s:LP_PatPop(1)
+	call s:LP_PatPush(s:LP_Not(n1))
+ 
+   elseif op == '|'
+    let n1= s:LP_PatPop(1)
+    let n2= s:LP_PatPop(1)
+    call s:LP_PatPush(s:LP_Or(n2,n1))
+ 
+   elseif op =~ '&'
+    let n1= s:LP_PatPop(1)
+    let n2= s:LP_PatPop(1)
+    call s:LP_PatPush(s:LP_And(n2,n1))
+   endif
+ 
+"   call s:StackLook("execute") "Decho
+  endwhile
+
+"  call Dret("LP_Execute")
+endfun
+
+" ---------------------------------------------------------------------
+" LP_Not: writes a logical-not for a pattern {{{2
+fun! s:LP_Not(pat)
+"  call Dfunc("LP_Not(pat<".a:pat.">)")
+  if a:pat =~ '^\.\*' && a:pat =~ '\.\*$'
+   let pat= substitute(a:pat,'^\.\*\(.*\)\.\*$','\1','')
+   let ret= '^\%(\%('.pat.'\)\@!.\)*$'
+  else
+   let ret= '^\%(\%('.a:pat.'\)\@!.\)*$'
+  endif
+"  call Dret("LP_Not ".ret)
+  return ret
+endfun
+
+" ---------------------------------------------------------------------
+" LP_Or: writes a logical-or branch using two patterns {{{2
+fun! s:LP_Or(pat1,pat2)
+"  call Dfunc("LP_Or(pat1<".a:pat1."> pat2<".a:pat2.">)")
+  let ret= '\%('.a:pat1.'\|'.a:pat2.'\)'
+"  call Dret("LP_Or ".ret)
+  return ret
+endfun
+
+" ---------------------------------------------------------------------
+" LP_And: writes a logical-and concat using two patterns {{{2
+fun! s:LP_And(pat1,pat2)
+"  call Dfunc("LP_And(pat1<".a:pat1."> pat2<".a:pat2.">)")
+  let ret= '\%('.a:pat1.'\&'.a:pat2.'\)'
+"  call Dret("LP_And ".ret)
+  return ret
+endfun
+
+" ---------------------------------------------------------------------
+" StackLook: {{{2
+fun! s:StackLook(description)
+"  call Dfunc("StackLook(description<".a:description.">)")
+  let iop = 1
+  let ifp = 1
+"  call Decho("Pattern                       Operator")
+
+  " print both pattern and operator
+  while ifp <= s:npatstack && iop <= s:nopstack
+   let fp = s:patstack_{ifp}
+   let op = s:opstack_{iop}." (P".s:opprec_{s:nopstack}.')'
+   let fplen= strlen(fp)
+   if fplen < 30
+   	let fp= fp.strpart("                              ",1,30-fplen)
+   endif
+"   call Decho(fp.op)
+   let ifp = ifp + 1
+   let iop = iop + 1
+  endwhile
+
+  " print just pattern
+  while ifp <= s:npatstack
+   let fp  = s:patstack_{ifp}
+"   call Decho(fp)
+   let ifp = ifp + 1
+  endwhile
+
+  " print just operator
+  while iop <= s:nopstack
+   let op  = s:opstack_{iop}." (P".s:opprec_{s:nopstack}.')'
+"   call Decho("                              ".op)
+   let iop = iop + 1
+  endwhile
+"  call Dret("StackLook")
+endfun
+
+" ---------------------------------------------------------------------
+"  Cleanup And Modeline: {{{1
+let &cpo= s:keepcpo
+unlet s:keepcpo
+" vim: ts=4 fdm=marker