XMonad の NamedScratchPad と restart.vim のアギャーーーー!

これは、タンスの裏の隙間に潜んだマンボウや棚の上に潜んだモモンガが襲い掛かってくる Vim Advent Calendar 2013 : ATNDの 100 日目の記事です。

XMonad 伝説

XMonad には、特定の(アプリを起動|アプリのウィンドウを出し入れ)する、「スクラッチパッド」という機能があります。
これを使うと、ホットキーで gVim のメモ帳などを簡単に呼び出したり、非表示化できます。

これは超便利なのですが、restart.vim で再起動してしまうと問題が起きます。
スクラッチパッドのウィンドウとみなされなくなってしまい、ホットキーで呼び出したつもりが、新規に gVim が起動してしまうのです。

原因は、スクラッチパッドウィンドウの特定をするのに各 Window に付随するプロパティ値などを使う必要があり、それが再起動により消えてしまうから。
(プロパティを使わないと、複数gVim ウィンドウがあったときにどれをスクラッチパッドとしたいのか判断できない)

解決方法

restart.vim には、再起動後に実行するコマンドを設定する機能(?)があるので、それを用いてプロパティ値の復帰を行います。
ただ、起動時に指定する以外の標準的な方法がなさそうなので、xprop コマンドを実行する関数を作ってやります。
(ついでに、起動後自分で任意の値に変更できるように、コマンドも定義します)

function! s:SetWindowRole(role)
  call system(printf('xprop -id %s -f WM_WINDOW_ROLE 8s -set WM_WINDOW_ROLE %s', v:windowid, a:role))
endfunction
command! -bar -nargs=* SetWindowRole call s:SetWindowRole(<q-args>)

あとは、restart.vim が復帰時に使うコマンドを生成する関数の定義と、設定です。

function! s:OnRestart()
  let res = [] " ここに復帰時に実行したいコマンドを突っ込んでいく

  " 念の為&手抜きで、role に使用する文字を制限してる ([a-zA-Z_-])
  let l:window_role = substitute(system('xprop -id ' . v:windowid . ' WM_WINDOW_ROLE'), '^.*= "\([a-zA-Z_-]\+\)".*', '\1', 'g')
  if match(l:window_role, "^WM_WINDOW_ROLE:.*not found") < 0
    call add(res, 'SetWindowRole ' . l:window_role)
  endif

  return join(res, ' | ')
endfunction

let g:restart_save_fn = [function('s:OnRestart')]

できた!

第三部完

起動時の role の設定

ちなみに、gVim の場合、以下のようするだけでウィンドウの WM_WINDOW_ROLE プロパティを設定できます。
初めに起動するときは、これで適当な名前をつけてやれば OK です。

gvim --role notes ~/notes.txt

XMonad の設定はこちら

https://bitbucket.org/anekos/xmonad-conf/

スクラッチパッドの設定は lib/Anekos/Config/Scratchpad.hs