"============================================================================= " File: eregex.vim and eregex_e.vim " Author: AKUTSU toshiyuki " Maintainer: Kao, Wei-Ko " Requirements: Vim version 6.1 and later. " Description: eregex.vim is a converter from extended regex to vim regex " eregex_e.vim is an evaluater for command of eregex.vim " The meaning of extended regex is pseudo ruby/perl-style regex. " Previous $Id: eregex.vim,v 2.56 2010-10-18 11:59:41+08 ta Exp $ " $Id: eregex.vim,v 2.60 2013-02-22 14:38:41+08 ta Exp $ " Note: English isn't my mother tongue. "============================================================================= " Principle: " eregex.vim adopts the way of extended regex about "alternation", " "repetition" and "grouping". " As for those things, the way of Vim regex is adopted. " You can use '\_^', '\zs', '\<', '\%<23c', '\_u', etc in extended regex. "============================================================================= " Functions: " " E2v({extended_regex} [, {iISCDMm}]) " The result is a String, which is vim style regex. " " :let vimregex = E2v('(?<=abc),\d+,(?=xzy)','i') " :echo vimregex " \c\%(abc\)\@<=,\d\+,\%(xzy\)\@= " " E2v('','V') " The result is a Number, which is eregex.vim version. " " :echo E2v('','V') " 238 " " E2v({replacement} ,{R1,R2,R3}) " The result is a String, which is used for the "to" part of :S/from/to/ " " E2v('\r,\n,\&,&,\~,~', 'R1') => \n,\r,\&,&,\~,~ " E2v('\r,\n,\&,&,\~,~', 'R2') => \r,\n,&,\&,~,\~ " E2v('\r,\n,\&,&,\~,~', 'R3') => \n,\r,&,\&,~,\~ " "============================================================================= " Commands: " " :[range]E2v [iISCDMm] " Extended regex To Vim regex. " Replace each extended-regex in [range] with vim-style-regex. " " :M/eregex/[offset][iISCDMm] " Match. " :M/.*?<\/span>/Im " => /\C\_.\{-}<\/span> " " :[range]S/eregex/replacement/[&cegpriISCDMm] " Substitute. " :'<,'>S/(\d{1,3})(?=(\d\d\d)+($|\D))/\1,/g " => :'<,'>s/\(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@=/\1,/g " " :[range]G/eregex/command " Global. " :G/<<-(["'])?EOD\1/,/^\s*EOD\>/:left 8 " => :g/<<-\(["']\)\=EOD\1/,/^\s*EOD\>/:left 8 " " :[range]V/eregex/command " Vglobal " "============================================================================= " Tips And Configuration: " " Put the following commands in your ~/.vimrc to replace normal / with :M/ " " nnoremap / :M/ " nnoremap ,/ / " " v238, v243 " If you put 'let eregex_replacement=3' in your ~/.vimrc, " " :S/pattern/\r,\n,\&,&,\~,~/ will be converted to :s/pattern/\n,\r,&,\&,~,\~/ " " +--------------------+-----------------------------+ " | eregex_replacement | :S/pattern/\n,\r,&,\&,~,\~/ | " +--------------------+-----------------------------+ " | 0 | :s/pattern/\n,\r,&,\&,~,\~/ | " | 1 | :s/pattern/\r,\n,&,\&,~,\~/ | " | 2 | :s/pattern/\n,\r,\&,&,\~,~/ | " | 3 | :s/pattern/\r,\n,\&,&,\~,~/ | " +--------------------+-----------------------------+ " See :h sub-replace-special " "============================================================================= " Options: " Note: "^L" is "\x0c". " " "i" ignorecase " "I" noignorecase " "S" convert "\s" to "[ \t\r\n^L]" and also convert "\S" to "[^ \t\r^L]" " Mnemonic: extended spaces " "C" convert "[^az]" to "\_[^az]" and also convert "\W" to "\_W". " Mnemonic: extended complement " Vim's "[^az]" matches anything but "a", "z", and a newline. " "D" convert "." to "\_." " Mnemonic: extended dot " Normally, "." matches any character except a newline. " "M" partial multiline; do both "S" and "C". " In other words, It is not "multiline" in ruby way. " "m" full multiline; do all the above conversions "S", "C" and "D". " In other words, It is just "multiline" in ruby way. " "+-----+----------------------------------------------+--------------------+ "| Num | eregex.vim => vim regex | ruby regex | "+-----+----------------------------------------------+--------------------+ "| (1) | :M/a\s[^az].z/ => /a\s[^az].z/ | /a[ \t][^az\n].z/ | "+-----+----------------------------------------------+--------------------+ "| | :M/a\s[^az].z/S => /a[ \t\r\n^L][^az].z/ | /a\s[^az\n].z/ | "| | :M/a\s[^az].z/C => /a\s\_[^az].z/ | /a[ \t][^az].z/ | "| | :M/a\s[^az].z/D => /a\s[^az]\_.z/ | /a[ \t][^az\n].z/m | "+-----+----------------------------------------------+--------------------+ "| (2) | :M/a\s[^az].z/M => /a[ \t\r\n^L]\_[^az].z/ | /a\s[^az].z/ | "| (3) | :M/a\s[^az].z/m => /a[ \t\r\n^L]\_[^az]\_.z/ | /a\s[^az].z/m | "+-----+----------------------------------------------+--------------------+ " " Note: " As for "\s", "[^az]" and ".", "M" and "m" options make " eregex.vim-regexen compatible with ruby/perl-style-regexen. " Note: " Vim's "[^az]" doesn't match a newline. " Contrary to the intention, "[^az\n]" matches a newline. " The countermeasure is to convert "[^\s]" to "[^ \t\r^L]" with " multiline. " "============================================================================= " pseudo ruby/perl-style regexen. " " available extended regexen: " alternation: " "a|b" " repetition: " "a+", "a*", "a?", "a+?", "a*?", "a??," " "a{3,5}", "a{3,}", "a{,5}", "a{3,5}?", "a{3,}?", "a{,5}?" " grouping: " "(foo)", "(?:foo)", "(?=foo)", "(?!foo)", "(?<=foo)", " "(?foo)" " modifiers: " "(?I)", "(?i)", "(?M)", "(?m)", "(?#comment)" " " Note: " The use of "\M" or "\m" is preferable to the use of "(?M)" or "(?m)". " "(?M)" and "(?m)" can't expand "\s" in brackets to " \t\r\n^L". " " not available extended regexen: " "\A", "\b", "\B", "\G", "\Z", "\z", " "(?i:a)", "(?-i)", "(?m:.)", " There are no equivalents in vim-style regexen. " " special atoms: " "\C" noignorecase " "\c" ignorecase " "\M" partial multiline " "\m" full multiline " " For example: " :M/a\s[^az].z/M => /a[ \t\r\n^L]\_[^az].z/ " :M/a\s[^az].z\M/ => /a[ \t\r\n^L]\_[^az].z/ " :M/a\s[^az].z/m => /a[ \t\r\n^L]\_[^az]\_.z/ " :M/a\s[^az].z\m/ => /a[ \t\r\n^L]\_[^az]\_.z/ " The order of priority: " [A] /IiMm, [B] \C, \c, \M, \m, [C] (?I), (?i), (?M), (?m) " " many other vim-style regexen available: " "\d", "\D", "\w", "\W", "\s", "\S", "\a", "\A", " "\u", "\U", "\b" " "\<", "\>" " "\zs", "\ze" " "\_[a-z]", "\%[abc]", "[[:alpha:]]" " "\_.", "\_^", "\_$" " "\%23l", "\%23c", "\%23v", "\%#" " and so on. See :h /ordinary-atom " " misc: " Convert "\xnn" to char except "\x00", "\x0a" and "\x08". " "\x41\x42\x43" => "ABC" " "\x2a\x5b\x5c" => "\*\[\\" " Expand atoms in brackets. " "[#$\w]" => "[#$0-9A-Za-z_]" " " "\f" in brackets is converted to "\x0c". " but "\f" out of brackets is a class of filename characters. " " eregex.vim expansion of atoms and its meaning. " +-------+----------------------+----------------------+ " | atom | out of brackets | in brackets | " +-------+----------------------+----------------------+ " | \a | alphabetic char | alphabetic char | " | \b | \x08 | \x08 | " | \e | \x1b | \x1b | " | \f | filename char | \x0c | " | \n | \x0a | \x0a | " | \r | \x0d | \x0d | " | \s | [ \t] or [ \t\r\n\f] | " \t" or " \t\r\n\f" | " | \t | \x09 | \x09 | " | \v | \x0b | \x0b | " | \xnn | hex nn | hex nn | " +-------+----------------------+----------------------+ " "============================================================================= if version < 601 | finish | endif if exists("loaded_eregex") finish endif let loaded_eregex=1 "============================================================================= "Commands And Mappings: command! -nargs=? -range E2v :,call ExtendedRegex2VimRegexLineWise() command! -nargs=? -count=1 M :let s:eregex_tmp_hlsearch = &hlsearch | let v:searchforward = Ematch(, ) | if s:eregex_tmp_hlsearch == 1 | set hlsearch | endif "command! -nargs=? -range S :,call Esubstitute() command! -nargs=? -range S :,call Esubstitute() :noh command! -nargs=? -range=% -bang G :,call Eglobal(, ) command! -nargs=? -range=% V :,call Evglobal() "============================================================================= "Script Variables: let s:eglobal_working=0 "-------------------- let s:ch_with_backslash=0 let s:ch_posix_charclass=1 let s:ch_brackets=2 let s:ch_braces=3 let s:ch_parentheses_option=4 let s:ch_parentheses=5 let s:re_factor{0}='\\\%([^x_]\|x\x\{0,2}\|_[.$^]\=\)' let s:re_factor{1}= '\[:\%(alnum\|alpha\|blank\|cntrl\|digit\|graph\|lower\|print\|punct\|' . \ 'space\|upper\|xdigit\|return\|tab\|escape\|backspace\):\]' let s:re_factor{2}='\[\%([^^][^]]*\|\^.[^]]*\)\]' let s:re_factor{3}='{[0-9,]\+}?\=' "v141 "let s:re_factor{4}='(?[iISCDMm]\{1,7})' let s:re_factor{4}='(?[iImM]\{1,2})' let s:re_factor{5}='(\(?:\|?=\|?!\|?<=\|?\|?[-#ixm]\)\=[^()]*)' let s:re_factor_size=6 "-------------------- let s:mark_left="\" . strftime("%X") . ":" . strftime("%d") . "\" let s:mark_right="\" . strftime("%X") . ":" . strftime("%d") . "\" let s:stack_size=0 let s:invert=0 let s:multiline=0 let s:ignorecase=0 "v220 let s:re_unescaped='\%(\\\)\@ '.g:eregex_forward_delim.' ":".v:count1."M/"' exec 'nnoremap '.g:eregex_backward_delim.' ":".v:count1."M?"' if silent != 1 echo "eregx.vim key mapping enabled" endif else exec 'nunmap '.g:eregex_forward_delim exec 'nunmap '.g:eregex_backward_delim if silent != 1 echo "eregx.vim key mapping disabled" endif endif let s:enable = 1 - s:enable endfun if !(exists('g:eregex_default_enable') && g:eregex_default_enable == 0) call eregex#toggle(1) endif "============================================================================= "Functions: function! s:Push(fct, kind) let fct = a:fct if (a:kind==s:ch_with_backslash) && (fct =~# '^\\x\x\{1,2}$') " \x41 exec 'let code=0 + 0x' . matchstr(fct, '\x\{1,2}$') if code!=0x0a && code!=0 && code!=0x08 let fct = nr2char(code) "v141 if stridx(s:meta_chars, fct)!=-1 let fct = "\\" . fct endif endif elseif a:kind == s:ch_with_backslash " \. \_x let chr = fct[1] if chr =~# '[+?{}|()=]' let fct = chr elseif chr =~# '[Vv]' if chr ==# 'v' let fct=nr2char(0x0b) else let fct='V' endif "[IiMm] endif elseif a:kind == s:ch_posix_charclass " [:alpha:] pass through elseif a:kind == s:ch_brackets "[ ] let fct = s:ExpandAtomsInBrackets(fct) elseif a:kind == s:ch_braces "{ } let fct = '\' . fct " minimal match, not greedy if fct =~# '?$' if fct =~# '\d\+,\d\+' let fct = substitute(fct, '{\(\d\+\),\(\d\+\)}?', '{-\1,\2}', '') elseif fct =~# ',}' let fct = substitute(fct, '{\(\d\+\),}?', '{-\1,}', '') elseif fct =~# '{,' let fct = substitute(fct, '{,\(\d\+\)}?', '{-,\1}', '') else let fct = strpart(fct, 1) endif endif elseif a:kind==s:ch_parentheses_option "( ) "v223 call s:SetModifiers(fct) let fct = '' elseif (a:kind==s:ch_parentheses) && (fct =~# '(?[-#ixm]') "( ) if fct =~# '(?-\=[ixm]\{1,3})' || fct =~# '(?#' let fct = '' else let fct = substitute(fct, '(?-\=[ixm]\{1,3}:\([^()]*\))', '\1', "") let fct = s:ReplaceRemainFactorWithVimRegexFactor(fct) endif elseif a:kind==s:ch_parentheses "( ) let kakko = matchstr(fct, '(\(?:\|?=\|?!\|?<=\|?\)\=') let fct = substitute(fct, '(\(?:\|?=\|?!\|?<=\|?\)\=', "", "") let fct = strpart(fct, 0, strlen(fct)-1) let fct = s:ReplaceRemainFactorWithVimRegexFactor(fct) if kakko ==# '(' let fct = '\(' . fct . '\)' elseif kakko ==# '(?:' let fct = '\%(' . fct . '\)' elseif kakko ==# '(?=' let fct = '\%(' . fct . '\)\@=' elseif kakko ==# '(?!' let fct = '\%(' . fct . '\)\@!' elseif kakko ==# '(?<=' let fct = '\%(' . fct . '\)\@<=' elseif kakko ==# '(?' let fct = '\%(' . fct . '\)\@>' else let fct = ":BUG:" endif endif let s:stack{s:stack_size} = fct let s:stack_size = s:stack_size + 1 endfunction "end s:Push() "----------------------------------------------------------------------------- function! s:ExpandAtomsInBrackets(bracket) let bracket = a:bracket let re_mark = s:mark_left . '\d\+' . s:mark_right let re_snum = s:mark_left . '\(\d\+\)' . s:mark_right "v120 let has_newline=0 "v216,v249 let complement=(bracket =~# '^\[^') let searchstart = 0 let mtop = match(bracket, re_mark, searchstart) while mtop >= 0 let mstr = matchstr(bracket, re_mark, searchstart) let snum = substitute(mstr, re_snum, '\1', "") + 0 "v222 let fct = s:stack{snum} "exclude, \e=0x1b, \b=0x08, \r=0x0d, \t=0x09 if fct =~# '^\\[adfhlosuwx]$' let chr = fct[1] if chr ==# 'a' let fct='A-Za-z' elseif chr ==# 'd' let fct='0-9' elseif chr ==# 'f' "let fct=nr2char(0x0c) let fct="\x0c" elseif chr ==# 'h' let fct='A-Za-z_' elseif chr ==# 'l' let fct='a-z' elseif chr ==# 'o' let fct='0-7' elseif chr ==# 's' "v141 if s:extended_spaces==1 "v217 if (s:countermeasure==1) && (complement==1) let fct=" \\t\\r\x0c" else let fct=" \\t\\r\\n\x0c" endif let has_newline=1 else let fct=' \t' endif elseif chr ==# 'u' let fct='A-Z' elseif chr ==# 'w' let fct='0-9A-Za-z_' elseif chr ==# 'x' let fct='0-9A-Fa-f' endif let s:stack{snum}=fct else "v120 if fct ==# '\n' "If there is only "\n" of inside of the brackets. "It becomes the same as "\_.". let has_newline=1 "v219 elseif fct ==# '-' " '-' converted from \xnn "If there is '-' in the beginning of the brackets and the end. "Unnecessary '\' is stuck. let s:stack{snum}='\-' "v237 elseif fct ==# '\[' " '\[' converted from \xnn let s:stack{snum}='[' endif endif let searchstart = mtop + strlen(mstr) let mtop = match(bracket, re_mark, searchstart) endwhile "v120 if (complement==1) && (has_newline==0) let bracket = s:mark_complements . bracket endif return bracket endfunction "end ExpandAtomsInBrackets() "----------------------------------------------------------------------------- function! s:Pop() if s:stack_size <= 0 | return "" | endif let s:stack_size = s:stack_size - 1 return s:stack{s:stack_size} endfunction "----------------------------------------------------------------------------- " Debug: function! s:UnletStack() let i = 0 while exists("s:stack" . i) exec "unlet s:stack" . i let i = i + 1 endwhile let s:stack_size = 0 endfunction " Debug: "function! EachStack() " let lineno = line(".") " let i = 0 " while exists("s:stack" . i) " call append(lineno + i, i . " -> " . s:stack{i}) " let i = i + 1 " endwhile "endfunction "----------------------------------------------------------------------------- function! s:ReplaceExtendedRegexFactorWithNumberFactor(extendedregex) let halfway = a:extendedregex let s:stack_size = 0 let i=0 let id_num=0 while i < s:re_factor_size "CASESENSE: let regex = '\C' . s:re_factor{i} let mtop = match(halfway, regex) while mtop >= 0 let factor = matchstr(halfway, regex) let pre_match = strpart(halfway, 0, mtop) let post_match= strpart(halfway, mtop + strlen(factor)) let halfway = pre_match . s:mark_left . id_num . s:mark_right . post_match "END: call s:Push( factor, i ) let id_num = id_num + 1 let mtop = match(halfway, regex) endwhile let i = i + 1 endwhile return halfway endfunction "end s:ReplaceExtendedRegexFactorWithNumberFactor() "----------------------------------------------------------------------------- function! s:ReplaceRemainFactorWithVimRegexFactor(halfway) let halfway = a:halfway " minimal match, not greedy let halfway = substitute(halfway, '+?', '\\{-1,}', 'g') let halfway = substitute(halfway, '\*?', '\\{-}', 'g') let halfway = substitute(halfway, '??', '\\{-,1}', 'g') "-------------------- let halfway = substitute(halfway, '+', '\\+', 'g') let halfway = substitute(halfway, '?', '\\=', 'g') "-------------------- let halfway = substitute(halfway, '|', '\\|', 'g') "-------------------- let halfway = substitute(halfway, '\~', '\\&', 'g') "-------------------- "v141 if s:extended_dots==1 let halfway = substitute(halfway, '\.', '\\_.', 'g') endif return halfway endfunction "end s:ReplaceRemainFactorWithVimRegexFactor() "----------------------------------------------------------------------------- function! s:ReplaceNumberFactorWithVimRegexFactor(halfway) let vimregex = a:halfway let i = s:stack_size while i > 0 let i = i - 1 let factor = s:Pop() let str_mark = s:mark_left . i . s:mark_right let vimregex = s:ReplaceAsStr(vimregex, str_mark, factor) endwhile "Debug: call s:UnletStack() "v221 "v120 if stridx(vimregex, s:mark_complements)!=-1 "v141 if s:extended_complements==1 "there isn't \_ before [^...]. " [^...] doesn't contain \n. let re='\C\%(\%(\\\)\@ 0 let tmp = (s:ignorecase==1) ? '\c' : '\C' let vimregex = tmp . vimregex endif "if &magic==0 " let vimregex = '\m' . vimregex "endif return vimregex endfunction "end s:ReplaceNumberFactorWithVimRegexFactor() "============================================================================= "Main: function! s:ExtendedRegex2VimRegex(extendedregex, ...) "v141 let s:ignorecase=0 let s:multiline=0 let s:extended_spaces=0 let s:extended_complements=0 let s:extended_dots=0 if a:0==1 "v238,v243 if a:1 =~# 'R[0-3]' return s:ExchangeReplaceSpecials(a:extendedregex, matchstr(a:1, 'R\zs[0-3]')) "v240 elseif a:1 ==# 'V' return s:version endif call s:SetModifiers(a:1) endif "v240 moved here if strlen(a:extendedregex)==0 return "" endif "v141 let eregex=a:extendedregex "v221 let mods = matchstr(eregex, '\C' . s:re_escaped . '[Mm]') let mods = mods . matchstr(eregex, '\C' . s:re_escaped . '[Cc]') if mods !=# '' let mods = substitute(mods, '\CC', 'I',"g") let mods = substitute(mods, '\Cc', 'i',"g") call s:SetModifiers(mods) let re='\C' . s:re_escaped . '[MmCc]' let eregex=substitute(eregex, re, '', "g") endif "-------------------- let halfway = s:ReplaceExtendedRegexFactorWithNumberFactor(eregex) let halfway = s:ReplaceRemainFactorWithVimRegexFactor(halfway) let vimregex = s:ReplaceNumberFactorWithVimRegexFactor(halfway) "v221 return vimregex endfunction "end s:ExtendedRegex2VimRegex() "----------------------------------------------------------------------------- function! s:ExtendedRegex2VimRegexLineWise(...) range if a:1 ==# '--version' echo "$Id: eregex.vim,v 2.56 2003-09-19 17:39:41+09 ta Exp $" return endif let modifiers= a:1 let i = a:firstline while i <= a:lastline call setline(i, s:ExtendedRegex2VimRegex(getline(i), modifiers)) let i = i + 1 endwhile endfunction "end s:ExtendedRegex2VimRegexLineWise() "----------------------------------------------------------------------------- "Public: function! E2v(extendedregex, ...) if a:0==0 return s:ExtendedRegex2VimRegex(a:extendedregex) endif return s:ExtendedRegex2VimRegex(a:extendedregex, a:1) endfunction "end E2v() "----------------------------------------------------------------------------- function! s:Ematch(...) let ccount = a:1 if strlen(a:2) <= 1 let string = a:2 . @/ else let string = a:2 endif let delim=string[0] if delim !=# '/' && delim !=# '?' let v:errmsg= "The delimiter `" . delim . "' isn't available, use `/' ." echohl WarningMsg | echo v:errmsg return endif let rxp ='^delim\([^delim\\]*\%(\\.[^delim\\]*\)*\)' . \ '\(delim.*\)\=$' let rxp=substitute(rxp, 'delim', delim, "g") let regex = substitute(string, rxp, '\1',"") let offset= substitute(string, rxp, '\2', "") "-------------------- let modifiers='' "v141 if offset =~# '[' . s:str_modifiers . ']' let modifiers = substitute(offset, '\C[^' . s:str_modifiers . ']\+', "", "g") let offset = substitute(offset, '\C[' . s:str_modifiers . ']\+', "", "g") endif if g:eregex_force_case == 1 if match(modifiers, 'i') == -1 && match(modifiers, 'I') == -1 let modifiers .= 'I' endif endif let regex = s:ExtendedRegex2VimRegex(regex, modifiers) "v130 "set s:bakregex let regex = s:EscapeAndUnescape(regex, delim) "-------------------- if offset==# '' let offset = delim endif let cmd = 'normal! ' . ccount . delim . regex . offset . "\" let v:errmsg='' set nohlsearch silent! exec cmd if (v:errmsg !~# '^E\d\+:') || (v:errmsg =~# '^E486:') "v130 if s:bakregex !=# '' let @/ = s:bakregex endif endif if v:errmsg ==# '' redraw! if &foldenable && &foldopen =~# 'search' exec 'normal!zv' endif else echohl WarningMsg | echo v:errmsg endif if delim == '?' return 0 else return 1 endif endfunction "end s:Ematch() "----------------------------------------------------------------------------- function! s:Esubstitute(...) range if strlen(a:1) <= 1 | return | endif let string = a:1 let delim = s:GetDelim(string[0]) if delim==# '' | return | endif let rxp ='^delim\([^delim\\]*\%(\\.[^delim\\]*\)*\)delim\([^delim\\]*\%(\\.[^delim\\]*\)*\)' . \ '\(delim.*\)\=$' let rxp=substitute(rxp, 'delim', delim, "g") if string !~# rxp if s:eglobal_working==0 echohl WarningMsg | echo 'Invalid arguments S' . a:1 endif return endif let regex = substitute(string, rxp, '\1',"") let replacement = substitute(string, rxp, '\2', "") let options = substitute(string, rxp, '\3',"") "-------------------- "v141 let modifiers='' if options =~# '[' . s:str_modifiers . ']' let modifiers = substitute(options, '\C[^' . s:str_modifiers . ']\+', "", "g") let options = substitute(options, '\C[SCDmM]', "", "g") endif if g:eregex_force_case == 1 if match(modifiers, 'i') == -1 && match(modifiers, 'I') == -1 let modifiers .= 'I' endif endif let regex = s:ExtendedRegex2VimRegex(regex, modifiers) "v130 "set s:bakregex let regex = s:EscapeAndUnescape(regex, delim) "v238, v243 if (s:eregex_replacement > 0) && (strlen(replacement) > 1) let replacement = s:ExchangeReplaceSpecials(replacement, s:eregex_replacement) endif "-------------------- if options ==# '' let options = delim endif let cmd = a:firstline . ',' . a:lastline . 's' . delim . regex . delim . replacement . options "Evaluater: let g:eregex_evaluater_how_exe = s:eglobal_working if g:eregex_evaluater_how_exe==0 let v:statusmsg='' let v:errmsg='' endif let confirmoption = (options =~# 'c') if confirmoption==1 "with confirm option. let g:eregex_evaluater_how_exe=1 endif let g:eregex_evaluater_cmd = cmd runtime plugin/eregex_e.vim if g:eregex_evaluater_how_exe==0 || confirmoption==1 unlet! g:eregex_evaluater_cmd "v130 if s:bakregex !=# '' let @/ = s:bakregex endif if confirmoption==0 if v:errmsg==# '' if v:statusmsg !=# '' echohl WarningMsg | echo v:statusmsg endif else echohl WarningMsg | echo v:errmsg endif endif endif endfunction "end s:Esubstitute() "----------------------------------------------------------------------------- function! s:Eglobal(bang, ...) range if strlen(a:1)<=1 | return | endif let string=a:1 let delim = s:GetDelim(string[0]) if delim==#'' | return | endif "-------------------- let re_pattern = substitute('[^delim\\]*\%(\\.[^delim\\]*\)*', 'delim', delim,"g") let re_offset = '\%([-+0-9]\d*\|\.[-+]\=\d*\)' let re_sep = '[,;]' let re_command = '[^,;].*' let re_command_less = '\_$' let re_end = '\%(' . re_sep . '\|' . re_command . '\|' . re_command_less . '\)' "-------------------- let toprxp0 = '^' . delim . '\(' . re_pattern . '\)\(' . delim . re_offset . re_sep . '\)' let toprxp1 = '^' . delim . '\(' . re_pattern . '\)\(' . delim . re_sep . '\)' let toprxp2 = '^' let endrxp0 = delim . '\(' . re_pattern . '\)\(' . delim . re_offset . re_end . '\)' let endrxp1 = delim . '\(' . re_pattern . '\)\(' . delim . re_end . '\)' let endrxp2 = delim . '\(' . re_pattern . '\)' . re_command_less "-------------------- let mtop = -1 let j = 0 while j < 3 let i = 0 while i < 3 let regexp = toprxp{j} . endrxp{i} let mtop = match(string, regexp) if mtop>=0 | break | endif let i = i + 1 endwhile if mtop>=0 | break | endif let j = j + 1 endwhile if mtop<0 | return | endif "-------------------- if a:bang==# '!' let s:invert=1 endif let cmd = (s:invert==0) ? 'g' : 'v' let s:invert=0 let cmd = a:firstline . ',' . a:lastline . cmd let globalcmd = '' if j == 2 let pattern1 = substitute(string, regexp, '\1', "") let strright = delim if i < 2 let strright = substitute(string, regexp, '\2', "") endif let pattern1 = s:ExtendedRegex2VimRegex(pattern1) "v130 let pattern1 = s:EscapeAndUnescape(pattern1, delim) let globalcmd = cmd . delim . pattern1 . strright else let pattern1 = substitute(string, regexp, '\1', "") let strmid = substitute(string, regexp, '\2',"") let pattern2 = substitute(string, regexp, '\3', "") let strright = delim if i < 2 let strright = substitute(string, regexp, '\4', "") endif let pattern1 = s:ExtendedRegex2VimRegex(pattern1) let pattern2 = s:ExtendedRegex2VimRegex(pattern2) "v130 let pattern1 = s:EscapeAndUnescape(pattern1, delim) let pattern2 = s:EscapeAndUnescape(pattern2, delim) let globalcmd = cmd . delim . pattern1 . strmid . delim . pattern2 . strright endif "-------------------- "Evaluater: let s:eglobal_working=1 let g:eregex_evaluater_how_exe=2 let g:eregex_evaluater_cmd = globalcmd runtime plugin/eregex_e.vim let s:eglobal_working=0 "let g:eregex_evaluater_how_exe=0 unlet! g:eregex_evaluater_cmd endfunction "end s:Eglobal() "----------------------------------------------------------------------------- function! s:Evglobal(...) range let s:invert=1 let cmd = a:firstline . ',' . a:lastline . 'G' . a:1 exec cmd endfunction "end s:Evglobal() "----------------------------------------------------------------------------- function! s:GetDelim(str) let valid = '[/@#]' let delim = a:str[0] if delim =~# valid return delim endif let v:errmsg = "The delimiter `" . delim . "' isn't available, use " . valid echohl WarningMsg | echo v:errmsg return '' endfunction "end s:GetDelim() "============================================================================= "v130 "called from Ematch(), Esubstitute(), Eglobal() "use s:re_unescaped, s:re_escaped, s:bakregex function! s:EscapeAndUnescape(vimregex, delim) let vimregex = a:vimregex let s:bakregex= a:vimregex if a:delim ==# '@' return vimregex endif if s:bakregex =~# s:re_escaped . a:delim " \/ or \# exists let s:bakregex = substitute(vimregex, s:re_escaped . a:delim, a:delim, "g") endif if vimregex =~# s:re_unescaped . a:delim " / or # exists let vimregex = substitute(vimregex, s:re_unescaped . a:delim, '\\' . a:delim, "g") endif return vimregex endfunction "end s:EscapeAndUnescape() "============================================================================= "v141 "called from only s:ExtendedRegex2VimRegex() function! s:SetModifiers(mods) "v221 if s:ignorecase==0 if a:mods =~# 'i' let s:ignorecase=1 elseif a:mods =~# 'I' let s:ignorecase=2 endif endif "v221 if s:multiline==0 if a:mods =~? 'm' let s:extended_spaces=1 let s:extended_complements=1 if a:mods =~# 'M' "partial multiline let s:multiline=1 else "full multiline let s:extended_dots=1 let s:multiline=2 endif endif endif if a:mods =~# 'S' let s:extended_spaces=1 endif if a:mods =~# 'C' let s:extended_complements=1 endif if a:mods =~# 'D' let s:extended_dots=1 endif endfunction "End: s:SetModifiers(mods) "============================================================================= "v238, function! s:ExchangeReplaceSpecials(replacement, sort) let rs=a:replacement "v243,v246 if (rs !~# '[&~]\|\\[rnx]') || (rs =~# '^\\=') return rs endif if (a:sort % 2)==1 let rs=substitute(rs, '\C' . s:re_escaped . 'r', '\\R', "g") let rs=substitute(rs, '\C' . s:re_escaped . 'n', '\\r', "g") let rs=substitute(rs, '\C' . s:re_escaped . 'R', '\\n', "g") endif if a:sort >= 2 let rs=substitute(rs, '\C' . s:re_escaped . '&', '\\R', "g") let rs=substitute(rs, '\C' . s:re_escaped . '\~', '\\N', "g") let rs=substitute(rs, '\C' . s:re_unescaped . '[&~]', '\\&', "g") let rs=substitute(rs, '\C' . s:re_escaped . 'R', '\&', "g") let rs=substitute(rs, '\C' . s:re_escaped . 'N', '\~', "g") endif return rs endfunction "End: s:ExchangeReplaceSpecials() "============================================================================= "============================================================================= "Import: macros/locrian.vim function! s:ReplaceAsStr(str, search, replacement, ...) let gsub = a:0 if a:0 > 0 let gsub = (a:1=~? 'g') ? 1 : 0 endif let oldstr = a:str let newstr = "" let len = strlen(a:search) let i = stridx(oldstr, a:search) while i >= 0 let newstr = newstr . strpart(oldstr, 0, i) . a:replacement let oldstr = strpart(oldstr, i + len) if gsub==0 break endif let i = stridx(oldstr, a:search) endwhile if strlen(oldstr)!=0 let newstr = newstr . oldstr endif return newstr endfunction "end s:ReplaceAsStr() "============================================================================= function! ExtendedRegex2VimRegex(data) return s:ExtendedRegex2VimRegex(a:data) endfunction