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

Thanks Driven Life

日々是感謝

Pokemon-Emacs 〜あなたが Emacs で開いているファイルに潜んでいるポケモン〜

emacs

TL;DR

f:id:gongoZ:20160715135904p:plain

https://github.com/gongo/pokemon-emacs

経緯

最近は Pokemon Go が流行っているようで、正式サービス開始を待ち望まれているようです。

『Pokémon GO』は、位置情報を活用することにより、現実世界そのものを舞台として、ポケモンを捕まえたり、交換したり、バトルしたりするといった体験をすることのできるゲームです。 このゲームはモニターの中だけで完結せず、プレイヤーは実際に家の外に出てポケモンを探したり、他のプレイヤーと出会ったりしながら楽しむことができます。

面白そうですね。海外でも既にユーザが爆発的に増えており、スマホ片手に街をうろうろする様子などを画像や動画でも目にします。

さて、日本は夏まっさかりであり、暑い日が続いています。そんな中

「私もポケモン探しにいきたいけどまだサービス開始してないし、 そもそも外に出たくない…

という Emacs 使いも多いと思います。

でもよく考えてみてください。ポケモンは何も外だけに居るわけじゃないんです。 昔はゲームボーイにいました。じゃあ Emacs にも居るかもしれないですよね。

Pokemon-Emacs とは

https://github.com/gongo/pokemon-emacs

Emacs のマイナーモードの一つです。効果としては「今開いているファイル名の絶対パス(もしくはバッファ名)で一意に決まるポケモン名を表示する」だけです。

とりあえずいろいろがんばってインストールしてもらったあと

M-x pokemon-emacs-mode

を実行すると、(おそらく)ファイル名の横あたりに、下図っぽい感じでポケモン名が表示されます。

f:id:gongoZ:20160715133107p:plain

この場合は ナッシー が選ばれました。

つまり /Users/gongo/src/github.com/gongo/pokemon-emacs/README.md にはナッシーが潜んでいる。豆知識です。

ちなみに *scratch* にはナゾノクサが居ます。多分。

実装についてちょっとだけ

特に難しいことはしてませんが

  1. ファイル名、もしくはバッファ名を seed として乱数をゲット
    • なのでどの環境でもファイル名が同じ = 同じポケモンが出てくる。はず。
    • (もちろんポケモン一覧 pokemon--monsters が変化したら変わりますが…)
  2. ポケモン一覧から↑の乱数を index としてポケモンをゲット

これだけです。

少し前に Pokemon-Go におけるポケモン出現率*1 みたいな画像を見たので、出現率に併せて「出やすいポケモン」「出にくいポケモン」みたいな実装をしてたんですが、 あの画像自体デマだったみたいなコメントもあったので、まあいいかってことでとりあえず愚直にリストから取るようにしました。

あとはポケモン一覧はとりあえず初代の 151 匹*2をチョイスしました。他のシリーズ追加すれば勝手に出てくるとおもいます

まとめ

/path/to/fooピカチュウが潜んでいたぞ!!」 「ミュウが見つからねえ!!」

みたいな楽しみ方で、エディタ生活に華を添えてください。ポケモン大好き!!

Docker Image がデプロイできるようになった Heroku で、Emacs (elnode) on Alpine Linux を動かす

emacs docker

成果物

(7/21 追記: Docker Hub のリポジトリ名を gongo/docker-emacsgongo/emacs に変更しました)

経緯

Container registry public beta - deploy Docker images to Heroku | Heroku Dev Center


半年ほど前に heroku-docker を使ってみた んですが、 今回の発表は更に熱くて、まさに Docker Image そのものを Heroku にもっていけるということで、早速試してみました。

作成した Docker Image

今回は Alpine Linux をベースに、Emacs や Cask に必要なライブラリ(python など)をインストールしています。

デプロイしてみる

Container Registry and Runtime | Heroku Dev Center の手順通り。 今回はあらかじめ docker build して動作確認したりしていたので、いざデプロイする時には「Pushing an existing image」を行いました。

$ heroku apps:create gongo-docker-emacs
$ docker tag gongo/emacs:example registry.heroku.com/gongo-docker-emacs/web
$ docker push registry.heroku.com/gongo-docker-emacs/web 

そして出来上がったのがこちら(いつか消します)

https://gongo-docker-emacs.herokuapp.com/

まとめ

お手軽感が高いです。 いくつか制限はある らしいですが、まだ Beta ですし、正式リリースされたら解決するかもしれないので、そこらへんはゆったり待ちましょう。

そんなわけでみなさん Emacs を動かしましょう!!

terraform plan の実行結果で、属性値が変更になる行に色付けする sed

TL;DR

readonly escape_ansi=$(printf '\033')

sed -e '/".*" => ".*"$/!b' \
    -e '/^.*: *"\(.*\)" => "\1"$/!s/.*/'"$escape_ansi"'[31m&'"$escape_ansi"'[m/'

f:id:gongoZ:20160702110516p:plain

経緯

毎晩暑い日が続く日本、AWS の各種リソース管理を Terraform で行っている皆様におかれましては、 日々の業務において terraform plan をよくお使いになられていることと存じます*1

そんな中、例えばこのような実行結果が表示されたとします:

..
.. (message)
..

+ aws_security_group.app
    ingress.#:                   "" => "1"
    ingress.0.cidr_blocks.#:     "" => "1"
    ingress.0.cidr_blocks.0:     "" => "192.0.2.0/24"
    ingress.0.from_port:         "" => "80"
    ingress.0.protocol:          "" => "tcp"
    ingress.0.to_port:           "" => "80"

-/+ aws_security_group.db
    ingress.#:                   "2" => "2"
    ingress.0.cidr_blocks.#:     "1" => "1"
    ingress.0.cidr_blocks.0:     "198.51.100.0/24" => "198.51.100.0/24"
    ingress.0.from_port:         "3306" => "3306"
    ingress.0.protocol:          "6" => "tcp"
    ingress.0.to_port:           "3306" => "3306"
    ingress.1.cidr_blocks.#:     "" => "1"
    ingress.1.cidr_blocks.0:     "" => "203.0.113.0/24"
    ingress.1.from_port:         "" => "5432"
    ingress.1.protocol:          "" => "tcp"
    ingress.1.to_port:           "" => "5432"

-/+ aws_security_group.mail
    ingress.#:                   "2" => "1"
    ingress.0.cidr_blocks.#:     "1" => "1"
    ingress.0.cidr_blocks.0:     "198.51.100.0/24" => "198.51.100.0/24"
    ingress.0.from_port:         "587" => "587"
    ingress.0.protocol:          "6" => "tcp"
    ingress.0.to_port:           "587" => "587"
    ingress.1.cidr_blocks.#:     "1" => ""
    ingress.1.cidr_blocks.0:     "198.51.100.0/24" => ""
    ingress.1.from_port:         "995" => ""
    ingress.1.protocol:          "6" => ""
    ingress.1.to_port:           "995" => ""

Apply complete! Resources: 1 added, 2 changed, 0 destroyed.

(実行結果はてきとうです)

各セキュリティーグループのルール数が2、3個なのでまだまだ見えますが、例えばルール数が20個とかになるとかなりの行数が目に入ります。その中で どの行(属性)が変更なのかぱっと見、わかりづらい と思うわけです。思いました。

まあそんなわけで、属性値に変更のある場所がわかりやすく見えればいいな、ということで、いくつか方法はあると思いますが、今回は sed でやってみました。

sed

readonly escape_ansi=$(printf '\033')

sed -e '/".*" => ".*"$/!b' \
    -e '/^.*: *"\(.*\)" => "\1"$/!s/.*/'"$escape_ansi"'[31m&'"$escape_ansi"'[m/'
  1. "xx" => "yy" という文字列(xxとyyは任意)を 含まない 行はスキップして次に進む
  2. "xx" => "xx" という条件に一致しない(つまり左と右の "" 内の値が 同じではない )場合 に、赤で色付けする

こんな感じでできました。パターンは単純なんですが terraform plan の実行結果に対してだけ使うのであれば充分かなと思います。

ついでにこいつをスクリプトに落とすと、雰囲気こんな感じ

#!/bin/sh

readonly escape_ansi=$(printf '\033')
readonly program_name=$0

if [ -p /dev/stdin ] ; then
    cat -
else
    if [ ! $# -ge 1 ] ; then
        echo "$0: [ERROR] You must specify file."
        exit 1;
    fi

    if [ ! -f "$1" ] ; then
        echo "$0: [ERROR] \"$1\" No such file."
        exit 1;
    fi

    cat "$1"
fi | sed -e '/".*" => ".*"$/!b' \
         -e '/^.*: *"\(.*\)" => "\1"$/!s/.*/'"$escape_ansi"'[31m&'"$escape_ansi"'[m/'

てきとうに tpdiff とか名前で保存しておいて

$ terraform plan | tpdiff

こんな感じで、冒頭の画像のように表示されます。多分。

ひとまず

あたりでは動いているようです。

まとめ

sed 難しい

おまけ

当初、sed の色付けする部分を

-e $'/^.*: *"\\(.*\\)" => "\\1"$/!s/.*/\e[31m&\e[m/'

みたいな感じでやってたんですが、 POSIX 準拠してるかってチェックしてくれる shellcheck を使うと

fi | sed -e '/".*" => ".*"$/!b'
         -e $'/^.*: *"\\(.*\\)" => "\\1"$/!s/.*/\e[31m&\e[m/'
            ^-- SC2039: In POSIX sh, $'..' is undefined.

ってな感じで怒られたので、printf 使うようにしました。

*1:手元実行なんかせず、Atlasにお任せしてる人が多いのかもしれない

「Methods & Tools Summer 2016 Magazine」に Turnip について寄稿しました

turnip

A free software development magazine であるところの Methods & Tools に 「Turnip - Gherkin extension for RSpec」というタイトルで寄稿しました。

Methods & Tools - Summer 2016

書いたこと

  1. テストやってますか。受け入れテストどうですか。
  2. Cucumber が人気だよね
  3. だけど人によっては Cucumber のこういう部分がちょっと気になる人いるよね
  4. そこらへんを解決しようとしてるのが Turnip です
  5. Turnip 導入編
  6. Turnip のこういう機能が、3 で挙げた点を解決してるのだー
  7. まとめ

目新しいことは何もなく、Turnip の誕生理由とか Cucumber との軽い比較ぐらいですね。

経緯

Methods & Tools の編集者(なのかな)の Franco さんから「Turnip の紹介記事とか書いてみませんか」みたいなメールが来ました。 正直なところ Methods & Tools の存在をこの時知りました。1999年から続いてる老舗なんですね…

ちなみに Turnip 作者である Jonas さんに「この件どうしましょうかー」って聞いたところ

jonas「書いていいよ」
gongo「お、おう」

という感じで。まあせっかくの機会だしなってことで、私がメインで、英語のおかしい点を jonas さんに見てもらう、という体制で始めました。

できた

この後 jonas さんにめっちゃくちゃ添削してもらった

終わり

今回はただの紹介記事だったのでそれほどの量でもなく、英語も難しい言い回しとかは無かったのですが、 それでもなかなか書けず時間がかかってしまいました。英語すごい。

そんなわけでよろしくお願い致します。

「1時間後に OSX をスリープする」をセットするコマンド

$ sudo pmset schedule sleep "$(date -v +'1H' +'%D %T')"

OSX 10.11 El Capitan および OSX 10.10 Yosemite で動作確認しています。おそらくそれ以下のバージョンでも動くやつは動くと思います。多分。

経緯

私は就寝する時に Mac mini で音楽を鳴らしながら床に就くのですが、つけっぱなしなのもあれなので、毎晩寝る直前に

  1. システム環境設定
  2. 省エネルギー
  3. スケジュール

を経て*1、「今は0時だから、1時にスリープするようにセットして…と…」みたいな感じで設定しています。 だいたい寝る時間は一定なのですが、夜更かしするなどしてスリープ時刻を過ぎてから寝ることもしばしばなので そういう時は上記の設定を毎回行っています。

正直めんどいのでコマンドラインでぱぱっとできないかなと調べてみました。

pmset

遅ればせながら pmset というコマンドの存在を知りました。

スリープモードの変更(hibernateとか)等もできるらしいのですが、今回使うのは pmset schedule です。

pmset schedule

schedule サブコマンドでは引数として

  • sleep
  • wake
  • poweron
  • shutdown
  • wakeorpoweron

これらの type と時刻を受けとります。例えば

$ sudo pmset shceudle wake "07/04/16 20:00:00"

とすれば「2016年7月4日の午後8時 にマシンをスリープから復帰させろ(wake)」になります。便利。

「1時間後」の時刻を取得する

おなじみの date コマンドを使います。

pmset schedule が許容する時刻のフォーマットは MM/dd/yy HH:mm:ss なので

$ date -v +1H +'%D %T'

こうなります *2

最終的に

組合せると、冒頭の

$ sudo pmset schedule sleep "$(date -v +'1H' +'%D %T')"

になります。お疲れ様でした。

余談ですが

しっかり登録されてるかを確認しましょう。

$ date
Wed Apr 20 09:51:24 JST 2016

$ sudo pmset schedule sleep "$(date -v +'1H' +'%D %T')"

$ pmset -g sched
Scheduled power events:
 [0]  sleep at 04/20/16 10:51:27

OK

まとめ

眠い

*1:https://support.apple.com/kb/PH18583

*2:OSX標準の date は BSD date なので、時刻計算のオプションが GNU date と違う。GNU date だと -d '1 hours' みたいな感じ

Turnip 2.1.0 リリースしました

turnip

Release Version 2.1.0 · jnicklas/turnip

Ruby のサポートバージョンポリシー変更

先月24日に Ruby 2.0 が EOL を迎えたということで、それに合わせて Turnip も今後は Ruby 2.1 以上をサポートすることにしました。 Ruby 2.0 お疲れ様でした。Ruby 1.9.3 や Ruby 2.0 で世界はいろいろ動いた気がします。

See: Ruby 2.0.0 および Ruby 2.1 の今後について

カスタムプレースホルダーでデフォルトの値を返す DSL の追加

@ さんからの Pull Request を経て最終的にこうなりました。

placeholder :user_name do
  match /admin: (.*)/ do |user_name|
    User.find_by!(name: user_name, role: :admin)
  end

  default do |user_name|
    User.find_by!(name: user_name)
  end
end

こんなプレースホルダが定義されている時

When admin: gongo がログイン
When wataru がログイン

みたいなステップを書いていると、前者の step ブロックには name = gongo and role = admin を満たす User インスタンスが、 後者には name = wataru を満たす User インスタンスが渡されるという感じです。

まとめ

Ruby 2.0 の EOL と新 DSL の追加ということで 2.0.x から 2.1.0 に上げました。よろしくお願い致します。

Ruby 2.x 環境で magic comment 無しファイルを開くと flycheck で "invalid multibyte char (us-ascii)" と言われる場合

emacs ruby

結論から言うと

(setenv "LC_ALL" "ja_JP.UTF-8")

;; or

(setenv "LANG" "ja_JP.UTF-8")

を試しましょう

経緯

こんなファイルのことです。

p 'あいうえお'

f:id:gongoZ:20160210091618p:plain

メッセージ自体はお馴染のものなので

といった情報がググるとすぐ出てきます。確かに ↑ のファイルに # coding: utf-8 を追加したらメッセージは出なくなりました。

ですが私が使っているマシンにはもはや Ruby 1.9 は入っていないので、このメッセージが出るのがおかしい。ってことで謎は深まっておりました。

原因

そんなときに @ さんより

といったアドバイスを頂いたので

(setenv "LC_ALL" "ja_JP.UTF-8")

を実行してみると

f:id:gongoZ:20160210092451g:plain

消えました。やったぜ。@ さんありがとうございました!

まとめ

以前から https://github.com/purcell/exec-path-from-shell は使っていて GOPATH とか RBENV_ROOT は取り込むようにしていましたが、 LC_ALL とかのことは忘れていました。要注意。