haya14busa

haya14busa’s memo

2015年夏,はてなインターンでMackerelをとにかく便利にして優勝してきた

インターン終わったときに書きたかったのですが,バタバタしていたのと,イカ (Splatoon)という麻薬に犯されたので2015 年の振り返りとして書いています. 乗り遅れた感しかないけど記録として残しておきま す! 2015年全体の振り返りはこちら -> はてな,Googleインターン行ってイカやりすぎたイカVimmerの2015年の振り返り - haya14busa

今年の夏はどこかインターン行きたいなぁ〜,最高の夏を過ごしたいなぁ〜と思っていました. そんな時に はてなサマーインターン2015 情報, 特に今年は Scala や swift が書けるコースもある という話を聞いてこれは行きたい! と応募しました. その結果幸運なことに選考に受かったので8月10日から9月4日まで最高の夏を過ごしにはてなインターンに行ってきました.

はてなインターン TL;DR

  • 噂の(?)今年のインターン生の Emacs 率が0だった
  • 僕は言語がScalaのMackerelコースで, id:tyage くんさんと一緒に Mackerel を便利にして優勝してきましたっ! めでたいっ 🎉🎉🎉
  • はてなインターンで優秀なはてなの社員さんや他のインターン生の仲間と開発できたのは最高の体験でした.もっかい体験したい.

参考情報

はてなインターン応募と参加

一昨年の2013年夏にインターン探していたときも,はてなインターン卒業生のブログな どを読んで, はてなインターンよさそうだなぁ〜と思ってました.その時は能力たりな さすぎて無理だろう…というのと perl かぁ〜 という思いで応募すら出来ていま せんでした.

今年は言語が Scala (!)のコースができていたこともあったこと,一昨年よりはアルバイトでScala 書いたりとある程度経験値積んでいて,Vim でよければいくつかアピールできるようなものもあったので えいやっと応募しました.はてなインターンの選考では基本的にポートフォリオを提出するのみ だったのですが,ポートフォリオは8割 Vim でした.評価されてよかった…

ところで実際にインターンに参加してから思ったことは,もし仮に書く言語が perl だったとしても来たほうが良かったなということでした. もし来年度以降のインターン に応募しようと思っているけど perl がちょっとネック… くらいで参加を迷ってるな ら勢いで参加申し込んでもよいと思います.

結局僕は perl 1行も書きませんでしたが.Scala最高!!!(コンパイル爆速になればより…)

事前課題がScalaを基礎から勉強するのに最高

さて,晴れてはてなインターンに行けることになったらインターンまでの学習としてちょっとした事前課題が課されます.

この事前課題では perl か scala, それに JavaScript でいくつか課題が与えられ,問題を解いてテストを通していく形式でした. 事前課題は全体,課題ごとに課題のねらいが書いてあり,言語の基本を学ぶのに最高だと思いました.

Scala の課 題 は 与えられたログ用に Labeled Tab-separated Values (LTSV) パーサを書くという課題だったのですが,言語の基本やテストの仕方,テストの追加の 仕方はもちろんのこと,問題の性質上 エラーハンドリングをどうするか,Option型を 使うか,Either型を使うか,パース失敗時に エラーの行を収集するために scalaz でいう Validation 型を使えばベンリ なんじゃないか…!といろいろやりがいがありました. もっと言うと指定されたログの モデル以外にも対応できるような汎用的なLTSVパーサにしたら便利そうと思ったんですが そこまでは時間と実力が足りなくてできませんでした.残念.

LTSV パーサ,Scalaの課題としてよかったなぁと思います.

またこの事前課題は単にテストを通して提出すると終了…というわけではなくインターンの初日あたりに 講評が行われるのが最高でした.自分のコードはどう書けばよりよかったのか,他のインターン生は どう書いていてどこがよかったのかといったことも知れて便利でした.この講評はインターンの前半課題 でも行われました.

前半の講義がウェブ開発を基礎から勉強するのに最高

スケジュール

  • 1日目 Perl/Scalaによるプログラミングの基礎
  • 2日目 Perl/Scalaによるデータベースプログラミング
  • 3日目 Perl/ScalaによるWebアプリケーション開発
  • 4日目 JavaScriptによるイベント・ドリブンプログラミング
  • 5日目 自由課題
  • 6日目 インフラ
  • 7日目 SwiftでのiOSアプリ開発

前半の講義パートは言語の基礎からWebアプリケーション,インフラ,それにSwift コースや希望者はSwiftのiOSアプリ開発までを1週間で学べるようになっていました. それぞれのコースのインターン生ごとにメンターさんがついてくれます.僕の場合は id:sixeight さん でした.

毎日課題が課されてそれをメンターさんに質問したり,レビューを受けたり,講評をも らったりとヒイヒイこなして行くことで後半に向けて基礎力を向上できる仕組みになってい ました.大変でしたが楽しかった…!

課題としては自由課題が最後で,その内容はそれまでに学んできた技術と課題で作って きたブログシステムを活かして好きなWeb アプリケーションを作るというものでした.

ここで作ったサービスは社内で投票で順位もつく前半の集大成という課題で厳しくも楽 しい,燃える課題となっていました.僕はあんまり独創的なアイデアのなくこれがあれ ばベンリやろ〜というノリでちょっとしたものしか作れなかったのですが,他のイン ターン生のアプリケーションのクオリティが高くて刺激になりました.

完全に言い訳になるのですが僕は自由課題の日の前の土日で開催されたオープンイン ターネッツに公開されてない,はてなで行われたもくもく回ハッカソンで途中まで 作ってた Vim script版 power-assert に夢中になってました. 他のインターン生のつくったサービスをみてもっと自由課題に力入れればよかった…と 思ったので来年度以降はてなインターンへの参加を考えている各位は前半最後の自由 課題はやりがいあってよいよ!と言っておきます.

後半の実践パートでサービスにコミットしていく実践経験が得られて最高

実践パート - はてなサマーインターン2015 レポートサイト

今年から前半/後半の比率が代わり前半が少し短く,その分後半の実践パートが長く なったようです.開発に時間がとれてベンリ.

後半は僕は id:tyage くんさんと一緒にMackerelコースに配属され, ちょっとしたバグ修正によるインターン生最速リリース(ちょっとズルイ)から始まり4つほ ど多方面からMackerelの機能改善や新機能のリリースを行い,最終成果発表で1位を獲得できました!

だいたい id:tyage くんやメンターの id:sixeightさんをはじめとするMackerelチーム の皆さんのおかげでした.

id:tyage くんさんはインターンまでScalaほとんど書いてなかったらしいのに, 後半過程では1年くらいScala経験あった僕と同じかそれ以上のレベルでScalaかけちゃうし, JavaScriptまわりでペアプロして相談しても的確に正しい方向に導いていってくれるし最強かよ〜という感じでした. id:tyage くんさんとのペアプロ,最高に便利体験でした.

id:sixeightさんやMackerelチームの方には 方針を一緒に考えてもらったり,ダメなところをダメと指摘してもらったり,実装・仕様の相談をさせてもらったりと, 最高の体験でした.

id:tyageくんや優秀なMackerelチームのメンバーと 少しの間とは言えチームとして働く経験ができて,しかも最後には優勝というおまけまでついてきて 最高の夏を過ごせました.ありがとうございました!

はてなインターン最高でした

上述したカリキュラム上の話だけじゃなく毎日おいしいはてなのまかないをはてなの社員さんと お話しながら食べたり,他の優秀なインターン生の話を聞いたり,実力を垣間見たり, インターン途中に参加したYAPCや社内TGIF,ごはん連れてってもらったりしたときにはてなの社員さんの 話を聞いたりなどなど,最高の夏を過ごせました.

逆に慣れなかったことといえばはてなの 「シュッと」 っという言葉だけは いやいや「サッと」とかのほうが馴染むじゃん…?とあんまり慣れな かったのですが, インターン終わってから「シュッと」,いいじゃん使いやすいじゃん…? となぜかインターン終わってから馴染むようになってしまいました.不思議だ…

他のインターン生の紹介

イカしたやつらを紹介するぜ! ってやつ.終始凄い人多すぎてびびってました… 僕も頑張りたい.

最高の夏〜

はてな,Googleインターン行ってイカやりすぎたイカVimmerの2015年の振り返り

今年は4月から大きく環境が変わったり,インターンに行ったりちょくちょくVim活したりイカ(Splatoon)したりと振り返ってみる と色んな事がありました.

最初にネタバレをすると最も進捗があったのは Splatoon で最高ウデマエS+90まで行ったことでした.

マンメンミ!

去年や一昨年の

今年はプログラミング初めてからだいたい3年目でした.もう初心者とか言ってられないようになって気がしますが,まだまだ勉強不足・力不足すぎるので精進したい.

はてなサマーインターン

長くなったので記事分けた -> 2015年夏,はてなインターンでMackerelをとにかく便利にして優勝してきた - haya14busa

最高の夏〜

Google Japan Software Engineer インターン

はてなインターンが終わった後,3ヶ月ほどGoogle Japanのインターンに行っていました. Googleは内側ではオープンで全然違う国の違うチームの情報を見れたりするオープンさなのですが, 外側にはオープンではないので基本的にブログに書いたらだめっぽい,というか線引きがわ からないので参加した内容に関する感想は書けません…残念…

Googleの優秀なエンジニアさんたちとGoogleという会社で開発できたのは学びもやりが いもたくさんあって最高の体験でした.

インターン対策とか競技プログラミング

はてなとGoogle以外にもいくつか応募して受かったり落ちたりしたのですが, そのうち1回ホワイトボードコーディング面接があり,超基本的なことを聞かれているの にぜんぜん答えられない…という苦い経験がありました.

頭のどこかで僕は情報学部じゃなかったし,プログラミングも独学で好きなことやってる段階だし 基礎的も知らなくてもまだ仕方ない…と思ってた節があったりしました. しかしこれは完全に言い訳です. 基礎は土台.最低限理解して説明できる程度にはなってないと面接とか関係なく マズいな…と思いデータ構造,アルゴリズムなど勉強しなおしました.

その一環として前から興味はあったんだけどなかなか手がでなかった競技プログラミングにも今年はちょくちょく手をだしはじめました. 最近ちょっとイカしすぎておろそかになってますがやっていきたいです.

面接対策でつかった本とか

世界で闘うプログラミング力を鍛える150問

The Joel on Software 採用面接ゲリラガイド

採用面接ゲリラガイド(version 3.0) - The Joel on Software Translation Project)

Vim 活

incsearch.vim v2.0

incsearch.vimをカイゼンしてv2.0にしてました.もっと昔にやってた気がするけど今年 の7月でした.リファクタリングしてコンポーザブルにしたりと拡張性をましてincsearch.vimをより便利にできました.

vital-power-assert と VimConf | Vim script 版 powerassert!

はてなインターン中に作ってその後もちょくちょくと触ってました.またVimConfで発表したりもしました.

去年も大概だったのですが今年は個人的にVimConfに向けての準備がゼンゼン足りてなくて来年こそはちゃんとするゾ!!という気持ちです.

underscore.vim

underscore.jsのVim scriptバージョンを作ってました.実装は去年からなんだかんだやっていましたがエイプリルフールにリリースしました. 実用性がないわけではないけど,ラムダが無いとかスコープの関係上凝ったことしようとすると微妙に使いづらいのが残念ですが開発してて面白かったです.

勢い Vim プラグイン系

niconicomment.vim

niconicomment2.gif (1366×747)

思い出したように実行すると面白い.

vim-undoreplay

undoreplay_fizzbuzz2.gif (1366×747)

思い出したように実行すると面白い2.

vital.vim にPullRequest

vim-jp/vital.vim というVim scriptのライブラリにいくつか欲しいモジュールをPRで送ったりした. Vim.ScriptLocal は Vim scriptのスクリプトローカル変数を外からハックするモジュールでVim scriptのテストフレームワークである thinca/vim-themis で使ってもらったりした. 他にはPythonあたりにある便利なデータ構造をVim scriptにポートする業などしていました.

Vim Advent Calendar

前から自分が欲しかった,まとめたかった記事を書きました.今までで最高ブクマ数を頂いてありがたい.

vim-operator-flashy

年末駆け込みプラグイン.VimConfでt9mdさんが開発してる t9md/atom-vim-mode-plus でヤンク対象を フラッシュしていてわかりやすいというのを見せて頂いたのがきっかけになってます. 地味にUX向上してよい.

参加・発表したミートアップ・勉強会系

YAPC

YAPCに初めて参加しました.学生無料便利すぎました.LT発表は応募したのですが残念ながら落ちて残念.

Yokohama.vim

Yokohama.vimではなぜか基調講演という名の戦犯をしてきました. 内容はYAPCでしようとしていたVim駆動学習の話の微調整という感じでした. ちゃんと基調講演と言えるような発表をできるようになってまたYokohama.vim参加したい.

VimConf 2015

上述した.

fpinscala読書会完走

大阪で定期的に開催されていたfpinscala読書会でFunctional Programming in Scalaを(一応)読了しました. が,まだまだ理解しきれてないところ,飛ばしたところなどたくさんあるので2週目に参加してしっかり 関数型プログラミング身につけたいなと思います.

GitHub 記録

あんまり大したことできてなかった

Splatoon

Splatoon S+ 90

インターン中に買ってインターン終了までにS+になるという目標は達成したのですが, 年内にカンストするという目標は残念ながらできませんでした. しかし,今年の後半は本当にイカしかやってないというベルでやっていてイカ進捗が一番でてました. イカちゃん楽しすぎる…

よかったらみなさん一緒にイカしましょう!

その他

ちょくちょくReact触ったり, 引き続きScala書いたり, golang はじめたりしましたが, OSSっぽいこと,ここに書くようなことはほとんどできませんでした.

最後に

今年は環境が変わっただとか,インターン長期間行ってたとか,Splatoonやってたとか で特に今年後半はあんまり見える活動できてなかったです.もっと頑張りたい.

去年も似たようなこと言ってたような気がしますが来年はVimはもちろんのことVim以外のこともやっていきたいなぁと思います. あともう少し大きいレベルで目標を定めてそれに向かってやれるとよさそう(まだふわふわだけど真剣に考えなきゃ…).

それと今年最も苦労して迷惑かけたのは英語ではないかという説があるので, 来年は英語でコミュニケーションとれるように頑張って勉強していきたいですね.

以上, @haya14busa の 2015年の振り返り記録でした.

来年もイカよろしく〜

Vim Mnemonic | Vim のコマンドの覚え方大全

この記事は Vim Advent Calendar 2015 の21日目の記事です.

もくてき

本記事では Vim のコマンドの”覚え方”を紹介します. 基本的にはトリッキーな”覚え方”ではなく由来の紹介となります. 例えば J で行連結は Join が元だとか, gfが”goto file”の略だといったことを 知っておくとなにかと憶えやすいと思います.

対象読者

主にこれから Vim を使ってみよう! でもなかなかコマンドを覚えられないっ! という Vim 初心者の方に由来を知ることで少しでも コマンドを憶えやすいようにすることが目的です. 初心者を想定しているのでコマンドの動作などもなるべく紹介していきます.

中・上級者の方には普段何気なく使ってたあのコマンドの由来を知って「フハハハハ」と ほくそ笑んでもらえるような記事になれば嬉しいです.

注意

注意点として公式のものから公式っぽいもの,独自の調査結果によるものなど信憑性はまちまちです. そしてVimのコマンドは無数にあるので覚え方大全と言っておきながらすべてを網羅できているわけではなくかなり偏っています. 抜けてるものとか間違ってるものとか俺はこう覚えてるぜ!というものがあったら教えてください!

出典は

  • ヘルプファイル
  • ソースコード
  • 出典不明だけどどこかで見聞きした話

などです.基本英語に直して理解する方針のものが多いです.

またこれからたくさんのコマンドを羅列していきますがすべてを覚える必要は一切ないこと, そして逆にここに載ってない便利な覚えるべきVimコマンドはきっとたくさんあるので覚えようと気負ったり, だいたいわかるからokと思ったりしないようにおねがいします.

そして何よりの注意点としては結局覚え方よりも実際にやってみることが大事だということです!!!

ただ単にやってみるだけでなく由来や覚え方も知ることでより憶えやすくなったらよいなというのが本記事の趣旨なので, 深く考えすぎずにそうなんだ〜へぇ〜と思いながら読むとよいと思います.

ではスタートっ

基本のカーソル移動 hjkl

vimtutor Lesson1

        ^
        k              Hint:  The h key is at the left and moves left.
  < h       l >               The l key is at the right and moves right.
        j                     The j key looks like a down arrow.
        v

出典: vimtutor

右手のホームポジションから1つ左にあるのでhは左方向に移動し, 右にあるlが右方向への移動です. jはどことなく(下矢印)に似ているので下方向に移動すると憶えましょう. kに関してはどことなく上にとんがってるので上方向に移動すると考えてもいいかも知れません.

もともとのhjklの由来

viの開発者であるビル・ジョイさんが 当時使っていたPCがADM-3A - Wikipedia, the free encyclopediaであり, そのキーボードには矢印キーはなくHJKLを使ってカーソルを移動していたのが由来とのこと.

931px-KB_Terminal_ADM3A.svg.png (931×301)

この由来は知っても憶えやすくならない単なる豆知識でした.

VIM の保存,終了と! (<bang>)

コマンド 説明と由来 help
:q :q[uit] カレントウィンドウを閉じる.quit から :h :q
:qa :qa[ll] quit all から. :h :qa
:q!, :qa! バッファに変更点があっても閉じる. quit + !
:w :w[rite] バッファ全体をカレントファイルに書き込む.writeから :h :w
:wq :wqall :w:qの組み合わせ :h :wq

コマンド末尾の!

:h :command-bang

Vim のコマンドは!修飾子を取ることができ,!の有無によって動作が変わる場合があります. 基本的には強制的に実行するという意味合いが多いので憶えておくと未知のコマンド + !に出会った時に びっくりしないですみますね.

挿入コマンド

コマンド 説明と由来 help
i カーソルの前にテキストを[count]回挿入する.insertから :h i
I 行の先頭の非空白文字の前にテキストを[count]回挿入する.insertの大文字バージョン.大文字は行指向になるパターンが多い印象 :h I
a カーソルの後ろにテキストを[count]回追加する.appendから :h a
A 行末にテキストを[count]回追加する. appendの大文字バージョン :h A
o カーソルのある行の下に新しい行を作り、そこにテキストを[count]回繰り返し挿入する.open line から. :h o
O カーソルのある行の上に新しい行を作り、そこにテキストを[count]回繰り返し挿入する.open line の大文字バージョン. :h O
gi 最後に入力がされた場所にテキストを入力. goto last insert position and start insert と思ってたがgは単なるprefixかも.後述するgvgiのヴィジュアル版っぽい :h gi

モーション,オペレータ, テキストオブジェクト, ヴィジュアルモードについて

個々のモーション(hjlk, w, etc…)やオペレータ(d,c, y…)について それぞれ説明する前に全体的な動作について理解しておくと覚えることが減って, しかもとても便利なのでぜひ理解しましょう.

モーション {motion}

  [count] {motion}

:h motion.txt

モーションとはカーソル移動コマンドです.[count]を前置すると[count] x {motion}分だけ移動します. すでに見たhjklももちろんモーションなので4hなどすると左に4文字移動するという意味になります.

オペレータ {operator} とモーション {motion}

:h operator

d2w.gif (661×157)

  {operator} {motion}

厳密にはカウントを{operator},{motion}のそれぞれに前置することができるので以下のようになります. ([count]を両者に前置させると掛け算になります. 2d3w -> 6つの単語を削除. 普通に6dwd6wとしたほうが基本的にわかりやすそうですね)

  [count] {operator} [count] {motion}

またオペレータによってはレジスタを前置できます.:h registers

  ["x] [count] {operator} [count] {motion}

Vimは変更する,削除するといった操作を表すオペレータ{operator}と, その操作の適用範囲であるモーション{motion}を組み合わせることでテキストを編集できます. 先ほどみた{motion}に操作を加えている形になっています.

オペレータ {operator} とテキストオブジェクト {text-objects}

:h text-objects

di'.gif (657×128)

  {operator} {text-objects}

また,移動コマンドとしては使えないけれど{operator}と組み合わせた時の操作範囲 となるテキストオブジェクトを先ほどの{motion}の代わりに使うことができます. 例えば文字列の中身を削除(オペレータの1つ)したい場合の”文字列の中身”は移動するような概念 ではないですが,オペレータの操作対象として妥当です.

ヴィジュアルモード とモーション,テキストオブジェクト

そして厳密にはオペレータではないですがヴィジュアルモードでもモーションやテキストオブジェクトと 組み合わせることができ,対象の範囲を選択できます.

vi'.gif (657×177)

  {visual-operation} {motion|text-objects}

ヴィジュアルモードを”選択する”という”操作”とみれば自然に理解できるかと思います.

オペレータの対象範囲としてのヴィジュアル選択範囲 {Visual}

そしてヴィジュアルモードで選択した範囲{Visual}{motion}{text-objects} と同様にオペレータの対象範囲として使えます.

  {Visual} {operator}

{operator}{operator} は行指向オペレーション!

gqq.gif (1131×312)

  [count] {operator} {operator}

そして上記の組み合わせの特殊なケースとしてオペレータ (2コマンド以上のオペレータの場合は最後の文字のみでも可), を繰り返して入力すると操作範囲が行指向になります.

例えばddyy といったオペレータを繰り返すと行を削除したりヤンクできるといった具合です.

僕が観測している範囲ではこの挙動はddyyといった基本的な編集オペレータだけでなく, 全てのオペレータに当てはまっているので憶えておくと便利です.(ソースコードは読んでないので確証がない.)

例えば2文字のオペレータであるgq(:h gq)は gqqgqgqと打つことでカーソル下の行を整形できたりします.

1つの変更単位としての {operator} {motion|text-objects}

Vim のおすすめコマンド10選!!! として “diw でカーソル下の単語を消す” といったここで述べた オペレータとテキストオブジェクトをいっしょにまとめたものを1つのコマンドとして 紹介するような記事がたくさんあったりしますが,これらは1つのコマンドでもなんでもないです. オペレータやモーション,テキストオブジェクトの概念を理解すれば無限大の組み合わせをそれぞれ 覚える必要はなく,便利なオペレータとモーションを別々に覚えてそれらを組み合わせればよいです.

これは覚え方とはまた別ですが上述したオペレータとモーション,テキストオブジェクトの組み合わせは 1つの”変更単位”となっておりドット.コマンドで同じ操作を繰り返すことも可能です (:h .).

説明が長くなりましたが,ここからそれぞれのオペレータやモーションの覚え方について見ていきましょう.

オペレータ {operator}

コマンド 説明と由来 help
c 変更する.changeから. :h c
d 削除する.deleteから. :h d
y コピーする.yankから. :h y
gU 大文字にする.おそらくprefixとしてg + Uppercaseから. 大文字にマッチする正規表現の \U :h gU
gu 小文字にする.おそらくgUの逆で小文字にするから.小文字にマッチする正規表現の \u :h gu
> 右にインデントをシフトする.見た目から?. :h <
< 左にインデントをシフトする.見た目から?. :h >
zf 折畳を作成する.zは後述するが”z” は紙片を折った様子を横からみた姿に見えるから.fは折りたたみを作成するのが一番基本コマンドと考えてfoldから? :h zf

他にも由来わからないけど便利なオペレータはあるので使って憶えましょう.個人的に憶えておくと便利そうなものをリストアップ.

コマンド 説明と由来 help
= フィルタ処理. インデント整形 :h =
gq 整形する.80文字で折り返すよう整形とかできる :h gq

先ほどオペレータを連続させると対象が行指向になると説明したように, ccなら行を変更,==gqqで行を整形できます.個別に覚える必要はないですね.

また ヴィジュアルモードでの<>を連続で操作するために下記のようなマッピング をしている人もいますが,他の選択範囲に対するオペレータによる操作となんら変わらないので 代わりにドットリピート.を使って繰り返すことができます.

1
2
vnoremap > >gv
vnoremap < <gv

ちょっと脱線してその他の変更コマンド系

c, d, y, gU…の他にもオペレータではない変更系コマンドがたくさんあります.:h change

コマンド 説明と由来 help
C 行末まで変更する.changeの大文字バージョン. :h C
D 行末まで削除する.deleteの大文字バージョン. :h D
Y 行をコピーする.yankの大文字バージョン.viの互換性から行末までではなく行. :h Y
p テキストをレジスタから貼付ける.put から.paste と憶えてもよさそう :h p
P カーソルの前にテキストを貼り付ける. pの逆 :h P
x カーソル下の文字を削除. バツマークに似てるから? :h x
X カーソルの前の文字を削除. xの逆 :h x
s カーソル下の文字を削除して挿入を始める. substituteから. :h s
S 行を削除して挿入を始める. sの大文字バージョン. :h S
r カーソル下の文字を置き換える. replaceから. :h r
R 置換モードに入る. replaceから. :h R
gr gR r, Rの仮想文字バージョン. g prefix :h gr :h gR
J, gJ 行を連結する. Join から :h J
:s/// 置換コマンド. 省略しないとsubstitute :h :substitute

由来ナゾ変更コマンド

コマンド 説明と由来 help
<C-a> カーソルの下または後の数またはアルファベットに [count] を加える. addから? :h CTRL-A
<C-x> カーソルの下または後の数またはアルファベットに [count] を減じる. 英語ではsubtractなので何故xかは不明.CTRL-Sが端末によっては使えない.XAに近いから? :h CTRL-A

モーション {motion}

:h motion.txt

左右の移動

コマンド 説明と由来 help
0 その行の最初の文字に移動. 0文字目??? :h 0
^ その行の最初の文字に移動. 正規表現の^ :h ^
$ その行の最後の文字に移動. 正規表現の$ :h $
g0 g^ g$ それぞれのスクリーン行バージョン(折り返し考慮)
gm スクリーンの幅の真ん中に移動. midleから.出典: ソースコード. middle of “g0” and “g$”. :h gm
f{char} 右に向かって [count] 番目に現れる {char} に移動.findから…と思いきやヘルプ/ソースコード的にはfindとは一切書いてない.確かにfindに移動するニュアンスはないか…? :h f
F{char} fの左に向かうバージョン. :h F
t{char} 右に向かって [count] 番目に現れる {char} まで移動.till(〜まで) から :h f
T{char} tの左バージョン :h f

由来ナゾ

コマンド 説明と由来 help
; [count] 回最後の f, t, F, T を繰り返す. 余った記号で;を順方向,,を逆方向にした? :h ;
, [count] 回最後の f, t, F, T を反対方向に繰り返す. :h ,

上下の移動

コマンド 説明と由来 help
G [count] 行目の最初の非空白文字に移動.カウントがなければ最後の行. Goto から :h G
gg [count] 行目の最初の非空白文字に移動.カウントがなければ最初の行. goto から :h gg
{count}% ファイルの {count} パーセントの位置に移動.そのままパーセントで直感的! :h %

単語単位の移動

コマンド 説明と由来 help
w [count] words前方に移動. word から :h w :h word
W [count] WORDS(非空白文字の連続)前方に移動. word から :h G :h WORD
e [count] word 前方の単語の終わりに移動. end of word から :h e
E [count] WORD 前方の単語の終わりに移動. End of WORD から :h E
b [count] words後方に移動. backward から :h b
B [count] WORDS後方に移動. backward から :h B
ge [count] word 後方の単語の終わりに移動. g prefix + end of word から :h ge
gE [count] WORD 後方の単語の終わりに移動. g prefix + End of WORD から :h gE

オブジェクト単位で移動

3つのオブジェクト, sentence(文), paragraph(段落), section(セクション) が存在し,それぞれ(), {}, []が対応する. セクションのみ少し例外で1桁目の’{‘ か ’}‘への移動を2コマンド目で表現する.

他に特に覚え方はわからないので表は省略.

:h object-motions

ジャンプ

コマンド 説明と由来 help
CTRL-O ジャンプリストの中の [count] だけ古いカーソル位置に移動({motion}ではない). Older cursor position から :h CTRL-O
CTRL-I ジャンプリストの中の [count] だけ新しいカーソル位置に移動({motion}ではない). キーボードでOの左にIがある :h CTRL-I
g; 変更リスト中の [count] 個前の位置に移動. ;が順方向への移動っぽい :h g;
g, 変更リスト中の [count] 個後の位置に移動. ,が逆方向への移動っぽい :h g,

様々な移動

コマンド 説明と由来 help
% 対応するアイテム([{}])にジャンプ. percent と parentheses(丸括弧) をかけている? %の文字が/を挟んで対応したがあると憶えてもよいかも :h %
H スクリーンの最上行から [count] 行目(デフォルト: スクリーンの最上行)に移動, Home(top) of window とhelpに書いてあるがhomeってそんなニュアンスあるんだろうか… High と覚えてもよいかもしれない. :h H
M スクリーンの中央に移動.Middle line of windowから :h M
L スクリーンの最下行から [count] 行目(デフォルト: スクリーンの最下行)に移動.Last line on the windowから.HHighと覚えた場合はLLowと覚えてもよいかも :h L

角括弧コマンド: [ + “?”, ] + “?” 系

:h [

ブロックやメソッド,コメントといった何かしら決められたものの始まり,終わりに移動する. “?”には({mM#*/などが入る.

コマンド 説明と由来
[{, [(, ]} or ]) マッチしない ‘{’, ‘(’, ‘}’ ‘)’ に移動
[#, ]# マッチしない #if..#endif の最初か最後に移動.
[/, [*, ]/, ]* Cスタイルコメントの最初か最後に移動.
[m or ]m Javaスタイルメソッドの最初に移動.
[M or ]M Javaスタイルメソッドの最後に移動.

テキストオブジェクト {text-objects}

基本的なテキストオブジェクトはi, aの2種類がそれぞれprefixとしてつくものが多い. iinner(内部)を表し,aa(1つの)まとまり(“a”n object)を表している. iinside, aのをオブジェクトのaround(まわり)まで含むと覚えてたりしてもよいと思いますが公式は”inner”と”a”です.

コマンド 説明と由来 help
aw, iw wordを選択. “a word”, “inner word”. aは周りのホワイトスペースを含む :h aw :h iw
aW, iW WORDを選択. “a WORD”, “inner WORD” :h aW :h iW
as, is “sentence”(文)を選択 :h as :h is
ap, ip “paragraph”(段落)を選択 :h ap :h ip
ab, a(, a), ib i(, i) (,)ブロック,またはその内部を選択. braces block から :h ab
aB, a{, a}, iB i{, i} {,}ブロック,またはその内部を選択. Brackets block から :h aB
a[, a], i[, i] [,]ブロック,またはその内部を選択 :h a[
a<, a>, i<, i> <,>ブロック,またはその内部を選択 :h at :h it
a", a', a`, i", i', i` 前の引用符から次の引用符まで, またはその内部を選択 :h aquote
gn 最後に使われた検索パターンを前方/後方検索してマッチを選択. g prefix + n, Nから :h gn :h gN

テキストオブジェクトの部分をハイライトした例 textobjects-example.gif (1366×721)

削除オペレータとの組み合わせ例

コマンド 動作
“dl” 1文字削除 (“x” と同じです)
“diw” inner word を削除
“daw” a word を削除
“diW” inner WORD を削除 (参照: |WORD|)
“daW” a WORD を削除 (参照: |WORD|)
“dgn” 次に検索パターンにマッチするものを削除
“dd” 1行削除
“dis” inner sentence を削除
“das” a sentence を削除
“dib” inner ‘(’ ‘)’ block を削除
“dab” a ‘(’ ‘)’ block を削除
“dip” inner paragraph を削除
“dap” a paragraph を削除
“diB” inner ‘{’ ‘}’ Block を削除
“daB” a ‘{’ ‘}’ Block を削除

検索コマンド

コマンド 説明と由来 help
/ 前方検索.由来はナゾ :h /
? 後方検索.SHIFT + //の逆から :h ?
n 最後の “/” か “?” を [count] 回繰り返す.next から :h n
N 最後の “/” か “?” を逆方向に [count] 回繰り返す.nの大文字でnの逆 :h N
* カーソルに最も近い単語で前方検索.USキーボードで4段目右手の中指 :h *
# カーソルに最も近い単語で後方検索.USキーボードで4段目左手の中指 :h #
g* g# *, # の”\<“ と ”>“(単語区切り)を加えないバージョン :h g*
gd カーソルからローカル宣言を検索.goto + declaration から. :h gd
gD カーソルからグローバル宣言を検索.gdの大文字バージョン :h gD

スクロールコマンド

上/下方スクロール

                                 +----------------+
                                 | some text      |
                                 | some text      |
                                 | some text      |
  +---------------+              | some text      |
  | some text     |  CTRL-U  --> |                |
  |               |              | 123456         |
  | 123456        |              +----------------+
  | 7890          |
  |               |              +----------------+
  | example       |  CTRL-D -->  | 7890           |
  +---------------+              |                |
                                 | example        |
                                 | example        |
                                 | example        |
                                 | example        |
                                 +----------------+
コマンド 説明と由来 help
CTRL-E 下へ[count]行ウィンドウをスクロール.Extra lines から(vimdocでは割増との訳注あり. 追加の行?) :h CTRL-E
CTRL-Y 上へ[count]行ウィンドウをスクロール.由来ナゾ… :h CTRL-Y
CTRL-D ウィンドウをバッファ内で下にスクリーンの半分スクロールする.Scroll Downwards から :h CTRL-D
CTRL-U ウィンドウをバッファ内で上にスクリーンの半分スクロールする.Scroll Upwards から :h CTRL-U
CTRL-F ページ前方(下方)にスクロール.Scroll Forwards から :h CTRL-F
CTRL-B ページ後方(上方)にスクロール.Scroll Backwards から :h CTRL-B

カーソル相関スクロール

  +------------------+            +------------------+
  | some text        |            | some text        |
  | some text        |            | some text        |
  | some text        |            | some text        |
  | some text        |  zz  -->   | line with cursor |
  | some text        |            | some text        |
  | some text        |            | some text        |
  | line with cursor |            | some text        |
  +------------------+            +------------------+
コマンド 説明と由来 help
zt [count]行(省略時はカーソルのある行)をウィンドウの最上行にして再描画. z prefix + top of window から :h zt
zz [count]行(省略時はカーソルのある行)をウィンドウの中央にして再描画. 由来はナゾ… :h zz
zb [count]行(省略時はカーソルのある行)をウィンドウの最下行にして再描画. z prefix + bottom of window から :h zz

折畳コマンド

全ての折畳コマンドは z で始まっている.z は紙片を折った様子を横からみた姿に見える.

コマンド 説明と由来 help
zf 折畳を作成する.(再掲) fは折りたたみを作成するのが一番基本コマンドと考えてfoldから? :h zf
zd 折畳を1つ削除する. delete から :h zd
zD 折畳を再帰的に削除する. 折りたたみコマンドにおける大文字は”再帰的”, “すべて”といった意味合いのものが多い :h zD
zE 折畳をすべて削除する. Eliminate から :h zE
zo 折畳を1つ開く. open から :h zo
zO 折畳を再帰的に開く. zoの大文字版 :h zO
zc 折畳を1つ閉じる. close から :h zc
zC 折畳を再帰的に閉じる. zcの大文字版 :h zC
za 折畳をトグル(開いていたら閉じ,閉じていたら開く). 由来はナゾ… :h za
zA 折畳を再帰的にトグル. zaの大文字版 :h za
zv カーソルのある行がちょうど表示されるレベルまで折畳を開く. View cursor から :h zv
zx, zX 折畳を更新する. 由来はナゾ…というかそもそもhelp読んでも動作がいまいちわからない… :h zx
zm 折畳をより閉じる(‘foldlevel’ を1減少させる) Fold More から :h zm
zM 全ての折畳を閉じる(‘foldlevel’ に0を設定する) zm の大文字版 :h zM
zr 折畳をより開く(‘foldlevel’ を1増加させる) Reduce folding から :h zr
zR 全ての折畳を開く(‘foldlevel’ に最大の折畳レベルを設定する) zr の大文字版 :h zR
zn 折畳しない(‘foldenable’ をリセットする。全ての折畳が開かれる) Fold none から :h zn
zN 折畳する(‘foldenable’ をセットする。全ての折畳が ‘foldenable’がリセットされる以前と同様になる) Fold normalから.しかしnが2つあって正直意味ない… :h zN
zi ‘foldenable’ を反転する. Invert から :h zi
[z, ]z 現在の開いている折畳の先頭/末尾へ移動する.角括弧コマンド(:h [)は似た動作をする :h z[
zj カーソルより下方の折畳へ移動. 折りたたみにおけるhjklj移動 :h zj
zk カーソルより上方の折畳へ移動. 折りたたみにおけるhjklk移動 :h zk

(zxとかzn,zNなどは覚えなくてもたいていの動作に支障ないのではという気がする...)

undo と redo のコマンド

コマンド 説明と由来 help
u [count] 個の変更を元に戻す.undo から :h u
CTRL-R undo された変更を [count] 個やり直す.redo から :h CTRL-R

ビジュアルモード

コマンド 説明と由来 help
v 文字単位のビジュアルモードを開始する.visualから :h v
V 行単位のビジュアルモードを開始する.vの大文字版 :h V
CTRL-V 矩形ビジュアルモードを開始する.vのctrl版 :h CTRL-V
gv 最後に使用したのと同じ範囲のビジュアルモードを開始する. gotoか単なるprefix. 最後に入力がされた場所にテキストを入力するgiのヴィジュアル版と言える :h gv
v_o 選択されたテキストのもう一方の端へ移動する.Go to other end of highlighted text から :h v_o
v_O 選択されたテキストのもう一方の端へ移動する.矩形選択では行内のもう一方のコーナーに移動する.Go to other end of highlighted text から :h v_O

その他

すべてのコマンドを体型的に網羅するとを諦めてその他で残りの言及すべきっぽいコマンドをいっしょくたにまとめる男の姿がそこにはあった…

コマンド 説明と由来 help
CTRL-W + “?” ウィンドウコマンド. Window commandsから. Windowの操作や”?“の結果を新規ウィンドウで開いたりする :h CTRL-W
i_CTRL-R c_CTRL-R レジスタの内容を挿入する. Registerから :h i_CTRL-R
gf カーソルの下か後ろの名前のファイルを編集する. goto file から :h gf
K カーソル位置のキーワードを調べるためのプログラムを実行.Keyword から :h K
q タイプした文字をレジスタ{0-9a-zA-Z”}にレコーディングする.特に覚え方は見つからなかったが,macro -> maqro みたいな覚え方もあり…? :h q

おわりに,そして覚えるのもよいけれど…

以上で本記事のコマンドの覚え方大全は終了です. ここまで読んだ方お疲れ様です.そして「アレ…?まだまだあるはずじゃない?」と思ったそこのあなた,正解です. 挿入モード,コマンドモードのコマンドはほとんどかけてないですし,単純に抜けてるものもあるかと思います. チカラ付きました… ただこう理解するとわかりやすいよ〜というコマンドはなるべく網羅したような気がします. もっとこれ追加しろとかあったらコメントかtwitterか何かで言っていただけると嬉しいです. そしてVimを始めたころの初々しい気持ちを忘れていて,いやもっとここ丁寧に書かなきゃわからんぜ!ってとこも遠慮無くおねがいします.

そして覚えるのも大事ですが,それと同じくらいわからないことをドキュメントから調べる力を つけるのも重要かなぁと思います.最初は覚えられなくても調べることができればかなり便利です. たとえば :helpだけでなく:helpgrepを使いこなしたり, :h help-context を読んで引きたい項目の指定ができるようになるとはかどります. (他にも(を末尾につけることで関数のヘルプを引くといった書いてないプチハックとかもあります)

種類 修飾子
ノーマルモードコマンド (無し) :help x
ビジュアルモードコマンド v_ :help v_u
挿入モードコマンド i_ :help i_<Esc>
コマンドラインコマンド : :help :quit
コマンドライン編集 c_ :help c_<Del>
Vim の起動引数 - :help -r
オプション ' :help 'textwidth'
正規表現 / :help /[

僕が思うhelp周辺の便利ツールとかは Vimのhelpを快適に引こう - haya14busa にまとめているのでよかった読んでみてください.

おわり.

Vim のコマンドを覚えて思考のスピードで編集しましょう!!!

ブログを書くまでが #yapcasia なのでブログでLT発表して感想かく ― Vim駆動学習

YAPC::Asia 2015 に1日目・2日目と参加してきました.

ブログを書くまでがYAPCで,LTしてみたかったならやぷしー終了するまでにブログで発表すればいいじゃない

YAPC 2015 初めての参加でしたが一言で言うと最高でした!!! 刺激になるトーク多すぎました.

ただひとつ悔やまれるのは1日目の前日くらいに勢いでLT応募したけど,そのまま勢いで落ちたのでチョット発表してみたかった…倍率高すぎる〜

(本当に悔やまれるのはトラック被って見れなかった裏トラックを見れてないということで,資料とかまとめとかYouTube見ていくゾ!!!)

…ところで,YAPCはブログを書くまで終わらないんだからブログでLTしたかった内容発表すれば, それはもうYAPCでLTしたことになるのでは…!?!?!?(混乱)

と考えたのでブログで発表したかった資料をあげる最高にカッコワルイことを今からします. その後参加記みたいな何かを書いています.

いろいろと,読む前でも読んだ上でも思うことはあると思いますが自分でも思うことはあるので 察してそっとしておいてください!! いろいろと反省はしている.

Vim 駆動学習

※ 1箇所gifが表現できないのでクリックして見てと言っているけどSpeaker Deckだとクリックできないのでスルーしてください(PDFをダウンロードすれば一応クリックできるけど)

LT説明や資料の反省とか.あと参考記事

エモイ話だ…

基本的にはこれまでにどこかでアウトプットした内容で,なるべくそうならないように意識はしてたのだけど, 説明文とか内容とか何か聴衆に有益情報話すというより,単なる自分語り感が強すぎるのがウーンっていう感じだと思っています.

まぁ技術的な説明とかは他の人のほうが断然できるはずだし, 僕ができるのは僕の経験を話すこと.それが一番僕にしかできない発表で, そこで何か聴衆に響かせることができたらいいなって考えたのでこういった内容になってます.

内容がだいたいどこかで以前アウトプットしたものになった原因は,これまで基本的には記事書くようにしていたからっていうことや, 聴衆がどうよりも経験としてYAPCみたいな舞台で発表したいというエゴによって自分のなかでGoサインが勢いで出てしまった感じになってます.

資料できてここまで書いて思ったけどたぶん落ちてよかったんじゃないかなぁみたいな思いもある. 普通に5minオーバーすると思うし.

これからまた頑張っていくゾイ!!!

参考記事

だいたい僕のブログ読んでたらLT資料読まなくてもだいたいわかる感じになっている. もし興味出たっていう優しいかたは気になった記事を読んでいただけると少し詳しく書かれています.

自分の LT のくだり終了.

YAPC::Asia 2015 Day1 感想

聴いたTalkと感想

1日目は朝5時半くらいから起きて東京に向かったのでなかなか大変でしたが,早起きチャレンジ成功してよかった.

1) メリークリスマス! - YAPC::Asia Tokyo 2015

perl を書いたことは無かったけど歌って踊るラリーウォールみれてよかった. perl6 面白そうなようなので(又聞き),クリスマス期待.

2) 世界展開する大規模ウェブサービスのデプロイを支える技術 - YAPC::Asia Tokyo 2015

Miiverse のデプロイを支える技術の話だった.海を超えたgit pullとかその不可を抑えるためのランダムスリープみたいな つらい話からはじまって,それを解決していった話が聞けました. 大規模ウェブサービスのデプロイ,やったこと一切なくてあまり個人の実感がわかないのでムズカシイけどこういう話も勉強していきたい.

3) TBD - YAPC::Asia Tokyo 2015

Rubyのパパ Matz が Rubyの話しを封印したと思ったら10分で封印を解いたり, Ruby のディスと見せかけて間接的にperlディスってたりしておもしろかった. 内容も面白くて,主流のアーキテクチャが変わると言語デザインも変わってきて,それに対応してデザインされているのが streem ならしい.

4) Perlの上にも三年 〜 ずっとイケてるサービスを作り続ける技術 〜 - YAPC::Asia Tokyo 2015

おもしろトークだった上にめっちゃ開発の参考になる話が多かった.紹介されていた本読みたい -> YAPCの発表で紹介した本 - hitode909の日記. DDDとかユビキタス言語の導入の話とかがとてもいい話で,僕もやっていきたい. 最近自分でもプログラムやドキュメントに書いてる単語がブレていたりするのを感じていて, ユビキタス言語.md (ファイル名違う気がする) とかをリポジトリに置いて管理するのとかもよさそうと思った.

事前条件/事後条件とかあってそこで 責任外のことをチェックせずお互いを信頼するとスッキリするという話もなんとなくスッキリして面白かった.

5) うっかりをなくす技術 - YAPC::Asia Tokyo 2015

うっかりすることよくあるので,うっかりをなくす技術を聞きに行った. assertion ライブラリ的なものを最近作っていたのでassertionの話とかもっと聞きたかった.契約プログラミングとか???(わかってない) defer/guard object とかスゴイよさそうだった.golang に defer とかあるようだし,goやっていきたい.

追記: あとせっかくうっかりをなくす技術聴いたのに2日目に会場に荷物忘れるうっかりをやらかした. そしてこの文をブログに書くのを忘れるといううっかりもして,うっかりしないようにするのはムズカシイ…

6) Lightning Talks Day 1 - YAPC::Asia Tokyo 2015

Slack + Hubot でお前の一番好きな二次元嫁キャラと一緒に仕事をする 話とかが思考がぶっ飛んでいて面白かった. PHPでregister_globalsの話をしてた方が最初にgongo/emacs-ikkuとか作っていて 「Vimでやらなきゃ…負けてられない…」とか考えていたけどまだできていない.

YAPC::Asia 2015 Day2 感想

聴いたTalkと感想

Mackerel開発におけるScalaとGo、そしてPerl - YAPC::Asia Tokyo 2015

  • 複数の言語,技術を用途によって適切に使い分けてるのがすごい.
  • Scalaのimplicit conversion の解決遅すぎ問題のつらさわかる〜みたいな気持ちになったりした.
  • ちょっと最初の10minくらい遅れていってしまってツライ…ちゃんと見直したい.

我々はどのように冗長化を失敗したのか - YAPC::Asia Tokyo 2015

  • 式年遷宮面白かった.
  • 発表前から資料がアップロードされていてよさ.
  • 冗長化ムズカシイ.

MySQLで2億件のシリアルデータと格闘したチューニングの話 - YAPC::Asia Tokyo 2015

  • 自分にとっては難しかったのとあまり集中して聞けてなかったのであまり記憶がない…(LT採択どうかな〜みたいな気持ちで気が気じゃなかったのもある)
  • あとから資料見てみたい.

Adventures in Refactoring - YAPC::Asia Tokyo 2015

  • GitHubの中の人のリファクタリングの話でめっちゃよかった!!! リファクタリングしたい気持ちが高まりまくった.
  • リファクタリングは挙動を変えては行けなくて,それはバグも同じで一緒に修正したら問題の切り分けができなくてダメだよという話は, わかるという思いと共に,そうは言ってもムズカシイので意識してデキルようにしていきたい.
  • リファクタリングをナゼするのかとか,成果を計測しなくてはならないというのは全然意識したことがなかった.資料とか見直しながらやっていきたい.
  • (変数・)メソッド名のアンダースコアはリファクタリングチャンス.なるほどという感じだった.
  • とにかくリファクタリングやっていくゾ!!!

Posture for Engineers - YAPC::Asia Tokyo 2015

  • 肩こりがひどいので姿勢の話を聞きに行った.
  • いくつかヨガのポーズみたいなものを教えてもらったので実践できればいいのだけどデキルだろうか…
  • バランスボールのって開発してたら逆に肩こりと首こりがヤバくなった経験があってすぐにやめちゃったのでいい座り方・使い方がしりたい.(質問しそこねた)

Run containerized workloads with Lattice - YAPC::Asia Tokyo 2015

  • 正直わからんかったマン(ムズカシイ…)

Profiling & Optimizing in Go - YAPC::Asia Tokyo 2015

  • とにかくライブコーディングがカッコヨサで Go の標準で提供されている tool すごい強いし,コンパイル速くて書きやすそうだし, まだ Go はかけてないけど,Go 書いていくゾ!という気持ちになった. Go 書き始めたらまた参照して学んで行きたい.

Lightning Talks Day 2 - YAPC::Asia Tokyo 2015

  • どのLT もこれぞLTってカンジで良かった…あんなLTできるようになりたい.
  • @orga_chem さんの Vim script 静的解析の闇がトリで Vim script の闇を暴露していていい話だった. Vim script はああいった感じでカワイイのでぜひ興味を持った皆さんには vint のチカラを借りながら Vim script を書いてみて欲しい. 基本静的解析のときツライという話で,v:count, 関数と変数のネームスペース, map() の引数とかが文字列って以外は普通に書いてるときの 闇としては避けられそう.(十分多い…???)

個人的な悔やまれることとか

  • 最近Vim版power-assert作って補足して頂いたりしたので @t_wada さんに会ってご挨拶くらいしておきたかった. Vim版 power-assert もっと便利にしておきたい.
  • 世界の @miyagawa さんを見かけて Rebuild.fm 大好きでめっちゃ聴いてますって言ってみたかったけど,誰かと話されていて, Rebuild.fm 聴いてますとか耳たこかもしれないし,その後何か話せるか考えたけど訳分からんくておそらく Rebuild.fm で Vim とかエディタの話をしてほしいとかは言わないまでも,Vimmerのゲスト増やしてくださいみたいな困らせるようなことを喋りそうで そうこう言ってるうちに機会が過ぎてしまった…フベン…
  • Twitter のタイムラインを見る限り,オープンインターネッツ上で見たことあるひとがたくさんいたけど,現実の顔と一致しなくて結局 会わずじまいな人が多かったのでまた何かの機会にお会いしたい.会えたひとも何人かいてそれはよかった.
  • 発表しようと思うならもっと早めに用意しないと,僕のレベルだと時間をいっぱいかけてやっと聴くに耐えるものになるかどうかギリギリみたいな 感じだと思うし,ちゃんと準備したい.

全体的に

YAPC::Asia 2015,YAPC初めての参加でしたが本当に最高でした!!! 同時通訳の方の同時通訳がすごくて圧巻されたり,会場のWifiはあの人数だったのに個人的にはほとんど繋がっていて CONBU さん凄かった. 無限に湧き出てくるコーヒーも美味しかったし,懇親会も豪華だしスポンサーの皆様ありがとうございました.

そして発表者の皆様,@lestrratさんをはじめとした運営の皆様,他の参加者の方々, (漏れていたとしたらその方々!), 最高のYAPC本当にありがとうございました.楽しかったです!!!

絶対来年も参加したい!!!!

Vim Script版 Power-assert! テスト書いてないとかお前それ Vim Script の前でも同じこと言えんの?

Vim script で最高の assertion 体験,vital-power-assert を作りました

Gyazo

haya14busa/vital-power-assert

テスト書いてないとかお前それ Vim script の前でも同じこと言えんの?

ということで Vim script 版 power-assert, vital-power-assert を作りました.

Vim script でも power-assert できてテストをバリバリ書けるんだから Vim で書いてる他の言語でテスト書いてないとか Vim が泣いちゃいますね…(煽り,そしてブーメラン)

使い方とか 力こそパワー!! 百聞よりパワー!!

使っている様子です

1
2
3
4
" in your vimrc
NeoBundle 'vim-jp/vital.vim'
NeoBundle 'haya14busa/vital-vimlcompiler'
NeoBundle 'haya14busa/vital-power-assert'
1
2
3
4
5
6
7
8
9
10
11
12
13
let s:V = vital#of('vital')
let s:PowerAssert = s:V.import('Vim.PowerAssert')
let s:assert = s:PowerAssert.assert
execute s:PowerAssert.define('PowerAssert')
function! s:power_assert() abort
  let x = { 'ary': [1, 2, 3], 'power': 'assert' }
  let l:zero = 0
  let s:two = 2
  PowerAssert index(x.ary, l:zero) is# s:two
  " or
  execute s:assert('index(x.ary, l:zero) is# s:two')
endfunction
call s:power_assert()

上記コードを実行するとこうなります.

1
2
3
4
5
6
7
8
9
vital: PowerAssert:
index(x.ary, l:zero) is# s:two
     |||     |       |   |
     |||     |       |   2
     |||     |       0
     |||     0
     ||[1, 2, 3]
     |{'ary': [1, 2, 3], 'power': 'assert'}
     -1

インストールや詳しい使い方は GitHub/help を参照してください.

-> haya14busa/vital-power-assert

基本的に関数とコマンドのassert方法を用意しているのですが,プラグインのコードに残しておいたりするものは 関数の .assert(), Vimのテスティングフレームワークで使う際などはコマンドでやることを推奨してます.

1
2
3
4
" 関数で assert. 引数は文字列として渡す必要がある
execute s:assert('index(x.ary, l:zero) is# s:two')
" コマンドで assert. 文字列で囲う必要がないのでシンタックスハイライトも効く
PowerAssert index(x.ary, l:zero) is# s:two

両者ともデバッグ用変数をONにしないとassertは実行されないので,プラグインに埋め込んでおいても プラグインのユーザが使ってる時は発動しないし,評価なにもされないのでコードに残しておいても 問題ないようになっています.(コマンドの方はユーザのVimにコマンドが新たに定義されてしまうので推奨しません)

power-assert 最高! 一番好きな assertion ライブラリです!

vital-power-assert はもちろん JavaScript の assertion ライブラリである https://github.com/power-assert-js/power-assert にインスパイアされて作っています.

何がベンリなのかとかは @t_wadaさんが本家のpower-assertの紹介とかで 各所で説明なされているので説明は不要だとおもいますが,

個人的にはやはり

  1. assert 失敗時の式がどうなってるか一目瞭然のグラフィカルな見た目
  2. たくさんの matcher を一つ一つ憶えたりドキュメントを見なくても assert 一つだけ知ってれば使える優しさ

あたりのよさが使ってみて,開発してみて本当によいなと思います.

マッチャーは自然言語的な書き方ができたり, テストのコード自体が間違えにくいみたいなところがよいとチラッと聞いたことがありますが 僕は断然power-assertのほうが好きという思いが強まりました (間違ってたり他にもある場合は教えてください)

Vim script 版 vital-power-assert のよさ

(このあたりは特に Vim script 書いてる人/興味あるひと向けです)

power-assert としてのよさはもちろんのところ, Vim script の assertion ライブラリとしての vital-power-assert のいいところがあります.

それはassertionを実行する際のスコープが assert する行と 同じなので, スクリプトローカル変数やローカル関数など何でもassert する 式の中で使えるということです!!! (わかりづらい)

1
2
3
4
5
6
7
8
9
:let s:x = 2
:PowerAssert s:x == 1
" or
:execute s:assert('s:x == 1')
" => ちゃんとs:xも使える
"   s:x == 1
"   |   |
"   |   0
"   2

例えば Vimのテスティングフレームワークの一つの thinca/vim-themis の assert コマンドではスクリプトローカル変数が使えなくて不便…ということがあったりするのですが vital-power-assert を使えばそのあたりを気にせず使うことができます.ベンリ.

どうやって実装しているか

Vim script のパース & コンパイル

power-assert のようにassert が失敗したときに式中のそれぞれの変数や関数, 演算子の評価結果を得るためにはまず与えられた式をパースする必要があります. そこでは Vim script で Vim script をパースできる ynkdir/vim-vimlparser を使用させていただいています. 使っていて改めて ynkdir さんすごすぎる…

vitalのライブラリとして使うためにhaya14busa/vital-vimlcompilerにバンドルしちゃっています.(ライセンス的に問題なさそうだったのでynkdirさんに相談するまえに衝動的にVim版power-assertを作ってしまいました…スイマセン)

とにかく,vimlparser のおかげでVim scriptをパースしてASTを得ることができたので, あとはASTをトラバースして評価したいノードを集めることができました.

そして再コンパイル

あとは集めたASTのノードの式中の位置を記録, そしてASTをVim scriptに戻してスコープに気を付けながら評価すれば必要なものが揃います.

vimlparser に付属している Compiler オブジェクトはS式的なものにコンパイルするものだったので, Vim scriptにコンパイルする haya14busa/vital-vimlcompiler というライブラリを作って使用しています.

注意点としてまだexprのコンパイルしか実装してないので関数とかはコンパイルできないです. ドキュメントもないし今のところ完全に vital-power-assert 用になっていますが,何かできたら面白そう.

Vim script スコープハック

Vim のコマンドの引数はStringとして渡されてその場で評価しているわけではないので 普通にやるとスクリプトローカル変数が無いと怒られます. もちろん文字列で受け取って eval() してもスコープは変わってるので対応できません.

これを完全に解消するためにはassertする行と同じ位置で評価する必要がありますが, そこで execute を使うことによって実現しています.

どういうことかというと,{rhs} である s:assert('...') が評価され返り値が帰ってくるのですが, その返り値に実行したいコマンドを文字列として返すと :executeによってそのコマンドが同じスコープで 実行できて… という感じで実装しております.

1
2
3
4
5
6
7
8
9
10
11
:execute s:assert('x == 1')
" ->
:execute 'execute' "s:assert2(x == 1, 'x == 1')"
" -> {expr} と 文字列の '{expr}' を別の関数に渡し直す
:execute s:assert2(x == 1, 'x == 1')
" -> 評価したいノードリストを引数にとる関数を返す
:execute 'execute' "s:assert3('x == 1', [{pos: `xの位置`, value: x}])"
" -> { "value": x } で xが評価される
:execute s:assert3('x == 1', [{"pos": `xの位置`, "value": x}])
" -> 実はこのあとここで `:throw` コマンドを返してthrowすることによってエラー位置をこの行にしたり...
:throw ...

コマンドも基本は同じでコマンドの{rhs}executeになってるのですが, どうしてもスクリプトローカル変数だけはコマンドを定義したファイルの方で評価されてしまうので ファイルごとにコマンドは定義する必要があるのはこれが理由です.

つまりスクリプトローカル変数諦めるなら一回定義すればあとは同じように使えますが そもそもコマンドは雑な開発用スクリプトとかテスティングフレームワークで使うことを想定しているので そんな感じで察してください.

グラフィカルな描画

ところで見た目とユーザの驚き的には power-assert のあのグラフィカルな表示を作るところが華と見ることもできそうですが, 今のところとりあえず線が被らない最低限のアルゴリズムで作っているのでもっと改善した表示ができると思います.

もしいい感じのグラフ描画のアルゴリズムわかる人は僕に教えてくださると大変ウレシイです

最後に

勢いでワーッと作っていてまだまだ改善点はあるのですが,一通り開発してテストしてる限りではめっちゃよい感じに動くので Vim script 書いてる方や興味あるかたは是非使って見ていただけると嬉しいです.

あと themis との連携を書いてますが,別に themis の作者である thinca さんに使い方とか確認をとったわけでもないので もしかしたらもうちょっと良く出来たりするかもしれません.

フィードバックとか使い方の質問とか github: https://github.com/haya14busa/vital-power-assert , twitter: https://twitter.com/haya14busa , Lingr: http://lingr.com/room/vim あたりにいただけると嬉しさあります.

Vim script でも power-assert して最高の assertion 書いていくゾ!!!