1 名前:名無しさん@お腹いっぱい。 [01/12/17 12:15] みんなでスクリプトを覚えよう
20 名前:名無しさん@お腹いっぱい。 mailto:sage [01/12/18 22:27] :let で全変数が見れるんかー。デバッグ時に便利そう。 :let hoge だと hoge だけの値が表示されると。 表示に # がついていたら数値らしい。 :let hoge=123 :let hoge hoge #123 :let hoge="123" :let hoge hoge 123
21 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/19 21:23] <<<文字列変数と定数>>> 今んとこまだ変数には数字しか使ってねーんだけど,文字列も使えるんだ ぜぃ. Vim で使える変数ってのは数字と文字列しか無ぇんだよ.どっちの型に なるのかは ":let" で変数に代入する毎に,その場その場で決まるからな. 文字列を変数にブチ込みたい時は文字列定数を使うんだぞ.まぁ文字列定数っつっても 二種類あって,一個はダブルクウォートで括るやつで, :let name = "giko" :echo name giko ってな感じな.んで,文字列中にダブルクウォートそのものを含みたい時は ダブルクウォートの前にバックスラッシュを置くべし.つまり, :let name = "\"mona\"" :echo name "mona" こーゆー事.んで,バックスラッシュがメンドい場合は文字列をシングルク ウォートで括ればよし. :let name = '"KoRoN"' :echo name "KoRoN" んで,シングルクウォートに挟まれた文字列は全部そのまんま文字通り扱わ れるぞ.って事はシングルクウォートその物を含む事は出来ないってことだ. もちろんバックスラッシュもそのまんま扱われるから,直後の文字を変換す る為には使えねーからな. ダブルクウォートに挟まれた文字列は特殊文字(special characters)が使え るぞ.まーちっとばかり例を挙げてやると, \t <Tab> \n <NL>, 改行 \r <CR>, <Enter> (復帰) \e <Esc> \b <BS>, バックスペース \" " \\ \, バックスラッシュ \<Esc> <Esc> \<C-W> CTRL-W 最後の二つはただの例だぞ. "\<name>" ってやったら "name" っつー特殊キー として扱われるって事な. 文字列中の特殊文字の全リストは |expr-quote| にあるぞ.
22 名前:KoRoN@Vim%Chalice mailto:koron@tka.att.ne.jp [01/12/20 16:55] >>21 うわ。気づかなかったけど何気に > :let name = "\"mona\"" > :let name = '"KoRoN"' とかなってるし!!。見過ごしてた(゜Д゜)
23 名前:名無しさん@Vim%Chalice [01/12/20 17:42] vimメーラに期待age
24 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/20 22:47] >> KoRoN 殿 見つかってしまいましたか(藁 まぁ敬意を込めてのお遊びなんでお許しを.他意はありませぬ. 今日は忙しいから訳無し.スマソ.
25 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/22 00:32] 41.3 式 (Expressions) Vimは大胆かつシンプルな式の扱いが出来るよーになってるぜぃ.定義について は |expression-syntax| を見ろや.まーとりあえず一般的な事だけここでは 教えといてやろう. これまでに言ってきた数字や文字列,変数っつーのはそれ自体で式になって るぞ.んだから,式が要求されるところにはいつでも数字や文字列や変数が 使えるってわけだ.他の式の中で使われる基本的なものっつったら, $NAME 環境変数 &name オプション @r レジスタ ってな感じかな. 例) :echo "The value of 'tabstop' is" &ts :echo "Your home directory is" $HOME :if @a > 5 &option っつー形は,オプションをまずどっかに保存しといて,それからそのオプ ションを新しい値に設定した後に何かしてから,先に保存しておいた値を元に戻す 時なんかに使われるぞ. 例) :let save_ic = &ic :set noic :/The Start/,$delete :let &ic = save_ic
26 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/22 00:33] 今日はこれだけ. 忘年会シーズンは酔っぱらってる時はやらない方がいいカモ・・・
27 名前:名無しさん@お腹いっぱい。 [01/12/22 02:20] Vim6スクリプトでアウトラインプロセッサを作る事は出来ますか? 行編集の vi の系列だから、そういうのは得意そうな気がするのですが、 如何でしょう? もし既に在るならば、素の vi から乗り換えたいな。
28 名前:名無しさん@お腹いっぱい。 [01/12/22 02:48] vimのコマンドにエイリアスみたいのをつけたいんだけど。 例えば、 :aiueo ってやったら :se ts=2 sw=2 sts=2 et のかわりになるみたいな。 あと、よくvimでかかれたテキストファイルに vim:se ts=2 sw=2 sts=2 et とかあるけどあれって意味あるの?
29 名前:名無しさん@お腹いっぱい。 [01/12/22 05:51] >>28 その書き方は知らない。 C++とかJavaのソースなんかでは // vi:ts=4 sw=4 number: とか書いたりはするけど(これはちゃんと効く)
30 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [01/12/22 08:46] ここはスクリプトの勉強スレなので一連(>>27-28 )の質問がココにふさわしいかは疑 問ですが、折角ですから答えられる部分は答えてしまいましょう。 ■ ◆Vim6 2スレ pc.2ch.net/test/read.cgi/unix/1006246205/l50 >>27 完全なアウトラインプロセッサとは言えないのですが、folding(折畳み)機能を使え ばスクリプトを駆使しなくてもそれに近いことが実現可能です。foldingというのは テキスト中の指定された範囲を折畳んで隠す機能です。例えばプログラミングであれ ば特定のブロックを隠したり、関数の実装を隠したりできます。またちょっと毛色は 違いますがテンプレートコンパイラを利用する方法も考えられるかもしれません。 ■ テンプレートコンパイラの紹介 www.kaoriya.net/bbs/bbs.cgi?article=1238&bbs=bbs >>28 :help commandしてみて下さい。自分で任意のコマンドを定義することができます。 但しコマンド名は英大文字で始まる必要があります。 例: command! Aiueo set ts=2 sw=2 sts=2 et > あと、よくvimでかかれたテキストファイルに > vim:se ts=2 sw=2 sts=2 et > とかあるけどあれって意味あるの? もちろんあります。modelineといって(詳細は:help modelineを参照)これが書かれた ファイルを開いた時に、これらのオプションが自動的に設定されます。スクリプトが 実行されるわけではないので注意してください。modelineを書ける範囲はファイルの 先頭と末尾のそれぞれ5行(この5行はオプション'modelines'により変更可能)です。 例: *.cの先頭に /* vim:set ts=8 tw=4 sw=4 tw=0: */ と書く もちろんファイルタイプに拠らず*.txtでもなんでも書いてあれば有効になります。
31 名前:名無しさん@お腹いっぱい。 mailto:sage [01/12/22 13:57] modeline と fold ってけっこう組み合わせて使うよね。 KoRoN さんのサイトのソースなんか参考になるかもね。
32 名前:名無しさん@お腹いっぱい。 [01/12/22 20:42] うわ、マジココイイわ。そしてマジコココイイわ。要するにイイ。
33 名前:1 [01/12/22 23:11] ほんとに初めてVimスクリプトをお勉強しょうとおもーとる人の為に書いとくけんな。 スクリプト読んどって解らん命令出てきたら何でもその上で K を入力じゃ 親切なマニュアルが飛び出てくるけん。んで閉じるのは Ctrl+wc 英語じゃわけわからんとかいう場合はこっち ixeris.bios.ics.saitama-u.ac.jp/~noiz/gvim/ から日本語化してくれとるマニュアルを落として runtime/doc にコピーしときゃーええ。 それにしても日本語化を進めてくれとる人達には大感謝じゃなぁ。 # 酔っていると方言になります。
34 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/22 23:18] <<<演算>>> んで,まぁ上で挙げたよーな要素が結合とか出来たら面白い事が出来るでしょ. まずは数値の演算から行ってみよー!! a + b 加算 a - b 減算 a * b 積算 a / b 除算 a % b 剰余 まぁ優先順位は普通の算数と同じだぞ.例を挙げると, :echo 10 + 5 * 2 20 って事な(足し算よりかけ算の方が優先度が高い). んでジョーシキ通り,括弧を使えば優先度は変えられるぞ.つまり, :echo (10 + 5) * 2 30 って事ね. 文字列は "." で結合出来るぜぃ.だから, :echo "Vim" . "Manse-" VimManse- ってなもんよ. ":echo" コマンドは複数の引数を受け取ると,それぞれをスペースで区切っ て表示するんだけど,上の例は全部引数は一個の式だったからスペースで区 切られて表示する事は無いんだ. C 言語のパクリなんだけど,3項演算子 a ? b : c も式として使えるぞ.もし "a" が真だったら "b" が使われて,そうでなかっ たら "c" が使われる.つまり, :let i = 4 :echo i > 5 ? "i is big" : "i is small" i is small ってな感じで使えるわけだ.んで,3つの各パートは必ず最初に評価されるから な.つまり, (a) ? (b) : (c) ってなってると思えばいいわけよ.
35 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/22 23:20] KoRoN 殿や mattn 殿に続けぇ〜!!!! #マダミチハトオイナ・・・ 今日もこんだけ.なんかアンマリススマナイナ
36 名前:名無しさん@お腹いっぱい。 mailto:sage [01/12/23 01:10] >>33 >日本語化してくれとるマニュアルを落として runtime/doc にコピーしときゃーええ。 日本語のヘルプすごく助かるけど、Version 6.0 で追加された項目が見れなくなっちゃうんだよね。 ウィンドウの縦分割について調べるときにはまった。
37 名前:27 [01/12/23 04:11] >>30 どうもありがとう。 vim6.0 使ってみましたが emacs のような高機能ぶりで驚きました。 スクリプト機能は emacs の elisp にあたると考えて良いのでしょうか?
38 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [01/12/23 10:20] >>37 難しい質問です。elispはemacsのベースとして存在しているのでまったく同様に捉え られてしまうと間違いなのですが、エディタを制御したり内部の関数を利用できると いう表面的な意味においては同じと考えても差し支えないでしょう。lispに比べれば 表現力に相当の制約がありますが、それでもいかにもvimらしい命令体系で強力なス クリプトになっています。
39 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/24 00:44] 41.4 条件 ":if" コマンドは条件が満足された時のみ,それ以降の":endif" までの文を実 行しまっせ.まぁ普通は :if {condition} {statements} :endif こんな感じで.つまり, {condition}が真(ゼロ以外)って評価された時のみ {statements}が実行されるって事ね.当然その文はちゃんとしたコマンドじゃ なきゃダメだぞ.余計な変なのがあったりすると Vim が ":endif"を見付け られなくなっちまうからな. んで,":else" も使えるぞ.まぁ一般的な使い方っつったら, :if {condition} {statements} :else {statements} :endif こうね.2番目の{statements}は最初の{statements}が実行されない場合に実行 されるぞ. んでもって,やっとこさ":elseif"のご登場 :if {condition} {statements} :elseif {condition} {statements} :endif これは,":else" の後に ":if" を使ったよーに動くぞ.ただ,余計な ":endif" はいらない(つまり最後の一個だけでいい)けどね. vimrc ファイルに書くよーな,'term'オプションをチェックして,その値に応じて ちょっとした事をする便利な例をご紹介. :if &term == "xterm" : " ここに xterm 用のコマンドを書くべし :elseif &term == "vt100" : " ここに vt100 ターミナル用のコマンドを書くべし :else : " 他のターミナルについてのコマンドをここに書くべし :endif
40 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/24 00:45] <<<論理演算(っつーか単純な「比較」なだけなよーな)>>> まーいくつかは例の中で使って来たわけなんだけど,良く使われるのは a == b 等しい a != b 等しくない a > b より大きい a >= b 以上 a < b より小さい a <= b 以下 結果は条件が満たされてれ 1 で,そーじゃなかったら 0 ね. 例) :if v:version >= 600 : echo "おめでたう" :else : echo "バージョン古いぞ,アップデートしろや!" :endif "v:version" ってのは Vimのバージョンを表す,Vim に既に定義されてる変 数ね.600 は バージョン 6.0 の事で,バージョン 6.1 は 601 ってなるぞ. これ使うと,Vim の色々なバージョンで動くスクリプトを書く時には便利だ ぞ. |v:version| 論理演算(っつーか比較なんぢゃぁ…)は数値にも文字列にも使えるぞ.文字 列を比較した時は数学的な差が使われるぞ.つまり,バイト値が比較される から,言語によっては正しくない事もあるからな. 文字列と数値とで比較した場合は,まず文字列が数値に変換されて,それか ら比較されるぞ.これはちょっとトリッキーで,文字列が数字と認識されない 場合は文字列はゼロとして扱われるぞ.つまり, :if 0 == "one" : echo "禿同" :endif ってやると,"one" が数字とは認識されないから,ゼロに変換されちゃって, んでもって"禿同"が表示されちゃうわけよ.
41 名前:ヘッポコ訳者 ◆xBY/hgW2 [01/12/24 00:46] 文字列に対してはあと二つばかりまだあんのよ. a =~ b 正規表現にマッチする a !~ b 正規表現にマッチしない 左辺の "a" は文字列で,右辺の "b" は検索で使うような正規表現(以下パター ン)だぞ. 例) :if str =~ " " : echo "str contains a space" :elseif str !~ '\.$' : echo "str ends in a full stop" :endif シングルクウォートで括った文字列をパターンに使ってる事にご注目.パター ンって結構バックスラッシュ良く使うんだけど,ダブルクウォートの文字列 使うと,バックスラッシュ二重にしなくっちゃならないから,シングルク ウォートの文字列使った方が便利なわけよ. 文字列比較する時は 'ignorecase' オプションが使われるぞ.もしそれが嫌 だったら,大文字小文字を考慮する場合は "#",無視する場合は"?" を演算 子の後に付ければいいぞ.つまり,"==?" は大文字小文字関係無く一致を調 べるし, "!~#" ってやれば,大文字小文字を考慮して,パターンにマッチしな いかどうかを調べるってわけよ.まぁ完全な一覧は |expr-==| を見てくれや. <<<ループについてもーちっとばかり>>> ":while" コマンドについてはもうしゃべっちまったけど,あと2つばかり ":while" と ":endwhile" の間に使えるコマンドがあるのよ,実は. :continue while ループの先頭まで戻ってループを続ける :break ":endwhile" まで飛んで,ループから抜ける 例) :while counter < 40 : call do_something() : if skip_flag : continue : endif : if finished_flag : break : endif : sleep 50m :endwhile ":sleep" コマンドは待機するコマンド(makes Vim take a nap)ね. "50m" ってのは 50 ミリ秒の事.まぁもーちっと例を挙げると,":sleep 4" ってやれ ば 4秒間待機するってわけさ.
42 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/24 00:48] ハイ,クリスマスプレゼントは以上です(藁 ところで "LOGICAL OPERATION" って「論理演算」だよねぇ? これって僕の勝手な感覚では「論理和」とかあっちの方の意味 なんだけど,この感覚ってもしかして間違ってる?
43 名前:1 [01/12/24 01:25] 全バッファに対して一括置換が行える便利スクリプトをマニュアルの中に発見しました。 :help map.txt|/Allargs でジャンプ 抜粋。 > :function Allargs(command) > : let i = 0 > : while i < argc() > : if filereadable(argv(i)) > : execute "e " . argv(i) > : execute a:command > : endif > : let i = i + 1 > : endwhile > :endfunction > :command -nargs=+ -complete=command Allargs call Allargs(<q-args>) function 〜 endfunction で関数定義。 argc() は バッファ数。 argv(i) は i 番のバッファ名の取得。(:ls で確認できる) filereadable() は指定バッファが読み出せるか? execute は ex コマンドの実行。 使う時。foo を bar に置換しまくる。 :Allargs %s/foo/bar/ge|update eオプションをつけないと foo が無いというメッセージがのんびり表示されて、いつま でたっても置換が終わらないので気をつけよう(それに気づかずに密かにハマった) コマンドは | で連続で実行できて、update は変更のあったバッファだけを保存。と。 カレントの *.cpp を置換する場合は予め、 :ar *.cpp ってやっとくと全部読み込まれる。 確認するには :ar と。 すげー便利というか、他のエディタだったら最初から 装備しているような機能だから当然、 _vimrc に書いといて、 _vimrc に書くときは何回定義しても起こられないように function と command の後に ! を付けとくほうがいいかも。 >>36 縦分割って6.0から追加された機能あるの?? :sp とかじゃなくて? >>42 御苦労さんです。LOGICALだと同じく or and って感覚ですねえ。
44 名前:名無しさん@お腹いっぱい。 mailto:sage [01/12/24 01:57] >>38 わざわざどうもありがとう。 >>3 のリンクを見てなんとなく感じがつかめました。 今日から Vim Scriptor ということで宜しく。
45 名前:名無しさん@お腹いっぱい。 mailto:sage [01/12/24 03:27] >>43 ctrl-W_V とか
46 名前:45 mailto:sage [01/12/24 03:30] スレ違いなのね ちょっと反省
47 名前:1 mailto:(´Д`;) [01/12/24 22:34] call confirm("クリスマスイブ", "逝ってよし(´Д`;)")
48 名前:1 mailto:(´Д`;) [01/12/24 22:57] さぁて、お勉強。 とりあえずKoRoNさんのwc相当スクリプト解析 :function! s:CountChar(first, last) "!をつけると上書き定義になる。んで s: をつけているから command! のところで "<SID>CountChar と書かなくてはならない。 : let i = a:first "引数は a: を付けて参照する。a:first は先頭行 : let sum = 0 : while i <= a:last " a:lastは最後の行 : "echo "line: " . i " デバッグ用につけているみたい : let sum = sum + strlen(substitute(getline(i), '.', ' ', 'g')) " getline()は指定行の文字列取得。先頭行は0じゃなくて1 " substitute(a,b,c,d) は a =~ s/b/c/d と同等(たぶん) : let i = i + 1 : endwhile : return sum "戻り値はreturnで返す。Cと一緒。 :endfunction :command! -range=% CountChar :echo "Count of characters: " . <SID>CountChar(<line1>, <line2>) "command! で上書き。定義されるコマンド名は CountChar で別に関数名と同じにしなくちゃいけない "という決まりがあるわけじゃない。-range=% とすると <line1> に最初の行 <line2> に後の行が格納される。 "<SID>はしらん。と。
49 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/24 23:14] 41.5 式の実行 今んところコマンドは全部 Vim から直接実行されてたわけなんだが, ":execute" コマンドを使えば式の結果を実行する事が出来るぞ.こいつを使う とコマンドを作って実行する時にカナリ便利!! 例として,変数に含まれてるタグまでジャンプするのを挙げてやろう. :execute "tag " . tag_name "." は "tag " という文字列と, "tag_name" という変数に格納されてる値 を結合するのに使ってるんだぞ.つまり "tag_name" って変数の値が "get_cmd" だったとすると, :tag get_cmd っていうコマンドが実行される事になるわけよ. ":execute" コマンドはコロンコマンド(colon commands)しか実行出来ねーから な.":normal" コマンドを使えばノーマルモードのコマンド(Normal mode commands)が実行出来るぞ.でもその場合は引数は式じゃなくって,コマンドと なる文字だからそこんとこ分かっとくよーに.つまり, :normal gg=G ってやると,最初の行にジャンプしてから "=" の操作によって最後の行までを 整形するってわけ. ":normal" を式と一緒に使いたければ,":execute"と組み合わせればいいぞ. つまり, :execute "normal " . normal_commands ってやればいい."normal_commands" に格納されてる値はノーマルモードの コマンドになる文字じゃないとダメなのは当然な. ":normal" コマンドへの引数は完璧なコマンドじゃなきゃダメだぞ.そーしねーと Vim は 引数の最後まで実行した後はそのままそのコマンドを終了しちまうからな. # つまり,引数で指定されたコマンド以上の事は何一つとして余計な事は # しないって意味でしょうな,たぶん. 例えば,挿入モードを始めて,そこから抜け出すなんて事も出来る. :execute "normal Inew text \<Esc>" これで,カレント行に "new text " っていう文字列を挿入するぞ.特殊キー "\<Esc>" を使ってるところに御注目あれ.こーすれば実際のエスケープ文字を スクリプトに書かなく済むわけだ.
50 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:滅入り苦しみます!! [01/12/24 23:16] 今日はこれだけにしときます. あー,ヤダヤダ.世間様は楽しんでるんだろうなァ・・・
51 名前:実話 mailto:sage [01/12/25 00:07] KoRoN さんは今ごろセックスにふけってますよ
52 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/26 00:53] なんか一気にモチベーツョン下がった… なんで漏れはこんななんだろう… ハァ…………
53 名前:名無しさん@お腹いっぱい。 [01/12/26 01:03] >>52 がんばってage
54 名前:あぼーん mailto:あぼーん [あぼーん] あぼーん
55 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/26 02:19] 今日はなんかやる気無くしちゃったのでお休み. 明日からは忘年会地獄の三連荘(しかも女っ気ゼロ)だからたぶん連休になります. ご容赦あれ. >53 ぐすっ…うっうっうっ…こんなヲレに愛の手を…
56 名前:1 [01/12/27 00:29] foo.vim にある DoSp() の解読。 " 文字列中の<C-U>のような特殊文字を解釈して値を返す方法(?) fun! DoSp(str) let s = substitute(a:str, '.*\<C-U>', "", "") return s endfun :echo DoSp("Hello<C-U>World") World 特殊文字<C-U>でHelloが消されたと。 でも <C-U> に意味があるんじゃなくて単に "〜<C-U>" が "" に置換されただけちゃうんかと。 まーええか。寝よ。
57 名前:1 [01/12/27 22:24] " 入力モードにおける入力文字列を評価。特別文字<C-U>および<C-N>のように、入力 " モードで実行されるでしょう。生の<Esc>特徴は予測不能の結果を生むでしょう(Exciteより) fun! EvalInput(string) new execute "normal a" . a:string . "\<Esc>ggyG" q! return @" endfun new は新しいウィンドウ作成 execute は引数の結果をコマンドとして実行。詳しくは>>49 a:string の a: は引数を参照するから付ける。 . は文字列の連結。 string が "Hello" なら normal aHello\<Esc>ggyG が実行されて Hello が入力されて先頭(gg)から最後(G)までをヤンク(y)。 ちなみに ggyG は ggVGy でもいいけどチョトかっこ悪い。 q! はウィンドウを強制的に閉じる。 @ はレジスタ参照 " はヤンクのされたのが入っとるレジスタ。それが戻り値と。 今回もなにに使うのかよくわからんスクリプトじゃった。
58 名前:1 [01/12/29 13:10] 引き続き foo.vim の解読。 " HTMLの対応するタグにジャンプする fun! HTMLmatch() if getline(".")[col(".")-1] !~ "\\a" normal! % return endif execute "normal ?\\A\<CR>" normal lye if getline(".")[col(".")-2] == '/' execute 'normal ?<\s*' . @" . "\<CR>l" else execute 'normal /<\s*\/' . @" . "\<CR>ll" endif endfun nmap % :call HTMLmatch()<CR> getline(".") はカレント行取得。col(".") はカーソルのカラム値取得。(なんで1か ら始まるんだろう・・・) 正規表現 \a はタグ名にヒットさせる為の [A-Za-z] の事で マッチしないと通常の % を実行。?は後方検索。\A は [^A-Za-z] だからタグの< の 部分に移動。lye はでタグ名に移動(l)してからヤンク(ye)。んでカーソル前が / な ら終了タグなので ?で後方タグ検索。/ じゃなければ前方タグ検索と。 nmap はノーマルモード時に有効なコマンド割り当てで、% をタイプされたら :call HTMLmatch()<CR> が自動的に実行されると。 これは結構勉強になったなー
59 名前:1 [01/12/30 15:07] バッファに入った時、自動的に HelloWorld ダイアログを出す方法。 augroup Foo autocmd BufEnter *.cpp call confirm("HelloWorld", "OK") augroup END augroup 適当なグループ名 〜 augroup END の中で記述。 autocmd の引数は順に、どんな時? 対象ファイル どうする? この機能があるから拡張子に対応したシンタックスハイライトが 自動設定されたりするわけかぁ。 だんだんVimの謎が解けてきた。
60 名前:名無しさん@お腹いっぱい。 mailto:sage [01/12/30 18:06] なんか結構簡単に書けそうな気がしてきた。 もうちょっと勉強してみます。
61 名前:1 [01/12/31 14:04] 引き続き foo.vim の解読。 class Klass { などとタイプすると、 //-------------------- class Klass class Klass { }; となるスクリプト。 まず発動の準備。 augroup Foo autocmd BufEnter *.cpp,*.h inoremap { {<Esc>:call ClassHeader("-")<CR>a autocmd BufLeave *.cpp,*.h iunmap { " Keep your braces balanced!}}} augroup END *.cpp または *.h のバッファに移動した瞬間に挿入モードの時に { を タイプすると、どさくさに ClassHeader("-") を実行する。 バッファから抜けた時(BufLeave)には { での発動を解除。 fun! ClassHeader(leader) if getline(".") !~ "^\\s*class" return endif normal yyP$x let width = 80 if exists("&tw") let width = &tw endif execute "normal " . (width-virtcol(".")-3) . "I" . a:leader . "\<Esc>" execute "normal a \<Esc>" execute "normal I//\<Esc>" " Keep your braces balanced!{ execute "normal! jo};\<Esc>" normal k$ endfun 行頭に空白が含まれるかもしれない class がある行じゃなかったら終了。 で、行を二重化(yyP)して、行末移動($)して "}" を削除(x)。 widthはデフォルトで80にしたけど、tw オプションがあればそっちを有効に。 virtcol(".") は画面上のカーソルX座標。col(".") とはチョット違う。 で、"60I-<ESC>" みたいなのが実行されて - がたくさん挿入されて "a <ESC>" は右隣に一文字スペース挿入して、下移動(j)、下に一行挿入(o)して }; を入力して、上の行の最後に移動(k$)。 って、これじゃ読んでる人わけわからんだろうーな。 ちなみに tw オプションが 0 なら上のスクリプトは "-" を負の個数分挿入する事に なってうまく動作しないので exist("&tw") && &tw != 0 にしたほうがいいのかも。 あと、ハイライトが崩れないようにコメントで調整しているところもポイント! なんかスクリプトの要領が若干つかめてきた感じがするなー
62 名前:1 mailto:sage [01/12/31 14:08] >行末移動($)して "}" を削除(x)。 は >行末移動($)して "{" を削除(x)。 でした。
63 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [01/12/31 14:34] >>61 Vim6向け補足 > *.cpp または *.h のバッファに移動した瞬間に挿入モードの時に { を > タイプすると、どさくさに ClassHeader("-") を実行する。 > バッファから抜けた時(BufLeave)には { での発動を解除。 Vim6ではバッファ毎にマップを指定できるのでftplugin/c.vimに (ftpluginはUNIXなら$HOME/.vim/ftplugin、Winなら$VIM/vimfiles/ftplugin) :inoremap <buffer> { {<Esc>:call ClassHeader("-")<CR>a と書いておけば'filetype'が"c"の時に自動的に読み込まれる。だからaugroup Fooは 要らない。 # 'filetype'がcppの時は$VIMRUNTIME/ftplugin/cpp.vimの記述から'runtimepath'の # c.vimが読み込まれるようになっているのでc.vimだけで良い。 あと<silent>フラグも指定すればマップ実行時にコマンドラインが汚れることもなくて 更にハッピー。例: :inoremap <silent> <buffer> { {<Esc>:call ClassHeader("-")<CR>a
64 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/31 15:57] 41.6 関数を使う Vim は沢山の関数を定義してて,んでもって大量の機能を提供してるわけよ. まぁちぃとばかりこのセクションで例を挙げてやろう.全部のリストは |functions| を見ておくれ. 関数は ":call"コマンドで呼び出されるぞ.引数はカッコの中にカンマで区 切って渡すべし. 例) :call search("Date: ", "W") この例は search() 関数を "Date: " と "W" という引数を渡して呼ぶぞ. search() 関数は最初の引数を検索パターンとして使い,二番目の引数をフラグ として使うぞ."W" フラグはファイルの最後まで検索が行ったらもう上には 戻って来ないようにするフラグ(doesn't wrap around the EOF)な. 関数は指揮の中で呼ぶ事も出来るぞ. 例) :let line = getline(".") :let repl = substitute(line, '\a', "*", "g") :call setline(".", repl) getline() 関数は現在のファイルの行を得るぞ.引数には行数を指定すべし. この場合は "." が使われてるけど,コイツはカーソルのある行っつー意味にな るぞ. substitute() 関数は ":substitute" コマンドと同じよーな事をするぞ.最 初の引数は関数を適用する文字列で,二番目の引数は置換されるパターン, 三番目が置換する文字列,そんで最後の引数にはフラグを指定すべし. setline() 関数は第一引数で指定された行の内容を第二引数で指定された文 字列にセットするぞ.つまり,この例ではカーソルのある行の内容を substitute()関数の結果で置き換えるようになってるわけだ.んだからこの 三行は :substitute/\a/*/g と同じ事をやるってわけね.こーやって関数を色々使えば substitute() を呼ぶ前や後にもっと色々やって面白い事が出来るようになるぞ.
65 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/31 15:58] <<<関数紹介>>> まぁ沢山関数はあるわけなんだが,使用目的別にちょいと列挙してみようか. アルファベット順のリストは |functions| を見てくれ. CTRL-] を関数名の 上で入力すればその関数の詳細なヘルプに飛べるぞ. 文字列操作: char2nr() 文字から文字コードを得る nr2char() 文字コードから文字を得る escape() 文字列中の文字達を'\'を使ってエスケープする strtrans() 文字列を表示可能な形に変換する tolower() 小文字に変換 toupper() 大文字に変換 match() 文字列中でパターンにマッチする場所を得る matchend() 文字列中で最後にパターンにマッチする場所を得る matchstr() 文字列中でパターンにマッチする文字列を得る stridx() 文字列に含まれる部分文字列の位置を得る strridx() 文字列に含まれる最後の部分文字列の位置を得る strlen() 文字列の長さを得る substitute() 文字列中でパターンにマッチしたものを置換 submatch() ":substitute" 中で特定のマッチを得る(n番目の括弧の中とかそーゆーヤツ) strpart() 部分文字列を得るget part of a string expand() 特殊キーワードを展開する(%=>現在のファイル名とか) type() 変数の種類を得る カレントバッファのテキストに適用: byte2line() あるバイト数の行番号を得る line2byte() ある行までのバイト数を得る col() マークやカーソル位置の列番号を得る(tab を 1 とカウントするとか) virtcol() マークやカーソル位置のscreen columnを得る(tab を tabwidth 分だけカウントするとか) line() マークやカーソル位置の行番号を得る wincol() カーソル位置のwindow columnを得る(set nu の数字とかも含んでカウント) winline() カーソル位置のwindow lineを得る getline() バッファから行を得る setline() バッファ中の行を置き換える append() {lnum} で指定された行の後に{string}を追加する indent() 指定された行のインデント数を得る cindent() 指定された行のインデント数を cindent に従って得る lispindent() 指定された行のインデント数を lisp に従って得る nextnonblank() 次の空行でない行の行番号を得る prevnonblank() 手前の空行でない行の行を得る search() パターンにマッチする行を得る searchpair() find the other end of a start/skip/end # 対応する if とかを探すやつ.どう訳していいか分からん.
66 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [01/12/31 15:59] とりあえずちょっと復活. でもなんかこの関数列挙あんま意味無いよーなあるよーな. まぁ訳してるヲレ自身は詳細のヘルプ見たりして勉強にはなるから いいんだけど.
67 名前:1 mailto:sage [01/12/31 21:32] 吉野家で「大盛りねぎだく玉」を頼んで 殺伐として帰る2chのイベントに参加してきたよ(w >>KoRoNさん 補足どうもです。 バッファローカルで設定出来るってことは BufLeave での設定も 必要ないってことなんですかね。 ちなみにVim6スクリプトお勉強、といいつつマニュアルは 5.7の日本語化されたのしか読んでなかったりします(ぉ >>へっぽこ訳者さん やっぱり、人の作った(書いた)のを漠然と読むより自分で 調べた時に、身につくような気がしますねぇ。 でもまぁ、お勉強仲間がいると切磋琢磨できるので、 気にせずマイペースでカキコしちゃってください。
68 名前:名無しさん@お腹いっぱい。 mailto:sage [01/12/31 21:48] 今までQX一辺倒だったけどここ見て急にVIMが使ってみたくなったのです(●´ω`●) ここに書かれてることスクリプトってWindowsでも共用なのですか?
69 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [01/12/31 22:02] >>67 おおお。で、どうでした?。殺伐としてましたか?。吉野家の「ねぎたく禁止令」はデ マでしたか?。ちょっとレポートが聞きたかったり(苦笑)。なおBufLeaveでの設定も 勿論この例では要りません。 >>68 大丈夫です。使えます。Vimはキー操作が一般のエディタとはあまりにかけ離れてい てきっと戸惑うこととは思いますが、幸運な出逢いであることを願っています。 日本語Windows版のダウンロードはこちらからどうぞ www.kaoriya.net/
70 名前:1 mailto:sage [01/12/31 23:07] >>69 殺伐としてましたねぇ。んで突然「水きぼーん」の声。もうワライ堪えるのが大変。 詳しくはこちら↓今見たら、なんか元旦もやるとかいってるし(w 大晦日は殺伐と吉野家へ(集合)その7 corn.2ch.net/test/read.cgi/entrance/1009805196/ >>68 OSには依存しないから大丈夫。 Winで覚えたことはLinuxになってもそのまま活かせるし。
71 名前:名無しさん@お腹いっぱい。 [01/12/31 23:11] なにやら新ルール { つゆだくを頼むヤツがいたら鼻で笑ってやってください 牛鮭定食を頼むヤツがいたら舌打ちしてやってください }とさ
72 名前:1 [02/01/01 22:28] 今日も吉野家逝ってきた。あえて牛鮭頼んだら 隣の奴がブチ切れだったららしい(w というわけで<args>と<q-args>の違いの確かめる。 command! -nargs=* Test1 echo <args> command! -nargs=* Test2 echo <q-args> command! で Test1 と Test2 のコマンドを定義。 -nargs=* は引数を0個以上取る :Test1 "Hello" Hello :Test2 "Hello" "Hello" <q-args>は " をクォートしてくれていると。 そんだけ。 明日から牛の鳴き声が聞こえるような所に帰省します、、、。
73 名前:1 mailto:sage [02/01/01 22:32] なんか誤字が多いなー、牛乳飲も。
74 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [02/01/03 01:02] システム関数とファイル操作関数: browse() put up a file requester(GUI バージョン使ってないから分からん) glob() ワイルドカードの展開 globpath() 指定されたパス内で glob resolve() ショートカット先を探す(MS-Win) fnamemodify() ファイル名変更 executable() 実行可能プログラムがあるかどうか調べる filereadable() ファイルが読み込み可能かどうか調べる isdirectory() ディレクトリがあるかどうか調べる getcwd() カレントディレクトリを得る getfsize() ファイルサイズを得る getftime() ファイルの最終更新時を得る localtime() 現在時刻を得る strftime() 時間を文字列に変換 tempname() テンポラリファイル名を得る delete() ファイル削除 rename() ファイルリネーム system() シェルコマンドの実行結果を得る hostname() システムのホスト名を得る バッファ,ウィンドウ,引数リスト: argc() 引数リストの引数の数 argidx() 引数リストでの現在位置 argv() 引数リストから一つの要素を得る bufexists() バッファが存在するかどうかを調べる buflisted() バッファがバッファリストに存在するかどうかを調べる bufloaded() バッファがロードされているかどうかを調べる bufname() バッファ名を得る bufnr() バッファナンバーを得る winnr() カレントウィンドウのバッファナンバーを得る bufwinnr() バッファのウィンドウナンバーを得る winbufnr() ウィンドウのバッファナンバーを得る getbufvar() バッファの変数を得る setbufvar() バッファの変数を設定する getwinvar() ウィンドウの変数を得る setwinvar() ウィンドウの変数を設定する
75 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [02/01/03 01:03] なんか訳しててあんま楽しくない個所なんで今日はここまで(苦笑)
76 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/03 02:00] 陰ながら応援してますよ、がんばってください。
77 名前:KoRoN@Vim%Chalice ◆ALICEsdk [02/01/03 10:39] >>75 eval.txtの翻訳の時、同じ気持ちになった(苦笑)
78 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [02/01/03 23:31] Folding: foldclosed() ある行のfoldが閉じているかどうかを調べる foldlevel() ある行のfoldの深さを調べる foldtext() 閉じている fold を表示する行の生成 シンタクスハイライティング: hlexists() ハイライトのグループがあるかどうかを調べる hlID() ハイライトのグループのIDを得る synID() ある位置における syntax ID を得る synIDattr() syntax ID の特定の属性を得る synIDtrans() translated syntax ID を得る 履歴: histadd() 履歴に要素を追加 histdel() 履歴から要素を削除 histget() 履歴から要素を得る histnr() 履歴の現在のインデックスを得る 対話: confirm() 選択肢の表示 getchar() ユーザからの入力(文字)を得る getcharmod() 最後に入力された文字のモディファイア(CtrlとかShiftとか)を得る input() ユーザからの入力(行)を得る inputsecret() ユーザからの入力(行)を得る(表示はしない) inputdialog() ユーザからの入力(行)を得る(ダイアログで) Vim サーバ: serverlist() サーバ名のリストを得る remote_send() コマンド文字列を Vim サーバに送信 remote_expr() Vim サーバで式を評価 server2client() クライアントに返信 remote_peek() Vim サーバからの返答があるかどうかを調べる remote_read() Vim サーバからの返答を読み込む foreground() Vim のウィンドウを全面へ移動 remote_foreground() Vim サーバのウィンドウを全面へ移動 Various: mode() 現在の編集モードを得る visualmode() 最後に使われたビジュアルモード("v" or "V" or "C-V") hasmapto() map が存在するかどうかを調べる mapcheck() マッチする map が存在するかどうかを調べる maparg() マッピングの実体(rhs)を得る exists() 変数,関数等が存在するかどうかを調べる has() vim が機能を備えているかどうかを調べる cscope_connection() cscope のコネクションがあるかどうか調べる did_filetype() check if a FileType autocommand was used eventhandler() イベントハンドラによって起動されたのかどうかを調べる getwinposx() GUI Vim ウィンドウの X 位置を得る getwinposy() GUI Vim ウィンドウの Y 位置を得る winheight() ウィンドウの高さを得る winwidth() ウィンドウの幅を得る libcall() 外部ライブラリの関数呼び出し(戻り値が文字列) libcallnr() 外部ライブラリの関数呼び出し(戻り値が整数値)
79 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [02/01/03 23:32] やっとツマランところ終了. KoRoN 殿のような方々の辛さを実感(苦笑)
80 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:sage [02/01/03 23:49] >>79 お疲れさん!!
81 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/05 22:00] 現在行から一番近い上か下のマークへジャンプするスクリプトを作ってみました。 皆様のおかげです。厨房くさいスクリプトですが思い切って、投稿してみます。 まずいとことかあったら教えてください。 行単位でしか見てないので、一行に複数のマークがあっても無視してます。 "マークにジャンプする function! JumpToMark(mode) let i = 0x61 if a:mode == "up" let s:LineNo = 0 endif if a:mode == "down" let s:LineNo = line("$") + 1 endif let s:LineNoOrg = line(".") let s:MarkChar = "" "a-z をチェック while i < 0x7b let s:x = line("'" . nr2char(i)) if (a:mode == "up" && s:LineNoOrg > s:x && s:LineNo < s:x) || (a:mode == "down" && s:LineNoOrg < s:x && s:LineNo > s:x) let s:MarkChar = nr2char(i) let s:LineNo = s:x endif let i = i + 1 endwhile if (a:mode == "up" && s:LineNo > 0) || (a:mode == "down" && s:LineNo < line("$") + 1) "移動 execute "normal `" . s:MarkChar echo "マーク" s:MarkChar "にジャンプ" else execute "echohl ErrorMsg" echo "該当するマークがない;;" echohl None endif endfunction ■使い方 "上のマークへ :call JumpToMark('up') "下のマークへ :call JumpToMark('down') なぜか画面のスクロールを伴うマークへのジャンプをした後の echo で出力した メッセージが表示されません(表示されて消える?) スクロールされた後でもメッセージが表示できるようにする方法はあるんでしょうか? win2000 のgvim 6.0 です。
82 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [02/01/06 00:45] 折角公開してくれたのだから少し細かくコメントしましょう。こういうのは全く無反 応だと公開した方・使っている方、両方にとってためになりませんからね。 > function! JumpToMark(mode) s:を使ってスクリプトファイルローカルに宣言しませう。 で、command SomeCmd call <SID>JumpToMark()な感じで呼び出すようにする。 > let i = 0x61 let i = char2nr('a')とかのほうが意味合いがしっかりする。 もしくはlet markchar = "abc...xyz"としてmarkchar[i]でアクセスするように。 後者のほうが移植性に富むからベター。 > if a:mode == "up" 演算子==は'ignorecase'の影響を受けるので==#とか==?とかも考慮する。 > let s:LineNo = 0 関数内のletは関数にローカルな変数になるので特に必要性がないのならs:は使わな い。(以下全変数同様) > endif > (中略) > if (a:mode == "up" && s:LineNoOrg > s:x && s:LineNo < s:x) || (a:mode == "down" && s:LineNoOrg < s:x && s:LineNo > s:x) この判定ロジック、もうちょっと工夫のしようがないかしら?。 同じような文字列の比較が何度も出てくる場合は簡潔に書き直せることが多い。 > let s:MarkChar = nr2char(i) > (中略) > execute "echohl ErrorMsg" なんでここexecuteしてるの?。生で実行できる。 > echo "該当するマークがない;;" > (中略) > :call JumpToMark('up') 前述のとおりcommandでコマンド定義するかmapすべし。 > なぜか画面のスクロールを伴うマークへのジャンプをした後の echo で出力した > メッセージが表示されません(表示されて消える?) マークでジャンプした後にredraw!で強制的に更新バッファをflushしませう。 Chaliceの中では多用しているテクニックです。 私からはこんなところです。
83 名前:81 mailto:sage [02/01/06 03:07] KoRoNさんにこんなに詳細にコメントを頂けるなんて感激です。 ありがとうございます。 このスレでvimスクリプト入門を果たしたので知らないことばかりですが これからも精進したいです。 修正したものを貼り付けます。 # マーク位置を判定 の部分は私の能力では簡潔に書き直せなかった;; "マークにジャンプする function! s:JumpToMark(mode) let markchars = "abcdefghijklmnopqrstuvwxyz" if a:mode ==? "up" let LineNo = 0 endif if a:mode ==? "down" let LineNo = line("$") + 1 endif let LineNoOrg = line(".") let MarkChar = "" let i = 0 "a-z をチェック while i <= (char2nr('z') - char2nr('a')) let x = line("'" . markchars[i]) "マーク位置を判定 if (a:mode ==? "up" && LineNoOrg > x && LineNo < x) || (a:mode ==? "down" && LineNoOrg < x && LineNo > x) let MarkChar = markchars[i] let LineNo = x endif let i = i + 1 endwhile if MarkChar != "" "移動 execute "normal `" . MarkChar redraw! echo "マーク" MarkChar "にジャンプ" else echohl ErrorMsg echo "該当するマークがない;;" echohl None endif endfunction "コマンド定義 command! JumpToMarkDown call <SID>JumpToMark('down') command! JumpToMarkUp call <SID>JumpToMark('up')
84 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [02/01/06 04:05] >>83 ナイスですねぇ。 > while i <= (char2nr('z') - char2nr('a')) ここだけwhile i < strlen(markchars)としたほうが良いでしょう。 私は変数名を大文字で始めるのは避けるようにしています。ユーザ定義コマンドや関 数名は大文字で始めなければなりませんよね。それとかぶって見づらいかなと思うわ けです。スタイルの問題なのですぐ宗教論争になってしまいますが一応参考意見とし て。
85 名前:81 mailto:sage [02/01/06 21:10] >>KoRoNさん > 私は変数名を大文字で始めるのは避けるようにしています。 確かにです。私もそうしたいと思います。 ほんとにありがとうございました。 これから vim online に逝ってきます。
86 名前:1 [02/01/06 21:42] >>81-84 うーん、いろいろ勉強になりますなー。 <SID>はスクリプトローカル関数を呼ぶ時の為のものだったのか、、、 で、引き続き foo.vim の解読。 2〜4行目のfooをbarに置換するには、 :2,4 s/foo/bar/g と書くけど 2 と 4 が変数a,bの場合、 :a,b s/foo/bar/g と書いてしまうと正常に動作しない。 それに対応するのが次のスクリプト。 command! -nargs=* Line \ | let Line_range = matchstr(<q-args>, '\S\+') \ | let Line_range = "(" . substitute(Line_range, ",", ").','.(", "") . ")" \ | execute "let Line_range = " . Line_range \ | execute Line_range . substitute(<q-args>, '\S\+', "", "") \ | unlet Line_range 使い方。 :let a=2 :let b=4 :Line a,b s/foo/bar/g あと範囲指定部分で演算が可能。 :Line a-1,b+1 s/foo/bar/g スクリプト解読。 -nargs=* は引数を0個以上取る。 行をまたいで定義するには \ で繋ぐ。 <q-args>は引数を一つの文字列として参照する "a,b s/foo/bar/g" \S\+ は1個以上の空白以外で matchstr は最初のにヒットするから、 matchstr("a,b s/foo/bar/g", '\S\+') は "a,b" がヒットする。 んで、ごちゃごちゃしているけど Line_range="(a).','.(b)" となって、次がポイント。 Line_range が execute で評価されて結果 "2,4" が Line_range に入る。 ちなみに let Line_range = execute(Line_range) などとは書けそうで書けない。 で、substitute(<q-args>, '\S\+', "", "") は a,b の部分を消して " s/foo/bar/g" が残る。 二つを連結して execute "2,4 s/foo/bar/g" が実行されると。
87 名前:1 [02/01/08 00:32] 逆転裁判(GBA)をやっとクリアした今日この頃。 じゃ、foo.vim解読の続き。 >>86 の別のやり方。 command! -nargs=* Range \ | execute substitute(<q-args>, '\(\S\+\)\s\+\(\S\+\)\(.*\)', \ 'let Range_range=\1.",".\2', "") \ | execute Range_range . substitute(<q-args>, '\S\+\s\+\S\+', "", "") \ | unlet Range_range a〜b行目を置換するには? :let a = 2 :let b = 4 :Range a b s/foo/bar/g ごちゃごちゃしている正規表現もよく見れば簡単。 \s は空白。\S は空白以外。+は前の文字が1個以上。 ()で囲ったのは置換文字列内で順に \1 \2 とかで参照出来る。 + と () には \ を付ける。 んで、let Range_range=a.",".b が実行されて変数が数値に展開されて、 execute "2,4" . " s/foo/bar/g" となると。
88 名前:1 [02/01/08 23:17] 可変長引数の参照方法。 fun! Foo(...) echo a:0 a:1 a:2 endfun :call Foo("A","B") 2 A B なんとも奇妙な感じがするけど、 a:1 から順に引数が入ってて a:0 に引数の数が入っていると。 ちなみに :call Foo("A") だと a:2 が参照出来ないのでエラーになった。
89 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/08 23:27] 初めて見てみたけどわけわかんないっす。 「じゃあ来るな」はナシよ。
90 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/08 23:30] >>89 馴れろ
91 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [02/01/08 23:56] >>88 変数の有無のチェックにexists()を使う方法もあります。 >>89 確かにVimとは、Vimスクリプトとはなんぞや、 とかいうリンクは出てなかったかもしれませんね。 まとめてくれると嬉しいかも。
92 名前:1 mailto:sage [02/01/09 01:41] >>89 漏れもわけわからんで(w ま、とりあえず>>2 からやってみよう。 踏み出せばその一足が道となり・・・(略 >>91 ナルホド。a:0 >= 2 と書くより、場合によっては 読み易さを考慮(?)して exists("a:2") と書く方法もありと。
93 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/09 02:04] コメントの書き方って説明がまだ出てきてないみたいなんですけど " で始まる行がそうなんでしょうか?
94 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [02/01/09 11:06] >>93 お察しのとおりです。
95 名前:68 mailto:sage [02/01/09 18:41] >>68 です。 やっとhjklに拒絶反応が出なくなりました。先は、、長いですね、、(●´ω`●)
96 名前:名無しさん@お腹いっぱい。 [02/01/09 22:17] 勉強age
97 名前:1 [02/01/10 01:05] foo.vim解読の続き。 カーソル位置移動と画面上の表示開始行をセットする コマンド文字列を取得するスクリプト。 ma 〜 `a に似てるけどちょっと違う。 fun! Mark(...) if a:0 == 0 let mark = line(".") . "G" . virtcol(".") . "|" normal! H let mark = "normal!" . line(".") . "Gzt" . mark execute mark return mark elseif a:0 == 1 return "normal!" . a:1 . "G1|" else return "normal!" . a:1 . "G" . a:2 . "|" endif endfun line('.')はカーソル行。virtcol('.')はカーソル桁。 G は指定行移動。| は指定桁移動。 引数なしで呼んでみると、 :echo Mark() normal!20Gzt30G8| このコマンド文字列を変数に保存しといて後で実行させれば元の位置に戻るという仕組みか。 20G は20行目にジャンプ。zt はその行を画面上での先頭に移動。 これで画面上での表示開始行がセットされる。 30G8| は 30行 8桁目に移動と。 引数1つの場合は指定された行番号でコマンド文字列を作る。 :echo Mark(100) normal!100G1| 引数2つの場合は指定された行と桁でコマンド文字列を作ると。 :echo Mark(100,30) normal!100G30| 実際に使う場合こんな感じ。 :let a = Mark() :exe a
98 名前:名無しさん@お腹いっぱい。 mailto:age [02/01/11 00:11] age
99 名前:1 [02/01/11 00:40] Mark() の続きで取得したコマンド文字列から、 行または桁を取り出すスクリプトの解読。 " 行取得 fun! Line(mark) if a:mark =~ '\dG\d\+|$' return substitute(a:mark, '.\{-}\(\d\+\)G\d\+|$', '\1', "") else return line(a:mark) endif endfun " 桁取得 fun! Virtcol(mark) if a:mark =~ '\d\+G\d\+|$' return substitute(a:mark, '.*G\(\d\+\)|$', '\1', "") else return col(a:mark) endif endfun 引数が 数字G数字| というフォーマットなら、、 Mark() で作ったコマンド文字列と見なして、 それ以外なら通常の関数に引数を渡す仕組み。 正規表現の初めて見る \{-} は最短一致する * らしい。 けど、どうして * を使うとまずかったのか、などということは深く考えない。 実際に試してみると、 :echo Line("normal!10Gzt20G30|") Virtcol("normal!10Gzt20G30|") 20 30 line() または col() としても機能する。 :echo Line(".") Virtcol(".") 31 23 ん?なんで Virtcol() のなかで呼ばれているのが、 virtcol() じゃなくて col() なんだろ? ま、いいか。
100 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [02/01/11 13:49] 「100ゲット!!」 だけじゃあんまりだから、ちょっとマメ知識を。 vimスクリプトで1行が長くなってしまった時に、改行を入れて先頭を \ にすると次 行に繋がっていると見なされる。C言語の行末の \ と一緒。 # なおvimスクリプトでは \ の直前の空白は無視されるのでインデント可能 ここまでは一般常識。ここからが本題。実は'cpoptions'に"C"フラグが含まれていな い時には、この \ が使えずエラーとなる。なので一般に公開したいスクリプトを書 くときには \ による行連結は使わないほうが良いかも。 # それともスクリプトごとに避ける設定があるのかしら?
101 名前:1 [02/01/12 02:24] foo.vim解読の為の予習。 偶然Vim6スレでも話題になっている行範囲を、 関数側で受け取るテスト。 関数名定義の最後に range と書くだけで行範囲を、 a:firstline と a:lastline で参照出来るようになるらしい。 さっそく受け取った範囲を表示する関数を作ってみる。 fun! RangeCheck() range echo a:firstline a:lastline endfun そのままつかうと現在の行だけが対象 :call RangeCheck() 10 10 範囲指定すると、ちゃんと範囲が受けとれている :3,7call RangeCheck() 3 7 全体行でも大丈夫。% は 1,$ と同等 :%call RangeCheck() 1 10 >>100 どもっ、でもなぜかCフラグが無いのに、 \が使えたので調べてたらCフラグの意味が逆?? それにしても options.txt すんげぇサイズ。 翻訳してくれてる人、大変だろうなぁ。
102 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [02/01/12 03:16] >>101 あ、逆でした。>>100 は'cpoptions'に"C"が含まれる時には行頭の \ が連結の意味に ならない、といので正しいです。
103 名前:mattn@Vim%Chalice mailto:sage [02/01/12 19:32] >>74 > resolve() ショートカット先を探す(MS-Win) あれ〜・・・ bram氏、docの変更忘れてんのかなぁ・・・(^^;) unix系はシンボリックリンクを解析するよう変更したはずのに・・・ と言っても訳は間違ってないのでsage
104 名前:1 [02/01/12 23:16] foo.vim解読の続き。 現在の文書から引数で指定した単語を最後の行に出力するスクリプト。 :%call Pippo('\\\a\+') とやって LaTex での辞書を作る為の単語を収集するのに使うらしい。 (LaTex使ったこと無いからよくわからんけど) fun! Pippo(...) range if a:0 let pat = a:1 else let pat = '\<pippo\d\+\>' endif let bot = line("$") execute a:firstline . "," . a:lastline . 'g/' . pat . '/copy $' if bot == line("$") return endif execute (bot+1) . ',$s/' . pat . '/&\r/ge' execute (bot+1) . ',$v/' . pat . '/d' execute (bot+1) . ',$s/.\{-}\(' . pat . '\)$/\1/e' endfun 選択したテキストがこれ。先頭のは :set nu で表示した行番号。 10 pippo1 aaa pippo2 bbb 11 pippo3 12 ccc そこで :10,12call Pippo() を実行すると :10,12g/\<pippo\d\+\>/copy $ が呼ばれ て、10〜12行目でpippoの後に数値がある単語が含まれる行を最後の行にコピーすると いう意味だから、最後の行が50だとこうなる。 50 51 pippo1 aaa pippo2 bbb 52 pippo3 copy はノーマルコマンドの p 同じような機能らしいから次行からペーストされる。 :51.$s/\<pippo\d\+\>/&\r/ge が実行される。& は検索文字列。\r は改行だから検索 文字列の直後に改行入る。 51 pippo1 52 aaa pippo2 53 bbb 54 pippo3 次に :51,$v/\<pippo\d\+\>/d の実行。v は検索されなかった行を返す。d は :delete の事だから、 51 pippo1 52 aaa pippo2 53 pippo3 次に :51,$s/.\{-}\(\<pippo\d\+\>\)$/\1/e は pippo数値 の単語だけを残すから、 51 pippo1 52 pippo2 53 pippo3 になると。ふぅ勉強になった。
105 名前:1 mailto:sage [02/01/12 23:29] copy 命令に感動したのでちょっと練習。 ■20〜30行目を100行目にコピーするには? :20,30copy 100 ■カレント行を2重化するには?(:normal Yp と同じ) :copy . ■全体行をを2重化するには? :%copy $ ■上の3つを短く書くと? :20,30co100 :co. :%co$ copy の仲間で move というのもあってこれがまた凄い。 コピーじゃなくて移動しちまう。 ■20〜30行目を100行目に移動するには? :20,30move 100 そんなところ。
106 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/13 01:45] This script is intended to provide an easy and quick way of sending e-mail messages from within vim vim.sourceforge.net/scripts/script.php?script_id=179
107 名前:名無しさん@お腹いっぱい。 mailto:age [02/01/13 02:11] age
108 名前:1 [02/01/13 23:28] >>106 のViMail.vimを使ってみようとしたけど、 sendmail使っててCygwinだと無くて動かないようだから 練習でblatjに変えてみた。 BlatJ www.piedey.co.jp/softs/blat182bj7.html 103,106c103,107 < let s:cmd = "cat " . s:tempfile < let s:cmd = s:cmd . "\| sendmail -- " . s:to . " 2>&1" < let s:error = system(s:cmd) < --- > let smtp_server = 'xxxx' " SMTPサーバー名を指定 > let mail_address = substitute(s:sender, '.*<\(.*\)>.*', '\1', '') > call system('blatj -install ' . smtp_server . ' ' . mail_address) > let s:error = system('blatj ' . s:tempfile . ' -t ' . s:to . ' -s ' . s:subject . ' -q') > 123a125 >
109 名前:1 [02/01/14 00:31] foo.vim解読の続き。 ALT+4 で行の最後の空白以外にカーソルを移動する方法 :map <M-4> 0:let@9=@/<Bar>set nohls<CR>/.*\S/e<CR>:let @/=@9<Bar>set hls<CR> 読みにくいのでバラしてみると下のようになる 0 :let @9=@/ :set nohls /.*\S/e :let @/=@9 :set hls 0 は行頭に移動。:let @9=@/ 〜 :let @/=@9 はレジスタ / を 9 に保存して復帰。 :set nohls 〜 :set hls は検索文字列ハイライトを一時的に無効化。 で残ったのが /.*\S/e でこれが最後の空白以外に飛ぶ処理をやっていると。 ちなみに /e をつけないとなぜか次の行にカーソルが飛ぶ。
110 名前:1 [02/01/14 21:56] foo.vim解読続き。 >>109 の別の方法 map <M-4> :call LastNonBlank()<CR> fun! LastNonBlank() let i = matchend(getline("."), '.*\S')-1 if i > 0 execute "normal!0" . i . "l" elseif i == 0 execute "normal!0" endif endfun 現在行で .*\S で最後にヒットする位置を取得して最初に 0 で行頭に移動してからそ の位置へ l で移動する。最初に 0 しないで | で直接指定カラムに飛べば if else は 必要無くなるような気がする。
111 名前:1 [02/01/15 23:22] foo.vim解読の続き。 ちなみにfoo.vimとはこれのことです。 vim.sourceforge.net/scripts/script.php?script_id=72 キーワードからパターンを剥いでタグにジャンプするスクリプト 例えば、 nmap <C-]> :call StripTag("Hello")<CR> と定義しておくと HelloWorld という単語の上で C-] した時、HelloWorld の Hello の部分が削除されて残った World でタグジャンプしてくれる! ・・・これがどんな時に役に立つのかよくわからないけど。 nmap <C-]> :call StripTag("xxx")<CR> fun! StripTag(pattern) let keyword = expand("<cword>") if keyword =~ '^' . a:pattern execute "tag!" . substitute(keyword, a:pattern, "", "") else execute "normal! \<C-]>" end endfun expand("<cword>") はカーソル位置の単語(キーワード)を返す。 指定パターンがキーワードの先頭からヒットしたらヒットした部分を消してタグジャンプ。 autowrite オプションを有効にしておくと tag 実行時に自動的にカレントのファイル が保存されるけど、tag! にすると保存されない。 パターンがヒットしなかったら通常の <C-]> を呼ぶと。
112 名前:1 [02/01/17 08:28] foo.vimの続き 拡張子が jsp のファイルを編集中 <scr と入力した瞬間に、 <script language="JavaScript"> function foo() { alert("Hello, world."); } </script> ↑ここまでふくれあがるスクリプト。 augroup Foo autocmd BufEnter *.jsp imap r r<Esc>:call JS_template()<CR>a autocmd BufLeave *.jsp iunmap r augroup END fun! JS_template() if getline(".") !~ '<scr$' return endif s/scr$/script language="JavaScript">/ append function foo() { alert("Hello, world."); } </script> . endfun>>61 にも登場した書き方で、*.jsp のバッファに入った時に、r を再定義してバッファ から抜けたら解除。Ver6.0からはバッファローカルで設定出来るからいちいち入った 時、出たときって書かなくてよいらしい(>>63 より) append は次の行から . だけを含んだ行の前までを入力する。 これはCのコメント生成とかにも使えるかな。
113 名前:1 [02/01/17 22:45] foo.vim続き。 C++ソースで << を次の行に続けて書いてると、 cout << "Hello" << "World" << endl; こんな風に << のカラムを一つ上の行に合わせて、 自動的にそろえていってくれるスクリプト。 augroup Foo autocmd BufEnter *.cpp imap < <<C-O>:call LineUpLT()<CR> autocmd BufLeave *.cpp iunmap < augroup END fun! LineUpLT() " 1行目や、<< だけを入力してない行ならなんもせん if line(".") == 1 || getline(".") !~ '^\s*<<$' return endif " 一つ上の行を取得して << が始まる位置を取得 let newline = getline(line(".")-1) let col = match(newline, "<<") if col != -1 " 上の行に << があったら << が始まる前までを取得して、全てスペースに置換し " て << を付け加える。 let newline = strpart(newline, 0, col) let newline = substitute(newline, '\S', " ", "g") . "<<" " それをカレント行にセットしてカーソルを最後に移動 call setline(line("."), newline) normal!$ endif endfun
114 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [02/01/17 23:26] まっつんさんのcalender.vim、次のように設定すると日本語暦。 vim.sourceforge.net/scripts/script.php?script_id=52 let g:calendar_mruler = '睦月,如月,弥生,卯月,皐月,水無月,文月,葉月,長月,神無月,霜月,師走' let g:calendar_wruler = '日 月 火 水 木 金 土' これに加えて「平成14年」とか「皇紀2662年」 とかいう表記ができたらまさにパーフェクト(苦笑)
115 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/17 23:54] それだったら縦書きとか るせま読に左らか右 とかも出来るようにしないと。
116 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/18 00:29] きれいなカレンダーにびっくり
117 名前:KoRoN@Vim%Chalice mailto:sage [02/01/18 14:24] >>115 rightleft時にMBを正しく捌けるようにするか(苦笑)
118 名前:1 [02/01/18 23:17] foo.vim解読続き。 指定パターンにマッチする行数を得るスクリプト。 例) Helloを含む行はいくつある? :echo Count("Hello") 10 fun! Count(pat) let num = 0 execute 'g/' . a:pat . '/let num = num + 1' return num endfun numを0で定義して g/ で検索したパターンが出現するたびに num をインクリメントしてそれを返すと。 # calendar.vim使ってます。
119 名前:1 [02/01/20 21:40] foo.vim解読の続き。 ハイライト設定一覧を新しいウィンドウでハイライト付きで確認出来るスクリプト。 fun! ShowHi() " a に hi の内容を取得 let save_more = &more set nomore redir @a hi redir END let &more = save_more " 新しいウィンドウでハイライト設定 new put a v/\h/d %s/.\{-}\(\h\w*\).*/syn keyword \1 \1/ %y a @a endfun hi はハイライト設定一覧を表示する。その時、画面が一杯になると表示が止まってし まうので more オプションを一旦保存して nomore に設定しておく。redir @a は、コ マンドの出力がレジスタ a にも入るようにする。だから hi の表示結果が a にも入 る。redir END でリダイレクトを停止。 次に new で新しいウィンドウを開いて a に入っている hi の結果をペースト。v/ の 部分は、単語の先頭が [A-Za-z] で始まらない行を削除。%s の部分は、ハイライト設 定をハイライト設定名自身に反映させるコマンドとなるように置換。例えば :syn keyword Visual save_more とするとsave_more の部分が選択範囲用の色になるみた い。%y a は全体をレジスタ a に入れる。ノーマルコマンドで ggVG"ay という方法も あるけど、%y a の方がずっと読みやすいな。で、コマンドとして @a を実行すると、 なんとレジスタ a の中のコマンドが一気に実行されてハイライトが反映される仕組み。
120 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/21 03:04] >1 お疲れ様です。 # ちょっと前に、ハイライト表示の定義をしようとして出来なかったのですが # もう一回チャレンジしようかな?