Hatena::ブログ(Diary)

t9mdの日記 Twitter

2014-01-12

[] choosewin.vim をつくりました

この記事はVim Advent Calendar 2013 44回目(不吉な..)の記事です。

新しいプラグイン vim-choosewin を作りました。

最初に作ったのは去年(2013年)の12月なのですが、正月頃、manga-osyo さんに

色々とアイデアを貰い、発展し、けっこう大げさなプラグインになりましたので紹介します。


■ これは何をするものか?

以下の GIF アニメを見てください。

ウィンドウに表示されるラベルを入力することで、目的のウィンドウに一発で移動できます。

f:id:t9md:20140113002740g:image


■ 作った背景

tmux というターミナルマルチプレクサ(一つのターミナルで、沢山のウィンドウを開いたりするソフト)

があります。 Mac とか、Linux の人は使っている人も多いでしょう。

tmux には display-pane というコマンドがあり、数字キーを押すことで、飛びたいウィンドウに一足飛びに移動できます。

f:id:t9md:20140113002741p:image

tmux の display-pane 機能: こんな画面で数字キーを押すと数字の Window にフォーカスが移る。


今回作成した choosewin は tmux のこの機能に着想を得たものです。

大きな解像度の、広い広いディスプレイを使っている人は、沢山ウィンドウを開いているでしょう。

沢山開いていると、一番右端のウィンドウから、一番左端のウィンドウまで移動するのにとても苦労するでしょう。

私はウィンドウの移動を CTRL キー jkhl と組み合わせて移動する様にしていますが、

一番右下、一番左上の移動には、C-h C-h C-h C-k C-k とかやらにゃならん。

そうなるとコントロールの押しすぎで、小指が痛むでしょう。

小指が痛むと悲しいでしょう。

ということで、Choosewin はこの問題を解決すべく作りました。



インストールと使い方

NeoBundle 等でインストール後 <Plug>(choosewin) をマッピングして下さい。

以下の例では、'-' で choosewin を呼び出すようにマッピングしてます。

nmap  -  <Plug>(choosewin)

ウィンドウ選択は以下のような流れになります。

  1. '-' で choosewin を呼び出す。
  2. 各ウィンドウのステータスバー又は、画面の真ん中(オーバーレイ機能有効時:後述)にラベルが出る。
  3. 移動したいウィンドウのラベルを入力
  4. 選択したウィンドウに着地する。

同様にタブにもラベルが出るので、ラベルを入力することで別タブのウィンドウにも移動できます。

タブ間の移動はラベルを入力して移動する以外に、以下のキー操作でも行えます。

キー アクション 何するか?
0 tab_first 最初(一番左)のタブへ
[ tab_prev 前のタブ
] tab_next 次のタブ
$ tab_last 最後(一番右)のタブへ
; win_land カレントウィンドウに着地
<CR> win_land カレントウィンドウに着地
<NOP> マッピングを消すときに使う


■ オーバーレイ機能

choosewin のデフォルト設定では、ウィンドウラベルはステータスバーに出るのみです。

大きな画面ですと、目線が移動して不便でしょう。

画面の広大さに比して、ステータスラインは細すぎてほぼ見えないでしょう。

tmux は各ウィンドウの真ん中に大きな文字でラベルが出るので、やっぱりあんまり便利じゃないかも、と思ったでしょう。

そんな人は勇気を出して以下の機能を有効にしてみてください。

" オーバーレイ機能を有効にする。
let g:choosewin_overlay_enable = 1

" オーバーレイ時、マルチバイト文字を含むバッファで、ラベル文字が崩れるのを防ぐ
let g:choosewin_overlay_clear_multibyte = 1

これで各ウィンドウの真ん中にラベル文字が出るようになります。

かなり tmux のオリジナルの機能に近づきました。

目線も動かないし、素晴らしい。

しかし先ほど「勇気を出して」機能を有効にする、と書いたように、この機能を実現するために、結構無茶なことをやっています。

Vim は画面にフォントをオーバーラップして表示する機能をサポートしていません。

そのため、matchadd() というハイライト機能で、1バイトずつハイライトして、ドット文字として、ラベルを表現しています。

タブ文字や、マルチバイト文字があると、1バイトずつのハイライトが出来ないのでラベル表示前にこれらの文字を空白スペースに置き換えたり、ファイルの末尾だと、何も文字がないので、行を追加したり、という大げさな事をやっています。

単なるウィンドウ移動にこれは大げさだ、とか、ハイライトが遅い、とか、あるいはまだ多くの人がつかっていないので、破壊的エラーが起こらないとも限らない、とかでデフォルトで無効にしていますが、

私自身の印象としては結構イケそうな気がするので、どんどん使ってみていただきたいです。




■ 最後に、私の設定

私は、オーバーレイをメインで使用し、ステータスラインのリプレイスも、タブラインのリプレイスも無効にしています。

色は、tmux の雰囲気に合わせています。

" '-' で呼び出し
nmap  -  <Plug>(choosewin)

" オーバーレイを使う
let g:choosewin_overlay_enable = 1

" マルチバイトバッファでオーバーレイフォントを崩さないように
let g:choosewin_overlay_clear_multibyte = 1

" tmux の色に雰囲気を合わせる。
let g:choosewin_color_overlay = {
      \ 'gui': ['DodgerBlue3', 'DodgerBlue3' ],
      \ 'cterm': [ 25, 25 ]
      \ }
let g:choosewin_color_overlay_current = {
      \ 'gui': ['firebrick1', 'firebrick1' ],
      \ 'cterm': [ 124, 124 ]
      \ }

let g:choosewin_blink_on_land      = 0 " 頼むから着地時にカーソル点滅をさせないでくれ!
let g:choosewin_statusline_replace = 0 " どうかステータスラインリプレイスしないで下さい!
let g:choosewin_tabline_replace    = 0 " どうかタブラインもリプレイスしないでいただきたい!

2013-12-27

[] 私の Vim 活記録

この記事は Vim Advent Calendar 2013@25日目 の記事です。

私が Vim を本格的に触り始めたのは、Emacs を使いすぎて、小指が痛くなり、

泣く泣く Emacs 使いとしての選手生命を断念した、2010 年の秋頃でした。


より小指にやさしい、Vim に乗り越えた私は、Emacs で鍛えられた、「エディタ

設定を妥協せず、どこまでもカスタマイズする 」という精神の元、Vim を本格的に

使い始めました。

以前なら諦めていたような、理解不能な動作に出会っても、Emacs で鍛えられた不屈の

精神を持って立ち向かい、Google 検索をし、quickrun で試し、というように格闘しながら

Vim 力を少しずつ向上させていきました。

そして、 vim-textmanip, vim-quickhl, vim-chef, といったプラグインを作成したりしました。

vim-chef を作った頃は、chef を使い始めようと、学習し始めた途端、まだ chef を使う前に、

Vim プラグインを作り始めてしまうという Vim 中毒の典型的な症状を示すほどに、Vim 依存が

進行していました。


しかし、そんな蜜月に突然おわりが訪れました。

2012年の1月のことです。私は転職をし、仕事で使うパソコンが、Linux からWindows になりました。

仕事で、プログラムを書く機会はなくなり、Vim を使うのをやめました。

それまでの1年間、あんなに毎日触っていた .vimrc を触らないまま 1年半以上が経過した今年の9月(2013年9月)に、

私はまた Vim を触り始めました。以前とは違い、純粋に趣味的な意欲で。


それから3ヶ月が過ぎました。

作成したプラグインや、追加した機能など一つ一つ紹介した気持ちと、機能実装を終え最低限の help

ドキュメントを書いたものに、また説明を加える面倒臭さの両方があります。

しかし、面倒ながらも記録には残しておきたいと思い、このエントリを書いています。

また、Vim を触らなくなってしまう日が来るかもしれませんが、少なくともこの3ヶ月間、

かなり熱心に Vim と過ごしました。

その3ヶ月間のアウトプットとして次のような成果が残りました。


---------------------------------------------------

2011年10月ー2013年12月中旬までの僕の Vim 活の記録

---------------------------------------------------

vim-unite-experiment

バッファ名を使用した、source 毎のヒストリー保持を実験的に実装


vim-quickhl

全面書き直し。主にリファクタリング

tag ハイライトの追加


vim-macvim-transparency

新規作成。小型プラグイン

macvim のGUIウインドウの透明化を行いやすくする

透明度を変更する仮想キーマップを提供する。


vim-textmanip

全面書き直し。今や自分の作った中では大型プラグインの部類。

大きなファイル編集時の行移動のパフォーマンス向上

矩形選択範囲の複製、移動機能を追加

モードの概念の導入(従来モードはinsertモード)し、新しく replace (上書き) モードの追加。

はっきり言って開発つらかった。気合と根性としぶとさで仕上げた。


vim-mapswap

新規作成。

キーマップの一部を一時的に変更して、元に戻すプラグイン

submode と似ているが目的が異なる。

submode は設定したキー以外を入力するとサブモードから抜けてしまうが、

mapswap は特定のキーのみマッピングを差し替え、他のキーは元のままのマッピングで使える。

スワップしたキーマップはユーザーが明示的に戻す。

用途としては、読み込み専用のファイルでのみ d や u でページスクロールしたり、

diff モードの時、変更点間を移動するキーマップを有効にするといったもの


vim-ruby-xmpfilter

全面書き直し。小型プラグイン

seeing_is_believing をサポート。


vim-easymotion

カーソル移動系プラグイン(smalls) 作成の為の事前学習として本家のものを

fork して自分が理解しやすいように大幅に書き換え。

動作理解の為なので、一部の機能が動かなくなっても気にせずどんどん書き換えた。

これで easymotion のやっていることを大体理解した。


vim-smalls

新規作成。割と大型の部類。現在も開発中。

カーソル移動補助プラグイン

easymotion style のジャンプと独自のexcursion モード


vim-ezbar

新規作成。小型プラグイン。機能追加は多分ない。あとはメンテのみ。

lightline を使ってみて、設定に苦しみ(というかやりたい事ができず)

お試しで作り始めた。

自由度の高さと、色変更のやり易さが特徴


yankround.vim への pull request.

@ さんの yanround.vim に貼り付け範囲をハイライトする、pull request.

Emacs の頃にやっていた yank-pop のハイライトを思い出して。

smalls で矩形範囲ハイライトに慣れていたので、それを流用。

細かいところは LeafCage が直してくれた。


vim-phrase

全面書き直し。個人的には結構便利に使っているプラグイン

試しに vital も使ってみた

phrase file のフォーマット変更

もう少しちゃんとして、これは流行らせる努力をしたい。


vim-choosewin

新規作成。小型プラグイン

tmux の `display-pane` 機能を模倣するアイデアプラグイン

単にウィンドウ番号を読み取って `:{N}wincmd w` で移動するだけ。

window 番号の表示には `'statusline'` を使用する。

eazybar の機能を利用すればいい感じにウィンドウ番号を表示可能。


---------------------------------------------------

2011 年頃、Vim に熱中している僕を「このVim 野郎 」と罵った妻は、今では夜遅く寝室に入ってくる僕に

寝ぼけ眼で「 Vim ちゃんやってたの? 」と優しく声をかけてくれるまでに、僕と Vim との関係を理解

してくれています。

ますます Vim との触れ合いが捗る今日この頃です。

それではまた。

2013-10-16

[] Unite menuを使ってオプションのToggleを簡単にする

この記事はVim Advent Calendar 2012 321日目の記事です。

昨日の記事は id:osyo-manga さんの vimneosnippet.vim を活用しよう でした。

今日は unive.vimUnite menu を使って Vimオプションをトグル(反転)させる方法を紹介します。

■ 概要

  • Vim の boolean option はいっぱいあるけど、めったに変えないオプションだと忘れてしまう。
  • キーマップ設定してても、たまにしか使わないので思い出せない!
  • unite menu 化して、曖昧な記憶でもオプションを Toggle 出来るようにしよう。

■ boolean option の基本

Vim にはboolean(0か1の値)オプションが沢山あります。

number とか hlsearch とかがそれです。

" 行番号を表示
set number

" 1が表示される。
echo &number

" 行番号を非表示
set nonumber

" 0が表示される。
echo &number

" 値を反転。0 => 1, 1=>0
set number!

" 現在の設定値を表示
set number?

Unite menu 化する。

set number! の様に'!'をつけるとオプションをトグル出来ます。

set number? とすると現在の値が表示されます。

これをまずコマンドにしてみます。

" コマンド ToggleOption の定義
command! -nargs=1 ToggleOption set <args>! <bar> set <args>?

これで

:ToggleOption number

等とすることで、オプションの設定をトグルし、現在の値を表示出来るようになりました。

あとは、Unite menu の command_candidates で登録します。

let g:unite_source_menu_menus = {}
let g:unite_source_menu_menus.toggle = {}
let g:unite_source_menu_menus.toggle.command_candidates = {
      \ 'number': "ToggleOption number",
      \ 'hlsearch': "ToggleOption hlsearch",
      \ }

" mac の 'Command-/' で呼び出し。
nnoremap <D-/> :Unite menu:toggle -start-insert -auto-resize<CR>

これで ':Unite menu:toggle' を実行すれば、Toggle 系のオプションを変えられる様になりました。

Vimデフォルトオプション以外にも、Toggle 系を全部まとめてしまえると便利です。

':Unite command' から toggle を検索してよく使いそうなものを探すといいです。

最終的には以下の様な設定を .vimrc に設定しました。

let g:unite_source_menu_menus = {}
let g:unite_source_menu_menus.toggle = {}

" vim 以外のオプション
let g:unite_source_menu_menus.toggle.command_candidates = {
      \ 'tagbar': "TagbarToggle",
      \ 'nerdtree': "NERDTreeToggle",
      \ 'quickhl':  "QuickhlTagToggle",
      \ 'neocomplete': "NeoCompleteToggle",
      \ }

" options にスペース区切りでオプション名を列挙する。
let options = "
      \ paste spell list number relativenumber incsearch wrap hlsearch
      \ foldenable ignorecase readonly wrapscan"

for opt in split(options)
  let g:unite_source_menu_menus.toggle.command_candidates[opt] = "ToggleOption " . opt
endfor
unlet options opt

これで NeoCompleteToggle とか、TagbarToggle とか Toggle 系のオプションがまとめて '<D-/>' で呼び出せるようになりました。

■ 最後に

上記のサンプルに反して、あまりにもよく使う number とか hlsearch とかのトグルは以下の様に設定してます。

'キーマップを手が覚えている' 状態のものは Unite menu:toggle に追加する必要はないです。

nnoremap <Space>n  :ToggleOption number<CR>
nnoremap <Space>/  :ToggleOption hlsearch<CR>

2013-08-13

2011-07-17

[] Sugamo.vim 第四回に行ってきた。

7/16 日、Sugamo.vim というミニ勉強会みたいなのに行ってきた。

場所は巣鴨ルノアールの会議室。

ルノアールって会議室とかあるんですね。プロジェクターも使えたし、便利ですなー。

Sugamo.vim ってのは Sugamo.css という勉強会Vim 使いのメンバー達が始めた派生的な勉強会みたい。


id:tihnca さんも発表内容はレポートしてくれてます。

http://d.hatena.ne.jp/thinca/20110717/1310838288

はじめに

こういうスタイルの勉強会に参加したのは初めてだったし新鮮だったし、Vim使いがマイナー扱いされない

サークルは今の俺の職場ではないわけで、それだけでうれしかった。

id:thinca さんや、@ さん

といった、名前けは知っている、プラグインの作者に会えたのが良かった。

やっぱりお世話になっているプラグインの作者と生で会えるとヤル気がでますな。

フリートーク的な時間がなかったので tsukkee さんや thinca さんと直接にいろいろと話せなかったのは残念だった。

まあ俺自身も、飯を食いに行かずに帰っちゃったというのもありますが。。

自己紹介のコーナー

最初、自分の自己紹介をしつつ、自分の Vim レベルを5段階評価で発表する。

レベル5が最大で、'プラグインを作っている' だと最大の5になる評価基準。

俺はプラグインつくってるから一応5とは言ったのですが、この5の中にも色々いて、

ちょっとプラグインつくった、って言うレベルと、本格的に巨大な、あるいは Vim のはまりどころを

巧みにかわしつつ、お行儀の良いプラグインを作成しているか?といったところではレベル5といっても

ピンキリなワケで、そういう意味で自分がレベル5というのはおこがましく感じたというのはある。

いや、ほんとにエライ差があるんです、Vim の鍛錬はキリがないのでね!

発表

@ さんによる、彼の vimrc の内容を読んでいく発表。

疑問点はその場でポンポン質問するスタイル。

@sigwyg さんは自己紹介で、自分のレベルをレベル3で、'function かけるレベル'(だったかな?)'みたいに

分類してたけど、設定は VimShell/VimFiler/Unite とかつかってたり、プラグインは Bundle で管理してたりと

まったくの初心者はよくわからん、というぐらいアドバンスドだったと思う。

surround / align / vimfiler / vimshell / unite / neocomplecache / snipmate etc..

@ (俺) による発表

特に発表する予定はなかっけども、@sigwyg さんの発表を聞いているうちに、自分でも喋りたいなという気になってきて、「やります」といって発表した。

GitHub - t9md/vim-textmanip: easy text manupilation for vim

「おー!」と言ってもらえて嬉しかった。

個人的には、作った当初は「スゲー!」と自画自賛してはいるんですが、普段も実用で使ってるわけですが、会社で見せても、「気持ち悪」がられ、「どうせすごくマニアックな設定が必要なんでしょう?そこまでは必要ないわ」みたいな白い目で見られる感じなので、「自分もやってみよう」とはなってくれない。。

Sugamo.vim にいた人たちは「使ってみよう」的な人も結構いたので報われた。という感じ。

素直にうれしいかった。

他には

GitHub - t9md/vim-ruby_eval: evaluate text fragment as ruby then insert or print

GitHub - t9md/vim-quickhl: quickly highlight <cword> or visually selected word

unite関数/変数の使用箇所をクイックチェックするサンプル

unite_ack で見つかった jump_list を C-z に割り当てた <Plug>(unite_toggle_transpose_window) で、vertical にし、persist_open アクションで、関数変数の使用箇所をクイックチェックする、みたいなの。

surround.vim のカスタマイズ例

帰ってきてからプラグイン化して GitHub - t9md/vim-surround_custom_mapping: helper utility for tpope's surround.vim , which enables you setup filetype based custom mapping. に上げた。

@ さんによる発表

リクエストされて、thinca さんの Unite の設定をいろいろと紹介。

本当はひとつひとつじっくり聞いたり理解したりしたかったけど、あの時間ではさすがにムズカシイ。個人的に後半でバテてたのもあるし。

filetype プラグインとしてファイル分けて書くスタイルなんですね。自分は .vimrc 一ファイルにベタ書きなので新鮮だった。

最後に感想とか希望とか

全体的には小規模で、いい意味でゆるい雰囲気で好きだった。

個人的な希望としてはフリートーク的な時間が欲しかった。それぞれパソコン持ってきているので、自由に話したい人と vim の設定いじったりしながらああだこうだ言うスタイルの時間。

発表形式だけだと、初めて来た Vim の初心者の人はあまり発言が出来ずに聞きたいことが聞けなかったのではないか?と思ったりもする。

初心者向けではないのかもしれないけど、初心者も結構いたので初心者へ優しい時間対を明示的に設けるとかどうだろう。

自分のプラグインを職場の人以外に実際に見せたのは初めてだったのですが、quckhl.vim とかは明らかに気づいているバグもあって、発表した手前、「これはまずい」ということでさっき直したり、

surround.vim のカスタマイズは 手っ取り早く使えるようにプラグイン化したり、作者に pull_request 送ってみたりもした。

こういうことは会に参加して発表しなければやらなかったので、個人的に、いいプレッシャーというか、フィードバックをもらえたのでした。

Vim Hacks Project になんか書きませんか?と thinca さんに誘っていただいたのもよいプレッシャー。

※ ちなみに textmanip についてはドラフトを書いてみた。

次回もあれば参加してみたいな。

主催者の方、参加者のみなさま。ありがとうございました。