niszetの日記

アナログCMOS系雑用エンジニアが頑張る備忘録系日記

Pandoc 2.9.2 で 入力ファイル形式にcsvが追加されました

仲間が増えたよ!

掲題のとおり、Pandoc 2.9.2 で 入力ファイル形式にcsvが追加されました。

https://pandoc.org/releases.html#pandoc-2.9.2-2020-02-15

他にも変更点多々ありますが、ひとまずcsvファイルを入力にしたときの挙動を見ておきます。

とりあえずcsvファイルを準備。irisデータで。

write.csv(head(iris), "iris.csv")

Markdownへの変換

とりあえずMarkdown形式へ変換してみます。入力ファイル形式csvを指定し、markdown形式へ先のcsvファイルを変換します。

pandoc -f csv -t markdown iris.csv

結果は以下の通り。

      Sepal.Length   Sepal.Width   Petal.Length   Petal.Width   Species
  --- -------------- ------------- -------------- ------------- ---------
  1   5.1            3.5           1.4            0.2           setosa
  2   4.9            3             1.4            0.2           setosa
  3   4.7            3.2           1.3            0.2           setosa
  4   4.6            3.1           1.5            0.2           setosa
  5   5              3.6           1.4            0.2           setosa
  6   5.4            3.9           1.7            0.4           setosa

これで、Markdownの面倒くさい表形式への変換がPandocだけでも出来ることがわかりました。

とはいえ、これは全体がcsvであるファイルを単一のmarkdownファイルに変換しているだけなので、 Markdownファイル中でcsvファイルを取り込むといったことは(まだ)できません。

もちろん内部でPandocを呼び出して上記変換を行って結合すればよいですが、たとえばR Markdownであればそもそもその言語で処理を書けばよいということになるので…。

Pandoc's ASTへの変換時点でTable形式となっている

Pandocのデータ構造も確認しておきます。

pandoc -f csv -t native iris.csv

結果は以下のように、Tableとなっています。

[Table [] [AlignDefault,AlignDefault,AlignDefault,AlignDefault,AlignDefault,AlignDefault] [0.0,0.0,0.0,0.0
,0.0,0.0]
 [[]
 ,[Plain [Str "Sepal.Length"]]
 ,[Plain [Str "Sepal.Width"]]
 ,[Plain [Str "Petal.Length"]]
 ,[Plain [Str "Petal.Width"]]
 ,[Plain [Str "Species"]]]
 [[[Plain [Str "1"]]
  ,[Plain [Str "5.1"]]
  ,[Plain [Str "3.5"]]
  ,[Plain [Str "1.4"]]
  ,[Plain [Str "0.2"]]
  ,[Plain [Str "setosa"]]]
  ,[Plain [Str "3"]]
  ,[Plain [Str "1.4"]]
  ,[Plain [Str "0.2"]]
  ,[Plain [Str "setosa"]]]
 ,[[Plain [Str "3"]]
  ,[Plain [Str "4.7"]]
  ,[Plain [Str "3.2"]]
  ,[Plain [Str "1.3"]]
  ,[Plain [Str "0.2"]]
  ,[Plain [Str "setosa"]]]
 ,[[Plain [Str "4"]]
  ,[Plain [Str "4.6"]]
  ,[Plain [Str "3.1"]]
  ,[Plain [Str "1.5"]]
  ,[Plain [Str "0.2"]]
  ,[Plain [Str "setosa"]]]
 ,[[Plain [Str "5"]]
  ,[Plain [Str "5"]]
  ,[Plain [Str "3.6"]]
  ,[Plain [Str "1.4"]]
  ,[Plain [Str "0.2"]]
  ,[Plain [Str "setosa"]]]
 ,[[Plain [Str "6"]]
  ,[Plain [Str "5.4"]]
  ,[Plain [Str "3.9"]]
  ,[Plain [Str "1.7"]]
  ,[Plain [Str "0.4"]]
  ,[Plain [Str "setosa"]]]]]

この結果から、csvのReaderは従来からあるTable形式を返しているだけということがわかり、Pandocのフィルタをこのあとに書く場合はTableを受ける仕様でないといけない、ということがわかりますね。

現状のPandoc's MarkdownのTableの仕様そのものに不満がある場合はその不満点はそのまま残るということになります。

まとめ

  • Pandoc 2.9.2からcsvファイル形式を入力ファイル形式に指定することが出来る
  • このとき、単一のcsvファイルを指定したファイル形式の表形式として出力できる(表形式が出力できるファイル形式なら何でも問題なし。docx形式でも対応可能)
  • 中間表現として、PandocのNative ASTはTableとなっている。そのため、従来のPandocのTableの表現力によって制限される。フィルタを書く場合は対象はTableとすること。
  • その他、オプションやファイルの取り込みは未調査。

以上です。

Haskellの勉強中(勉強記録メモ)

昨日の続き。

昨日書いたコードに対して、showをいじってみる。

instance Show Atom where
  show s = "Hoge"

などとすると、Atom型は常に"Hoge"と表示される。このとき、元々の定義、newtype Atom = Atom String deriving Show の deriving ... は消しておく。Atomの場合はdataじゃなくてnewtypeで良い。

デストラクタとかデコンストラクタと呼ばれるやつを定義する。こんな感じで。

unAtom :: Atom -> String
unAtom (Atom s) = s

unMole :: Mole -> [(Int, Atom)]
unMole (Mole s) = s

これは、Stringしか受け取らない関数に対してAtom String の形で受け取れるようにするのを避けるため、一旦unAtomしてAtomすればよいみたいな感じでつかう(と思う)。一度読んだはずだが完全に忘れている。

さて、MoleのShowを自分で定義する。最終的にこんな感じになった。最初、show Mole s = ... としていたが、sに対して unAtom $ snd $ head $ unMole s みたいなことをしていたのだが、右辺で分離して受け取るようにすればよかった。何気に再帰であるが、終わりになるやつの書き方で苦労した。型注釈が必要かと思って書いたら怒られて、最終的にはMole []で問題ないことが分かった。unAtomは入れておかないと、Atom He みたいに表示されるので入れている。空文字は"\NUL"で入れるらしい。""だと""が表示されるのでダメだった。

instance Show Mole where 
   show (Mole ((a, b):c))  = (unAtom $ b) ++ show a ++ show (Mole c)
   show (Mole []) = "\NUL"

あと、isAtomは型がAtom指定しているので、Atom以外を与えるとエラーになる。a -> Bool とかにした方が良いのかと思ったが、本体でAtomって書いてあるのでそれはだめっぽい(Atomだろって怒られる)まぁ、isUpperとかもCharじゃないと怒られるので良いことにした。dataを使うかnewtypeを使うか、whereを使うかletを使うかとか、ちゃんと条件を網羅出来ているのか、再帰で書いたときの終止条件が書けているのか、など課題が多い。しばらくは続けていく。

Haskellを書き始める(勉強進捗メモ)

初心者なので…。

昨日ふと思い立って書き始めた。やはり読むのと書くのでは全然違う。知ってることと出来ることは違うように。

この記事はどこで躓いていたのかを記すだけのメモ的な日記です。あとで振り返るため。なので、有益なことは書かれていません。

また、半月に1度(月2回)を目途に進捗を書いていきたい。とはいえ、普段投稿する記事とどう分けるのかは何も決まっていません。まぁやってれば固まるさ…

GHCiで複数行入力

関数を定義する場合などは複数行一気に入力をしないといけないので、:{ ... :} が必要。最後が:}である点に注意。何度も書くようであればファイルに書いた方が良い。

deriving Show

これをつけないと、GHCi上で表示しようとしたときに怒られる。

識別子

dataの左辺と右辺で型とか値とかコンストラクタとか色々呼び名があってまだ整理できていない。

今後、このあたりを参照、調査。

https://www.slideshare.net/knzm/haskell-7-14864975

たとえば以下のような記述はNG.

`data Atom = Atom String | Atom Char deriving Show

次のようなエラーが出る。

Multiple declarations of ‘Atom’

Stringを受け取るやつとCharを受け取るやつで名前を変えておく必要がある。そういえば本にも書いてあったな…。

次の書き方はOK.

data Mole = Mole [(Int, Atom)] deriving Show

右辺のMoleを消すとダメ。

    Cannot parse data constructor in a data/newtype declaration: [(Int,
                                                                   Atom)]

isUpperを使いたいならimport Data.Charを入れる

Preludeに入っているのは本当に基本的な関数だけ。import Data.CharするまえにiSUpperを使おうとすると怒られる。

<interactive>:6:1: error: Variable not in scope: isUpper

引数なしだと当然エラー

<interactive>:8:1: error:
    ? No instance for (Show (Char -> Bool))
        arising from a use of ‘print’
        (maybe you haven't applied a function to enough arguments?)
    ? In a stmt of an interactive GHCi command: print it

isUpperはCharに対する関数なので、Stringを引数に与えても当然エラー。

Prelude Data.Char> isUpper "a"

<interactive>:9:9: error:
    ? Couldn't match expected type ‘Char’ with actual type ‘[Char]’
    ? In the first argument of ‘isUpper’, namely ‘"a"’
      In the expression: isUpper "a"
      In an equation for ‘it’: it = isUpper "a"

優先順位づけに()をたくさんつける。

先の Atom String を受け取る関数を定義するとき、(Atom String) のように括弧で囲わないと引数の数があわないぞ~みたいなことを言われる。型の定義でAtom a => a -> Bool 等はしない。そもそも違う?要チェック。

タプルの()と優先順位の()がわかりづらいなと思っていたが、前者は,が必要。後者は不要なので見ればわかることだった。

本当はもっと厳しいチェックにする(既存のものに含まれるかをチェックする)が、今回は書き方を学びたいので、1文字でかつ大文字であること。あるいは2文字で1文字目が大文字で2文字目が小文字であることをチェックし、そのいずれかであればTrue、それ以外はFalseという関数にしてみた。とりあえずこんな感じ。

isAtom :: Atom -> Bool
isAtom (Atom x@(a:b:_)) 
  | (length x == 2) && (isUpper a) && (isLower b) = True
  | otherwise = False
isAtom (Atom x@(a:_)) 
  | (length x == 1) && (isUpper a)                = True
isAtom _ = False

as記法x@(a:b:_)を使うのは、文字数と内部の文字それぞれをチェックしたいため。&&か&かで迷ったが、:t (&&)みたいにコンソールで確認すればよい(なければ怒られるので)。:tは:type。(&&)は演算子&&の関数での書き方。

いたるところに()があるが、基本的に左結合で持って行かれてしまうので。

otherwiseは万能ではない…

いや、最初のマッチで拾えれば、確かに常にTrueなのだが、上の例で、x@(a:b:)は少なくとも2文字ある状態でマッチし、1文字の場合はマッチしない。この場合、その式?はスキップされるので、otherwiseは実行されない。そのため、1文字の場合は別途定義をしてあげる必要があるし、そもそもコレだとは不要な気がする。通ったのでそのままだが、また調べよう。

これ以外のケースを拾う場合は最後のようにisAtom _で拾う。これでisAtom (Atom "a")はFalseを返す。こうなると、最初のotherwiseは不要そうだな…。あとでまた書き換えよう。

関数に直接与える場合は()つけないと2引数と思われてしまうが、先に変数に代入しておけば()は不要。

x = Atom "He"
isAtom x
> True

実際に存在する元素名であるか?をチェックする場合はあらかじめそれらをリストに入れておいて、その中にマッチするものがあるか?のチェックが必要。その前チェックに↑のチェックを入れても良いが。

一応それっぽい動きをしている。

isAtom (Atom "あ")
> False
isAtom (Atom "2")
> False
isAtom (Atom "H2O")
> False
isAtom (Atom "HO")
> False
isAtom (Atom "H")
> True
isAtom (Atom "O2")
> False
isAtom (Atom "Al")
> True
isAtom (Atom "Ale")
> False

まとめ

やはり、コードは書いてなんぼ…。多分読むだけより数倍~数十倍の効果がある。しかし、前知識がないと無駄に時間を溶かすのも事実なので、バランスが難しいなと。

しばらくはHaskellで色々遊んでみたいので、ゆるい記事が続きますが、ここは私の備忘録なので…。

とりあえず簡単なパーサーを書こうと思います。

Wordをちゃんと使いたくて、スタイル周りがわからなかったら「疑問解消!しくみからよくわかるWord再入門」を読もう

タイトルで言いたいことを言い切りました。

そんなわけで、何度かTwitterの方では言及しているこの本ですが、Wordは出来ることが多い割に使い勝手、設定し勝手がよくわからず、スタイルを使えばいいのはわかるけど、具体的にどうすれば…みたいな学習コストが無駄に高い気がします。ちゃんと使いこなせれば、それなりに良いツールだと思うのですが。

で、それは良い本がないからなんだよなぁ…とずっと思っていたのですが、去年みつけた、「疑問解消!しくみからよくわかるWord再入門」という本が私的にとても良かったです。

gihyo.jp

この、Wordで作ったWordの本シリーズは絶版も含めて何冊かあるのですが、ひとまずこの本を読んでおけばよいかと。他のタイトル気になったらそちらも調べてもらえれば。内容的に重複する部分もあるので、差分の内容にどのくらい価値があると思うか次第で他の本の必要性は変わるかもしれません。まぁ私は1ページ、1文、1語でも「この本を買わなければ至ることが出来なかった」と思える内容があればその本は「価値がある」ので、私の意見はあんまり参考にならないので…。ってこの記事自体の否定をw

さて、それでも素のWordで"ちゃんと"書くのは大変ですね…そういうときはPandocでmarkdownから変換するのが良いでしょう。そうすればスタイルがちゃんと設定されるので。まぁ、文字レベルだとされてなかったり、カスタムスタイルを指定する云々で色々あるんですけど、それはまた別の話として。

ちなみに、スタイルの話だけでなく、ページ設定の話とか、段落とはみたいな話もあり、知見の塊みたいな本です。しかも安い…。

是非、最新のWordに対応した版を、出してほしいなぁ…と思うのでした。

Word使う方は持っていて損ないと思いますので、是非見てみてくださいな。本音は、これを見たうえで自分なりの知見を持ってるような人とかと、この本についてやWordについてあれこれ議論したい、そういう人を増やしたいという気持ちです。

もし、ほかにもおすすめの本があれば、是非教えてください。よろしくお願いします

(Pandoc) Wordの画像の回り込みの処理を入れるのはちょっとしんどい(メモ)

部分的にWriterを書き換える必要がある。

出来ないと断言はできないものの、現状私の能力では難しいです。Pandoc's ASTでいうところのImageはdocx中では<graphics>タグに置き換わりますが、これが結構複雑で…。この中に回り込みの処理を入れることになりそうですが、この変換自体はDocx Writerの処理なので、それをまるまる置き換えないといけない。テンプレートで一律処理ではなくて個別の画像に対応が必要なので、変換の時点でなんとかしないといけなさそう。また、おそらく前後にタグを仕込むタイプでは難しいだろなとも思っています。

一方で、画像を中央に寄せることは可能で、変換後の対応するスタイルを設定するだけでOKです。これはまた別記事にて。

コメダで作業をしてみた

2020年は1/1から作業を開始した。

茶店とかでの作業、あまりやったことがなかったのですが、近所の小さな喫茶店とかで原稿の校正とかしていたらそれなりに捗ったので、今年もやってみようと思っています。しかし正月期間は個人商店は基本的にお休みになっているので、ちょっと歩いてコメダに行ってみました。何気にここのコメダ行くのは初ですね

量は確かに多い

コメダは食べ物の量が多いとよく言われますが、実際注文してみると結構なサイズですね。とはいえ、パンなのでそれなりにぺろりと平らげてしまう量。まぁ、だから太るんだろうけど…。

パンだとあんまり腹持ちが良くないのが難点?ですね。

コーヒーの味

やっぱり専門店に比べると、一歩劣るという感じですが、専門点と比べたらまぁそうよね…。

とは言え値段的には小さな喫茶店でも同程度なので、むしろそっちが頑張っている気がする。量多めが出来るので、量飲むならコメダも良いかな。

カフェインレスコーヒー

カフェインレスもあったので飲んでみましたが、味はやはり普通のコーヒーの方が美味しいかな。でも何杯も飲むとカフェイン多すぎるので、2時間くらい滞在する関係でお金を落としていく意味でも追注が必要なので2杯目はコレですね。

Wifiが便利。

試してみたけど簡単に使えたので良かった。Twitterしつつ調べものしつつ書きモノするだけなら十分ですね。

そんな感じでコメダデビューしたお話しでした。

総合的には満足ですが、逆に地元の小さいお店もアリだな…と思わせる結果となりました。用途に合わせてそれぞれ使っていきたいですね。

あと、良く使うお店にはちゃんとお金を落としていきましょうね…。時間当たり客単価をキープしていきたいところです(どんなに良いお店でもお金落とさないとつぶれてしまうので)

(Pandoc) PandocのWordテンプレートはテンプレート出力よりも通常のファイル出力結果を使った方が良い。

2020年初Pandoc記事です(前の2記事も実質Pandocですが)

さて、PandocでWord形式の出力ファイルが必要な場合、素の出力では見づらかったり自分なりにカスタマイズしたいということがよくありますね。

これは、--reference-doc であらかじめ見た目を調整したテンプレートを指定するとうまくいきます。

https://pandoc.org/MANUAL.html#option--reference-doc

テンプレートとスタイルを使うと、見た目が同じで内容が違うドキュメントを生成するのが楽になります

Pandocが生成するWordドキュメントは、もとのファイルの構造に基づいて、それぞれにスタイルが適用されます。そのため、それに必要なスタイルがあらかじめ含まれているのが望ましいです。

マニュアルには、以下のようにしてテンプレートファイルを生成せよと書かれています。

pandoc -o custom-reference.docx --print-default-data-file reference.docx

しかし、実際に使用してみるといくつかのスタイルが不足していることに気づきます。

PandocはPandocの生成したドキュメントをテンプレートにすることが出来ます。ざっくり言えば本文要素以外がほぼ残り、本文が差し変わるという挙動です。 Pandocが生成したドキュメントなので、Pandocが使用するスタイルは全て入っているという点がメリットです。

本文は何でも良いので、PandocへのPATHが通っているなら例えば次のようなコマンドでテンプレートファイルが生成されます。

echo hoge | pandoc -o reference.docx

この方法であれば、実際に使用するスタイルが全て含まれているので安心です。

いつの間にか**Tok系の文字スタイルに基準スタイルが設定されていて、1年半前の努力は何だったのか…という気もしますが。

スタイルの設定については技術書典向けに鋭意作成中…。終わるのだろうか…?

追記

Issueがあった。あったのだが、この件についてはうやむやというか、触れずにcloseしている。ちょっと聞いてみようかなぁ…

github.com