Google 製 Visual Programming Editor「Blockly」の調査
Blockly とは
smalruby-editor の視覚的なプログラムエディタ(Visual Programming Editor)の実装には Blockly を使うことを想定しています。 Blockly は Google 製の Visual Programming Editor です。Apache License, Version 2.0 にしたがって配布されているオープンソースソフトウェアです。また、いわゆるタダ乗りにも寛容なフリーソフトウェアの思想を感じます。
まずは デモサイト Code - Export a Blockly program into JavaScript, Python or XML. にアクセスして Blockly がどのようなものか確認するといいでしょう。
さて、ざっと Blockly がどのようなものかわかったところで smalruby-editor の実装に必要な次の情報を調査していきましょう。
- デモサイトをローカルマシンで動作させる方法
- Blockly を改良する方法
- Rubyのソースコードを出力する方法
- 任意のブロックを作成する方法
- ブロックをカテゴリ分けする方法
- インタフェースをカスタマイズする方法
- インタフェースを日本語にする方法
デモサイトをローカルマシンで動作させる方法
まずは git clone
します。
git clone https://github.com/google/blockly
そして、 \path\to\blockly\apps\code\index.html
をブラウザで開きます。
あらま、これだけで Blockly の デモサイト が手元でも動作します。
Blockly を改良する方法
Blocklyを改良するために必要なソフトウェアをインストールします。
-
- Blocklyに必要なバージョンがなにかわからなかったのですが、https://groups.google.com/forum/#!searchin/blockly/build.py/blockly/2hkbRAV_-KA/jiRTIEKejMYJ から 2.7 系にしました。
- インストーラに従ってインストールします。
- 環境変数Pathに
C:\Python27;C:\Pyhton27\DLLs
を追加しました。 - インストール後は PowerShell を起動して python コマンドが実行できることを確認しました。python コマンドの終了は
quit()
です。
-
- soyというGoogle Closure Libraryが提供するテンプレートエンジンのために必要です。
- https://developers.google.com/closure/templates/docs/helloworld_java には「you'll need to have Java Development Kit (JDK) version 6 installed」と書かれていましたが、いまどきは JDK 7 だろうということで、 jdk-7u51-windows-x64.exe をインストールしてみました。
- インストーラに従ってインストールします。
- インストール後は PowerShell を起動して java コマンドが実行できることを確認しました。
Google Closure Library
以下のコマンドでインストールします。
cd path/to/blockly/../ git clone https://code.google.com/p/closure-library/ closure-library-read-only
これで準備が完了しました。
Blocklyをビルドします。
PS C:\Users\kouji\work\smalruby\blockly> python build.py ('Error running i18n/js_to_json.py: ', WindowsError(193, '%1 \x82\xcd\x97L\x8c\xf8\x82\xc8 Win32 \x83A\x83v\x83\x8a\x83P\x81[\x83V\x83\x87\x83\x93\x82\xc5\x82\xcd\x82\xa0\x82\xe8\x82\xdc\x82\xb9\x82\xf1\x81B')) SUCCESS: blockly_uncompressed.js SUCCESS: blockly_compressed.js Size changed from 1814 KB to 439 KB (24%). SUCCESS: blocks_compressed.js Size changed from 91 KB to 53 KB (59%). SUCCESS: javascript_compressed.js Size changed from 76 KB to 44 KB (58%). SUCCESS: python_compressed.js Size changed from 62 KB to 29 KB (47%).
なんかエラーが出ていますね。失敗しているのは以下の箇所です。 i18n/js_to_json.py
の実行に失敗していますが、Windows では shebang を指定してもスクリプトは実行できないのでどうにかする必要があります。
subprocess.check_call([ os.path.join('i18n', 'js_to_json.py'), '--input_file', 'msg/messages.js', '--output_dir', 'msg/json/', '--quiet'])
以下のように修正して回避します。
diff --git a/build.py b/build.py index 4dbbf89..92f917b 100755 --- a/build.py +++ b/build.py @@ -334,6 +334,7 @@ class Gen_langfiles(threading.Thread): ['en.json', 'qqq.json', 'synonyms.json']]): try: subprocess.check_call([ + 'python', os.path.join('i18n', 'js_to_json.py'), '--input_file', 'msg/messages.js', '--output_dir', 'msg/json/', @@ -350,6 +351,7 @@ class Gen_langfiles(threading.Thread): try: # Use create_messages.py to create .js files from .json files. cmd = [ + 'python', os.path.join('i18n', 'create_messages.py'), '--source_lang_file', os.path.join('msg', 'json', 'en.json'), '--source_synonym_file', os.path.join('msg', 'json', 'synonyms.json'),
これでBlocklyをビルドできるようになりました。
PS C:\Users\kouji\work\smalruby\blockly> python build.py WARNING: definition of LOGIC_NEGATE_TOOLTIP in msg\json\th.json contained a newline character. SUCCESS: msg\js\ar.js SUCCESS: msg\js\az.js (省略) Size changed from 91 KB to 53 KB (59%). SUCCESS: javascript_compressed.js Size changed from 76 KB to 44 KB (58%). SUCCESS: python_compressed.js Size changed from 62 KB to 29 KB (47%).
Blockly が正しく動作しているかどうかは、 https://code.google.com/p/blockly/wiki/UnitTesting に従って操作することで確認できます。なお、Windows 8.1/Internet Explorer 11 では確認用の HTML が正しく動作しません。Firefox or Chromeで試しましょう。
ついでにちょっと修正してみます。意味は特にないのですが文字列のダブルクォーテーションを2つにしてみます。
以下の修正を行って、ビルドして、demos/fixed/index.html をブラウザで開くと修正内容が反映されていることが確認できます。
diff --git a/blocks/text.js b/blocks/text.js index 3bdd714..9797353 100644 --- a/blocks/text.js +++ b/blocks/text.js @@ -36,6 +36,8 @@ Blockly.Blocks['text'] = { this.appendDummyInput() .appendField(new Blockly.FieldImage(Blockly.pathToBlockly + 'media/quote0.png', 12, 12)) + .appendField(new Blockly.FieldImage(Blockly.pathToBlockly + + 'media/quote0.png', 12, 12)) .appendField(new Blockly.FieldTextInput(''), 'TEXT') .appendField(new Blockly.FieldImage(Blockly.pathToBlockly + 'media/quote1.png', 12, 12));
Ruby のソースコードを出力する方法
Blocklyは、JavaScriptとPythonのソースコードを生成できます。しかしながら、Rubyには対応していません。 でもね、 https://github.com/velniukas/blockly.cascading.jruby で Ruby のソースコード生成に対応したものが公開されています。 とっても参考になります。
レポジトリをリモートに追加しておきます。
cd path/to/blockly git remote add velniukas git@github.com:velniukas/blockly.cascading.jruby.git
また、 https://code.google.com/p/blockly/wiki/CustomBlocks から参照できる以下の文書も参考になります。
まとめると、Blockly が Ruby のソースコードを生成できるようにするには、
といったことをすればいいようですね。
任意のブロックを作成する方法
チュートリアルに従ってタートルグラフィックス用のブロックを作ってみました。ブロックのカスタマイズを GUI で行える ことには驚きました。よくできています。
ただし、Windows の PowerShell だと最後のコマンドの --srcs
オプションの引数を以下のように "
で括ってやる必要がありました。
PS C:\Users\kouji\work\smalruby\blockly\apps\turtle> java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs "../common.soy,template.soy"
ブロックを作るときに使うAPIのリファレンス もあります。
ブロックをカテゴリ分けする方法
Blockly ではブロックを選択するところを Toolbox と呼びます。このサンプルのように Toolbox にずら~とブロックを並べたり、タートルグラフィックス用のブロック のようにカテゴリ分けしてブロックを配置することができます。
そのやり方は https://code.google.com/p/blockly/wiki/Toolbox に記述されています。この文書の最後のサンプルには、あらかじめいくつかのブロックを組み合わせたものを Toolbox に配置する方法が説明されていますね。
インタフェースをカスタマイズする方法
Blockly のインタフェースのうち、ブロックやブロックを配置するためのキャンバスは SVG で表現されているようですので、それをカスタマイズするのは簡単ではなさそうです。 しかしながら、Toolbox は HTML で表現されていますので、CSS で簡単に見た目を変えることができそうです。
smalruby-editor では、できればScratchのように選択中のカテゴリのブロックを常に表示させたいのですが、そのためには core/toolbox.js を編集するか、それを継承した独自の Toolbox を作成する必要がありそうですね。
インタフェースを日本語にする方法
Blockly で利用している Soy というテンプレートエンジンがメッセージの翻訳に対応しているようです。
前述した「任意のブロックを作成する方法」で使ったコマンド java -jar ../_soy/SoyToJsSrcCompiler.jar --outputPathFormat generated/en.js --srcs "../common.soy,template.soy"
のようにして、テンプレートから翻訳対象の文字列を抽出して、 JavaScript のメッセージカタログを出力できます。
実際には、SoyMsgExtractor.jar/xliff_to_json.py
というコマンドを使って翻訳対象のメッセージをJSON形式で抽出して、ja.json
などの各国語に翻訳したものを作成後、 json_to_js.py
で JSON から JavaScript のメッセージカタログを出力するようです。
ここまでの準備ができたら、以下のJavaScriptの処理によってメッセージカタログを読み込みます。これでインタフェースを日本語にできます。
document.write('<script type="text/javascript" src="generated/' + BlocklyApps.LANG + '.js"></script>\n');
詳細は TranslationForDevelopers の Applications and Tutorials に書いてあります。