PlantUMLの-pipeモードとEmacsのplantuml-mode

Emacsのplantuml-modeが謎のぬるぽ

なんだろうなぁと思っていた。一部の PlantUML ファイルについて Emacs の plantuml-mode で正しく preview できずに Java のレベルで異常終了してしまう。VS Code の PlantUML extension では特に問題ない。

違いとしては

  • VS Code 側は画像を出力している
  • Emacs 側は txt で出力している

あとなんとなくだけど

  • Emacs 側は stdio で PlantUML の出力を受け取っているんじゃないか

と予測できる。ファイルを渡すのではなく選択範囲(region)の内容を渡して preview することが可能なので。

plantuml-modeの動作

まず plantuml に与えられる引数をチェック。

$ plantuml -h

すると

    -p[ipe]             To use stdin for PlantUML source and stdout for PNG/SVG/EPS generation

というオプションを見つける。実にそれっぽい。確かに plantuml コマンドでファイルを直接渡した場合と違って plantuml-mode の中から実行している場合と同様に落ちる。ビンゴか。

Emacs Lisp の方を調べると以下のような関数がある。

(defun plantuml-jar-start-process (buf)
  "Run PlantUML as an Emacs process and puts the output into the given buffer (a\
s BUF)."
  (let ((java-args (if (<= 8 (plantuml-jar-java-version))
                       (remove "--illegal-access=deny" plantuml-java-args)
                     plantuml-java-args)))
    (apply #'start-process
           "PLANTUML" buf plantuml-java-command
           `(,@java-args
             ,(expand-file-name plantuml-jar-path)
             ,(plantuml-jar-output-type-opt plantuml-output-type)
             ,@plantuml-jar-args
             "-p"))))
(defun plantuml-executable-start-process (buf)
  "Run PlantUML as an Emacs process and puts the output into the given buffer (a\
s BUF)."
  (apply #'start-process
         "PLANTUML" buf plantuml-executable-path
         `(,@plantuml-executable-args
           ,(plantuml-jar-output-type-opt plantuml-output-type)
           "-p")))

jar を与えて Java を起動する方法でもコマンドを起動する方法でも -pipe で与えていることが分かる。

なぜか放置されている問題

理由は分からないが、

  • PlantUML は -pipe で渡されたデータの中に複数の diagram が含まれていると処理できず NullPointerException が発生する。どうもファイルに出力することが基本的な前提のようだ。

加えて、これはある程度仕方ないとは思うが、

  • -Ttxt で表現しきれない diagram でも同様に NullPointerException になってしまう。

まぁ無理なのは分かるけど、

さすがに NullPointerException を放置するのではなく、意味の分かるエラーメッセージにしてほしい

と思う。

さすがに何が起きてるか分かるようにしたい

ということで wrapper script を書いた。

#! /bin/bash
set -o pipefail
OUTPUT=$(plantuml "$@" 2>&1)
printf "%s" "$OUTPUT"
if printf "%s" "$OUTPUT" | grep -q 'java\.lang\.'; then
cat <<EOD >&2
Did you write multiple diagrams in single file ?
PlantUML with -pipe option cannot accept multiple images ...
Or something wrong about some diagrams with txt type ...
EOD
fi
exit 0

これで PlantUML を実行してぬるぽになったら「こういうことが疑わしいよ?」というメッセージを付け加えることができるので、無駄にトラブルシュートに入ろうとしないんじゃないんかな。たぶん。

More