org-modeのソースコードブロック( #+BEGIN_SRC ~ #+END_SRC )は非常に便利で特に評価結果を生成してくれるところが素晴らしいですが、エクスポートするたびにソースコードを再評価するか聞かれるのは鬱陶しいところです。 もちろんエクスポートのたびに毎回評価した方が良いこともあるでしょうが、私の利用状況ではほとんどの場合エクスポート時の評価は必要ありません。
エクスポート時の評価を抑制する方法はいくつかありますが、最も普通なのはヘッダー引数 :eval を指定することではないでしょうか。 ヘッダー引数 :eval に no-export または never-export を指定することでエクスポート時に評価しないようにできます。(参考: Evaluating Code Blocks)
例えば次のように :eval no-export を付けるとエクスポート時に評価されずに今 #+RESULTS: のところに生成されている結果がそのままエクスポートされます。
Emacs Lispで1+2+3を計算するには次のようにします。
#+begin_src elisp :exports both :eval no-export
(+ 1 2 3)
#+end_src
結果:
: 6
他にもキャッシュ機能を使えばソースコードの内容(ハッシュ値)が変わったときだけ評価するようにもできます。
Emacs Lispで1+2+3を計算するには次のようにします。
#+begin_src elisp :exports both :cache yes
(+ 1 2 3)
#+end_src
結果:
: 6
ただ、正直キャッシュまでは必要ない場合がほとんどです。大抵は書いている途中に手動で評価して確認し、それをそのままエクスボート時に出力してくれれば十分です。
他にもorg-confirm-babel-evaluateをnilにするという方法もありますが、これは確認せずに全て評価するという意味なのでセキュリティ的な懸念があります。
というわけで私は結果を出力するソースコードブロックにはいつも :eval no-export を付けていたのですが、インラインソースコードブロックを書くときにはウンザリしていました。例えば次のようにいちいち [:eval no-export] と書かなければなりません。
2750円から3000円へ値上がり(src_[:eval no-export]{100*(3000/2750-1)} {{{results(=9.090909091=)}}} %増)
打つのが面倒というのもありますが、見返したときにゴチャゴチャしていて読みづらいのが一番の問題です。
そもそもほとんどのソースコードブロックに :eval no-export を指定するのであれば、デフォルト値がそうなっていれば済む話ではないでしょうか。
調べてみると、次の書き方でorgファイル全体のデフォルトを設定できるようです。(参考: Using Header Arguments)
これは良いものだと思いますが(こんなの前からあった?)、でもほとんどのファイルにこれを書くのも面倒です。
もう少し調べてみるとob-core.el内で定義されている変数org-babel-default-header-argsとorg-babel-default-inline-header-argsを修正すればデフォルト値を変えられるようでした。
通常のソースコードブロックとインラインソースコードブロックとで変数が違います。
;; ob-core.elより
(defvar org-babel-default-header-args
'((:session . "none") (:results . "replace") (:exports . "code")
(:cache . "no") (:noweb . "no") (:hlines . "no") (:tangle . "no"))
"Default arguments to use when evaluating a source block.
...略...")
(put 'org-babel-default-header-args 'safe-local-variable
(org-babel-header-args-safe-fn org-babel-safe-header-args))
(defvar org-babel-default-inline-header-args
'((:session . "none") (:results . "replace")
(:exports . "results") (:hlines . "yes"))
"Default arguments to use when evaluating an inline source block.")
(put 'org-babel-default-inline-header-args 'safe-local-variable
(org-babel-header-args-safe-fn org-babel-safe-header-args))
(余談ですが、 :exports が通常では code で、インラインでは results になっているのが興味深いところです)
なのでこれを次のようにして書き替えてしまえば良さそうです(init.el等で)。
;; ソースブロックのヘッダー引数で :eval no-export をデフォルトにする。
(with-eval-after-load "ob-core"
(push '(:eval . "no-export") org-babel-default-inline-header-args)
(push '(:eval . "no-export") org-babel-default-header-args))
;; (setf (alist-get :eval org-babel-default-header-args) "no-export")でも良いのかもしれないけど……非破壊的なalist設定関数って無いんだよね。いや、破壊してもいいのかもしれないけど……copyしてsetする? マニュアルにはassq-delete-allしてconsする設定例が載っているなぁ
ちなみに変数に safe-local-variable プロパティの設定があるのでファイルローカル変数で指定できるのかなと思ってやってみたのですが (:eval . "no-export") の指定は安全だと見なされないようです。何が安全かは定数org-babel-safe-header-argsで決まっているので、そこを修正すれば通るようにはなります。どのみち指定しづらいですし、ファイル全体で指定したければ #+PROPERTY: header-args :eval no-export で設定した方が良いでしょう。
2750円から3000円へ値上がり(src_{100*(3000/2750-1)} {{{results(=9.090909091=)}}} %増)
# Local Variables:
# org-babel-default-inline-header-args: ((:eval . "never-export") (:session . "none") (:results . "replace") (:exports . "results") (:hlines . "yes"))
# End:
というわけでデフォルトを :eval no-export にしたのでインラインソースコードブロックが書きやすくなりました。
2750円から3000円へ値上がり(src_{100*(3000/2750-1)} {{{results(=9.090909091=)}}} %増)
……まぁ、比較的。それでも見づらさは残りますけどね。
ここからは余談ですが、式が出力されても良いならCalcのEmbedded Modeを利用する手もあります。例えば次のように書いて$と$の間で C-x * u と押すと結果が => の右に挿入されます。
2750円から3000円へ値上がり($100 (3000/2750 - 1) =>$ %増)
マクロを使えば => の右側だけ取り出すことも一応できます。
2750円から3000円へ値上がり({{{calc-result($100 (3000/2750 - 1) => 9.090909091$)}}}%増)
区切りの $ は必要ですが、calc-embedded-open-formulaあたりで区切りを変更すれば無くせるかもしれません。
うーん、でもインラインソースコードブロックと大差ないような気もしますね。
ところで #+BEGIN_SRC~#+END_SRC のブロックを何と呼ぶかいつも困っています。ここでは「ソースコードブロック」と書いてみましたが、これまで私は「ソースブロック」と書くことが多かったような気がします。マニュアルでは「source code block」「code block」「source block」が混在しています。「src block」と書いてあるのもどこかで見たような気もします。