数式とUMLが記述できる静的サイト生成 Middleman + Asciidoctor の連携
PlantUMLや数式が記述できる静的サイト生成の環境が欲しいと思い調べたところ、Middleman + Asciidotor + asciidoctor-diagramで実現できたのでメモします。 (Hugoが気に入っていたのですが、現時点ではAsciiDocには対応していませんでした。)
AsciiDocはMarkdownよりも表現力が高く、リッチな文書を記述するのに向いています。 例えば以下の記事 [1]では、書籍 "Pro Git" をAsciidoctorで作成したとあります。
このAsciiDocですが、仕様が2つあります。 1つはオリジナルのAsciiDocで、その変換ツールはPythonで作られています。 もう1つは後発のAsciidoctorで、ツールはRuby製です。 両者の仕様の違いはこちら[2]。 今回は後者を使います。
インストール
環境:
インストールするもの:
- JDK 1.8.0
- Graphviz 2.38.0
- PlantUML 8024
- rbenv 0.4.0
- bundle 1.10.4
- Middleman 3.3.12
- Asciidoctor 1.5.2
- asciidoctor-diagram 1.3.0.preview.1
- 他、依存パッケージ
事前準備
(1) 図の生成に必要なツール
GraphvizとPlantUMLをインストールします。
なお、PlantUMLはJava製のため、Javaをインストールしておく必要があります。
$ brew update $ brew cask install java # 既にJDKをインストール済みの場合は不要 $ brew install graphviz $ brew install plantuml
(2) rbenv, bundle
gemを直接使わず、rbenvとbundleを使うので、先にそれらをインストールします。
インストール方法は以下の記事 [3]が参考になります。
ここではRuby 2.2.2を使いました。なお、Railsはここでは使いません。
既にrbenvとbundlerがインストール済みの場合
既にrbenvとbundlerがインストールしてある場合は、パッケージの依存関係による問題を回避するため、すべてのグローバルなgemを削除してローカルなgemで運用することをお勧めします。
グローバルなgemを削除する:
$ for i in `bundle exec gem list --no-versions | grep -v bundler`; do bundle exec gem uninstall -aIx $i; done
このとき、デフォルトのgemはアンインストールできない旨のエラーメッセージが出ますが、問題は無いので無視して先へ進みます。
Middlemanのインストール
(1) プロジェクトフォルダの作成
まず、任意の場所にプロジェクト用のフォルダを作成します。ここではmysite
というフォルダ名にします。
$ mkdir ~/mysite $ cd ~/mysite
(2) asciidoctor-diagramリポジトリの取得 [暫定対処]
次にasciidoctor-diagramをインストールします。
gemからインストールしたいところですが、現時点でrubygemsに登録されているバージョン1.2.1
は、Middleman経由で画像を生成するとParmission Deniedエラーが発生します。
バージョン1.3.0.preview.1
で試したところ、エラーを回避出来ていたので、今回はこのバージョンを使います。
$ mkdir -p vendor/repo $ cd vendor/repo $ git clone https://github.com/asciidoctor/asciidoctor-diagram.git $ cd asciidoctor-diagram $ git checkout v1.3.0.preview.1
注意:
バージョンアップなどで、将来的には挙動が変わるかもしれません。
エラーの原因については、後述の「おまけ:エラーの原因」を参照してください。
(3) Gemfileの編集
Gemfileを生成するために、まずmysite
フォルダでbundle init
を実行します。
$ cd ~/mysite $ bundle init
ここでGemfile
が作成されるので、次のように編集します。
# If you do not have OpenSSL installed, update # the following line to use "http://" instead source 'https://rubygems.org' gem "middleman", "~>3.3.12" # Live-reloading plugin gem "middleman-livereload", "~> 3.1.1" # For faster file watcher updates on Windows: gem "wdm", "~> 0.1.0", :platforms => [:mswin, :mingw] # Windows does not come with time zone data gem "tzinfo-data", platforms: [:mswin, :mingw, :jruby] # Activate support for AsciiDoc gem "asciidoctor", "~> 1.5.2" # Enable to embed diagrams in AsciiDoc documents. gem 'asciidoctor-diagram', "=1.3.0.preview.1", :path => "vendor/repo/asciidoctor-diagram"
(4) gemのインストール
Gemfileの編集が終わったらgemをインストールしていきます。
--path
オプションを指定するのを忘れないで下さい。
$ bundle install --path vendor/bundle
これでインストールは完了です。
Middlemanのセットアップ
(1) サイトの生成
まずGemfileのバックアップをとり、mysite
フォルダにてmiddleman init
コマンドでサイトを作ります。このときGemfileが上書きされるので、バックアップから元に戻しておきます。
$ cd ~/mysite $ cp Gemfile Gemfile.bk $ bundle exec middleman init . $ mv Gemfile.bk Gemfile
(2) config.rb
次に設定ファイル(config.rb
)のconfigure :build do ... end
ブロックの中に、次の行を追加します。
Asciidoctorでは文書の様々な属性を指定できますが、共通的に指定しておきたいものはここで設定しておきます。
config.rb:
... configure :build do ... # Asciidoctor set :asciidoc_attributes, %w(source-highlighter=coderay coderay-css=style) end
(3) MathJaxの設定
Asciidoctorで記述した数式は、HTMLに変換されるときにMathJaxのコードになります。
数式が表示されるように、MathJax.jsを読み込むようlayout.erb
を編集します。
source/layouts/layout.erb
を開き、<head> ... </head>
ブロックの中に以下の行を追記します。
MathJaxにはいくつかの設定パラメータがありますので[4]、必要に応じて設定してください。
<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML"> </script>
(4) サーバ起動
それではサーバを起動してみます。
$ bundle exec middleman server
次の画面が表示されたら成功です。
(5) サーバ終了
サーバの終了はCtrl+C
で行います。
ページを作る
ページファイルはsource
フォルダに格納します。必要に応じて任意のサブフォルダに格納することもできます。
他のSSGのように_post
フォルダに置く、といった決まりはありません。
また、ページファイルのフォーマットもMarkdownやAsciidoctorだけでなく、ERBやHaml(エクステンションを追加すればSlimも)が使えるので柔軟なWebサイトの構成が可能です。
サンプルページ
では、Asciidoctor形式のページを作ります。
source
フォルダ直下に、次のファイルを置いてください。
ファイル中のditaaやUML図は公式ドキュメント [5]のサンプルを使いました。
sample.adoc
:
:stem: latexmath = ドキュメントタイトル これは本文です。 == 数式を書く インラインの数式 latexmath:[\lambda \vec{x}.M]. .ブロック形式の数式 [latexmath] ++++ \begin{align*} e &::= c \mid x \\ &\phantom{::}\mid \lambda x.e \mid e\;e \end{align*} ++++ == 図を書く .ditaaによる図 [ditaa, dia-ditaa, png] .... +-------------+ | Asciidoctor |-------+ | diagram | | +-------------+ | PNG out ^ | | ditaa in | | v +--------+ +--------+----+ /---------------\ | | --+ Asciidoctor +--> | | | Text | +-------------+ | Beautiful | |Document| | !magic! | | Output | | {d}| | | | | +---+----+ +-------------+ \---------------/ : ^ | Lots of work | +-----------------------------------+ .... .PlantUMLによるクラス図 [plantuml, dia-classes, png] .... class BlockProcessor class DiagramBlock class DitaaBlock class PlantUmlBlock BlockProcessor <|-- DiagramBlock DiagramBlock <|-- DitaaBlock DiagramBlock <|-- PlantUmlBlock ....
ページをビルドする
middleman build
コマンドを使います。
ただしPlantUMLやditaaなどで図を記述した場合、今のところLaTeXのように2回ビルドする必要があります。
$ bundle exec middleman build $ bundle exec middleman build
これは1回目で画像ファイルを生成し、2回目で生成された画像ファイルを検知してbuild
フォルダへ移すためです。
ビルド中にasciidoctor-diagramが生成したものを、Middlemanが検知できていないのだと思います。
結果
先ほどと同じようにmiddleman server
コマンドでサーバを起動し、ページを開きます。
sample.adoc
の場合はsource
フォルダの直下においているので、URLはhttp://localhost:4567/sample.html
となります。
sample.adoc
をhtmlに変換した結果は次のようになります。
sample.htmlが表示されない場合
sample.htmlが表示されず、build
フォルダにsample.adoc
が格納されている場合、
Asciidoctorとasciidoctor-diagramがインストールされていない可能性があります。
もう一度Gemfileを確認して、bundle install --path vendor/bundle
を実行してください。
おまけ:エラーの原因
現行のasciidoctor-diagram-1.2.1とMiddleman 3を連携させると、画像の生成でエラーになります。
画像の出力フォルダをimages
とした場合、Middlemanはそれをサイトルート相対パスとして/images
というパスで扱います。しかし、asciidoctor-diagram-1.2.1では、そのパスをそのまま画像の出力フォルダとして扱います。
つまり、ルートディレクトリ直下にあるimages
フォルダとなるので、書き込み権限がなくてエラーになります。
この画像出力の問題で、過去にimagesoutdir
なる属性が追加されたり、いまは消えていたりと、現時点では公式な仕様がまだ確定されていません。[6]
今回は不安定なバージョンである1.3.0.preview.1
を使いましたが、将来的に挙動が変わる可能性があります。
安定版である1.2.1を使いたい場合は、以下にパッチを置いておきますので、利用を検討してみてください。
https://gist.github.com/succzero/34e57c01209ed9581fd9
どちらの方法をとるにせよ自己責任でお願いします。
参考ページ
[1] テクニカルライティングの将来 ー GitHub上のAsciidocで技術書Pro Gitを協働執筆. http://postd.cc/living-the-future-of-technical-writing/
[2] Differences between Asciidoctor and AsciiDoc. http://asciidoctor.org/docs/asciidoc-asciidoctor-diffs/
[3] Rails開発環境の構築(複数バージョン共存可能)(Homebrew編). http://qiita.com/emadurandal/items/e43c4896be1df60caef0
[4] Loading and Configuring MathJax. http://docs.mathjax.org/en/latest/configuration.html
[5] Asciidoctor Diagram. http://asciidoctor.org/docs/asciidoctor-diagram/
[6] Missing documentation on imagesoutdir attribute #59. https://github.com/asciidoctor/asciidoctor-diagram/issues/59
不動点とfix演算子
ある関数に対する不動点 とは、 なる です。 例えば、べき乗を関数とみなすと、 となり、1と0はべき乗の不動点となります [1]。
プログラム言語の教科書では という演算子が登場します [2,3,4]。 この と先の不動点はどう関係があるのか、フィボナッチ数の例で考えてみます。
フィボナッチ数を求める関数は、再帰的に定義すると次のようになります。
これをλ式で書くと
となります。しかしは、λ抽象の本体にという自由変数が現れています。
自由変数が現れているので、OCamlで書くとエラーになります(ただし、型なしラムダ計算では許されます)。
# let fib = fun n -> if n==0 || n==1 then 1 else fib (n-1) + (n-2);; Error: Unbound value fib
不動点
このままでは型付きの言語で再帰が書けません!
考え方を変えてみましょう。
次のような高階関数を定義します。
ここで本体の式にあるは、λによって束縛された変数であることに注意してください。 このを先ほどのに適用してみます。
\begin{align} F_{fib}\,fib &= (\lambda f. \lambda n. \mathsf{if}\;n=0 \lor n=1\;\mathsf{then}\;1\;\mathsf{else}\; f (n-1) + f (n-2))\;fib \\ &= \lambda n. \mathsf{if}\;n=0 \lor n=1\;\mathsf{then}\;1\;\mathsf{else}\; \color{red}{fib} (n-1) + \color{red}{fib} (n-2) \\ &= fib \end{align}
なんと、 という等式を満たすではありませんか!すなわち、はの不動点ということです。
しかし、 は自由変数が含まれており、実際には定義するとエラーになりました。 ということは をに適用することだって、本当はできません。 でも、高階関数 は定義できました!
不動点コンビネータ
先のを定義せず、から不動点なるを求めるにはどうしたらいいんでしょうか?
不動点コンビネータは、任意の関数からその関数の不動点を対応させてくれます。 代表的な不動点コンビネータの1つにコンビネータ [1]があり、次のように定義されます。
Yコンビネータを使うと、
となり、 であることがわかります。
になるのはわかりましたが、これをどうやって計算したらいいんでしょうか? この計算には、
- (1) 型を考えない(型なしラムダ計算)
- (2) 名前呼び戦略で計算する
という2点を知っておく必要があります。
(1) 型なしラムダ計算
型なしラムダ計算においては、どんな2つのλ式 であっても、 を に適用できます[5]。*1
例として、先の の赤字部分は、を自分自身に適用しています。これって型を考えるとおかしいですよね。 まずの型は です (最初に定義したの型はでした)。 ということは、 のの型はでなければなりません。
では、関数適用の型付け規則をみてみます。
ここで、 の型は のはずなので、
となります。
という式は、型を要求されています。
これはでなければならないはずです。
では、のの型についてはどうでしょうか?
だとわかりづらいので、と表記します。
いま不明な型をと表します。関数適用の型付け規則からの型は次のようになります。
さて、との型は同じはずです。 の型はいまなので、 も であるべきです。
おっと、 がであることを要求されてしまった!
というように自身の型が再帰的に現れています。 これは再帰型と呼ばれるものだそうです。 ということは、再帰型を扱えれば型付けされたYコンビネータが扱えるということでしょうか。 試してみましょう。
$ ocaml OCaml version 4.01.0 # let y = fun f -> ((fun x -> f (x x)) (fun x -> f (x x)));; Error: This expression has type 'a -> 'b but an expression was expected of type 'a The type variable 'a occurs inside 'a -> 'b $ ocaml -rectypes OCaml version 4.01.0 # let y = fun f -> ((fun x -> f (x x)) (fun x -> f (x x)));; val y : ('a -> 'a) -> 'a = <fun>
OCamlの-rectypes
を使ってYコンビネータを定義できました。
しかし、OCamlは値呼び戦略の言語であるため、これを実行すると延々と再帰し続け(後述)、スタックオーバーフローになります。
なおこのオプションは、より多くの値を受け付けてしまい、読みづらい型を与えてしまう傾向があるようです [6]。
ここでは単純な型の世界で再帰関数を実現したいので、再帰型は考えないことにします。 ともかく、Yコンビネータは型なしの世界で有効なのです。
(2) 名前呼び戦略 Call by Name
型を考えないとしても、 すなわち、をどのように計算すればいいでしょうか?
値呼び戦略 (Call by Value, CBV) だと延々と適用が繰り返されてしまいます。 CBVは関数適用の前に引数を先に計算して、その結果の値を関数に渡します。 試しに計算してみます。 の引数はですから、先にそれを計算します。
\begin{align} & F ( (\lambda x. F (x x) ) (\lambda x. F (x x) ) ) n \\ &= F ( (\lambda x. F (x x) ) (\lambda x. F (x x) ) ) n \\ &= F ( (\lambda x. F (x x) ) (\lambda x. F (x x) ) ) n \\ &= F (F ( (\lambda x. F (x x)) (\lambda x. F (x x) ) ) ) n \\ &= F (F (F ( (\lambda x. F (x x)) (\lambda x. F (x x) ) ) ) ) n \\ & \dots \end{align}
やはり延々と続いてしまいます。
では名前呼び戦略(Call by Name, CBN)はどうでしょうか? CBNでは、式の評価は名前を呼ばれるまで後回しにします。 ここで、読みやすさのためとします。 そして、は です。また、としておきます。
ではCBNで計算してみます。
\begin{align} & F (F' F') 5 \\ &= (\lambda n. \mathsf{if}\;n=0 \lor n=1\;\mathsf{then}\;1\;\mathsf{else}\;(\color{red}{F' F'}) (n-1) + (\color{red}{F' F'}) (n-2)) 5 \\ &= \mathsf{if}\;5=0 \lor 5=1\;\mathsf{then}\;1\;\mathsf{else}\;(\color{red}{F' F'}) (5-1) + (\color{red}{F' F'}) (5-2) \end{align}
おお!5への適用ができました! 引き続き、式の中を計算していきます。 の条件はになりますから、節を計算していきます。
\begin{align} &= (\color{red}{F' F'}) (5-1) + (\color{red}{F' F'}) (5-2) \\ &= F (F' F')(5-1) + (\color{red}{F' F'}) (5-2) \\ &= (\lambda n. \mathsf{if}\;n=0 \lor n=1\;\mathsf{then}\;1\;\mathsf{else}\; (\color{red}{F' F'}) (n-1) + (\color{red}{F' F'}) (n-2) ) (5-1) + (\color{red}{F' F'}) (5-2) \\ &= (\mathsf{if}\;(5-1)=0 \lor (5-1)=1 \\ &\phantom{=(}\;\mathsf{then}\;1 \\ &\phantom{=(}\; \mathsf{else}\;(\color{red}{F' F'}) ( (5-1)-1) + (\color{red}{F' F'}) ( (5-1)-2) ) (5-1) + (\color{red}{F' F'}) (5-2) \end{align}
あとは先ほどの繰り返しです。 以上のように、Yコンビネータで再帰処理が実現できました。
fix
Yコンビネータは型のない世界では有効ですが、型付きの世界では使えません。 そこで演算子です。 これはYと同じように不動点コンビネータとして作用します。
は教科書によっては と書いたり、と書いたりします。
先ほどのに対して、
前者:
後者:
と書きます。後者は中のをλで束縛するのではなく、で束縛します。のスコープは前者同様に、です。
ここでは後者の定義を用います。
各規則を以下に示します。
評価規則
は式中の変数を式に置き換える 代入 (substitution) と呼ばれる操作を行います。 これによってのときのように、再帰を実現しています。
型付け規則
型は関数型を含みます。
実際に式 を型付けしてみます。式 は型ですから、になります。
そしてlet recへ
は、との組み合わせで、以下のように定義できます [7]。
のほうが使いやすいですが、を使ったほうが計算の意味が見えてくると思います。
fixを実際に使ってみたい
を実際に使ってみたい方(あるいは自分で実装してみたい方)は、
https://github.com/succzero/fino
をどうぞ。(なお評価規則は、代入ではなく環境を使ったものになっています。)
cabal build
すれば使えるはずです。
OCamlではlet rec
を使ってしまえば、次のようにを定義できます。
# let rec fix f x = f (fix f) x;; val fix : (('a -> 'b) -> 'a -> 'b) -> 'a -> 'b = <fun> # let fibo = fun f -> fun n -> if n==0||n==1 then 1 else f (n-1) + f (n-2);; val fibo : (int -> int) -> int -> int = <fun> # fix fibo 10;; - : int = 89
Haskellの場合はfix
関数が用意されています。
Prelude> import Data.Function Prelude Data.Function> :i fix :: (a -> a) -> a -- Defined in ‘Data.Function’ Prelude Data.Function> let fact = fix (\f -> \n -> if n==0||n==1 then 1 else f (n-1) + f (n-2)) Prelude Data.Function> fact 10 89
まとめ
不動点コンビネータは、任意の関数から不動点を対応付けるものです。 型なしの世界で考えられた不動点コンビネータ(Yコンビネータ)は、単純な型付きの世界では型付けできないものでした。 型付きの不動点コンビネータとして作用するは、式あるいは型式中に再帰的に現れるに対して、代入操作を行うことで定義できました。 そして、再帰関数を束縛できるは、とによって定義付けでき、再帰関数の定義には不動点コンビネータが深く関わっていることをみてきました。
参考文献
[1] Fixed-point combinator - Wikipedia, the free encyclopedia. 2015年6月アクセス.
[2] Benjamin C. Pierce. 2002. Types and Programming Languages. MIT Press, Cambridge, MA, USA.
[3] Professor Robert Harper. 2012. Practical Foundations for Programming Languages. Cambridge University Press, New York, NY, USA.
[4] Gilles Dowek and Jean-Jacques Lvy. 2010. Introduction to the Theory of Programming Languages (1st ed.). Springer Publishing Company, Incorporated.
[5] 高橋正子 (1991). 計算論. 近代科学社.
[6] Jeremy Siek. Extensions the the Simply Typed Lambda Calculus. 2015年6月アクセス.
[7] Emmanuel Chailloux, Pascal Manoury, Bruno Pagano.
Developing Applications With Objective Caml, Appendix A Cyclic Types, Option -rectypes. 2015年6月アクセス.
OCaml モジュールとシグネチャの命名規則
モジュール名
OCamlのモジュール名は大文字から始まる必要があり、単語の区切り方は以下の2つのケースが多いようです。
- 先頭大文字のスネークケース (例: Type_utils)
- アッパーキャメルケース (例: TypeUtils)
前者はJane Street CoreやOcsigen等で見受けられます。後者はBatteriesやExtLib等で見受けられるスタイルです。
どちらを使うかは好みの問題なのでしょうが、特に理由がなければ
- 公式のコーディング規約で推奨されている(ようだ)
- Jane Street CoreやOcsigenを使った時にモジュール名の語感が合う
ということで、先頭大文字のスネークケースのスタイルを扱うのが良さそうです。
module Type_utils = struct ... end
シグネチャの名前
モジュールの型のようなものであるシグネチャについては、全て大文字で記述するのが慣習のようです。
module type TYPE_UTILS = sig ... end
ウェルズリー大学のTheory of Programming Languagesコースの資料では、 http://cs.wellesley.edu/~cs251/handouts/modules.pdf
Many OCaml programmers name signatures with all caps, but this is only a convention.
と述べられています。
コーディング規約
いくつかのコーディング規約から命名規則についてみていきます。
(1) 公式のコーディング規約
公式のコーディング規約については「アンダースコアで単語を区切る」とあります。
How to choose identifiers (識別子の決め方)というセクションの Separate words by underscores: (int_of_string, not intOfString) という項目です。
この「識別子(Identifiers)」が、小文字から始まる変数名や関数名のみを指しているのか、型構築子やモジュール名を含んでいるのかが気になるところです。
マニュアルをみてみると、識別子は大文字か小文字あるいはアンダースコアから始まる、と定義されています。
ということは単に「識別子」といった場合、モジュール名も該当すると考えられます。モジュールや構築子の識別子はアンダースコアで区切る、というのが推奨されているようです。(ただし、キャメルケースを使っている既存ライブラリと連携する場合は、その限りではないと書かれています。)
(2) OCaml Best Practices for Developers
Xen API (XAPI) のOCamlライブラリのプロジェクトで使われているコーディング規約です。
OCaml Best Practices for Developers - Xen
以下のように、単語の区切りはアンダースコアであり、略語が続く場合は大文字可としています。
module Parser = struct...end module Locking_strategy = struct...end module XML_UTF8 = struct...end
なお、シグネチャについては大文字でアンダースコア区切りとしていますが、読みやすさを妨げない事が前提となっています。
module type CAR_FACTORY = sig...end module Fast_car_factory : CAR_FACTORY = struct...end
(3) CS3110 OCaml Style Guide
コーネル大学のData Structures and Functional Programmingのコースで配布しているコーディング規約では、構築子やモジュールの命名規則はアッパーキャメルケースとしてます。また、ファンクタについてはFnを付けています。
上記資料より抜粋:
Token | OCaml Naming Convention | Example |
---|---|---|
Variables | Symbolic or initial lower case. Use snake_case instead of studlyCaps. | getItem, getItem |
Constructors | Initial upper case. Use StudlyCaps for multiword names. Historic exceptions are nil, true, and false. Rarely are symbolic names like :: used. | Node, EmptyQueue |
Types | All lower case. Use underscores for multiword names. | priority_queue |
Signatures | All upper case. Use underscores for multiword names. | PRIORITY_QUEUE |
Structures | Initial upper case. Use embedded caps for multiword names. | PriorityQueue |
Functors | Same as for structures, except Fn completes the name. | PriorityQueueFn |
先頭大文字のスネークケースというのは、他の言語ではあまり見られない慣習です。混乱を招くことが考えられる場合には、上記のような規約を導入し、特に理由が無い場合は公式のスタイルに準拠するのが良さそうです。
OCamlでPostgreSQLにアクセスする
シンプルなPostgreSQLのOCamlライブラリがないかと探したところ、Mottl氏らによるpostgresql-ocamlというライブラリがありました。
というわけで、postgresql-ocamlの導入と簡単な使い方のご紹介です。
公式ページ
インストール
OPAM経由でインストールすると楽です。
opam update
opam upgrade
opam install postgresql-ocaml
インストールしたところ、ライブラリのディレクトリ(~/.opam/4.02.0/lib
)にpostgresql-ocaml
とpostgresql
ディレクトリが作成されていました。postgresql-ocaml
側が空で、本体はpostgresql
ディレクトリに格納されています。
ocamlfindに登録されているか確認します。
$ ocamlfind list bigarray (version: [distributed with Ocaml]) postgresql (version: 2.1.0) threads (version: [distributed with Ocaml]) unix (version: [distributed with Ocaml])
なお、postgresql-ocamlはbigarray, threads(とunix)を必要とします。
サンプルデータを仕込む
適当なSQLファイルを作成します。
example.sql:
-- テーブルを作成する CREATE TABLE customers ( id INTEGER PRIMARY KEY, name VARCHAR(20) NOT NULL, address VARCHAR(60) ); -- サンプルデータを投入する INSERT INTO customers (id, name, address) VALUES (100, '山田太郎', '東京都港区'), (200, '佐藤一郎', '東京都千代田区');
SQLファイルをロードします。
$ psql -U user1 example -f example.sql
ここではデータベース、テーブル、所有者を以下のようにしています。
- データベース名: example, 所有者: user1
- テーブル名: customers, 所有者: user1
PostgreSQLのセットアップやコマンドの使い方はこちらを参照: MacでPostgreSQL - 一歩前進
サンプルコード
前半は通常のクエリ発行で、後半はprepared statementを使用しています。
#use "topfind";; #thread;; #require "postgresql";; open Printf open Postgresql (* DB名、ユーザ名、パスワードを指定してconnectionクラスのインスタンスを作成する *) let conn = new connection ~dbname:"example" ~host:"localhost" ~user:"user1" ~password:"user1" () (* SQL文;$1, $2, ... でプレースホルダを指定できる *) let query = "SELECT id, name, address FROM customers WHERE id = $1" (* 取得した結果を表示する関数 *) let show res = for tuple = 0 to res#ntuples - 1 do for field = 0 to res#nfields - 1 do printf "%s, " (res#getvalue tuple field) done; print_newline () done (* 受け取った文字列sをパラメータとしてクエリを発行し、結果を出力する *) let run s = show @@ conn#exec ~expect:[Tuples_ok] ~params:[| s |] query;; (* @@ はHaskellの$と同じく、( ) を省略するためのもの * ~ はラベル付き引数 * ~expectは、結果がTuples_ok(データが返ってきた場合)以外であれば例外を出すという指定 * ~paramsでプレースホルダにバインドするパラメータを、配列で指定 *) run "100";; (* => 100, 山田太郎, 東京都港区, *) run "200";; (* => 200, 佐藤一郎, 東京都千代田区, *) run "300";; (* => (表示されない) *) (* test1 という識別名でprepared statementを作る *) assert ((conn#prepare "test1" query)#status = Command_ok);; let prepared_run s name = show @@ conn#exec_prepared ~expect:[Tuples_ok] ~params:[|s|] name ;; prepared_run "100" "test1";; (* => 100, 山田太郎, 東京都港区, *) prepared_run "200" "test1";; (* 200, 佐藤一郎, 東京都千代田区, *) prepared_run "300" "test1";; (* => (表示されない) *)
MacでPostgreSQL
MacPorts経由でMacにPostgreSQLをインストールしたときのメモです。ここでは、サーバ運用は考慮せず、シングルユーザでの利用を想定しています。
通常ユーザのプロンプトを%
、postgresユーザのプロンプトをpostgres$
で示します。
インストール
% sudo port install postgresql93 +universal % sudo port install postgresql93-server
ユーザ環境の設定
postgresユーザの設定
PostgreSQLをインストールするとpostgres
というユーザが自動的に作成されます。
postgresユーザを有効化せずに、su - postgres -c コマンド
によって間接的にpostgresユーザとしてコマンドを実行する方法もあるのですが、頻繁に管理作業を行う場合はコマンドが煩雑になるため、postgresユーザを有効にしておきます。
パスワードの設定
postgresユーザにパスワードを設定して、アカウントを有効にします。
% sudo passwd postgres
Changing password for postgres.
New password: パスワードを入力
Retype new password: パスワードを再度入力
環境変数を設定する
.profile
を作成して、各種環境変数を設定します。
なお、postgresユーザのホームディレクトリは/opt/local/var/db/postgresql93
です。
% cd /opt/local/var/db/postgresql93 % sudo vi .profile
以下のような内容でパスおよびPGLIB, PGDATAを設定します。
export POSTGRES_HOME=/opt/local/lib/postgresql93 export PATH=${POSTGRES_HOME}/bin:${PATH} export PGLIB=${POSTGRES_HOME} export PGDATA=/opt/local/var/db/postgresql93/defaultdb
保存したら所有権を変更しておきます。
% sudo chown postgres:postgres .profile
一般ユーザの設定
次に、普段使用しているユーザの設定を行います。
パスを通す
MacPortsのPostgreSQLパッケージは、postgresql93やpostgresql84等、バージョンごとにパッケージが分かれています。そのため、コマンドの格納先が/opt/local/postgresql93/bin
となっていますが、port select
コマンドを使うことで/opt/local/bin
にコマンドへのシンボリックリンクを貼ることが出来ます。
postgresqlのバージョンをpostgresql93にする:
% sudo port select --set postgresql postgresql93 Selecting 'postgresql93' for 'postgresql' succeeded. 'postgresql93' is now active.
確認する:
% port select --list postgresql
none
postgresql93 (active)
元に戻す場合:
% sudo port select --set postgresql none Selecting 'none' for 'postgresql' succeeded. 'none' is now active.
設定の再読込み:
port select --set
を使ったらターミナルを再起動するか、.zshrc
や.bashrc
を読み込みます。
% source ~/.zshrc
これでpg_ctl
やpsql
コマンドにパスが通りました。
% which pg_ctl
/opt/local/bin/pg_ctl
環境変数の設定
環境変数PGDATA
を.zshrc
や.bashrc
に設定します(コマンドへのパスは通っているので、POSTGRES_HOME等は設定しません)。
後述するデータベース・クラスタの名前はdefaultdb
にしてします。
export PGDATA=/opt/local/var/db/postgresql93/defaultdb
ターミナルを再起動するか、設定を再ロードします。
% source ~/.zshrc
データベース・クラスタの作成
データベース・クラスタはディスク上のデータベース格納領域であり、1つのサーバインスタンスで管理されるデータベースの集合とのこと。Oracleでいうデータベース(≠データファイル)に相当するものでしょうか。
(参考:データベースクラスタの作成 )
(1) ディレクトリの作成
defaultdb
という名前でディレクトリを作成し、パーミッションをpostgres
にします。
既に${PGDATA}
にディレクトリパス/opt/local/var/db/postgresql93/defaultdb
を設定しているので、これを利用します。
% sudo mkdir -p ${PGDATA} % sudo chown postgres:postgres ${PGDATA}
(2) initdbの実行
次に、先ほど作成したdefaultdb
ディレクトリを指定してinitdb
コマンドを実行します。initdb
はpostgresユーザで実行する必要あります。su - postgres
のようにハイフンを指定することで、現ユーザの環境を引き継がないようにして余計なトラブルを回避します。
日本語を扱えるようにするため、initdb
のオプションに--encoding=UTF-8 --locale=ja_JP.UTF-8
を指定しています。他のエンコーディングを使いたい場合はそれを指定してください。ただし、encodingとlocaleが異なるとデータを破壊する原因になるようです。(参考:ロケール(国際化と地域化) — Let's Postgres)
なお、postgresユーザ環境に環境変数PGDATA
を設定しているため、-D /opt/local/var/db/postgresql93/defaultdb
のようにディレクトリへのパスを指定する必要はありません。
% su - postgres (postgresユーザのパスワード入力) postgres$ initdb --encoding=UTF-8 --locale=ja_JP.UTF-8 The files belonging to this database system will be owned by user "postgres". This user must also own the server process. The database cluster will be initialized with locale "ja_JP.UTF-8". The default database encoding has accordingly been set to "UTF8". initdb: could not find suitable text search configuration for locale "ja_JP.UTF-8" The default text search configuration will be set to "simple". ... WARNING: enabling "trust" authentication for local connections You can change this by editing pg_hba.conf or using the option -A, or --auth-local and --auth-host, the next time you run initdb. Success. You can now start the database server using: postgres -D /opt/local/var/db/postgresql93/defaultdb or pg_ctl -D /opt/local/var/db/postgresql93/defaultdb -l logfile start
WARNING:
の部分では、デフォルトではTrust認証を使っているので注意ってことらしい。ここではシングルユーザ(個人)で使うだけなのでデフォルトのままにしておきます。
(参考:https://www.postgresql.jp/document/9.3/html/auth-methods.html)
起動と停止
起動:
postgres$ pg_ctl start もしくは % sudo su - postgres -c "pg_ctl -D ${PGDATA} start"
停止:
postgres$ pg_ctl stop もしくは % sudo su - postgres -c "pg_ctl -D ${PGDATA} start"
(参考:pg_ctlコマンド https://www.postgresql.jp/document/9.3/html/app-pg-ctl.html)
サポートスクリプトを使う場合
MacPortsでは、/opt/local/etc/LaunchDaemons/org.macports.postgresql93-server
ディレクトリに起動・停止のためのサポートスクリプトがインストールされていました。
これを使って.zshrc
あたりにエイリアスを設定しておくと、postgres以外のユーザから起動・停止がしやすくなります。
alias pg_start='sudo /opt/local/etc/LaunchDaemons/org.macports.postgresql93-server/postgresql93-server.wrapper start' alias pg_stop='sudo /opt/local/etc/LaunchDaemons/org.macports.postgresql93-server/postgresql93-server.wrapper stop'
データベースに対する一般ユーザの作成
現在のdefaultdb
には管理ユーザpostgresしかいないため、一般ユーザを作成しておきます。(ここでのユーザはOSのユーザではなく、PostgreSQLのdefaultdb
クラスタに登録されたユーザのことを指します)
ここで作成する一般ユーザの名前を普段使用しているOSのユーザ名と同じにしておくと、psql
等のコマンドを実行する際に-U 接続ユーザ名
の指定を省略できるようになります。
しかし、CやJavaのプログラムからPostgreSQLサーバに接続して使用することを想定するため、異なるユーザ名を指定します。
# サーバ起動 postgres$ pg_ctl start # 対話環境の起動 postgres$ psql psql (9.3.5) Type "help" for help. postgres=# # 別のユーザが対話環境を起動する場合: % psql -U postgres ← 接続ユーザを指定する
ユーザ一覧の確認:
\du
コマンドでユーザの一覧を確認します。
postgres=# \du List of roles Role name | Attributes | Member of -----------+------------------------------------------------+----------- postgres | Superuser, Create role, Create DB, Replication | {}
現在はpostgresユーザしかいません。
ユーザの作成:
別のターミナルを立ち上げ、createuser
コマンドでuser1というユーザを追加します。
% createuser -U postgres -P user1 Enter password for new role: (パスワードを入力) Enter it again:(パスワードを入力)
スーパーユーザ権限を与えるなどのオプションは--help
オプションで確認できます。
再度\du
コマンドで確認するとuser1ユーザが作成されています。
postgres=# \du List of roles Role name | Attributes | Member of -----------+------------------------------------------------+----------- postgres | Superuser, Create role, Create DB, Replication | {} user1 | | {}
データベースの作成
先ほど作成したuser1ユーザを所有者にして、example
というデータベースを作成します。
% createdb -U postgres --owner=user1 example
psqlから\l
コマンドでデータベースの一覧を確認すると、example
データベースが表示されます。
postgres=# \l List of databases Name | Owner | Encoding | Collate | Ctype | Access privileges -----------+----------+----------+-------------+-------------+----------------------- example | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | postgres | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | template0 | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres template1 | postgres | UTF8 | ja_JP.UTF-8 | ja_JP.UTF-8 | =c/postgres + | | | | | postgres=CTc/postgres (4 rows)
テーブルの作成
まず、\c データベース名 ユーザ名
で作成先のデータベースに切り替えます。テーブルの所有者をuser1で作成するため、ユーザ名にuser1を指定しています。
postgres=# \c example user1 You are now connected to database "example" as user "user1".
ここからは通常のSQLコマンドを実行していくだけです。
example=# CREATE TABLE customers example-# ( id INTEGER PRIMARY KEY, example(# name VARCHAR(20) NOT NULL, example(# address VARCHAR(20)); ← セミコロンで文を閉じる CREATE TABLE
SQLファイルを直接実行する場合
# 作成するテーブルの所有者:user1 # 作成先のデータベース:example % psql -U user1 example -f setup.sql
さらなる設定
そのほかの設定はここでは割愛しますが、postgresql.conf
やpg_hba.conf
等の各種設定ファイルは/opt/local/var/db/postgresql93/defaultdb
直下にあります。
また、参考になるリンクをご紹介しておきます。
- ログの設定
- 他ホストからの接続許可
コマンドを簡略化するため、postgresアカウントを有効にしましたが、ひと通りの管理作業が終わったらpostgresアカウントを無効(初期状態)に戻すとセキュリティ的に安心です。初期状態に戻すにはpasswd
コマンドで空のパスワードを設定します。
コマンドまとめ
コマンド | 説明 |
---|---|
pg_ctl start | サーバ起動 |
pg_ctl stop | サーバ停止 |
createuser -P ユーザ名 | ユーザ追加 |
dropuser ユーザ名 | ユーザ削除 |
createdb --owner=所有者名 データベース名 | データベース追加 |
dropdb データベース名 | データベース削除 |
psql -U 接続ユーザ名 データベース名 -f SQLファイル | SQLファイルを処理する |
- pg_ctlコマンドはpostgresユーザから実行
- その他のコマンドはPostgreSQLユーザ以外のユーザから操作する場合は、
-U 接続ユーザ名
オプションを付加
(上記以外のコマンド: https://www.postgresql.jp/document/9.3/html/reference-client.html)
psqlメタコマンド:
コマンド | 説明 |
---|---|
\l | データベースを列挙する |
\du | データベースのユーザ(ロール)を一覧表示する |
\z | テーブル、ビュー、シーケンスの一覧を表示する |
\c データベース名 ユーザ名 | 現在のデータベースを切り替える |
\cd ディレクトリ | 作業ディレクトリを変更する |
\h SQLコマンド | SQLの構文に関するヘルプを表示する |
\o ファイル名 | クエリの結果をファイルに出力する |
\r | コンソールバッファをクリアする |
\q | 対話環境を終了する |
(上記以外のコマンド : https://www.postgresql.jp/document/9.3/html/app-psql.html)
MacTeX 2014
TeX環境を入れ直したのでメモ。
なんだかんだでhomebrewからMacPortsに戻ってきました。
MacPortsにはtexのパッケージが用意されています。しかし、MacPortsからインストールするとTeXのパッケージ管理ツールTeX Live Manager(tlmgr)での管理が出来ないのと、パスがTeXの共通的な/usr/texbin
ではなく/opt/local
なパスになって、他の人とのTeXに関するスクリプトの共有が難しくなります。というわけで、ここはやはりMacTeX (TeX Live)を使います。
方針:TeX Live Managerで管理されないものはMacPortsで管理する
MacTex 2014にはps => pdf 変換に使われるghostscriptがバンドルされていますが、これはTeX Live Managerの管理対象外なので、MacPortsで管理することにします。
1. インストールするもの
パッケージ名 | 内容 | 備考 |
---|---|---|
ghostscript | ps => pdf変換等々に使われる | MacPortsからインストールする |
ImageMagick | TeXに画像を埋め込むときに、png, jpg等々の画像からepsに変換するためによく使う | MacPortsからインストールする |
MacTeX 2014 | デファクトスタンダードなTeXのディストリビューションであるTeX Liveと、Mac用のGUIアプリ、ghostscriptをバンドルしたもの | ここでは必要最小限のGUIアプリを導入するため、TeX Live 2014のみインストールします |
TeX Live Utility | パッケージ管理ツール TeX Live Manager (tlmgr)のフロントエンド | 個別にインストールします |
MacTeX 2014には、
が同梱されています。MacTeXに同梱されたGUIアプリは今回扱いませんが、紹介だけしておきます。
MacTeXに同梱されたGUIアプリ(今回は割愛):
- TeXShop: TeXのエディタ。これ使うよりvim使いましょう。
- TeXworks: TeXの統合環境、補完機能とかある。それよりvim使おう。
- BibDesk: 文献管理ツール。これ使うならJabRefかMendeleyがオススメ。
- LaTeXiT: 数式エディタ。パワポに数式を貼り付けるのに便利。
- TeX Live Utility: TeXのパッケージ管理ツール。個別にインストールするので、MacTeX に同梱されているものは無視。
- Excalibur: スペルチェッカ。誤字脱字は恥ずかしいのであったほうがいいかも。
2. 前提環境
3. インストール
3.1 ghostscript
ghostscriptは、ページ記述言語であるPostScriptとPDFのインタプリタであり、これらのデータを入力として、ラスタ画像(ビットマップ画像)に変換し、印刷やビューアでの表示、あるいはPostScript <-> PDF間の変換に使われます。
CUPS対応のghostscriptを導入するなら、+cupsオプションをつけておきましょう。
$ sudo port install ghostscript +universal +cups + x11
3.2 ImageMagick
ImageMagickは様々なフォーマットの画像に対するフォーマット変換やリサイズ、回転、色調整等々の各種操作を扱うソフトウェアスイートです。
以下のオプションを指定してインストールします。 大量の依存パッケージがインストールされますが、細かいコトは気にしないようにしましょう。問題があるようなら、オプションを変えてパッケージを再インストールすればいいのです。
$ sudo port install ImageMagick +graphviz +jbig +jpeg2 +pango +rsvg +universal +wmf +x11
オプションが気になる方へ:
ImageMagickパッケージは依存関係のある厄介なオプションが多く、パッケージのオプションを注意深く検討しているporterにとっては要注意パッケージです。
特に、ImageMagickパッケージの+graphvizオプションを有効にしたときに依存するgraphvizパッケージは、オプションとそれに依存するパッケージが多いので、気になる方は事前にgraphvizを導入しておいたほうがいいでしょう。
3.3 MacTeX 2014
以下から、MacTeX.pkg
をダウンロードします。
ダウンロードしたpkgを実行し、TeX Live 2014のみをインストールするようにします。
インストールが完了したら、環境がTeX Live 2014になっていることを確認します。
Appleマーク→「システム環境設定」→「TeX Distribution」を開き、TeXLive-2014が選択されていることを確認します。
4. パッケージ管理
$ mkdir -p /Applications/TeX
4.1 Tex Live Utilityのインストール
以下から、最新のTeX Live Utilityをダウンロードします。ダウンロード一覧の中にはBETA版が混在していますが、避けたほうがいいです。
https://code.google.com/p/mactlmgr/
ここでは、TeX Live Utility.app-1.17.tar.gzをダウンロードしました。このファイルを展開して、出てきた.appファイルを/Application/TeX
に移動してください。
4.2 パッケージの最新化
TeX Live Utilityを起動すると、自動的にパッケージの一覧を取得しにいくので、しばらく待ちます。
メニューの「作業」→「すべてのパッケージを更新」を選びます。
4.3 pmetapost, pxdvi の導入
4.3.1 pmetapost, pxdviとは
pmetapostはMetaPostを日本語に対応させたものです。
MetaPostは、図形描画のための一種のプログラミング言語であり、そのインタプリタでもあります(ドナルド・クヌース先生のMetafontという言語に基いていて、構文的に類似性があるそうです)。 重要なのは直接EPS(Encapsulated PostScript)を生成できるところで、これによってベクトルデータのみを含むようなepsが扱えるようになります。pngやjpgといった画像からepsに変換することも出来ますが、ビットマップデータを含む形になってしまい、画像がややぼやけてしまう問題があります。綺麗な図形を扱うならmetapostというわけです。pmetapostを使うことで、日本語文字の入った図形を描画できます。
pxdviは、dviビューアであるxdviの日本語化版です。(Mac環境でこれを使うことはあまりないので、こっちはどうでもいい)
4.3.2 tlptexliveリポジトリによるパッケージの導入
これらpmetapost, pxdviを扱っているリポジトリがtlptexliveであり、TeX Live 2014 版のURLは以下になります。
http://www.tug.org/~preining/tlptexlive/
(参考: http://www.preining.info/blog/2014/05/tex-live-2014%E3%81%AEtlptexlive/)
※以前はptex, uptexも上記のリポジトリから導入していましたが、現在ではTeX Liveに取り込まれたようです。
このURLを、Tex Live UtilityのURLに貼り付けると、
http://www.tug.org/~preining/tlptexlive/のリポジトリにはTeX Live 2013がありますが、ここに導入されているものは TeX Live 2014です。続行するにはリポジトリを切り替えなくてはなりません。
というエラーが出て先に進めません。(2014年7月現在)
ここでは、コマンドラインから直接リポジトリを追加してパッケージを導入していきます。
$ sudo tlmgr repository add http://www.tug.org/~preining/tlptexlive/ tlptexlive tlmgr: added repository with tag tlptexlive: http://www.tug.org/~preining/tlptexlive/ $ sudo tlmgr pinning add tlptexlive '*' tlmgr: package repositories: main = http://mirror.ctan.org/systems/texlive/tlnet tlptexlive = http://www.tug.org/~preining/tlptexlive/ tlmgr: new pinning data for tlptexlive: * $ sudo tlmgr install pxdvi pmetapost tlmgr: package repositories: main = http://mirror.ctan.org/systems/texlive/tlnet tlptexlive = http://www.tug.org/~preining/tlptexlive/ ...(中略)... done running mtxrun --generate.
これで、pxdvi, pmetapostが導入できました。
5. 日本語フォントの設定
PDFはフォントを埋め込むことが出来ます。逆にフォントを埋め込まない場合、(特に印刷所での印刷で)文字化けを起こす可能性があります。 学会等ではフォント埋込みを要求しているところが多く、フォント埋め込みがなされていない場合は投稿時にエラー、なんてところもあるようです。
TeX Live 2014はデフォルトで埋込みがなされない(noEmbed)設定になっています。というわけで、ここでは、日本語フォントを埋め込む設定を行っていきます。
MacのTeXに関するページで、よくヒラギノフォントの設定が書かれていますが、これをやってしまうと、気づかないうちにヒラギノフォントを埋め込んだPDFを外部に公開してしまうのでオススメしません(ご自身の利用ケースではライセンス的に問題無いことが明確であれば別です)。
かといって、ライセンスフリーなIPA, IPAexフォントは太字が無いため、単にIPA, IPAexフォントにすればいいというものでもありません。 そのため、明朝の太字、ゴシックの太字等々、パターンに応じたフォントの用意とそのフォントマップの設定をする必要があります。(太字をゴシックで代用する方法で問題なければ、IPAexフォントでいいと思います)
ここでは、以下のthomas氏のページを参考に、基本的な5種類のフォントについて具体的な設定を行っていきます。ディレクトリやファイル名等は若干変えていきます。
参考:http://www.fugenji.org/~thomas/texlive-guide/font_setup.html
(フォントに関する問題を知っておくためにも、一読されることをお勧めします。ここでは単にMacでのインストール作業について述べます。)
No. | フォントの種類 | 採用するフォント |
---|---|---|
(1) | 明朝 | IPAex 明朝 |
(2) | ゴシック | IPAex ゴシック |
(3) | ボールド明朝 | MogaMincho Bold |
(4) | ボールドゴシック | MigMix 2P Bold |
(5) | 丸ゴシック | MigMix 1M Regular |
5.1 FontBookの設定
フォントは、ユーザディレクトリ側ではなくシステム側にインストールします。 まず/Applications/Font Book.appを起動します。(Launchpadの場合、「その他」の中にあります)
次にメニューの「Font Book」→「環境設定」を開き、デフォルトのインストール場所を「コンピュータ」に変更しておきます。
5.2 (1) 明朝、(2)ゴシック
基本となる明朝・ゴシック体フォントは、IPAexフォントを使います。
IPAフォントとIPAexフォントの違いは、IPAフォントが固定幅フォント(IPA 明朝等)と可変幅フォント(IPA P明朝等)で別れていたのに対し、IPAexフォントでは和文文字が固定幅、欧文文字が変動幅となっており、日本語文書の慣例に沿っている点が特徴的です。
IPAexフォントはTex Live 2014に同梱されておりそれをインストールすればいいのですが、ここでは新たにダウンロードしてインストールします。 ダウンロードは以下から行います。
http://ipafont.ipa.go.jp/ipaexfont/download.html
2書体パックとなっているものをダウンロードすると手っ取り早いです。
2書体パック(IPAex明朝(Ver.002.01)、IPAexゴシック(Ver.002.01)) IPAexfont00201.zip(9.31 MB)
ファイルを展開すると、「ipaexg.ttf」と「ipaexm.ttf」が出てくるので、それぞれインストールします。 このとき、ユーザ側に同じフォントがインストールされていないことを確認します。もしインストールされていた場合は、先にそのフォントをアンインストールしておきます。
次に、texliveフォルダにIPAexフォントのリンクを貼ります。
# texliveのフォントフォルダに移動する $ cd /usr/local/texlive/texmf-local/fonts # IPAexフォントを格納するフォルダを作成する $ sudo mkdir -p truetype/public/ipaex # インストールしておいたIPAexフォントのリンクを貼る $ sudo ln -fs /Library/Fonts/ipa*.ttf ./
5.3 (3) ボールド明朝
明朝のボールドはMogaMinchoを使用します。 現状では、フリーなフォントとしてはこれが唯一の選択肢のようです。
以下のページにMogaMinchoを含む「ゴシック&明朝 MoboGothic / MogaGothic / MogaMincho TTCパック」がありますので、それをダウンロードします。
http://yozvox.web.fc2.com/82A882B782B782DF8374834883938367.html
ここでは、MoboMoga-001.02.12b.7zをダウンロードしました。 これを展開し、「mogamb.ttc」をダブルクリックすると、複数のフォントが表示されます。
これらをひと通りインストールします。
次にフォントのシンボリックリンクを作成します。
$ cd /usr/local/texlive/texmf-local/fonts/truetype/public $ sudo mkdir moga $ cd moga $ sudo ln -fs /Library/Fonts/mogamb.ttc .
5.4 (4) ボールドゴシック、(5)丸ゴシック
ゴシック体のボールドにはMigMix 2P、丸ゴシックとしてMigMix 1Mを使います。
以下のページから、MigMix 2PとMigMix 1Mのファイルをそれぞれダウンロードします。
http://mix-mplus-ipa.sourceforge.jp/migmix/
(今回は、migmix-2p-20130617.zip, migmix-1m-20130617.zipをダウンロードしました。)
それぞれのzipファイルを展開して、
- MigMix 2P: migmix-2p-bold.ttf
- MigMix 1M: migmix-1m-regular.ttf
をそれぞれインストールします。 先と同様に、シンボリックリンクを作成します。
$ cd /usr/local/texlive/texmf-local/fonts/truetype/public/ $ sudo mkdir migmix $ cd migmix $ sudo ln -fs /Library/Fonts/migmix-*.ttf ./
5.5 フォントマップの設定
(1) マップファイルの配置
マップファイルを格納するフォルダを作成します。
$ cd /usr/local/texlive/texmf-local/fonts/ $ sudo mkdir -p map/dvipdfmx/jfontmaps/allfree
次に、以下のファイルをptex-allfree.mapというファイル名で保存し、/usr/local/texlive/texmf-local/fonts/map/dvipdfmx/jfontmaps/allfree
に格納します。
※ 以下のファイルはthomas氏のmapファイルを若干修正したものです。
platex-allfree.map:
rml UniJIS-UTF16-H ipaexm.ttf rmlv UniJIS-UTF16-V ipaexm.ttf rml Identity-H ipaexm.ttf rmlv Identity-V ipaexm.ttf rml H ipaexm.ttf rmlv V ipaexm.ttf unijmin-h UniJIS-UTF16-H ipaexm.ttf unijmin-v UniJIS-UTF16-V ipaexm.ttf cidmin-h Identity-H ipaexm.ttf/AJ16 cidmin-v Identity-V ipaexm.ttf/AJ16 gbm UniJIS-UTF16-H ipaexg.ttf gbmv UniJIS-UTF16-V ipaexg.ttf gbm Identity-H ipaexg.ttf gbmv Identity-V ipaexg.ttf gbm H ipaexg.ttf gbmv V ipaexg.ttf unijgoth-h UniJIS-UTF16-H ipaexg.ttf unijgoth-v UniJIS-UTF16-V ipaexg.ttf cidgoth-h Identity-H ipaexg.ttf/AJ16 cidgoth-v Identity-V ipaexg.ttf/AJ16 otf-ujmr-h UniJIS-UTF16-H ipaexm.ttf otf-ujmr-v UniJIS-UTF16-V ipaexm.ttf otf-cjmr-h Identity-H ipaexm.ttf/AJ16 otf-cjmr-v Identity-V ipaexm.ttf/AJ16 hminr-h H ipaexm.ttf hminr-v V ipaexm.ttf otf-ujgr-h UniJIS-UTF16-H ipaexg.ttf otf-ujgr-v UniJIS-UTF16-V ipaexg.ttf otf-cjgr-h Identity-H ipaexg.ttf/AJ16 otf-cjgr-v Identity-V ipaexg.ttf/AJ16 hgothr-h H ipaexg.ttf hgothr-v V ipaexg.ttf otf-ujmb-h UniJIS-UTF16-H :1:mogamb.ttc otf-ujmb-v UniJIS-UTF16-V :1:mogamb.ttc otf-cjmb-h Identity-H :1:mogamb.ttc/AJ16 otf-cjmb-v Identity-V :1:mogamb.ttc/AJ16 hminb-h H :1:mogamb.ttc hminb-v V :1:mogamb.ttc otf-cjgb-h Identity-H migmix-2p-bold.ttf/AJ16 otf-cjgb-v Identity-V migmix-2p-bold.ttf/AJ16 otf-ujgb-h UniJIS-UTF16-H migmix-2p-bold.ttf otf-ujgb-v UniJIS-UTF16-V migmix-2p-bold.ttf hgothb-h H migmix-2p-bold.ttf hgothb-v V migmix-2p-bold.ttf otf-ujmgr-h UniJIS-UTF16-H migmix-1m-regular.ttf otf-ujmgr-v UniJIS-UTF16-V migmix-1m-regular.ttf otf-cjmgr-h Identity-H migmix-1m-regular.ttf/AJ16 otf-cjmgr-v Identity-V migmix-1m-regular.ttf/AJ16 hmgothr-h H migmix-1m-regular.ttf hmgothr-v V migmix-1m-regular.ttf
注意点として、上記のフォントファイル名(migmix-2pp-bold.ttf等)の箇所は、大文字小文字が区別されるため、実際のファイル名と合わせて下さい。
余談ですが、上記のmapファイルのファイル名には、先頭にplatex-と付けています。これをつけておかないと、マップの反映をする際に次のようなエラーが発生します。
$ kanji-config-updmap allfree NOT EXIST ptex-allfree.map
スクリプトをみると、mapファイルの先頭にptex-を決め打ちで付けていました(3行目)。
sub SetupMapFile { my $rep = shift; my $MAPFILE = "ptex-$rep.map"; if (check_mapfile($MAPFILE)) { print "Setting up ... $MAPFILE\n"; system("$updmap --quiet --nomkmap --nohash -setoption kanjiEmbed $rep"); if ($opt_jis) { system("$updmap --quiet --nomkmap --nohash -setoption kanjiVariant -04"); } else { system("$updmap --quiet --nomkmap --nohash -setoption kanjiVariant \"\""); } system("$updmap"); } else { print "NOT EXIST $MAPFILE\n"; exit 1; } }
(2) ls-Rデータベースの更新
ひと通りのフォントのセットアップが終わったら、mktexlsrコマンドでls-Rデータベースを更新します。 このls-Rは、/usr/local/texlive/texmf-local以下のテキストファイルの検索を高速化するために用いられるものです。
$ sudo mktexlsr mktexlsr: Updating /usr/local/texlive/2014/texmf-config/ls-R... mktexlsr: Updating /usr/local/texlive/2014/texmf-dist/ls-R... mktexlsr: Updating /usr/local/texlive/2014/texmf-var/ls-R... mktexlsr: Updating /usr/local/texlive/texmf-local/ls-R... mktexlsr: Done.
(3) マップファイルの適用
$ kanji-config-updmap allfree
上記の場合、ユーザ環境に個別に設定が適用されます。システム全体に適応した場合は、sudo kanji-config-updmap-sys
コマンドを使用してください。
5.6 ヒラギノフォントを埋め込む場合
以下のコマンドをコピペして実行するだけで設定できます。
sudo mkdir -p /usr/local/texlive/texmf-local/fonts/opentype/hiragino/ cd /usr/local/texlive/texmf-local/fonts/opentype/hiragino/ sudo ln -fs "/Library/Fonts/ヒラギノ明朝 Pro W3.otf" ./HiraMinPro-W3.otf sudo ln -fs "/Library/Fonts/ヒラギノ明朝 Pro W6.otf" ./HiraMinPro-W6.otf sudo ln -fs "/Library/Fonts/ヒラギノ丸ゴ Pro W4.otf" ./HiraMaruPro-W4.otf sudo ln -fs "/Library/Fonts/ヒラギノ角ゴ Pro W3.otf" ./HiraKakuPro-W3.otf sudo ln -fs "/Library/Fonts/ヒラギノ角ゴ Pro W6.otf" ./HiraKakuPro-W6.otf sudo ln -fs "/Library/Fonts/ヒラギノ角ゴ Std W8.otf" ./HiraKakuStd-W8.otf sudo ln -fs "/System/Library/Fonts/ヒラギノ明朝 ProN W3.otf" ./HiraMinProN-W3.otf sudo ln -fs "/System/Library/Fonts/ヒラギノ明朝 ProN W6.otf" ./HiraMinProN-W6.otf sudo ln -fs "/Library/Fonts/ヒラギノ丸ゴ ProN W4.otf" ./HiraMaruProN-W4.otf sudo ln -fs "/System/Library/Fonts/ヒラギノ角ゴ ProN W3.otf" ./HiraKakuProN-W3.otf sudo ln -fs "/System/Library/Fonts/ヒラギノ角ゴ ProN W6.otf" ./HiraKakuProN-W6.otf sudo ln -fs "/Library/Fonts/ヒラギノ角ゴ StdN W8.otf" ./HiraKakuStdN-W8.otf sudo texconfig-sys rehash
実際にヒラギノフォントのマップファイルを適用するには、以下を実行します。
$ kanji-config-updmap hiragino
5.7 確認
テキトーなファイルを作って、allfree版とhiragino版それぞれの結果を確認してみます。
せっかくuplatexがTeX Liveにバンドルされているので、uplatexを使いましょう。{jsarticle}
の前に、uplatexを指定します。
sample.pdf:
\documentclass[uplatex]{jsarticle} \usepackage[expert, deluxe]{otf} \usepackage{amsthm} \begin{document} \section{漢字とひらがなとカタカナ} \subsection{漢字とひらがなとカタカナ} \subsubsection{漢字とひらがなとカタカナ} これは通常のテキストで、明朝で表示されます. {\bf ボールド明朝}と{\gt ゴシック}、{\bf \textgt{ボールドゴシック}}、そして{\mgfamily 丸ゴシック}の書体が使い分けられます. \noindent {\bf 集合}(set)とは、ものの集まりのことである. \noindent {\gt 集合}(set)とは、ものの集まりのことである. \noindent {\bf \textgt{集合}}(set)とは、ものの集まりのことである. \end{document}
Makefileはちゃちゃっとこんな感じで。(スペース4つはタブに読み替えてください)
LATEX=uplatex PDFLATEX=pdflatex DVIPDFM=dvipdfmx TARGET=sample.pdf .PHONY: all clean all: $(TARGET) clean: /bin/rm -f *.dvi *.out *.nav *.snm *.vrb *.toc *.aux *.log *.pdf %.pdf: %.dvi dvipdfmx $< %.dvi: %.tex uplatex -interaction=batchmode $<
結果をみてみましょう。
allfree版:
hiragino版:
集合(set)とは〜、の下りのところは、上からボールド明朝、ゴシック、ボールドゴシックです。
allfree版で示したMogaMincho Boldはやや太さが足りない気がします。やはりヒラギノフォントは優秀です。フォントについて考えだすときりがないので、(クオリティについては)商用の出版物でない限り気にしないことにします。
5.8 フォントマップ切り替え
- デフォルトに戻す
kanji-config-updmap noEmbed
- allfreeなフォント埋込みにする
kanji-config-updmap allfree
- ヒラギノフォント埋込みにする
kanji-config-updmap hiragino
システム全体に適用する場合はkanji-config-updmap-sys
を使います。また、以前はupdmap-setup-kanji
というコマンド名でしたが、現在ではkanji-config-updmap
に変わっています。
Vim + Vim-LaTeX
Vimのtexプラグインは、Vim-LaTeXが有名らしいです。
インストール
NeoBundleを使っている場合、.vimrc
に以下の行を加えてvimを起動すれば勝手にインストールされます。
NeoBundle 'git://git.code.sf.net/p/vim-latex/vim-latex'
.vimrcの設定と使い方
.vimrcの設定はこちらをそのままコピペします。
使い方は、以下のページが詳しいです。
http://oku.edu.mie-u.ac.jp/~okumura/texwiki/?Vim-LaTeX#v4639f7b
さらなる詳細は、vimから:help latex-suite
で出てきます。
特に使用頻度の高そうな機能を紹介すると、以下の操作でコンパイルと表示が出来ます。いずれもノーマルモード時にて。
特に、Preview.appを使っている場合、pdfを表示したまま\ll
で再コンパイルすると、その結果がそのまま反映されます。
\ll
すら面倒だ、という方にはOMakeを使用することをオススメします。
OMakeでtexをコンパイルするのはこのあたりが参考になります。
http://d.hatena.ne.jp/hayamiz/20081208/1228727272
texのファイルが変更されたことを監視して勝手にコンパイルしてくれるので、
「texファイルを更新・保存」
↓
(OMakeがコンパイル)
↓
「Preview.appが勝手に再読み込み」
という擬似リアルタイムプレビューの完成です。
それでは新しいTeX環境で素敵な執筆ライフを!
参考にさせていただいたページ
TeX Wiki, 「Vim-LaTeX」
http://oku.edu.mie-u.ac.jp/~okumura/texwiki/?Vim-LaTeX
Norbert Preining, 「TeX Live 2014のtlptexlive」
http://www.preining.info/blog/2014/05/tex-live-2014%E3%81%AEtlptexlive/
Tamotsu Thomas UEDA, 「日本語フォントのセットアップ」
http://www.fugenji.org/~thomas/texlive-guide/font_setup.html
hayamiz, 「OMake つかって LaTeX コンパイルしたら簡単すぎて身長が5cm伸びた」
http://d.hatena.ne.jp/hayamiz/20081208/1228727272
MacにF#をビルド&インストールする
MacでF# 3.1をビルドしたときのメモ。
0. 前提環境
1. 事前準備
(1) autoconf, automake, libtool
MacPortsやHomebrewあたりで、autoconf, automake, libtoolを用意しておきます。\ 今回使ったバージョンは以下のとおりです。
- autoconf @2.69_2 (active)
- automake @1.14.1_2 (active)
- libtool @2.4.2_3+universal (active)
(2) stow
自前でビルドしたパッケージを管理するためにstowを用意しておきます。 MacPortsの場合:
$ sudo port selfupdate $ sudo port install stow
(3) ディレクトリの準備
ソースコードを格納するディレクトリ(src)と、ビルドしたパッケージを格納するディレクトリ(stow)を作成します。
$ sudo mkdir -p /usr/local/{src, stow}
※ビルド時にいちいちsudoするのが面倒な場合はsrcディレクトリをchownしておいてください
2. Mono
(1) ビルド
F#を実行するための環境として、monoランタイムをビルドします。
$ cd /usr/local/src $ sudo git clone https://github.com/mono/mono $ cd mono $ sudo ./autogen.sh --prefix=/usr/local/stow/mono --enable-nls=no --disable-bcl-opt $ sudo make get-monolite-latest $ sudo make $ sudo make install
--disable-bcl-opt
は、BCL(基本クラスライブラリ)を最適化なしでコンパイルしてデバッグを有効にするものです。パフォーマンスが気になるなら外しておいたほうがよいでしょう。
またmake get-monolite-latest
をしておかないと、以下のようなエラーが出ます。
File `DoesNotExist' referenced in TOC but it doesn't exist.
(2) インストール(リンク)
前述の作業で/usr/local/stow/mono
にmonoランタイムがインストールされたので、stowを使ってこれを/usr/local/{bin,lib,share,...}
ディレクトリにリンクさせます。
$ cd /usr/local/stow $ sudo stow mono
/usr/local/bin
にパスが通っていれば、これでmonoランタイムが使えるようになります。
$ mono -V Mono JIT compiler version 3.4.1 (master/adcc774 2014年 5月30日 金曜日 23時19分09秒 JST) Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com TLS: normal SIGSEGV: altstack Notification: kqueue Architecture: amd64 Disabled: none Misc: softdebug LLVM: supported, not enabled. GC: sgen
3. F#
(1) ビルド
$ sudo git clone https://github.com/fsharp/fsharp $ sudo ./autogen.sh --prefix=/usr/local/stow/fsharp $ sudo make $ sudo make install
(2) インストール(リンク)
$ cd /usr/local/stow $ sudo stow fsharp
(3) ライブラリパスの設定
DYLD_FALLBACK_LIBRARY_PATHを.bashrcあたりに設定しておきます。
設定値はご自身の環境に合わせて変更してください。
(特にここでは、/usr/local/lib, /usr/libが必須になります)
$ export DYLD_FALLBACK_LIBRARY_PATH=${HOME}/lib:/usr/local/lib:/opt/local/lib:/lib:/usr/lib:${DYLD_FALLBACK_LIBRARY_PATH}$
ここでライブラリのパスが正しく設定されていないと、以下のようなエラーが出ます。
Failed to install ctrl-c handler - Ctrl-C handling will not be available. Error was: Exception has been thrown by the target of an invocation.
上記の場合、実行中のF#コードをインタラクティブから中断する事はできません。(止まらない計算を中断できなくなります)
使ってみる
インタラクティブを使う
Windowsではfsi
コマンドでF# Interactiveを立ち上げますが、Macではfsharpi
コマンドを使います。
fsharpi
はただのラッパーシェルで、実際はmono fsi.exe
を実行しています。
monoは、exe形式のMSILコードを実行時にコンパイルします。
$ fsharpi F# Interactive for F# 3.1 (Open Source Edition) Freely distributed under the Apache 2.0 Open Source License For help type #help;; > 1+1;; val it : int = 2 > printfn "Hello, World";; Hello, World val it : unit = ()
インタラクティブの終了は、Ctrl+ZかCtrl+Dです。
実行中のF#コードを中断したい場合は、Ctrl-Cを実行します。
> while true do printfn "Hello, F Sharp" done;; Hello, F Sharp Hello, F Sharp Hello, F Sharp Hello, F Sharp Hello, F Sharp .... (Ctrl + C を押す) - Interrupt
コンパイラを使う
適当なコードを作成します。 fact.fs:
let rec fact n = if n=0 then 1 else n * fact (n-1) [<EntryPoint>] let main (args:string[]) = printfn "%d" (fact (int args.[0])) 0
※上記ではint32の値で計算しているため、nの値が大きいと正しく計算されません。
F#のソースコードをコンパイルするときはfsharpc
コマンドを使います。
$ fsharpc fact.fs
すると、fact.exe
ファイルが作成されますが、exe形式のためmonoコマンドを経由して実行します。
$ mono fact.exe 5 120
おまけ. fsharp-vim
VimでF#のシンタックスハイライトをさせたかったので、NeoBundleでfsharp-vimを入れました。
NeoBundle 'kongo2002/fsharp-vim'