のらねこの気まま暮らし

Perlについてとか、創作についてとか、発展途上の自分と向き合う記録。

Macを外部ディスプレイにつなげた時のWindow配置を記憶したい!

背景

最近の僕は、GoogleChromeのタブを38個とか開いているようです。

Tabs OutlinerSpaces という拡張機能を併用して、 たっくさんあるタブを用途やカテゴリ毎にwindowに分割しているんです。

まあ、ぞれでもWindowは5,6個できるんですけど。

Tabs OutlinerとSpacesのおかげで管理は大分楽になったんですが、困ったことが一つありまして。

問題

普段はMac Bookを外部ディスプレイにつなげて普段作業しているんですよね。Mac Bookのディスプレイと外部ディスプレイ二枚。

会議や相談なんかあれば、外部ディスプレイの接続切ってMac Bookを持っていくわけです。 そして話し終えたら席に戻ってきて外部ディスプレイに接続する。

画面にでてくるのは、SlackやiTerm、そして5,6個重なったGoogle Chrome

微妙に位置を調整して、ワンクリックで目的のWindowを開けるようにしていたGoogle Chromeの位置を戻すのがもう、面倒でしかたないったらありゃしない。

さすがに、疲れました。

調査

そんなわけで、頼れるGoogle先生に聞いてみたんです。できないかって。

参考になったのは、以下の記事でした。

forget-me-not は残念ながらアクセス出来ませんでした。まあ2012年の記事だし。 代わりにStay の方を見てみました。

AppStoreで\1,800だったので、即買。

検証

先ほどの StayさえあればもうMBAをサブディスプレイに繋げるのは怖くない を見ながら設定してみました。

2,3回試しました。繋いで、はずして。

Google ChromeのWindow7枚とiTermとSlackだけ個別にstoreしてみました。 Mac Bookを開いたままコネクタを外すと、まあ位置画面に収まります。 そのまま繋げ直してみると、「Restoring windows」と表示されてガチャガチャwindowのサイズや配置が変わっていきます。

結論

なにこれ便利...!

お試しあれ

参考

2015年の振り返り

新年早々いろいろあって振り返ってる余裕が無かったので、それっぽいのをハリボテで。

2015年に書いた記事

当ブログ

mizuki-r.hatenablog.com

8記事!少ない!!

Qiita

qiita.com

qiita.com

2記事!少ない!!

2015年に発表したトーク(public)

www.slideshare.net

www.slideshare.net

www.slideshare.net

www.slideshare.net

4回!ま、まあ...

振り返り

JavaScript一色だなぁ...

ブラウザサイドからNodeJSまで。 ただ、使っているツールや関心の範囲はこの一年でだいぶかわってきたのかなと思う。

フロントエンドツールの開拓、WAFのアーキテクチャ設計、それに関連する各種ライブラリの選定等など、外部モジュールを触るのが多い一年だった。 MVCよくわからんっていう時期から、FluxやReduxを通じてアプリのアーキテクチャを考えていく中で、 単一のライブラリに頼るのも、複数を組み合わせるのもそれなりに模索が必要だと感じているのが年末だった。

2016年の抱負

ツールは揃ってきているけど、いま欲しいものが現状ない。 そういう「何がほしいのか」という部分を自分が適切に理解し、それに即したライブラリを模索・制作していきたいなとは思っている。

年が明けてから、FluxやReduxによって手放そうとしたMVC,DDDを取り戻す方向性を考えている。 技術的にModelとはどういうものか、というより、Model的な考え方をFlux上に載せつつ、効率的に開発できないかと考えている最近。

僕はもともとMVCについての理解が浅かったので、改めて勉強しようかなと思う。

余談

新年早々部屋が半分水浸しになって大変大変つらかったけど、この先は楽しい一年にしていこうとおもったのでした

#gotandajs でトークしてきました

ブログを書くまでがgotandajsだ!ってことで。

gotandajs

五反田や沖縄で JavaScript の勉強する(conpassから引用)会で、AngularJSにFluxとRiotJSを導入したというトークをしてきました。

gotandajs.connpass.com

発表資料

発表について

不足してたなっていう状況を幾つか補足。

  • モバイル中心のウェブアプリ(ゲーム)
  • JavaScriptを触る人は基本的に僕一人
  • 実際にFluxを導入し始めて発表内容の形に持ってくるまで3,4ヶ月くらいかけてる
  • injectorをRiotJSから参照できるようにするのってどうなの?
    • 僕一人だから許容してたけど複数人で触るとリスクのほうが高そうなので、ぶっちゃけあんまオススメしない

全体を通して

  • 思っていたよりガチで濃ゆい人が集まっていた -- flux, angular, riotを知ってる人が思いの外多くいた -- 他の人のトークも結構濃ゆい話題だった
  • Mithrilやreduxといった最近気になっているけど本気で触る余裕がない~なモノとかの話題もあって嬉しい -- トレンドをみんな抑えてる感じで、初回なのにレベル高い

懇親会ネタ

ぱっと思い出せたネタを書き出してみる

  • みんな結構、FluxとかReduxとかの設計面で悩んでいる
    • Fluxやってると全体でstateを管理したいけど、Reduxみたいに全部管理するのはちょっと
    • 程よくComponentとStoreで分散させたい
  • ルーターとかどうしてる?
    • ReactRouterとか学習コスト高すぎ
    • redux-routerは良さそう?
  • 最近のライブラリだと何を選ぶ?
    • 僕なら初期開発の楽さでAngular
    • Vueはすべてがそこそこ良いので安定
    • Reactはなんかいろいろめんどくさい、が思想はいい
    • Mithrilはmsx-loaderが壊れてて...
    • などなど...
  • テストどうしてる?
    • reduxはサンプルをベースに
    • fluxとかでロジックはテストし易い
    • Reactはテストしやすい...んだろうけど...「「...」」
    • Viewのテストのコストが高すぎる
    • E2Eでテストしたほうがカバーする範囲広くてリファクタリングとかしやすそう
    • 「何」をテストしたいのか? 「ユーザに届ける価値」「どうやってテストすればいいんだー!」
  • DIは料理番組
    • 下ごしらえ済みの素材を受け取って料理にするイメージ
    • だからinjectorをRiotで受け取るのどーなん?って思った
  • 静岡アツい
  • 次回はG社で

設計の話からビルドシステムの話、他の言語やコミュニティの話、かなり幅広く盛り上がっていた印象

感想

とても楽しい会だった。

なんかみんな似たようなことで悩んでいたり、試そうと思っていたことを試したっていうFBもらえたり、なかなかいい知見を得られたと思う。 コンポーネントのあり方とか、Fluxの設計とかはまだまだ議論の余地もあるだろうし、こういう機会があるのはありがたい。

新しいライブラリも短いサイクルでバンバンでてくるようなJavaScript界隈においてそれぞれが試して意見を交換できる会は貴重だ。

みんなのレベル感も結構近いのでは?と思うくらい懇親会では盛り上がっていたし、本当に楽しかった。

というわけで、大変満足でした。次回も期待します。

お疲れ様でした!

MINILA AIR US67 を購入したのでMac用にカスタマイズしたメモ

商品

Majestouch MINILA Air US67キー 茶軸

設定

  • caps lockctrl
    • 鉄板
  • [修飾キー設定] cmdoption
    • Mac Book Airの配置に合わせてみた
  • [修飾キー設定] caps lockcmd
    • caps lockなんて要らん
    • windows時代のctrl + v|cの癖が抜けなくてな...
  • [ショートカット] 入力ソース/前の入力ソースを選択 cmd + ESC
    • 左手だけで切り替えたいけど大きくブラインドタッチの状態から手を動かしたくないので

f:id:ry_mizuki:20150930090618p:plainf:id:ry_mizuki:20150930090625p:plainf:id:ry_mizuki:20150930090635p:plain

所感など

  • ctrl + alt + fn で接続設定出来るみたいなことが書いてあったけど、結局 connect ボタン使わないと初期設定できなかった
  • ESC~ するかも
  • キーの差し替えできるの便利
  • 押し心地と触り心地が以前使ってたMajestouchと若干違くて新鮮な心地よさがある

指定期間でDOMを出し分けてくれるangular-periodを公開しました

angular-periodとは

AngularJS のDirectiveで、期間を指定するとその 期間前期間中期間後でDOMの表示を切り替えてるようにするものです。

例えば、なんかの応募とかで、以下の様なHTMLをテンプレートエンジンやJavaScriptなどを使って出し分けることがある時に便利です。

angularJSを使った一番お手軽なケースとしてはこんなかんじでしょうか。

angular.module("campaign", [])
  .controller('CampaignCtrl", function () {
    this.now   = new Date().getTime();
    this.start = new Date('2015-08-01T00:00:00').getTime();
    this.end   = new Date('2015-08-31T23:59:59').getTime();
  });
<div class="campaign" ng-controller="Campaign as campaign">
  <!-- 期間前の表示 -->
  <div class="form is-previous" ng-if="campaign.now < campaign.start">
    <p>○月☓日から応募できます</p>
  <!-- 期間中の表示 -->
  <form class="form" ng-if="start <= campaign.now && campaign.now <= campaign.end">
    <button type="submit">応募する!</button>
  </form>
  <!-- 期間後の表示 -->
  <div class="form is-after" ng-if"campaign.end < campaign.now">
    <p>応募は締め切りました</p>
  </div>
</div>

angular-periodを使えば、以下のように書けます。

angular.module('campaign', ['angularPeriod']);
<div class="campaign" ng-period
  ng-period-start="'2015-08-01T00:00:00'"
  ng-period-end  ="'2015-08-31T23:59:59'">
  <!-- 期間前の表示 -->
  <div class="form is-previous" ng-period-when="previous">
    <p>○月☓日から応募できます</p>
  <!-- 期間中の表示 -->
  <form class="form" ng-period-when="during>
    <button type="submit">応募する!</button>
  </form>
  <!-- 期間後の表示 -->
  <div class="form is-after" ng-period-when="after">
    <p>応募は締め切りました</p>
  </div>
</div>

開始と終了を渡すと、その期間の前、中、後のHTMLを選択してDOM Treeに組み込みます。 最も単純なケースではコントローラーすら不要なので、ロジックやテストを大幅に削減できます。

また、angular-periodはリアルタイムな反映及び、setTimeoutの上限値である32bit intを超える値もサポートできるようにしているので、長期にわたる期間であってもある程度は許容されます。

インストール

npm, bowerともに公開しているので必要な方を利用してください。

npm install angular-period
bower install angular-period

日付の指定とパースについて

利用可能な値

上記には文字フォーマットを用いた例を記載しました。 ただ、実際にプログラムする上で文字列だけでは様々な不便なことがあるでしょう。

ngPeriodは Date オブジェクトに変換可能な値をサポートしています。

具体的には、 - Dateパース可能な文字列 - Date オブジェクト - momentjsなどのDateオブジェクトに渡せるオブジェクト

先ほどの例で、例えばmomentjsを使う場合は以下の様に書けます。

angular.module('campaign', ['angularPeriod'])
  .controller('CampaignCtrl", function () {
    this.start = moment('2015-08-01 00:00:00');
    this.end   = moment('2015-08-31 23:59:59');
  });
<body  ng-controller="Campaign as campaign">
<div class="campaign" ng-period
  ng-period-start="campaign.start'"
  ng-period-end  ="campaign.end">
  <!-- 期間前の表示 -->
  <div class="form is-previous" ng-period-when="previous">
    <p>○月☓日から応募できます</p>
  <!-- 期間中の表示 -->
  <form class="form" ng-period-when="during>
    <button type="submit">応募する!</button>
  </form>
  <!-- 期間後の表示 -->
  <div class="form is-after" ng-period-when="after">
    <p>応募は締め切りました</p>
  </div>
</div>
</body>

至ってシンプル。

パースできない値

Dateオブジェクトでパース可能な値はブラウザによって異なります。 パースできない値を渡すと、Dateは Invalid Date というオブジェクトを返すので、 それをそのままDateとして扱おうとすると、Nanだったり不適切な値になりえます。

困るケースでは、ChromeSafariで利用可能なDateのフォーマットが異なるという点です。

ChromeYYYY-MM-DD HH:mm:ssという値をサポートしていますが、SafariではInvalid Dateが返ってきます。 これは失念すると非常に気づきにくくリスキーで、常にChromeSafariでの動作確認を要求されるため大変不便です。

angular-periodでは、Invalid Date になるような値を渡された場合その時点でErrorオブジェクトをthrowするようにはしています。 JavaScriptのDateオブジェクトは非常に複雑かつブラウザ間で挙動が違うので、それを吸収するよりは、すでに実装され安定的に運用されている他のモジュール(momentjsのような)を利用することを推奨します。

まとめ

というわけで結構便利なモジュールを書いたつもりで居るのでどうぞお試しあれ。

node-hariko にクリパラメータによってモックデータを割り振る機能を入れた

欲しかった機能をいれたかったので、 hariko を v1.1.0 に更新しました。

更新内容としては、複数のリクエストをExamplesに設定している時に、リクエストパラメータがマッチするやつを優先的にレスポンスさせるような機能を追加しました。

multipe example

API-Blueprintでは一つのアクションに複数のレスポンスを記載できます。

# GET /messages{?page}

+ Request /messages (application/json)

+ Response 200 (application/json)

    パラメータが無いときは `page=1` としてデータを返す

    + Body

             [
               /* message arrays */
             ]

+ Request /messages?page=2 (application/json)

+ Response 200 (application/json)

    + Body

             [
               /* message arrays */
             ]

+ Request /messages?page=9999 (application/json)

+ Response 200 (application/json)

    存在しないページをしたら空の配列(`[]`)を返す

    + Body

             []

モックサーバのレスポンスとの兼ね合い

複数のExampleを定義をした時、リクエストとレスポンスは一つのActionの中に配列で格納されるんだけど、drakov ではキーのマッチングで優先順位を決めてマッチングしてたけど、そんなことよりキーと値が一致したらそいつを優先的に返して欲しい。

上記の例だと

|GET /message|ひとつめ| |GET /message?page=1|ふたつめ| |GET /message?page=2|ふたつめ| |GET /message?page=9999|ふたつめ|

みたいに帰ってきて、9999にリクエストしたら空のレスポンスが帰ってこない!!みたいになる。 いくら、json-outputの機能があるとはいえ、毎回毎回書き換えるのはだるくて仕方ないし、ドキュメント上で明示しておきたい。

クエリパラメータのでマッチングして完全一致したやつを優先的に出力する

node-hariko/resource_spec.js at master · rymizuki/node-hariko · GitHub

こんな感じで。 クエリパラメータの値がMarkdown上で定義されて居て、かつ一致するものがあればそれをレスポンス、 一致するものが無かったら先頭で定義しているものをレスポンスという形にした。

|GET /message|ひとつめ| |GET /message?page=1|ひとつめ| |GET /message?page=2|ふたつめ| |GET /message?page=9999|みっつめ|

を返してくれるようにした。

まとめ

  • リクエストとレスポンスを密に連携してよりデバッグしやすい環境を作りました!

todo

  • warningsをいまちゃんと出力してないので教えてあげてほしい。
    • できれば、コードを示して「どこでwarningsでているのか」をもっとわかりやすくしたい

Introduction to Hariko API Server with API-Blueprint

はい、harikoの紹介です。

harikoとは

hariko

harikoとはNodeJS製のAPI MockServerであり、APIドキュメンテーションツールであるAPI Blueprintのエコシステムです。

使い方

npmからインストールして下さい。

npm install -g hariko

harikoはAPI-Blueprintのドキュメントをベースにレスポンスを返すAPI Serverを立ち上げるので、 まずはAPI-Blueprintの仕様に沿ったmarkdownが必要です。

# GET /api/message
+ Response 200 (text/plain)

        hello world

適当に、 docs/api/message.md とかに保存します。

harikoのサーバを立ち上げます。 CLIから以下のように打ち込んで下さい。

hariko -f 'docs/api/*.md'
[INFO] Running Hariko Server ... http://localhost:3000

とshellがレスポンスしたらサーバの実行完了です。 ブラウザとかから http://localhost/api/message を叩いてみてください。 hello world と表示されるはずです。

harikoの機能たち

詳細はREADME.md とか見て下さいねって感じなんですけど、便利!!!と思って作った機能を幾つか紹介しませう。

markdownファイルの一部除外

drakovになくて地味に不便だったので入れた。 APIサーバに載せたくない一部ファイルを任意で除外するやつ。

glob形式で読み込む奴はブラックリストで弾ける用にしてほしい気持ち。

hariko -f 'docs/**/*.md'\
       --exclude 'docs/metadata.md'\
       --exclude 'docs/overview.md'

watch

ファイルを監視して、更新したらサーバを再読み込みします。 これは gaze をそのまま使ってます。gruntやgulpやらで使ってる奴。

gruntやらgulpやらのplugin書くときにいちいちreload書くの面倒でしょ?って思ったので。

hariko -f 'docs/**/*.md' -w

proxy

API-Blueprintに定義されていないパスにリクエストが飛んできたら、 指定したサーバにプロキシするオプション。

stubcellの全部のAPIリソースを一斉に移管するのが辛かったので、逐次移行できるようにしたいが為に用意したの。

application → hariko server → stubcell

hariko -f 'docs/**/*.md' --proxy 'http://localhost:8100'

output

これ!!!まじべんりだから!!!べんりだから!!!! 指定したディレクトリにレスポンスデータを吐き出すオプション。

stubcellやeasymockみたいにJSONファイルを弄れば次のレスポンスから結果が変わるという、手動アプリケーションのための仕組み。 リロードしたら全部リセットされるので注意ね♪

hariko -f 'docs/**/*.md' -o 'api/'

verbose

ログレベルをverboseに設定します。 リクエストのデータとか、その辺のデバッグに使うといいかも?

ログ周りは自前だけどそれなりに気を配って書いた気持ち。

hariko -f 'docs/**/*.md' -v

harikoを作った背景

もともと、いまいる会社でSPA (Single Page Application) の開発で、UIファーストを実践していたのですが、どうにもAPIドキュメンテーションが不足し、サーバとフロントエンドでやりとりの齟齬や過去のリソースについての確認があったり、まあ、ドキュメント欲しいよねって感じでした。(主に僕が

過去に easymock を使っていたのですが、ドキュメントの記法が独特で、メンテナンスもしばらくされていなかったので次のプロジェクトからは、 stubcell を使うようになりました。

どちらのツールも、JSONファイルをレスポンスとして返却してくれるツールだったんですが、 stubcellはJSON5に対応しているし、レスポンス内容を細かく設定できるしで好んで使っていました。

でもさすがに、JSON5だからといってjsonファイルにコメントアウトドキュメンテーションするのは読みやすいとはいえない状況...

その当時(大体2015年の2月あたり?)からAPI-Blueprintの存在は知っていて、でもドキュメントMarkdownとは言いつつも学習コスト高そうだなぁ、エコシステムもどうなんだろうなぁと思っていたのでした。

時は経ち、「やっぱりドキュメント欲しいね」ってなって、改めてAPI-Blueprintを検証したのでした。

改めて調べてみるとエコシステムはなかなか充実しており、aglio なんかは美しいドキュメントを生成してくれて素晴らしいなぁと思っていたので、ついでに drakov というAPI Mock Serverがあるそうなのでそれも一緒にインストしました。

やーべんりべんり、と思っていたのはつかの間。 drakovを使っていた上で幾つか不便な点が出てきました。

  • mdファイルを監視してサーバをリロードしてほしい
  • mdファイルを一部除外したい
  • 検証用にうん万行のJSONデータを返すようにしたい
  • 存在しないAPIはstubcellで立てたAPIにproxyしてほしい

stubcellやらeasymockやらでやっていたファイルを書き換えたら次のリクエストで反映されたJSONが帰ってくるっていう状況は実に効率的だった...

という要望が積み重なってわっと作ったのが hariko というわけです。