commit 38a631a8490078f1011dd020252a39aed27f9d02 Author: othree Date: Fri Oct 15 22:01:39 2010 +0800 first commit diff --git a/doc/eregex_j.txt b/doc/eregex_j.txt new file mode 100644 index 0000000..a1363b9 --- /dev/null +++ b/doc/eregex_j.txt @@ -0,0 +1,480 @@ +*eregex_j.txt* + + ファイル: eregex.vim, eregex_e.vim + 作者: AKUTSU toshiyuki + バージョン: 2.55 + 必要なもの: Vim version 6.1 かそれ以降。 + 説明: eregex.vim は、拡張正規表現を Vim の正規表現に変換します。 + eregex_e.vim は、eregex.vim のコマンドを評価します。 + +1. 使用許諾 |eregex-license-to-use| +2. インストール |eregex-installations| +3. 関数 |eregex-functions| +4. コマンド |eregex-commands| +5. 使い方 |eregex-examples| +6. キーマップ |eregex-keymappings| +7. 原則 |eregex-principle| +8. 内部的な変換を表す一覧 |eregex-table| +9. 特殊なオプションとアトム |eregex-options| +10. マルチライン |eregex-multiline| +11. デリミタの制限 |eregex-limitation-of-delimiter| +12. Vim の正規表現について |eregex-about-vimregex| + +============================================================================== +1. 使用許諾 *eregex-license-to-use* + + eregex.vim と eregex_e.vim の著作権は、作者である AKUTSU toshiyuki に + 帰属します。しかし、改変、再配布は自由にしてかまいません。 + # GPL とか分かんないのだ。(^^ )>> + + 作者は本スクリプト(eregex.vim, eregex_e.vim) を使用したことによって生じた + いかなる損害について、一切の責任を負いません。 + +============================================================================== +2. インストール *eregex-installations* + 参考 |add-plugin| + + (1) UNIX/Linux + $HOME/.vim/plugin/eregex.vim + $HOME/.vim/plugin/eregex_e.vim + $HOME/.vim/doc/eregex_j.txt + + それから、次のようにして helptags の再構築をします。 + :helptags ~/.vim/doc + + これで、:h :E2v とかできます。 + + (2) MS-Windows + eregex_j.txt は EUC-JP です。 + MS-Windows の場合は予め ShiftJIS にしておいてください。 + + %HOME%\vimfiles\plugin\eregex.vim + %HOME%\vimfiles\plugin\eregex_e.vim + %HOME%\vimfiles\doc\eregex_j.txt + + または、 + + %VIM%\vimfiles\plugin\eregex.vim + %VIM%\vimfiles\plugin\eregex_e.vim + %VIM%\vimfiles\doc\eregex_j.vim + + それから、次のようにして helptags の再構築をします。 + :helptags $HOME\vimfiles\doc + または、 + :helptags $VIM\vimfiles\doc + + これで、:h :E2v とかできます。 + +============================================================================== +3. 関数 *eregex-functions* *eregex* + *E2v()* +E2v({extendedregex} [, {iISCDMm}]) + + 返り値は Vim の正規表現です。 +> + :let vimregex = E2v('(?<=abc),\d+,(?=xzy)','i') + :echo vimregex + \c\%(abc\)\@<=,\d\+,\%(xzy\)\@= +< + オプションの詳しい説明は |eregex-options| や |eregex-multiline| + を見てください。 + +E2v("","V") + 返り値は eregex.vim のバージョンです。 +> + :echo E2v('','V') + 248 +< +E2v({replacement}, {R1,R2,R3}) + これは、:S/pattern/to/ の "to" の部分で使う文字列を返します。 +> + E2v('\r,\n,\&,&,\~,~', 'R1') => \n,\r,\&,&,\~,~ + E2v('\r,\n,\&,&,\~,~', 'R2') => \r,\n,&,\&,~,\~ + E2v('\r,\n,\&,&,\~,~', 'R3') => \n,\r,&,\&,~,\~ +< + +============================================================================== +4. コマンド *eregex-commands* + *:E2v* +:[range]E2v [iISCDMm] + Extended regex To Vim regex. + Replace each extended-regex in [range] with vim-style-regex. + + *:M* +:M/eregex[/{offset} [iISCDMm]] + Match + :M/.*?<\/span>/Im + ==> /\C\_.\{-}<\/span> + + *:S* +:[range]S/{eregex}/{string}/[&cegpriISCDMm] + Substitute + :'<,'>S/(\d{1,3})(?=(\d\d\d)+($|\D))/\1,/g + ==> :'<,'>s/\(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@=/\1,/g + + *:G* *:G!* +:[range]G/{eregex}/{command} +:[range]G!/{eregex}/{command} + Global + :G/<<-(["'])?EOD\1/,/^\s*EOD\>/:left 8 + ==> :g/<<-\(["']\)\=EOD\1/,/^\s*EOD\>/:left 8 + + *:V* +:[range]V/{eregex}/{command} + Vglobal + +============================================================================== +5. 使い方 *eregex-examples* + +(1) :E2v コマンド + + 次の拡張正規表現の行にカーソルを置く。 + +(\d{1,3})(?=(\d\d\d)+($|\D)) + + んで、:E2v を実行すると、次のようになる。 + +\(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@= + + +(2) :M コマンド +> + :M/.+?<\/Items>/Im +< + :normal! /\C\_.\{-1,}<\/Items> + + + + + + + + +(3) :S コマンド +> + :'<,'>S/(\d{1,3})(?=(\d\d\d)+($|\D))/\1,/g +< + :'<,'>s/\(\d\{1,3}\)\%(\(\d\d\d\)\+\($\|\D\)\)\@=/\1,/g + + 1 --> 1 + 12 --> 12 + 123 --> 123 + 1234 --> 1,234 + 12345 --> 12,345 + 123456 --> 123,456 + 1234567 --> 1,234,567 + 12345678 --> 12,345,678 + 123456789 --> 123,456,789 + +(4) :G コマンド +> + :G/^begin$/+1;/^end$/-1:S/\l+/\U&/g +< + :g/^begin$/+1;/^end$/-1:s/\l\+/\U&/g + +begin + hello world. + hello world wide web. + hello The Internet. +end + + |begin + | HELLO WORLD. + | HELLO WORLD WIDE WEB. + | HELLO THE INTERNET. + |end + +(5) :V コマンド + 説明省略。 + +============================================================================== +6. キーマップ *eregex-keymappings* + + / で行なう通常の検索と :M/ を入れ替える。 + .vimrc に以下を書く。 ( MS-Windows の場合 _vimrc か _gvimrc ) + +nnoremap / :M/ +nnoremap ,/ / + + "/" で、:M/ になり、",/" で従来の "/" が使えます。 + + -------------------- + ~/.vimrc の中に、 + let eregex_replacement=3 + を書いておくと :S コマンドの動作が次のように変わります。 + +:S/pattern/\r,\n,\&,&,\~,~/ +: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,\&,&,\~,~/ | + +--------------------+-----------------------------+ + + +============================================================================== +7. 原則 *eregex-principle* + eregex.vim において、 + 「選択」「繰り返し」「丸カッコ」は、拡張正規表現流 を採用する。 + それ以外は Vim の正規表現に従う。 + +============================================================================== +8. 内部的な変換を表す一覧 *eregex-table* + + 左には拡張正規表現を書き、右には Vim 流正規表現('magic')を書く。 + +選択 +-------------------- + :M/a|b /a\|b + +繰り返し +-------------------- + :M/a* /a* + :M/a+ /a\+ + :M/a? /a\= + + :M/a*? /a\{-} + :M/a+? /a\{-1,} + :M/a?? /a\{-,1} + + :M/a{3,5} /a\{3,5} + :M/a{3,} /a\{3,} + :M/a{,5} /a\{,5} + + :M/a{3,5}? /a\{-3,5} + :M/a{3,}? /a\{-3,} + :M/a{,5}? /a\{-,5} + +丸カッコ(パレン) +-------------------- + :M/(abc) /\(abc\) + :M/(?:abc) /\%(abc\) + :M/(?<=abc) /\%(abc\)\@<= + :M/(?abc) /\%(abc\)\@> + +文字そのもの +-------------------- + :M/\\,\|,\(,\),\{,\},\?,\+,\*,\[,\] /\\,|,(,),{,},?,+,\*,\[,\] + :M/\^,\$ /\^,\$ + +拡張正規表現で使えないもの +-------------------- + \A, \b, \B, \G, \Z, \z + これらは全て Vim のものとして扱われる。 + (?i:a) や (?-i) なども使えない。 + +Vim の正規表現で使えないもの +-------------------- + \%(re\) 等、パレン(丸カッコ) を使うもの全般。 + ~ matches the last given substitute string + \m 'magic' on for the following chars in the pattern + \M 'magic' off for the following chars in the pattern + \v the following chars in the pattern are "very magic" + \V the following chars in the pattern are "very nomagic" + + \x hex digit: [0-9A-Fa-f] + \\x[0-9A-Fa-f]{1,2} の場合、文字そのものに変換する。 + \x82\xa0 => 'あ' ( shift-jis, cp932 ) + ただし、0x00 と 0x0a と 0x08 は変換しません。 + +Vim の正規表現で使えるもの +-------------------- + 大抵使えます。(^^;) + \d, \D, \w, \W, \s, \S, \a, \A, \u, \U, \b, ... + \<, \>, \zs, \ze + \_[a-z], \%[abc], [[:alpha:]], \_., \_^, \_$ + \%23l, \%23c, \%23v, \%# + など。 + +============================================================================== +9. 特殊なオプションとアトム *eregex-options* + Note: "^L" は \x0c + + eregex.vim Vim +--------------------------------------- + :M/a/i /\ca/ + :M/\ca/ /\ca/ + :M/a/I /\Ca/ + :M/\Ca/ /\Ca/ + + :M/\s/S /[ \t\r\n^L] + :M/\S/S /[^ \t\r^L] + :M/[^az]/C /\_[^az]/ + :M/\W/C /\_W/ + :M/./D /\_./ + + :M/\s[^az]./M /[ \t\r\n^L]\_[^az]./ + :M/\s[^az].\M/ 同上。 + + :M/\s[^az]./m /[ \t\r\n^L]\_[^az]\_./ + :M/\s[^az].\m/ 同上。 + ++--------+------+--------------------------------------------------------+ +| OPTION | ATOM | 説明 | ++--------+------+--------------------------------------------------------+ +| /i | \c | 大小文字の区別無し。 | +| /I | \C | 大小文字の区別あり。 | ++--------+------+--------------------------------------------------------+ +| /S | | \s および \S を [ \t\r\n^L] や [^ \t\r^L] に変換する。 | +| /C | | 補集合が改行にもマッチする。 | +| /D | | ドットが改行にもマッチする。 | ++--------+------+--------------------------------------------------------+ +| /M | \M | /S と /C を行なう。 部分マルチライン。 | +| /m | \m | /S と /C と /D を行なう。完全マルチライン。 | ++--------+------+--------------------------------------------------------+ + + Note: + (A) オプション /iImM + (B) \c, \C, \m, \M + (C) (?i), (?I), (?m), (?M) + これらが同時に指定された場合、上の方が優先順位が高い。 + ちなみに、(?M) と (?m) は、ブラケットの中の \s には適用されません。 + +============================================================================== +10. マルチライン *eregex-multiline* + + とりあえず以下の表を見て。(^^;) ++-----+----------------------------------------------+--------------------+ +| 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 | ++-----+----------------------------------------------+--------------------+ + + (1) は、「文字クラス」が Vim 流。 + (2) は、「文字クラス」が Ruby 流。 + Vim 流に言えば、改行にマッチする所が増えたので、部分マルチライン。 + Ruby 流に言えば、マルチラインでない。よってオプションは大文字の M 。 + (3) は、いわゆる Ruby 流のマルチライン。 + + Note: + Vim の正規表現では、/[^az]/ は改行にマッチしません。 + 改行にマッチしないことを明示して /[^az\n]/ と書く必要はありません。 + /[^az\n]/ は意図に反して改行にもマッチします。 + よって、本来 /[^ \t\r\n^L]/ とするべきところを、/[^ \t\r^L]/ に + 変換している場合があります。 + 原則的に Vim では、[^...] の中に \n を書いてはいけません。 + +============================================================================== +11. デリミタの制限 *eregex-limitation-of-delimiter* + + :M で使える区切り文字は / だけです。 + :S 、:G および :V で使える区切り文字は /, #, @ です。 + これらの使用方法は :s 、:g 、:v と同じです。 + 制限も同様です。 + + 区切り文字を @ にするといろいろ制限があります。 + + 一見うまくいきそうに見えてダメな例。 + "foo@bar.baz.co.jp" を "foo@hoge.co.jp" に置換しようとして、 +> + :%s@\@foo\@hoge.co.jp@Ig +< + は、エラーです。 + Vim の正規表現で、\@ は特別な扱いを受けています。 +============================================================================== +12. Vim の正規表現について *eregex-about-vimregex* + + 以下 カーソルを "111,222,333" の行に置いて、:S... を実行してください。 + +(1)通常のサブマッチ。 + +111,222,333 +> + :S/(\d+),(\d+),(\d+)/\=submatch(1) + submatch(2) + submatch(3) +< +666 + +(2)Vim 独自機能。 + マッチデータ($&, &, matchdata) と、サブマッチを分離できます。 + \zs と \ze を使う。 See :h /\zs + +111,222,333 +> + :S/(\d+),\zs\d+\ze,(\d+)/\=submatch(1) + submatch(0) + submatch(2) +< +111,666,333 + + +(3) + 以下の方が分かりやすいかも。 + +111,222,333 +> + :S/(\d+),\zs(\d+)\ze,(\d+)/\=submatch(1) + submatch(2) + submatch(3) +< +111,666,333 + + \zs と \ze を使うと、マッチデータに含まれないサブマッチを操作できます。 + +(4) \_x の機能。 + + \u で [A-Z] を表す。 + \_u で [A-Z\n] を表す。 + \_[A-Z] は [A-Z\n] と同じ。 + + 大文字以外で改行を含む文字。 + \_U == \_[^A-Z] + + \_. は改行を含む任意の文字。 + + +(5) ^ と \_^ および $ と \_$ の違い。 + + $ を例にとります。 + + 通常 $ は + (1)正規表現の一番最後。 + (2) ) の直前。 + (3) | の直前。 + にある場合だけ行末を表す。 + + ところが任意の場所で行末を表せるのが \_$ 。 + +111,222,333 +> + :S/(\d+),(\d+),(\d+)\zs\_$\ze/\=',' . (submatch(1) + submatch(2) + submatch(3)) +< +111,222,333,666 + + ここで使っている \_$ の代わりに $ を使っても意図した結果になりません。 + Note: + \_^ と \_$ は perl の /m オプションとは全然違います。 + + +============================================================================== +13. 履歴 +revision 2.55 + (1) E2v() にバージョン番号や、sub-replace-special の置換を加えた。 + (2) \v を 0x0b に置換するようにした。 + (3) :M/pattern/ でマッチしなくても、@/ を更新した。 + +revision 2.35 + (1) オプション S,C,D,M,m の追加と変更。 + +revision 1.4x + (1) :S/\x2f/\\/g とかすると、:s///\\/g に変換してしまうバグ修正。 + (2) エスケープされたデリミタを検索履歴ではアンエスケープした。 + デリミタが '@' の場合を除く。 + (3) オプション m の修正。 + +revision 1.13 + :G で ! を使えるようにした。 + +revision 1.1.1.21 + :S の /c オプションで確認のプロンプトが見えなくなってしまう問題修正。 + +-- vim:ft=help: diff --git a/plugin/eregex.vim b/plugin/eregex.vim new file mode 100644 index 0000000..d801b8e --- /dev/null +++ b/plugin/eregex.vim @@ -0,0 +1,1030 @@ +"============================================================================= +" File: eregex.vim and eregex_e.vim +" Author: AKUTSU toshiyuki +" 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. +" $Id: eregex.vim,v 2.55 2003-09-19 17:39:41+09 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=? M :call Ematch() +"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='\%(\\\)\@\)\=') + 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.55 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(...) + if strlen(a:1) <= 1 | return | endif + + let string = a:1 + let delim=string[0] + + if delim !=# '/' + let v:errmsg= "The delimiter `" . delim . "' isn't available, use `/' ." + 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 + + 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! ' . delim . regex . offset . "\" + let v:errmsg='' + silent! exec cmd + if (v:errmsg !~# '^E\d\+:') || (v:errmsg =~# '^E486:') + "v130 + if s:bakregex !=# '' + let @/ = s:bakregex + endif + endif + if v:errmsg ==# '' + redraw! + else + echo 'M' . a:1 + echo v:errmsg + 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 + 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 + + 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 !=# '' + echo v:statusmsg + endif + else + 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 + 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() +"============================================================================= diff --git a/plugin/eregex_e.vim b/plugin/eregex_e.vim new file mode 100644 index 0000000..9ffce1b --- /dev/null +++ b/plugin/eregex_e.vim @@ -0,0 +1,17 @@ +" $Id: eregex_e.vim,v 1.40 2003-06-03 18:25:59+09 ta Exp ta $ +" An evaluater for eregex.vim +if exists('g:eregex_evaluater_cmd') && exists('g:eregex_evaluater_how_exe') + if g:eregex_evaluater_how_exe==0 + " :s silently exec, handle errmsg + silent! exec g:eregex_evaluater_cmd + elseif g:eregex_evaluater_how_exe==1 + " :s invoked by :g and + " :s with confirm option + exec g:eregex_evaluater_cmd + elseif g:eregex_evaluater_how_exe==2 + ":g + redraw + exec g:eregex_evaluater_cmd + endif +endif +