反省はしても後悔はしない

Vim とか備忘録とか。それと関数型言語勉強中

Vim 7.4 からの ocaml.vim の変更点

Vim の次期バージョンである Vim 7.4 *1から、デフォルトの ftplugin/ocaml.vim が変わります。 というかデフォルトのやつがいろいろひどかったので僕がパッチを書きました。

パッチを書くにあたり、github の vim-jp の人たちにいろいろ教えてもらいました。ありがとうございました。

変更点

  • global なマッピングを排除してすべて buffer-local なマッピングに

一番許せなかったやつです。型を表示させる <LocalLeader>t がなぜか global なマッピングになっていましたが、最新版では buffer-local になっています。

  • すべてのコマンドに <Plug> によるインターフェースを追加

既存のキーマップを変えたい場合に便利です。

<Plug>マッピング デフォルトの割り当て 機能
<Plug>OCamlSwitchEdit <Localleader>s ml と mli を切り替え
<Plug>OCamlSwitchNewWin <Localleader>S ml と mli を切り替え(分割して開く)
<Plug>OCamlPrintType <Localleader>t 型を表示

デフォルトのマッピングをさせたくない場合は vimrc に let g:no_ocaml_maps = 1 と書きましょう。

  • きもい abbrev を削除

ASS で assert (0=1) とかに展開されるなどという設定があったのですが、こういう個人的な設定はデフォルトの ftplugin にはふさわしくないので削除。他の ftplugin でも abbrev を設定しているようなものはほとんどないようですね。欲しい人は自分で vimrc に書きましょう。

*1:正確には、アルファ版の Vim 7.4a.047

おすすめの :help まとめ

この記事は Vim Advent Calendar 2012 の 240 日目の記事です。 昨日は id:thinca さんの 空間を飛び越えろ!portal.vim を作りました でした。

:help について

:help といえばおなじみ Vim のヘルプを引くためのコマンドです。

:help の引き方については過去の良質な記事を参照しましょう。

しかし、:help はあくまでもリファレンスであるため、調べたい対象がある程度わかっている場合でなければ望んだ情報にたどり着けません。 そこで、今回は膨大な :help のページの中からおすすめを紹介します。

一番最初の :help

:help

引数なしで :help を起動します。:help から見れるページの目次が閲覧出来ます。気になる項目があれば <C-]> で閲覧してみましょう。

ユーザマニュアル

:help usr_toc

Vim の使い方や機能が体系的にまとまっています。とりあえず、Vim 初心者の人は初級編の :help usr_01 から順番に読んでいきましょう。Vim に慣れた人でも時間があるときに全部読んでみましょう。新しい発見があるかもしれません。

クイック・リファレンス

:help quickref

Vim のよく使うコマンドを網羅したクイックリファレンスです。機能ごとに分類されています。クイックリファレンスなのに約 1400 行あります。Vim にはそれだけ膨大なコマンドがあるってことですね。これも時間があるときに目を通してみるといいとおもいます。詳細な説明を読みたければ <C-]> です。

:help index

Vim の(ほとんど)すべてのコマンドがまとめてあります。こちらはアルファベット順になっています。

オプションまとめ

:help option-list

一番最初に vimrc を書くとすればまずはオプションの設定でしょう。このページでどんなオプションがあるかを調べて自分だけの Vim にカスタマイズしましょう。実はこのページは先ほど紹介した quickref の中にあります。

Tips

:help tips

Vim Advent Calendar の中でも Tips 系の記事は人気ですね。Vim のヘルプの中にも Tips のページがあります。一度覗いてみると良いでしょう。

Vim の起動引数

:help startup-options

Vim には起動するときにオプションとして引数を渡せます。たとえば vim --noplugin でプラグインを読み込まない、などです。このページでどんな起動引数があるか調べましょう。

Vim のウィンドウについて

:help windows

Vim のウィンドウは水平や垂直に分割できたりしてかなり高機能なのですが、それ以外にもいろいろ機能があります。このページに Vim のウィンドウについての情報があります。ちなみに、OS の Windows について知りたい場合は :help win32 です。

Vim のタブページについて

:help tabpage

あまり使いこなされていないという噂の Vim のタブページについての help です。<Tab> と混同しないようにしましょう。

Vim正規表現

:help pattern-overview

Vim正規表現は結構独特で記号なんかどれをエスケープすべきかいつも忘れます。そんな時はこのページを見に行きましょう。Vim で使えるパターンがまとめてあります。

Vim script

:help usr_41

Vim を本気でカスタマイズしようと思ったら Vim script を書かざるを得ません。このページでは Vim script について学ぶことができます。変数、条件文、ループ、関数と Vim script の基本的な部分かプラグインの書き方まで体系的に説明されています。量が多い (2400 行ほど) ので一気に読むのは大変です。最初は基礎的なところだけでいいでしょう。

Vim script の関数一覧

:help function-list

上の usr_41 の一部なのですが、Vim script で使える関数の一覧が機能ごとにまとまっています。

:help functions

こちらはアルファベット順です。

プラグインを書く

:help write-plugin

これも usr_41 の一部ですが。Vim script に小慣れてきたら自分でプラグインを作ってみたくなるものです。プラグインの書き方については良質な記事が Web 上にもありますが、:help に書いてある方も読んでおくといいかもしれません。

:help write-filetype-plugin

ftplugin を作る場合はこちら。

:help help-writing

プラグインを書いたら必ずドキュメントも書きましょう。このページでは自作プラグインのためのヘルプの書き方が説明されています。

Vim の哲学

:help design-goal

Vim そのものを開発するための設計目標が書かれていますが、Vim はかくあるべきという哲学とも言えます。特に design-not には Emacs との考え方の違いに言及されているので一度読んでおくと良いです。

最後に

Vim の :help は情報の宝庫です。:help をうまく活用して Vim の戦闘力を高めましょう。 ちなみに、vimrc 読書会では「歩く :help」みたいな人がたくさんいて気軽に質問に答えてくれます。

明日は id:manga_osyo さんです。*1

*1:おしょーさんすごい

あなたの知らない Vim ~ デフォルトの ftplugin 達 ~

この記事は Vim Advent Calendar 2012 の 214 日目の記事です。 昨日は id:manga_osyo さんの Vim で Web ページを :source する でした。

Vim では何も設定せずとも様々なプログラミング言語のためのシンタックスがはじめから提供されています。マニアックなプログラミング言語を編集しようとしていきなりシンタックスで色付けがされてたりするので驚きです。

実は、Vim にはシンタックスだけでなくプラグインみたいなものも言語別にあります。それが ftplugin です。言語によってコメントの仕方やコンパイルエラーの解析*1だけのものからマッピングやコマンドなどの機能まで提供されているものまであります。しかし、これらは help に書かれておらず調べるには自分でソースを読まないといけないのでなかなか知られていないのが現状です。

そこで、今回はこの知られざる ftplugin の世界を紹介したいと思います。

いざ旅立とう 知られざる ftplugin の世界へ

面倒なプラグインのインストールや設定はほとんど不要です(基本的には)!今お使いの Vim (7.3) ですぐに動作します。

追記 filetype plugin on を vimrc に書く必要があります。完全に忘れてた。thx thincs さん。

git

Git のエディタを Vim にしているとコミットするときに Vim が立ち上がりますね。え、Git の設定をしていない?それはいけない。今すぐ設定しましょう!

git config --global core.editor vim

さて、Git の何らかの編集(commit や rebase -i とか)をするときには Vim 上ではいろいろ便利な機能がデフォルトで使えます。

コマンド 機能 備考
gf, <C-w>f など カーソル下のファイルを開ける diff 表示の時の a/hoge b/hoge みたいなのでも開ける。ちなみに、gf よりも <C-w>f とか <C-w>gf とかの方がコミットメッセージ編集用のバッファが迷子にならないのでおすすめ
K カーソル下のリビジョンで git show する rebase -i の時はカーソル下じゃなくてもOK。すごく便利。ちなみに、Vim のカレントディレクトリが全然別のところにあっても正しいパス上で実行されます
:DiffGitCached コミットされる予定のファイルの差分をプレビューウィンドウで見る コミットメッセージの編集時のみ。ちなみに、開いたプレビューウィンドウは q で閉じれるようになっている
:Pick rebase -i のあれを pick にする rebase -i の編集時のみ。マッピングを設定すると便利かもしれない。
:Squash rebase -i のあれを squash にする 同上
:Edit rebase -i のあれを edit にする 同上
:Reword rebase -i のあれを reword にする 同上
:Fixup rebase -i のあれを fixup にする 同上
:Cycle pick, squash, edit, reword, fixup を順に切り替える 同上

ちなみに、書いた人は fugitive や pathogen や rails.vim の作者の Tim Pope 氏のようです。信頼と実績の ftplugin ですね。

ruby

Ruby 界隈は Vimmer が多いと勝手なイメージを持っています。

コマンド 機能 備考
K カーソル下のキーワードを ri で調べる
キーワードの上にマウスカーソルを置く マウスカーソル位置のキーワードを ri で調べてバルーンで表示 GVim のみ。set ballooneval しておく必要があります
]m, [m 次(前)のメソッド定義(def)に移動
]M, [M 次(前)のメソッド定義の終わり(end)に移動
]], [[ 次(前)のクラス、モジュール定義(class, module)に移動
][, [] 次(前)のクラス、モジュール定義の終わり(end)に移動

ちなみに、vim-ruby というプラグインを入れている人も多いと思いますが、vim-ruby はこれらのデフォルトの ftplugin に追加で textobj とかを提供しているので vim-ruby の有無に関係なく上記のコマンドは使えます。

python

私自身は python はほとんど書けないのですがとりあえず、紹介します。 そういえば、最近 VimPython IDE 化する記事がありましたね。設定が面倒くさくてやっていない人もとりあえず、デフォルト機能くらいは覚えておくといいんじゃないでしょうか。

コマンド 機能 備考
]], [[ 次のトップレベルのクラス、メソッド定義(class, def)に移動 nnoremap しかないのでビジュアルモードでは使えません
]m, [m 次のクラス、メソッド定義(class, def)に移動 nnoremap しかないのでビジュアルモードでは使えません
gf, <C-w>f など from, import とかに書いてあるファイルを開く hoge.fuga は hoge/fuga.py みたいな感じで開かれます。ただし、あまり賢いことはしてくれないようです。

ocaml

静的型付け関数型言語です。楽しい! OCaml は割りとデフォルトでもいろんな機能があります。ちなみに、同じく静的型付け関数型言語Haskell の ftplugin には最低限の設定しかないです。

コマンド 機能 備考
<LocalLeader>s ml と mli ファイルを切り替える
<LocalLeader>S ml と mli ファイルを切り替える(分割して開く)
<LocalLeader>c コメントアウト ノーマルモードのときは行コメント、ビジュアルモードのときは複数行コメントになります
<LocalLeader>C コメントアウトを解除
(インサートモードで)ASS (assert (0=1) ( XXX )) を挿入 iabbrev なので何か他のキーを押した時に展開されます
<LocalLeader>t カーソル下の項の方を表示 annot ファイルが存在している必要があります

<LocalLeader> はデフォルトで \ になっています。let g:maplocalleader = ','などのようにすれば変更できます。

sql

突然の SQL!!! お仕事とかで書く人とかいそうですね。私は資格試験のために勉強しただけで書いたことないです...。ちなみに、ここで紹介する以外に割りと細かいオプションを設定できるようです(ソースを見る限り)。たぶんいろんな方言に対応させるためなんでしょうね。正直全然わからないので気になる人はソースを読んでみるといいと思います。

コマンド 機能 備考
]], [[ 次(前)の begin に移動
][, [] 次(前)の end に移動
]}, [{ 次(前)の create 文に移動 どの文に移動するかはg:ftplugin_sql_statementsで設定可能
]}, [{ 次(前)の create 文に移動 どの文に移動するかはg:ftplugin_sql_statementsで設定可能
]" 次のコメントの始まりに移動
[" 次のコメントの終わりに移動

おわり

割りとメジャーそうな(独断)言語の中で便利な機能が定義されているのは以上でした。もっとあるかと思ったのですが。。。 気になる方は $VIM/vim73/ftplugin 以下を探索してみてはいかがでしょうか?

明日は @supermomonga さんです。

*1:QuickFix で使います

vim-hier をフォークしてみた

背景

最近 watchdogs.vim の便利さ加減がもうどうしようもないのですが、vim-hier が行にしかハイライトしないので、長い行だとどの桁でエラーが出ているのかよくわからないという問題がありました。

ということでちょっと改造した

QuickFix が持っている情報には (あれば) col という名前でエラーの原因となった桁番号が取得出来ます。ということで Vimキモい素晴らしい正規表現を駆使してエラーのあった桁以降をハイライトするようにしてみました。

cohama/vim-hier

f:id:cohama:20130618220640p:plain

1行なのに処理たっぷりな関数型言語なんかでは非常に有用ですね。

残念ながら

マルチバイトな文字があるとずれます。

なんか Vim の relativenumber オプションの仕様が変わったっぽい

私は set relativenumbr するのが好きです。ちょっと前のパッチでカーソルのある行だけ普通の行番号を表示、それ以外で相対行数の表示という感じになっていたので気に入って使ってました。

ところが、最新のパッチ*1を含めてビルドするとカーソル行の現在行数表示の仕様が変わってしまったようです。 具体的には、set numberset relativenumbr が両方指定されているとカーソル行が現在行数、その他が相対行数になるようです。

私は numberrelativenumbr をトグルさせるコマンドを作ってたのですが、それを作り直すはめになりました。

以下が最新のパッチに対応しつつ、前のバージョンでも使えるトグルコマンドです。

nnoremap [Toggle]n :<C-u>call ToggleNumber()<CR>
nnoremap [Toggle]r :<C-u>call ToggleRelativeNumber()<CR>
function! ToggleNumber()
  if &l:number && !&l:relativenumber
    setlocal nonumber
  else
    setlocal number
  endif
  setlocal norelativenumber
endfunction
function! ToggleRelativeNumber()
  if &l:number && &l:relativenumber
    setlocal nonumber
    setlocal norelativenumber
  else
    setlocal number
    setlocal relativenumber
  endif
endfunction

*1:多分1115くらいから

Linux Mint 15 をいれたときにやることリスト

Linux Mint 15 が出てたので入れました。
そのとき最初に行う設定のメモ。
これは完全に自分用の備忘録です。いつも忘れるので。

初期状態のディレクトリを英語表記にする

ターミナルから使うときは日本語だとつらいので。

$ env LANGUAGE=C LC_MESSAGES=C xdg-user-dirs-gtk-update

Update Names -> 一旦ログアウト -> 次回から表示しないにチェック -> 古い名前のままにする
参考
Ubuntu 13.04をインストールした直後に行う設定 & インストールするソフト

Vim をコンパイル

これは前のエントリを参照。

Google Chrome を入れる

ブラウザは Chrome 使ってますね。
最初から入ってる FireFoxgoogle.co.jp にアクセスすれば OK。

Dropbox を入れる

Dropbox 重要。
スタート -> ソフトウェアの管理
から nautilus-dropbox をインストール。
インストール後、スタート -> Dropbox 起動でアカウント設定などを入力すれば OK。

Workspace の数を変更

デフォルトが2なんだけど、4つくらいは使いたいよね。

$ gsettings set org.cinnamon number-workspaces 4

なんか GUI じゃ設定できないのかな。調べたけどわからんかった。
あとはパネルに Workspace 切換器を設置すると便利。

Mozc を入れる

インプットメソッドは Anthy より IBus-Mozc 派なので。

$ sudo apt-get install ibus-mozc

インプットメソッドを再起動後、インプットメソッドを右クリック -> Preferences -> Input Method -> Customize active input methods にチェックを入れる -> Select an input method から Japanese > Mozc を選択 -> Add

ssh を入れる

外部から繋ぎたい時もあるよね。

$ sudo apt-get install ssh

Git を入れる

そういえば、いれてなかった。
Vim のプラグイン管理に必要なので。バージョン管理にも使いますがおまけです。(お

$ sudo apt-get install git

鍵を作る

GitHub にプッシュするときとかに必要なので。

$ ssh-keygen

鍵を GitHub に登録

~/.ssh/id_rsa.pub を登録する。

dotfiles とかを git cloen

.zshrc とか .gitconfig とかは github で管理してます。

シェルを zsh に変える

bashzsh の違いとかよくわかってないけど、割と前から zsh 使ってるので。

$ sudo apt-get install zsh
$ chsh
  .. /bin/zsh

そしてログオフ。

nodebrew を使って JavaScript 環境を入れる

職業 JS プログラマなので。
node は nodebrew で入れます。

$ sudo apt-get install curl
$ curl https://raw.github.com/hokaccha/nodebrew/master/nodebrew | perl - setup

zshrc にて ~/.nodebrew/current/bin を PATH に追加します。

$ nodebrew install stable
$ nodebrew use stable
$ npm install -g coffee-script
$ npm install -g jshint

OPAM 使って OCaml 環境を入れる

OCaml 面白いよ!
まず opam いれます。公式見ると 64 ビットだと apt で入れられるっぽい(ホントか?)ですが、私の場合は 32 ビットにしているのでソースからビルドします。

$ sudo apt-get install ocaml ocaml-native-compilers camlp4-extra m4
$ git clone https://github.com/OCamlPro/opam
$ git reset --hard latest
$ cd opam
$ ./configure --prefix=/path/to/opam
$ make
$ make install

.zshrc で $PATH に OPAM のパスを追加するのと $ export OCAML_ANNOT=1 という環境変数を定義しておく。

$ source ~/.zshrc
$ opam init
$ . $HOME/.opam/opam-init/init.zsh > /dev/null 2> /dev/null || true
$ opam isntall spotinstall
$ opam switch 4.00.1+annot
$ eval `opam config env`

あと、OCaml 用の便利ツールもインストールしておく。

$ opam install spotinstall
$ eval `opam config env`
$ spotinstall -v ocaml
$ opam install ocamlspot
$ eval `opam config env`

rbenv で Ruby その他

職業 Rubyist なので。(入れるの忘れてた)

$ git clone https://github.com/sstephenson/rbenv ~/.rbenv
$ git clone https://github.com/sstephenson/ruby-build ~/.rbenv/plugins/ruby-build

.zshrc に以下を追加

$ export RBENV_HOME=~/.rbenv
$ export PATH=$RBENV_HOME/bin:$PATH

執筆時点での最新は ruby 2.0.0-p195 なのでこれをインストール

$ rbenv install 2.0.0-p195
$ rbenv global 2.0.0-p195
$ source ~/.zshrc
$ ruby -v

bundler 重要

$ gem install bundler
$ rbenv rehash

このままだと gem をインストールするたびに rbenv rehash しないといけないんだけど、自分の場合はどうせ bundler 使ってプロジェクトローカルにしか gem を入れることがないので気にしない。

あと、rails4 環境の作り方

$ mkdir myapp & cd myapp
$ bundle init
$ echo 'gem "rails", "4.0.0.rc2"' >> Gemfile
$ sudo apt-get install libsqlite3-dev
$ bundle install --path vendor/bundle
$ bundle exec rails new . -T

参考

まだあった気がするけど、とりあえず、これくらいで。

OCaml のソースコードの型を表示したり定義にジャンプしたりする Vim のプラグイン作った

この記事は Vim Advent Calendar 2012 の 185 日目の記事です。
昨日は id:deris さんの Vimでできる脱出系パズルゲーム でした。

はじめに

OCaml という静的型付けの関数型言語があります。同じく静的な型をもつ関数型言語である Haskell とは異なり、副作用をもつ関数を定義したり破壊的な操作も行うことができます。

ところが、OCaml 界隈ではどうやら Emacsデファクトのエディタらしく、Vim での開発環境の情報は非常に少ない、またあったとしも情報が古くなっているものが大半というのが現状です。

参考 OCaml.jp > 開発環境
(追記:更新されたみたいです)

私は Vim でも OCaml をやりたいと思い、プラグインを開発することにしました。

OCamlSpotter (ocamlspot) について

実は、OCamlソースコードから型情報や定義情報を取得するためのプログラムはすでにあります。OCamlSpotter と言います。
インストールはこの辺が参考になりました。
OSXへOCamlの開発環境をOPAMで構築し直した - tmaeda 日記(2012-10-28)
例えば、下のような階乗を計算する OCaml のコードがあったとして、このファイルの 5 行目 12 桁目 (つまり print_int (factor 5) の factor の f) の位置を指定して OCamlSpottre を起動すると以下の様な出力が得られます。

$ ocamlspot test.ml:l5c12
load /home/cohama/tmp/test.cmt
Pathreparse: not supported: factor (Failure("The given position is not clear enough"))
Use: Value, factor__1008
Type: int -> int;
XType: int -> int;
At: Expr;
Tree: l5c11b78:l5c17b84
XTree: </home/cohama/tmp/test.ml:l5c11b78:l5c17b84>
In_module: 
Val: val factor : int -> int
Spot: </home/cohama/tmp/test.ml:l1c8b8:l1c14b14>
BYE!

この出力から型情報や定義情報なんかが取得できます。あとはこれを Vim Script でパースするだけなので簡単ですね。

というわけでプラグイン作った

実は前述の OCamlSpotter には公式の Vim 用のスクリプトも用意されているのですが、Emacs 版に比べると機能が少なく、また実装もいろいろ気に入らなかった*1ので自作することにしました。

the-ocamlspot.vim と言います。インストールは NeoBundle 等を使えば簡単に出来ます。依存する Vim プラグインはありませんが、OCamlSpotter のインストールは必須です。

NeoBundle 'cohama/the-ocamlspot.vim'

使ってみる

the-ocamlspot.vim は特に設定をしなくてもある程度最初から使えるようになっています。*2

型の表示

型を表示させたい項にカーソルをもっていってしばらく待ちます(この時間は set updatetime で設定出来ます)。

上図のようにエコーエリアに型の情報が表示されます。また、現在の項と定義位置がそれぞれ違う色でハイライトされます。ちなみに、<Leader>ot で明示的に呼び出すこともできます。


あと、GVim をお使いの場合にはマウスカーソルのホールドでも型情報の表示が可能です。

この時はエコーエリアではなくバルーンで表示されます。

定義位置の表示

定義位置へのジャンプもできます。調べたい項の上でおもむろに <Leader>op を押します。

この様に定義されたファイルの定義された位置がプレビューウィンドウので表示されます。まだプレビューウィンドウのハイライトが実装されていないので少し分かりづらいですが、、、近日中に実装する予定です。しばしお待ちをば。

the-ocamlspot.vim の今後について

今後追加で実装したいものとしては

  • (echodoc のように) 型情報の表示のときに簡単な色をつける
  • 定義位置の表示だけじゃなくてジャンプも
  • 定義されたファイルの開き方をプレビューウィンドウ以外にも水平、垂直分割やタブで開く

などなど。
ただ、私自身が OCaml 超初心者なのでなにが必要なのか分かっていないというのもあります。OCaml の習得も課題ですね。

最後に

今回は作ったプラグインの紹介がメインでしたが、そのうち VimOCaml 開発環境を記事にまとめたいと思っています。関数型言語を始めてみたいという Vimmer の方も今までやむなく Emacs を使っていた OCamler の方もこれを機に VimOCaml プログラミングを始めてみてはいかがでしょうか?

次回は id:manga_osyo さんです。

*1:OCamlSpotter の作者の方は Emacs 使いだそうです。そう考えると Vim のスクリプトが用意されているというだけでも脱帽です。

*2:もちろん設定をカスタマイズすることも可能です!