vimにluajitを対応させてみた作業ログ

先日、vacにneocompleteを入れてみた作業ログという記事を書き、それをlingrで報告すると以下のような発言をもらった。

f:id:saihoooooooo:20131202111744p:plain

luajit知りませんでした。
現状でneocompleteの速度には困ってないし、if_luaを駆使してプラギン作る予定も無いので正直必要ないっちゃないけど、せっかく教えてもらったので入れてみることにする。

前回のluaはyumでインストールしたけど、luajitはyumにないので自前でビルドする。
本家サイト(http://luajit.org/)を参考にcloneしてmake。

$ cd /usr/local/src
$ git clone http://luajit.org/git/luajit-2.0.git luajit
$ cd luajit
$ sudo make
$ sudo make install

特に問題なし。
続いてvimもluajit対応させます。

$ cd /usr/local/src/vim
$ vim vuild.sh
$ cat vuild.sh
#!/bin/sh
./configure \
  --prefix=/usr/local \
  --with-features=huge \
  --enable-multibyte \
  --enable-luainterp \
  --with-luajit \
  --enable-fail-if-missing && make && make install
$ ./vuild.sh

configureは前回と比べると、--with-luajit の部分だけ追加しました。
ビルドで特にエラーが発生せず、:version で +lua もついてるので多分いけてるはず。

むしろこれを機にluaを勉強してみようかな。

neocompleteを入れてみた作業ログ

Vim Advent Calendar 2012の364日目の記事になります。
363日目は@haya14busaさんによる Vim-Easymotionを拡張してカーソルを縦横無尽に楽々移動する でした。
あと1日でvacが365日達成してしまうことに驚きを隠せません。
advent calendarとは一体何だったのか。

f:id:saihoooooooo:20131129152502p:plain

では本題に入ります。
neocomplcacheが進化してneocompleteとなったことは知ってましたがif_luaを使ってるためインストールは敬遠していました。
そんな僕もShougoさんのスライドを見てneocompleteに移行することを決意しました。
neocomplcacheはもう開発がされないそうですしね。

という訳でやったことをメモしておきます。

luaのインストール

まず手元のlinuxマシンにluaが入っていなかったのでインストールから。

$ sudo yum install -y lua lua-devel

vimのビルド

その後、if_luaを有効にするためvimをビルドします。

$ cd /usr/local/src
$ hg clone https://vim.googlecode.com/hg/ vim
$ cd vim
$ vim vuild.sh
$ cat vuild.sh
#!/bin/sh
./configure \
  --prefix=/usr/local \
  --with-features=huge \
  --enable-multibyte \
  --enable-luainterp \
  --enable-fail-if-missing && make && make install
$ chmod +x vuild.sh
$ ./vuild.sh
$ alias vim="/usr/local/bin/vim"

正直configureはそんなにわかってない。
vimを起動して、:version で確認してみる。

f:id:saihoooooooo:20131129175246p:plain

問題なさそうです!
では最後にneocompleteをvimにインストールしていきます。

neocompleteのインストール

.vimrcに以下を記述します(neobundleを使用)。

" if_luaが有効ならneocompleteを使う
NeoBundle has('lua') ? 'Shougo/neocomplete' : 'Shougo/neocomplcache'

if neobundle#is_installed('neocomplete')
    " neocomplete用設定
    let g:neocomplete#enable_at_startup = 1
    let g:neocomplete#enable_ignore_case = 1
    let g:neocomplete#enable_smart_case = 1
    if !exists('g:neocomplete#keyword_patterns')
        let g:neocomplete#keyword_patterns = {}
    endif
    let g:neocomplete#keyword_patterns._ = '\h\w*'
elseif neobundle#is_installed('neocomplcache')
    " neocomplcache用設定
    let g:neocomplcache_enable_at_startup = 1
    let g:neocomplcache_enable_ignore_case = 1
    let g:neocomplcache_enable_smart_case = 1
    if !exists('g:neocomplcache_keyword_patterns')
        let g:neocomplcache_keyword_patterns = {}
    endif
    let g:neocomplcache_keyword_patterns._ = '\h\w*'
    let g:neocomplcache_enable_camel_case_completion = 1
    let g:neocomplcache_enable_underbar_completion = 1
endif
inoremap <expr><TAB> pumvisible() ? "\<C-n>" : "\<TAB>"
inoremap <expr><S-TAB> pumvisible() ? "\<C-p>" : "\<S-TAB>"

念のため、if_luaが効いてない環境でも補完が動くよう、neocomplcacheの設定は残しました。

感想

速度の向上はまだ実感できてませんが、あいまい補完の動作はちょっとした感動です。
またtypoした文字列をいつまでもキャッシュされないというのもポイント高いです。

とりあえずこれで様子を見ながら他のオプションも設定したいですね。

vac2012について

明日はついにvim advent calendar 2012のファイナルです!
マジですごい!!
この偉業に少しでも貢献できたことは幸せだと思います。
それでは!
Have a nice vim!

vimのtextobjで検索文字列を指定する

Vim Advent Calendar 2012の331日目の記事になります。
330日目は@LeafCageさんによる 俺が見たいのはメッセージの最後なんだ!:messagesを便利にするVimプラグイン でした。

はじめに

先日このようなvimの記事を見つけました。

feedkeys() を使用します。

function! HLsearch()
    call feedkeys(":set hlsearch\<CR>", "n")
endfunction
call HLsearch()

これでハイライトが行われます。

少々バッドノウハウっぽくはありますが、自分はこの関数内でのset hlsearchの方法を待ち望んでいました。
過去にvim-operator-userを使って検索オペレータを作ろうと思い立つも、関数内ハイライトの壁に阻まれて諦めていたのです。
でもこの方法さえ知ればもう怖いものはない、一度敗れた雪辱を果たしてやろうと思います。倍返しです。

ちなみに関数内でハイライトが効かないのは仕様だそうです(:h nohlsearch)。

実装

では早速実装してみましょう。
こんな感じ。

NeoBundle 'kana/vim-operator-user'

" 検索オペレータ
map <SPACE>/ <Plug>(operator-search)
call operator#user#define('search', 'OperatorSearch')
function! OperatorSearch(motion_wise)
    " v or V or <C-v>
    let v = operator#user#visual_command_from_wise_name(a:motion_wise)

    " textobjで選択した文字列を検索パターン用レジスタに格納
    let orig = @"
    execute 'normal! `[' . v . '`]y'
    let @/ = '\V' . substitute(escape(@", '\'), '\n', '\\n', 'g')
    let @" = orig

    " 検索履歴に追加
    call histadd('/', @/)

    " 強調表示
    if &hlsearch
        call feedkeys(":set hlsearch\<CR>", 'n')
    endif
endfunction

どやろか?

ただ上記は思いっきり自分仕様に作ってます。
自分は*の動作でも移動はせずハイライトのみするようにしているので、これも同じように作成しました。
その後n/Nで移動する感じです。

とりあえず動かしてみる。

f:id:saihoooooooo:20131026225917g:plain

うーん、いい感じっす。
あと捕捉ですがilの動作はvim-textobj-lineでやってます。

いやぁハイライトって本当にいいものですね。
私もう満足です。
一片の悔いなしっす。

が一応

さっきも言ったように上記は思いっきりオレオレ仕様であります。
普通は初回の動作でも移動+ハイライトになると思うので頑張って作ってみたいと思います。

map <SPACE>/ <Plug>(operator-search-forward)
map <SPACE>? <Plug>(operator-search-backward)

call operator#user#define('search-forward', 'OperatorSearch', 'call SetOpSearchCmdtype("/")')
call operator#user#define('search-backward', 'OperatorSearch', 'call SetOpSearchCmdtype("?")')

let s:op_search_cmdtype = ''
function! SetOpSearchCmdtype(cmdtype)
    let s:op_search_cmdtype = a:cmdtype
endfunction

function! OperatorSearch(motion_wise)
    let v = operator#user#visual_command_from_wise_name(a:motion_wise)
    let save = @"
    execute 'normal! `[' . v . '`]y'
    let @/ = '\V' . substitute(escape(@", '\'), '\n', '\\n', 'g')
    let @" = save
    call histadd('/', @/)
    if &hlsearch
        call feedkeys(":set hlsearch\<CR>", 'n')
    endif
    " キーマップから実行することで<SPACE>?でのn/Nの方向が?と同じになる
    call feedkeys(s:op_search_cmdtype . "\<CR>", 'n')
endfunction

うーん、検索周りは自分のつたないvimscript力ではこの辺が限界か。
一応動作はしますが、納得はいってません。
特に2回もfeedkeys()を使わされているのが悔しいです。
v:searchforwardもまた関数から出ると元に戻るようで。

プラグイン化も考えてたけどまた次回に・・・。
だれかキレイなものを作ってくれる方募集中です。

まとめ

@thincaさんのvim-visualstarはすっごいよく出来てる。

tablineもvim-airline

f:id:saihoooooooo:20130914014247p:plain

vimのタブラインもairline化できるようなのでヘルプから適当にみつくろって設定してみた。

" タブラインにもairlineを適用
let g:airline#extensions#tabline#enabled = 1

" (タブが一個の場合)バッファのリストをタブラインに表示する機能をオフ
let g:airline#extensions#tabline#show_buffers = 0

" 0でそのタブで開いてるウィンドウ数、1で左のタブから連番
let g:airline#extensions#tabline#tab_nr_type = 1

" タブに表示する名前(fnamemodifyの第二引数)
let g:airline#extensions#tabline#fnamemod = ':t'

ただ右上に「×マーク(マウスクリックで表示中のタブを閉じる)」だの「tabs / buffers」だのが表示されているが、ここの内容を変更する方法がどうも無さそうだった。
いつもはカレントディレクトリを表示しているからairline化しても同じようにしたかったのに。

なんで一回CUIのタブラインに戻す( ´ー`)y-~~

設定できるようになったらもっかい使ってみよう。
airlineの開発は活発そうなのでそのうち用意されるだろうと期待。