Hubot で Scala REPL を動かす
HUBOT はヒューボットと発音するのが正しいらしい。
HipChat などのチャットツールの特定の部屋で、特定のメンションを付けたメッセージを Scala コードとして REPL 上で実行し、その結果をチャットに返すのが目的。 REPL環境はメッセージのたびに毎回初期化される。
今回初めて Coffee Script に触ってみた。
コード
以下のようなスクリプトを scripts ディレクトリ配下に書く。
外部プロセスとして scala コマンドを起動し、その標準入力にメッセージを流しこむだけ。
# Description:
# ScalaのREPLを実行する
#
exec = require('child_process').exec
module.exports = (robot) ->
robot.respond /((?:.|\n)+)/i, (res) ->
if res.message.room == 'your_room'
code = res.match[1]
n = code.length
res.reply n + ' Byte' + if n <= 1 then '' else 's'
try
scala = exec 'scala', (error, stdout, stderr) ->
lines = ('' + stdout).split '\n'
# 余計な行を省く
lines = lines[4...-2]
res.send '/code ' + lines.join('\n')
scala.stdin.setEncoding = 'utf-8'
scala.stdin.write(code + '\n')
scala.stdin.end()
catch e
res.reply "command failed: " + e.message
- line 7: 改行を含むメッセージを正しく処理できるように、少しトリッキーな正規表現を使っている。
res から直接メッセージ文字列を取得できれば、こんな必要はなさそうだが…… - line 12: コードゴルフ用にメッセージの長さを通知。
- line 15: child_process.exec を使って実行。
これが非同期で実行されるというところが最初理解できずハマった。 - line 18: REPLの冒頭に表示されるバージョン表示などの冗長な出力部分をカット
たぶん、まだまだリファクタリングできるところは多そう。が、そもそも文法を学んでないので厳しい。
備考
- OSのシステムコマンドや外部接続、リソース消費などに対するセキュリティは全くの無防備状態なので注意。
- 将来的には conscript と連携して、各プロジェクトごとの sbt console に直接入って操作できるようにしたり、あるいはいくつか常駐プロセスを立ち上げておき、状態を永続化できるように拡張できたらよいと思う。
0 件のコメント:
コメントを投稿