vvakame / language-review

Re:VIEW support for Atom
https://atom.io/packages/language-review
MIT License
27 stars 9 forks source link

いい感じのサクサク動くエディタ環境をどうやって確保するかという話 #23

Open muojp opened 9 years ago

muojp commented 9 years ago

元々は #11 をサポートするために必要なものを考えていった話ですが、広い話になったのでまとめました。

Re:VIEW(Ruby Re:VIEW)とreview.js、そしてlanguage-reviewについてしばらく考えていたことのサマリです。

悩み

前述( #11 )のように@<chapref>{}構文を使いたいと考えました。

この要望をきちんと満たすためには、実はいくつかの段階が必要です。

このあたり調査経緯などは長くなったため別途blogにまとめました。後でURLを貼ります。

根っこの原因

前節を読むと「わぁ、これは大変だ。issuesを分割してコツコツ対応しなきゃ」と思うところですが、少し戻って考えてみましょう。

review.jsの本流としてはbookを正しく解釈してビルドできるようにし、さらに付加価値を加えるというのがきれいですが、language-reviewの性質は異なります。

そもそもRe:VIEWは、例えHTML向け出力に限ったとしても、book全体(たとえば15章から成るとしましょう)を50ms - 200ms程度でビルド終了できるような性質のものではありません。

これをエディタ稼働中、数タイプごとに毎回いちから処理するというのがあまりうまく行く筋ではありません。

雑にAndroidでいえば、エディタ保存の都度.apkがフルビルドされる必要は通常ないのです。

language-reviewは「そこそこの軽さで執筆の手間を減らせる。しかもプレビューもいい感じにできる」というものであるべき(私見)で、この観点からはbookの構造の正当性自体はさほど優先度の高くないもの(lintに必要ならば適宜拡充する、程度のもの)のはずです。

そういうわけで

は別物という認識で進んだほうが、すっきりと話が進みそうです。

現行review.js的な正しさとlanguage-reviewのミスマッチ例

book全体ビルドの重さ

たとえば、language-reviewで他の章の見出しを参照するために@<chapref>{}構文をサポートしても、その参照関係を正しく解決し、章/節番号解決までするならば、review.jsへbookの全chaptersを食わせてコンパイルさせる必要が生じます。 これはプレビュー生成どころか エディタ側のツールチップ生成などにかかる時間を章の数だけリニアに延ばすことになるため、language-review向けのreview.js機能として適切ではありません。

ここでの逃げ道として、

という形が考えられます。これはreview-runnerの改修によりある程度省力で実現可能でしょう。 それでも「15-20章におよぶbookの全体を、Atom開き直すたびにコンパイルすんの?マジで?」という懸念は依然あります(後に挙げるcatalog.yml不在時のデフォ挙動を考えるとなおさらです)。

加えて、執筆中にありがちな「作業集中のためのcatalog.yml一時コメントアウト」(次に挙げます)とも相性がかなり悪そうです。

作業集中のためのcatalog.yml部分コメントアウトとの相性悪さ

私は、執筆時にそのとき取り組んでいる章へ集中し、プレビュー用PDFファイルの生成にかかる時間を減らすためにcatalog.ymlへ列挙されている他の章を一時的にコメントアウトすることが多いです。

これにより、本の分量によりますが多くの場合PDFビルド時間が10倍は速くなります。

このとき、review.jsが正直にcatalog.yml/CHAPSを処理してしまうと、カタログに載っていない章を見つけて@<chapref>{}解決が失敗してしまうでしょう。

シーケンス例としては、review.js+language-reviewを拡張してcatalog.yml(book全体ロード&ビルド)対応をすると、PDFビルド→確認→エディタへ戻って編集→保存→エディタ内で確認してみる というタイミングで参照エラーへ至りそうです。

catalog.ymlを用意していない場合の重さ

Ruby版Re:VIEWの挙動へ倣うと、catalog.ymlCHAPSも存在しない場合には対象ディレクトリ内の全.reファイルを探して片っ端からビルドセッション固有のカタログとして確保していきます。

空っぽのCHAPSファイルでも置いておけば済む話ですが、エディタの出来としては「利用者にあまり多くの予備知識(罠回避のtipsを含む)を要求しない」ことが望ましいでしょう。

先のシナリオ

つらそうな事情が段々洗い出されてきました。

対応策はいくつか考えられます。

以下はざっくりとした叩き台で、それぞれ独立です。

1: review.jsにエディタ支援のための仕組みを加える

文書の構造チェックやlint追加のための枠組みとして、現行のreview.jsは強力です。

これ(review.js)に対して、インタラクティブな編集において重要な、速度を稼ぐための割と泥臭いハックを随所に仕込んでいくのは得策とは言えません。

「ちょっぴり雑かもしれないけどめっちゃ速いよ」系の黒魔術はひとつの概念で括って閉じ込めておくべきです。

たとえば、language-review側でReVIEWクラスを継承してエディタ向けの機能拡張を施した枠組みを用意したほうがいいかもしれません(イメージ共有のための名前としてはInteractiveReVIEW かな、と思ったけれど LiteweightReVIEW あるいは LiteReVIEW というのがやりたいことを表現していそうです)。

2: review.jsへの構文追加のみをおこない、しばらくお茶を濁す

現状でlanguage-reviewを使っていて一番困るのは、@<chapref>{}構文を使うとこれが不正な構文として弾かれ、language-review側で当該.reのプレビューが一切表示されなくなることです。

@<chapref>{}による参照先章・タイトル表示は、機能セットの完全性(そして間違いの早期検出)として嬉しくはあるのですが、必須機能ではありません。

つまり、@<chapref>{muojp.re}と書いたらそのままmuojp.reと(例えば適当に下線付きで)表示されるようになれば、当座は問題ありません。

これが有力策である理由として、(1)で挙げたLiteReVIEW(仮)がそもそも不要となる可能性が挙げられます。 LiteReVIEW(仮)は速度を稼ぐためのコードを突っ込んだ、language-review専用の黒魔術集というイメージですが、これは以下の条件が満たされれば不要なはずです。

仮にこれらが実現できれば、bookを開くタイミングのごく初期のみ数秒我慢すれば あとは快適に編集できるようになるかもしれません(初期化処理すら、文書構造ダンプのキャッシュにより軽減される可能性があります)。

当座の問題を最低限のパワーで解決し、より大きな問題へ取り組むアプローチもアリと思います。

3: 見なかったことにする

chap/chapref禁止令

muojp commented 9 years ago

http://twitter.com/vvakame/status/615489232811888640 http://twitter.com/vvakame/status/615489540170473472 http://twitter.com/vvakame/status/615489751055908865 http://twitter.com/muo_jp/status/615489978714361857 http://twitter.com/vvakame/status/615490118774714369

vvakame commented 9 years ago

chap, chapref, title はreview.js側でサポートしたけどお茶を濁す方向に戻した。 peg.jsをnpmリリースのものからmaster/HEADに変えたら9倍くらい早くなったので0.9.0系がリリースされるまではmaster/HEAD使っていこうと思った。 ↑イマココ

takahashim commented 9 years ago

やや古いissueへのコメントですが、catalog.ymlを用意していない場合(CHAPSのみがある場合も含めて)はオワコンというか基本はNGで、現状のRuby版Re:VIEWは後方互換性と利便性のためにいろいろフォローしてやっている、くらいの方向性で良いのではないかと思います。

というわけでcatalog.ymlは読んで欲しい、と思ったり…。(@<chapref>のサポートよりも、今書いている章の章見出しのpreviewに正しく章番号が入って欲しい、という気がしております)