詩と創作・思索のひろば

ドキドキギュンギュンダイアリーです!!!

Fork me on GitHub

Go Conference 2015 Summer で Go の REPL gore の話をしてきました & gore 0.2.1

去年からこちら Go の話をしたり聞いたりする機会があればぜひ言ってみたいと思っていたのですが、このたび Go Conferecne 2015 Summer の話を聞きつけて、うまいことスピーカー枠に入ることができたので、前に作った Go の REPL(正確には違うんだけど)である motemen/gore の話をしてきました。

speakerdeck.com

gore の紹介は過去のエントリ コード補完もできる Go の REPL「gore」を作った - 詩と創作・思索のひろば にある通りです。今回はその実装に若干立ち入った紹介をしました。

この日のトークは oracle の紹介にはじまり Go の静的解析めいた発表が多く、個人的にはとてもわくわくさせられた内容でした。時間の都合もあって、gore(と go-quickfix)の面白い部分の詳細の話はぜんぜんできなかったので、また別の機会にできればなと思います。しかし今回は思いがけず Gopher 君人形をもらえて本当にうれしかった! 運営のみなさま、楽しいイベントをありがとうございます。

gore 0.2.1

また GoCon 後のテンションで、gore のバージョンをアップデートしました。主な変更は以下のとおりです。

  • -pkg=<path> フラグを追加しました。あたかも特定のパッケージの中にいるかのようにして、gore セッションを開始することができます。
% gore -pkg=github.com/motemen/gore
gore version 0.2.1  :help for help
added file /Users/motemen/dev/go/src/github.com/motemen/gore/commands.go
added file /Users/motemen/dev/go/src/github.com/motemen/gore/complete.go
added file /Users/motemen/dev/go/src/github.com/motemen/gore/liner.go
added file /Users/motemen/dev/go/src/github.com/motemen/gore/log.go
added file /Users/motemen/dev/go/src/github.com/motemen/gore/main.go
added file /Users/motemen/dev/go/src/github.com/motemen/gore/node.go
added file /Users/motemen/dev/go/src/github.com/motemen/gore/quickfix.go
added file /Users/motemen/dev/go/src/github.com/motemen/gore/terminal_unix.go
added file /Users/motemen/dev/go/src/github.com/motemen/gore/utils.go
gore> version
"0.2.1"

ここでは version 定数 が評価されています。

ちなみに -pkg の指定にはパッケージのパスのほか、ディレクトリを指定することもできます。

  • 内部で motemen/go-quickfix を使うようにしました。これは GoCon の仕込み的な変更です。何か変なことがあった場合には GitHub Issues 経由でお知らせください。
  • ある形の式を評価するとエラーが発生していた件を修正しました。(#21

アップデートは以下のようにして行えます。(開発者向けのツールなのでバイナリの配布はしていません)

% go get -u github.com/motemen/gore

Google Apps Script の TypeScript 型定義ファイルを作った

2015-12-08 追記

TypeScript の型定義ファイルリポジトリのデファクト・スタンダードであるところの DefinitelyTyped に無事 Pull Request が取り込まれました ので、今後は DefinitelyTyped のほうを参照していただければと思います!


Google Apps Script は JavaScript っぽい言語で Google 製品の自動化を行える便利環境で、定期実行や外部との HTTP 通信など、意外と痒いところに手が届く出来であり、今となっては身につけておくとよいツールのひとつと言えるでしょう。GAS の開発はおもにオンラインエディタでおこなうこととなっていて、ここで便利なのは補完が効くこと。慣れたエディタで書くこともできるけれど、補完のない環境で、多岐にわたる API をリファレンス引きながら書くというのは心細い。

そもそも JS を書くなら静的型の恩恵のある TypeScript で書きたいという人類原初からの欲求もある。TypeScript は非 TS なライブラリや環境むけに型付きの API 宣言ファイルを用意することで、静的型チェックや補完に利用できる仕組みがある(.d.ts という名前でこれらを用意する)。それならば、GAS の API の型定義ファイルを用意してしまえば、好きなエディタで GAS の補完をしながら書けるはずだと考えるのは、当然の帰結でしょう。

というわけで作ったのがこちら。

motemen/dts-google-apps-script · GitHub

使い方

入手と利用

Spreadsheet や Drive など製品ごと(正確にはリファレンスのカテゴリごと)に定義ファイルを分けているので、必要な物を参照するようにしてください。

けっこうな数のファイルがありますが、主だったところは以下でしょう。定義されるグローバル変数を併記してあります。

  • google-apps-script.base.d.ts -- Logger とか
  • google-apps-script.calendar.d.ts -- CalendarApp
  • google-apps-script.document.d.ts -- DocumentApp
  • google-apps-script.drive.d.ts -- DriveApp
  • google-apps-script.gmail.d.ts -- GmailApp
  • google-apps-script.spreadsheet.d.ts -- SpreadseetApp
  • google-apps-script.url-fetch.d.ts -- UrlFetch

とりあえず DefinitelyTyped には入っていない(テストとか用意したら Pull Request 作ります……)ので、motemen/dts-google-apps-script から入手する必要があります。これには vvakame/dtsm解説)を使うのがオススメです。たとえば Spreadsheet および UrlFetch を使いたい場合は、dtsm.json に以下のように書けばよいです。

  "dependencies": {
      "google-apps-script/google-apps-script.spreadsheet.d.ts": {
          "repo": "https://github.com/motemen/dts-google-apps-script"
      },
      "google-apps-script/google-apps-script.url-fetch.d.ts": {
          "repo": "https://github.com/motemen/dts-google-apps-script"
      }
  }

生成

イケイケドンドンで作ったのではっきり言って読みにくいコードですが、https://developers.google.com/apps-script/ にアクセスして必要な情報を取り出した JSON を生成し(spider.js)、それを d.ts に変換する(gen.js)という 2 パスの工程になっています。Byte や Integer などプリミティブっぽい型に関しては、google-apps-script.types.d.ts というファイルだけ手で用意していて、とりあえずコンパイルが通るようにはなっているのだけれど、これであっているのかはあまり分かっていない。

けっこうページがあるのでスロットリングしつつ並列アクセスしつつやるのは面倒だなと思っていたけれど、ES6 Generators を使ってみたら案外すんなり書けた。co を使って、こんな感じに書くと、MIN_WAIT ミリ秒ごとに CONCURRENCY ページずつアクセスするようにできた。GET したページのスクレイピング自体は cheerio を使いました。

function* visit (url) { ... }

co(function* () {
  ...
  while (Scraper.queue.length > 0) {
    var urls = Scraper.queue.splice(0, CONCURRENCY);
    yield Promise.all(
      urls.map((url) => co(visit(url)))
        .concat(new Promise((ok) => setTimeout(ok, MIN_WAIT)))
    );
  }
});

以上

作ってみたはいいものの、どのくらい使い物になるのかはよくわかってません。試してみてくださいね!

TypeScriptリファレンス Ver.1.0対応

TypeScriptリファレンス Ver.1.0対応

Dropbox のファイル選択/保存ダイアログを表示できる Polymer エレメントを書いた

デモを動かしてみるとこんな感じです。

f:id:motemen:20150611202513g:plain

概要

dropbox/dropbox-js を利用してファイル選択/保存ダイアログを表示するコンポーネントです。基本的にフォルダ内のファイルの一覧を行うだけで、それ以上のことはコンポーネントのユーザに委ねているので、ユーザは dropbox-js の API を使って実際のファイルの読み書きを行う必要があります。

使い方

bower でインストールして、

bower install --save motemen/dropbox-file-chooser-dialog

ダイアログを表示したいページや要素で import しつつ、配置します。

<script src="path/to/webcomponentsjs/webcomponents-lite.js"></script><!-- 必要であれば -->
<link rel="import" href="path/to/bower_components/dropbox-file-chooser-dialog/dropbox-file-chooser-dialog.html">
...
<dropbox-file-chooser-dialog app-key="YOUR_APP_KEY"></dropbox-file-chooser-dialog>

API

ドキュメント にある通り、openFolder(path[, mode]) でダイアログを開けます。

var dialog = document.querySelector('dropbox-file-chooser-dialog');

// 「ファイルを開く」ダイアログ
dialog.openFolder('/', 'open');

// 「ファイル名を指定して保存する」ダイアログ
dialog.openFolder('/', 'save');

また簡便のため、dropbox-js へのインターフェースも少し定義してあります。

dialog.authenticate(function (err, dropbox) { ... });

dialog.readFile(path, function (err, content, file) { ... });

dialog.writeFile(file, content, options, function (err, file) { ... });

イベント

ダイアログが表示されて、ユーザによってファイルが選択またはファイル名が指定された時には以下のイベントが発火します。

dropbox-file-chosen-open

ファイルを開く選択。event.detail{ file: Dropbox.File.Stat }

dropbox-file-chosen-save

ファイルを保存する選択。event.detail{ folder: Dropbox.File.Stat, filename: String }

カスタマイズ

  • 必須の属性として、Dropbox に登録したアプリの App Key を app-key に記述する必要があります。
  • with-backdrop 属性を与えることで、デモのようにダイアログの表示時にそれ以外の要素をグレーアウトさせることができます。(詳しくは IronOverlayBehavior
<dropbox-file-chooser-dialog with-backdrop></dropbox-file-chooser-dialog>
  • スタイルシートで dropbox-file-chooser-dialog の width, height を指定することでいい塩梅にダイアログが配置されます。(同上)
dropbox-file-chooser-dialog {
  width: 60%;
  height: 60%;
}
  • iframe 内に表示するなど、遷移による Dropbox 認証が行えない場合、popup-oauth-receiver-url 属性を使うことができます(デモを参照してください)。

また、ヘッダの色はデフォルトで灰色に黒ですが、Custom CSS properties という機構を利用して、以下のようにしてカスタマイズできます。

<style>
:host {
  --dropbox-file-chooser-dialog-header-background-color: red;
  --dropbox-file-chooser-dialog-header-color: white;
}
</style>

上の例は何がしかの Polymer エレメントからスタイルをあてたい場合で、素の HTML から利用するときは以下のように is="custom-style" を指定する必要があります。

<style is="custom-style">
:root {
  --dropbox-file-chooser-dialog-header-background-color: red;
  --dropbox-file-chooser-dialog-header-color: white;
}
</style>

ソースとドキュメント

ソース: https://github.com/motemen/dropbox-file-chooser-dialog

ドキュメントとデモ: https://motemen.github.io/dropbox-file-chooser-dialog/

デモはその性格上お使いの Dropbox の読み書き権限を要求しますが、ファイルの内容の書き換えや読み出しまでは行いません。為念。

初回の認証あたりの流れがちょっといかしてない感じがしますが、どうぞご利用くださいね。

はてなで一緒に働きませんか?