Author Archives: misohena

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 |
2017-10-22

Emacsでイタリック(斜体)が表示されないのを何とかした(Windows Emacs25.3)

org-modeを使っていて、ふと斜体が表示されないのに気がつきました。

私の最近のフォント設定は前回の通り次のような単純な物でした。

;; 記号をデフォルトのフォントにしない。(for Emacs25.2)
(setq use-default-font-for-symbols nil)
;; デフォルトはASCII用のフォントでなければダメっぽい。
(set-face-attribute 'default nil :family "Inconsolata" :height 120)
;; ASCII以外を指定する。
(set-fontset-font nil '(#x80 . #x10ffff) (font-spec :family "MS Gothic"))

ASCII部分はプログラミング用フォントとして有名なInconsolataを使っています。 それ以外は基本的にMS ゴシック。私はMS ゴシックの低解像度ディスプレイ下でのシャープさをとても評価しているのです。

それでまず試したのはマニュアル(Bold and italic - GNU Emacs FAQ For MS Windows)にもあるこの設定。

(setq w32-enable-synthesized-fonts t)
(set-face-font 'italic "-*-Courier New-normal-i-*-*-11-*-*-*-c-*-iso8859-1")
(set-face-font 'bold-italic "-*-Courier New-bold-i-*-*-11-*-*-*-c-*-iso8859-1")

んー、確かに斜体になります。でもCourier Newは嫌なのでこれをInconsolataなどにしてみてもうまく行きません。MS Gothicなどでもダメです。Consolas等あらかじめ斜体が用意されているフォントならうまくいきます。

ひょっとしたら計算で傾かせている場合はダメなのでしょうか。でも昔は傾いたと思うのですが……。 w32-enable-synthesized-fonts を調べてみましたが、これ現在はobsoleteで何の効果も無いみたいです。ソースを過去に遡って追ってみましたが、Emacs23になってからはどこからも使われていないみたいです。 色々試してみてもどうあがいても斜体がないフォントを斜体にすることができませんでした。

仕方が無いので斜体がある等幅フォント(日本語あり)ということで、Ricty Diminishedを使ってみました。

(set-face-font 'italic "Ricty Diminished:italic")

うん、斜体になります。……でも、日本語は斜体になっていません。あれー????

日本語部分はMS Gothic(非斜体)のままです。ASCII部分は設定の通りRicty Diminishedの斜体。上のフォントセットの設定が優先されているのでしょうか?

斜体専用のfontsetを作ってASCIIもそれ以外もRicty Diminishedにし、italicフェイスのfont属性に設定してみましたが、やはり日本語(非ASCII)はMS Gothic(非斜体)です。

諦めかけたところでふと (describe-face 'default) のfontset:の項目が目に付きました。あれ、faceの属性にもfontsetってあるんですね。試しに (set-face-attribute 'italic nil :fontset "fontset-standard") とやってみるとエラーが出ません。もしかして……と思い、Ricty Diminishedだけのfontsetを:fontset属性に設定してみると、無事日本語も含めて斜体はRicty Diminishedになりました。

なるほどー、italicフェイスのfontset属性がunspecifiedだとデフォルトのfontset(defaultフェイスのfontset属性?)が使われて上で設定したMS Gothicが使われてしまうんですね。だからitalicフェイスのfontset属性で再度非ASCII用のフォントを指定してあげれば良いわけですか。

というわけで、最終的な設定は次のようになりました。

;; 記号をデフォルトのフォントにしない。(for Emacs25.2)
(setq use-default-font-for-symbols nil)

(defun my-font-available-p (name) (find-font (font-spec :name name)))
(cond
 ;; ASCII用のフォントを設定する。
 ;; Inconsolataを優先する。理由:
 ;; - 等幅プログラミング用フォント
 ;; - Windows上でのhintingが良いのでRictyより文字がぼやけない
 ((my-font-available-p "Inconsolata") (set-fontset-font nil 'ascii "Inconsolata-12") (setq-default line-spacing 0.0))
 ((my-font-available-p "Ricty Diminished") (set-fontset-font nil 'ascii "Ricty Diminished-12") (setq-default line-spacing 0.2))
 ((my-font-available-p "Consolas") (set-fontset-font nil 'ascii "Consolas-12")))
;; ASCII以外のフォントを設定する。
(set-fontset-font nil '(#x80 . #x3fffff) "MS Gothic")
;; 斜体フォントを設定する。
;; faceのfontset属性を設定するところがミソ。そうでないと上で設定した非ASCII用フォントが優先されてしまう。
(cond
 ;; Ricty Diminishedを使う。理由:
 ;; - ASCIIにも日本語文字にも斜体バージョンがある(実際には独自にFontForgeで少し角度を増やした物を使っています。その際フォント情報も調整しました)
 ;; - 日本語も等幅である
;;  - Inconsolataと同じプログラミング用フォント
 ;; - Inconsolataには斜体バージョンがない
 ;; - hintingや文字の高さの違いは斜体に限り諦められる
 ((my-font-available-p "Ricty Diminished")
  (create-fontset-from-fontset-spec "-*-*-*-italic-*-mono-*-*-*-*-*-*-fontset-myitalic")
  (set-fontset-font "fontset-myitalic" '(#x80 . #x3fffff) "Ricty Diminished")
  (set-face-attribute 'italic      nil :fontset "fontset-myitalic")
  (set-face-attribute 'bold-italic nil :fontset "fontset-myitalic"))
)

本当は日本語部分はMS Gothicの斜体にしたかったのですが、どうあがいても出来なかったので仕方がありません。日本語の斜体を使う機会は多くはありませんし諦めます。

script slant フォント
ascii normal Inconsolata
非ascii normal MS Gothic
ascii italic Ricty Diminished
非ascii italic Ricty Diminished

という組み合わせで使いたいという人はあまりいないかもしれませんが、ひとまずこんな感じで。

それにしても set-face-attribute の説明に :fontset のことが書いていないのですが大丈夫なのでしょうか。実際常に変更できるわけではないようで、少なくともdefaultフェイスに対する:fontset属性の変更は何故かうまくいきませんでした。defaultフェイスはフレームパラメータと結びついているので制約があるのでしょうか?

一番最初にASCII用のフォントを設定するところですが、同じ事を次のようにも書けます。

(set-face-attribute 'default nil :font "Inconsolata-12")
defaultフェイスのフォント関連属性を変更することで、フレームのfontパラメータも書き換わります。自動的に fontset-auto1 のようなfontsetが作られます。 :family "Inconsolata" :height 120 のような指定をするとfontset-auto1とfontset-auto2の二つが作られたりします。
(set-frame-font "Inconsolata-12") または (set-frame-parameter nil 'font "Inconsolata-12")
フレームのfontパラメータを書き換えるとdefaultフェイスも書き換わります。自動的に fontset-auto1 のようなfontsetが作られます。
(set-fontset-font "fontset-startup" 'ascii "Inconsolata-12")
今回採用した方法とほぼ同じです。起動直後はfontset-startupがフレームに設定されているため、"fontset-startup"と書いてもnilと書いても同じです。余分なfontsetは自動的に作られません。

フレーム、フレームのdefaultフェイス、フレームに現在設定されているfontsetのいずれを修正しても同じような挙動になります。

いやはや、Emacsのフォントまわりは本当に難解ですね。

(2021-07-29追記:現在はFontForgeで自分で斜体に加工したフォントを使っています)

2017-10-17

PowerShellについて少しは真面目に調べてみた

ちょっとした変換作業を効率化するためにbatを書いていたらファイル名の扱いで困った(空白を含むパスやネットワークパスの扱いが絶望的に面倒くさい)ので代わりにPowerShellでやったら(前回)すんなりうまくいったので 、気をよくしてPowerShellについて少しは真面目に勉強してみました。PowerShellってとっつきにくくて何となく見よう見まねで細部は気にせず適当にやり過ごしていたのですが、知らずに使うのも気持ちが悪いですし。

資料

PowerShellの何が分かりづらいって公式のドキュメントが不足していることですよね。特に言語仕様。結構独特な文法やセマンティックスを持っているのでその辺りの説明が必要です。

探してみると次の場所に3.0の言語仕様書があります(docx形式です)。

最新版は見当たりませんが、この手の仕様書は昔のバージョンの方がシンプルで見やすかったりもしますし我慢します。

日本語で簡単にまとめてくださっているサイトとしては次のサイトがありました。

公式っぽいところだと次のサイトが結構重要なことを書いている気がします。

パイプラインとコマンド実行と関数呼び出し

言語仕様のイントロダクションにも書いてあることですが、PowerShellでとても重要なのはパイプラインだと思います。従来のシェルスクリプトはコマンドの実行によって生じたテキストが次のコマンドへパイプでつながれていきます。しかしPowerShellではコマンドの実行結果はオブジェクトであり、それが次のコマンドへ流れていきます。この一連のオブジェクトが流れる道をパイプラインと呼びます。

PowerShellでのコマンドは、外部のスクリプトや実行ファイルだけでなくユーザーが定義した関数なども含まれます。

コマンドを実行する方法はいくつかありますが、基本的には「コマンド名 引数1 引数2 …」という単純な構文を使います。言語仕様のexpressionを見ても式の中に関数呼び出し構文というのがありません。関数もコマンドですから、式の中ですらカッコで囲んでこの構文を使って呼び出します(メソッド呼び出し構文は式の中にあります。「オブジェクト . メソッド (引数…)」みたいなやつ)。

例えば次のようなtupleという関数。この関数は引数で指定した二つの数を要素とする配列オブジェクトをパイプラインへ出力します。

function tuple($a, $b){$a,$b}

この関数を呼び出すには次のようにコマンドと同じように実行します。

tuple 2 3 #結果は (2, 3) というArray

コマンドを実行した結果、(2, 3)という2要素の配列(Array)オブジェクトが生じるのですが、特に行き先が指定されていないのでコンソールに表示されます。

tuple 2 3 > result.txt

このようにリダイレクトすれば結果をファイルへ出力することも出来ます。

次のように式の中からコマンドを実行して結果を演算することも出来ます。

(tuple 2 3) * 2 + (tuple 4 5) #結果は(2, 3, 2, 3, 4, 5)というArray

「配列 * 整数」は配列の指定回数の繰り返しを作ります。「配列 + 配列」は連結した配列を作ります。

この辺りの事情は外部のスクリプトを呼び出すときでも同じです。例えば次のようなtuple.ps1というファイルを作成します。

# tuple.ps1
$args[0],$args[1]

これを呼び出すには次のようにします。

.\tuple.ps1 2 3 #結果は (2, 3) というArray
.\tuple.ps1 2 3 > result.txt
(.\tuple.ps1 2 3) * 2 + (.\tuple.ps1 4 5) #結果は(2, 3, 2, 3, 4, 5)というArray

重要なのは、こうしてコマンドを実行するとその都度生じた値がパイプラインへ流れるということです。

流す先が実際にどこになるかは呼び出し側によって変わります。コンソール、ファイル、演算子の項、コマンドの引数、変数、などなど。

流したくなければ明示的に破棄する必要があります。

.\tuple.ps1 2 3 > $null
[void](.\tuple.ps1 2 3)
$null = .\tuple.ps1 2 3

このようにすればコマンドを実行して生じた値はどこへも流れず破棄されます。

ちなみに式のトップレベルにある代入演算子は、その結果がパイプラインへ流れません。

$a = "hello" #helloは変数に格納されるのでパイプラインへは流れない

「トップレベル」と断っていると言うことは、トップレベルでなければ流れます。

($a = "hello") # 式のトップレベルはカッコなので代入演算子の結果であるhelloがパイプラインへ流れる。

変数へ代入するたびにいちいち破棄が必要になるのは面倒だからでしょう。意味的にもリダイレクトと同じようにパイプラインの流し先を変数にしただけと考えられます。

この辺りの事情は関数の中でも同じです。

関数というと何か値を返すものと考えますが、PowerShellでももちろんそう考えても良いのですが、返す先は結局はパイプラインなのです。

function compute($filename){
  echo "begin"
  $result = 42 #$result = very_complex_processing $filename の代わり
  echo "end"
  $result
}
compute("example.txt") > result.txt

例えばこのようなcomputeという関数があったとき、result.txtはどのようになるでしょうか。 Rubyあたりをやっていると最後の$result、つまり42だけ出力されそうな気がしてしまいますが、PowerShellでは「begin end 42」が出力されます。

解説をすると次のようになります。

function compute($filename){
  echo "begin" # beginがパイプラインへ流れます。
  $result = 42 # トップレベルにある代入演算子の結果はパイプラインへ流れません。
  echo "end" # endがパイプラインへ流れます。
  $result # $resultの評価結果がパイプラインへ流れます。
}
$r = compute("example.txt") # パイプラインの接続先は変数r。$rは3要素の配列("begin", "end", 42)になります。

この辺りのことが分かっていれば、次の関数もよく理解できるでしょう。

function range($first, $last){
  for($i = $first; $i -le $last; ++$i){
    $i # パイプラインへ$iの値が流れる
  }
}
range 10 15 #結果はArray(10, 11, 12, 13, 14, 15) 10..15と同じ
2017-10-16 ,

PowerShellスクリプトへファイルをドラッグ&ドロップする(bat不要)

ショートカットのリンク先を工夫すればOK。

単純に.ps1へのショートカットを作ってもダメ。.ps1を開く既定のハンドラが登録されていないので。

次のような記事もあるくらいだし、漠然とbatファイル経由でないとダメだと思っていた。

でも次のような記事を見つけて試してみたらうまくいった。

つまり、適当なショートカットを作成して、リンク先を powershell -NoProfile -File ファイル名(.ps1) とすればOK。

色々オプションもあるみたいなので注意。

$Args にちゃんとドロップしたファイルのパスが格納される。空白文字が入っているパスでも大丈夫。UNCでも大丈夫。

考えてみれば当たり前の話なのかもしれないけど、この方法でちゃんとドロップしたファイル名だけが $Args に入るというのはちょっと不思議なような気もする。 -File ファイル名.ps1 の後に適当な文字列を入れて試すとその文字列は $Args[0] に入るのでそういう仕様みたい。

2017-10-15

2017秋の新番組

良い滑り出しかなと思ったのは次:

秋の新番組第一話、最初サクサク切りまくって「今期は楽が出来るかな~」と思っていたのですが後半○を付けたものが多く出ました。

印象 開始日時 チャネル タイトル
10/01(日) 07:00~ テレビ東京 レゴ ニンジャゴー 新シリーズ
× 10/01(日) 25:00~ TOKYO MX お見合い相手は教え子、強気な、問題児
10/01(日) 25:35~ テレビ東京 銀魂 ポロリ篇
10/02(月) 24:00~ TOKYO MX UQ HOLDER!~魔法先生ネギま!2~
× 10/02(月) 25:00~ TOKYO MX ディアホライゾン(被)
× 10/02(月) 25:05~ TOKYO MX aiseki MOGOL GIRL
10/02(月) 25:35~ テレビ東京 おそ松さん 第2期
× 10/03(火) 18:25~ テレビ東京系 ブラッククローバー
10/03(火) 21:54~ TOKYO MX アイドルマスター シンデレラガールズ劇場 第2期
× 10/03(火) 23:00~ TOKYO MX 戦刻ナイトブラッド
10/03(火) 24:30~ TOKYO MX 食戟のソーマ 餐の皿 (第3期)
× 10/03(火) 25:00~ TOKYO MX お酒は夫婦になってから
10/04(水) 17:20~ NHK Eテレ うっかりペネロペ 新シリーズ(第4期)
× 10/04(水) 22:25~ TOKYO MX あめこん!!
× 10/04(水) 22:30~ TOKYO MX TSUKIPRO THE ANIMATION
× 10/04(水) 24:00~ TOKYO MX このはな綺譚
10/05(木) 22:00~ TOKYO MX URAHARA
10/05(木) 23:30~ TOKYO MX Just Because!
× 10/05(木) 24:00~ TOKYO MX 十二大戦
× 10/05(木) 25:58~ TBS DYNAMIC CHORD(ダイナミックコード)
10/06(金) 21:54~ TOKYO MX 大正ちっちゃいさん
× 10/06(金) 22:00~ TOKYO MX ドリフェス! R (2ndシーズン)
10/06(金) 22:30~ TOKYO MX 少女終末旅行
10/06(金) 24:30~ TOKYO MX キノの旅 -the Beautiful World- 新作
× 10/06(金) 25:05~ TOKYO MX Dies irae
10/06(金) 25:23~ テレビ東京 VANISING LINE
10/06(金) 25:40~ TOKYO MX 王様ゲーム The Animation
10/06(金) 25:55~ TBS 結城友奈は勇者である 第2期
× 10/06(金) 26:10~ TOKYO MX グラマラスヒーローズ
× 10/07(土) 06:54~ テレビ東京 シルバニアファミリー ミニストーリー
10/07(土) 09:20~ NHK Eテレ ピングー in ザ・シティ
10/07(土) 09:27~ NHK Eテレ PEANUTS スヌーピー ショートアニメ
10/07(土) 17:30~ 日本テレビ系 タイムボカン 逆襲の三悪人
10/07(土) 17:35~ NHK Eテレ クラシカロイド 第2シリーズ
10/07(土) 22:00~ TOKYO MX 宝石の国
10/07(土) 22:30~ TOKYO MX ラブライブ!サンシャイン!! 第2期
10/07(土) 23:30~ TOKYO MX アイドルマスター SideM
10/07(土) 24:30~ TOKYO MX ブレンド・S
10/07(土) 25:00~ TOKYO MX 鬼灯の冷徹 第弐期
10/07(土) 25:30~ TOKYO MX 魔法使いの嫁
10/08(日) 10:00~ テレビ東京系 カードファイト!! ヴァンガードG Z(第9期)
10/08(日) 22:00~ TOKYO MX アニメガタリズ
10/08(日) 22:30~ TOKYO MX 妹さえいればいい。
10/08(日) 23:00~ TOKYO MX クジラの子らは砂上に歌う
10/08(日) 24:00~ TOKYO MX 干物妹!うまるちゃんR (第2期)
10/08(日) 24:30~ TOKYO MX 血界戦線 & BEYOND (第2期)
10/08(日) 25:35~ TOKYO MX Code:Realize ~創世の姫君~
10/09(月) 24:30~ TOKYO MX つうかあ
× 10/09(月) 25:35~ TOKYO MX おにゃんこポン
10/09(月) 25:40~ TOKYO MX ネト充のススメ
10/09(月) 26:05~ テレビ東京 Wake Up, Girls!新章
10/10(火) 22:05~ AT-X ラブ米(ラブコメ)-WE LOVE RICE- 第2期
10/10(火) 25:41~ TOKYO MX EVIL OR LIVE
10/11(水) 25:05~ TOKYO MX 僕の彼女がマジメ過ぎるしょびっちな件
10/12(木) 24:55~ フジテレビ いぬやしき
10/13(金) 22:30~ WOWOW ROBOMASTERS THE ANIMATED SERIES
10/14(土) 23:00~ NHK Eテレ 3月のライオン 第2シリーズ

これは番組の傾向が偏っていたのか、それとも視聴時の体調の変化によるものなのか不明。

2017-10-11

浄土平周辺(一切経山、五色沼、家形山、吾妻小富士、吾妻小舎)へ行った

はじまり

魔女の瞳こと五色沼を見に一切経山(いっさいきょうざん)へ行ってきました。

きっかけはTwitter。うーん綺麗ですね。

調べてみると、福島県に浄土平というところがあって、そこから徒歩で1~2時間くらいで行けるみたいです。裏磐梯の五色沼とは違います(そっちは中学の修学旅行で行ったような)。登山としては初心者レベルなので私でも大丈夫そうです。浄土平までは福島駅から観光路線バス(福島交通 - 観光路線バス『スカイライン循環線』)が出ています。通常は土日のみ、紅葉シーズン(10月~)は毎日運行だとか。天気も大丈夫そう。良し行くぞ。

それにしてもバスの本数は1日2本、それもずいぶん遅い時間から動き出すんですね。最初の便が昼前に浄土平着。最後の帰りの便が15:40発なのでほとんど滞在できません。と、地図を見ていたら吾妻小舎の文字が。どうやら山小屋のようです。

吾妻小舎は浄土平から歩いてすぐの所にある山小屋です。これを利用すれば滞在時間を丸一日延ばせますね。紅葉の時期は混みそうですが土曜日を避ければ大丈夫でしょう。というわけで予約の電話。携帯はつながらなかったので微温湯温泉にある固定電話の方へ。無事予約が出来ました。一人布団一枚保証だそうなので安心ですね。

福島駅への交通はに書いたとおり。行きはバスに乗り遅れてはいけないので新幹線にしました。帰りはバスの時間が読めないので当日決めましょう。

コースや地形はYamakei Online他で確認。コースタイムを元にゆとりを持たせて大まかなスケジュールを作成。

というわけで、荷物を準備して出発。

浄土平へ

早朝発。府中本町-(武蔵野線)-武蔵浦和-(埼京線)-大宮-(新幹線)-福島。途中大宮で朝食。福島で昼食のおにぎりを購入。福島駅前のバス窓口で切符を買ってバス停に一番乗りで並びバスを待ちます。この手のバスは大抵並ぶので、早めに行って一番前の席が取れると良い景色が見られます。

バスに乗って浄土平へ。隣に座った登山者風の方が話しかけてきて吾妻小舎に泊まるとのこと。私もということで、色々おしゃべりをしながら浄土平へ向かいました。日曜日ということもあってバスは補助席も含めて満席。途中で運転手が乗車を断ろうとしていましたが、電話で本社と話をしてなんとか全員乗せていました。いや、あんなところに取り残されちゃたまらないよね。今時はシートベルトの問題もあって色々難しいみたいです。

いよいよ浄土平が近づいてきたところで渋滞。バスが全く動きません。時々動いても一台分進むだけ。どうも浄土平の駐車場が混んでいるようです。一つ前の兎平で下りて歩くことにしました。

2017-10-11-trafic1.jpg 2017-10-11-trafic2.jpg

10分ほどで浄土平に到着。時間も過ぎているのでそのまま登山道へ向かいました。

浄土平ってこんなところ

ちなみに浄土平はこんなところです。

2017-10-11-jyoudodaira.jpg

浄土平関連リンク:

浄土平から一切経山へ

直登ルートなるものもあるらしいのですが、火山ガスの影響で立ち入り禁止とか。いったん西の方へまわってから頂上を目指します。

結構岩がゴロゴロしていて日頃歩かない人間には足へのダメージがつらいですね。一応登山靴を履いてきているのでなんとか。

2017-10-11-to-issaikyou1.jpg 2017-10-11-to-issaikyou2.jpg

中盤の上りが傾斜としては一番きついですが、手を着くような所もありませんし、砂利で滑らないように注意すれば問題ありません。 風が強くて寒いと聞いていたのですが、幸い天気も良く風も穏やかでその点でも苦労しませんでした。

2017-10-11-to-issaikyou3.jpg 2017-10-11-to-issaikyou4.jpg

1時間ほどで一切経山到着。山頂付近一帯はこんな感じで見渡す限り茶色です。

2017-10-11-issaikyou-top.jpg

しかしその断崖絶壁の下に見えるのは青い湖。

2017-10-11-issaikyou-north.jpg

来た方角(南)を振り返れば吾妻小富士の火口が見えます。

2017-10-11-issaikyou-south.jpg

風もそれほどではなかったので、ゆっくり滞在しておにぎりを頬張りました。

Google Photosがエフェクトをかけてくれた写真:

2017-10-11-goshikinuma-effect.jpg

鎌沼経由で浄土平、桶沼、吾妻小舎へ

元来た道を戻り、避難小屋の少し南にある分岐を右へ。湿原が広がっていて、すぐに鎌沼が見えます。所々紅葉が見られました。

2017-10-11-to-kamanuma.jpg 2017-10-11-to-kamanuma2.jpg 2017-10-11-to-kamanuma3.jpg

2017-10-11-kamanuma1.jpg 2017-10-11-kamanuma2.jpg 2017-10-11-kamanuma3.jpg

鎌沼を通り過ぎて姥ヶ原を過ぎると藪みたいな道をひたすら下り。疲れもピークなので足にきます。

2017-10-11-gezan1.jpg

なんとか浄土平へ戻ってきました。

ビジターセンターの方ではなく、湿原の木道を通って吾妻小舎へ向かいます。

途中少し登って桶沼を経由。

2017-10-11-okenuma.jpg

15:30頃に吾妻小舎にたどり着けました。

吾妻小舎に泊まる

林というか森というか、そんなところにある山小屋です。浄土平から続く道は木々で鬱蒼として少し通りづらかったです。

2017-10-11-azumagoya.jpg

1Fにいた人に声をかけてみると入口は2Fだとか。外の階段を登って入ると管理人の方が寝る場所と食事や消灯時間を案内してくれました。

靴置き場:

2017-10-11-in-azumagoya4.jpg

寝る場所(左から二人組、一つ空けて私、一つ空けて一人、他の客はハシゴを登って上のロフトで計13人ほど):

2017-10-11-in-azumagoya2.jpg

一番乗りでしたが、すぐに他の人たちも到着しました。バスで一緒だった人の姿も。布団を敷いて寝っ転がって本を読んだりしながら食事まで時間を潰しました。ちなみに携帯の電波は入りません(ドコモ系)。

2017-10-11-in-azumagoya1.jpg 2017-10-11-in-azumagoya3.jpg

18時夕食。1Fの食堂で食べます。宿代等はこのとき支払いました。

2017-10-11-diner.jpg

19時前には食べ終わり、消灯まで暇なので星でも見えないかなと外へ散歩に出かけました。

外は真っ暗なのでライト必須。ヘッドランプをつけて浄土平方面へ。国道沿いまで行くと多少開けています。携帯の電波も入ります。あいにくの薄曇りで星はほとんど見えませんでした。月もおぼろげ。時々天頂付近が晴れることがあってそのときに写真を撮りました(夏の大三角形)。

2017-10-11-stars.jpg

浄土平レストハウスまで歩いてみると自動販売機があったのでペットボトルのお茶を購入。山小屋に泊まっているのにこんなに便利で良いのか。

20時過ぎに宿に戻り、布団の上で本を読んで過ごし、21時に消灯。そのまま寝ました。

2日目

一切経山の他には東吾妻山へ登る人が多かったのですが、私は再び一切経山へ。五色沼を挟んで向かいの家形山へ登ってみました。ここからも五色沼が見渡せます。あいにくの曇り空でそれほど綺麗には写りませんでした。残念。

2017-10-11-goshikinuma-side2.jpg 2017-10-11-goshikinuma-side.jpg 2017-10-11-iegata1.jpg 2017-10-11-iegata2.jpg 2017-10-11-iegata3.jpg

再び浄土平へ戻りレストハウスのレストランで昼食。

2017-10-11-resthouse.jpg 2017-10-12-restaurant.jpg

バスまで時間があるので吾妻小富士へ。浄土平のすぐ近くにあります。吾妻小富士だけ登る観光客も多いです。

2017-10-11-azumakofuji.jpg

火口の中は水も溜まっておらず何もありません。足場も広くて案外スリルもありませんでした。一切経山の方から遠目に眺める方が迫力があります。でも見晴らしは良いです。

1時間もかからずまわってしまい浄土平へ下りている間に目の前でバスが発車。次のバスは15:40発。3時間ほど時間が。

ビジターセンターを訪問。良くある感じの地質や植物、動物などの自然環境を紹介する施設です。

2017-10-11-visitor-center.jpg

レストランでおやつを食べたりお土産屋を見たりしても時間があまり、外のベンチがぼやーっと浄土平の景色を眺めて時間を潰し、ようやくバスの時間に。ちょうと雨が降り出しました。車内では半分ぐらい眠りながら過ごし、夕方福島駅着。予定より少し早い到着。

新幹線自由席特急券と自宅駅への乗車券を購入して停まっていたやまびこに乗り込んで帰りました。

2017-10-12-yamabiko.jpg

2017-10-11

アナデン25章クリア

とりあえず25章までクリアしてスタッフロール。苦痛だった。単純作業が。恥ずかしくて身悶えしそうなシナリオが。それで終わってもまた次の冒険に行こうとか言ってる。何やらされるんだろう……。

キャラのレベルはだいたい50から60いかないくらい。早々にマリエルが引けたのがラッキーだったのかな? 戦闘中にサブへのチェンジを繰り返すことで食事しなくても十分回復できることに気がついたのも(ほんとバカバカしいシステム)。

なんでこういうRPGはシナリオを読み進めるためや新しいアートを見るためにつまらない単純作業をやらされるゲームになってしまうんだろう。昔からすごく不思議。

2017-10-06

DVD-ROM, CD-ROMのHDDへの取り込み

ふと思い立って円盤(CD-ROMやDVD-ROM)のハードディスクへの取り込みを進めている。思ったより良い成果を上げている。手間の割に広がるスペースの体積が大きい。

PowerDVDと一緒に付いてきたPower2GOがあったので、それでISOイメージや.p2iという独自形式で取り込んでいる。複数のトラックがあるCDは単一のISOイメージにはできないのでp2iで取り込んでいる。

本のスキャンと違って円盤の取り込みは監視している必要が無い。本のスキャンは必ず給紙のトラブル(重なりとか紙詰まりとか)が発生するのでその対処をしなければならない。それが無くても裁断は面倒だしスキャン時の紙の継ぎ足し、溜まった紙の取り出し、スキャン後のPDFの編集作業とやることが一杯ある。それに対して円盤の取り込みはファイル名を入れてディスクを入れるだけだ。取り込み中に同じPCで他の作業をしていてもそれほど問題にはならない。

この二年くらい部屋の汚さに大変なストレスを感じていた。それというのも昨年亡くなった人の遺品(主に書類)を部屋に持ち帰ったためだ。年々本のスキャンを進めて部屋が片付いてきたところに思いもしなかったところから他人の荷物をぶっ込まれたのだ。その無力感たるや。これでもほとんどの遺品は処分した。服や家具などは問答無用。冷たいと責められもしたがどうしようもない。狭い自室に置く場所など無い。それでも一部の書類は持ち帰った。重要な書類もあったし、それほど重要でなくても故人の生前の活動や考えが感じられる物もあったからだ。その大量の書類のごく一部を持ち帰っただけでも私の部屋はキャパシティを越えてしまった。元々簡単に捨てられるような物は既に捨てている部屋だ。キッチンや通路に積まれた書類を前に為す術は無かった。

まぁ、とはいえ、その書類や自分の本をスキャンしたりして少しずつスペースを空け、本棚の前に積んであるくらいまでには処理した。しかしいよいよ減らなくなったそれは私に一層の無力感を感じさせるのであった。

先日ハードディスクとお立ち台(HDDをUSB接続できるようにする機器)を買った。以前からの課題であった8mmビデオテープの取り込みを一気に進めるためだ。とりあえずエンコードはせずにmp2のまま保存してしまおう。そう考えたのだ。ビデオテープの取り込み自体はそれほど大変じゃない。USB接続のアナログ録画が出来る機器がすでにあるので、それを使って「予約」をしてその予約時間にビデオを再生するだけだ。後は録画が終わって1本分のmp2が完成し、ビデオテープは最後まで再生して自動で頭まで巻き戻る。

ところが、順調に10~20本取り込んだところでトラブルが発生した。ビデオテープがビデオデッキから出てこないのだ。蓋を開けて調べてみたところ、どうやらイジェクトの時に動くパーツが割れてしまったらしい。指で動かしてなんとかテープの出し入れが出来るといった具合だ。これはつらい……。このまま捨ててしまおうかと思ったけれど、とりあえず再び蓋をして放置してある。

そんなこんなで無気力な日々を過ごした後、最近時間ができたのを期にどうにかならないかと考えたところ、本棚の最上段に積まれていた大きなディスクケースが目に付いた。「MSDN」のマークが付いているアレだ。 これが無くなれば空いた場所に本棚の前に積んである書類が収まりそうだ。他にも雑誌や書籍に着いてきたものやPCソフトのパッケージやマニュアルも残っているので、これらも一気に一つのHDDに取りこんでしまおう。幸いHDDはある。

というわけで、案外サクサクと取り込みが進み、無造作に積まれた見苦しい書類が無事本棚に収まった。

2017-10-05

東京都(府中周辺)から福島駅への行き方

福島駅へ行くのにどのどのような方法があるのだろう。パッと思いつくのは次の方法だ。

  • 新幹線
  • 普通列車
  • 高速バス

新幹線

  • 府中本町5:16→5:46武蔵浦和5:52→6:03大宮6:30→7:39福島
  • 乗り換え2回
  • 2時間23分
  • 8220円(運賃4750円, 自由席特急券3470円)

※NAVITIME調べ(2017年10月 平日)

普通列車

  • 府中本町05:16→05:46武蔵浦和05:52→06:03大宮06:12→07:29宇都宮07:40→08:31黒磯08:54郡山10:08→10:54福島
  • 乗り換え5回
  • 5時間38分(新幹線+3時間15分)
  • 4750円(新幹線-3470円)

※NAVITIME調べ(2017年10月 平日)

高速バス

さくら観光の東京-福島間の高速バスが最安値で3000円らしい。これは相当安いケースで普通なら5000円くらいは見ておいた方が良いが、とりあえずこれにしてみる。

高速バス・夜行バス 東京・東京駅周辺発 福島(中通り・会津・浜通り)・福島駅周辺行 空席検索 | さくら観光

  • 分倍河原15:27→15:51新宿15:56→16:11東京駅16:11→16:19鍛冶橋駐車場16:30→22:15福島駅
  • 乗り換え2回
  • 6時間48分(新幹線+4時間25分)
  • 4180円(電車480円+高速バス3000円)(新幹線-4040円)

正直鍛冶橋駐車場まで行くのはつらいのでバスタ新宿くらいにしたいけれど少し料金が上がってしまう。

まとめ

  自由席新幹線 普通列車(対新幹線差) 最安時高速バス(対新幹線差)
料金 8220円 4750円 (- 3470円) 4180円 (- 4040円)
所要時間 2:23 5:38 (+ 3:15) 6:48 (+ 4:25)
乗り換え回数 2回 5回 2回(ただし徒歩距離あり)

考察

まぁ、普通は新幹線を選ぶよね。

とはいえ車内で時間を潰すネタがあるとか列車の旅を楽しむ心の余裕があるとかであれば普通列車は十分魅力的だと思う。浮いたお金で美味しいものが食べられる。

普通列車が高速バスに対して健闘している。最安値が選べなければ普通列車の方が安く済む場合もある。時間帯を柔軟に選べるのも良い。

高速バスのメリットは料金の割に乗り換え回数が少ないことくらいだろうか。

2017-09-30 ,

org-modeの見出しの色を統一する

org-modeの見出しの色が気に入らなかったので調整しました。

見出しの色は大分前に変更したのですが、使っているうちに常々見づらいような気がしていたのです。

変更前のスクリーンショット:

2017-09-30-orgmode-color-before1.png 2017-09-30-orgmode-color-before2.png

なぜ見づらいのだろうと考えたのですが、見出しの色(色相)が階層のレベルによってバラバラだからなのではないかと思い至りました。特に見出しが青になるとき。現在の設定では本文に青系の色が多用されています。リンク、タイムスタンプ、テーブル、etc……。それに加えて見出しまで青だと青色の意味がなんだかよく分からなくなる気がするのです。レベルの深さはインデントで分かるので色で表現する必要はない気がします。

というわけで、次のようなコードを書きながら調整して試行錯誤した後、第一レベルの色である黄色で統一してみました。(最終的にはcustomize-faceで設定)

(progn
  (set-face-attribute 'org-level-1 nil :foreground "#ffd000" :bold t :height 1.0)
  (set-face-attribute 'org-level-2 nil :foreground "#ffd000" :bold nil :height 1.0)
  (set-face-attribute 'org-level-3 nil :foreground "#ffd000" :bold nil :height 1.0)
  (set-face-attribute 'org-level-4 nil :foreground "#ffd000" :bold nil :height 1.0)
  (set-face-attribute 'org-level-5 nil :foreground "#ffd000" :bold nil :height 1.0)
  (set-face-attribute 'org-level-6 nil :foreground "#ffd000" :bold nil :height 1.0)
  (set-face-attribute 'org-level-7 nil :foreground "#ffd000" :bold nil :height 1.0)
  (set-face-attribute 'org-level-8 nil :foreground "#ffd000" :bold nil :height 1.0))

2017-09-30-orgmode-color-after1.png 2017-09-30-orgmode-color-after2.png

どうでしょうか。黄色は他で使っていない色なので「黄色なら見出し!」とはっきり分かります。

文字の大きさも試しに大きくしてみたのですが、折りたたんだときに文字は小さい方が良いのでやめました。

しばらくこれで使ってみようと思います。

ついでにorg-bulletsも導入してみました。「***」を他の記号文字に変えてくれます。MELPAにパッケージがあるのでそれでインストールしました。デフォルト設定の記号はあまり綺麗に表示されなかったのでUNICODEの中からMEDIUM CIRCLEやMEDIUM SQUAREあたりを設定してみました。