Yokohama.vim.reboot #6 に行ってきた

Yokohama.vim.reboot #6 に行ってきた!
最近は勉強会自体あまり行けてなくて、それなのに行っても感想記事サボっているので反省…。久々に書く。

アイスブレイク

Vim に関するキーワードが書かれたカードを、自分には見えない(というより見ない)ように、他の人には見えるように首から下げる。
そしてペアを組んで、軽く自己紹介したあと、互いに自分のカードに書かれた内容について、はいかいいえで答えられる質問をしてって、自分の持ってるカードに書かれたキーワードを当てる、というゲームをした。ペアは適当な時間毎に組替える。
これが意外にむずくて、なかなか当てられない…。キーワードは初心者向けと上級者向けに分かれていたので、私は空気を読んで上級者向けのを取ったのだけど、上級者向けのワードはそもそも初心者の人に質問しても相手がその単語についてよくわかっていなくて曖昧な答えが返ってきたりして、そうなることも計算に入れつつ質問を考えて答えを探すのがめっちゃむずかしかったけど楽しかった。
かなり盛り上がって、予定の時間より長くなったけどめっちゃ良かった。ちなみに私のキーワードは view でした。view コマンド使わないなぁ…。

KazuakiM さんの発表

Vim を使うようになった軌跡みたいなお話。Vim にデレていく話はいい話ですね。
ちなみにサクラエディタを使ってたという話だったけど、私も以前はサクラエディタ使ってました。よさ。

vimrcソースリーディング

各テーブルに分かれて vimrc 読んだりなんだりした。
他のテーブルがどういう感じだったのかは知らないのだけど、私のところのテーブルは3人で、私以外の二人の vimrc を順番に読んでいって改善ポイントとか探したり、改善のための編集操作で、こうした方がいいよ、とかこういう方法があるよ、みたいなアドバイスをしていくみたいな偉そうなアレをしてました。マンボウさん偉そう。
ガッツリ読んで改善して、みたいなことをしていたので、予定のタイムテーブルにあった、スクラッチからの vimrc 構築は結局やらなかった…。希望者が少なかったのもあるけど、スクラッチからはやはりなかなか難しい感じがある。

懇親会

ビアバッシュで、寿司とかナン+カレーとかチキンとか食べつつおしゃべりも少ししつつ割ともくもくと食べてた。
食べ終わって、勢いでやるって言ってあったライブコーディングをすることになったんだけど、ネタは考えてなくもなかったんだけど正直みんなに楽しんで貰えるネタか自信がなくてその場でみんなにネタ聞いたりしてやった。
その結果、とあるsyntax定義プラグインが微妙なので直すのをやって欲しい、みたいな話があって始めたのだけど、なぜか Vim がエラー出しまくって、調査をした結果 Vim のバグっぽいということがわかり、そのIssueを登録するということをして、当初の目的は忘れられてライブVimデバッギングになってしまった…すまぬ…。
これはこれで滅多に見られないもの見せられたしよかったかな感はあるけど、所詮結果論だし、グダってしまったのは本当に申し分けない。その場でお題を募集なんてすると下調べもないもんだからどうやってもグダるし、やはりやるときはちゃんと自分でお題を用意しとこうって思った。次に活かしたい。

まとめ

次回も行きます!

漢字パズルを解く word-finder というのを作った

例えば、以下のような問題があったとします。

    全  全
    ↓  ↓
中→□→□→結
    ↓  ↓
    曲  金

□に入る漢字を答えろ

この手の問題を解く場合、自前の知識の中から、時には勘も交えて総検索することになります。
ヒラメキと言えば聞こえはいいですが、別に考え方を変えたりして解ける問題ではないので、やることはただひたすら検索です。
なら機械にやらせてもいいのでは、ってことで、こういう問題を解くやつを作りました。
とりあえず動くレベルで、仕様とか見た目がかなり雑ですが、動くので公開します。

http://thinca.github.io/word-finder/

使い方

上記の URL を開いても、(少なくとも記事公開時点では)謎のフォームと[検索]ボタンがあるのみで、意味不明です。
というわけで使い方。
まず、わからない部分をアルファベットに置き換えます。

    全  全
    ↓  ↓
中→A →B →結
    ↓  ↓
    曲  金

今のところ置き換えられる文字は半角英数字と一部の記号のみです。
そして、ここから拾える単語を列挙します。

全A
中A
A曲
全B
B結
B金
AB

この単語のリストをフォームに貼り付けます。
そして検索ボタンを押すと…答えが出ます!
ちなみに単語の文字数としては 2-5 文字まで対応していますが、合成単語とかは出ないかもしれないです。詳細は下記の「辞書について」を参照。

なぜブラウザなのか

スマホから使いたかった。

辞書について

できればフリーの国語辞典でもないかなーと思って探したんですが、単語の一覧を簡単に扱えるようなものは見付けられなかったので、最終的に SKK の辞書ファイルに落ち着きました。
SKK の辞書から必要な部分を切り出して使っています。なので、SKK の辞書に載っていない単語は検索できません。
ところで SKK の辞書データって GPL っぽいのだけど、データが GPL の場合にその扱いについて調べたけれど、GPL はソフトウェアに適用されるものらしく、データの場合はよくわからなかった…。
word-finder を GPL にしないといけないならどうせコードは公開しているので問題はないのだけど、なんか気持ち悪いので詳しい方いたら教えていただけると助かります。

そう言えば完全に余談だけど、SKK の辞書って未だに EUC-JP なんですね。そろそろ UTF-8 とかにしてもいいのでは…。辞書に登録できない文字とかも出てきちゃうだろうし。

今後の課題

Web ページを作るということを普段しないので、習作も兼ねているので、作りがだいぶ雑です。CSS すらないし…。

  • 使い方が意味不明なのでせめて説明をページ内に入れたい。
    • スペース取るのは邪魔なのでポップアップするリンクがあると良さそう。
  • 見た目もう少しマシにしたい(案はない)。
  • 辞書を加工するツールをなんとなく Ruby で書いたけど、ブラウザ側のコードが JavaScript(正確には CoffeeScript)なので、統一する意味で nodejs 辺りで書き直したい。
  • jQuery を使っているけど、最近だとあまりよろしくないらしいとの噂なのでなんか置き換えるなどしたいかも。
    • この程度の規模なら別によいって話もあるかもしれないけどよくわかっていない。
  • 読み(カタカナ)の辞書を足せばクロスワードパズルにも使えそうな予感。

OmniSharp.vim のメンテナになりました

http://i.gyazo.com/648e0bbd21949a25313e8ab983e4df04.png
https://github.com/OmniSharp/omnisharp-vim
顔アイコンの中にマンボウアイコンを潜り込ませることに成功しました。壮観ですね。
問題の報告や機能要望などは私に直接言ってもらっても大丈夫です。日本語でOK。サーバ絡みだと対応は難しいかもしれないですが、善処します。
GitHub の Issue の方は世界中の人が見ているので、あちらに書く場合は英語でお願いします。

master への push を禁止するローカル git hook の正しい書き方

GitHub などで Pull Request ベースで開発をしていると、master には間違っても push したくないわけです。
GitHub 側には残念ながら master への push を禁止するような設定はできないので、仕方ないのでクライアント側の Hook で対応しようってことになり、この方法についてググるこことかこことか、いくつか方法を紹介しているページが出てくるんですが、どれもやり方が間違っている*1ので、正しい方法を紹介。

何がまずいのか

上記に挙げた方法では、細かい部分は違ってたりするけど、git symbolic-ref HEAD を使って現在ブランチを見て、master だったら push を禁止する、という方法を取っている。
しかし、push はカレントブランチから行われるとは限らない。dev ブランチにいるときに git push origin master とすれば、当然 master ブランチが push される。この場合上記の方法だと防げない。他にもありがちなパターンだと、git push origin --all などでも master が push される。

正しい方法

pre-push hook を以下のような感じにする。

#!/bin/bash

while read local_ref local_sha1 remote_ref remote_sha1
do
  if [[ "${remote_ref##refs/heads/}" = "master" ]]; then
    echo "Do not push to master branch!!!"
    exit 1
  fi
done

標準入力から push 先のブランチ名の情報なんかがくるので、そこをチェックする。詳しく知りたい人は man githooks の pre-push の辺りを見るとよい。

なぜ間違った方法が出回っているのか

恐らくだけど、master ブランチへのコミットを禁止する pre-commit のスクリプトが流用されたのだと思う。pre-commit の場合は、現在ブランチを見ればいいので、それで正しい。それを pre-push へそのまま適用しようとしてはいけない。

ところで

そもそも GitHub さんがサーバ側で master への push を禁止できる機能を入れてくれると色々と捗るのでそういう機能是非入れて欲しい。なんでないのー。

*1:少なくとも私には正しい方法を記述したページを見付けられなかった

Ruby の Hash で値だけ map で変換したかった

hash = {a: 1, b: 2, c: 3}
hash2 = hash.map {|k, v| [k, v * 2] }.to_h
p hash2  # => {a: 2, b: 4, c: 6}

めんどくさい。Scala には mapValues というのがあるらしい。

Ruby で書くならこうかな。

class Hash
  def map_values(&block)
    dup.map_values!(&block)
  end

  def map_values!(&block)
    update(self) {|_, v| block.call(v) }
  end
end


hash = {a: 1, b: 2, c: 3}
hash2 = hash.map_values {|v| v * 2 }
p hash2  # => {a: 2, b: 4, c: 6}

ググる似たようなはちらほらあるっぽい。Ruby にも標準で欲しかった。

無料で使える CI サービス 8 個まとめ

CI サービスをいくつか触ってみたのでまとめ。
今回の目的は、テストを実行すること。なので、ビルドやデプロイ辺りはちゃんとは見ていない。
ドキュメントで確認しただけの項目などもあったりするので、間違っていたらごめんなさい。教えてもらえると助かります。
ただ、これは記事を書いた時点での比較で、今後のサービスの変更に対応する予定はないです。

触ってみたサービス一覧

アルファベット順。

codeship ってのもあったけど、無料プランは月100ビルドまでとかで常用には耐えないと感じたので中身見てない。

機能比較

機能比較は全て無料プランでのもの。有料だと対応している場合でもここでは x にしている。
比較項目は私の独断と偏見で適当に選出した。

項目 AppVeyor CircleCI Drone IO Magnum CI semaphore shippable Travis CI wercker 備考
YAML による設定 × × リポジトリ内の YAML ファイルからビルド手順を設定できる
Web UI による設定 × × × Web UI でビルド手順のスクリプトを書くことができる
GitHub 連携 GitHubリポジトリ一覧から新規プロジェクトを作れる
BitBucket 連携 × × BitBucket のリポジトリ一覧から新規プロジェクトを作れる
GitHub PR 対応 × × GitHub の Pull Request を自動でビルドしてステータスを返せる
ビルド環境キャッシュ × × × × × 複数ビルド間を跨ぐキャッシュ領域を利用できる
手動リビルド × *1 過去のビルドを手動でリビルドできる
複数環境ビルド × × × × × 環境変数などで複数の環境に対してビルドできる
private なプロジェクト × × × ビルド状況などを private にできる(かなり未検証)
ビルド時間制限 30分 20分 15分 30分 60分 60分 50分 25分 無出力時間による制限が別途ある場合もある

YAML による設定の利点は、プロジェクト構成の変更とビルド手順の変更を紐付けることができること。
Web UI による設定の利点は、プロジェクトに直接関係ないファイルを置かなくて済むこと。特にファイルを置く権限がない場合などには助かる。

各サービスについて雑感

以下、かなり主観かつざっくりな雑感。

AppVeyor

http://www.appveyor.com/

.NET 向けの CI サービス。
.NET に特化した機能が色々使えるけど、重要なのは、テスト環境が Windows であるということ。他に Windows 環境での CI サービスを少なくとも私は知らないのでかなり貴重。.NET 製じゃなくてもこれを使えば Windows 環境でテストができる。
設定のスクリプトは、Windows のバッチファイル(.bat) と、PowerShellスクリプト(.ps1)の形式で書ける。PowerShell .NET のライブラリにアクセスできるので、外部からリソースのダウンロードなども可能。
ビルドトリガーが引かれると、新しいビルドは QUEUE に積まれて、実際にビルドが始まるまでに結構時間がかかる。

ビルド時間について、このページでは全てのプランは40分と書いてあるが、このページでは、Free、Professional、Premium は 30 分で Enterprise は 50 分と書いてある。どちらが正しいか不明。

CircleCI

https://circleci.com/

必要な機能は一通り揃っている印象。
YAML での設定において、各ビルドフェーズに、pre(フェーズ前)、override(フェーズのデフォルト動作を上書き)、post(フェーズ後)それぞれに対してスクリプトが書けたり、コマンド毎にカレントディレクトリや環境変数タイムアウト時間などを指定できるので、柔軟に設定できる。

Drone IO

https://drone.io/

Go 言語製の CI サービス。
他のサービスがビルド手順をいくつかに分割している中、Drone IO のビルド手順は1つのみと、とてもシンプル。
Pull Request 時のビルドは、がんばればできるらしいけど、それでもPR以外の普段の push で API が叩かれたり、ビルドページから Pull Request のページへ飛べなかったりするので、できるとは言わない方が良さそう。

Magnum CI

https://magnum-ci.com/

現時点でまだ public beta の CI サービス。結構前からずっと beta な気がする。
使い勝手については特に問題はない。普通に使える。
beta なので、private リポジトリが無制限で使える模様。いつ beta が取れるのかは不明。

semaphore

https://semaphoreapp.com/

ビルド中にスレッドが使えるのが特徴。ビルドパイプラインの各コマンド単位で、どのスレッドで走らせるか指定できる。無料で 1 ビルド中に 2 スレッドまで使える。
あとはプロジェクト構成を見て、一般的な構成の場合は自動で検出してビルド設定を自動で終わらせてくれるらしい。私が試したプロジェクトは一般的な構成ではなかったので、どこまでやってくれるのかよくわかってない。

shippable

https://www.shippable.com/

Travis CI と互換があり、.travis.yml ファイルが置いてあるとそれを認識してビルドを行ってくれる。ただ、どこまで互換があるのかは不明。Travis CI には language に generic が指定できるのだけど(ただしドキュメント化されていない)、shippable では指定できなかった。
Web UI が開かれるまでに結構時間がかかる。

Travis CI

https://travis-ci.org/

恐らく今回まとめた中では一番有名な CI サービス。
GitHub 限定とは言え、テストをするのに必要な機能は十分揃っている。鉄板。

wercker

http://wercker.com/

他の CI と比べても変わった、box と step という特徴がある。
box はテストの実行環境。ユーザーが作成したものを wercker ディレクトリに登録しておけば、誰でも使えるようになる。特定のツールがインストール済みの環境などを作っておけば、ビルド時間が短縮できる。標準でいくつか用意されているので、それらを使ってももちろんよい。
step はビルドの手順の1つ。bash で言う1つのコマンドで、wercker ではこの step のリストをビルド手順として指定する。step は、特定の動作を抽象化してまとめたもので、Amazon 3S との同期とか、npm install とか、そういう感じのが1つの step として登録されている。最悪 script step というのがあるので、これで bash でやってもよい。この step もユーザーが自作できる。

まとめ

無料でもこれだけの選択肢があるというのがすごい。
よりどりみどりなので、各自のユースケースにあった CI サービスを選んで使うといいと思う。

*1:ブランチ最新のみ

Google の Vim script Guide について言っておきたいこと

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

Google が、様々な言語に対する自社内でのスタイルガイドを公開しているのはご存知でしょうか。C++ のものJavaScript のものなどがあり、この辺りは割と有名かと思います。
では、Vim script のものがあるのはご存知でしょうか?
Google は、Vim script について、2 つのガイドを公開しています。

前者がカジュアルユーザー向け、後者がヘビーユーザー向け、といった位置付けのようです。さすが、Google がまとめているだけあって、なかなかポイントを抑えています。
ただ、これはあくまで Google が社内向けに作ったもの。鵜呑みにしてはいけない、もしくは、一般の人が使う場合は参考にしない方がいい部分もちらほら見受けられます。
そこでこの記事では、この 2 つのスタイルガイドを見るにあたって注意すべき点をまとめようと思います。全て個人の見解です。引用に入っている訳は、私による勝手訳です。

全体について

maktaba が前提になっている

Google が公開している、maktaba と言う Vim プラグイン向けのプラグインライブラリがあります。
これらのガイドでは、事あるごとに、Vim のこの機能は使わないで代わりに maktaba のこれを使え、のように指示してきます。
しかし、誤解を恐れずに言うと、maktaba はその仕組み上使うべきではありません。
ざっくり簡単に理由を言うと、maktaba は $ から移すことができない jQuery のようなものであり、別の言い方をすると、URL にバージョンが含まれていない Web API のようなものです。今後互換性のない変更が入った瞬間に死亡する未来がありますし、今でも、maktaba のバグに依存した動作をするプラグインはバグが修正されると死にます。
と言うわけで、maktaba 云々と書かれている部分は華麗にスルーするのが良いです。

Google Vimscript Style Guide

Regular Expressions

Prefix all regexes with \m\C.

全ての正規表現は \m\C で始めること。

\m は 'magic' がオンの状態で正規表現の解釈を行い、\C はパターン全体を大文字小文字を区別するようにします。
これは確かに誤爆を防ぐのには役に立ちますが、毎回指定するのはやや冗長です。
正規表現を受け取る Vim script の関数のうち、'magic' オプションが適用されるのは search() と searchpos() くらいです。
よく使う =~# も 'magic' の影響は受けません。
'ignorecase' オプションの影響を受けるのは、match()、matchend()、matchlist()、matchstr()、search()、searchpos()、searchpair()、searchpairpos()、substitute() になります。多いようですが、match() とその派生、search() とその派生、substitute() なので、系統としては 3 つくらいです。
この辺りはざっと調べたものなので、足りなかったり違っていたら教えてもらえると助かります。
自信がなければ \m や \C を付けておくのは悪いことではないですが、必須にするほどでもないかな、と思います。

Type checking

Use strict and explicit checks where possible.

可能ならば厳密かつ明示的な型チェックをしなさい。

is# などを使え、というのはその通りですが、全ての変数を使う前に型をチェックするのは冗長になりすぎます。
例えば Ruby を書いていて、全ての関数で、その引数について型のチェックをするコードを書くでしょうか? 書きませんよね。
期待した型でなければ、大体の場合は例外が飛ぶので、きちんと例外を処理すれば問題はないでしょう。たまに運悪く期待しない状態のまま先に進んでしまうこともありますが、その時はその時です。

Python / Other Languages

Python
Use sparingly.
Use python only when it provides critical functionality, for example when writing threaded code.
Other Languages
Use vimscript instead.
Avoid using other scripting languages such as ruby and lua. We can not guarantee that the end user's vim has been compiled with support for non-vimscript languages.

Python は慎重に使いなさい。他の言語は使ってはいけません。

はい。Google なのでお察し、といったところでしょうか。Python だけ許可して他を許可しない理由が全く説明されていません。
個人的な見解を述べるならば、外部インターフェースは余程の必然性がない限りは使うべきではありません。理由は Google が説明している通りで、ユーザーの Vim で使えるとは限らないからです。これは当然 Python にも言えることです。
ただ、あなたが書く Vim script があくまで自分向けのものであれば、書き易いように外部インターフェースを使うことは選択肢となりえるでしょう。他言語であればすでに揃っているライブラリを Vim script でわざわざ書き直すような真似は、一部の変態さんたちに任せて、あなたは使いなれた言語で使いなれたライブラリを使えばよいのです。
…私は変態さんなのでもう手遅れです。

Commands

In the plugin/commands.vim or under the ftplugin/ directory, defined without [!].

plugin/commands.vim か ftplugin/ ディレクトリに、[!] を付けずに定義します。

plugin/commands.vim に、と書いてますが、絶対にやってはいけません。
最近でこそ Vim プラグインプラグインマネージャでインストールして、runtimepath を追加していく方式が流行っていますが、本来は Vim プラグインは 1 つのユーザディレクトリにまとめていれていくもので、そのような運用も可能になっているべきです。
みんながみんな plugin/commands.vim にコードを書いたら、当然ファイル名が衝突します。
ちなみにどうやらこのファイル名のルールは maktaba によるもののようです。
[!] については、適切なコマンド名を付けていれば、ユーザの定義を上書きすることはほとんどないかとは思いますが、ここはどちらでも良いと思います。

Autocommands

Place them in plugin/autocmds.vim, within augroups.

plugin/autocmds.vim に、augroup 付きで定義しなさい。

Commands と同じファイル名の問題。

Mappings

Place them in plugin/mappings.vim, using maktaba#plugin#MapPrefix to get a prefix.

plugin/mappings.vim に、maktaba#plugin#MapPrefix を使って定義しなさい。

Commands と(ry
maktaba(ry

Naming

Prefix all variables with their scope.

全ての変数にはスコープのプレフィックスを付けなさい。

l: については無理に付ける必要はないと思いますが、一部の変数名が v: と衝突する可能性があるので、付けた方が安全ではあります。
私は省略する派です。

Google Vimscript Guide

こちらはヘビーユーザ向けということで、Style Guide の方の内容も含まれています。重複していない部分について言及します。

Structure

ここに書かれているものの多くは maktaba 前提の構成のようです。

Documentation

Use vimdoc.

vimdoc を使いなさい。

この vimdoc というツールは、私もあまり詳しくないのですが、軽く調べてみた限りだと maktaba の構成に依存しているようです。
あとは変則的な help に対応しているのかがちょっとわかりませんでした。




と言うわけで、個人的に問題があると思う点を挙げてみました。
結構色々書きましたが、最初に言った通りポイントは抑えられていて、maktaba に絡まない部分はかなり参考になります。つまり諸悪の根源は maktaba…。


これで今年の Vim Advent Calendar は終わりです。でも、皆さんの Vim ライフは始まったばかりです。それではまたいつの日か、未来でお会いしましょう!