2026-03-15 ,

org-modeの中でEmacs Calcを使う(主にインラインで)

Calcの埋め込みモード(Embedded Mode)の基礎

org-modeはLaTeXの表記がある程度そのまま使えますしCalcの埋め込みモードはLaTeXをサポートしているので何も設定しなくてもorg-modeからCalcの埋め込みモードはある程度使えます。

一番簡単なのは $ で囲むことでしょう。(もちろん他にも $$~$$\[~\]\(~\)\begin{equation}~\end{equation} 等の表記が使えます(参考: Embedded LaTeX)。空行も数式の区切りとして使えます)

例えば次のように書きます。

1~4を足すと $1+2+3+4$ になります。

$ の中で C-x * u (update)を押すと 1+2+3+4 が計算されて 10 に置き換わります。

1~4を足すと $10$ になります。

数式の部分は C-x * f (new formula)の後に 1+2+3+4 と入れても良いですし、その場合はその後RPN電卓のように 2 * で2倍にしたりといった操作ができます。 q でquit。式をバッファに入力してから C-x * e を押す方法もあります。ただこのあたりの専用モードに移る使い方はCalcの操作に慣れていないと難しいですね。幸い移らなくても C-x * u (update)は使えます。

これだけだったら埋め込みモードを使う必要性は少ないです。 C-x * q でQuick Calcを呼び出して計算して結果をyankすれば済む話です。

今度は次のように => を加えてから C-x * u (update)を押します。

$1+2+3+4=>$

すると今度は次のように計算結果が => の後に挿入されました。

$1 + 2 + 3 + 4 => 10$

変数を使うこともできます。次のように打ってから C-x * u (update)を押すと変数xに256が記録されます。

$x:=256$

そして同じバッファの別の場所で次のように入力して……

$x^2=>$

C-x * u (update)を押すと次のように変化します。

$x^2 => 65536$

この時、バッファ内の二つの数式 $ x:= 256$$x^2 => 65536$ はアクティブ(活性)なものとして、その位置が記録されています。

なので $x := 256$$x := 65536$ に変更して C-x * u (update)すると、 $x^2 => 65536$ の方も更新されて $x^2 => 4294967296$ に自動的に変化します!

バッファを閉じてしまうとこのアクティブ状態は失われてしまいますが、再度ファイルを開いて C-x * a (activate) を押すとバッファの中にある :==> が検索されてその周囲が有効な数式であればアクティブ化されます。

このように作られた数式部分をエクスポートするとどうなるでしょうか。 $ で囲まれた部分はorg-modeではLaTeX fragmentと呼ばれています(参考: LaTeX fragments)。なので数式のフォーマットで出力されることになります。他のLaTeX fragmentの形式($$~$$\[~\]\(~\)\begin{equation}~\end{equation} でも同様です。唯一、空行で区切られた数式だけは通常の段落として出力されます。また、当然ですが数式がコメント(#)の後に書かれていれば出力されませんし、その他状況によっては特殊な出力になることもあるかもしれません。

数式のフォーマットで出力されるのは大仰だと感じることも多いでしょう。また、出力されるときは数式全体が出力されるので、結果だけを出力するというようなコントロールはできません。

そういった問題はorg-modeのマクロを使うとある程度解決できます。

設定

ここではマクロの定義の他により気軽に使えるように区切りのパターンもいくつか余分に追加しています。

  • {{{calc(x := 123)}}}{{{calc(2 x => 246)}}} のようなマクロを追加
  • 式の区切りパターンを追加
    • インラインコードブロック src_???{ ... }
    • マクロ {{{???( ... )}}}
    • ブロック #+begin ... #+end
    • 非ASCII文字(日本語が出てきたら数式ではないものとする)
;; マクロ {{{calc(式)}}} を定義する
;;   {{{calc(左辺=>結果)}}}       => 結果のみエクスポート
;;   {{{calc(変数:=右辺=>結果)}}} => 結果のみエクスポート
;;   {{{calc(変数:=右辺)}}}       => 右辺のみ (空にして => を必須にしても良いが)
;;   {{{calc(式)}}}               => 式のみ (評価結果にしても良いが)
(defun my-org-macro-calc (expr)
  (cond
   ((string-match "=> *" expr) ;; Include x := y + 3 => 20
    (substring expr (match-end 0)))
   ((string-match ":= *" expr)
    (substring expr (match-end 0)))
   (t expr)))

(setf (alist-get "calc" org-export-global-macros nil nil #'equal)
      "(eval (my-org-macro-calc $1))")

;; org-modeでのCalc式の区切りパターンを追加。
;; 新しいマクロ表記({{{calc()}}})の他に$や\[等の従来のものも一応残す。
(setf (alist-get 'org-mode calc-embedded-open-close-formula-alist)
      (list (concat
             "\\`\\|^\n\\|\\$\\$?\\|\\\\\\[\\|^\\\\begin[^{].*\n\\|^\\\\begin{.*[^x]}.*\n\\|\\\\("
             "\\|{{{[a-zA-Z][-a-zA-Z0-9_]*(" ;;マクロ
             "\\|\\<src_[^ \t\n[{]+\\(\\[[^]]*\\]\\)?{" ;;インラインソース
             "\\|^#\\+begin[_:][^\n]*\n" ;;ブロック
             "\\|[[:nonascii:]]:? ?" ;;ASCII以外(お好みで)
             )
            (concat
             "\\'\\|\n$\\|\\$\\$?\\|\\\\]\\|^\\\\end[^{].*\n\\|^\\\\end{.*[^x]}.*\n\\|\\\\)"
             "\\|)}}}" ;;マクロ
             "\\|}" ;;インラインソース
             "\\|^#\\+end[_:][^\n]*\n" ;;ブロック
             "\\| ?[[:nonascii:]]"
             )))
;; C-x * a (`calc-embedded-activate')で検索するパターンを追加
;; 設定しなくても := や => は検索するので必要なのかどうか分からないが一応
(setf (alist-get 'org-mode calc-embedded-announce-formula-alist)
      (concat
       "# Embed\n\\(# .*\n\\)*\\|"
       "{{{calc(.*)}}}"))
;; d p (`calc-show-plain')を使ったときに出力されるコメントの構文
;; 一応他のメジャーモードの時と同じように設定しておく
(setf (alist-get 'org-mode calc-embedded-open-close-plain-alist)
      '("# %% " " %%\n"))
;; C-x * f (`calc-embedded-new-formula') で数式を作るときに挿入する区切り
;; 設定しない方がいい? 余計かも
(setf (alist-get 'org-mode calc-embedded-open-close-new-formula-alist)
      '("{{{calc(" ")}}}"))

独自のcalcマクロの使用例

上の設定の後、org-modeのバッファに例えば次のように書きます。

# 杯数: $ servings := 3 $

# [calc-mode: float-format: (fix 3)]
{{{calc(servings => 3)}}}杯分を作るには、水を{{{calc(water := 250 servings => 750 )}}}ml、レモン果汁を{{{calc(lemon := 125 servings => 375)}}}ml使います。合わせると{{{calc(water + lemon => 1125)}}}mlとなり、果汁{{{calc(100 lemon / (lemon + water) => 33.333)}}}%のレモン水になります。

その後 C-x * a (activate)を押すと := や => を含む全ての式が「アクティブ」になります。

C-x * n (next)や C-x * p (previous)を押すとポイントを次のアクティブな数式や前のアクティブな数式へ移動できます(アクティブになっていることを確認できます)。

この状態で $ servings := 3 $34 に変更して C-x * u (update)を押すと、他の全てのアクティブな数式も更新されます。

もちろんエクスポートすれば次のようにシンプルな文章になります。

4杯分を作るには、水を1000ml、レモン果汁を500ml使います。合わせると1500mlとなり、果汁33.333%のレモン水になります。

非ASCII文字を区切りにする

上の設定では非ASCII文字も区切りとして追加しているので、より気軽に文章の中で数式を書くことができます。例えば次のように:

2026年10月1日の為替レートはrate_before := 148.170円/ドルだった。10月10日はrate_after := 153.090円/ドル。実に100 (rate_after / rate_before - 1) => 3.320パーセント上がったことになる。

文の中に三つの数式があるのが分かるでしょうか。区切りとして非ASCII文字を追加したため、 が区切りになってその間をCalcは数式と認識してくれるわけです。

もちろんエクスポートすると余分な式も出力されてしまいますが、自分だけが見るのであれば困ることも無いと思います。いちいち {{{calc()}}} で囲むのが面倒であればこういった方法もあります。

ただ、数式の中に非ASCII文字を書きたい人はこの設定は使えません。

ソースコードブロックを使う

似たようなことはソースコードブロックを使ってもできます。特にインライン版のソースコードブロックが有用です。

次のように書くと先ほどと同じことができます(式の部分でC-c C-cを押すと結果部分が生成される)。

1~4を足すと src_calc[:eval no-export]{1+2+3+4} {{{results(=10=)}}} になります。

= が付くのが気に入らなければ次のようにヘッダー引数 :wrap を指定すれば良いみたいです。(t で良いのかはイマイチよく分かりません。 :results wrap でもいけるみたいです)

1~4を足すと src_calc[:eval no-export :wrap t]{1+2+3+4} {{{results(10)}}}になります。

ちなみに数式部分だけ出力したければ :exports code を指定します。これは今回のテーマである計算するというところから少々はみ出していますが。

1~4を足す式は src_calc[:exports code]{1+2+3+4} と書きます。

変数を使うには……どうしたらいいんでしょうね。

#+CONSTANTS: は参照できないみたいなんですよね。他のソースコードブロックの結果かテーブルかリストか……。とりあえずテーブルを参照してみましょうか。

#+NAME: drink-params
| servings |   3 |
| water    | 750 |
| lemon    | 375 |
#+TBLFM: @2$2=250*@1$2::@3$2=125*@1$2

src_calc[:eval no-export :wrap t :var params=drink-params]{params_1_2} {{{results(3)}}}杯分を作るには、水を src_calc[:eval no-export :wrap t :var params=drink-params]{params_2_2} {{{results(750)}}}ml、レモン果汁を src_calc[:eval no-export :wrap t :var params=drink-params]{params_3_2} {{{results(375)}}}ml使います。合わせると src_calc[:eval no-export :wrap t :var params=drink-params]{params_2_2+params_3_2} {{{results(1125)}}}mlとなり、果汁src_calc[:eval no-export :wrap t :var params=drink-params]{100 params_3_2/(params_2_2+params_3_2)} {{{results(33.333)}}}%のレモン水になります。

だめだ、やってられん!

課題

埋め込みモードはorg-modeが提供する変数、つまり、ソースコードブロックの :var で参照できるものにアクセスできないのは残念なところです。

とはいえ、Calcの関数を作ってしまえばアクセスできるのではないでしょうか。

そのあたりはまた今度。