macvim を +lua でビルド

http://www.kaoriya.net/blog/2013/04/02/:こんな記事を見かけた。

というわけで、ぐぐったり gist をあさったり、いろいろもろもろ参考にして、Formula 書いた。

https://github.com/pekepeke/homebrew-pekepeke/blob/master/macvim-kaoriya.rb

gettext の install_name_tool あたりが怪しいのでげすが、多分問題なし。でも、僕の環境だけかもしれんでげす・・・
--with-lua で指定したら有効にする感じではなく、brew install lua してある場合は +lua するようにしてある。
ココらへんは僕の brew 力不足+個人的な理由な感じが否めないのですが、あくまで個人で利用するために作ったものなので、特にもんだいなし。

まー、僕、Lua はほとんど書けないのですが…滝汗

Data::Section 的なことを PHP でおこなう

つくってみて、あまり応用が効かなそうと思いつつ、テストデータとか、使い捨てスクリプトの作成には便利なのかも…と思ったり。

function section($name = null) {
	static $data = null;
	static $sections = array();

	if (is_null($data)) {
		$data = preg_replace('/\r\n|\r|\n/', "\n", file_get_contents(__FILE__, FALSE, NULL, __COMPILER_HALT_OFFSET__));
		$contents = explode('@@', $data);
		foreach (preg_split('/(^|\n)@@/', $data) as $section) {
			$lines = explode("\n", $section);
			$key = array_shift($lines);
			$sections[$key] = implode("\n", $lines);
		}
	}
	if (is_null($name)) {
		return $data;
	}
	return $sections[$name];
}

echo section("start");

__halt_compiler(); // __END__

@@start
Hello world.

ぐぐったら、こうすればできるよてきな情報が stackoverflow ででてきたので、それをまんまコードにした感じ。
とりあえず、書きなぐりなスクリプトで、↓みたいな感じ(ちょっと変えてるが…)で sinatra ぽくかけるような感じでつかってみている。

function render_file_or_contents($view_path, $vars) {
	extract($vars);
	ob_start();
	if (file_exists($view_path)) {
		include $view_path;
	} else {
		eval('?>' . section($view_path));
	}
	$content = ob_get_clean();
	return $content;
}

function render($view, $vars = array(), $layout = null) {
	$content = render_file_or_contents($view, $vars);
	is_null($layout) && $_SERVER['HTTP_X_REQUESTED_WITH'] && $layout = "layout";

	echo is_null($layout) ? $content : render_file_or_contents($layout, array_merge(compact('content'), $vars));
}

sinatra ぽくというか、Vの部分だけ sinatra 風を作った感じ。
あまり応用例は思いつかないのだけれど、極力ファイル数を減らしたいとか、別ファイルにするよりも1ファイルにした方が管理しやすい時とかにはいいのかもしれない。
低コストな V が作れるので、個人的にはわりかし好印象。
ちなみに、lib 化した時は file_get_contents(__FILE__, FALSE, NULL, __COMPILER_HALT_OFFSET__) は多分動かないのでなにかしらの魔法が必要に思われる。phpヨクワカラナイ・・・

unite.vim で良い感じ(?)にディレクトリ周りの source を使う

とりあえず、以下のコードを .vimrc に記述してみた。
(元々の記述上、色々と違うところはあるが、大枠は以下のような記述になるはず。。。)

	let s:unite_action_open_unite_file = {
		\ }
	function! s:unite_action_open_unite_file.func(candidate)
		" echoerr a:candicate.word
		let path = a:candidate.action__path
		execute 'Unite' 'file:'.path
		call unite#custom_action('directory', 'open_unite_file', s:unite_action_open_unite_file)
	endfunction
	unlet! s:unite_action_action_open_unite_file

	nnoremap   <Leader>d :<C-u>Unite directory_mru -default-action=open_unite_file<CR>

unite.vim の directory kind の action を作成して、ディレクトリが選択されたら、
source=file を起動させる action を定義した。
kind=directory の default action が narrow かとおもってたりしたんだけど、違ったみたいなのでこのような定義をしてみたり…。

作った理由としては、file_mru が食いつぶされていたため、「あれ〜、あのディレクトリなんだっけ???」→「unite-z」が必要だ→できた!!→「directpry_mru」あるよね?→directory kind の挙動なにこれ???
から始まった騒動だったり…。

まぁ、なんで directory kind が展開されないの〜?はともかく、超短時間で拡張できてしまう(リアルに3分程度で対応できてしまった…w) unite.vim の底力に驚かされた出来事でした。(笑)

zsh の補完関数を作るのといろいろとはかどる

が、まだよくわかっていない…

とりあえず、milkode の補完コマンドを作ってみた。

初 gist である。

追記

俺の環境で gist が展開されてないようなので直リン

https://gist.github.com/4649031

hatena blog に移動するか、他の blog 使えってことなんかなぁ…

Vim を高速にしたたったひとつの作業

# こんなことがおこってしまいました

見に覚えがないのですが、ある日突然 vim が激重になってしまいました。

vim が重い…

それは vimmer にとっては耐え難いもの…

単純に重いといっても色々あると思います。
重い症状といえば、大体は以下の2つに分類されるかと思います。

  • 起動が遅い
  • ある特定の処理が遅い

- FileType の処理とか、あと、特定の重めなプラギンの処理とか

ところか、Vim の操作の一つ一つが遅いという現象が発生してしまいました。
具体的に言うと、起動はもちろん、バッファの移動、タブの作成、ファイルの保存ですら重い。
ついでにいうと、gui だけでなく、cui も激重です。

というわけで、僕は結構前から vimrc の高速化を図りつつ、乗り換えるエディタを探していました。
候補にあがったのは以下のエディタです

# Emacs を使う

昔、結構長いことつかっていたのですが、設定ファイルのメンテがカオスなのと、
プラグインの管理とキーバインドの管理で挫折。
evil のおかげで割りと快適だったりしたんですけど…最近の elisp 事情を漁るのも結構大変で…むー

# Vico を使う

vi clone な Mac のエディタ。
Nvu (だっけか?)を使うことで、結構カスタマイズができそうなことと、
そこそこ軽快に動作するため、一時期ハマる。

が、しかし、plugin ぽいものが TextMate 互換だったり、
ドキュメントというものはあるものの、ほぼ、ソースを読め的な感じだったので、
結局使用をやめた。
Obj-Cレベルでいじれるので、カスタマイズによっては化けるエディタだと思うのだけれど、
Lisp を使うのであれば Emacs 使うわと思って、挫折

# CotEditor を使う

今でも使ってます。
とりあえず、全体的にバランスがよいのでとても使いやすい。
というか、今でも使っているので…

エディタとしての機能はほぼ網羅していると思うし、プラグインがとても作りやすいので
未だに重宝しています。

が、がっつり使うエディタとしては物足りなかった。
あと、大容量なファイルを開くのがとても苦手なエディタというのもマイナス要因。

# Sublime Edit 2 を使う

これも今でも使っています。

標準でもそこそこ使える上、プラグインも豊富。
で、もごもごしているうちに、Web 上でも注目され、解説 Blog が一気に増えたことでもお馴染みのエディタ。

とても高機能で、文句もないのですが、どうしても CUIGUI が混在してしまうため、
Vim の代替ではないなと感じました。

ちなみに、Vim ユーザーの方は Vintage を使っているのでしょうが、僕は Vintage なしで使っています。
Vintage なしで使っているのは、やはり CUIGUI の違和感…というところでしょうか。。。なんか、使っていて Vim じゃないと思うといちいち気にかかってしまうのです…orz

ともあれ、簡単な拡張も書きやすいし、すでにたくさんのプラギンがあるため、今でも使っていますし、使うことで勉強にもなっていたりします。

# Vimにもどる。そして改善をはかる

結局 Vim に戻って来ました。

とりあえず、遅い原因は vimrc だろうと思い、vimrc を最適化することにしました。

まず最初にやることと言えば… プラグインの整理…

とりあえず、特定の filetype でしか使わないようなものは、遅延ロードするように修正しました。
その時のコードがこれ

```vim

let s:lazyutil = {
\ '_' : {},
\ }
function! s:lazyutil.add(on, mode, source)
let k = a:on."_".a:mode
if !self.has(k)
let self[k] =
endif
call add(self[k], a:source)
endfunction

function! s:lazyutil.has(key)
return exists('s:lazyutil["' . a:key . '"]')
endfunction

function! s:lazyutil.get(on, mode)
let k = a:on."_".a:mode
if !self.has(k)
return
endif
return self[k]
endfunction

function! s:lazyutil.clear(on, mode)
let k = a:on."_".a:mode
if !self.has(k)
return
endif
let sources = self[k]
unlet self[k]
return sources
endfunction

function! s:lazyutil.load(on, mode)
let sources = self.clear(a:on, a:mode)
if empty(sources)
return
endif
let F = function('neobundle#config#source')
" call call(F, sources)
call call(F, [sources])
" syntax enable
endfunction

function! s:lazyutil.register(on, modes, source)
silent execute 'NeoBundleLazy' a:source
let modes = type(a:modes) == type() ? a:modes : split(a:modes, ",")

let name = fnamemodify(a:source, ':te')
let name = substitute(name, '^[''"]*\|\.git[''"]*$\|[''"]*$', '', 'g')

for mode in modes
call self.add(a:on, mode, name)

let k = a:on . "_" . mode
if !self.has("_".k)
let self._[k] = 1
let cmd = printf('autocmd vimrc-neobundle-lazy %s %s NeoBundleLazyOnSource %s %s', a:on, mode, a:on, mode)
silent execute cmd
endif
endfor
endfunction

function! s:neobundle_lazy_source(on, mode)
call s:lazyutil.load(a:on, a:mode)
endfunction

command! -nargs=+ NeoBundleLazyOnSource call neobundle_lazy_source()

function! s:neobundle_lazy_on(on, modes, source)
call s:lazyutil.register(a:on, a:modes, a:source)
endfunction
command! -nargs=+ NeoBundleLazyOn call neobundle_lazy_on()

```

なお、今では `NeoBundle 'fuga/piyo' {'autoload': {'filetypes':'ruby'}}` みたいな感じで、遅延ロードできるようになっているようです。

# 結果。。。

あまり変わりませんでした。
多少は早くなったものの、やっぱり操作の一つ一つが遅いのです。

# 悶々とする・・・

ただただ悶々としていたある日のこと…

「むきーーーーー!!!」

と、思いながら、おもむろに ps aux | bash を連打したときのこと。。。

```shell

user 18365 0.0 0.0 2423336 188 s001 RN 12:54PM 0:00.00 bash /Users/user/.rbenv/bin/rbenv init -
user 19381 0.0 0.0 2423336 188 s001 RN 12:54PM 0:00.00 bash /Users/user/.rbenv/bin/rbenv rehash ...
user 20322 0.0 0.0 2423336 188 s001 RN 12:54PM 0:00.00 bash /Users/user/.rbenv/bin/rbenv rehash ...
```


異様に rbenv 関連のスクリプトが多いことに気づいたのでした。
なんじゃこれ・・・?とおもいつつも、デバッグコードをいれたところ、zshenv が異様に遅いことが判明。
遅いのは rbenv 関連というのは明らかだったので、とりあえずそこら辺をコメント化。

で、 vim を起動すると…


なんじゃこりゃぁぁぁーーー


立ち上りチョッパヤ、バッファ移動チョッパヤ、プラギン起動チョッパヤ…


これは…と思い、zshenv の処理をごにょごにょして最適化した結果、キビキビとした vim を取り戻すことができました。

と、いうお話。

これの問題に関しては、さんざんぐぐったのだけれど、
bashrc/zshenv のせいで遅いという話はあまり見受けられなかった。

というわけで、遅くなったのは僕のめちゃくちゃな環境のせいなのかもしれないのだけれど、 Vimmer で、かつ Vim が遅いと思っている方には, シェルの初期化ファイル
(.bashrc/.zshenv)の見直しをお勧めします。


※ちなみに rbenv が遅かったわけですが、これは色々と plugin を導入していたためで、一般的に rbenv が遅いということではありません。あしからず。

markdown でかけると思ってたら、、、hatenablog only だったのか…死

Vimfiler をIDEでよくある感じな感じでつかう

だいぶまえから設定しているけど、Vimfiler でいわゆるIDEツリー的に使うのも結構快適です。
設定のさんぷるは、以下。

let g:vimfiler_tree_leaf_icon = ' '
let g:vimfiler_tree_opened_icon = '&#9662;'
let g:vimfiler_tree_closed_icon = '&#9656;'
let g:vimfiler_file_icon = '-'
let g:vimfiler_marked_file_icon = '*'

command! -nargs=? -complete=file VimFilerTree call s:vimfiler_tree_launch(<f-args>)

  let s:org_scrolloff=-1
  function! s:noscrolloff_leftmouse()
    if s:org_scrolloff < 0
      let s:org_scrolloff = &scrolloff
    endif
    let &scrolloff = 0
    exe 'normal!' "\<LeftMouse>"
    " let &scrolloff = org_scrolloff
  endfunction
  function! s:restore_noscrolloff()
    if s:org_scrolloff < 0
      return
    endif
    let &scrolloff = s:org_scrolloff
    let s:org_scrolloff = -1
  endfunction
  autocmd CursorMoved * call s:restore_noscrolloff()

function! s:vimfiler_tree_launch(...) "{{{4
  let fpath = a:0 > 0 ? a:1 : getcwd()
  execute 'VimFiler -toggle -split -direction=topleft -buffer-name=ftree -simple -winwidth=40 file:' . fpath
endfunction

function! s:vimfiler_smart_tree_h() "{{{4
  let file = vimfiler#get_file()
  let cmd = "\<Plug>(vimfiler_smart_h)"
  if !empty(file)
    if file.vimfiler__is_opened
      let cmd = "\<Plug>(vimfiler_expand_tree)"
    elseif file.vimfiler__nest_level > 0
      let nest_level = file.vimfiler__nest_level
      while 1
        exe 'normal!' 'k'
        let file = vimfiler#get_file()
        if empty(file) || file.vimfiler__nest_level < nest_level
          " let cmd = "\<Plug>(vimfiler_expand_tree)" | break
          normal! ^
          return
        endif
      endwhile
    endif
  endif
  exe 'normal' cmd
  normal! ^
endfunction

function! s:vimfiler_tree_edit(method) "{{{4
  " let file = vimfiler#get_file()
  " if empty(file) || empty(a:method) | return | endif
  " let path = file.action__path
  " wincmd p
  " execute a:method
  " exe 'edit' path
  if empty(a:method) | return | endif
  let linenr = line('.')
  let context = s:vimfiler_create_action_context(a:method, linenr)
  wincmd p
  " call vimfiler#mappings#do_action(a:method, linenr)
  call context.execute()
  unlet context
endfunction

function! s:vimfiler_smart_tree_l(method, ...) "{{{4
  let file = vimfiler#get_file()
  if empty(file) 
    if (a:0 > 0 && a:1 == 1)
      exe 'normal' "\<Plug>(vimfiler_smart_h)"
    endif
    return
  endif
  let path = file.action__path
  if file.vimfiler__is_directory
    if (a:0 > 0 && a:1 == 2)
      exe 'normal' "\<Plug>(vimfiler_smart_l)"
    else
      exe 'normal' "\<Plug>(vimfiler_expand_tree)"
    endif
    normal! ^
    return
  endif
  call s:vimfiler_tree_edit(a:method)
endfunction "}}}
function! s:vimfiler_tree_tabopen() " {{{4
  let bnr = bufnr('%')
  let linenr = line('.')
  let context = s:vimfiler_create_action_context('tabopen', linenr)
  call context.execute()
  unlet context
  silent! exe printf('vsplit +wincmd\ H\|wincmd\ l #%d', bnr)
endfunction

let s:vimfiler_context = {} " {{{4
function! s:vimfiler_context.new(...)
  let dict = get(a:000, 0, {})
  return extend(dict, self)
endfunction

function! s:vimfiler_context.execute()
  call unite#mappings#do_action(self.action, self.files, {
        \ 'vimfiler__current_directory' : self.current_dir,
        \ })
endfunction

function! s:vimfiler_create_action_context(action, ...) " {{{4
  let cursor_linenr = get(a:000, 0, line('.'))
  let vimfiler = vimfiler#get_current_vimfiler()
  let marked_files = vimfiler#get_marked_files()
  if empty(marked_files)
    let marked_files = [ vimfiler#get_file(cursor_linenr) ]
  endif

  let context = s:vimfiler_context.new({
        \ 'action' : a:action,
        \ 'files' : marked_files,
        \ 'current_dir' : vimfiler.current_dir,
        \ })
  return context
endfunction

function! s:vimfiler_my_settings() " {{{3
  if exists('b:vimfiler')
    if exists('b:vimfiler.context') && b:vimfiler.context.profile_name == 'ftree'
      nnoremap <silent><buffer> e :call <SID>vimfiler_tree_edit('open')<CR>
      nnoremap <silent><buffer> E :call <SID>vimfiler_tree_tabopen()<CR>
      nnoremap <silent><buffer> l :call <SID>vimfiler_smart_tree_l('')<CR>
      nnoremap <silent><buffer> <LeftMouse> <Esc>:set eventignore=all<CR>:call <SID>noscrolloff_leftmouse()<CR>:call <SID>vimfiler_smart_tree_l('', 1)<CR>:set eventignore=<CR>
      nnoremap <silent><buffer> <2-LeftMouse> <Esc>:set eventignore=all<CR>:call <SID>noscrolloff_leftmouse()<CR>::set eventignore=<CR>:call <SID>vimfiler_smart_tree_l('open', 2)<CR>
      nmap <buffer> L <Plug>(vimfiler_smart_l)
      nnoremap <silent><buffer> h :call <SID>vimfiler_smart_tree_h()<CR>
    endif
  endif
endfunction


h でディレクトリ戻り or ディレクトリ閉じ、l でディレクトリ展開。
L は下位ディレクトリ移動です。
e/E は最後にアクティブなウィンドウで開く/タブで開くような挙動です。
マウスのだぶくりはディレクトリ開閉です。

b:vimfiler を使っていて、これって公式に触っていいの?という疑問はさておき、、、しばらくつかっておりますが、問題なく動作しております。

eventignore=all をしているのは、主にマウス関連の挙動調整です。
scrolloff とか設定していると、真ん中にきちゃったりしたりするので、それ用の対応策。

CursorMoved とか使わなくてもできるのかもしれないけど、僕の少ない vim 力だとこれで精一杯…(・´з`・)