blog.risouf.net

alacritty で Emacs を使う

alacritty というターミナルエミュレータが速いという話を聞き、仕事が一段落したタイミングで導入してみた。

alacritty

まだまだ実装段階というかリッチな機能が不足していてつらいという話を聞いたりもするが(タブで複数開けないとか)、個人的には今のところ使っていくのに最低限必要なものは揃ってくれていると感じた。

僕が使っていくのに困らない大きな要因は tmux を愛用しているから、というのが大きそうではある。
tmux でタブや分割に相当する機能が確立されているため、ターミナルエミュレータ側での実装を必要としていない。

alacritty で Emacs を使う

本題。

Mac OS 上で試してみたところ、いくつかの問題が起きた。

Meta キーが反応しない

Mac OS で Emacs を使うにあたっては option/alt キーを Meta として扱うように設定しているが、これまで使っていた iTerm2 では設定できたこれが alacritty では今はまだ設定できない。

これにどう対応するかというと、以下のような設定を追加する。 以下の設定は Set option as meta in MacOS · Issue #62 · jwilm/alacritty から拝借した。

key_bindings:
  # meta
  - { key: A,         mods: Alt,       chars: "\x1ba"                       }
  - { key: B,         mods: Alt,       chars: "\x1bb"                       }
  - { key: C,         mods: Alt,       chars: "\x1bc"                       }
  - { key: D,         mods: Alt,       chars: "\x1bd"                       }
  - { key: E,         mods: Alt,       chars: "\x1be"                       }
  - { key: F,         mods: Alt,       chars: "\x1bf"                       }
  - { key: G,         mods: Alt,       chars: "\x1bg"                       }
  - { key: H,         mods: Alt,       chars: "\x1bh"                       }
  - { key: I,         mods: Alt,       chars: "\x1bi"                       }
  - { key: J,         mods: Alt,       chars: "\x1bj"                       }
  - { key: K,         mods: Alt,       chars: "\x1bk"                       }
  - { key: L,         mods: Alt,       chars: "\x1bl"                       }
  - { key: M,         mods: Alt,       chars: "\x1bm"                       }
  - { key: N,         mods: Alt,       chars: "\x1bn"                       }
  - { key: O,         mods: Alt,       chars: "\x1bo"                       }
  - { key: P,         mods: Alt,       chars: "\x1bp"                       }
  - { key: Q,         mods: Alt,       chars: "\x1bq"                       }
  - { key: R,         mods: Alt,       chars: "\x1br"                       }
  - { key: S,         mods: Alt,       chars: "\x1bs"                       }
  - { key: T,         mods: Alt,       chars: "\x1bt"                       }
  - { key: U,         mods: Alt,       chars: "\x1bu"                       }
  - { key: V,         mods: Alt,       chars: "\x1bv"                       }
  - { key: W,         mods: Alt,       chars: "\x1bw"                       }
  - { key: X,         mods: Alt,       chars: "\x1bx"                       }
  - { key: Y,         mods: Alt,       chars: "\x1by"                       }
  - { key: Z,         mods: Alt,       chars: "\x1bz"                       }
  - { key: A,         mods: Alt|Shift, chars: "\x1bA"                       }
  - { key: B,         mods: Alt|Shift, chars: "\x1bB"                       }
  - { key: C,         mods: Alt|Shift, chars: "\x1bC"                       }
  - { key: D,         mods: Alt|Shift, chars: "\x1bD"                       }
  - { key: E,         mods: Alt|Shift, chars: "\x1bE"                       }
  - { key: F,         mods: Alt|Shift, chars: "\x1bF"                       }
  - { key: G,         mods: Alt|Shift, chars: "\x1bG"                       }
  - { key: H,         mods: Alt|Shift, chars: "\x1bH"                       }
  - { key: I,         mods: Alt|Shift, chars: "\x1bI"                       }
  - { key: J,         mods: Alt|Shift, chars: "\x1bJ"                       }
  - { key: K,         mods: Alt|Shift, chars: "\x1bK"                       }
  - { key: L,         mods: Alt|Shift, chars: "\x1bL"                       }
  - { key: M,         mods: Alt|Shift, chars: "\x1bM"                       }
  - { key: N,         mods: Alt|Shift, chars: "\x1bN"                       }
  - { key: O,         mods: Alt|Shift, chars: "\x1bO"                       }
  - { key: P,         mods: Alt|Shift, chars: "\x1bP"                       }
  - { key: Q,         mods: Alt|Shift, chars: "\x1bQ"                       }
  - { key: R,         mods: Alt|Shift, chars: "\x1bR"                       }
  - { key: S,         mods: Alt|Shift, chars: "\x1bS"                       }
  - { key: T,         mods: Alt|Shift, chars: "\x1bT"                       }
  - { key: U,         mods: Alt|Shift, chars: "\x1bU"                       }
  - { key: V,         mods: Alt|Shift, chars: "\x1bV"                       }
  - { key: W,         mods: Alt|Shift, chars: "\x1bW"                       }
  - { key: X,         mods: Alt|Shift, chars: "\x1bX"                       }
  - { key: Y,         mods: Alt|Shift, chars: "\x1bY"                       }
  - { key: Z,         mods: Alt|Shift, chars: "\x1bZ"                       }
  - { key: Key1,      mods: Alt,       chars: "\x1b1"                       }
  - { key: Key2,      mods: Alt,       chars: "\x1b2"                       }
  - { key: Key3,      mods: Alt,       chars: "\x1b3"                       }
  - { key: Key4,      mods: Alt,       chars: "\x1b4"                       }
  - { key: Key5,      mods: Alt,       chars: "\x1b5"                       }
  - { key: Key6,      mods: Alt,       chars: "\x1b6"                       }
  - { key: Key7,      mods: Alt,       chars: "\x1b7"                       }
  - { key: Key8,      mods: Alt,       chars: "\x1b8"                       }
  - { key: Key9,      mods: Alt,       chars: "\x1b9"                       }
  - { key: Key0,      mods: Alt,       chars: "\x1b0"                       }
  - { key: Space,     mods: Control,   chars: "\x00"                        } # Ctrl + Space
  - { key: Grave,     mods: Alt,       chars: "\x1b`"                       } # Alt + `
  - { key: Grave,     mods: Alt|Shift, chars: "\x1b~"                       } # Alt + ~
  - { key: Period,    mods: Alt,       chars: "\x1b."                       } # Alt + .
  - { key: Key8,      mods: Alt|Shift, chars: "\x1b*"                       } # Alt + *
  - { key: Key3,      mods: Alt|Shift, chars: "\x1b#"                       } # Alt + #
  - { key: Period,    mods: Alt|Shift, chars: "\x1b>"                       } # Alt + >
  - { key: Comma,     mods: Alt|Shift, chars: "\x1b<"                       } # Alt + <
  - { key: Minus,     mods: Alt|Shift, chars: "\x1b_"                       } # Alt + _
  - { key: Key5,      mods: Alt|Shift, chars: "\x1b%"                       } # Alt + %
  - { key: Key6,      mods: Alt|Shift, chars: "\x1b^"                       } # Alt + ^
  - { key: Backslash, mods: Alt,       chars: "\x1b\\"                      } # Alt + \
  - { key: Backslash, mods: Alt|Shift, chars: "\x1b|"                       } # Alt + |

Ctrl/Alt + 記号の一部が反応しない

上記の他に、僕が Emacs 上で設定しているホットキーが一部反応しなかったのでそれについても設定を加えている。

  - { key: Semicolon, mods: Control,   chars: "\x18\x40\x63\x3b"            } # Ctrl + ;
  - { key: Semicolon, mods: Alt,       chars: "\x1b;"                       } # Alt + ;
  - { key: Slash,     mods: Control,   chars: "\x1f"                        } # Ctrl + /
  - { key: Apostrophe, mods: Control,  chars: "\x18\x40\x63\x27"            } # Ctrl + '

それぞれ helm-mini, comment-dwim-2, undo-tree-undo, redo を割り当てていたが、この設定を追加しておかないと反応しなかった。

その他のカスタマイズ

本題は以上だが、その他にいくつか不便を解消するために行った設定があるので残しておく。

日本語を表示するためのフォントの設定

これまで Menlo for Powerline を使っていたが、 El Capitan で alacritty を動かすとマルチバイト文字の右半分が欠けてしまった。
これについては Cica というフォントに切り替えることで解消した。
ちなみに High Sierra ではこの問題には遭遇しなかった。

locale を自動判定してもらえない

シェルの起動時に locale が自動判定されず Powerline の設定を読み込むタイミングで Python がエラーを吐いてしまった。
これはうまく設定する方法がなさそうだったので、ひとまず rc ファイルに以下の1行を加えて事なきを得た。

export LANG="ja_JP.UTF-8"

ちなみにこの問題は日本語の表示とは逆に High Sierra では起きたが El Capitan では起きなかった(ただしこれについてはそれぞれの環境での設定の違いが原因であって OS のバージョンの問題ではなさそうな気がしている)。

2019-05-13 23:33:09.734916 JST

Tweet $B$3$N%(%s%H%j!<$r$O$F$J%V%C%/%^!<%/$KDI2C(B

buiderscon tokyo 2018 (の記録)

参加した理由

友人からのお誘い。
「会場、家から近いでしょう?」
なるほどたしかに。

サポーターチケット

なんでサポーターチケットにしたのかちょっと記憶が曖昧だけれど、特に後悔はしていない。
ノベルティについては、電子名札はそんなに期待してなくて、サコッシュ良さそう〜という気持ちだった。
けど、会場で実物に触れてみると電子名札が想像以上に良くてワクワクするアイテムだったので、サポーターチケットで正解でしたね。

聞いてきた話

IoT開発の闇

本当に闇だった。
個人的にはこれがベストトークなんだけれど、投票することもできないし、この感情を当日聞けなかった人と共有することもできない。

Electronによるアプリケーション開発事情2018

個人的に共感しまくった話だった。
今年に入って Electron でアプリを作り始めた、というところがタイミング的にバッチリ自分と重なってて、あちこちで「わかる〜」って気持ちになった。
しかし僕と違って、他の人も使うことをちゃんと考えて開発してて偉い……。

パスワードレスなユーザー認証時代を迎えるためにサービス開発者がしなければならないこと

パスワード早く滅びて、と思いつつもそういう世界の実現って大変だろうなあ、と思っていたことを実際に実現しようとしている人たちの話が聞けた。
認証周りは考えることが多いし、慎重に一歩ずつ進んでいってくれてるだけでもありがたい。

JavaCardの世界

うーん、これはなかなか……。
10年前〜20年前を彷彿とさせる話が大量に出てきて、これが2018年の話です、と言われてもにわかには信じがたい、みたいな内容だった。
(自分は当事者ではないので他人事として楽しめたけれど)

遠いようで身近なサウンドエンジニアリング

普段の自分には関わりのない世界の話。
とはいえ、学術的な部分は当然知っていることで、そこから実際に曲として完成させていくまでにどのようなことをやっているのか、自分の知識と現場での現実の結びついてないところが知れてよかった。
自分の仕事に関係なさそうだから他のを優先するつもりだったけど、行って正解だった。

感想

builderscon 、安定感というか安心感がある。
一番緊張せずに参加できるカンファレンスだと思う。 最近、事情があってあまりカンファレンスに行かないようにしていたけれど、行ってみるとやはり楽しいので今度はもっと早い段階から参加を決めて準備できるようにしたい。

2018-09-11 00:28:33.974911 JST

Tweet $B$3$N%(%s%H%j!<$r$O$F$J%V%C%/%^!<%/$KDI2C(B

HHKB を漂白した

3ヶ月ほど前のこと。

諸事情で、押入れにしまっていた HHKB Type-S 白を約2年ぶりに出すことになった。
出してみると、(暗所に保存していたのに)かなり日焼けしており、そのまま使うには抵抗のある状況だった。
これは叙述的な問題で、実際には日焼けしたのではなく黄ばんでいる、といった方が正しいのかもしれない。
(今回、原因とか回避方法とかは調べていない)

漂白前

漂白前

白さを取り戻す方法についてはググるといろいろ出てくるのでここでは手順を詳細に記したりはしない。
簡単に言うと、バラして漂白剤につけて1週間くらい日光(紫外線)に当てると白くなる、という感じ。

漂白後

漂白後

無刻印だったので、バラしてキートップを洗浄したあと、戻すのに若干手間取った。
外側のキーは横幅が違ったり同じだったりするので微妙にややこしいし、内側のキーは列ごとに角度(傾斜)が異なるので、どの列かは容易に判断できるが、そこから先の判断材料がない。
バラす前と全く同じではないけれど、同じ形のものがちゃんと入るように試行錯誤して、動作を確認したところ、問題なく動いたので、これでいいか、という感じになった。

2018-06-24 22:27:34.381084 JST

Tweet $B$3$N%(%s%H%j!<$r$O$F$J%V%C%/%^!<%/$KDI2C(B

Qiita Team Viewer というアプリを作った

インターネットで生きていると、様々なサービスのアカウントが増えて管理が大変になったりすると思います。あるいはアカウント自体は1つだけど紐づくグループが増えるパターンもあります。

たとえば Google アカウント(G Suite アカウント)とか GitHub の organization とか Slack の team とか Qiita:Team とか、仕事してたり OSS 活動してたりするとうっかり増えちゃいますよね。

本題とは一切関係ないけど、僕はこの現象をアカウント・マルティプライズ(account multiplies)と呼んでいます。

複数の所属している Qiita:Team の記事を一覧で見たい

今回は Qiita:Team の話です。紆余曲折あって所属するチームが複数に増えてしまった僕は、わざわざチームごとにブラウザのタブを開いて個別に閲覧することにつらさを感じました。

この手の同一サービス複数アカウントについては、サービスの主旨によって対応が変わるところですが、個人的には Qiita:Team の記事自体は複数のチームのものが混ざって一覧表示されても困らないなと思ったので、そういう使い方ができるアプリを作ることにしました。

Qiita Team Viewer

作ったものはここから落とせます。

Releases · risou/qiita-team-viewer

使い方は簡単で、起動して(Gatekeeper 周りで警告でるかもしれません) Qiita のアカウントでログインしてアプリの連携を許可してもらえば、アカウントに紐づく Qiita:Team の記事の一覧が画面左側に出てきます。記事を選ぶと画面右側に記事の内容およびコメントが表示されます(その他は README をご覧ください)。

Qiita Team Viewer v0.1.0 では以下のことができます。

Qiita Team Viewer v0.1.0 ではできないけど、今後のバージョンで以下のことができるようになる予定です(実装の難易度やアプリの方向性によって変更される可能性があります)。

一方で以下のことは今後もできるようにならない予定です。

これは主に、複数ある Qiita:Team で投稿先のチームを間違える危険を避けるためです。

Qiita Team Viewer の技術選定

ここからは素人がアプリを開発する上で考えたことを記録として残しておこうと思います。

今回アプリを作るにあたって最初に考えたのは、 兼ねてより興味のあった Electron を使ってみよう ということです。
ネイティブアプリがよかったのと、後々 Windows, Linux にも対応したかったということでちょうど良さそうに思いました。 NW.js などの類似の選択肢もありましたが、初めて触るジャンルということもあり現状で一番情報が多そうな Electron にしました。

最初は Electron の簡単なアプリをチュートリアルなどを参考に作り、そのアプリ上で Qiita の API を実行して結果を得るだけのプログラムを書きました。そこから、実際にアプリを作っていく上で必要なことを考えました。

あとは「node module に electron-vue ってのがあるのかー」みたいな雑な感じで使ってみたり。

専門職の人たちからすれば最適には程遠い選択だと思いますが、素人の手遊びとしては思ったより順調に試行錯誤しつつ実装が進み、なんとか現状まで持ってこれました。

新しく触れた技術要素

Electron を使うことを決めた時点で避けられない道だったのですが、ひとつひとつのことを実現するのに新しい技術要素に触れていくことになって新鮮な経験でした。実際に触れた新しいものは以下のとおり。

どれもこれも全然知らないところからはじめて v0.1.0 をリリースするまで約1ヶ月。バッドプラクティスと言われるような使い方をしている箇所もあるかもしれないけど、なんとか使えるレベルまで持ってこれました。わからないこと多すぎてかなり勉強になった気がする(それをいちいち書き留めておく余裕は残念ながらなかったけれど)。

その他感想とか

できればテストも書きたかったけれど、特に仕事を休んだりもせず空いた時間で進めるには、試行錯誤しながら動くものを作るので精一杯でした。まあ、テスト自体は後からでも追加できるのでモチベーションが続けば。

今後はドッグフーディングしつつ、検索機能とか追加していければなあと思ってます。けど、他にもやるべきことがあるので、ここから先はゆっくり進めていこうかと。  あと、今回の開発で(僕みたいな人間にとっての) CSS フレームワークの強力さを思い知ったので、ブログのデザインとかアップデートしていきたいですね。

Qiita Team Viewer を作るにあたって参考にしたサイト

2018-04-16 22:43:19.346896 JST

Tweet $B$3$N%(%s%H%j!<$r$O$F$J%V%C%/%^!<%/$KDI2C(B

GitHub で assign されている Issue の件数を Slack の custom_status に表示する

元ネタというか、インスパイアされたのは以下の記事。

「おまえは今までレビューしたプルリクの数をおぼえているのか?」 - pixiv inside

@kana1 さんの上記の記事では、依頼されているレビューの件数を表示することで、同僚にどれくらい忙しいか(レビュータスクが溜まっているか)を知ってもらって、レビュー依頼が集中しないようにしている。

Slack の custom_status は前々から有効活用できそうだなーと思っていたけど、このアイデアはとても良いものだと思ったので自分に合う形にカスタマイズしてみた。

僕の今の働き方だと、

という感じなので、レビューの数ではなく Issue の数を可視化することにした。

どこでどうやって動かすか

@kana1 さんの用途では、 Slack のチャンネルを監視して custom_status に対して get/set を行っている。
僕の用途ではチャンネルの監視は必要なくて、リアルタイムじゃなくて良いので定期的に Issue の件数を数えてもらえればそれで良い。

さらに、これだけのためにサーバを用意するのとかはとても面倒だったので Google Apps Script で全部やることにした。
GAS では一定時間ごとに実行するトリガーを設定できるため、定期実行は GAS に任せることができる。

GitHub から assigned Issue の件数を取得する

僕は複数の organization に所属していて、それぞれに対応する Slack Team に所属しているので、「ある organization のリポジトリに紐づく assigned Issues の件数を、対応する Slack Team の custom_status に設定」することが目標になる。

GitHub の API では以下の URL で目的の情報が取得できる。

https://api.github.com/orgs/{:org}/issues

特にクエリパラメータを設定しなくても、初期状態で self-assigned かつ open な Issue のリストが取れるためこれで良い。

当然 API を叩くために token が必要。 scope はそんなに広くなくてよくて、 repo だけチェックしておけばよい。

GAS で API を叩く際には UrlFetchApp.fetch を使えば良いらしい(このあたり node.js のモジュールとかそのまま使えないのかな?)。

Slack の custom_status を設定する

assigned Issues の件数がとれたら、件数に合わせて custom_status を設定したい。

基本方針は @kana1 さんのものと同じく10件までは件数を表示して、10件を超えたら溢れている感のある絵文字を表示すれば良さそう。

Slack の API はチームごとに token が取れるので、 GitHub organization に対応するチームの token を用意しておく。
Slack の API はクエリパラメータに token とセットしたい内容を与えてリクエストを送れば良い。
今回のケースでは以下のような URL を叩くことになる。

https://slack.com/api/users.profile.set?token={:token}&profile={:data}

data の部分にはセットしたい値を URL エンコードされた JSON を与える。以下のような形になる。

{
    status_emoji: emoji,
    status_text: text
}

定期的に実行する

GAS はトリガーを設定できる。僕の場合は15分ごとに実行するように設定している。

これだけで15分毎に assigned Issues の件数を Slack の custom_status に設定できる。

2018-04-07 00:13:53.002221 JST

Tweet $B$3$N%(%s%H%j!<$r$O$F$J%V%C%/%^!<%/$KDI2C(B