« 2011年1月 | トップページ | 2011年3月 »

2011年2月

2011年2月28日 (月)

windowsにおけるgnuchlog.vimの不具合(パス区切り文字問題)

windowsにおけるgnuchlog.vimの不具合(パス区切り文字問題)

Time-stamp: "Wed Oct 27 11:22:31 JST 2010"

vimでChangeLogを書くために便利なプラグインとしてchangelog.vimがあ る。デフォルトでvimに含まれているから~/_vimrcに少しの設定を書けば使 えるようになる。ChangeLogはコンピュータプログラムを書く人達がその作 業を記録するために使うものである。ふだんプログラムを書くテキストエ ディタで作業記録も書くから当然にChangeLogもプレインなテキストファイ ルである。

もともとはemacsでプログラムを書く人達が考えだしたものらしい。emacsで プログラム(もっと広くにテキストファイル全般)を書いているとき「C-x 4 a」と打つとChangeLogファイルが開かれて当日の日付と(筆者の)名前とメー ルアドレスからなるヘッダー行が挿入される。そして次の行にタブでインデ ントされたアイテム(項目)を書くための行を準備する。アイテムの冒頭にそ の始まりのしるしのアスタリスクと編集中ファイル名が自動的に挿入されて 入力待ちになる。

emacsでは何の設定もなしにChangeLogを使うことができる。その際に一番気 掛りなのはChangeLogファイルが何処のディレクトリに作られるのかという ことである。emacsのバッファのどれかで「C-x 4 a」 (add-change-log-entry-other-window)を打つとChangeLogが開く。ショート カットキーに定義されていないM-x add-change-log-entryでは書き込むべき ChangeLogを尋ねるメッセージが表示される。「C-x 4 a」ではいきなり ChangeLogが開く。

さてChangeLogはどこにあるのだろうか。emacsは編集中バッファのファイル があるディレクトリ(カレントディレクトリ)からChangeLogを探す。もしカ レントに見つからないときは親ディレクトリを探しにゆく。そしてルート ディレクトリまで遡って再帰的に探し出そうとする。どうしても見つからな いときは編集中ファイルのディレクトリに保存するようにセットした ChangeLogバッファを開く。

emacsのChangeLogモードでは日付等のヘッダー行の次の行にアイテム始まり のアスタリスクに続けてChangeLogを呼び出した編集中ファイルのファイル 名を自動的に挿入してくれる。もしChangeLogが編集中ファイルの親ディレ クトリにある場合はChangeLogのあるディレクトリからの相対パスでファイ ル名を入れるようになる。

現用中のvim7.2にデフォルトで入っているftplugin/changelog.vimを使う場 合は編集中ファイル名の自動挿入ができない。またChangeLogを親ディレク トリまで探すことをしない。emacsのChangeLogモードに使い勝手を近付ける プラグインがvimの公式サイトにある。

ここからgnuchlog_1.3.tgzをダウンロードする。アーカイブにある plugin/gnuchlog.vim(12kB)を~/vimfiles/pluginに入れる。またアーカイブ のftplugin/changelog.vim(2kB)を~/vimfiles/ftpluginに入れる。vimのイ ンストールディレクトリにあるデフォルトの vim72/ftplugin/changelog.vim(9kB)をvimの支配の及ばない(呼び込まれな い)ところへ移す(changlog.vim.orgにリネームするだけでも問題ないようで ある)。

デフォルトのvim7.2にはvim72/ftplugin/changelog.vim(9kB)及び vim72/syntax/changelog.vim(3kB)がある。syntaxディレクトリの changelog.vimはそのままにする。

~/_vimrcに次を書く。

let g:changelog_timeformat = "%Y-%m-%d"
let g:changelog_username = "name  mail-address"
filetype plugin on

作業が終ったらvimをいったん終了してから開き直す(vim自身の再起動)。そ うしたら編集中のバッファで「\o」(バックスラッシュと小文字のオーの二 連打、間隔を開けすぎると「o」だけに解釈される)を打つ。もし編集中ファ イルのディレクトリにChangeLogファイルがあれば画面が二分割されてその 一方にChangeLogが表示される。もしカレントディレクトリにChangeLogが無 ければ親ディレクトリが探される。どこにもChangLogファイルがないときは 何も起こらない。

「\o」に反応がなかったらとりあえず編集中ファイルのディレクトリに中身 が空のChangeLogファイルを作る(秀丸エディタではスペースを一個入れるな どでする。まったく空のファイルは保存できない。vimなら空のファイルが 作れる)。そうしたあとに編集中ファイルのバッファで(コマンドモードか ら)「\o」するとChangeLogが呼び出される。

(注)ChangeLogのファイル名は大文字・小文字を区別するいわゆるキャメル ケースで書いたものに限定している。もしchangelogという名前のファイル があったとしても「\o」や「C-x 4 a」では呼び出せない。camel caseとは 要素語の最初を大文字で書くことをいう。いくつかの要素語の連結であるこ とを強調する書き方である。大文字が駱駝のコブに見えることからキャメル ケースと呼ばれる。コンピュータ関連で多く使われるがMcDonaldとか PlayStationなど一般でも見られる。ちなみに要素語をアンダースコアで連 結したものはスネークケースという。

plugin/gnuchlog.vimにはg:changelog_relativepathというグローバル変数 がある。何も設定しなければ1にセットされてChangeLogに挿入される編集中 ファイル名がChangeLogのあるディレクトリからの相対パスになる。もし0(1 以外)にセットするとファイル名だけになる。

例えば、ChangeLogのパスが/parent/ChangeLogであり、編集中ファイル名 file.txtのパスが/parent/subdir/file.txtならChangeLogに書き込まれるファ イル名はsubdir/file.txtになる。g:changelog_relativepathを0 セットする ならfile.txtだけになる。

現在使用中のwindow版のvim7.2にgnuchlog.vimを入れたものでは g:changelog_relativepathの設定しないでも、ChangeLogに書き込まれる編 集中ファイル名がドライブ名から始まるフルパス(絶対パス)になってしま う。フルパスは長すぎて煩わしい。gnuchlog.vimがChangeLogに書き込んだ フルパスを自分で相対パスに書き換えればよい。しかしせっかく相対パスを 書き込む筈なのにそうならないには理由があるだろう。それを知りたいし、 直せるものなら直したい。

plugin/gnuchlog.vimからファイル名書き込みに関係ある部分を取り出すと 次になる。

  " Search for the ChangeLog file to edit starting up
  " from the directory where the current file is
  let s:changelog = findfile("ChangeLog", expand("%:p:h") . ';')
  " don't do anything if we can't find the file
  if !filereadable(s:changelog)
      return
  endif
  " compare the ChangeLog directory and get the difference
  " ie. include the filenames path relative to ChangeLog
  if g:changelog_relativepath == 1
      let fname = expand("%:p")
      let changelogdir = fnamemodify(s:changelog, ":p:h")
    let fname = substitute(fname, "\\", "/", "g")
    let changelogdir = substitute(changelogdir, "\\", "/", "g")
      let m = matchend(fname, changelogdir) + 1
      let fname = fname[(m):]
  else
      let fname = expand("%:t")
  endif

とりあえずこのスクリプトに現われる組み込み関数が何をするものかを知ら なければならない。vimのヘルプで引けるものはfindfile(), expand(), fnamemodify(), matchend()があり、それぞれについてvimのコマンドモード から「:help findfile」として説明を読む。それで何をしているのかの凡そ をつかむ。

次は実際に組み込み関数の働きをvim上で実行してみることで確認する。ま ず、let fname = expand("%:t")を確認する。編集中の既存ファイルの バッファのコマンドモードから「:echo expand("%:t")」としてみる。そう するとミニバッファに編集中ファイルのファイル名が返ってくる。編集中 ファイルのディレクトリには関係なく、編集中ファイル名だけがChangeLog に挿入されることになる。

次にfindfile("ChangeLog", expand("%:p:h") . ';')に注目する。組み込み 関数findfile()の最初の引き数は"ChangeLog"という名前のファイルを探す ことを表す。そして二番目の引き数はフィイルの検索パスの指定になる。 expand("%:p:h")とセミコロン';'の間にあるピリオドは文字列を結合する。 「%」は現在のファイル名で、「:p」(path)はフルパスに展開する。そして 「:h」(head)はディレクトリを表す。結局expand("%:p:h")は現在ファイル のディレクトリ(ファイル名を切り落したもの)になる。

検索ディレクトリの文字列の後にくっつけるセミコロンの意味するところは 見つけにくい。「:help filesearching」に書いてある。そのディレクトリ からルートまで遡って上向きに検索するとある。

もし編集中ファイルのディレクトリがカレントディレクトリであれば findfileの2番目の引き数は".;"(カレントディレクトリから上向きに検索) で済む。vimでは~/_vimrcに「set autochdir」(:help autochdirに解説があ る)を書くと開かれた/選択されたファイルを含んでいるディレクトリがカレ ントディレクトリになる。

編集中ファイルにおいてコマンドモードからechoコマンドを使って

:echo findfile("ChangeLog", expand("%:p:h") . ';')

を実行するとカレントまたはその上位ディレクトリからChangeLogと名付け られたファイルを探す。これで表示されるのはChangeLogの文字だけである がフルパス情報を持っておりfnamemodify()関数で所属ディレクトリやフル パスに展開することができる。

以上はもっぱらヘルプを頼りにしたスクリプトの解読である。次は実際にス クリプトをステップ実行してどこに問題があるのかを見つける。途中で入力 待ちのあるいわゆる対話型のスクリプトは今迄にいじったことがない。入力 ファイルにテキスト処理をして出力ファイルに書き出すいわゆるフィルター 処理をPerlでやった経験しかない。

スクリプトのデバッグをするモードがあるらしいが、さっぱり使い方が分か らない。ヘルプにはデバッグモードのコマンドの説明はあるが、それを使っ て実際にどうするのかの実況放送的な実例がない。私はPerlを少しやったこ とがありデバッグモードというものを触ったこともある。しかし実際にそれ を便利と感じるまでに使いこなすことができていない。経験のないものには 察し(ひらめき)が効かない。

Perlでフィルター処理をやったときにはプログラムの彼方此方にprintコマ ンドを置いて変数や配列(リスト)が処理される度にその中身をコマンドライ ンに表示させることにしている。途中経過をその都度確認することでエラー を見つける。

問題のありそうな部分が特定できるならスクリプト全体を実行せずにその個 所だけを部分実行すれば何とかなると思う。つまり対話する場所を外して特 定の変数を追跡することで問題が解けるかもしれない。

インターネットを探してもスクリプトをデバッグ(テスト)する実例がない。 そんな中でvim関連情報発信の「名無しのvim使い」さんのところで次のvim スクリプトを見つける。pluginディレクトリにBatch.vim(3kB)を入れるだけ で何も設定する必要はない。藁にもすがる思いで早速試してみる。

「選択した範囲に記述されたvimエディタのコマンドを、 順々に実行するス クリプトです。 vimエディタ設定の確認や、vimスクリプトのデバッグで使 用します。 (Windows, Mac)
または、vimエディタのコマンドの入力が面倒になってきた時に、ファイル にコマンドを記述して簡易入力で実行するために用います。
プラグイン をダウンロードして、pluginディレクトリにコピーしてくださ い。まず、vimスクリプトのコマンド、もしくはvimスクリプトの文を記述し ます。次に、それらのコードをビジュアルモードで選択するか、コマンドラ インモードで指定して、「:Batch」コマンドを実行してください。
:{range}Batch
" コマンド実行のサンプル
" 1から20行目の範囲のvimスクリプトのコードを実行
:1,20Batch
「:Batch」コマンドは選択した範囲のコードを一時ファイルにコピーし、そ の後に、そのファイルをvimスクリプトとして実行します。
(注)「:Batch」コマンドによる選択スクリプトの実行処理は、選択したコー ドが単体で実行できないような場合(たとえば、スクリプトローカルな関数 に依存している場合)、コードの実行に失敗します。」

plugin/gnuchlog.vimをvimに読み込みコマンドモードにおいて上記の抜き出 したスクリプト部分を範囲指定して

:1,12Batch

のように入力してみる。そうするとエラーメッセージが出る。s:changelog が未定義であるという。

「:help script」でヘルプを引いてみると「s:」を前置した変数はスクリプ トローカル変数と分かる。さらに「:help script-variable」によると「Vim スクリプト内では"s:"で始まる変数名を使うことができる。これはスクリプ トについてローカルであり、スクリプトの外部からはアクセスできない」と ある。そうか、これこそがs:changelogが未定義というメッセージの理由 だったのかと気付く。

そこで上記に抜き出したplugin/gnuchlog.vimの一部分を別ファイル test.txtにする。if文とelse以下は除く。

1  " test.txt
2  let changelog = findfile("ChangeLog", expand("%:p:h") . ';')
3  let fname = expand("%:p")
4  let changelogdir = fnamemodify(changelog, ":p:h")
5  let m = matchend(fname, changelogdir) + 1
6  let fname = fname[(m):]

スクリプトのローカル変数の接頭辞である「s:」は取り除く。そのうえで test.txtのバッファのコマンドモードから

let fname = expand("%:p")

のある行の行番号にBatchを付けて「:3Batch」のように打つ。ミニバッファ には何も表示されない。次に同じコマンドモードで「:echo fname」を打つ とD:\home\comp\test.txtのようにgnuchlog.vimから抜き出して作った部分 スクリプトの書かれたテキストファイルtest.txtのフルパスが表示される。

「s:」を除いた第二行目に対して「:2Batch」を実行したあとで「:echo changelog」とするとChangeLogが返る。これでBatch.vimの使い方が飲み込 めた。スクリプトの動きを手軽に見ることができる。いちいち上記の各行の コマンドをコマンドモードから打ち込む面倒から解放される。

今度はtest.txtの2行目から5行目までを「:2,5Batch」で実行してみる。そ うすると変数のchangelog, fname, changelogdir, mのそれぞれを「:echo fname」で確認できる。あるいはtest.txtの、変数に代入するコマンドのある 各行の次の行にそれぞれecho changelog, echo fname, echo chagelogdir, echo m, echo fnameという風に変数を表示するエコーコマンドを挟み込むと 変数の移り変わりを追跡することができる。

問題はmとして0が返ることにある。そのためにフルパスがChangeLogに書き 込まれる。ところで最後の行にあるfname[(m):]の解釈が難しい。fnameは文 字列である。ところがその直後に[(m):]が続く。角括弧[]はリストの要素の インデックス(リストの先頭要素を0とし順番に自然数を番号として割り振 る)を表す。そして角括弧の中にあるコロンは部分リストを作る際の始点と 終点を区切る役目をする。終点または始点を指定しない場合は末尾までまた は先頭からになる。

:echo ["a","b","c"][1] → b
:echo ["a","b","c"][1:] → ["b","c"]

以上は「:help variable」で引けるヘルプに書かれている。実際にコマンド モードで実験して確かめると使いこなせる気になる。簡単な入力を与えてみ てどんなものかを確認することが「これなら使える」という自信につながる。

文字列に対してリスト流儀のインデックスを付けた場合のことはヘルプに書 かれていない。これは実験で確かめるしかない。コマンドモードで次のよう になる。

:echo "asdf"[2] → d
:echo "asdf"[1:] → sdf

文字列の一文字ずつをリストの要素とみなして一文字や部分文字列を取り出 すことができるということになる。これはヘルプに見当たらないので裏技な のだろう。gnuchlog.vimを解読する際の最初の関門が文字列変数にリストの インデックスを付けたこの表現であった。何かの間違い(タイプミスとか)で はないかと思うがそれを検証する手段を知らない、まったく情報がないの八 方塞がりであった。

インターネットを検索しているうちに「:help variable」による部分リスト の説明から角括弧[]の中にあるコロンの意味するところを知る。コマンド モードからecho(エコー)コマンドで変数を読み出す方法により上記の実験を することでようやくモヤモヤが晴れた。

test.txtをBatch.vimを使って部分的に実行した後でfnameとchangelogdirを エコーコマンド「:echo」で表示させる。fnameは現在編集中ファイル test.txtのフルパスでありchngelogdirは、ChangeLogを同じディレクトリに 置いているのでtest.txtの所属ディレクトリになる。

どちらの変数も間違いなく文字列であり異なるのは末尾に\test.txtがぶら 下がるかどうかだけである。それなのにどうして文字列からパターンを探す matchend()関数が、検出不能の「-1」を返すのであろうか。

vimリファレンスマニュアル(vim/doc/eval.txt)を繰っていると「:help expr-string」で参照できる内容の「\\」で突然に閃く。他にも手掛かりと なるインターネット上の記事を読んだけれど何の記事だったかを忘れた。結 局インターネットに公開されているvimのマニュアルを見て気付く。

vimのマニュアルの虱潰し(しらみつぶし)的な検索方法を知らない(「: helpgrep」があるらしいが未だ使えてない)。ついグーグル検索に頼る。vim でヘルプを読むのとグーグルでvimで読むマニュアルはほぼ同じものであ る。慣れているグーグルで検索するほうが多い。

ヘルプに「文字列定数には以下の特殊文字が使用できる」とありその後に列 挙されたものの中に「\\ 円記号(バクスラッシュ)」がある。バックスラッ シュは正規表現におけるエスケープ文字(メタ文字)の(ような)扱いになるら しい。文字列定数ではスッピンのバックスラッシュが使えない。エスケープ した「\\」でなければならない。

これこそがmatchend()関数がマッチなしの「-1」を返してくる理由である。 windowsではパス区切り文字としてバックスラッシュを使う。expand("%:p") が返してくる現在ファイルのパス区切りにはバックスラッシュが使われる。 これがmatchend()関数の機嫌をそこねる原因になる。

泥縄式解決としてfnameとchangelogdirをmatchend()関数に渡す直前で substitute()関数により「\」を「/」で置き換えることにする。インデック スmへの代入式の直前に次の二行を付け加える。

let fname = substitute(fname, "\\", "/", "g")
let changelogdir = substitute(changelogdir, "\\", "/", "g")

再度test.txtを実行してみると、インデックスmとして0でない数値が返るよ うになる。さっそく使用中の~\vimfiles\plugin\gnuchlog.vimにこの二行を 付け加える。そしてvimを起動しなおすとChangeLogにおけるファイル名挿入 が、ChangeLogのあるディレクトリからの相対パスで入るようになった。

ちなみにもう一つ悩んだのは部分リストのインデックス[(m):]における(m) の丸括弧である。どうやら変数m(mという文字そのものではなくて変数mが保 持している)から数値を引き出すためのものらしい。matchend()問題と分かっ たのでこちらは触ることなく終わる。

とにかくvimスクリプトに関する情報は少ない。emacsが使う emacs-lisp(elisp)の本は何冊もあるがvimスクリプトの本は見たことがな い。インターネット検索でも引っ掛かるものはほとんどvimのマニュアルで ある。vimのヘルプをインターネット経由で読んでいる状態である。グーグ ルのほうが検索しやすいからである。

私はvimの日本語ヘルプを読めるようにしているが、そうでなかったらデフォ ルトは英文になる。英語の理解不足のうえに書いてある内容についていけな い二重苦になる。ヘルプ操縦法は今回のトラブルでようやく習得できた。

vimスクリプトをいじった体験談とか失敗談とかの記事も見つからない。ど うしてなのだろう。そして、ペラペラめくりのできる解説本がなくて不自由 する。そんな中でマニュアル由来ではない次の記事は貴重である。

「古い冗談にこうあります。まともなテキスト・エディターさえあったら Emacs は優れたオペレーティング・システムになっていただろうし、まとも なオペレーティング・システムさえあったら vi は優れたテキスト・エディ ターになっていただろう。この冗談は、これまで常に Emacs が vi よりも 戦略的に大きく勝っていた 1 つの点を表しています。それは、組み込みの 拡張プログラミング言語です。Emacs のユーザーは腱鞘炎を起こしそうなほ どの制御コードの入力を快く我慢し、進んで Lisp 言語を使って拡張機能を 作成しているという事実が、まさに、組み込み拡張言語がいかに大きな利点 であるかを証明しています。
しかし、vi プログラマーが今までのように Emacs の括弧で括られたスクリ プト言語に羨望のまなざしを向ける必要はもうありません。我々のお気に入 りの vi エディターも今やスクリプトで処理できるのです。しかもその方法 は、Emacs より遙かに人間の作業に向いたものです。」

| | コメント (0) | トラックバック (0)

2011年2月26日 (土)

ChangeLogをメモ(memo)として使う

テキストファイル本文にタイムスタンプを入れる

Time-stamp: "Sat Oct 23 09:00:59 JST 2010"

テキストファイルの冒頭にはタイムスタンプを自前で入れるようにしてい る。自力(手打ち)で時刻を打ち込むのではなくファイル保存時刻をテキスト 本文に挿入するエディタの機能を使う。そうしておくことの便利を書いてみ る。

テキストファイルが何時書かれたかはそれを保存するハードディスクやフ ロッピーディスクに本文内容と一緒に記録するファイルの作成日付や更新日 付で知れる。コンピュータはファイルを管理するためにファイルの内容と一 緒にファイルサイズとかタイムスタンプなどのファイル情報を記録する仕組 みを持っている。

一台のパソコンだけならファイル情報が失われることはない。二つのコン ピュータ間でファイルをやり取りするときはファイル情報がそのまま伝わる とは限らない。ファイルの内容さえ伝わればよいのであってコンピュータに よって表現法が違うかもしれないファイル情報を扱う面倒を避けている。 ファイルサイズは受け取った側がカウントしなおせばよいしファイル日付は 受け取った側がその時点の日付を付けるほうがファイル管理上の都合がよい だろう。

ウェブログ以前の従来型のホームページはftpを使って関係ファイルをhttp サーバーにアップロードする。ftpによりファイルをサーバーにアップロー ドすると、受け取ったftpサーバーはその受付時刻をタイムスタンプとして ファイルに付ける(ftpのサーバーがアップロードで受け取ったファイルに付 けたタイムスタンプをクライアント側で知ることはできる)。

ftpはファイルのタイムスタンプ(ファイル情報)を伝達しない。それに対し てホームページを管理するhttpサーバーはタイムスタンプなどのファイル情 報を伝達する。ところがホームページを表示するブラウザはファイルのタイ ムスタンプなどのファイル情報を内部処理に使うだけで閲覧者の目に見える 場所に表示しない。

従来型のホームページが何時書かれたものであるかはブラウザの画面からは 分からない。そこでホームページを作成する人がページの本文へ「Last modified:」に作成(更新)日付を続けたタイムスタンプを自前で入れるよう にしている(たいていホームページ作成ソフトが自動的に挿入してくれる)。

ホームページ本文の末尾(または冒頭)にタイムスタンプを入れることはペー ジ開設者にも便利なことである。インターネット上に公開した記事とその後 に加筆訂正したかもしれないパソコン内の記事との違いを本文記載のタイム スタンプで判断できる。

httpサーバーにあるホームページファイルのタイムスタンプも、それの元に なる自分のパソコン内のホームページ原稿ファイルのタイムスタンプのどち らの時刻もそれ知る手段はある(ファイラであるエクスプローラでパソコン 内のアップロード用のhtmlファイルのタイムスタンプを見ること、そして ftpクライアントソフトからアップロード済みhtmlファイルのタイムスタン プを見る)。そうは言ってもそれはちょっと面倒なことである。リモート (httpサーバー)とローカル(自分のパソコン内)にあるファイルの本文にタイ ムスタンプが書かれていれば手間をとらない。実際のページを目で見ながら 更新の有無を判断するほうが安心である。

ウェブログ(ブログ)が流行りはじめた頃は日記形式の簡易型ホームページと 紹介されていたように思う。ブログの記事には必ず公開年月日が入る。年号 のディレクトリの下に月別のサブディレクトリが作られ、それらに一ヶ月分 ずつの投稿記事が収められる。インデックスページとしては最新の公開記事 が使われる。そこには最新記事の直前に公開した記事にリンクが貼られる。 最新と最古の中間にある記事には先行ページと後続ページへのリンクが貼ら れる。最初のページには二番目のページへのリンクがある。リンクをいもづ る式にたどることでブログの全ページを読むことができる。

それとは別に月別の記事をひとまとめにしたページとか記事内容で分類した カテゴリー別のまとめページが作られたりする。それらにもインデックス (最新の記事、表紙)ページからリンクを貼られる。ブログ作者は索引(表紙) ページを作る必要がない。これらの作業はブログ作成システムが自動で実行 する。

従来型のホームページにはインデックスページとして他のページへのリンク を貼った索引ページとなる表紙ページを作る必要があった。ホームページを 閲覧するためのソフトであるブラウザには見たいホームページの内容を記述 したhtmlファイルの名前を直接に指定しなければならない。

ホームページのタイトルはそれを記述したhtmlファイルのファイル名に比べ ると長いものになる(だろう)。ファイル名として同名のファイルが出来ない 範囲のできるかぎり短い名前のほうがファイルを管理するのに便利である。 長すぎるファイル名はそれをブラウザのurl欄へ完全に指定することが難し い。キーボードから打ち込むべきファイル名の字数は少ないほどよい。

自分のパソコンの中にあるファイルなら補完機能(auto-completion)により ファイル名の全部を入力しないでよいかもしれないが、遠いところにある ファイルにはそれが効かない。ファイル名を一字の間違いなく指定しなけれ ばならない。それは面倒なので題名の文字にリンクを貼ることでファイル名 の直接入力に代える。

ホームページのファイル名にはページ内容に相応しいものを付けたいがそれ がかなうとは限らない。ブログのファイル名は日付由来のものが多い。なか にはまったくの通し番号というものもある。従来型のホームページではペー ジ内容と関連のあるファイル名としたほうが開設者にとって便利である。そ のような適切なファイル名を付けること、そしてインデックスページに載せ たページの題名に実際のファイルへのリンクを貼る作業が必要になる。これ らはブログの記事内容とは別の裏方仕事である。

ブログではファイル名を付けることやインデックスページを作る手間が要ら ない。こういう面倒から解放されたことがブログの人気につながったのかも しれない。また、コメントを受け付けるとかトラックバックといった相互リ ンク風な仕組みを備えたこと、そして細切れ記事ゆえに検索サイトで扱いや すいなどの総合力でブログが受け入れられたらしい。

最近は発言を140文字以内に抑えたtwitterが流行っている。ブログにも字数 の少ない記事はあるが、twitterは初めから字数制限があるので「つぶや き」しかできない。気軽なメモ書きと感じる。グーグル検索でも結構 twitterがヒットする。「これ(何々)ならばあれ(何々)である」を検索して いるときに入力した検索キーワードそのままのtwitterがヒットしたりす る。そんなことは分かっている、その理由を知りたいのだとがっかりする。 何か露出度を高める工夫をしているらしく検索結果の上位にあったりする。

私はココログにプレインなテキストファイルをアップロードしている。ブロ グ記事にすると加筆訂正が面倒ということもあって内容を度々書き換えるよ うなものはテキストファイルのままアップロードする。月別ディレクトリの 下に作ったサブディレクトリに入れる。アップロードしたままのテキスト ファイルは作成者しかその存在を知らない孤島である。そこでブログ本文か らテキストファイルへリンクを貼る。ブログ本文を書き換えるのと違いテキ ストファイルはアップロードして置き換える手間だけで済む。

ブログサイトにアップロードしたテキストファイルを更新するかどうかはサ イト上にあるファイルのタイムスタンプと自分のパソコンにある元ファイル のタイムスタンプを比べて判断する。それは面倒なのでテキストファイル本 文冒頭に更新保存の時刻を書き込むようにしている。テキストエディタに時 刻挿入機能が備わっているので上書き保存時に人手をわずらわすことなく自 動的に書き込むことができる。

ブログ記事は、あらかじめエディタでテキストファイルとして作成しておき ブラウザに表示したココログ新規作成画面にコピーアンドペーストしてい る。作成画面へ直接にキーボードから打ち込むいわゆるオン書きはしていな い。下書きのテキストファイル冒頭にタイムスタンプがあるのでそれを含め て作成画面に貼り付ける。

ココログの投稿は「今すぐ公開」「公開日時を指定」「下書き」を選べる。 そして何月分の記事となるのかは公開月で決まる。とりあえず下書きとして 保存しておきしばらくして読み返し点検してから公開する。そのうち公開し ようとページ原稿を手元においたままにすると忘れることがある。そこで書 き上げた勢いに乗って多少の間違いが残っていようとも下書きとしてココロ グサイトに上げておくようにする。そうしておけば下書きから「今すぐ公 開」か「公開日時を指定」に変更するだけで済む。書いた直後に「今すぐ公 開」するには勇気がいる。書き込みと実際の公開を分離して記事をアップ ロードする心理的負担を軽くすることにしている。

サイトにアップロードしてしまうと多少の気掛かりがあっても公開する頃に はそのことを忘れている。折角上げたのだから公開しないのは勿体ないと自 分に言い聞かせる。エイヤーッの気合のもとに公開(それでもたいていは控 え目に公開日時を指定する、ホントの公開はサイトのタイマーに任せてしま う)する。

公開記事のなかには気に入らない、ひょっとしたら間違えているかもな記事 がある。書き直したほうがよい気がするがなかなか踏み切れない。いっその こと消したほうがよいかなとも思う。それらはそれなりに時間を掛けて書き 上げたものだからスッパリ消すのは惜しい。自戒のためにわざと誤りあるか もしれない記事をあえて残しておくのだとこじつける。

ブログに書き込んでから公開するまでに時間を置くので実際に書いた時期が 分からなくなる。そのときブログ記事の冒頭に入れたタイムスタンプが役に たつ。ブログ記事を公開した後に書き換えても月別分類からは動かない。書 き換えたかどうかはココログ管理ページのコントロールパネルからファイル マネージャーのファイルタブでタイムスタンプを見るしかない。それよりは ブログ本文冒頭に自前で入れたタイムスタンプを見るほうがはやい。

ChangeLogをメモ(memo)として使う

一つのテキストファイルに何度も加筆訂正することがあると、何時頃にどの 部分を書き加えたのか、何時誤りを修整したのかなどの記録を残しおきた い。書き留めた最終更新日時だけではなく、それを書くことになった経緯の 手掛りが欲しい。文書情報が最終更新日だけというのでは情報としてとぼし すぎる。本文には書き込まなかった元ネタの出所とかそのときの感想とかを 記録して少なくとも他人作そのままなコピペでないことを記録しておきた い。その経過を足場記録として時系列で残す。間違いがあったならそれに気 付いた日時を記録してその原因探しを始める。書き留めることはより深くよ り広く考えることの切っ掛けになる。書くという作業中に新しいアイデアの 湧くことが多い。パソコンが使えないときはとりあえず手書きメモする。頭 に浮かんだことはすぐに書き留めておかないと忘れてしまう。それらをまと めるための気楽なメモツールとしてChangeLogはとても便利なものである。

かつてCVS(conccurrent versions system)というバージョン管理システムを 使ってみたことがある。CVSはグループで一つのソフトウェアを分担して作 り上げてゆくに便利に出来ている。例えば、一つのファイルを二人が同時に 編集を始めた場合にファイルの読み出しと保存のタイミングにより一人分の 修整しか盛り込まれかったりする。そのような衝突(コンフリクト)が起きた ときに警告を出す機能がある。

プログラムのソースファイルのうち希望の動きをするようになったものは別 に(一里塚として)残しておいて、そのコピーに対してさらなる改良とか機能 拡張をする。残しておく一里塚ファイルのファイル名も改良を加えるファイ ルのファイル名も同じにしたい。そうしないと何個かの別々に書かれたソー スファイル間の連系が取れなくなる。そこで残すものは別ディレクトリに移 すとか、同じディレクトリにそのままにしておくなら元のファイル名に接尾 辞として「.org」とか「.1st, .2nd, ...」を付けるなどで別名にしなけれ ばならない。これらの作業は面倒で紛らわしい。

CVSを使えば一つのファイル名にバージョンを設定することができる。ファ イル名にバージョン番号を付けるという単純なものではなくて、ファイル名 とは別にバージョンを指定することで同名のバージョン別ファイルを取り出 すことができるようになる。

CVSが扱うものはテキストファイルであるからコンピュータのプログラムで はない普通の文章のテキストファイルに対してバージョンを設定することも できる。そうすればバージョン毎を比べることで何処を変更したかが分か る。一文字でも間違えると正常に動かないプログラムに対して普通の文章に CVSを使うのは高機能にすぎる。変更を加えた日時とその概要を記録すれば 十分である。

ソフトウェアの開発者は作業記録としてのChangeLogを書く。作業記録をプ ログラムにコメントとして書き入れるのも一つの方法だろうが一覧記事があ ると便利である。

プログラミングに使われるエディタのemacsやvimはChangeLog作成に便利な 機能を備えている。ChageLogを作るために他のツールを使うのは面倒であ る。プログラムを書いているテキストエディタをそのままChangeLog作成 ツールにしたい。

ChangeLogの書式はガチガチに固められた窮屈なものではなくてとてもシン プルで緩やかなものである。

ヘッダーと呼ばれる日付と名前、メールアドレスを並べた行が見だしになる (ヘッダーは行頭から始まる)。それに続けてアイテムと呼ばれる箇条書きを 続ける。アイテム部分はタブでインデントする。

ヘッダーの日付と名前とメールアドレスの間は二個のスペースで区切る。 メールアドレスは不等号<>で囲む。 アイテムはアスタリスクとスペースに 続けて書く。最初に関係ファイル名と括弧で囲んだ関数名、それにコロン及 びスペースを続けた後に文章を書く形式が多い。

テキストエディタのmeadowとvimにはChangeLogファイルを作る機能がデフォ ルトで付属する。ChangeLogファイルが呼び出されたときにヘッダーとして の日付と名前、メールアドレスを書き込みアイテムの始まりのアスタリスク とスペースをタブでインデントして挿入する。

meadowの場合はテキストファイルを編集中に「C-x 4 a」とすると編集中の ファイルがあるディレクトリ(カレントディレクトリ)に存在するChangeLog を開く。カレントディレクトリにChangeLogがない場合はペアレントディレ クトリからChangeLogを見つけようとする。見つからなかった場合にはカレ ントディレクトリに保存することになるChangeLogのバッファを作る (ChangeLogファイルに書き込んだら自分で保存操作をする必要がある)。

ヘッダーの下にアイテム始まりのアスタリスクと編集中のファイル名と関数 名が入る。もし、「C-x 4 a」によらないで直接にChangeLogを開いた後で 「C-x 4 a」を使ったときは編集中のファイルがないのでアイテム始まりの アスタリスクだけの挿入になる。

vim付属のchangelog.vimによる機能はmeadowのChangeLogモードに比べて貧 弱である。設定が不足すると編集中のファイルのバッファからChangeLogフ ァイルを呼び出すことができない(使い始めにはChangeLogを編集可能状態に してからでないと「\o」できないものと思った。編集中ファイルのディレク トリにあるChangeLogを呼び出すことはできる)。

vimの公式サイトにあるgnuchlog_1.3.tgz (gnuchangelog : Changelog support like Emacs/GNU)を入れると「\o」がmeadowにおける「C-x 4 a」の ような働きになる。

meadowの「C-x 4 a」とかvimにおける「\o」はChangeLogを作るためのヘル パー機能である。作成するのはテキストファイルであるから自由に改変でき る。書き込みの準備(日付挿入と関係ファイル名の挿入)をしたらアイテム部 分のタブ挿入インデントをやってくれる(だろう)。使用者の書き込み方が気 に入らないからと一旦書き込んだものを改変することはない。今迄どおりに エディタの整形機能が使える。

新しいツールの使い方は実際に使いながら慣れてゆくしかない。それにはま ずそれが使える環境を整備しなければならない。meadowとvimにはデフォル トでChangeLog作成機能が備わっているので使用開始にあたってやるべきこ とは初期設定ファイル(.emacsや_vimrc)にChangeLogファイル用の名前と メールアドレスを登録することである。

簡単な設定で使えるようになるが使い方を知るまでは少しばかりとまどう。 そこでChangeLog機能を使う試行錯誤の記録をChangeLogに書くという泥縄式 で使い方の練習する。他の仕事をしながらChangeLogの使い方を練習する二 重苦は避ける。それではどちらにも集中できない。

インターネット検索で知ったことをChangeLogにメモ書きする。ChangeLogの 普通の使い方は、何かのファイルに加えた変更記録としてChangeLogに書き 込む。それを逆転させてこれから作成するテキストファイルのネタとなるメ モを先にChangeLogに書き込んでしまう。そのメモを見ながら本文を作ると いう反対なことをする。

changelog.vimを使う(vimに付属しているもの)

最初は~/_vimrcに何も設定せずに使おうとする。g:changelog_usernameと g:changelog_new_date_formatを設定しなかった。そうすると changelog_usernameをシステムから探し出そうとする。whoamiとhostnameコ マンドを使うためにdos窓が二回開いてすぐに消える。

そこで~/_vimrcに次を設定する。

let g:changelog_timeformat = "%Y-%m-%d"
let g:changelog_username = "name  mail-address"

vim付属のchangelog.vimは同名のものがftpluginディレクトリとsyntaxディ レクトリの両方にある。所属ディレクトリが違うこれら二つはまったくの別 物である。

「vimエディタ標準のファイルタイププラグインで、 チェンジログの入力を 補助する機能を持っています。 ただし、ファイルタイププラグインなの で、 特定のファイルタイプ(changelog)のファイルを開いた時のみ動作しま す。 (Windows, Mac)」
「Vimには標準でchangelog.vimというプラグインがあります。使い方はこち らが参考になります。で、このプラグインはヘルプによれば. vimrcに
runtime ftplugin/changelog.vim
とするとグローバルにマッピングされます。」

自分が試したところでは編集中ファイルのバッファで「\o」してもエラーが 出る。さらに次を~/_vimrcに書いたらエラーが出なくなった。

filetype plugin on

後付けスクリプトのgnuchangelogを使う(vim)

vim7.1付属のftplugin/changelog.vimにバグがあって上手く動かなかった時 期があるらしい。そのときに次のスクリプトに置き換えたら動いたという報 告を見つける。こちらならemacsライクな動きになるという。

pluginディレクトリに入れるgnuchlog.vimとftpluginディレクトリに入れる changelog.vimの二つからなる。ftpluginディレクトリに入れる changelog.vim(2kB)はデフォルトのもの(9kB)を上書きすることになる。新 しいftplugin/changelog.vimは小さいが、その機能がplugin/gnuchlog.vim (12kB)に移されている。デフォルトのsyntaxディレクトリにある changelog.vimはそのままとする。

~/_vimrcにfiletype plugin onを書くとvim起動時にdos窓が開く。外部コマ ンドを呼び出している。ChangeLogという新規バッファを作るときにもdos窓 が二回開く。gnuchlog.vimを見るとg:changelog_usernameが設定されてない とwhoamiとhostnameコマンドを使って取得しようとする。vim起動時にこの 処理が入るためにdos窓が二回開いて何かを処理してすぐに消える。一瞬で あるため何をやっているかが見えない。

vimデフォルトのftplugin/changelog.vimでも同様な処理がされる。usename が設定されてないままでChangeLogファイルを開いたとき、あるいはvimで ChangeLogファイルを作成したときにdos窓が二回開くことになる。

そこで~/_vimrcに次を設定する。

let g:changelog_timeformat = "%Y-%m-%d"
let g:changelog_username = "name  mail-address"
filetype plugin on

なお、ChangeLogファイルが存在しないディレクトリにあるテキストファイ ルのバッファで「\o」しても何も起こらない。emacsではChangeLogが存在せ ず、そのペアレントディレクトリにも存在しなければカレントディレクトリ にChangeLogを新規作成する。

| | コメント (0) | トラックバック (0)

2011年2月14日 (月)

vimスクリプト(script)の文法(syntax)を知る方法

vimスクリプト(script)の文法(syntax)を知る方法

Time-stamp: "Tue Nov 02 07:07:21 JST 2010"

vimスクリプトの文法に関する情報は少ない。emacsのスクリプト言語である elisp(emacs lisp)を説明した本は何冊もある。インターネット上にも多く の情報がある。vimスクリプトを扱った本は見たことがない。需要がないと ころには供給がないということなのだろうか。一見C言語風のvimスクリプト に比べてやたらと括弧で囲むelispにはなかなか馴染めないことからすると vimスクリプトは分かりやすいのかもしれない。

vimスクリプトの解読にはその文法知識が要る。インターネットを検索する と次のページがあった。

「全て :help に書いてあります。Web 上の怪しい資料には誤ったものや古 いものが多いので、可能な限り :help を参照しましょう。」

ここに耳寄りな情報があった。「すべて:helpに書いてあります」とある。 なるほどそういうことか。本屋をあさらなくとも目の前にあるパソコンに vimスクリプトに関する情報が詰っているのである。vimのヘルプにはハイ パーリンク機能があって文字色の違う部分からリンク先に飛べるらしいが、 その操縦方法が分からない。

vimヘルプの使い方を見るにはvimのコマンドモードで引き数なしの 「:help」を打つ。表示される内容はdoc/help.txtに書かれたものである。 このことを知らなかった。使っているのはwindows版のguiなものである。そ のメニューバーからヘルプの「概要」をマウスでクリックしてもよかったの である。vimはキーボードから使うものと思いマウスを使わないようにして いた。そのために気が付かなかった。なお、windowsの標準である「F1」を 使っても同じヘルプ表示になる。

ヘルプの中にある文字色が地の文章とは違うところにリンクが貼ってある。 その文字にカーソルを置いて「ctrl+]」とするとリンク先にジャンプでき る。元の場所に戻るには「ctrl+t」(または「ctrl+o」英字のオー)を使う。 ヘルプを終わるには「:q」を使う。この方法を知らなければヘルプを読む気 にならない。多数のファイルに分かれたヘルプから希望の場所を探すのは極 めて困難である。今回どうしてもヘルプを読む必要ができたことでヘルプの 操縦法を知ることができた。

vimのヘルプを読むコマンドはvimのコマンドモードで使う。ヘルプを読むた めにはインサートモードからコマンドモードに復帰しなければならない(マ ウスでメニューバーのヘルプをクリックすると自動的にコマンドモードへ復 帰する)。ヘルプ自体はテキストファイルであり、それを改変してはいけな い。そのためヘルプはコマンドモードで読む。ヘルプのバッファを間違えて インサートモードにすることのないようにヘルプファイルはリードオンリー (読み込み専用)になっている。インサートモードに居るときにヘルプを読み たくなったら「:help」が使えるコマンドモードにしなければならない。

ユーザー定義関数はプログラム(スクリプト)本体からその働きを読み取るし かないが、組み込み関数(builtin function、付属の定義済み関数)について はその解説がなければ分からない。それらは「:help 関数名」で参照でき る。

vimのデフォルトのヘルプは英文になる。ヘルプを日本語化する手順につい ては次のページを参考にする。英語ヘルプはそのままとし~/vimfiles/doc や~/vimfiles/syntaxに日本語ヘルプファイルを置く。日本語ヘルプを先に 表示するようになる。デフォルトの英文ヘルプを置き換えることはしない。

「まず、日本語のヘルプドキュメントをダウンロードしてください。日本語 のヘルプドキュメントは、現在、次のURLで配布しています。
ダウンロードした圧縮ファイル
(http://www.kaoriya.net/vimdoc_j/vimdoc_ja-snapshot.tar.bz2)を解凍します。
解凍後のruntime/docディレクトリにある拡張子「jax」のファイル及び runtime/syntaxディレクトリの「help_ja.vim」ファイルを、それぞれ、 ユーザの設定ファイルディレクトリのdocディレクトリ、syntaxディレクト リにコピーします。ディレクトリが無い場合は、ディレクトリを作成してか ら、そのディレクトリにコピーしてください。
NOTE: docディレクトリに含まれるファイルの拡張子「jax」の、「ja」の部 分が、ヘルプの言語の種類を示しています。
$HOME/vimfiles/docに解凍ファイルのruntime/docディレクトリにある拡張 子が「.jax」のファイルを、そしてruntime/syntax/help_ja.vimを $HOME/vimfiles/syntaxに入れる。
vimエディタを起動し、設定ファイルディレクトリにコピーした拡張子 「jax」のファイルに、「:helptags」コマンドを実行します。windowsなら 次を実行する。
:helptags $HOME/vimfiles/doc
ここまでの設定を行うと、日本語環境のvimエディタでは、「:help」「: helpgrep」コマンド実行時に、インストールされた日本語のヘルプが先に検 索されるようになります。(日本語のヘルプで見つからなかった場合は、英 語のヘルプも検索します。)」
Vim には独自のスクリプト言語が備わっており、それを用いればマクロで対 応するのが難しいような複雑な作業を自動化できる。Vim のスクリプトは -s オプションを付けて起動したり、いわゆるプラグインディレクトリ内に 入れたりすれば読み込まれる。':source' コマンドでもスクリプトが読み込 まれ実行される。Vim スクリプトの例に Vim の設定ファイルがあり、UNIX や Linux では .vimrc、Windows では _vimrc というファイル名になってい ることが多い。このファイルは起動時に自動的に実行される。Vim のスクリ プト言語ではコマンドラインのコマンドが全て利用でき、':normal' コマン ドで通常モードの全てのコマンドも使うことができる。この言語では数と文 字列の二つのデータ型が用意されている。ブール値は数で実現され、0は偽 でそれ以外の数は真と評価される。また、重要な比較演算子や基本的な算術 演算子もある。制御構造も用意され、if文や while文が使える。さらにユー ザが自前の関数を定義でき、100を超える定義済み関数を利用できる。作成 したスクリプトはデバッグモードでテストすることができる。
Wikipediaからリンクが貼ってあるだけにvimについての詳しい情報がある。 tips(小技、こわざ)がとても参考になる。

vimスクリプトのftplugin/changelog.vimを読む

vimにはChangeLogを作る便利のためにデフォルトで ftplugin/changelog.vim及びsyntax/changelog.vimなるスクリプトが入って いる。ftplugin/changelog.vimの終わりのほうに次がある。この内容を理解 したくてヘルプを見ながら解読に取り組むことになった。

ChangeLogファイルを開いているときに「\o」(バックスラッシュと小文字の オー)を打つとChangeLogファイルに日付、(執筆者の)名前、メールアドレス を並べた一行(ヘッダー行)が挿入され、次の行はタブでインデントされて項 目始まりのしるしとなるアスタリスクとスペースが挿入されて、その直後に カーソルが置かれる。そこへ変更記録のメモを書き加える。

ChangeLogはソフトウェアのプログラムを作るにあたって、その作業記録の ために使うものである。編集中のプログラムファイルのあるディレクトリに ChangeLogと名付けたテキストファイルをつくり作業の覚え書きをメモして ゆく。

changelog.vimの使い方は二通りある。一つは、自分でChangeLogを開き(コ マンドモードで)「\o」を打つと日付などのヘッダー行と項目初めのアスタ リスクが自動挿入されてインサートモードになる。

もう一つは、編集中ファイルのバッファのコマンドモードで「\o」を使 う。既にChangeLogのバッファがあればそれに新しい項目が書き込めるよう にする。もしChangeLogのバッファがなかったら編集中ファイルのディレク トリにあるChangeLogファイルを開いて新項目を書き込めるように準備をす る(編集中ファイルのディレクトリにChangeLogファイルがなかったら何も しない)。

meadow(emacs)のChangeLogモードでは、編集中ファイルのバッファで「C-x 4 a」を打つとChangeLogファイルが開かれてvimと同じように書き込みの準 備がされる。もし編集中ファイルのディレクトリ(カレントディレクトリ)に ChangeLogファイルが見つからないときはカレントの親ディレクトリから ChangeLogファイルを見つけようとする。こうして再帰的にルートディレク トリまで遡ってChangeLogを検索する。それでも見つからない場合はカレン トに保存することになるChangeLogのバッファをつくる。

emacs流儀が便利なのは、例えばホームディレクトリに一つだけChangeLogを 作っておけばホームディレクトリ配下のサブディレクトリにあるどのテキス トファイルを編集中でも「C-x 4 a」でホームディレクトリのChangeLogを書 き込み準備済みで開くことができる。そうなると個々の変更記録がどのディ レクトリのどのファイルについてのものかを書き込む必要がある。emacsの ChangeLogモードでは「C-x 4 a」で呼び出した編集中のファイル名を ChangeLogに自動挿入してくれる。

すべてのメモ書きをホームディレクトリにある唯一つのChangeLogファイル に書き込めるので記録を検索するには便利になる。方々のディレクトリにあ るテキストファイルの変更記録を一ファイルに詰め込むことは便利な面もあ るが不便もある。vimのようにディレクトリ毎にChangeLogを置けば記録され る分野が同じになってよいかなと思う(テーマ毎にディレクトリを作ってい るから)。

vimによるChangeLogでは、それをルートディレクトリまで再帰的に探すこと をしない。編集中ファイルのカレントディレクトリにChangeLogがあるもの としている。再帰的な検索をしないことをスクリプトを解読して確認した い。それはftplugin/changelog.vimの終わりに書かれている。

" Add the Changelog opening mapping
nmap <silent> <Leader>o :call <SID>open_changelog()<CR>
function! s:open_changelog()
  if !filereadable('ChangeLog')
    return
  endif
  let buf = bufnr('ChangeLog')
  if buf != -1
    if bufwinnr(buf) != -1
      execute bufwinnr(buf) . 'wincmd w'
    else
      execute 'sbuffer' buf
    endif
  else
    split ChangeLog
  endif
  call s:new_changelog_entry()
endfunction

コメントの少ないvimスクリプトの場合は中身を解読しないと挙動がつかめ ない。コメントが無いときはスクリプト自体がマニュアルという ことになる。ごく短いスクリプトにはそういうものが多い。親切なものにな ると詳細な説明がコメントとして書き込まれてヘルプファイルとして取り出 せる仕組みのあるものがある(Perlなど)。ftplugin/changelog.vimの冒頭に 次の説明がある。

Local Mappings:
  <Leader>o -
      adds a new changelog entry for the current user for the
      current date.
Global Mappings:
  <Leader>o -
      switches to the ChangeLog buffer opened for the current
      directory, or opens it in a new buffer if it exists in the
      current directory.  Then it does the same as the local
  <Leader>o described above.
Notes:
  run 'runtime ftplugin/changelog.vim' to enable the global mapping
  for changelog files.

この説明書きをスクリプト上で確認したい。上記スクリプトに現われる function, call, filereadable, bufnr, execute, bufwinnr, wincmd, sbuffer, split, callなどはvimスクリプトの組み込み関数である。それら が何をするものであるかはvimのコマンドモードで、たとえば「:help filereadable」と打てば説明が読める。なお、bufがバッファ番号を表す変 数であることはコマンドの前後周辺から分かる。

まず、filereadable('ChangeLog')により、カレントディレクトリに 「ChangeLog」ファイルが無ければ何もしないで終わる。ChangeLogがあるな らbufnr('ChangeLog')によりChangeLogのバッファがあるかどうかを調べ る。ChangeLogのバッファが存在しないときは-1が返る。そのときは「split ChangeLog」が実行される。

このsplitコマンドが一番の難題であった。「:help split」でヘルプを引い ても分からない。表示されたヘルプの場所から下方向にスクロールしたとこ ろにある「:help split_f」で直行できるヘルプの内容が求めるものであ る。

引き数のある「split ChangeLog」は画面を二分割してその一方にカレント ディレクトリにあるChangeLogファイルを読み込む。もしChangeLogファイル が無ければカレントディレクトリに保存するようにセットされたバッファ (新規ファイル)が開かれる。

なお、vimのコマンドモードから「:split ChangeLog」とすればカレント ディレクトリにChangeLogがなくてもバッファが開く。しかし ftplugin/changelog.vimを使って「\o」を使うときには上記のユーザー定義 関数s:open_changelog()の冒頭にあるif文からreturnになり「split ChangeLog」コマンドに届かない。拒否(「\o」で何も起こらない)されたら カレントディレクトリに「:e ChangeLog」で新規ファイルのバッファを自前 で作ってから再び「\o」を実行すればよい。

既にChangeLogのバッファが作られている場合はその名前のウィンドウがあ るかどうか(vimの分割画面の中にChangeLogがあるか)をbufwinnr(buf)で調 べる。ChangeLogのウィンドウが無ければ「execute 'sbuffer' buf」により ウィンドウを分割してChangeLogバッファを表示する。ChangeLogがウィンド ウに表示されたら新しいエントリを書き込むためのユーザー定義関数である s:new_changelog_entry()を呼び出す。

splitコマンドについてインターネット検索したところ「split {file}」は 画面分割して一方にfileを読み込むとある。さっそくvimのコマンドモード から「:split {file}」を打つとfileを読み込んでくれる。splitは画面分割 専用のコマンドではなくて引き数としてファイル名を与えると画面分割する と同時にその一方にファイル読み込むのである。vimのコマンドが多すぎて 見つけられなかった。結局ftplugin/changelog.vimからChangeLogファイル を呼び出す手順を読み取るのにまる一日掛かった。

vimのコマンドモードにおける実験で「:sprit filename」の働きを確かめる ことができる。コマンドモードにおいて「:split ChangeLog」を実行する。 もしカレントディレクトリにChangeLogファイルが存在するなら画面が二分 割されて一方にChangeLogが開く。存在しないならばカレントディレクトリ に保存することになるChangeLogバッファが開く。なお、カレントディレク トリを知るには「:pwd」を使う。

このスクリプトはChangeLogのファイル名をChangeLogに決め打ちしている。 もしカレントディレクトリにあるChangeLogファイルのバッファがあり、それ とは別ディレクトリにあるChangeLogファイルのバッファもあるとき「\o」で 開かれるChangeLogがどちらになるかは不定な気がする。また、編集中の(アク ティブな)バッファのファイルの所属ディレクトリがカレントディレクトリに なるかどうかも分からない。

(注)~/_vimrcに「set autochdir」を設定すると現在編集中の(アクティブ な)バッファのファイルの所属ディレクトリがカレントになる。ヘルプで「: help autochdir」とすると説明が読める。デフォルトではオフになってい る。~/vimrcに「set autochdir」と記述するかvimのコマンドモードから「: set autochdir」を打つ。オフにするには「:set noautochdir」を使う。な お、ヘルプの注意書きに「このオプションがオンになっていると動かないプ ラグインがある」と書かれている。アクティブバッファを切り替える度に 「:pwd」を使うとアクティブバッファになっているファイルのディレクトリ に変わることが確かめられる。

現用のwindows版のvim7.2に新しいvim7.3のftplugin/changelog.vimと syntax/changelog.vim(こちらは変更されてないように見える)を試しに入れ てみたけれどエラーになる。スクリプトの中身を見るとカレントディレクト リからルートまで遡ってChangeLogを探すようになっているらしい。

(注)vim7.2にvimの公式サイトにある次のスクリプトを入れると再帰的に ルートまで遡ってChangeLogを探してくれるし、編集中ファイル名も挿入し てくれる。
gnuchangelog : Changelog support like Emacs/GNU
http://www.vim.org/scripts/script.php?script_id=1631

vimでChangeLogを使うにはそれ用のスクリプトがデフォルトで付属してい る。使うにはChangeLogに記録される(執筆者の)の名前とメールアドレス及 び日付形式を指定する次を~/_vimrcに書く。

let g:changelog_timeformat = "%Y-%m-%d"
let g:changelog_username = "name  mail-address"

そして「\o」をグローバルマッピングにするためには ftplugin/changelog.vimに書かれているように次を~/_vimrcに書く。これを 書かないと編集中ファイルのバッファのコマンドモードで「\o」を打っても 画面分割されずChangeLogも表示されない。単にカーソルがある行の下に新 規入力行が開いたインサートモードになるだけとなる。コマンドモードで 「o」(小文字のオー)を押したインサートモードにしかならない。 なお、ChangeLogのバッファで「\o」すると日付を入れたインサートモード になる。

runtime vimfiles/ftplugin/changelog.vim

これだけではエラー表示となりChangeLogは開いても書き込み準備されな い。次を~/_vimrcに書き加えたら正常に動くようになった。

filetype plugin on

ChangeLogについて調べ始めてから、その記録をChangeLogに書くようにして いる。「あれならこうである」「あれするとこうなる」というようなメモ書 きをChangeLogに記録する。新しいことはどこから手をつけてよいのやら五 里霧中状態である。そんな中でこれこそ重要と思ったことを箇条書きにして 積み重ねてゆくことで少しずつ核心に迫ってゆく。確認できたことを書くこ とで記憶を確かにする。疑問点を書き留めて忘れないようにする。それを ChangeLog形式に書くことでChangeLog自体の便利さを知ることができた。

meadow(emacs)とvimの両方でChangeLogを使うために同時進行で使い方を調 べる。やはりChangeLog自体がemacsを使う人達によって考えられたものらし くemacsのChangeLogモードのほうが高性能である。使い始めてから常用の ツールになるまでに一週間くらいかかったことがChangeLogに記録された。

| | コメント (0) | トラックバック (0)

« 2011年1月 | トップページ | 2011年3月 »