deoplete.nvim をいれてみた

完全に食わず嫌いっていうか現状の neocomplete.vim で満足していたんですが、稀によく補完が重すぎてアイエエエエエとなることがあるので、重い腰を上げて deoplete.nvim を入れてみました。

導入

NeoBundle "Shougo/deoplete.nvim"
NeoBundle "roxma/nvim-yarp"
NeoBundle "roxma/vim-hug-neovim-rpc"

未だに neobundle.vim を使っている老人です。
また、neovim ではなくて Vim を使用しているので nvim-yarpvim-hug-neovim-rpc も導入する必要があります。
更に neovim 自体も必要になってくるので以下のように導入しておきます。

# ubuntu 環境だとこれ
$ sudo apt install python3-pip
$ pip3 install --upgrade neovim

あとは vimrc に起動時に有効になるように設定を追加しておきます

let g:deoplete#enable_at_startup = 1

neocomplete.vim だとキーマッピングとか設定とかもっとしているんですが、とりあえず暫定的に動けばいいかなーというので細かい設定はまだしてません。

所感

で、実際に使ってみた感想ですが兎に角軽い。
あれ、Vim ってこんなに軽かったの?っていうぐらい軽い。
もうそれまで飛んでいきそうなくらい高い。
入力しているときもそうなんですが、それ以外(カーソル移動とか)もなんか軽くなっている気がするぐらい軽い。
導入してからまだ 1〜2日ぐらいなので細かい挙動とかは確認していないんですが、今の所は特に問題なさそうです。
と、いうかこれだけ軽いと多少問題があっても neocomplete.vim に戻るよりは deoplete.nvim を使ったほうがメリットがでかいですね…。
軽い以外の利点だとデフォルトで look を使った英語補完があるのもいいですね。
neocomplete.vim 時代でも look を使った補完はあったのですが、設定とかがめんどくさくて結局あんまり使いこなせてなかったんですよね…。
設定とか何もしないでいい感じに補完されるのがいいですね。
軽いし。
あと、現状の欠点というか惜しい挙動としては補完ウィンドウがポップアップされるまでにタイムラグがあるのがちょっと気になりますね。
neocomplete.vim だと入力中でもポップアップされたんですが、deoplete.nvim だと『入力が止まった時にポップアップされる』という感じの挙動になっています。
まあ欠点というか今での挙動に慣れているのでちょっと戸惑う挙動ですね。
これがあればもう完璧100点だったんですが、まーこれぐらいなら deoplete.nvim でもいいかなーと。
今のところはデメリットよりもメリットが上回っているのでしばらくは deoplete.nvim を使って様子をみてみます。

Cookpad Ruby Hack Challenge #5 [二日間開催] に行ってきた話

先週の月木に Cookpad Ruby Hack Challengeに行ってきました。
わたしは今回で4回目の参加になります。

1日目

1日目はコミッタの人が Ruby の実装や内部についてお話しつつ、実際に Ruby のコードを見たり触ったりしよう、というような内容でした。
1日目はみんなもくもくと作業していて、あんまり議論したり、騒がしくなかったイメージですね。
午前中は Ruby 開発についての講義があり、後半は実際に Ruby のコードを触ってみましょう。 みたいな内容でした。
今まで参加した RHC とは違って『みんなで Ruby のバグを取ろう』っていう共通課題があったのが面白かったですね。
普段は printf デバッグでソイヤッ!することが多いんですが、やっぱり gdb とか使うのが便利そー。
gdb といえば、Mac (+ docker?) 環境でうまく動いていない人が結構いたらしくて lldb を使っている人もいましたね。
Ruby を開発する時にこのあたりの環境はハマりポイントなのかもしれない。
関係ないですが、課題をやっている時に問題点を取り除いたのになぜかまだテストが失敗していて永遠と悩んでいたのが一日目のハイライトです。
あ、本来やりたかったことは解決方法とか実装方法が全然わからなくて進捗は完全に無でした。

2日目

1日目は月曜日で、2日目は木曜日と2日間空いたスケージュルとなっていました。
実際のところ開催場所の都合により 2日間ずれてしまった形になってしまったらしいのですが、そのおかげでわからなかった部分を考える時間が出来たので結果的によかったですね。
いや、本当によかった。
2日目は完全にそれぞれがやりたいことをやっていた感じですね。
Ruby に機能を追加したり、ドキュメント整備しようとしていたり、実装を読んだりと様々な作業を行っていました。
最終的には何名かの方が bugs.ruby にチケットを立てていたりとよかった。
あと 1日目よりかは議論とかが盛り上がっていたかなーという印象。
ちなみに 2日目の知見は『Proc.new のブロック引数を省略した場合、それを呼び出したメソッドのブロック引数を返す』というのを教えて貰ったことです。

def meth
    # meth のブロック引数を返す
    Proc.new.call
end

p meth { 42 }

これを知っていると自慢できるので皆さんも覚えておきましょう。
ちなみに proc でも同様の挙動になります。
進捗ですが、この2日間でやりたかったことは一応出来たんで、それは別の記事で書きます。

追記:書きました

その他

アフターパーリィで matz に直接 %h 記法について話してみたんですが、まーなんかダメそうかなーという感じ。
ダメそうというか、うーん…どうしようかなーと。
ポイントとしては、

  • 該当する機能の知名度(他の言語ではどれぐらい一般的なのか
  • もうちょっと具体的なユースケース
    • JavaScript だと利用するケースは多そうだけど Ruby だとどうなの、みたいな

あたりですかねぶっちゃけ酔っててよく覚えてない
より具体的なユースケースは存在していて、例えば、RSpec + FactoryBot を使っている時に以下のようなコードを書くのが一般的だと思うんですが、そういう時にめっちゃほしいんですよね。

let(:name) { "homu" }
let(:age) { 14 }
# ここで  FactoryBot.create(:user, **%(name age)) みたいに書きたい
let(:user) { FactoryBot.create(:user, name: name, age: age) }

最近 RSpec ばっかり書いているのでこういうのがめちゃくちゃほしい。
上のコードだと短いのでそうでもないんですが、引数が5〜6個とかあったり、updated_atcreated_at みたいなちょっと長い名前を使っているとどんどん横に長くなっていくんですよね…。
ただ、逆にいうとこれ以外で必要なケースがないような気もするのでもうちょい考えたいなーという気持ちも。
あれば確かに便利なんだけど、変数をそのまま譲渡する機会がそんなにないっていうのもわからなくもないのでむずかしい。
なので、まーこの提案を議論するとすれば、

  • この機能は必要なのか(需要があるのか
  • この機能が必要であればどう実装するべきなのか

が、鍵なのかなぁ。

あと matz 関連で言うと『StringSymbol の違いってどう思っているの?』って質問したら『Symbol がこんなに難しいのに気づくのが遅すぎた』と言っていたのが印象的でしたね。
まあ、 matz も言っていましたが StringSymbol って全然別のオブジェクトでそれこそ "1"1 ぐらい違うとは思っています。
ただ、StringSymbol って使用する場面が微妙にかぶっているところがあり、例えば Hash のキーが String だったり Symbol だったりすると思います。
こういう時に Hash の値を参照する場合、『hash["key"] なのか hash[:key] なのかわからんなー』と思う事が稀によくあるので、このあたり難し言っていうかめんどくさいんですよえね。
毎回 hash["key"] || hash[:key] みたいに書くのも馬鹿らしいですし…、hash["key"] = value って書いたらダメで、hash[:key] = value って書かないとダメだったりとか…。
StringSymbol の使い分けは置いといて、このあたりはなんか解決したいなーという気持ちはありますねえ。

所感

今まで参加した RHC は 数時間〜1日単位で開催されていたのに参加していたので2日連続で参加したのははじめてでした。
なので割とゆっくりと開発できたかなーと思います。
何回か参加していたので2日目だけ参加しようかなーと思っていましたが、結果的には2日参加してよかった。
時間が長かったので開発者に質問したり相談したりする機会も多かったと思いますし。
まあとは普段 Ruby の話とか聞く機会がないので開発者会議をちょろっと見学出来たのもよかったですね。
最後の発表の時にコミッタがマウント取ってるのは怖かったですが
今度参加したときはもうちょいゆるふわな感じで議論っていうか他の人がやりたいことに対して意見とか言い合えたらいいなーと思いましたまる。

Ruby で HTML を整形する

最近 HTML をゴニョゴニョする事が多いんですが、HTML が整形されておらず見づらい事がままあります。
いい感じに整形して出力したいなーと思って調べてみたら標準ライブラリに CGI.pretty というのがありました。

require "cgi"

html = <<~EOS
<!doctype html>
<html> <head> <title>Example Domain</title>
</head> <body> </body>
</html>
EOS

puts CGI.pretty html
# output:
# <!doctype html>
#
# <html>
#
#   <head>
#
#     <title>
#       Example Domain
#     </title>
#
#   </head>
#
#   <body>
#
#   </body>
#
# </html>

こういうのが標準ライブラリにあるとよいですね。

参照

Ruby でメソッドの定義元をシュッと調べる

デバッグなどしている時に Rails の実装を読みたい!、ということはよくあると思うんですが、そういう時にシュッと定義元を開きたいですよね。
優秀な IDE とかだとそういう機能もあるかもしれませんが、irb や pry を実行している時にサクッと調べたいですよね。

Method#source_location を使う

そういうときには Method#source_location を利用する事が出来ます。

# まず #method で Method のインスタンスを取得して、#source_location を呼び出す
User.method(:pluck).source_location
# => ["~/.rbenv/versions/2.5.1/lib/ruby/gems/2.5.0/gems/activerecord-5.2.0/lib/active_record/querying.rb", 16]

こんな感じでどのファイルの何行目で定義されているメソッドなのかを取得する事が出来ます。
Ruby に組み込まれているメソッドなので Rails のように闇の深いライブラリでもだいたい定義場所を調べることが出来ます。

注意

Method#source_location ですが、Ruby のコードの定義場所を調べることは出来ますが、C拡張で実装されているメソッドの場合は nil を返すので、標準ライブラリを調べる場合は注意しましょう。

[].method(:===).source_location
# => nil

[CombNaf x 学生LT] 第12回 学生エンジニアLT大会!!!で LT してきた

してきました。
相変わらず学生ではないんですが、遠目で見ていたりします。
今回は普段の学生LT とは違い CombNaf という別のコミュニティと合同で開催されました。
そのため、参加者が多かったり、普段の学生LT とは結構雰囲気が違っていたような感じでしたね。

Ruboty で Discord-Bot をつくろう

チョット前に Ruboty を使って Discord-Bot をつくろうとしていたのでその LT をしてきました。
LT と言ってもデモとかやってたらガッツリ時間食っていたんですが()。
やっぱり Ruboty 便利ですね。
こういう Bot がサクッとつくれるのがよきよき。
今回は参加者も多かったので Twitter とかでの反応も多くよかったです。
やはりレスポンスがあるとモチベーションがあがりますね。
あとやっぱり全体的に Ruby 使っている人が少なかったのでもっとこういうのを広めて行きたい気持ち。

補足

デモで使用していたお天気 bot ですが、各種 API のキーを設定しないと使えないので使いたい方がいれば注意してください。

Vim 8.1 がリリース!!

朝起きたら Vim 8.1 がリリースされていました。
Vim 8.0 のリリースが 2016/09/12 なので約1年8ヶ月ぶりとなるリリースです。
大きな追加点としてはやはり :terminal が実装されたことですかね。
わたしは :terminal はクソだと思っているんですが、リリースされたのでもう1度試してみようかなあ…。

3,4月で気になった Ruby のパッチ、提案

書こう書こうと思っていて結局書いてなかったシリーズ。
とりあえず、現状まとめていたやつだけ放出。

Feature #14579: Hash value omission - Ruby trunk - Ruby Issue Tracking System

JavaScript みたいに Hash を定義する時に『値を省略してキーだけ渡して Hash を定義する』みたいな記法の提案。
これ、JavaScript を書いていた時に結構多用していたので Ruby にもめっちゃほしかったんですが、Reject されてしまった模様…。

Feature #14473: Add Range#subrange? - Ruby trunk - Ruby Issue Tracking System

任意の Range が任意の Range の範囲内かどうかを判定するメソッドの提案。
あれば便利そう。

Feature #4824: Provide method Kernel#executed? - Ruby trunk - Ruby Issue Tracking System

Ruby だと『実行したファイルがコマンドラインから呼ばれたかどうか』を判定する場合に

if __FILE__ == $0
  my_main()          # call any method or execute any code
end

みたいに書くんですが、この __FILE__ == $0 をメソッド化してわかりやすくしたいよねーみたいな提案。
かなり前から議論されているんですが、いいメソッド名がないらしくてまだ決まってない模様。

Feature #14585: Array#each_pair - Ruby trunk - Ruby Issue Tracking System

ほしいのはわかるけど名前がいまいち。

Feature #14593: Add Enumerator#concat - Ruby trunk - Ruby Issue Tracking System

今までなんでなかったのか理由が気になる。

Feature #14594: Rethink yield_self's name - Ruby trunk - Ruby Issue Tracking System

yield_self の別名を考える、ということで色々と議論されていたみたいですが、ほぼほぼ then に決まったぽい。

Feature #14022: String#surround - Ruby trunk - Ruby Issue Tracking System

これ、稀によく欲しくなるのでちょっと期待していたんですが、Reject されてしまった模様。

Feature #13383: [PATCH] Module#source_location - Ruby trunk - Ruby Issue Tracking System

Module#source_location の提案 文字通りクラスの定義場所を取得するメソッドだけど、Ruby の場合はオープンクラスをいろんな場所で呼び出す事が出来るので複数ヶ所を取得する必要があって止まってるみたい。
ただ、最後の定義場所を取得できるだけでも便利そう

Feature #14197: Enumerable#{select,reject accept a pattern argument - Ruby trunk - Ruby Issue Tracking System}

collection.reject(/re/) みたいに『#reject にも値を渡したいよねー』という提案。
まあわからなくはない。