Yearly Archives: 2017

2017-12-26

新しいtableのスタイル

なんとなく表(table)のCSSを変えてみた。

ポイントはセルの角、つまり縦線と横線が交差する点の色をどう制御するか。

表はHTML要素的には table > tbody > tr > td の順に重なっているわけだけど、基本的に手前である子孫要素(tdに近い側)が優先される。なので、セル(td)の区切り線の色を指定すると、それは表全体(table)の境界線よりも優先されてしまう。その結果表全体の境界線にセルの区切り線が食い込む形になってしまう。

そこで重要なのが境界線の指定が重なったときに何が優先されるかというルール。親要素であっても線の幅が太い方が優先される。同じ太さならスタイル(破線とか二重線とか)によって優先度が決められている。特に二重線(border-style: double)は使える。solidよりもdoubleのほうが優先されるからだ。その上二重線といっても1pxの太さならsolidと見た目は変わらない。

外側(親、祖先)の要素の太さやスタイルをより優先度が高い物に変えることによって、セル区切りの色が外にはみ出さないように出来る。

/* table style */
table{ border: 1px double #4472c4;}
  /* striped background color */
thead{ border: none; background-color: #4472c4; color: #ffffff;}
tbody>tr:nth-child(odd){background-color: #d9e1f2;}
  /* vertical line between colgroups */
colgroup{ border: none;}
colgroup+colgroup{ border: none; border-left: 2px double #81a0d7;}
  /* horizontal line between tbodys */
tbody{border: none;}
tbody+tbody { border-top: 2px double #81a0d7;}
  /* vertical line between columns  */
tr:nth-child(even) >td+td {border-left: 1px solid #d9e1f2;}
tr:nth-child(odd)>td+td, th+th {border-left: 1px solid #fff;}

テスト

0 1 2 3 4
a b c d e
f g h i j
k l m n o

ヘッダー無し

項目1 項目2
項目3 項目4

ヘッダー無し

項目1 項目2

ヘッダー無し

項目1 項目2
項目3 項目4
項目3 項目4

良くある奴

品名 価格
りんご 100
みかん 80
みかん 80
  180

列グループ

場所 最低 最高
東京 晴れ 晴れ 曇り -1 9
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
大阪 晴れ 晴れ 0 12
2017-12-26

2017秋最終回

最近は全12話が多いから終わるのが早いね。

今期はどんどん切った。ここまで切ったのは初めてじゃないだろうか?

最後まで見たのは次:

不愉快な要素が鼻につくものは面白いところがあっても切りがちだと思う。 逆にそれほど面白くなくてもあまり期待せず気楽にながら見できるようなものは残りがち。

2017-12-26

2017年末ゲームアンインストール祭り

城とドラゴン、どうぶつの森ポケットキャンプ、ソリティア、Pokemon GO、駅メモをアンインストールした。

それほど面白くなくなっていた割に、合わせると結構な時間を消費していたからだ。

城とドラゴン。人に勧められて始めたのだけど、ずいぶん長いことプレイした。農場ゲー的育成要素と単純・短時間な対戦要素。チケット制。適度な緩さが良かったのだが、育成が進んでレベルが上がるにつれトロフィー戦はおろかリーグ戦も勝てなくなった。どうやら育成に失敗したらしい。次々と出る新キャラが古いキャラを相対的に弱くしていく。ついて行くには新キャラを手に入れて育成し続けなければならない。そういうキリのなさが見えてしまうともうダメだ。キャラクター間の相性ももはや全く覚えられない。チケットも最初は少なくて長時間遊べないのが逆に良かったのだけど、最近は対戦形式が増えたせいもあって全く消費しきれなくなっていた。

どうぶつの森ポケットキャンプ。プレイしたのは1ヶ月くらいだろうか。緩いように見えて案外時間を消費させられる。画面切り替え効果やローディングの時間はもとより、動物たちとの会話が単調で面白くなく、単なる時間の浪費でしかない。プレゼントを渡したときに時々発生するちょっとしたイベントはもはや罰ゲームでしかない。「バーベキューやるけど食っていくだろ?」いやいやいかねーよ!! はやく終わってくれよ。日々の作業が全部一括で終わるボタンがあれば良かったのに。

ソリティア。Androidのそのものズバリなゲームなのだが、ずいぶん長くプレイしてしまった。デイリーチャレンジがあるのが良かったのだが、通知が機能せずに逃してしまうことが多くなっていた。やり逃しても過去に遡ってプレイできるのだが、カレンダーに着く王冠マークが微妙に変わってしまう。それ以外に何の罰もないのだが何か不愉快だ。ゲーム自体もソリティアなので、何も考えずに適当にポチポチ押してクリアできるかどうか何回か試すだけである。まぁ、もういいよね。

Pokemon GO。もうずっとプレイしてなかった。

駅メモ。最初全く面白さが分からなかった。何回か旅行の際に遊んでみるうちにある日突然面白くなった。ローカル線主体の旅行でやるのが一番良いと思う。バスはずっと同じ駅しか入らないし新幹線や特急はずっと画面を見てないと通過駅を逃してしまうのでつらい。キャラクターの育成も最初全く分からなかったが、どうやると稼げるのか分かるとちょっと面白くなった。溜めていた無料ライセンス(1日のチェックイン回数が伸びるアイテム)が無くなってきたので最近はやらなくなっていた。課金してまでやりたいほどではない。路線コンプリートも一見魅力的だが、別にいつ無くなるか分からないようなアプリでやらなくていいじゃない。

2017-12-21 ,

org-mode スプレッドシート(表計算)での参照の書き方まとめ

org-modeで表計算が出来るということはよくご存じかと思いますが、細かいところがよく分からないという方も多いのではないでしょうか。特にフィールド(いわゆるセル)を式内から参照する書き方は広く使われている表計算ソフトとは異なるのでなかなか覚えられない、普段使うところだけ覚えてるということも多いと思います。なので今回はorg-modeのスプレッドシート機能の内、「参照」に的を絞ってまとめてみました。

参考: Org Mode マニュアル 3.5.1 参照 References (The Org Manual)

表内のフィールドや範囲等を参照する方法

フィールド参照

意味
@0 現在の行
$0 現在の列
@1 1行目
$2 2列目
@1$2 1行目2列目
@-1 直上の行
$-1 左隣の列
@-1$+3 現在のフィールドから上に1行、右に3列
@< 最初の行
@> 最後の行
$< 最初の列
$> 最後の列
@>$2 最終行の2列目
@>$> 最終行の最終列(右下)
@<<< 最初の行から下へ数えて3行目(@3)
@>> 最後の行から上へ数えて2行目
$<< 最初の列から右へ数えて2列目($2)
$>>> 最後の列から左へ数えて3列目
@I 一つ目の水平線
@-I 現在の行から上にある最初の水平線
@+II 現在の行から下にある2番目の水平線
@III+2 三つ目の水平線から下にある二番目の行
@III-1 三つ目の水平線の直上の行
  • @行$列
  • 0は現在
  • 符号が付くと相対指定
  • <が先頭で>が末尾
  • @Iは水平線
  • < > I は複数連続で書くとその個数分だけズレる

範囲参照

意味
@2$3..@3$5 「2行目の3列目」から「3行目の5列目」までの矩形範囲(6フィールド)
@2$1..@>>$> 「2行目の1列目」から「下から2行目の右端列」までの矩形範囲
@I..@II 一つ目の水平線から二つ目の水平線までにある行、現在の列

始点.. 終点 の形で 始点 から 終点 までの 矩形範囲 を指す。 始点終点 はそれぞれフィールドへの参照。

式の右辺に書いた場合範囲内の値を含む ベクトル になる。(例えば @1$1..@2$2 なら4要素のベクトルになる)

式の左辺に書いた場合計算で書き換える対象を表す。(@1=1行目の全列の式, $1=1列目の全行の式, @1$1..@2$2=左上2x2(4マス)の式)

※式の 左辺 に範囲参照を書く時 始点 には水平線参照(@I 等)は書けない(ダメな例: @I+1$>..@II-1$>=foo)。 終点 にはなぜか書ける(書ける例: @2$>..@II-1$>=foo)。(参考: 水平線参照を左辺には書けないのはなぜ?)

名前参照

意味
$name nameという名前の何かを参照

参照できる物:

リモート参照

意味
remote(table1, @>$>) table1という名前の表の最終行最終列(右下)にあるフィールドを参照。

#+NAME: 名前 を表の直前に書くとその表を名前で参照できる。

フィールド座標

意味
@# 現在の(計算対象の)行番号に展開される
$# 現在の(計算対象の)列番号に展開される
@@# @ ( @# ) と解釈。つまり@現在の行番号
$$# $ ( $# ) と解釈。つまり$現在の列番号
@$# @ ( $# ) と解釈。つまり@現在の列番号
$@# $ ( @# ) と解釈。つまり$現在の行番号

例1:列名と範囲参照

#+NAME: purchase2016
|   | 品名   | 単価 |     個数 |    計 |
| ! | item   | unit | quantity | total |
|---+--------+------+----------+-------|
| # | りんご |  128 |        5 |   640 |
| # | みかん |  200 |        3 |   600 |
|---+--------+------+----------+-------|
| # |        |      |          |  1240 |
#+TBLFM: @3$>..@II$>=$unit*$quantity::@>$>=vsum(@I..@II)

! の行は列名となる。列名は $unit*$quantity のように使える。 $3*$4 より幾分分かりやすい。 # の行は自動再計算(フィールド入力後TABやRETで全体を再計算する)対象となる。その他にも同じような方法でフィールド名やパラメータを定義する機能がある。(参考: Org Mode マニュアル 3.5.8 一歩進んだ機能 Advanced features (The Org Manual))

@3$>..@II$>=$unit*$quantity

式の左辺にある @3$>..@II$> は「3行目の最後の列」から「2本目の水平線までの行の最後の列」までの範囲を表す。つまり右端の小計を入れる部分(右下の合計部分を除く)を指す。水平線参照だけを使って @I$>..@II$> のようには(左辺には)書けない(エラー:"Can't assign to hline relative reference")。列名を使って @3$total..@II$total のようにも書けなかった。 @<<<$>..@>>$> のようには書ける。

@>$>=vsum(@I..@II)

@I..@II は現在の列の一つ目の水平線から二つ目の水平線の間の範囲を表す。範囲内の値を要素とするベクトルが作られ、vsumでその合計が計算される。結果は @>$> つまり一番右下のフィールドに格納する。

今回は代入先の範囲が重ならないように厳密に指定して書いたが、 #+TBLFM: $>=$unit*$quantity::@>$>=vsum(@I..@II) のように書いても構わない。 $> は右端の全てのフィールド(ヘッダー以外)を意味するので右下( @>$> )と重なってしまうように見えるが、列指定よりフィールド指定が優先されることが決まっている。(参考: Org Mode マニュアル 3.5.5 列の数式 Column formulas (The Org Manual))

例2:リモート参照

| 税抜き | 税率 | 税込み |
|--------+------+--------|
|   1240 | 1.05 |   1302 |
|   1240 | 1.08 |   1339 |
#+TBLFM: $1=remote(purchase2016,@>$>)::$3=floor($1*$2)

remote(表名, 参照) で別表の値を取り出せる。

この例ではpurchase2016という名前の表(例1)の一番右下のフィールド(@>$>)を1列目($1)へ代入している。

例3: リモート参照(表の名前を計算時に決める)

purchase2016とpurchase2017の二つの表があるとき、この二つの表の合計部分(一番右下のフィールド)を別の表から参照したいとする。

#+NAME: purchase2016
|   | 品名   | 単価 |     個数 |    計 |
| ! | item   | unit | quantity | total |
|---+--------+------+----------+-------|
| # | りんご |  128 |        5 |   640 |
| # | みかん |  200 |        3 |   600 |
|---+--------+------+----------+-------|
| # |        |      |          |  1240 |
#+TBLFM: @3$>..@II$>=$unit*$quantity::@>$>=vsum(@I..@II)

#+NAME: purchase2017
|   | 品名   | 単価 |     個数 |    計 |
| ! | item   | unit | quantity | total |
|---+--------+------+----------+-------|
| # | りんご |  128 |        3 |   384 |
| # | みかん |  200 |        8 |  1600 |
|---+--------+------+----------+-------|
|   |        |      |          |  1984 |
#+TBLFM: @3$>..@II$>=$unit*$quantity::@5$5=vsum(@I..II)

列に表名を入れれば次のように書ける。

|   表名       | 金額 |
|--------------+------|
| purchase2016 | 1240 |
| purchase2017 | 1984 |
#+TBLFM: @<<$>..@>$>=remote($1,@>$>)

remoteの第一引数である $1 は先に展開されるのに対して第二引数である @>$> は展開されない(1984に置き換わらない)のが興味深い。

表名を表の中に書くのはかっこ悪いので年から表名文字列を生成してリモート参照したいなら次のようにする。

|   年 | 金額 |
|------+------|
| 2016 | 1240 |
| 2017 | 1984 |
#+TBLFM: @<<$>..@>$>='(org-table-get-remote-range (concat "purchase" $1) (string ?@ ?> ?$ ?>))

remote(表名, 参照) の書き方では文字列の結合等はできない(リモート参照の展開タイミング的に)ので、Elisp式を使っている。

(string ?@ ?> ?$ ?>) の部分は "@>$>" とは書けない。展開のタイミング的に。

(参考: emacs - Org mode spreadsheet programmatic remote references - Stack Overflow)

例4: 結果の行内への埋め込み

行内コードブロックを使えば表の中の値を文書中の行内に埋め込める。

#+NAME: ex4
| 品名   | 金額 |
|--------+------|
| りんご |  123 |
| みかん |   89 |
|--------+------|
|        |  212 |
#+TBLFM: @>$>=vsum(@I..@II)

合計は src_emacs-lisp[:results raw]{(org-table-get-remote-range "ex4" "@>$>")} 円です。

参考: Org Mode: Using table formula outside of a table? - Emacs Stack Exchange

例5: 連番

| 番号 | 番号4桁 |
|------+---------|
|    0 |    0000 |
|    1 |    0001 |
|    2 |    0002 |
|    3 |    0003 |
#+TBLFM: $1=@#-2::$2='(format "%04d" (- @# 2))

例6: 文字列の参照

基本的にElisp式で行った方が良い。Calcで扱えないこともないが非ASCIIは怪しい?

| 参照する文字列→      | abc                  | りんご                     >
| ↓式                  | ↓結果               | ↓結果                     >
|-----------------------+----------------------+---------------------------->
| @1                    | abc                  | #ERROR                     >
| "@1"                  | [40, 97, 98, 99, 41] | [40, 12426, 12435, 12372, 4>
| string("@1")          | (abc)                | string([40, 12426, 12435, 1>
| '(identity @1)        | abc                  | りんご                     >
| '(format "%sです" @1) | abcです              | りんごです                 >
#+TBLFM: @3$2=@1::@3$3=@1::@4$2="@1"::@4$3="@1"::@5$2=string("@1")::@5$3=string("@1")::@6$2='(identity @1)::@6$3='(identity @1)::@7$2='(format "%sです" @1)::@7$3='(format "%sです" @1)::@8$2=string("$s1")

水平線(hline)参照の謎

水平線参照をフィールド参照として使うとどうなるか

単に @I と書いた場合どこを参照するのか。

|       | 10 |
|-------+----|
|       | 11 |
|       | 12 |
|-------+----|
| ↓式  |    |
| @I-1  | 10 |
| @I    | 11 |
| @I+0  | 11 |
| @I+1  | 11 |
| @I+2  | 12 |
| @II-1 | 12 |
#+TBLFM: @5$2=@I-1::@6$2=@I::@7$2=@I+0::@8$2=@I+1::@9$2=@I+2::@10$2=@II-1

水平線の直下の行を参照する模様。意図した動作かは不明。 @I+1 と書いた方が安心?

水平線参照を左辺には書けないのはなぜ?

範囲参照例1にも書いたが、水平線(hline)への参照(@I 等)は式の左辺に書けない。

例えば次の良くあるような例では、小計を集計するのに「一つ目の水平線から二つ目の水平線までの行、右端列」つまり @I$>..@II$> と左辺に書けると便利である。

|        | 重量 | 個数 | 計 |
|--------+------+------+----|
| みかん |   30 |    2 |    |
| りんご |   50 |    3 |    |
|--------+------+------+----|
|        |      |      |    |
#+TBLFM: @I$>..@II$>=$-2*$-1

しかし実際に書くとエラーになる。

Can't assign to hline relative reference

なぜ書けないのかメーリングリストを"left hline"で検索してみた。

長年未解決で放置中らしい。

リモート参照とフィールド座標の展開規則

例3でも触れたがremoteの第二引数は別表の参照前に展開されないように見える。

しかしマニュアルには次のような例がある。(Field coordinates in formulas)

@3 = 2 * remote(FOO, @1$$#)
Insert the doubled value of each column of row 1 of the table named FOO into row 3 of the current table.

この例の @1$$# はremote()を解決する前に @1$1 , @1$2 , @1$3 のように参照元の列の番号に展開されなければならないはずだ。

#+NAME: remote-ref-tbl1
| 1 |  2 |  3 |  4 |
| 5 |  6 |  7 |  8 |
| 9 | 10 | 11 | 12 |

| 2 | 4 | 6 |
#+TBLFM: @1=2*remote(remote-ref-tbl1, @1$$#)

ちなみに「現在の列」を表したいなら $0 やそもそも列を省略すれば良さそうだが、実際にやると次のようになる。

| 2 | 2 | 2 |
#+TBLFM: @1=2*remote(remote-ref-tbl1, @1$0)

マニュアルにもリモート参照の第二引数は絶対参照か名前参照でなければならないと書いてあるのでこの書き方はできないのだろう。

org-table-eval-formula 関数を見ると、 @# 等のフィールド座標表記はリモート参照よりも前に解決しているようだ。つまり、remoteとその引数の展開は次のような順番になっている。

  1. フィールド座標(@# $#)だけ先に解決(数字へ置き換え)
  2. 第一引数を現在の表上で解決し、得られた名前に従って参照先となる表を見つける
  3. 見つけた表上で1の結果得られた第二引数の参照を解決する

そもそもこの remote(表名, 参照) という表記は関数の計算などではなく文字列の置き換えに過ぎない。なので展開の規則はCalcともElispとも異なる。 実際マニュアルの例にもあるとおりElisp式内でも同じように書ける。

$2 = '(identity remote(FOO, @@#$1))
Copy text or values of each row of column 1 of the table named FOO into column 2 of the current table.
2017-10-31

Rのお勉強

R言語を勉強しています。org-modeから使うとこんな感じで簡単にグラフを書けてとても便利なのです。

ぱっと見簡単そうな言語なのですが、細部を見ていくと案外ひっかかる言語です。

スカラー型がない所とか。numeric(integerとかdouble)とかcomplex(複素数値)とかlogical(論理値)とかcharacter(文字というか文字列)といった型名があるのですが、全部ベクトル型なので0個以上複数の値を保持できます。

スカラー型がないところというよりは一見スカラー型に見える場合があるところが引っかかりの元なんでしょうね。単に 1 と書くとスカラーのように見えますが実際には要素数(長さ)1のベクトルを書いたことになっているという。型名も vector<numeric> とか numeric[1] とかではなく numeric だけで数値ベクトル型を表すので、最初 mode(1)mode(c(1,2,3)) が同じ型名 numeric になっているのを見てびっくりするわけです。

ベクトルを作るとされている c 関数も作るというと語弊があって、ベクトルを合成(combine)する関数だっりします。 c(1,2,3) は要素数1のベクトル3つを合成して要素数3のベクトル1つを返すというように。

1 #要素数1の数値型(double)ベクトル
c(1) #こう書いても同じ

c(1,2,3) #要素数3の数値型(double)ベクトル
c(c(1), c(2), c(3)) #こう書いても同じ

1:3 #結果はc(1L,2L,3L)と同じ数値型(integer)ベクトル
c(1L, 2L, 3L) #こう書いても同じ
seq(1,3) #こう書いても同じ
c(1:1, 2:2, 3:3) #こう書いても同じ
c(1:1, 2:3) #こう書いても同じ

オブジェクトと値と属性と変数の関係もちょっと分かりづらい、というかイマイチよく分かってません。オブジェクトを別の変数に代入すると同じ値と属性を持ったオブジェクトが新しく出来るみたいなのですが、それならまだ変数になる前の無名のオブジェクトはどうなっているのか、とか。

# 変数(オブジェクト?)aに属性を設定したり取得したり
a <- c(1,2,3)
attr(a, "attr1") <- "value1" # aの"attr1"属性を"value1"へ設定
attr(a, "attr1") # "attr1"属性を取得

# 変数bへaをコピー
b <- a # aの値と属性がbへコピー
attr(b, "attr2") <- "value2" # bの"attr2"属性を"value2"へ設定。aはそのまま

# 変数に入れないでnames属性を指定してみる
c(first=1, second=2, third=3) # "names"属性をc("first", "second", "third")へ設定
attr(c(first=1, second=2, third=3), "names") # "names"属性を取得 c("first", "second", "third")
c(first=1, second=2, third=3)["second"] # 名前で要素を指定

# 変数に入れないで属性を設定してみる
attr(c(1,2,3), "attr3") <- "value3" #エラー:target of assignment expands to non-language object

(function(obj, name, value){attr(obj, name)<-value; obj;})(c(1,2,3), "attr4", "value4") #OK

うーん??

基本型一覧(2.1 Basic types - R Language Definitionより):

  mode(x) storage.mode(x) typeof(x) class(x) x=作成例1 作成例2  
論理値(ベクトル) "logical" "logical" "logical" "logical" TRUE c(TRUE,FALSE) ※単純な数字も長さ1のベクトル
整数値(ベクトル) "numeric" "integer" "integer" "integer" 1L c(1L,2L) ※単純な数字も長さ1のベクトル
倍精度実数値(ベクトル) "numeric" "double" "double" "numeric" 1.0 c(1.0,1.0) ※単純な数字も長さ1のベクトル
複素数値(ベクトル) "complex" "complex" "complex" "complex" 1+1i c(1+3i,2+4i) ※単純な数字も長さ1のベクトル
文字列(ベクトル) "character" "character" "character" "character" "a" c("abc","def") ※単純な数字も長さ1のベクトル
リスト "list" "list" "list" "list" list() list(1,2) 任意の型を要素とするコレクション
シンボル "name" "symbol" "symbol" "name" quote(x)    
関数オブジェクト "function" "function" "closure" "function" function(x,y) x+y    
call "call" "language" "language" "call",etc… quote(x+y*z)   class(quote(x<-1))は"<-"になったり色々する。
expression(ベクトル) "expression" "expression" "expression" "expression" expression(1+0:9) expression(x,y,z+1)  
NULL "NULL" "NULL" "NULL" "NULL" NULL pairlist() 属性を設定することは出来ない
Promiseオブジェクト              
ドットドットドット              
環境オブジェクト             フレーム(シンボルテーブル)と外の環境への参照
対リストオブジェクト "pairlist" "pairlist" "pairlist" "pairlist" pairlist(1,2,3) as.pairlist(list(1,2,3))  

よく使われるクラス:

  mode(x) storage.mode(x) typeof(x) class(x) x=作成例  
matrix mode(要素) storage.mode(要素) typeof(要素) "matrix" matrix(c(1,2,3,4),2,2,byrow=TRUE)  
array mode(要素) storage.mode(要素) typeof(要素) "array" array(c(1,2,3,4,5,6,7,8), c(2,2,2)) matrixの多次元版
data.frame "list" "list" "list" "data.frame" mode(data.frame(name=c("orange", "banana"), price=c(100, 200)))  
Date "numeric" "double" "double" "Date" as.Date("2017-10-30")  
POSIXlt(ローカル時間) "list" "list" "list" c("POSIXlt" "POSIXt") strptime("2017-10-30 12:34:56", "%Y-%m-%d %H:%M:%S") 年月日時分秒曜日dst
POSIXct(カレンダー時間) "numeric" "double" "double" c("POSIXct" "POSIXt") Sys.time() 1970年1月1日からの経過秒
factor "numeric" "integer" "integer" "factor" factor(c("Choki"),c("Guu","Choki","Paa"))  
2017-10-29 ,

Windows版Emacs上でESSが文字化けする問題

勝手に default-process-coding-system 変えるなよ。

diff -u ess-20171022.322/lisp/ess-r-mode.el.old ess-20171022.322/lisp/ess-r-mode.el
--- ess-20171022.322/lisp/ess-r-mode.el.old     2017-10-29 01:06:34.182359100 +0900
+++ ess-20171022.322/lisp/ess-r-mode.el 2017-10-29 00:53:10.316792600 +0900
@@ -556,7 +556,8 @@
               (eq system-type 'cygwin))
       (setq use-dialog-box nil)
       (when ess-microsoft-p ;; default-process-coding-system would break UTF locales on Unix
-        (setq default-process-coding-system '(undecided-dos . undecided-dos))))
+        ;;(setq default-process-coding-system '(undecided-dos . undecided-dos))
+        ))
 
     (inferior-ess r-start-args cust-alist gdbp)
 

read.csvで入力した文字とバッファから入力した文字がどうしてもどちらか一方が化けてしまうので調べた。

Rがutf-8で入出力しているのかなと思って調べたら、Windows版はちゃんと現在のコードページで入出力してくれていた。 調べてみると process-coding-system のENCODING側がundecided-dosだから何事かと思ったら default-process-coding-system がRを起動した後だと書き換わっていた。 何でグローバルな設定である default-process-coding-system を勝手に書き換えちゃうかなー。

他にもWindows対応のコード(ess-microsoft-pで処理を分けているところ)は色々と変なところが多いね。

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] に入るのでそういう仕様みたい。