1 名前:名無しさん@お腹いっぱい。 [01/12/17 12:15] みんなでスクリプトを覚えよう
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 お疲れ様です。 # ちょっと前に、ハイライト表示の定義をしようとして出来なかったのですが # もう一回チャレンジしようかな?
121 名前:mattn@Vim%Chalice mailto:sage [02/01/21 09:54] >>118 > # calendar.vim使ってます。 どもです。 でも、実は使おうとおもって作ったわけじゃないんです。(^^;) 単に、cal を中呼びしてるスクリプトを見つけて、 「これならスクリプトだけでかける」と思ったのと M-x calendar があるなら :Calendar もあっていいかなと思って作り始めたのが、きっかけです。
122 名前:1 [02/01/21 21:09] foo.vim解読の続き。 指定関数の内容を新しいウィンドウで見るスクリプト。 fun! EditFun(name) " 指定関数の中身をレジスタ a に取得 let save_more = &more set nomore redir @a execute "function " . a:name redir END let &more = save_more " 新しいウィンドウに a をペーストして vim 用のハイライト設定 execute "sp " . tempname() put a set ft=vim endfun 前のスクリプトと似てるからあんまり書くことないけど、:function EditFun とすると EditFun の内容が表示されて set ft=vim でvim用のハイライト設定になると。 >>120 漏れもハイライト定義の方法はまだよくわかってないです。 foo.vimが終わったら覚えようかな。 >>121 へー、なんかEmacsに対抗して作ってるのかなとは思ってましたが(w
123 名前:mattn@Vim%Chalice mailto:sage [02/01/22 12:25] >>122 > ... なんかEmacsに対抗して作ってる ... って言いつつも emacs21 + navi2ch xyzzy + 2ch-mode が何時でも準備OKな状態だったりします。(w
124 名前:1 [02/01/22 19:58] foo.vim解読の続き。 ユーザーが独自に定義したモードラインを取得するスクリプト fun! GetModelines(pat, ...) " start と finish に範囲を求める let EOF = line("$") if a:0 > 1 let start = a:1 let finish = a:2 elseif 0 if a:1 > 0 let start = 1 let finish = a:1 else let start = EOF + a:1 + 1 let finish = EOF endif endif if !exists("start") || start < 1 let start = 1 endif if !exists("finish") || finish > EOF let finish = EOF endif " モードラインの行を n に取得 let n = 0 silent execute start . "," . finish \ 'g/' . escape(a:pat, "/") . "/let n=line('.')" " モードラインが見つかったら指定したパターンで置換 if n execute "normal!<C-O>" return substitute(getline(n), '.\{-}\(' . a:pat . '\).*', n.':\2', '') else echo return "0:" endif endfun これよくわかんねーな。 とりあえず前半は臨機応変な範囲指定に対応する処理 GetModelines(pattern, 100) ・・・先頭から100行まで GetModelines(pattern, -100) ・・・最後の100行 GetModelines(pattern, 50, 80) ・・・50行目から80行目まで GetModelines(pattern) ・・・全体行 んで、30行目に /* foo: bar=78 */ と書いておいて下のを実行すると、 :echo GetModelines('/\*\s*foo:\s*\(.\{-}\)\s*\*/') 30:bar=78 モードラインは g/ で検索されているから、その後の "normal!<C-O>" でモードライン にジャンプすると。でも、30:bar=78 を受け取ってどうすりゃいいのだろう。 30はいらないとして、bar=78 ってのを独自のオプションとして取り込めばいいのかなぁ。
125 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [02/01/23 02:44] 41.7 関数定義 Vim では独自の関数も定義出来るぞ.基本的には関数定義はこんな感じでやれば良し. :function {name}({var1}, {var2}, ...) : {body} :endfunction 注意: 関数名は大文字で始めるべし. とりあえず二つの値の小さい方を返す関数でも定義してみっぺかね.とりあえず最初の行は, :function Min(num1, num2) で,これは Vim に関数名が "Min" で,引数を"num1" と "num2" の二つ取るっ てことを宣言しとるっぺよ. まず最初はどっちが小さいかチェックせにゃいかんから, : if a:num1 < a:num2 と."a:" っつー接頭辞は Vim にこの変数が関数の引数だって事を宣言しと るだけぢゃ.んで,"smaller"という変数に,小さい方の数字を代入すれば OK ね,と. : if a:num1 < a:num2 : let smaller = a:num1 : else : let smaller = a:num2 : endif で,"smaller" って変数はローカル変数になるぞ.関数内で使われる変数は, "g:"とか "a:", "s:" とかって接頭辞が付かない場合はローカル変数になる からな. 注意: グローバル変数に関数内からアクセスする場合は "g:" って接頭辞を付ける べし.つまり,"g:count" を関数内から使うと,グローバル変数の "count" だ し,普通に "count" ってやったら,それとは別の関数ローカルの変数になるっ てわけよ.
126 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:滅入り苦しみます!! [02/01/23 02:44] んで, ":return" 文を使って小さい方の値をユーザに返しましょーかね. 最終的にはこの関数は : return smaller :endfunction ってな感じで終了するわけだ.まぁ完全な形で書くとこんな感じになるべさ. :function Min(num1, num2) : if a:num1 < a:num2 : let smaller = a:num1 : else : let smaller = a:num2 : endif : return smaller :endfunction ユーザ定義関数はビルトイン関数と同じように呼べるぞ.名前だけは違うけど. だから,Min 関数はこんな感じで呼べるわけよ. :echo Min(5, 8) って. >Only now will the function be executed and the lines be interpreted by Vim. 何言ってるんだ?ココは.分からん(鬱 もし未定義の関数や変数使ってたり,なんか間違いがあったらエラーメッセー ジが表示されるぞ.関数定義の時点ではエラーは検出されないんだよねー. もし関数が ":endfunction" まで到達しちゃったり, ":return" が引数無しで 呼ばれたりしてたら関数はゼロを返すぞ. 既にある関数を再定義する場合は ":function" コマンドに ! を使えばいい. つまり, :function! Min(num1, num2, num3) って事ね.
127 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:age [02/01/23 02:46] ふぅ,お久しぶりでヤンス. 最近忙しいでヤンスよ. まぁ暇が出来たらまたちょくちょくやるっす. そんぢゃ.
128 名前:mattn@Vim%Chalice mailto:sage [02/01/23 17:53] お遊びスクリプト・・・ if has('win32') && ($OSTYPE=='cygwin' || $TERM=='cygwin') let cygwin_root = "c:\\cygwin" let iargs = 0 let nargs = argc() while iargs < nargs let varg = argv(iargs) if varg =~ '^/cygdrive/' let varg = substitute(varg,'^/cygdrive/\(\a\)/\(.*\)','\1:/\2','g') elseif varg =~ '^/' let varg = cygwin_root.varg endif let varg = substitute(varg,'/','\\','g') exec "argadd ".varg let iargs = iargs + 1 exec "argdelete ".iargs endwhile let iargs = 0 while iargs < argc() silent argdo! rewind let iargs = iargs + 1 endwhile unlet iargs unlet nargs unlet varg unlet cygwin_root endif
129 名前:1 [02/01/23 20:43] Cygwin形式のパスをDOS形式に変換するスクリプトですかー とりあえず、 argadd - 引数リストにファイル追加 argdelete - 引数リストからファイルを削除 argdo! - 引数の全てのファイル対してコマンドを実行 を覚えました。 これらって5.7のマニュアルには見つからなかったから最近のコマンドかな。
130 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:sage [02/01/23 20:56] 余談ですけど、最近のCygwinってDOS形式(但しディレクトリセパレータは/)のパスを 受け付けますよね。おかげで'shellslash'との親和性がスゴク良い。 % ls d:/HOME/vim/vim60 とか出来ますから。 >>129 そうですね。6.0の新機能です。 :help new-argument-list
131 名前:1 mailto:sage [02/01/23 22:24] >>43 のAllargs関数を見つけた時はずいぶん喜んでたんだけど、 既にそれに代わるargdoってのがあったのかぁ。 それはいいとしてversion6.txt読んでたら gi って新コマンドを発見。 前回入力し終えた所にジャンプして i してくれる。これは(・∀・)イイ!!
132 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/24 01:19] 関係無いかもしれんけど cygwinで cygpath っちゅうコマンドも便利だよ。 # 外出か?
133 名前:1 mailto:sage [02/01/25 02:15] 糞みたいな残業強制させられて今タクシーで帰宅。 これじゃお勉強する暇ねーよ。あーあ。
134 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:sage [02/01/25 10:37] >>133 お疲れさんです(^-^;
135 名前:1 [02/01/26 22:43] foo.vim解読の続き。 入力モードの時に F7 で独自に指定したタブを挿入するスクリプト。 imap <F7> <C-R>=VarTab(virtcol("."),8,17,26,35)<CR> fun! VarTab(c, ...) " 最初のタブ位置を探す let i = 1 while i <= a:0 execute "let num_sp = -a:c + a:" . i if num_sp > 0 break endif let i = i + 1 endwhile if i > a:0 return "" endif " スペースを挿入する let spaces = " " let len = 1 while len < num_sp let spaces = spaces . spaces let len = len + len endwhile return strpart(spaces, 0, num_sp) endfun 可変長引数の部分でタブストップするカラム 8,17,26,35 が指定されている。 最初のタブを探す部分は定石として覚えとこ。 strpart() は spaces のインデックス 0 から num_sp 個分を返す関数。 上の場合 spaces の全体を返すから使う必要ない気もするけど。 そんだけ。
136 名前:名無しさん@お腹いっぱい。 [02/01/27 04:17] これvimスクリプトかどうか分かんないんだけどステータスラインに 文字コードとか改行コードを表示させるって出来る? もしかして、関数つくって呼ぶとかそんな方法ですか? つか、自分で調べろって?・・・スマソ。
137 名前:1 [02/01/27 11:16] >>136 set statusline=%<%f%h%m%r%=%b\ 0x%B\ \ %l,%c%V\ %P ↑これでできた(:help statusline より) お勉強スレなので解説付き 重要なカレントの文字コードは %b と %B で解る %b - 10進数 %B - 16進数 他のは %f - ファイル名 %h - ヘルプを見ている時だけ[ヘルプ]になる %m - nomodifiable の時 [-] になる %r - readonly の時に [RO] になる %l - 行番号 %c - カラム値 %V - 選択部分のライン番号。カラム値と同じ場合は表示されない? (再現できず) %P - ページの位置らしい 先頭 or 末尾 んで表示制御が、 %< - 1行に入りきらなかった時にこの位置から表示する?? (再現できず) %= - これ以降を右側に表示 あとスペースは \ でエスケープ
138 名前:136 [02/01/27 13:09] >>137 いやそうじゃなくて 文字コード = euc-jp, sjis, jis, utf8 改行コード = CRLF, LF, CR を言いたかったのです・・・。 説明の仕方が悪かったですかね・・・。
139 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [02/01/27 13:25] >136 function! GetStatusEx() let str = '' let str = str . '[' . &fileformat . ']' if has('multi_byte') && &fileencoding != '' let str = str . '[' . &fileencoding . ']' endif return str endfunction set statusline=%n:\ %<%f%y\ %m%r%h%w%{GetStatusEx()}\ %l,%c\ %P 確かコレ KoRoN 殿に教わったんだと思ったけど,こんな感じでどーよ? ゴチャゴチャ付いてるのはヲレのヤツそのまんまだからっつーことで御免 翻訳しなくっちゃなー
140 名前:1 [02/01/28 22:51] foo.vim解読の続き。 HTMLファイル編集中にバックスペース一発で とかを一気に消すスクリプト。 augroup Foo autocmd BufEnter *.html,*.htm inoremap <BS> x<Esc>:call SmartBs('&[^ \t;]*;')<CR>a<BS><BS> autocmd BufLeave *.html,*.htm iunmap <BS> augroup END fun! SmartBs(pat) let init = strpart(getline("."), 0, col(".")-1) let len = strlen(matchstr(init, a:pat . "$")) - 1 if len > 0 execute "normal!" . len . "X" endif endfun カレント行のカーソル位置より前の文字列を init に取得。 その文字列の最後に みたいな文字列があればその文字数を len に取得。 みたいな文字列が無ければ matchstr は "" を返し、len は 0 になる。 だから len > 0 の時、その数だけバックスペースすれば が消える仕組みらしい。
141 名前:1 mailto:sage [02/01/28 22:55] ありゃりゃ消えとるがな。 &nbsp の事です。
142 名前:名無しさん [02/01/29 00:41] Buf* の訳というか説明があるとイイナって思った。 BufNewとBufNewFileの違いが分からんし。
143 名前:ヘッポコ訳者 ◆xBY/hgW2 [02/01/29 00:45] >142 さぁ,言い出しっぺの法則ぢゃ!!ガムバレ(・∀・)!!! # ヲレ今風邪で寝込んどる.スマソ
144 名前:142 [02/01/29 00:48] ウワー。 マジ勘弁。英語できないし。 誰かにパス。なんていうのはアマい(・∀・)?
145 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [02/01/29 01:03] >142 しゃーないのぅ autocmd.txt を見ると, BufNewFile: 存在しないファイルの変数を始めた時. スケルトンからの読み込み時でも使われる. BufNew: 新しいバッファを作成した直後. バッファ名をリネームした時にも使われる. バッファがバッファリストに追加された時は BufAdd も 実行されるぞ. 注::この autocommand が実行された時はカレントバッファ"%" はその時作成されようとしてる"<afile>" とは違うよん とりあえず上記二つはこんな感じかな
146 名前:1 [02/01/29 23:40] foo.vim解読続き。 sed の y コマンドを実現するスクリプト 使い方(aをxにbをyにcをzに置換するには?) :Transform abc xyz (カレント行を対象) :%Transform abc xyz (全体行を対象) 素直にsedを使うと? :.!sed 'y/abc/xyz/' :%!sed 'y/abc/xyz/' command! -nargs=* -range Transform <line1>,<line2> call Transform(<f-args>) fun! Transform(old, new, ...) if a:0 let string = a:1 else let string = getline(".") endif let i = 0 while i < strlen(a:old) && i < strlen(a:new) execute "let string=substitute(string, '".a:old[i]."','".a:new[i]."','g')" let i = i + 1 endwhile if a:0 return string else call setline(".", string) endif endfun -range を付けているから <line1> と <line2> が有効に。 <f-args> は空白で区切った引数が自動的に , 区切りになって関数へ渡される。 だから :Transform abc xyz は Transform("abc", "xyz") となって関数が呼ばれる。 んで↓のように一文字ずつ対応するように置換されていく。 let string=substitute(string, 'a', 'x', 'g') let string=substitute(string, 'b', 'y', 'g') let string=substitute(string, 'c', 'z', 'g') setline(".", string) はカレント行を string の内容にする。 あと第3引数があればカレント行よりそっちを優先するので別のスクリプトからも使い まわせる。 :echo Transform("abc", "xyz", "aabbcc") xxyyzz
147 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:koron@tka.att.ne.jp [02/01/30 00:19] >>146 便利そうなスクリプトなので日本語対応版を書いてみました。ちょっと圧縮バージョ ンなので見難いかもしれないけどこれも勉強になるでしょう。 # 香り屋版には組み込むかも。 command! -nargs=* -range Transform <line1>,<line2>call Transform(<f-args>) function! Transform(from_str, to_str, ...) if a:0 | let string = a:1 | else | let string = getline(".") | endif let from_str = a:from_str | let to_str = a:to_str while 1 let from_char = matchstr(from_str, '^.') if from_char == '' | break | endif let to_char = matchstr(to_str, '^.') let from_str = strpart(from_str, strlen(from_char)) let to_str = strpart(to_str, strlen(to_char)) let string = substitute(string, from_char, to_char, 'g') endwhile if a:0 | return string | else | call setline(".", string) | endif endfunction
148 名前:ヘッポコ訳者 ◆xBY/hgW2 mailto:sage [02/01/30 00:26] <<<範囲(Range) を使う>>> ":call" コマンドには行範囲(line range) を指定する事も出来るよん. This can have one of two meanings. 関数が "range" キーワードと一緒に定義されてたら,その関数は行範囲を扱う んだな. そーゆー関数は,"a:firstline" と "a:lastline" っつー二つの引数が渡さ れる事になるぜぃ.この二つは関数が呼ばれた時に指定されてる行範囲の最 初と最後の行数でござるよ. 例: :function Count_words() range : let n = a:firstline : let count = 0 : while n <= a:lastline : let count = count + Wordcount(getline(n)) : endwhile : echo "found " . count . " words" :endfunction この関数は, :10,30call Count_words() と,こんな感じで呼び出せる. この場合関数は一回のみ実行されて,その行範囲に含まれてる単語数を出力するよん. # 訳者注: Wordcount っつー関数は自前で作らんとダメっぽい. # ついでに, while の中に let n = n+1 が要るような気もするんだが・・・ ちなみに"range" keyword 無しで定義した関数で行範囲を扱う事も出来て, 例: :function Number() : echo "line " . line(".") . " contains: " . getline(".") :endfunction これを :10,15call Number() って呼んでやると,この関数が 6 回呼ばれるよーになるのだ.
149 名前:ヘッポコ訳者 ◆xBY/hgW2 [02/01/30 00:27] 訳注のところってもしかして嘘書いてます? getline は行数 n をインクリメントしたりしないですよねぇ…? 風邪引いてるんで今日はここまで
150 名前:KoRoN@Vim%Chalice ◆ALICEsdk mailto:sage [02/01/30 00:34] >>149 試せばすぐわかりますがインクリメントはきっと必要でしょう。 # 丁度Transformもrangeの無い例になってて、タイムリーですなぁ
151 名前:名無しさん@お腹いっぱい。 mailto:sage [02/01/30 01:31] >146 ご苦労様です。 >sed の y コマンドを実現するスクリプト cygwin で man sed したんですが、s コマンドと y コマンドの違いがいまいちわからなかったです。 わかりやすく説明してるようなサイトなど教えていただけないでしょうか? スレ違いでごめんなさい。
152 名前:ヘッポコ訳者 ◆xBY/hgW2 [02/01/30 01:43] >KoRoN殿 ええ,一応試してはみたんですよ,ハイ(^^; ただなんとなくちょっと自信が無かったので… >151 日本語 man より [2addr]y/string1/string2/ string1 に現れるパタンスペース中の文字を string2 の対応した文字に 置換する。たとえば、`y/abc/ABC/' はパタンスペース中の文字 a、b、c を大文字に置換する。バックスラッシュと改行以外のすべての文字を区 切りとして用いることができる。 string1 、 stirng2 中では、`\' 直 後の改行以外の文字はリテラルに解釈され、`\n' は改行と解釈されま す。 あぁ,コリャ分からんかもね. つまり,s/sage/mona/ だと,'sage' が 'mona' に置換されるけど, y/sage/mona' だと s->m a->o g->n e->a ってな感じで置換される.分かるかな?これで. 例を挙げると,'sega' は s/sage/mona/ だと何も起こらんけど, y/sage/mona/ だと 'mano' になるのよ.
153 名前:151 mailto:sage [02/01/30 02:04] >152 ヘッポコ訳者さん、ありがとうございます。 試してみてわかりました。キャラクタ単位で複数の置換を一度にするって感じでしょうか? 風邪はやってますね。翻訳がんばってください。では
154 名前:1 [02/01/31 01:08] foo.vim解読の続き。 指定パターンを検索してセレクトモードで囲むスクリプト command! -nargs=1 Search call Search(<f-args>) fun! Search(pat) execute "normal! /" . a:pat . "\<CR>" execute "normal! v//e+1\<CR>\<C-G>" endfun -nargs=1 だから 1 個の引数が必要。 :Search foo だと /foo が実行されて次の foo にジャンプする。 v//e+1 は v でビジュアルモードにして //e+1 で再び検索ジャンプする。 // という表記は間に前回の検索文字列が省略されているので /foo/e+1 の 意味になってカーソル位置の foo の最後の文字の次のカラムまでカーソル 移動する。最後にビジュアルモードを Ctrl+G でセレクトモードに変更。 /foo の後に v//e+1 やらならくても単に vel でいいんじゃないのかと 思ったけど、検索されるのは単語とは限らないから v//e+1 の方がいいのかな。 あと Ctrl+G のセレクトモードって初めて知ったけど単純にWindowsの選択と 同じように選択後に何か入力すると選択部分が消えるモードらしい。