2021年12月11日

SATySFiでのページスタイル

これはSATySFi advent calendar 2021の11日目の記事です.昨日はmonaqaさんでした.明日はTakashi Suwaさんの予定です.

LaTeXにはページスタイルという機能があります.ヘッダとフッタを出力するためのもので,文書中での変更などができます.こんな感じのものがSATySFiでもあればよいかなと思い,PageStyleパッケージを作ってみました.あわせて必要なのでページ番号を管理するPageNumberパッケージも作りました.どちらも簡素な作りのものです.主にクラスファイル作成時に使うことを想定しているもので,ちょっと楽にするというのもありますが,違うパッケージでも基盤として同じだと便利だろうというのが目的です.

インストール

いつも通りSatyrographosを使いましょう.

> opam install satysfi-pagestyle satysfi-pagenumber
> satyrographos install

pagenumberについて

先にページ番号管理について説明します.通常文書にはページ数が打たれますが,これは文書開始からのページ数とは限りません.例えば前付けが終わったときにページ数がリセットされるということはよくあります.以下,文書開始時から一つずつ増えているページ数を「真のページ数」,実際に出力されるページ数を「見かけのページ数」と呼びます.

実際に出力されるのは見かけのページ数です.これは整数値ですが,この出力形式も多様です.多くはアラビア数字でしょうが,ローマ数字かもしれません.この出力に合わせた文字列を「ページ数文字列」と呼ぶことにします.これは実際に出力される文字列のことですが,与えられた見かけのページ数を文字列に変換する関数(int -> string型)を「ページ数文字列」と呼ぶこともあります.

PageNumberパッケージは,この見かけのページ数とページ数文字列を管理します.現在の見かけのページ数をnに変更するset-page-number n\set-page-number n,およびページ数文字列をfuncに変更するset-page-number funcが提供されます.真のページ数から見かけのページ数とページ数文字列を得るにはget-page-numberおよびget-page-stringを使います.詳しくはマニュアルをご覧ください.

クラスファイル側の使い方

ページスタイルの定義はシンプルです.

type page-style = (|
  odd-header : context -> int -> int -> string -> block-boxes;
  even-header : context -> int -> int -> string -> block-boxes;
  odd-footer : context -> int -> int -> string -> block-boxes;
  even-footer : context -> int -> int -> string -> block-boxes;
|)

どれも同じですが,pagestyle#odd-header ctx page1 page2 strの形で呼び出され,出力するべきblock-boxesを返します.page1は真のページ数,page2は見かけのページ数,strはページ数文字列です.現在のページスタイルはheaderおよびfooterで取得できます.どちらも同様で,header istwoside pbinfoで呼び出します.istwosideはbool型で,ページ数の偶奇に応じてヘッダとフッタを変更するかを指定します.LaTeXドキュメントクラスによくあるtwosideオプションに似ています.pbinfopage-numberフィールドに真のページ数が入っているやつです.

以上のことから,典型的には次のように定義されたpagestylepage-breakの第三引数(またはpage-break-multicolumnの第六引数)に指定することになるでしょう.

let pagestyle pbinfo =
  let (xh,yh) = ... in % header の位置を計算
  let (xf,yf) = ... in % footer の位置を計算
  (|
    header-content = PageStyle.header true pbinfo;
    header-origin = (xh,yh);
    footer-content = PageStyle.footer true pbinfo;
    footer-origin = (xf,yf);
  |)

ページスタイルの指定

ページスタイルはset-page-style-inlineで指定します.引数はページスタイル一つです.これが返したinline-boxesが埋め込まれた場所でページスタイルが変更されます.ユーザ用命令\set-page-style(page-style)もあります.

ページスタイルは上で述べたような関数ですから,SATySFiになれていれば簡単に定義をすることができます.一方,もうちょっと簡単に定義するためにpagestyle-schemeという関数も用意されています.これはヘッダとフッタを「柱」と「ノンブル」という単位に分割して定義するものです.詳しくはマニュアルをご覧ください.なお,クラスファイルとしての作成には次のマークの理解が必要です.

マーク

ページスタイルは上で述べたような関数ですから,SATySFiになれていれば簡単に定義をすることができます.しかし,多くの場合には「ヘッダに現在の節の見出しを出力したい」ということになるでしょう.このための機構が「マーク」です.これは次のようなことを実現します.ページの適当な場所に「マーク」として節の見出しなどのデータを登録します.そして,SATySFiがページ分割を通じて文書を構築する際に,この登録したデータを参照することができます.この機能を使うことで,ヘッダに節の見出しを出力するということは次のように実現できます.

  1. +sectionにて与えられた見出しを「マーク」に登録.
  2. ページスタイルの各関数で,このマークを参照する.

この機能を使うには@require: pagestyle/markします.全ての関数はMarkモジュールに配置されています.

登録できるマークは一つではありません.複数のマークは整数値で管理されています.n番目のマークの登録はset-markを使いset-mark n contentにより行います.典型的には見出しタイプに整数値を割り当てておくことになるでしょう.let section-mark-index=0のようにしておくと便利かもしれません.これを使うと,+sectionは例えば次のような形の定義になります.

let-block ctx +section ?:label title inner =
  % 整数値section-mark-indexをどっかで定義しておく.
  let mark-b = Mark.set-mark section-mark-index title in
  .... % +sectionの処理
  let main-b = ... % +section本体のブロックボックス
  % きちんとMark.set-mark の戻り値を埋め込んでおく.
  mark-b ++ main-b

同一ページ内に複数のマークがあるということもありますので,マークを参照する際にはどのマークを取得するかを指定しなければなりません.Markモジュールでは,「ページ最初のマーク」と「ページ最後のマーク」を取得する命令が提供されています.(ほかのマークを取得する命令は用意されていません,よくある文書作成ではこの二つで十分と思います.)それぞれget-first-markget-last-markです.どちらも使い方は同様で,get-first-mark index pageとします.これはindex番目(マークは複数作ることができ,おのおののマークは整数値で管理されるのでした)のpageページの最初のマークを取得する命令です.ページスタイルを独自に作るにはこれらの関数を使うことになるでしょう.pagestyle-scheme内ではこれらの関数が使われています.

0 件のコメント:

コメントを投稿

コメントの追加にはサードパーティーCookieの許可が必要です