2017-10-26 ,

org-modeのコードブロック(Babel)の使い方

基本的な使い方(コードブロックの評価とエクスポート)

ソースコードブロックは #+BEGIN_SRC で始まり #+END_SRC で終わります。

例えばorgファイルの中に次のように書きます。

Emacs Lispで1+2+3を計算するには次のように書きます。

#+BEGIN_SRC emacs-lisp
(+ 1 2 3)
#+END_SRC

これはEmacs Lispで1+2+3を計算するコードをOrg文書に埋め込んでいる例です。

#+BEGIN_SRC#+END_SRC は手で打たなくても org-insert-structure-template コマンドで挿入できます。デフォルトでは C-c C-, の後に s と打てば挿入されます。

#+BEGIN_SRC の直後には言語名を指定します(有効な言語名は Babel: Languages 等を参照してください)。

このソースコードブロックの上で C-c C-c を押すとコードを評価(実行)するかどうか聞かれます。yesを選択するとコードが評価されてコードブロックの下に結果が挿入されます。(評価できる言語は org-babel-load-languages 変数であらかじめ設定しておく必要がありますが、emacs-lispだけは初期値に含まれています)

Emacs Lispで1+2+3を計算するには次のように書きます。

#+BEGIN_SRC emacs-lisp
(+ 1 2 3)
#+END_SRC

#+RESULTS:
: 6

このOrg文書を C-c C-e でLaTeXやHTML等でエクスポートすると、ソースコードと実行結果の両方あるいは片方だけが出力されます(どちらが出力されるかは言語毎のデフォルト値や後述するヘッダー引数(:exportsにnone、code、results、bothを指定出来る)によって変わります)。

また、行の中にソースコードを埋め込むことも出来ます(インラインコードブロック)。例えばorgファイル中に次のように書けます。

Emacs Lispで2*3を計算するには src_emacs-lisp[:exports code]{(* 2 3)} のように書く。
結果はもちろん src_emacs-lisp[:exports results :eval no-export]{(* 2 3)} {{{results(=6=)}}} である。

src_言語名[ヘッダー引数]{コード本体} の形で段落中にソースコードを記述できます。インラインコードブロックの上でも C-c C-c を押すとコードが評価され、結果はその右に挿入されます。エクスポートすると言語毎のデフォルト値や指定されているヘッダー引数に従ってコードそのものが出力されたり結果のみが出力されたりします。

コードブロックに関連するキー操作

コードブロックを書いて、評価(実行)して、エクスポートする際には、次のキー操作が便利です。

(場所)キー操作 関数 動作
C-c C-, org-insert-structure-template 各種ブロック(コードブロックに限らず、=#+BEGIN_= で始まり #+END_ で終わるもの)を挿入します。
(コードブロック上で) C-c ' org-edit-src-code コードを別バッファで編集します。編集バッファから出るには再度C-c 'を押します。 (公式マニュアル: Editing source code - The Org Manual)
(コードブロック上で) C-c C-c org-babel-execute-src-block コードを評価(実行)します。 (公式マニュアル: Evaluating code blocks - The Org Manual)
(コードブロック上で) C-c C-v j org-babel-insert-header-arg ヘッダー引数を挿入します。
(orgファイル内で) C-c C-e org-export-dispatch エクスポートメニューを表示します。htmlでエクスポートしてブラウザで開くには続けてh oと打ちます。エクスポート時に各コードブロックは評価されます(後述するヘッダー引数:eval no-exportで抑制も出来ます)。

その他コードブロックに関するキー割り当てがあります。(公式マニュアル: Key bindings and Useful Functions (The Org Manual))

基本構文

(公式マニュアル: Structure of Code Blocks (The Org Manual))

一般に、コードブロックは次のような形式をしています。

#+NAME: <name>
#+HEADER: <header>...
#+HEADER: <header>...
#+BEGIN_SRC <language> <switch>... <header>...
<body>
#+END_SRC

#+BEGIN_SRC の後には言語名の他、様々なオプションを指定できます。また、 #+BEGIN_SRC の直前に #+NAME で名前を付けたり、 #+HEADER で追加のオプションを指定したりもできます。

インラインコードブロックは次のような形式をしています。

src_<language>{<body>}
src_<language>[<header>...]{<body>}

インラインコードブロックで指定できるオプションは通常のソースコードブロックとほぼ同等ですが、結果の表現方法が違うため一部で使用できない機能があります(結果のキャッシュなど)。

より具体的な例は言語毎の書き方を参照してください。

名前付きのコードブロック

#+BEGIN_SRC の直前に #+NAME: <name> と書くことで、コードブロックに名前を付けられます。

コードブロックに名前を付けることには、次のような使い道があります。

コードブロックと結果の対応関係

コードブロックに名前を付けると評価結果との対応関係を明確に出来ます。そのため、コードブロックに対する評価結果を離れた場所に置くことが可能になります。

コードブロックを評価した結果は通常コードブロックの直後に挿入されますが、コードブロックと同じ名前が付いた #+RESULTS: <name> があればその直後に挿入されます。

#+NAME: elisp-hello-world-ex
#+BEGIN_SRC emacs-lisp
(concat "hello, " "world")
#+END_SRC

結果は次のようになる。

#+RESULTS: elisp-hello-world-ex
: hello, world

コードブロックと結果の間に何か文章を入れたい場合に最適です。

C-c C-v r で指定した名前を持つ結果へジャンプすることも出来ます。

コードブロックを名前で参照

名前の付いたコードブロックは他から名前で参照できます。

例えば、まず次のように名前の付いたコードブロックを作成します。

#+NAME: multiply
#+BEGIN_SRC emacs-lisp :var x=2 :var y=3
(* x y)
#+END_SRC

この例ではEmacs Lispのコードブロックに「multiply」という名前を付けています。コードブロックには :var というヘッダー引数が二つ指定されていて、 xy という変数が定義されています。

次は、名前の付いたコードブロックを関数のように呼び出す例です。エクスポートすると結果だけが出力されます。

#+CALL: multiply(x=5, y=6)

#+RESULTS:
: 30

↑CALLの上でC-c C-cするとRESULTSが生成される。

次は、noweb参照の例です。 <<multiply>> と書いた部分が参照先のコードブロックの内容 (* x y) に置き換わります。ヘッダー引数に :noweb yes を指定する必要があります。

#+BEGIN_SRC emacs-lisp :noweb yes
(defun multiply (x y)
  <<multiply>>
)
#+END_SRC

また、次はEmacs Lispのコードから org-babel-lob--src-info という関数を使ってコードブロックの情報を得る例です。

#+begin_src emacs-lisp :results pp
(org-babel-lob--src-info "multiply")
#+end_src

#+RESULTS:
#+begin_example
("emacs-lisp" "(* x y)"
 ((:results . "replace")
  (:exports . "code")
  (:var . "x=2")
  (:var . "y=3")
  (:lexical . "no")
  (:tangle . "no")
  (:hlines . "no")
  (:noweb . "no")
  (:cache . "no")
  (:session . "none"))
 "" "multiply" 4211 "(ref:%s)")
#+end_example

他にもアイデア次第で色々な使い道があることでしょう。

CALLについては公式マニュアルのEvaluating Code Blocks (The Org Manual)、noweb参照についてはnoweb参照を参照してください。

C-c C-v g で指定した名前を持つコードブロックへジャンプすることも出来ます。

ヘッダー引数

(公式マニュアル: Using Header Arguments (The Org Manual))

#+BEGIN_SRC <言語ID> の後には : で始まる様々なオプションが指定できます。

最も重要なのは :exports:results (最初のコロンと最後のsが抜けないように注意すること)の二つです。

なお、ヘッダー引数は C-c C-v C-j でインタラクティブに挿入できます。

:exports

:exports はエクスポート時の出力(コードブロックがどうエクスポートされるか)を指定します。コードを出力するかしないか、評価結果を出力するかしないかの組み合わせで次の4つのうちのいずれかを指定できます。(公式マニュアル: Exporting Code Blocks)

  • コードブロックのみを出力する(code)
  • 評価結果のみを出力する(results)
  • 両方を出力する(both)
  • 何も出力しない(none)

:exports none の例:

#+NAME none-exports-example
#+BEGIN_SRC emacs-lisp :exports none :var x=0
(* x x) ;;このコードはエクスポートされません。他から名前で参照されるためだけのものです。
#+END_SRC

:results

:results は評価結果をどのように扱うかを指定します(公式マニュアル: Results of Evaluation (The Org Manual))。大きく分けて4つのカテゴリーに分類できる値を組み合わせて指定できます。

  • Collection : どこから結果を得るか
    • value : 言語が返した値(デフォルト) (functional mode)
    • output : 標準出力 (scripting mode)
  • Type : 結果の種類(使用例は結果の受け取り方を参照のこと)
    • table, vector : 表
    • list : リスト
    • scalar, verbatim : 単一の値
    • file : ファイルへのリンク
  • Format : 結果の出力形式
    • raw : そのままOrg文書として出力
    • org : orgのコードブロック(#+BEGIN_SRC org)として出力
    • html : htmlのエクスポートブロック(#+BEGIN_EXPORT html)として出力
    • latex : latexのエクスポートブロック(#+BEGIN_EXPORT latex)として出力
    • code : 同じ言語のエクスポートブロック(#+BEGIN_EXPORT 同じ言語)として出力
    • pp : pretty-printしたものを出力(一部の言語のみ対応)
    • drawer : :RESULTS::END: に挟まれた形で出力
    • link, graphics : orgのリンクとして出力
  • Handling : 結果をどう文書中に挿入するか(#+RESULTS:として)
    • replace : 置き換える (デフォルト)
    • silent : 挿入しない (ミニバッファにエコーする)
    • none : 挿入しない (ミニバッファにエコーしない)
    • discard : 挿入しない (エクスポートはされる!)
    • append : 最後に付け加える
    • prepend : 最初に付け加える

:results の例:

#+BEGIN_SRC emacs-lisp :results value raw drawer
"Hello\n\n| table | table |\n| table | table |\n"
#+END_SRC

#+RESULTS:
:RESULTS:
Hello

| table | table |
| table | table |
:END:

:results は言語毎にデフォルト値が異なるので注意が必要です。コードブロックの上で C-c C-v TAB を押すと現在の値が確認できます。または ob-<言語名>.el の変数(org-babel-default-header-args:<言語名>)や関数(org-babel-execute:<言語名>)の中身を見てどのように実装されているかを確認する手もあります。

エクスポート時の評価を抑制する(:eval)・結果のキャッシュ(:cache)

エクスポートするたびにコードブロックを評価するのは煩わしい場合があります。

そんな場合は :eval no-export を指定するとエクスポート時の評価を抑制できます。(公式マニュアル: Limit code block evaluation - Evaluating Code Blocks (The Org Manual))

または :cache yes を指定してあらかじめ実行しておくとエクスポートするたびにコードブロックを評価しなくて済みます。ただしこの方法はインラインコードブロックには使用できません。(公式マニュアル: Cache results of evaluation - Evaluating Code Blocks (The Org Manual))

:var :session :dir :prologue :epilogue

:var
変数を定義
:session
セッション
:dir
カレントディレクトリ
:prologue
コードの先頭に挿入するコード
:epilogue
コードの最後に挿入するコード

詳しくは 公式マニュアル: Environment of a Code Block (The Org Manual) を参照してください。

:noweb

noweb参照を参照してください。

:tangle :mkdirp :comments :padline :shebang :tangle-mode :no-expand

コードブロックの内容を別のファイルに書き出す機能に関するオプションです。

(公式マニュアル: Extracting Source Code (The Org Manual))

その他

コードブロック上で C-c C-v j を押すとヘッダー引数を選んで挿入できます。それでどんな物があるのかある程度確認できます。

noweb参照

(公式マニュアル: Noweb reference syntax - The Org Manual)

nowebとは文芸的プログラミング(Literate programming - Wikipedia)のツールなのだそうです(noweb - Wikipedia)。

よく知りませんが、名前付きブロックを参照する書き方ができます。

まず名前付きのコードブロックを作ります。次の例では js-hello-example という名前のコードブロックを作り、 suffix という変数も定義しました。

#+NAME: js-hello-example
#+BEGIN_SRC js :var suffix="world"
return "hello_" + suffix;
#+END_SRC

それを << 名前 >> という形式で参照します。つまり <<js-hello-example>> とします。

#+BEGIN_SRC js :noweb yes
function sayHello(){
    <<js-hello-example>>
}
return sayHello();
#+END_SRC

これをエクスポートすると次のように中身がそのまま展開されます。

#+BEGIN_SRC js :noweb yes
function sayHello(){
    return "hello_" + suffix;
}
sayHello();
#+END_SRC

括弧を付けると関数のように呼び出して実行結果に置き換わります。

#+BEGIN_SRC text :noweb yes
<<js-hello-example()>>
#+END_SRC

上は下のようにエクスポートされます。

hello_world

括弧の中に変数の値を指定するとコードに引き渡されて結果が変わります。

#+BEGIN_SRC text :noweb yes
<<js-hello-example(suffix="moon")>>
#+END_SRC

上は下のようにエクスポートされます。

hello_moon

公式マニュアル: Noweb Reference Syntax (The Org Manual)

言語毎の書き方

(公式マニュアル: Babel: Languages)

ここでは言語毎の具体的な使い方を紹介します。

Emacs Lisp

Emacs LispはEmacsに組み込まれているため最も安定して使えます。

次はEmacs Lispのコードブロックの例です。

Emacsのバージョンを表示するコードと結果は次の通り。

#+BEGIN_SRC emacs-lisp :exports both
(emacs-version)
#+END_SRC

#+RESULTS:
: GNU Emacs 25.3.50.1 (x86_64-w64-mingw32)
:  of 2017-09-20

#+BEGIN_SRC emacs-lisp#+END_SRC の間にカーソルを置いて C-c C-c を押すことで #+RESULTS: 以下が生成されます。

ヘッダー引数 :exports には none code results both が指定でき、コード(リスティング)と評価結果をそれぞれエクスポートするかどうかをコントロールできます。今回は both を指定しているためコードと評価結果の両方がエクスポートされます。実際にエクスポートすると次のようになります。

Emacsのバージョンを表示するコードと結果は次の通り。

(emacs-version)
GNU Emacs 25.3.50.1 (x86_64-w64-mingw32)
 of 2017-09-20

org-mode

Org文書の書き方を説明するためにOrg文書の中にorg言語のコードブロックを書くことは良くあります(まさにこの文書がそのようにして作られています)。

例えば太字、表、コードブロックの書き方を例示するために次のように書いたとします。

太字、表、コードブロックは次のように書きます。

#+BEGIN_SRC org
太字の例:
*bold*

表の例:
|a|0|
|b|0|

コードブロック例:
,#+BEGIN_SRC emacs-lisp
(concat "hello" "world")
,#+END_SRC
#+END_SRC

これをエクスポートすると次のように表示されます。

太字、表、コードブロックは次のように書きます。

太字の例:
*bold*

表の例:
|a|0|
|b|0|

コードブロック例:
#+BEGIN_SRC emacs-lisp
(concat "hello" "world")
#+END_SRC

これを読めば「太字は*で囲むのか」「表は|で区切るのか」といったことが分かることでしょう。

このように書き方を例示した場合、そのすぐ後に実際にどう表示されるかも一緒に掲載したくなる物です。まさに上でそうしているように。これはorg-modeの書き方に限らず他のマークアップ言語でもそうですし、ひいては普通のプログラミング言語でも結果を一緒に掲載するのは良くあることです。これはどのように実現したら良いのでしょうか。手動でマークアップをコピーしてペーストし少し手直ししても良いのですが、もっと良い方法があります。

他の言語と同じようにorg言語のコードブロックの評価結果をエクスポートさせれば良いのです。

Org文書は本来プログラムではないので「org言語のコードブロックの評価結果」というのは何を言っているのか分からないかもしれません。しかしorg言語の評価方法は org-babel-execute:org 関数で定義されています。見てみると基本的にコードブロックの中身をそのまま返すだけとなっています。つまり、org言語のコードブロックを評価するとその結果として書かれているorg言語のコードがそのまま結果としてバッファに挿入されたり、エクスポートされたりするようにできるわけです。

まず :exports には both を指定してコードと評価結果の両方を出力します。 :results のデフォルトは raw silent なのでそのままでは結果は何も出力されません。 :results raw replace としてもいいのですが、実際にやれば分かりますが少し面倒なことになります。 :results raw discard として評価結果をバッファに挿入せず、エクスポートさせるようにしてみましょう。

太字、表、コードブロックは次のように書きます。

#+NAME: org-bold-example
#+BEGIN_SRC org :exports both :results raw discard
太字の例:
*bold*

表の例:
|a|0|
|b|0|

コードブロック例:
,#+BEGIN_SRC emacs-lisp
(concat "hello" "world")
,#+END_SRC
#+END_SRC

これをエクスポートすると次のように表示されます。

#+RESULTS: org-bold-example

これをエクスポートすると次のようにコードと結果が両方(both)表示されます。

太字、表、コードブロックは次のように書きます。

太字の例:
*bold*

表の例:
|a|0|
|b|0|

コードブロック例:
,#+BEGIN_SRC emacs-lisp
(concat "hello" "world")
,#+END_SRC

これをエクスポートすると次のように表示されます。

太字の例: bold

表の例:

a 0
b 0

コードブロック例:

(concat "hello" "world")

デフォルトの :results (変数 org-babel-default-header-args:org) が :results silent なため、そのままでは結果が出力されません。明示的に :results discard と指定するとエクスポート時に評価されて出力されます。 :results replace とすると太字の例からコードブロックの例までがそのまま #+RESULTS: の後に挿入されます。しかしこれだとどこからどこまでが結果か後から判別できなくなるため、次回の評価時に正しく結果をreplaceしてくれなくなってしまいます。なので今回は discard を使いました。

HTMLやJavaScriptのところで紹介するように #+CALL を使う方法もあります。

太字、表、コードブロックは次のように書きます。

#+NAME: org-example
#+BEGIN_SRC org :exports code
太字の例:
*bold*

表の例:
|a|0|
|b|0|

コードブロック例:
,#+BEGIN_SRC emacs-lisp
(concat "hello" "world")
,#+END_SRC
#+END_SRC

これをエクスポートすると次のように表示されます。

#+NAME: ref-org
#+BEGIN_SRC emacs-lisp :exports none :results raw :var ref=""
(cadr (org-babel-lob--src-info ref))
#+END_SRC

#+CALL: ref-org("org-example")

noweb参照を活用する方法もあることでしょう。

コードブロック内にコードブロックを書く方法

ちなみに、org言語のコードブロックの中で #+BEGIN_SRC#+END_SRC はネストできません。

#+BEGIN_SRC org
aaa
#+BEGIN_SRC org
bbb
#+END_SRC
ccc
#+END_SRC

これをエクスポートすると次のように構造が壊れてしまいます。

aaa
#+BEGIN_SRC org
bbb

ccc #+END_SRC

これを避けるためには、行頭に , を入れて # をエスケープします。 * も行頭にあると見出しとして認識されてしまうのでエスケープする必要があります。

#+BEGIN_SRC org
,#+BEGIN_SRC org
,*bold*
,#+END_SRC
#+END_SRC

もちろん行頭の , 自体もエスケープする必要があって、上のように行頭にカンマを一つ表示させるために私は行頭にカンマを二つ打っています。

カンマを三つ打つと なぜかそのまま三つ表示されます。 二つ表示されます。

,,#+BEGIN_SRC org
*bold*
,,#+END_SRC

四つ打っても そのまま四つ表示されます。 三つ表示されます。

,,,#+BEGIN_SRC org
*bold*
,,,#+END_SRC

行頭に二つ表示させたい場合はどうしたらいいんでしょうか……。 (いつの間にか修正されたようです)

HTML

準備

  • 使っているモード(web-mode等)に合わせて org-src-lang-mode の書き換えが必要です。

    (add-to-list 'org-src-lang-modes '("html" . web))
    

Org文書の中でHTMLのコードを例示しつつそのHTMLをエクスポートしたHTMLに埋め込む

HTMLの書き方の説明をOrg文書で書きたい場合、Org文書の中にHTMLのコードブロックを書くことになります。

例えば次のコードブロックは、HTMLでcanvas要素とscript要素を使って絵を書く例を示しています。

#+BEGIN_SRC html :exports both
<div>
<canvas width="320" height="240" />
<script>
//<![CDATA[
  var canvases = document.getElementsByTagName("canvas");
  var canvas = canvases[canvases.length - 1]; //last canvas element
  var ctx = canvas.getContext("2d");
  var angle = 0;
  function draw(){
    ctx.fillStyle = "rgb(128, 128, 255)";
    ctx.fillRect(0, 0, 320, 240);

    ctx.fillStyle = "rgb(64, 64, 128)";
    ctx.beginPath();
    ctx.arc(160, 120, 110, 0, 2*Math.PI, false);
    ctx.fill();

    ctx.strokeStyle = "rgb(255, 255, 255)";
    ctx.lineWidth = 2;
    ctx.beginPath();
    ctx.moveTo(160, 120);
    ctx.lineTo(160+100*Math.sin(angle*Math.PI/180), 120-100*Math.cos(angle*Math.PI/180));
    ctx.stroke();
  }
  draw();
  setInterval(function(){ angle += 6; draw();}, 1000);
//]]>
</script>
</div>
#+END_SRC

当然「これをブラウザで見るとこうなりますよ」というようにHTMLの表示結果を併記したいのですが、素直にexportsにbothを指定しても結果はエクスポートされません。試しにC-c C-cでHTMLコードブロックを実行しようとすると失敗します。

org-babel-execute-src-block: No org-babel-execute function for html!

(org言語の時と違って) org-babel-execute:html が定義されていないのでそのままでは実行できません。

元々HTMLはプログラミング言語ではなくマークアップ言語なので、実行して結果が出るようなものではありません。 しかしHTMLの解説をする場合に書き方とブラウザでの表示結果を併記したいことは良くありますし、そのために例として書いたマークアップをそのままHTMLに埋め込められれば便利です。

解決方法は色々あります。

  1. noweb参照でコードの重複を避ける方法

    まず名前付きのhtmlコードブロックを作成し、それを後からorgコードブロックから参照します。

    canvasを使う例:
    #+NAME: html-example
    #+BEGIN_SRC html :exports code
    <div>
    <canvas width="320" height="240" />
    <script>
    //<![CDATA[
      var canvases = document.getElementsByTagName("canvas");
      var canvas = canvases[canvases.length - 1]; //last canvas element
      var ctx = canvas.getContext("2d");
      var angle = 0;
      function draw(){
        ctx.fillStyle = "rgb(128, 128, 255)";
        ctx.fillRect(0, 0, 320, 240);
    
        ctx.fillStyle = "rgb(64, 64, 128)";
        ctx.beginPath();
        ctx.arc(160, 120, 110, 0, 2*Math.PI, false);
        ctx.fill();
    
        ctx.strokeStyle = "rgb(255, 255, 255)";
        ctx.lineWidth = 2;
        ctx.beginPath();
        ctx.moveTo(160, 120);
        ctx.lineTo(160+100*Math.sin(angle*Math.PI/180), 120-100*Math.cos(angle*Math.PI/180));
        ctx.stroke();
      }
      draw();
      setInterval(function(){ angle += 6; draw();}, 1000);
    //]]>
    </script>
    </div>
    #+END_SRC
    ………略………
    
    ………略………
    先のcanvasを使う例をブラウザで表示すると次のようになる:
    #+BEGIN_SRC org :noweb yes :exports results :results raw replace
    #+BEGIN_EXPORT html
    <<html-example>>
    #+END_EXPORT
    #+END_SRC
    

    これをHTMLでエクスポートすると、HTMLのリストの後にそのリストの中のHTML(<div>~</div>まで)がエクスポートされるHTML文書の中にそのまま挿入されます。結果script要素が実行されてcanvas要素に描画が行われます。

    :results raw を使うのがミソです。rawはOrg形式としてそのまま文書に埋め込まれます。 :results org としてしまうと結果が #+BEGIN_SRC org#+END_SRC で囲われてしまうので注意。 #+BEGIN_EXPORT html :noweb yes と書ければ簡単なのだけど書けません。

  2. noweb参照とhereドキュメントで対処する方法

    1とほぼ同様ですが、何かhereドキュメントが使える言語でコードブロックをそのままエクスポートする方法です。 :results html は結果を #+BEGIN_EXPORT html で囲ってくれるので。

    #+BEGIN_SRC perl :noweb yes :results output html :exports results
    print<<EOF;
    <<html-example>>
    EOF
    #+END_SRC
    
  3. 実行関数を定義する方法

    org-babel-execute:html が定義されていないのが原因なので、素直に定義してしまえば良いという話です。

       (defun org-babel-execute:html (body params) body)
    
    #+BEGIN_SRC html :results html :exports both :noweb yes
    <<html-example>>
    #+END_SRC
    
  4. #+CALL を使用する方法

    (参考: org mode - Export Javascript source block to script tag in HTML when exporting Org file to HTML - Emacs Stack Exchange)

    #+NAME: ref-html
    #+BEGIN_SRC emacs-lisp :exports none :results html :var ref=""
    (concat "<div>" (cadr (org-babel-lob--src-info ref)) "</div>")
    #+END_SRC
    
    #+CALL: ref-html("html-example")
    
  5. ob-browserを使用する方法

    ob-browser を使用するとPhantomJS経由でスクリーンショットを撮って画像化してくれます。

  6. misohena/ob-htmlを使用する方法

    上記3や5のようなことを行う misohena/ob-html: Org Babel Functions for HTML Code Blocks というパッケージを作成しました。

うまく行くと次のように例示したHTMLがそのままページに埋め込まれてブラウザで実行されます。


参考:

JavaScript

JavaScriptを評価する方法はいくつかあるのですが、ここでは最も安定して使えるNode.jsを使う方法を紹介します。

準備

  • node.jsをインストールしてnodeコマンドへパスを通します。
  • 変数 org-babel-js-cmd を設定(確認)します。
  • 別のモード(js2-mode等)を使っている場合は org-src-lang-mode の書き換えが必要かもしれません。

    (add-to-list 'org-src-lang-modes '("js" . js2))
    
  • org-babel-load-languages に '(js . t) を追加

例1 コードとコンソールに出力した結果を併記する

#+BEGIN_SRC js :results output :exports both :cache yes
class Person{
    constructor(name, age){
        this.age = age;
        this.name = name;
    }
    greet(){
        return "my name is " + this.name + " " + this.age;
    }
}
var hanako = new Person("Kikuko", 17);
console.log(hanako.greet());
#+END_SRC

#+RESULTS:
: my name is Kikuko 17

上の例ではconsole.logを使って結果を出力しています。:resultsにoutputを指定することで標準出力に出力された文字列を結果として扱うことができます。

例2 コードブロックに変数で値を引き渡し、コードが返した値を結果とする

JavaScriptが返した値をEmacsが受け取り、それを結果として扱うことが可能です。

#+BEGIN_SRC js :results value :exports both :cache yes :var count=3
return Array.from(Array(count).keys());
#+END_SRC

#+RESULTS:
| 0 | 1 | 2 |

ヘッダー引数 :var count=3 でJavaScriptへ値3を引き渡しています。JavaScriptのコードは配列 [0,1,2] をreturnで返します。 :results value の指定によりその値(配列)を結果として扱います。結果はtableの形でOrg文書内に挿入されます。

例3 コードを表示しつつエクスポートしたHTMLにも埋め込む例

コードブロック内のJavaScriptを、エクスポート後のHTML文書内に埋め込みたい場合もあるでしょう。

最後の要素の親の親(最後のscript要素の親)へdiv要素を追加する例:

#+NAME: js-example
#+BEGIN_SRC js :exports code
(function(){
    var lastNode = document.body;
    while(lastNode.lastChild){ lastNode = lastNode.lastChild;}
    var div = document.createElement("div");
    div.innerHTML = "Hello World from JavaScript Code";
    div.style = "border: 1px solid;";
    lastNode.parentNode.parentNode.appendChild(div);
})();
#+END_SRC

実際にやってみる:

#+NAME: ref-js
#+BEGIN_SRC emacs-lisp :exports none :results html :var ref=""
(concat "<script>" (cadr (org-babel-lob--src-info ref)) "</script>")
#+END_SRC

#+CALL: ref-js("js-example")

↑ここに見えますか?

(参考: org mode - Export Javascript source block to script tag in HTML when exporting Org file to HTML - Emacs Stack Exchange)

Java

準備:

  • JDKをインストールします。
  • 変数を設定するかパスを通します。
    • org-babel-java-compiler (default: javac) (%JAVA_HOME%/bin/javac)
    • org-babel-java-command (default: java)
  • org-babel-load-languages に '(java . t) を追加します。

Javaのコードを実行するにはメインのクラス名を :classname で指定する必要があります。

#+BEGIN_SRC java :results output :exports both :classname HelloWorld :cmdline -Dorgmode.arg=test1234 :cache yes
public class HelloWorld {
    public static void main(String[] args){
        System.out.println("Hello");
        System.out.format("orgmode.arg=%s", System.getProperty("orgmode.arg"));
    }
}
#+END_SRC
Hello
orgmode.arg=test1234

変数(:var)や引数を渡す仕組みはありません(Org9.1時点。org-babel-execute:javaを参照)。無理矢理やるならcmdlineとシステムプロパティを使うくらいでしょうか?

C/C++/D

準備:

  • 変数を設定します。
    • org-babel-C-compiler (default:gcc)
    • org-babel-C++-compiler (default:g++)
    • org-babel-D-compiler (default:rdmd)
  • org-babel-load-languages に '(C . t) を追加します。

例1:

#+HEADER: :includes <iostream> <cmath>
#+HEADER: :var x=1.0 :var y=2.0
#+BEGIN_SRC C++ :exports results :results output :cache yes
std::cout << "hello " << M_PI << std::endl;
std::cout << "x=" << x << " y=" << y << std::endl;
#+END_SRC
hello 3.14159
x=1 y=2

例2:

#+BEGIN_SRC C++ :exports results :results output table :cache yes
#include <iostream>

int main(int argc, char *argv[]){
    std::cout << 123 << " " << 456 << '\n'
              << 789 << " " << 012 << std::endl;
}
#+END_SRC
123 456
789 10

例3:

#+HEADER: :includes <iostream> <vector> <utility>
#+BEGIN_SRC C++ :exports both :cache yes
std::vector<std::pair<int, int>> v{{0,1}, {2,3}, {4,5}};
for(const auto &e : v){
    std::cout << e.first << ',' << e.second << '\n';
}
#+END_SRC
0 1
2 3
4 5

ditaa

準備:

  • ditaa.jarをどこかに配置します。(http://ditaa.sourceforge.net/#download)
  • 変数を設定します。
    • org-ditaa-jar-path
    • org-ditaa-jar-option
    • org-ditaa-eps-jar-path
  • org-babel-load-languages に '(ditaa . t) を追加します。
#+BEGIN_SRC ditaa :file ditaa-example.png :exports both :cache yes
+--------+   +-----------+   +-------------+
| Source +-->+ Processor +-->+ Destination |
+--------+   +-----------+   +-------------+
#+END_SRC
2017-10-26-ditaa-example.png

書き方等についてはditaaを参照してください。

PlantUML

準備:

  • plantuml.jar をどこかに置いて org-plantuml-jar-path を設定します。
  • plantumlの動作にはgraphvizのインストールと環境変数 GRAPHVIZ_DOT の設定が必要です。
  • graphvizはCygwinやMSYS2、winget等のパッケージにもなっています。
  • org-babel-load-languages に '(plantuml . t) を追加します。

クラス図を描く例:

#+BEGIN_SRC plantuml :file plantuml-example.png :exports results :cache yes
World "1" *-right- "0..*" Animal : contains
Animal <|-- Dog
Animal <|-- Cat

World : void moveAllAnimals(double dt)
Animal : double age
Animal : double getAge()
Animal : void move(double dt)
Dog : void move(double dt)
Cat : void move(double dt)

note top of Animal
  Base class of all animals.
end note
#+END_SRC
2017-10-26-plantuml-example1.png

PlantUML自体については公式サイトを参照してください。

dot

準備:

  • dotコマンドへパスを通します(一応 :cmd ヘッダーでも指定できますがおすすめはしません。ちなみに :cmdline ヘッダーも有効のようです)
  • graphvizはCygwinやMSYS2、winget等のパッケージにもなっています。

適当な有向グラフを描く例:

#+BEGIN_SRC dot :file dot-example.png :exports results :cache yes
digraph {
  a -> b
  b -> c
  a -> c
}
#+END_SRC
2017-10-26-dot-example.png

dot自体の書き方については Graphviz | Graphviz - Graph Visualization Software を参照してください。

R

準備:

  • インストールはインストーラで簡単です。
  • 変数 org-babel-R-command にRコマンドへのパスとコマンドライン引数を設定します。
  • org-babel-load-languages に '(R . t) を追加します。

データを用意:

#+NAME: age-score-table
| Age | Score |
|-----+-------|
|  10 |    82 |
|  15 |   100 |
|   8 |    52 |
|  13 |    75 |
|  12 |    38 |
|   9 |    80 |
|  13 |    92 |
|  11 |    65 |
|  15 |    85 |
|  18 |    98 |
|   3 |    20 |
|  15 |    92 |
|  14 |    78 |
|  12 |    53 |
Age Score
10 82
15 100
8 52
13 75
12 38
9 80
13 92
11 65
15 85
18 98
3 20
15 92
14 78
12 53

org-modeの表から散布図を描く:

#+BEGIN_SRC R :var table=age-score-table :results graphics file :file r-plot.png :width 320 :height 320 :cache yes
plot(table)
abline(lm(table$Score ~ table$Age), col="red")
#+END_SRC
2017-10-26-r-plot.png

org-modeの表からヒストグラムを描く:

#+BEGIN_SRC R :var table=age-score-table :results graphics file :file r-hist.png :width 320 :height 320 :cache yes
hist(table$Age)
#+END_SRC
2017-10-26-r-hist.png

org-modeの表から年齢別スコアを集計(結果を表で表示する例):

#+BEGIN_SRC R :var table=age-score-table :results value :colnames yes :exports results
aggregate(x=list(Score=table$Score),by=list(Age=table$Age),FUN=function(x)c(Mean=mean(x), Count=length(x), Max=max(x), Min=min(x)))
#+END_SRC
Age Score.Mean Score.Count Score.Max Score.Min
3 20 1 20 20
8 52 1 52 52
9 80 1 80 80
10 82 1 82 82
11 65 1 65 65
12 45.5 2 53 38
13 83.5 2 92 75
14 78 1 78 78
15 92.3333333333333 3 100 85
18 98 1 98 98

:colnames yes:rownames yes を付けないと列名や行名を取りこぼします。

R Source Code Blocks in Org Modeに書いてあるようにasciiパッケージを使用してOrg形式で出力し、 :result output で受ける方法もあります。

好きな関数をプロットする例:

#+BEGIN_SRC R :results graphics file :file r-function.png :width 320 :height 320 :cache yes
y <- function(x){return (sqrt(x))}
plot(y, 0, 1)
#+END_SRC
2017-10-26-r-function.png

R自体については R: The R Project for Statistical Computing を参照してください。

結果の受け取り方

ヘッダー引数 :results のFormat毎の違いを見ていきます。コード側では何を返し、それがどう表示されるのでしょうか。

:results table

Emacs Lisp

#+BEGIN_SRC emacs-lisp :results table :exports results
'((1) (1 2) (3 4 5))
#+END_SRC
1    
1 2  
3 4 5

Java

#+BEGIN_SRC java :classname HelloWorld :results table :cache yes
class HelloWorld {
    public static void main(String[] args){
        final String[] hand = {"Guu", "Choki", "Paa"};
        System.out.println("\t" + hand[0] + "\t" + hand[1] + "\t" + hand[2]);
        for(int i = 0; i < 3; ++i){
            System.out.printf(hand[i]);
            for(int j = 0; j < 3; ++j){
                System.out.printf("\t%d", (4+j-i)%3-1);
            }
            System.out.printf("\n");
        }
    }
}
#+END_SRC
  Guu Choki Paa
Guu 0 1 -1
Choki -1 0 1
Paa 1 -1 0

:results list

#+BEGIN_SRC emacs-lisp :results list :exports results
'("orange" "apple" "banana")
#+END_SRC
  • orange
  • apple
  • banana

:results scalar

#+BEGIN_SRC emacs-lisp :results scalar :exports results
'("orange" "apple" "banana" ("tenpura" "sukiyaki"))
#+END_SRC
("orange" "apple" "banana" ("tenpura" "sukiyaki"))

:results pp

#+BEGIN_SRC emacs-lisp :results pp :exports results
'("orange" "apple" "banana" ("tenpura" "sukiyaki"))
#+END_SRC
("orange" "apple" "banana"
 ("tenypura" "sukiyaki"))

:results file

#+BEGIN_SRC emacs-lisp :results file :exports results :cache yes
(let ((filename "2017-10-26-file-result-example.txt"))
  (with-temp-buffer (insert "orange apple banana") (write-region (point-min) (point-max) filename))
  filename)
#+END_SRC

2017-10-26-file-result-example.txt

コードブロックから表を参照する方法

表に #+NAME で名前を付けると :var 変数名 = 表名 で表の中身を参照できます。

#+NAME: payment-table
| 科目   | 金額 |
|--------+------|
| 交通費 |  320 |
| 食費   |  500 |
| 交通費 |  120 |
| 食費   |  140 |
| 交通費 |  300 |
| 食費   |  550 |

#+BEGIN_SRC emacs-lisp :var payments=payment-table :colnames yes
(let (alist)
  (cl-loop for line in payments do
           (let* ((class (nth 0 line))
                  (amount (nth 1 line))
                  (cell (or (assoc class alist)
                            (car (push (list class 0) alist)))))
             (setcar (cdr cell) (+ (cadr cell) amount))))
  alist)
#+END_SRC

#+RESULTS:
| 科目   | 金額 |
|--------+------|
| 食費   | 1190 |
| 交通費 |  740 |

Pingback / Trackback