RE:ADV

UnityでADVを作るブログ

やっぱり入力補完<インテリセンス>って最高なのでは

ティラノスクリプト(tyranoscript)の入力補完についてです。
vscodeでできたらいいなぁと思って調べていたのですが、Sublime Text3 でできたので(情報量が多い…vscodeはまだできたてなので)そっちで作りこんでいこうと思います。

入力補完のない世界って、本当は名前のない世界で暫定的な名前を*覚えられる*能力者にちょっと有利だと思うんです。
規約で縛るのも、本当は名前なんてないものを「とりあえずこう呼ぼうよ」って決めたことにして*本当は名前のないものたち*を名付けているんだけど、そういうのが苦手(記憶力がない)な人に厳しい世界です。

VisualStudio2013を触って衝撃的だったのは言語世界のツリーを別に人間が覚えなくてもよくない?っていう提案がすごくあって、それで世界に入れたのが大きかったと思います。
一度入ってしまうとキャラ立ちして文字列も覚えられますしね。
つまり学習の補助をコンピュータがしているっていう当たり前なんだけど、まだ受け入れられてない世界観があります。

当時のことがおぼろげですが、吉里吉里っていうゲームエンジンにはすばらしいエディタが開発されていて、人間の入力を助けていました。
今、tyranoriderというデバッグ・入力補助ツールが開発されていますが、少し似ています。
DSLの扱い方って難しくて、webの方ではだいぶヘイトを稼いでいるようです。(次々にいろいろ出てくるからね…)
まあ、そこらへん乗り切るのに、入力補完がほしいと思ったのでちょっとやってみたっていう記事です。

とりあえず調べていくと、textmateっていうxmlのファイルがあるとカラライズ(色付け)ができるってわかってきます。
拡張子は.tmLanguageです。
vscodeの場合、そのファイルをYeomenなるもののコマンドを叩くと組み込まれるらしいです。
code.visualstudio.com
Extensionsのラングイッチサポートっていうそれらしいやつがそれだろうなと思いました。
つまりtmLanguageファイルをつくらなきゃダメらしい。
というわけでそっち方向にググりなおすと、この二つの記事にそのための知識がまとまっているとわかりました。

qiita.com
qiita.com

さっぱりわかりませんでした。
で、もう少し入門的な記事を探すとこんな記事が。

qiita.com

オレオレ記法をtextファイルに適用して、色づけしてみよう!っていう素晴らしいチュートリアルです。
これを写経して、やっと意味が分かりました。
まず、tmLanguageファイルを編集するには、SublimeTextがよさそう、ということ。
そして何はともあれパッケージコントロールでAAAPackageDevパッケージをインストールしなきゃいけないってことです。
※AAAPackageDevパッケージはPackageDevパッケージに改名していました。
慣れてない人間にxml形式のファイルを直書きするのはつらすぎます。pythonさんに(裏で)働いてもらいましょう。

あと、上の解説ではjsonで書いていますが、jsonのエスケープをいきなり書くとたいてい動きません(僕は)
なのでYAMLで書く下の例がサイコーということになります。
どっちで書いてもPackageDevがtmLanguage形式に変換してくれます(F7キーで)。

書き方は
Syntax Definitions — Sublime Text Unofficial Documentation
こういう英語のサイトの例も見ながらやります。
特に引数を書きたいってときにネストするので、その書き方を見る必要があります。

patterns:
- name: support.constant
  comment: 【link】タグの構文定義
  begin: \[(link)
  end: \]
  captures:
    '1': {name: keyword.other}
  patterns:
  - name: support.variable
    match: (storage)\s*(=)\s*"(.+)"
    captures:
      '1': {name: support.variable}
      '2': {name: constant.other}
      '3': {name: storage.modifier}

  - name: support.variable
    match: (target)\s*(=)\s*\*([^\].]+)

基本は name: のところで色づけ規則を指定して、match: のところでどんな文字を色づけするか決めるって感じです。
上では()でキャプチャして、captures:でその各々の色づけを指定、begin: と end: の文字で囲うってことをしています。一個目のpatterns: で大枠を決めて、引数は二個目のpatterns: で色付けしています。

正規表現でマッチしたところが色づくとわかり、いったん白目になりますが、1日くらい勉強してなんとなくわかったら書きます。
正規表現は三つの基本演算がある、ということを意識したら少し入れました(入門的な)。

  • 連接
  • 選択
  • 繰り返し

こいつらです。
詳しくは「正規表現技術入門」っていう本の1章にまとまってます。1章でキャプチャまで網羅してるのでとりあえず1章だけ読みます。

SublimeTextのPreferences>Browse Packages...>でエクスプローラが開くので、その中のUserフォルダに作ったファイル.YAML-tmlanguageと生成した.tmLanguageファイルがあると思います。
うまくいっていれば新規ファイルを作成、言語をUser><拡張子の前に指定した名前>にすると色付けができているはずです!

...でもこれってインテリセンスじゃないよね?

そこで気づくのが.sublime-completionsなるものです。もとより機械的な解釈をしていないので、インテリセンスという名前じゃなかったのかもしれませんが、疑似的にそういう風に動くようにしたい。

そこでks.sublime-completionsを作ってさっきのUserフォルダに保存。
先人の例をなんとなく改変していきます。
まあ、タグ一文字なら登録したら終わりですが、パラメータがあるタグをどうやって登録するか。
こんな感じになりました。

// Tags with paramaters
{ "trigger": "link_parm_full\t", "contents": "link storage=${1:val} target=*${2:val}" },

↑これもエスケープまわりですぐ動かなくなります。でもセーブするだけで反映されるので、トライアンドエラーが素晴らしく速くて、なんとか正解っぽくなりました。
番号で指定している文字列(ここではパラメータval)にTabキーで一発で飛ぶので、動作的には完璧感しかありません。
やった!狙った補完と色付けができたー!と思いました。
が。
コードヒントが出ない!!
入力を途中までやっていると「あなたが探しているのはこれじゃない?」ってエディタがサジェストしてくれるあれです!
あれがなかったら、こんなものなんの意味もありません。
エディタは初めから狙った文字列を覚えている能力者のための道具でしかなく、プログラムの世界は僕のようにすべてを曖昧にしか記憶していない人間にはとうてい踏み入れられない砂漠でしかなかったのです。

コードヒントでググれどもみんなメジャーな言語のコードヒントの情報しかググっていないので、独自のコードヒント出力法なんてさっぱりヒットしません。
というわけでふて寝してからもう一度基本に返って見直していると、最初にどっちでもいいよって感じで書いてあった設定回りのことが気になりました。

# [PackageDev] target_format: plist, ext: tmLanguage
---
name: Tyrano_Ks
scopeName: text.ks
fileTypes: [ks]

このスコープネイムscopeNameのところです。
マークアップならtext、プログラムソースならsourceって指定してね、って言われてた気がします。
そこでsource.ksに変更して、もう一度コンバート(トランスパイル?)をかけます。
すると...?
サジェストが出たぁー!!
f:id:aktaat:20160505194333p:plain
選択すると?
f:id:aktaat:20160505194447p:plain
ちゃんと入力されています!

パラメータも初めに入れておいたものが書式と一緒に出るのでなんとなく何をしたらいいかわかります。
登録時に名前を変えておいて、自分用に最適化されたパラメータのサジェストとかも作ることができますね。※そういうのをスニペットというらしいです。
(ちなみに上の例だと一つ目の引数storage=valは構文的にvalが""でくくられてないといけません。なので=のカラライズがうまくいっていません。それも意図通りの挙動です)
砂漠ではとりあえず自分の通る道だけ覚えるという戦術で挑みたいと思います。そのための下地についての記事でした。