読者です 読者をやめる 読者になる 読者になる

人類はもっともっとVim本来の機能を使うべきだった

人類はもっともっとVim本来の機能を使うべきだった

はじめに

所属サークルにいるvimmerが使っていなさそうな機能に焦点を当てているので, 若干紹介している機能に偏りがある恐れがあります.

この記事は,SLP_KBITその2 Advent Calendar 2016の18日目の記事です。 また,人類はもっとvim本来の機能を使うべきだったの続きなのでここで紹介している機能は紹介しません.

特に,サークル生がvimを使う上で使っていなさそうな機能に焦点を当てて紹介を行います.

f:id:maxmellon:20161225164711p:plain

遅刻してすみませんでした.

目次

  • 外部ツール連携編

    • vimの中からgrep
    • markdownをいい感じにpreviewしながら書く
    • コマンドの結果をvimに流し込む
    • web上のファイルをそのまま開く
  • 移動編

    • {,} を使って移動
    • <C-^><C-6> でもよい
    • :ls で buffer 一覧を確認し,指定した buffer に移動する

外部ツール連携編

vimの中からgrep

vimは,標準で :grep というコマンドがあります.これは,外部のgrepを呼び出し その結果をQuickFixに流し込無事ができるというものです.

QuickFixというのは,make時のエラーや検索の結果の該当位置をリストで保持し, かんたんにジャンプするためのbufferです.

また,'grepprg' というオプションをセットすることで,外部grepに用いる, grepコマンドを選択することができます.具体的には,aggit grep などを vimの中から叩くことができ,さらにその結果をQuickFixに流し混むことが できるというものです.

ここでは,git grep を用いる例を紹介したいと思います.

set grepprg=git\ grep\ -I\ --line-number

f:id:maxmellon:20161225164752g:plain

デモアニメーションのように,vim内部から素早く git grep を叩くことができ, 更にそれをリストから自由自在に選択できます. コマンドライン上で,grepを叩いて頭で行番号を覚えることから脱却しましょう.

常に 'grepprg'git grep にしていると,git管理下ではないソースコードに対して grepをかけるときに不便です. そこで,私は,:grep をラッピングしたコマンドで運用しています.

function! s:gitgrep(query)
  let l:current_grep = &grepreg " 前回の設定値の保存
  setlocal grepprg=git\ grep\ -I\ --line-number
  execute 'silent grep! ' . a:query
  let &grepprg = l:current_grep
  redraw!
endfunction

command! -nargs=? Ggrep call s:gitgrep(<f-args>)

function! s:jvgrep(query)
  let l:current_grep = &grepprg
  setlocal grepprg=jvgrep
  execute 'silent grep! ' . a:query ' ./*'
  let &grepprg = l:current_grep
  redraw!
endfunction

command! -nargs=? Jvgrep call s:jvgrep(<f-args>)

augroup Vimrc
  autocmd!
  autocmd QuickFixCmdPost make,*grep* cwindow
augroup END

:grep の前に,:silent を挟むことで,Returnキーを押下することなくVimに戻ってくるので便利です.

f:id:maxmellon:20161225164839g:plain

markdownをいい感じにpreviewしながら書く

vimで結構めんどくさいのが,マークダウンを preview しながら書くことです. kannokanno/previm を利用すれば, 実現できるらしいですが,ここではもっとお手軽にプラグインなしで livepreviewを実現する方法を紹介したいと思います.

利用するツールは rhysd/Shiba です.

これは,markdownのlivepreviewに特化したアプリケーションで,ファイルの変更を監視し, 変化があったときに自動でリロードしてくれるというものです. このツールの良いところは,markdownのpreviewに機能を絞っている(エディタに依存がない) ので,様々なツールから扱うことができるということです. ここでは,vimとの組み合わせを紹介したいと思います.

shibaのインストールですが,npmを経由してインストールする場合は,nodeが必要です.

$ npm install -g shiba

パッケージ済みのものをインストールする場合は特に必要ありません. npm経由でアプリケーションを落とさなかった場合は,落としたアプリをコマンドラインから 呼べるように`PATH``を通しておくと便利です.

インストールが完了すれば,これをvimから立ち上げるコマンドを定義します.

command! Shiba :silent call system('shiba ' . expand('%') . ' &>/dev/null 2>&1 &') | redraw!

このコマンドを定義することによって vim の中から shibaを立ち上げることができ, 現在のbufferに対してlivepreviewしてくれます.

f:id:maxmellon:20161225164920g:plain

外部アプリケーションを使うことで,pluginを使わずmarkdownのlivepreviewができるようになりました.

コマンドの結果をvimに流し込む

vimの実行時に - オプションを付与することで,標準出力をvimに流し込む事ができます. curlなどを叩いて,jsonを整形&編集したいときなどで,便利です.

f:id:maxmellon:20161225165230g:plain

web上のファイルをそのまま開く

vimは,:edit に URLを渡すと,そのURLをダウンロードし開いてくれます. wget して エディタで開くという二手間が,vimの中から開くことで一手間に変わります.

f:id:maxmellon:20161225165301g:plain

移動編

{,} を使って移動する

意外と知られていない移動モーション,{,} を紹介します.

{,} は,それぞれ,前後の段落に対するモーションです.

前後の空行に移動すると思えば良いです.大きく上下に移動したいときや, 一つ上の関数定義などに飛びたいとき便利な場面が多いです.

f:id:maxmellon:20161225165336g:plain

他にも,(, ), [[, ]], [], ][] などの便利なモーションが存在します. 興味のある人は,:help を使って調べてみてください

<C-^><C-6> でもよい

<C-^> の便利さは,昨年紹介しました

<C-^> : 直前のバッファに移動する

人類はもっとvim本来の機能を使うべきだった - うどん よこみち

一つ前のbufferに戻るという便利な移動コマンド <C-^> ですが,JISキーボードでは そこそこ押しやすいですが,USキーボードではとても押しづらいです. (Shiftを押す必要があるため)

そんな,<C-^> ですが,実は<C-6> でも動きます.

f:id:maxmellon:20161225165421g:plain

:ls で buffer 一覧を確認し,指定した buffer に移動する

vim では,:ls コマンドで,開いたbuffer一覧を取得することができます. そして,:edit #[number] で,指定した buffer id を開くことができます.

:Unite buffer に当たることを,pluginなしで実現することができます. (Uniteが使えるのであれば使えばいいが,Uniteがないとbufferの移動ができないというのは良くない)

個人的には, :Unite buffer<CR> とタイプするコストと :ls<CR>:e #[number]<CR> をタイプするコストはそんなに変わらない

f:id:maxmellon:20161225165458g:plain

まとめ

vimはpluginもイケているが,素の機能もイケている. 自分の好みに合わせて選択すると良いだろう.

vimの素を知っておくと,拡張がない場面でも難なくテキスト編集できるのではないだろうか.

React.js の syntax ハイライトプラグインを作成した話

React.js の syntax ハイライトプラグインを作成した話

はじめに

この記事は,Vim (その2) advent calendar の 13日目の記事です.

自分の中で,今年一番がんばったVim活動を振り返り,それについて書き記していく. どちらかと言うと,pluginの紹介ではなく,作って良かった点,苦労した点などに焦点を当てる.

背景

自分は,よく React.js *1 を用いて開発を行っている. React.js で開発するときの多くは,javascriptソースコード中にHTMLのような マークアップを埋め込む糖化シンタックスである JSX を用いることが多い. (JSXは,マークアップそのものではなく,トランスパイル時にjavascript の 関数呼び出しに展開される)

そして,自分は普段 Vim を使って開発しており,vim-jsx *2 という, syntax ハイライトのためのプラグインを用いて開発していた.

このプラグインは,とても良いものだったが,バグや不具合が多く目立った. 具体的には,特定の文字列でハイライトが崩れてしまったり,オートインデントが 壊れてしまったりなどである.例えば次のようなものである.

ハイライトが崩れたり,インデントが自動でいい感じにならないのは,僕にとって ストレスが大きかった. そこで,これらの問題の解決を目指して, このpluginを手元で改変して扱うことにした.(最初は,特に fork も push もせず, 手元でのみ書き換えていた.理由としては,vim-jsxに,LICENSEが明記されておらず, forkしていいかどうか判断できなかったため.)

そうしている間に,元のコードがなくなってしまったので,pluginとして公開にあたった.

それが,vim-jsx-pretty である.

プラグインの概要

vim-jsx-pretty では,vim-jsx で抱えていた問題を幾つか解決した. それは,次のデモを見てもらえるとわかりやすいだろう.

vim-jsx-pretty mxw/vim-jsx
vim-jsx-pretty vim-jsx

他にも,オートインデントに対応した.

Auto indent

Pluginを作成する上で参考にしたのは,Vimのruntime以下の最初から入っている, syntaxの設定ファイルである xml.vim だ.

コメント文による例も非常にわかりやすく,Vimにおける,正規表現の 教材としても良いのでは,と感じた.

プラグインの宣伝記事ではないのでこのあたりでとどめておいて, プラグインを作成して感じたことを振り返って行きたいと思う.

良かった点

  • 苦手な正規表現と向かい合うことができた.

前よりは,正規表現に明るくなった気がしている.

  • Github/issues を通して,かんたんなディスカッションをすることができた.

自分のツールを,他人に使ってもらえる嬉しさをしれた. また,意見やバグ報告を対応する,大変さと喜びを少ししれた.

  • 開発中の不満を自分の力である程度解決することができた.

今までは,口を開けて問題を解決するまで待っていたが,今年は,Vimに限らず これまでに比べて,自力でバグを修正しようとすることができた. (具体的には,今年はじめて利用しているライブラリにPull Request送ったりすることができた)

このプラグインの場合,Pull Request ではないけど, 自分の力で(完全ではないかもしれないが)不満を解決できてよかった.

まだできていない点

  • 網羅的な動作チェック

現在,手でインデントや,シンタックスハイライトに問題がないかどうか確認しているが, すべてのシンタックス及びインデントで正常に動作するかがまだわからない.

  • テストの自動化

単純な,コマンドや関数の単体テストの方法は,知っているがシンタックスハイライトが できているかどうかをコードでテストする手段がわからなかった. あるいは,そういったツールがあるのかがわからなかった. もし,ないのであれば,特定のバッファに対して,指定したカーソル位置が 期待したハイライトグループかを検証する,アサーションなどを作ってみても良いかもしれない.

  • 英語記事

今年中に英語記事書きたい.何故かと言うと,きっと同じ問題でストレスを抱えている, ユーザーがいるはずだと思ったから.(英語記事書きたいと思ってから,30日近く経っていて, 非常に良くないので,今年中とここに宣言しておく.)

わからない点

  • LICENSE 的に問題ないのかどうかがわからない

このプラグインは,vim-jsx の焼き直しに近く,LICENSE的に問題あるのかないのかがわからない. (vim-jsxのソースコードを利用しているわけではない.) そもそも, vim-jsx にライセンスが存在しない.

このあたり詳しい人教えてほしいです.

まとめ

  • 自分にとってのストレスを解決するために,プラグインを作った(焼き直した)
  • 他人に,ツールを使ってもらう喜びを知った
  • Vimにかぎらず,自分にとっての問題やストレスは,自力で解決を試みてみるべき
    • もし一人で無理なら,適当なコミュニティで質問するのとかが良さそう
    • 解決のためにいろいろ調べたり,試行錯誤したりするので,得るものがたくさんある (たぶん)
    • 新たな挑戦のきっかけにもなる(まだできてないけど英語記事書きたいな〜とか)

hammerspoon を入れてみた.

この記事は SLP-KBIT アドベントカレンダー その2 の1日目です.

hammerspoon とは

Staggeringly powerful OS X desktop automation with Lua

らしい.どうやら lua を使って OSX に強力な自動化を提供してくれるデスクトップアプリケーションらしい. 今回はコイツを使って,Windows である Win + ← や Win + → に似た機能を実現しようと思う. といっても,自分で実装したのではなく,公式のサンプル集 から抜粋したものである.

hammerspoon をインストールする (for mac)

https://github.com/Hammerspoon/hammerspoon/releases/tag/0.9.50

まず,ここから zip を落として,回答したものを ~/Applications に設置する. その後,アプリケーションを実行する.

実行すると,次のような設定画面が出てくる.

f:id:maxmellon:20161130220343p:plain

アクセス権限を求めてくるので,許可する

f:id:maxmellon:20161130220424p:plain

表示が切り替わっていることを確認する

f:id:maxmellon:20161130220513p:plain

これでインストールは完了.

ホームディレクトリに

~/.hammerspoon/ という名のディレクトリが作られているはずなので,その中に設定ファイルを作成しておくこと.

$ touch ~/.hammerspoon/init.lua

設定ファイルは,すべて lua で記述するのが,このアプリケーションの特徴の一つだ.

Windowsのようにウィンドウ をガンガン動かすためのスクリプトを導入する

github.com

この方の,この設定ファイルを導入するだけで,自由にウィンドウを操作できるようになる.

上記ファイル(position.lua)をダウンロードし,~/.hammerspoon/ 以下に設置する. その後,init.lua に次のように追記する

dofile("position.lua")

f:id:maxmellon:20161130221026p:plain

そして,リロードすると,

Ctrl + Alt + Cmd + カーソルキー で ウィンドウを次のように動かせるようになります!!

キーバインドを変更する

Ctrl + Alt + Cmd というのは非常に押しにくいので,自分は変えました.

137c137
< hs.hotkey.bind(hyper, "up", function ()
---
> hs.hotkey.bind({"cmd"}, "up", function ()
139c139

こうすることで, "cmd" キーだけで操作できます,他のキーにしたければ自由にでしてみてください.

まとめ

マウスを使わずに ウィンドウをきれいにわることができる!!便利!!!!

vimconf2016 参加感想

2016/11/05 (土) にmixiで行われた,VimConf2016 へ参加しました. 今回が初の参加となります.

ここでは,自分にとって,すごく面白いと感じたプレゼンを2つに絞り, 感想を共有したいと思います.

本記事で紹介する以外のプレゼンも大変素晴らしく今後の展望が気になるものなど たくさんあり,非常に素晴らしかったです.

まえおき

本記事で,すべてのプレゼンに対して感想を書かない理由は,ある程度他の参加者と 共通している部分が多いのと,記事が長ったらしくなってしまうことを懸念しました. また,全部を見せるのではなく,チラ見せすることによって他の方の参加者の報告を見る きっかけになれば良いと考えました.

もし本記事で,VimConfに対して興味を持っていただけたのであれば, 他の発表者のプレゼンテーションや参加記録も合わせてチェックすることを おすすめします! :)

Introduction to Vim 8.0

発表者: Ken Takata さん

資料: http://www.slideshare.net/k-takata/introduction-to-vim-80

発表は,version8の新機能紹介と,vimの誕生から現在までの歴史, 日本人の貢献度などについて触れられた. :h version8 の流れと,前半の発表資料の流れが連携していて感動した.

この発表では,自分の知らないVimの歴史について知ることができた. 特に,自分にとって衝撃的だったことは,vimへパッチを 送っている日本人がこんなにも多いというだった. 自分は,パッチを当てている人たちを見ているだけの,ただのファンだったが, パッチを当てている日本人が多いということにすごく誇らしく感じた. 同時に,自分が大きな不自由なくvimを使えているという現状には, vim patch職人の方々の苦労があるということに気が付かされる機会となった. そして,今すぐには不可能かもしれないが,いずれかは今,前線で輝いているパッチ職人の 方々のように何らかの形でvimに貢献したい と強く考えさせられる発表だった.

vimを当たり前のように使えていることがすごいことであるということに気づくことができた発表だった.

vim-mode-plus for Atom editor vimconf-2016

発表者: t9md さん

資料: http://qiita.com/t9md/items/0bc7eaff726d099943eb

この発表は,Atomにおける,vim拡張をより使いやすく便利にしたというものであった. 面白いと感じた部分は,Atom上でvimをエミュレートするだけにとどまらず, Atomの機能とVimの機能をそれぞれ組み合わせて,今までにないような 斬新的な機能を作ったという部分である. また,使いやすさや,便利さに対する貪欲でひたむきな考え方は, 発表を聞いている人全員のこころをガッチリと掴み,そして,Atomを使うことによって Vimしか使っていなかったときよりもVimに 詳しくなったという発言が, 誰もが納得できるほどのクオリティの高さを感じた.

もちろんプラグイン自体の斬新な発想から実装された独自機能も面白かったが, それをよりわかりやすく聴衆に伝えるためのデモの旨さを発表後の振り返りで気が付かされた.

考え方や,エディタに対する理念がすごく筋が通っていてめちゃくちゃかっこよかった.

おわりに

VimConfは,発表者のレベルが高い以外にも良いところがあるということに, 実際に参加してみて気が付かれたので,最後にそれをシェアしたいと思います.

個人的に,VimConfで良かったもう一つのポイントは, 同年代のエンジニアとたくさん対話することができたことです. 特に,github上で大きな貢献を成し遂げているの @b4b4r07 さんと, @haya14busa さんと,比較的長い時間 対話することができたことです.

多くのユーザーが付いているツールのメンテナンスの苦労話や,自分のプロダクトに 対するこだわりなどを聞けることができ,非常によかったです.

VimConfは,技術レベルの高い話が聞けるだけでなく,新しいコネクションも作れるので ぜひ,興味は持っているが,行ったことがないという方は次の機会にでも参加してみることを おすすめしたいです.

最後に,発表直後のテンション高い状態で書いた記事で拙い文章でしたが, ここまで読んでくださりありがとうございました.

感無量です!

おまけ

Udon.vim やる

反省点,3日前に熱で寝込んでしまったのでもうちょっと季節の変わり目,気温差が激しい時期は体調管理に気をつけ,次は良い体調で参加できるようにする.

git branch を fzf で選択していい感じに一括削除

git branch を fzf で選択していい感じに一括削除

git の branch を fzf で選択して削除するというもの

git-remove-branch()
{
  local branchs q k results
  while out=$(
    git branch | sed -e 's/\*//g' -e 's/\ //g' \
               | sed -e 's/master//g' -e 's/develop//g' \
               | fzf --ansi --multi --no-sort --reverse --query="$q" \
                     --print-query --expect=ctrl-d); do
    q=$(head -1 <<< "$out")
    k=$(head -2 <<< "$out" | tail -1)
    branchs=$(sed '1,2d' <<< "$out" | awk '{print $1}')
    branchs=("${(@f)$(printf $branchs)}")
    [ -z "$branchs" ] && continue
    if [ "$k" = ctrl-d ]; then
      for branch in $branchs; do
        git branch -D $branch
        if [ $? -eq 0 ]; then
          results=($results $branch)
        fi
      done
      printf "\n\e[31m Deleted branchs:\e[0m\n"
      for result in $results; do
        printf "\t\e[32m $result\e[0m\n"
      done
      printf "\n"
      break
    fi
  done
}

Ctrl-i で 複数選択後,Ctrl-d で削除

f:id:maxmellon:20160925031448g:plain

React 用 の Slider UI plugin つくりました

react-simple-slider

github.com

趣味アプリ作ってる時に既存のものを利用しようと思ったのですが, 既存のものがビミョだったので,1から作りなおしました.

(具体的には,デザインを変えづらかった,DOM構造が複雑だった.個人的にもっとシンプルなのが欲しかった)

使い方

      <Slider
        height={20}
        width={300}
        default={150}
        max={300}
        onChange={onChange}
        backStyle={{ backgroundColor: 'black', }}
        frontStyle={{ backgroundColor: 'red' }}
      />

みたいな感じです.

なるべくシンプルになるようにしました.

ref を指定すると

const value = this.refs.slider.getValue();
this.refs.slider.setValue(value);

みたいな感じで setValuegetValue を利用することができます.

EventEmitter Speed BATTLE!!!!

eventemitter比較しました.

javascript といえば,eventemitter, eventemitter といえば,javascript

(たぶん)

そんな,Eventemitter のベンチマークを書きました.

  • 調査対象.

    • node の標準搭載のEventEmitter
    • EventEmitter2
    • EventEmitter3
    • EventEmitter4
    • fast-event-emitter (計測時はEventEmitter5としています)
  • 参考にしたサイト

yosuke-furukawa.hatenablog.com

ここのeventemitterのベンチマークを勝手ながら流用させていただいています.

gist.github.com

結果発表

// EventEmitterHeatUp x 1,854,119 ops/sec ±3.33% (81 runs sampled)
// EventEmitter x 1,941,173 ops/sec ±2.13% (80 runs sampled)
// EventEmitter2 x 3,324,465 ops/sec ±2.08% (84 runs sampled)
// EventEmitter3 x 1,239,810 ops/sec ±1.57% (85 runs sampled)
// EventEmitter4 x 236,741 ops/sec ±1.42% (92 runs sampled)
// EventEmitter5 x 3,572,485 ops/sec ±1.81% (87 runs sampled)

// Fastest is EventEmitter5

5 > 2 > 1 > 3 >4 の順で速度がはやいみたい.

emit() の反応速度は,一概に新しい奴が早いわけではないみたい.

5 はまだスター数がそこまで多くないので様子見. 3 はon の第2引数にundefined入れても例外が投げられず,よくわからないとこでコケる. これからは,eventemitter2 を使うことにします.