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

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

Osaka.vim に行ってきたよ

この前の土曜日に Osaka.vim というのがあって、 「名古屋からすれば大阪なんて近所みたいなもんやろー」と思ってノリで行ってきました。

thinca さんのライブコーディング

quickmemo.vim というプラグインをライブコーディングしてました。 僕はこのプラグインの仕様とかよりも thinca さんのコーディングの仕方や Vim の設定の方ばかり目がいっていました。 p で貼り付けた部分がハイライトされるやつとか便利そうだと思って聞いたら、yankround.vim の機能だそうです。 yankround 便利そう。 あと、日本語入力が SKK でした。 あとあと、Vim script の関数とかスラスラ書けるあたりはさすが thinca さんすごいと思いました。

自由時間

もくもくタイムなのかと思っていたのですが、割とみんないろんなことしゃべってい賑やかでした。 僕は去年の末から開発がストップしていた某 Git 系プラグインの開発を再開すべく、自分が書いたコードを一生懸命読んでいました。 進捗は0でしたが、とりあえず開発再開の目処は立ったので良かったかなと。

LT のような何か

ゲリラ的に発表が始まっていました。 kozo2 さんのは T-Code とかいう日本語入力方法の話でした。これは近づいちゃいけない奴だと思いました。(褒め言葉)

itchyny さんは miv という自作のプラグインマネージャを紹介されていました。 これの面白いとこはなんと Haskell で書かれているところ。Vim プラグインというよりは Vim script 生成コマンドツールですね。 こういう仕組みはいろいろ応用できそうです。(しかし、現時点では特に思いついていない)

haya14busa さんはプラグインの作り方という感じの発表をされてました。 Vimプラグイン作ること自体の敷居はそこまで高くないよという旨の内容でした。 これを機にプラグイン開発者がどんどん増えればよいですね。

懇親会

お好み焼き美味しかったです。

帰りの新幹線

終新幹線で帰りました。 ちょうど車内にいるときに vimrc 読書会が始まったのでそれにも参加しました。 あと、なんと奇遇にも kyon_mm さんとばったり遭遇したりもしました。

おわりに

Osaka.vim とても楽しかったです。 新幹線ですぐ行けちゃうのでまた機会があったら参加したいです。

Nagoya.vim もそろそろ第2回を開催したいなと思いました。 (あとは会場さえあれば...)

Arch Linux (64bit) における SML# のビルド

どうやら巷では SML# をビルドするのが流行っているようなので、僕も乗っかってみました。 僕のメイン環境は Arch Linux (64bit) なのですが色々試行錯誤したらビルドできたので記録として残しときます。

Xubuntu 64bit でのビルドは、すでによんたさん (id:keita44_f4) が成功させているので僕もそれを参考にしました。

Xubuntu 64bitにおけるSML# 2.0.0のビルド - ししちにじゅうはち 4x7=28

32bit 用の gcc のインストール

32bit のバイナリを吐き出すために gcc-multilib を入れます。

sudo pacman -S gcc-multilib

普通の gcc とコンフリクトするというメッセージと共に上書きするか聞いてくるので yes と答えます。 なお、32bit のバイナリをインストールするには/etc/pacman.confmultilibリポジトリを有効にする必要があります。

GMP ライブラリのインストール

Arch Linux なら 32bit 版でもバイナリがあります。

sudo pacman -S lib32-gmp

LLVM ライブラリのインストール

Arch Linux なら 32bit 版でもバイナリがあります。

sudo pacman -S lib32-llvm

SML# のビルドの前に...

SML# のビルドでは LLVM 関連のパスを取得するのに llvm-config という実行ファイルを使っているみたいなのですが、Arch Linuxpacmanlib32-llvm をインストールした場合は llvm-config32 という名前になります。 これに対応させるため、SML# のソースに含まれる configure ファイルを編集します。

# configure の 4288 行目くらい
- set dummy llvm-config; ac_word=$2
+ set dummy llvm-config32; ac_word=$2

SML# のビルド

ここまでくればあとは SML# をビルドするだけ! ちなみに pacman 経由で 32bit バイナリを入れると /usr/lib32 以下にものができるのでそれをオプションで指定してやります。

./configure CC='gcc -m32' CXX='g++ -m32' \
    LD='ld -m elf_i386' \
    LDFLAGS='-L/usr/lib32' \
    --prefix=/opt/smlsharp-2.0 
make
sudo make install

まとめ

  • やっぱり 64bit は茨の道だった
  • そもそも SML# 書いたことないし文法も知らない
  • やってみたらできました

Vim で Coq 環境を整える

はじめに

昨日、スタート Ssreflect というイベントに参加して、Coq + ssreflect のハンズオン的なものをやりました。 Coq 環境といえば、Emacs の ProofGeneral が非常に有名です。 しかし、私は Emacs は終了の仕方すら分からないレベルの初心者なので Emacs + ProofGeneral ではチュートリアルの例題を打ち込むだけでも非常に苦労しました。

証明も普段使い慣れている Vim で何とかできないかと思い調べたところ、そこそこ良さ気な環境を構築できたので紹介します。

使用するプラグイン

以下の2つをインストールします。NeoBundle のようなパッケージマネージャを使用するのをおすすめします。

jvoorhis/coq.vim は Coq のシンタックスとインデント設定を追加するためのプラグインです。 vim-scripts/CoqIDE は Vim 上で CoqIDE の動作をエミュレーションするプラグインです。内部では coqtop を使っているようです。

インストール方法

NeoBundle 'jvoorhis/coq.vim'
NeoBundleLazy 'vim-scripts/CoqIDE', {
\ 'autoload' : {
\   'filetypes' : 'coq'
\ }}

使い方

Vim拡張子 .v のファイルを開くと自動的に色付けされるようになります。 適当に証明を書いて :CoqIDENext を実行すると、証明をひとつ進めることができます。 すると、Window が分割されて CoqIDE と同様に現在の情報が表示されるようになります。 証明をひとつ戻すには :CoqIDEUndo を使います。 :CoqIDEToCursor とするとカーソル位置まで証明を進めます。

f:id:cohama:20140427193733p:plain

色を変える

vim-scripts/CoqIDE のデフォルト設定では証明が済んだ部分の色はライトグリーンになっています。 これは白背景のカラースキームでは良いのですが、黒背景の場合は非常に見づらいです。 これを解決するには vimrc に下記のようにハイライト設定を書きます。

autocmd FileType coq highlight SentToCoq ctermbg=17 guibg=#000080

おわりに

Vim でも結構いい感じに Coq の環境が整えられました。 まぁ ProofGeneral と比べると (多分) 機能的に劣っているとは思いますが、どうしても Vim で証明したい人は試してみてはいかがでしょうか?

fugitive.vim をもっと使いこなす

この記事は Vim Advent Calendar 2013 の 16 日目の記事です。 昨日は id:deris さんの Vimmerなら2013年中に試しておきたい海外産Vim plugin 8選 - derisの日記 でした。知らないプラグインあったので時間ができたら試してみたいですね。

進捗ダメです

すみません。本当は自作プラグインを大々的に紹介するつもりだったのですが、進捗ダメでした。今日は fugitive.vim の小ネタについて書きます。 次回作にご期待ください。

fugitive.vim について

Vim から Git を便利に使うプラグインです。詳しくは

みたいなところを参照してください。 とりあえず、git status 見たり、git add -pVim の diff 機能を使って実行できたりしてとても便利です。

リポジトリのルートに cd する

あまり知られていないような気がしているのですが、

:Gcd

リポジトリのルートに :cd することができます。

:Gedit を使って違うリビジョンのファイルを開く

git を使っていると、違うブランチにあるファイルを開きたくなりますね。Gedit でできます。

:Gedit feature-branch:path/to/file

<リビジョン>:<ファイル名> で特定のリビジョンの特定のファイルを閲覧することができます。ただ、このコマンドは :edit 相当なので現在のウィンドウで開きます。他には :vsplit 相当の :Gvsplit などがあります。

: の前はリビジョンを指定します。ブランチ名や HEAD^ のような指定の仕方以外にも fugitive.vim が定義する便利な記法が使えます。

例えば、~3 だけで HEAD~3 と同様の意味になります。詳しくは :help fugitive-revision

そして、これらのコマンドはブランチ名およびファイル名の補完が効きます。ファイル名の補完に至っては、現在のワーキングディレクトリになくても入力したリビジョンにあれば補完されます。

:Gdiff で違うリビジョンとの diff を取る

:Gdiff といえば、git add -p がとても便利ですが、別リビジョンにある同ファイルとの diff を取ることもできます。

:Gdiff feature-branch

例えば、:Gdiff developdevelop ブランチとの diff を取ったり、:Gdiff ~3 で 3 つ前のコミットと diff 取ったりできます。

おわりに

  • 進捗ダメです
  • fugitive.vim は内部の実装汚いけど便利

明日は @cocopon さんです。

Vim で Ruby の def end とかを自動入力する vim-endwise を vim-smartinput で実装してみた

この記事は Vim Advent Calendar 342 日目の記事です。 昨日は id:leafcage さんの README.mdをVimのヘルプファイルから生成する - cafegale でした。とても素晴らしいプラグインですね。本プラグインでも早速活用させていただきました。

vim-endwise について

例えば Ruby では様々な構文の終わりを end というキーワードで表します。という訳で Ruby ではコードが end だらけになるわけですがこれをいちいち手で打つのは面倒です。これの自動入力を行ってくれるのが tpope/vim-endwise です。 例えば、

f:id:cohama:20131108004248p:plain

このときに <CR> を打つと、

f:id:cohama:20131108004315p:plain

このように end が自動で挿入されます。便利! Ruby の他には Lua, Vim script, sh, VB, Elixir に対応しています。

vim-smartinput と vim-endwise の問題点 について

ところで、私の大好きなプラグインのひとつに kana/vim-smartinput があります。これは (){} の自動入力を行ってくれるものです。 例えば、

f:id:cohama:20131108004351p:plain

このときに { を打つと、

f:id:cohama:20131108004402p:plain

さらに <CR> を打つと、

f:id:cohama:20131108004412p:plain

このように } が自動で挿入されます。C や JavaScript などの中括弧系の言語に便利ですね!

で、この2つのプラグインやってることは似ています。Ruby などの end を使う系は vim-endwise 、JavaScript などの {} を使う系は vim-smartinput という使い分けをしたいですね。

が、残念なことにこの2つのプラグインは競合します。両者ともインサートモード時の <CR> をマッピングしてしまうためです。 私は以前はこのようにして解決していました。

vim-smartinput と vim-endwise が競合した時の対処法 - 反省はしても後悔はしない

という訳で vim-smartinput を使って vim-endwise を実装してみた

vim-smartinput は Vim 界の神こと kana さん作のプラグインであり、非常に高い拡張性を持っています。つまり、vim-smartinput さえあれば vim-endwise の機能は実装できるのです!!

という訳で実装しました。

cohama/vim-smartinput-endwise · GitHubcohama/vim-smartinput-endwise

インストール方法は NeoBundle の場合は

NeoBundle "kana/vim-smartinput"
NeoBundle "cohama/vim-smartinput-endwise"

call smartinput_endwise#define_default_rules()

と書けば OK です。

これで vim-smartinput ひとつで全て実現できるので競合の問題は解決です。さらに、neocomplcache などを使っていると、補完ウィンドウと競合することがあるので、neocomplcache / neocomplete に対しても特別な競合対策を施してあります。 他のプラグインとの競合が極力避けらルのが本プラグインのメリットです。

一応機能としては vim-endwise になるべく近くなるように実装しています。コメントや文字列では展開されないといったことは実現できています。ただ、やはりある機能だけに特化したプラグインと汎用的なプラグインの差というのはどうしてもあります。具体的には searchpair を使った「すでに end などのが入力されていたらそれ以上 end を入力しない」ということを vim-smartinput で実装するのは難しくてやっていません。

あと、現在対応している言語は Ruby, Vim script, sh (zsh) の 3 つだけです。他のやつはほとんど書いたことないのでやる気が出ませんでした。もし必要なら issue とかに上げてもらえると対応するかもしれません。

おわりに

  • vim-smartinput は素晴らしいプラグインなのでみなさん使いましょう。
  • プルリク待っています
  • そして私は def end の展開には neosnippet を使っているのであった...

明日は @Linda_pp さんです。

'set relativenumber' で Vim のカーソルの縦移動とかを改善する

この記事は Vim Advent Calendar の 311 日目の記事です。昨日は id:osyo-manga さんの unite.vim の action の設定方法いろいろ でした。

set relativenumber

みなさん、Vim で行番号を表示していますか?行番号の表示は vimrcset number ですね。行番号を表示する機能はほとんどのテキストエディタでありますね。ところで、Vim にはちょっと変わった行番号の表示をさせることができます。

vimrcset relativenumber という記述を追加してみましょう。

f:id:cohama:20131007014842g:plain

上のように、現在のカーソルがある行からの相対行数を表示させることができます。なんか気持ち悪いですね。これがなにの役に立つのでしょうか?

j, k を使って目的の行へ素早く移動する

下のスクリーンショットで、hogehoge と書かれた行に移動したいとしましょう。

f:id:cohama:20131007014758g:plain

j 連打する方法や }L のあとで j k で微調整する方法、/ で検索する方法などが思いつきますね。ところで set relativenumber が有効になっているので、目的の行のところはカーソルから 10 行分下方にあることが分かります。この情報を使って 10j とすれば目的の行へ即座にジャンプすることができるようになります。

もちろん、通常の行数を表示させて <行数>G のように移動することもできます。が、この方法だと 1000 行くらいある場合に数字の入力が辛くなってしまいます。relativenumber を使った場合では入力する数字が高々 2 桁程度に収まるのでこちらの方が打ちやすいです。

オペレータとの合わせ技

下のスクリーンショットfoo の行から bar の行までを削除したいとしましょう。

f:id:cohama:20131007015013g:plain

relativenumber で表示されている行数を使うと、これは d6j で一発で削除することができます。6j が 6 行下に移動するモーションコマンドなので現在行と合わせて 7 行分が一気に削除されます。もちろん、削除以外のオペレータと組み合わせることもできます。

Ex コマンドでも

下のスクリーンショットhoge の行をカーソル行の下の行に移動させたいとしましょう。

f:id:cohama:20131007015202g:plain

さて普通に考えれば 4k で移動したあと yy4j で戻って p ですね。実は Ex コマンドを使う別の方法があります。:-4t.<CR> と打つだけです。:t:copy と同じ効果の Ex コマンドで、範囲で指定した行を引数で指定した行の下にコピーします。ここでは範囲として -4 つまり 4 行上の1行分、引数として . つまり現在行をしていしています。

relativenumber の仕様とか

さて、以上で relativenumber の紹介は終わりなんですが、実はこいつは Vim のバージョンによって微妙に仕様が異なります。それをすこしまとめておきます。

  • Vim 7.2 以前: relativenumberVim 7.3 から追加されたオプションなので 7.2 以前の Vim では使えません。諦めるか最新の Vim をビルドしましょう

  • Vim 7.3.786 以前: relativenumber が使えます。カーソル行の表示は常に 0 になります。

  • Vim 7.3.1114 以前: カーソル行の表示が絶対行数の表示になります。

  • Vim 7.3.1115 以降 (Vim 7.4 とか): numberrelativenumber の組み合わせでカーソル行の表示が変わります。nonumber のときはカーソル行の表示が 0 に、number のときは絶対行数の表示になります。

便利だけど、たまに絶対行数も表示したいんだ!

relativenumber は編集には便利なんですが、コードレビューなんかをする際にはやっぱり絶対行数の表示のほうが良かったりします。うーん、どっちも使いたい。

こういう時は表示をトグルさせるようなコマンドを作ってしまいましょう。

nnoremap <F3> :<C-u>setlocal relativenumber!<CR>

Vim 7.3.1115 以降でかつ set number している場合は <F3> を押下するだけで相対行数と絶対行数の表示を切り替えられるようになります。 それ以外の環境だとちょっと工夫する必要がありますが、そんなに難しくないので挑戦してみましょう。

まとめ

  • relativenumber を使うと相対行数の表示ができる
  • j k と相対行の指定を組み合わせて目的の行へ一気に移動できる
  • オペレータとの組み合わせや Ex コマンドでも活用できる

明日は @tek_koc さんです。

Vim のバッファとウィンドウを理解する

この記事は Vim Advent Calendar の 302 日目の記事です。昨日は id:rattcv さんの Vimから電話がかけられるなんて・・・素敵! でした。すごいですね。

はじめに

Vim には強力なウィンドウ分割機能があります。一方で、プラグインなどのドキュメントなどではバッファという表現が使われることが多いです。この2つは何者なのでしょう?両者の違いは? 私ははじめの頃、ウィンドウ、バッファという2つを混同していました。他にも混同している人が多いのではないかと思ったので今回はこの2つについて解説したいと思います。

バッファとは?

基本的には1つのバッファ=1つのファイルです。ですが、プラグインなどでは必ずしもファイルとは一致しません。例えば、Unite のウィンドウを開いた場合にもバッファが作られます。メモリ上に読み込まれた(ことがある)内容に対応するものがバッファ、というのが正確な表現でしょう。

例えば、下記のような Ex コマンドを連続して打ったとしましょう

edit hoge.html
edit fuga.css
edit piyo.js

このとき、ウィンドウはひとつだけですが、バッファは3つある状態になります。 バッファの状態は :ls コマンドで確認することができます。

ウィンドウとは?

ウィンドウは今まさに目に見えている領域で、バッファの内容を表示するものです。

例えば、下記のような Ex コマンドを打ったとしましょう。

edit hoge.txt
split

このコマンドを打つと、hoge.txt の内容が水平分割されて表示されます。そして、片方を変更するともう片方にも自動的反映されます。 この場合、1つのバッファ(hoge.txt)に対して2つのウィンドウが対応します。一般的に、1つのバッファに対して0以上のウィンドウが対応する感じです。(つまり、1対多の関係)

さて、:q はウィンドウを閉じるコマンドです。なので分割してウィンドウが2つある場合は片方のみ閉じられてもう一方は残ります。対して、:bdelete, :bwipeout はバッファを削除するためのコマンドです。1つのバッファを分割している状態で :bdelete すると、バッファ自体が削除されます。そして、それに紐づく2つのウィンドウがいっぺんに閉じられることになります。

(ついで)タブページとは

ウィンドウを束ねるものがタブページです。ちなみにですが、単にタブというと <Tab> 文字のことになるので区別したい時にはタブページと言いましょう。 タブページはウィンドウを束ねているだけなので、タブページごとにバッファを管理したいとかそういうことは現状ではできません。 (https://github.com/vim-jp/issues/issues/342)

バッファローカル、ウィンドウローカル

前述したとおり、バッファは(ほぼ)ファイルに対応します。なので、ある特定のファイルだけに設定したいものはバッファローカルな変数やオプションを使います。例えば、hoge.html というファイルを開いたときは HTML として認識して欲しいし、fuga.css というファイルを開いた時には CSS として認識して欲しいですね。こういう場合には filetype というバッファローカルなオプションが使われていて、各ファイルに対して別々の設定をさせることができるようになっています。他にも、b:did_ftplugin という変数で filetype plugin が読み込まれたかどうかを記録するといったことや b:quickrun_config であるバッファだけ QuickRun の設定をするなどのように使われています。

また、見た目に関する設定にはウィンドウローカルな変数やオプションを使います。例えば、行番号を表示する number というオプションはウィンドウについてローカルな値を持つことができます。つまり、1つのバッファを分割して開いているときに、片方だけ行番号を表示しないといったことが可能です。他にも、indent-guides というプラグインではインデント量を可視化する(つまり見た目)ための設定をウィンドウローカルな変数で持っています。

ちなみに、オプションがバッファローカルまたはウィンドウローカルな値を持つかどうかはすべてヘルプに書いてあります。:help options もちろん、ignorecase などのようにグローバルな値しか持たないものもあります。

バッファローカル、ウィンドウローカルな変数を Vim script から操る

これらのローカル変数を Vim script から操ることができるといろいろ便利です。自分が今いる位置のウィンドウ、バッファのローカル変数は b: や w: を使うことで参照できます。では別のウィンドウやバッファの変数にアクセスするにはどうすればいいでしょうか。そんな時のために Vim の組み込みの関数が使えます。

関数名 説明
winnr('.') 現在のウィンドウ番号を返す
winnr('$') ウィンドウの個数を返す
bufnr('%') 現在のバッファ番号を返す
bufnr({expr}) {expr}という名前のバッファの番号を返す。{expr} はファイル名とか。
getwinvar({winnr}, {varname}[, {def}]) {winnr}という番号のウィンドウの {varname} というウィンドウローカル変数の値を返す(w: を付けない名前)。存在しない場合は {def} (指定した場合) または空文字を返す
getbufvar({expr}, {varname}[, {def}]) {expr} という名前または番号のバッファの {varname} というバッファローカル変数の値を返す。(b: を付けない変数名) {expr} は文字列か数値。存在しない場合は {def} (指定した場合) または空文字を返す
winbufnr({nr}) {nr} という番号のウィンドウで開かれているバッファの番号を返す。
bufwinnr({expr}) {expr} という名前または番号のバッファの最初のウィンドウの番号を取得する。

例えば、help を開いているウィンドウをフォーカスを動かさずに閉じるとかできるようになります。

function! CloseHelpWin()
  for w in range(1, winnr('$'))
    let bt = getwinvar(w, '&buftype')
    if bt ==# 'help'
      execute w . 'wincmd w'
      q
      break
    endif
  endfor
endfunction

help 閉じるが果たして便利かは置いといて、これを応用すると例えば Quickrun の出力ウィンドウとか diff してるときのもう片方とかも移動せずに閉じるということができますね。便利。

もっといいのないの?

Vim のバッファ、ウィンドウ系の関数はここに紹介した以外にもいくつかあるのですが、微妙に使い勝手が悪かったりします。id:osyo-manga さんが書いた vim-gift を使うとバッファ、ウィンドウの操作をもっと便利にできるでしょう。

明日は supermomonga さんです。