Home

Vim-users.jp

Hack #123: VimでSKK日本語入力環境を実現する

Emacsでは様々な日本語入力のプラグインがあります。
Vimでもkeymapなどの設定をいじれば可能ですが、
あまりkeymapファイルをいじった人は少ないでしょう。
そこでVimプラグインで日本語入力を実現しようと開発された、skk.vimを紹介します。

概要

skk.vimはYagi Noriaki氏によって作られたVimで日本語入力を実現するプラグインで、以下のような特徴を持ちます。

  • SKKによる日本語入力を実現する
  • so skk.vimのみで動作する (Windows環境では辞書ファイルのパスが異なるため、別途設定を.vimrcに書く必要があります)
  • 軽い

SKKについて簡単に説明すると、形態素解析(文節の区切り)をSKK自身が行わず、
使用者自身が行うように矯正することで、実装が簡単であり、
かつ慣れれば高速で正確なかな漢字変換が行えるInput Methodです。

形態素解析を行わないことで軽い動作を実現し、 かつ自分の意図した変換結果を得られやすいとされています。
詳しくは各自Wikipediaを見るなりググったりしてください。

導入

SKKの辞書を用意する

ここからダウンロードするか、Linuxだったら

skkdic skkdic-extra

のようなパッケージが用意されていればそれをインストールしてください。

skk.vim インストール

普通のVimプラグインと違いはありません。
www.vim.orgから最新版をダウンロードして解凍してVimのディレクトリにインストールするだけです。

メリット

  • sshのリモートホスト先で日本語入力ができない時もVim上で日本語を入力できる
  • 軽い
  • 自分の意図にあった変換をしてくれる(かもしれない)

デメリット

  • 他のInput Methodには戻れない
  • SKK信者でVim信者Vimmerは母数的に考えて少ない(要出典)

・・・はネタとして

  • Vimでしか使えない

MacならAquaSKK、Windowsならskkime、Linuxならuim-skkやscim-skkなど、
それぞれのOSのIMを変えてしまえばどのアプリケーションでも使えます。 ただ上で言った「sshのリモートホスト先で日本語入力ができない時もVim上で日本語を入力できる」は大きなメリットだと思います。
緊急時に備えてインストールしておくのもアリかもしれません。

  • SKKは人によっては慣れが必要かもしれない

SKKでもmecab-skkservというものを使えば普通の日本語入力と似た環境を手に入れられますが、残念ながらskk.vimはskkserv非対応です。

これまでのあらすじ

しかしskk.vimには一つ問題があり、 それはもう作者によるメンテナンスが行われていないことです。
skk.vimにはファンも多く、インターネット上でも野良パッチが散見されますが、
それらは本家にマージされることはなく www.vim.orgでの最終更新日は2006年10月15日で止まっています。

そんな中私はこの状況をなんとかしたいといった気持ちはまったくなく、
ふとした思いつきからGithubにskk.vimの改良版を登録し、それが一部の人の反響を受けます。(要出典)
気を良くした私は、勢いで作者である八木氏とメールで連絡をし、
ライセンスの確認と、メンテナンスの意志があるか、
また今後作者に無断で登録してしまったリポジトリに継続してコミットしていいかを尋ねました。
八木氏はこれに快く了承して、ライセンスは好きにしていいと仰ってくれました。

無事八木氏の了解が得られ、どんどんskk.vimのパッチをマージしていこうと考えたものの、
skk.vimがVimスクリプトの貧弱な時代に書かれたものだったため、互換性を維持するためのコードが散らばっていました。

ドキュメントはなんとか書いたものの、Vim6時代のコードを知らないために、変更をすることに怖気づいていたところ、
リポジトリのメンバーからもコードを一から書き直す必要があるとの声が高まってきます。
私はそれを喜んで賛成し、skk.vimのメンテナンスを続けることを約束しながらも、結局新しいskk.vimを作ることにしました。

skk7.vim (仮称)

新しいskk.vimは、今現在skk7.vimという仮称のもと開発が行われています。
それは今私のマシン上、完璧クローズドな環境で行われていて、
未だベータ版ですが、近々Githubに登録するつもりです。

しかしskk7.vimというのはあくまで仮称であって、正式名称ではありません。
未だ続々と希望が寄せられているものの、そもそも多数決で決めるのか、独断で決めるのか、それすらも決めていませんでした。

というわけで

  • 新しい名前希望!
    • 決め方は決めるつもり
  • skk.vimかskk7.vimの開発に興味があるなら、私かリポジトリのメンバーになんらかのコンタクトをとってくれれば、すぐにメンバーに招待したい
    • GithubのIDを取得している必要があります
    • 参加表明して何もしなくてもOKな気楽っぷり
    • 気が向いた時に機能追加なり修正を新しいブランチにプッシュしてもらえれば適当に拾ってマージします
  • その他要望等あれば下の連絡先からどうぞ

連絡先

参考リンク

tyru

Hack #122: 行末までヤンクする

問題

カーソル位置から行末まで削除するにはDします。 カーソル位置から行末まで編集する(削除して挿入モードに入る)にはCします。

さて、カーソル位置から行末までヤンクするにはどうすればいいでしょうか。 答えはYではなく、y$です。

VimのYの挙動は、「カーソル行をヤンク」です。カーソル位置より左もまとめてヤンクされてしまいます。 オリジナルのviとの互換性のためか、このような仕様になっているみたいです。 オリジナルのviがなぜこのような仕様になっているかは不明です。

解決

~/.vimrcに以下を記述します。

nnoremap Y y$

これで、Yの挙動がDCと同様に、「カーソル位置から行末までヤンクする」になります。 一貫性がとれる上に、$というとても人間には入力不可能な記号の入力を省略することができ、開発効率の大幅な向上が期待されます。

解説

なお、ヘルプ :h Y を引くと以下のように説明されています。

["x]Y yank [count] lines [into register x] (synonym for yy, |linewise|). If you like "Y" to work from the cursor to the end of line (which is more logical, but not Vi-compatible) use ":map Y y$".

しかし、このやりかたは2点留意事項があります。

  • ヘルプに書いている方法ですと、y$の挙動が上書きされているときに、上書きされた側の挙動で今回定義したYが実行されます。多くの場合それは意図した挙動ではないため、本Hackではmapではなくnoremapとしました
  • ビジュアルモードなどでは今回のYは関係ないため、mapではなくnmapがより好ましいです

組み合わせて、本Hackではnnoremapとしました。

ujihisa

Hack #121: バッファ名をペーストする

問題

ときおりバッファ名をペーストしたいことがあります。 短い名前なら手動で入力しても構いませんし、 ファイルに対応するバッファならばファイル名補完で多少の手間を省けますが、 面倒臭いことには変わりありません。 直接バッファ名をペーストできないでしょうか。

解決方法

Normal modeの場合は以下のコマンドを実行します:

"%p

Insert modeやCommand-line modeの場合は以下のコマンドを入力します:

<C-r>%

上記のコマンドはカレントバッファ名をペーストします。 %の代わりに#を用いると 代替バッファ の名前をペーストします。

解説

上記のコマンドは実際には指定されたレジスタの内容をペーストするコマンドです。 Vimには特殊なレジスタとしてカレントバッファ名や代替バッファ名を表すものがあり、 この二つを組み合わせることで上記のようにバッファ名のペーストができます。

Vimには他にも様々な 特殊レジスタ があるので、一度確認しておくとより便利に使うことができるでしょう。

参考資料

kana

Vim勉強会#5が開催されました

2010年1月31日(日)、第五回目となる関西でのVim勉強会が開催され、大盛況の中終了しました。

Vim5

関西vim勉強会#5

  1. ujihisaさん: Vim初級者レッスン(前半)
  2. ujihisaさん: Vim初級者レッスン(後半)
  3. Sixeightさん: text-object
  4. 少佐さん: はじめてのVim
  5. tsukkeeさん: .vimrcの書き方
  6. .vimrc hackathon

Vim勉強会は、家に帰って感想記事を書いてブログを書いてトラックバック等を送るまでがVim勉強会です。

食べ放題のお菓子、カナダ土産の美味しいお菓子、活発な質問、居心地の良い空間、エネミー、そしてVimへの愛にあふれたすばらしい勉強会でした。勉強会の後の懇親会では、乾杯のときに「Vim」という声が自然と出てきたとか。いやはや、高まるVim熱は、とどまるところを見せません。

次回のVim勉強会は5月中旬に行なわれる予定です。

Vim勉強会#5 ujihisa発表資料

Vim勉強会5 初級者向け講座

ujihisa

初級者とは

「初級者向け講座」 … 具体的に、初級者とは?

Vim使いのレベル10

  • Lv1 vimtutorを終わらせた。あるいは、hjklで移動できて保存と終了ができる
  • Lv2 ビジュアルモードを使うのをやめ、y}やdawなどの素晴らしい操作性に自己陶酔する
  • Lv3 自分でインストールしたプラギンの数が5を越え、ダメプラギンはすぐに判別できるようになる
  • Lv4 自分で作ったプラギンをvim.orgでリリースし、何人かをLife Changingさせる
  • Lv5 他のアプリケーション使用時にescやiを打鍵してしまい、イラっとする日々を送る
  • Lv6 シェルは当然vimshell。ネオコンなど大規模プラギンのバグを発見し、パッチ付きで報告する
  • Lv7 Vim本体のソースコードを読み、あまりの魔界に発狂する
  • Lv8 他言語インタフェースif_***を作り、vim_devに投稿する。当然採用されない
  • Lv9 Vim本体の開発への貢献が日常になる。投稿し採用されたパッチ数が10を越える
  • Lv10 神になる

つまり

  • Lv1~Lv4 初級者
  • Lv4~Lv7 中級者
  • Lv7~Lv10 上級者

今日の目標

Lv4 自分で作ったプラギンをvim.orgでリリースし、何人かをLife Changingさせる

全員ここまでやる

Be Lv1

  • Lv1 vimtutorを終わらせた。あるいは、hjklで移動できて保存と終了ができる

VimをインストールしてVimtutorを全部やる。25~30分。

$ vimtutor

Lv1の重要な点

  • u
    • undo。無制限
    • Vimは終了しない
    • キャンセルは<C-r>
  • A
    • その行の行末から文字入力開始!
  • dw
    • (delete 'word)
    • カーソル位置からその単語の終わりまでまとめて削除!
  • d$
    • カーソル位置から行末まで削除!
  • dd
    • その行を削除
  • p, P
    • 消した文字を貼付け。PだとVim以外のソフトのペーストのような挙動
  • 0
    • 行頭に移動

ビジュアルモード

  • v
    • 一文字単位のビジュアルモード
  • V
    • 行単位のビジュアルモード
  • <C-v>
    • 矩形選択

vしてyでヤンク、あるいはdで削除できる!

Be Lv2

  • Lv2 ビジュアルモードを使うのをやめ、y}やdawなどの素晴らしい操作性に自己陶酔する

非オブジェクト指向言語

値x に対して、 引数2 で、 関数f を実行する

f(x, 2)

オブジェクト指向言語

値x に対して、 引数2 で、 関数f を実行する

# f(x, 2)
x.f(2)

Vimのビジュアルモード

範囲x に対して、 引数2 で、 操作f を実行する

# f(x, 2)
# x.f(2)
x2f

Vimの非ビジュアルモード

範囲x に対して、 引数2 で、 操作f を実行する

# f(x, 2)
# x.f(2)
# x2f
2fx

例: 次の空行まで削除

ビジュアルモード

v}d

非ビジュアルモード

d}

非ビジュアルモードの薦め

  • 自分で画面を確認する必要がない! EP確保 (後述)
  • キータイプ数が少ない!
  • 範囲の大きさに依存しない!

dawは?

text-objectの一つ。

詳しくは次のSixeightさんによるtext-objectのためだけのプレゼンに刮目せよ!

Be Lv3

  • Lv3 自分でインストールしたプラギンの数が5を越え、ダメプラギンはすぐに判別できるようになる

Vim plugins

インストール: 単にファイルを置くだけ

  • (大抵の場合) ビルドとかいらないよ!

便利で小さいプラギン

  • quickrun
    • 編集中バッファを「実行」する
  • git-vim
    • gitをラクに使う
  • smartchr
    • いい感じに文字入力をラクにする

便利で大きいプラギン

  • neocomplcache
    • 補完!
  • vimshell
    • Vim scriptで実装されたシェル
  • blogger.vim
    • blogspot.comにブログを投稿する

自己紹介

ujihisa

自分のプロジェクト

  • quickrun.vim (現在はthincaさんがメインブランチ)
  • blogger.vim
  • few

関わっているプロジェクト

  • Termtter
  • Ruby Core

最近の活動

  • アメリカの大学院入試。いまは結果待ち
  • 明後日カナダに帰ります
  • アセンブリ言語勉強しています (LLVM, IA-32)

Be Lv4

  • Lv4 自分で作ったプラギンをvim.orgでリリースし、何人かをLife Changingさせる

プラギンの作り方

  1. Vimを使いまくる
  2. こんな機能があればラクなのになあと思う
  3. Vim標準でその機能があるか調べる :h
  4. www.vim.orgにそのスクリプトがあるか調べる

#

  1. 大抵はすぐにいくつか見つかる
  2. 実際に使ってみる
  3. ヒドい出来具合に発狂する
  4. 自分で実装する
  5. githubで公開する
  6. vim.orgで公開する

今後の発展

  • Vim用語を抑える
  • Vim hacksを毎日読む
  • Lingr Vim Roomに常駐する

Vim用語

  • Bram
  • 教皇
  • エネミー
  • hkn

Vim Hacks

http://vim-users.jp/

  • kana, ujihisa, thinca, Shougo, ukstudioらが執筆
  • 時々ゲスト執筆者も。

ゲスト執筆者は常時募集中!

Lingr Vim Room

http://lingr.com/room/vim/

  • 大勢が常に常駐
  • tsukkeeさんのlingr-vimを使うとさらに快適に!

let g:loaded_vimlectur = 1

Hack #120: gVim でウィンドウの位置とサイズを記憶する

GUI アプリケーションではよく終了時にウィンドウの位置とサイズを記憶し、次回起動時に復元するものを見かけます。Vim でも設定次第で同様のことが可能です。

設定

.gvimrc に以下のように書きます。

let g:save_window_file = expand('~/.vimwinpos')
augroup SaveWindow
  autocmd!
  autocmd VimLeavePre * call s:save_window()
  function! s:save_window()
    let options = [
      \ 'set columns=' . &columns,
      \ 'set lines=' . &lines,
      \ 'winpos ' . getwinposx() . ' ' . getwinposy(),
      \ ]
    call writefile(options, g:save_window_file)
  endfunction
augroup END

if filereadable(g:save_window_file)
  execute 'source' g:save_window_file
endif

解説

g:save_window_file

この変数で指定するファイルにウィンドウの位置やサイズを保存します。expand() は ~ を $HOME に展開するのに必要で、その必要がない場合はなくても問題ありません。

設定の書き出し

augroup SaveWindow 〜 augroup END で、Vim の終了時に発生するイベントを登録しています。

ここでは Vim の終了時に s:save_window() と言う関数を呼ぶようにしています。そしてこの関数のなかで、g:save_window_file にウィンドウの位置とサイズの情報を Vim スクリプトの形式で書き出しています。

設定の読み出し

最後の if でウィンドウ情報ファイルが存在するかをチェックし、存在した場合はそのファイルを :source で読み込みます。情報ファイルは Vim スクリプトとして書き出されているので、:source するだけで位置とサイズが復元されます。

thinca

Hack #119: neocomplcache Hacks(2)  オムニ補完

二回目の今回はオムニ補完です。AutoComplPopでも自動呼び出しが可能ですが、neocomplcacheでは、それに改良を加え、設定しやすくなっています。

オムニ補完とは

オムニ補完とは、Vim組み込みで用意されている補完とは違い、文脈を解析して行う補完です。関数を'omnifunc'に設定し、<C-x><C-o>のキーシーケンスを入力することで呼び出されます。標準でもいくつかの言語のオムニ補完関数が用意されていますが、ユーザーが自分で定義することができます。

inoremap <expr><C-x><C-o> &filetype == 'vim' ? "\<C-x><C-v><C-p>" : neocomplcache#manual_omni_complete()

私はこのようにキーマッピングを設定し、Vim組み込みのオムニ補完を置き換えています。

拡張機能

neocomplcacheのオムニ補完には次のような拡張機能があります。

自動補完の文脈定義

g:NeoComplCache_OmniPatterns[filetype]を設定すれば、呼び出し条件をカスタマイズしたり、呼び出しを無効化することができます。

多数の言語に対応

AutoComplPopでは標準でPerl/Ruby/html/CSS/Pythoのオムニ補完が可能です。neocomplcacheではPerl以外の確認できたすべての言語に対応しています。キーワードパターンに追加するだけなので、新たな言語に対応させることが容易です。

補完スキップ

g:NeoComplCache_EnableSkipCompletionが1ならば(デフォルト)、候補の取得に時間がかかりすぎる場合、補完をスキップすることができます。

ワイルドカード

ほかの補完と同様、ワイルドカードによる絞り込みに対応しています。

エラーを出さない

特定のオムニ補完では、変な場所で呼び出すとエラーを出したりすることがあります。neocomplcacheではエラーをcatchしているので、neocomplcache内部にバグがない限り、オムニ補完中にエラーになることはありません。

補完環境の厳密な判定

PythonやRubyのオムニ補完は:python:rubyが正常に動作する環境でなければ動作しません。よって、内部で判定しています。

ファイル名補完やバッファ名補完との同時呼び出し

オムニ補完とほかの補完を同時に呼び出せないAutoComplPopとは違い、neocomplcacheのオムニ補完はほかの補完と統合されています。 よって、同時に候補を出すことができるので、さらに便利に使えます。 ただし、オムニ補完の開始パターンが先にマッチした場合、オムニ補完の候補のみが計算されて表示されます。 これはVim自体の仕様です。これを防ぐためには、一度補完のポップアップを閉じて、補完を再呼び出しするしかありません。

キーワードの収集

空文字列でオムニ補完を呼び出してキーワードを収集してキャッシュし、オムニ補完候補として利用することができます。

neocomplcacheからオムニ補完関数を呼び出すときの注意

neocomplcacheは大抵のオムニ補完関数に対応していますが、オムニ補完関数を内部で無理矢理呼んで変換するという動作を行っているので、呼び出す関数によっては補完がうまく働かないことがあります。現在、complete_add()関数を内部で呼んでいる場合には動作がおかしくなることがわかっています。これはオムニ補完関数側がcomplete_add()を呼ばないようにするしかありません。 他に、Rubyのオムニ補完は時々フリーズする現象があることが報告されています。 これはRubyのオムニ補完が外部インタフェースを内部で使用しているためだと思われます。 Vimの外部インタフェース機能は不安定なので、時々エラーをはいたりフリーズすることがあります。 無効にしたい場合は.vimrcで

if !exists('g:NeoComplCache_OmniPatterns')
let g:NeoComplCache_OmniPatterns = {}
endif
let g:NeoComplCache_OmniPatterns['ruby'] = ''

と設定すると、無効にできます。これでは不便なので、Rubyのオムニ補完を書き直してくれる人を現在募集中です。

Shougo

Hack #118: ホームディレクトリをラクに入力する

問題

Vimのコマンドラインでホームディレクトリを入力する機会は比較的多いものの、~/という文字列を見ただけで小指に疲労が走ってくるのは、ほとんどのVimユーザに共通するのではないでしょうか。 もしも入力しやすいキー、例えばバックスラッシュなどで一発で~/が入力できれば、どんなに素晴らしいことでしょうか。

解決

以下のコードを~/.vimrcに記述することで、コマンドラインモードでバックスラッシュで~/が入力できる上、~/が来て欲しくなさそうなところではそのままバックスラッシュが入力されます。

function! HomedirOrBackslash()
  if getcmdtype() == ':' && (getcmdline() =~# '^e ' || getcmdline() =~? '^r\?!' || getcmdline() =~? '^cd ')
    return '~/'
  else
    return '\'
  endif
endfunction
cnoremap <expr> <Bslash> HomedirOrBackslash()

この設定を有効にしたVimで:e \と打鍵すると、ただちに:e ~/に展開されます。 また、:s/\と打鍵した場合は、:s/\とそのままになります。(:s/~/のように展開されません)

発展

本Hackはcho45さんの.zshrcへのハックへのアナロジーで考案されました。 残念ながら現在cho45さんの最新版の.zshrcにはそのコードは存在していないようですが、 少し古いところに残っています。 著者の手元の.zshrcから引用すると、以下のようなコードでした。

expand-to-home-or-insert () {
  if [ "$LBUFFER" = "" -o "$LBUFFER[-1]" = " " ]; then
    LBUFFER+="~/"
  else
    zle self-insert
  fi
}
zle -N expand-to-home-or-insert
bindkey "\\"  expand-to-home-or-insert
ujihisa

京都でVim勉強会#5が開催されます

2010年01月31日(日)、京都でVim勉強会が開催されます。

参加登録や詳細はこちらを参照ください。 http://cotocoto.jp/event/37291

※画像はイメージです

a

高まるVim熱!

Hack #117: 置換行為を繰り返す

問題

:substitute (:s)による置換処理は頻繁に使います。 バッファ全体を対象にする場合は:%s/foo/bar/gなどでできますし、 特定範囲のみを対象にする場合はVisual modeで選択しておいて :s/foo/bar/gでできます。

では飛び飛びの場所で置換を行なう場合はどうでしょうか。 例えばソースコード中の特定の関数3つに対して置換を行なうとしましょう。 この場合は3箇所それぞれを対象として置換を実行することになりますが、 毎回 :s/foo/bar/g のような長ったらしいコマンドを入力したくはありません。 <Up>/<Down> でコマンドの入力履歴を辿って実行してもいいのですが、 これらのキーは概して遠い位置にあるため押下が面倒ですし、 押し易いキーバインドを設定することも面倒です。 どうにかして最小の手数で置換行為を繰り返せないでしょうか。

解決方法

以下のコマンドを実行します:

:s

通常、:sには検索パターンと置換文字列を指定しますが、 それらを省略した場合は最後に実行された :sと同じ検索パターンと置換文字列で置換が行なわれます。

なお:sでは :s/foo/bar/gc などのフラグは無視されます。 フラグまで同一にする場合は:sの代わりに

:&&

を使います。

また1行だけ繰り返す場合には:sの代わりに

&

を使うこともできます。

参考資料

kana

Home

Search
Feeds
Links
  • 公式
  • 勉強会
  • 情報
  • コミュニティ
  • プラグイン
  • vimrc
  • Meta
    Etc
    Creative Commons License
    This blog is licensed under a Creative Commons License.

    Return to page top