Skip to content

Instantly share code, notes, and snippets.

@abenori
Created August 18, 2019 13:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abenori/b3d09bb02c90dfaa428554714376a602 to your computer and use it in GitHub Desktop.
Save abenori/b3d09bb02c90dfaa428554714376a602 to your computer and use it in GitHub Desktop.
RIMS用SATySFiファイル
% -*- coding: utf-8 -*-
@require: pervasives
@require: gr
@require: list
@require: math
@require: color
@require: option
@require: annot
type config = (|
show-pages : bool;
twoside : bool;
top-space : length;
bottom-space : length;
gutter : length;
fore-edge : length;
paper-size : page;
header-sep : length;
header-height : length;
|)
module RIMS : sig
val default-config : config
val document : 'a -> config ?-> block-text -> document
constraint 'a :: (|
title : inline-text;
author : inline-text;
show-toc : bool;
show-title : bool;
|)
val font-latin-italic : string * float * float
direct \ref : [string] inline-cmd
direct \ref-page : [string] inline-cmd
direct \figure : [inline-text; block-text] inline-cmd
direct +p : [inline-text] block-cmd
direct +pn : [inline-text] block-cmd
direct +abstract : [inline-text] block-cmd
direct +section : [string?; string?; inline-text; block-text] block-cmd
direct +subsection : [string?; string?; inline-text; block-text] block-cmd
direct \emph : [inline-text] inline-cmd
direct \textbf : [inline-text] inline-cmd
direct +definition : [inline-text?; string?; inline-text] block-cmd
direct +theorem : [inline-text?; string?; inline-text] block-cmd
direct +assumption : [inline-text?; string?; inline-text] block-cmd
direct +corollary : [inline-text?; string?; inline-text] block-cmd
direct +lemma : [inline-text?; string?; inline-text] block-cmd
direct +proposition : [inline-text?; string?; inline-text] block-cmd
direct +proof : [inline-text?; inline-text] block-cmd
end = struct
type toc-element =
| TOCElementSection of string * inline-text
| TOCElementSubsection of string * inline-text
let generate-fresh-label =
let-mutable count <- 0 in
(fun () -> (
let () = count <- !count + 1 in
`generated:` ^ (arabic (!count))
))
let no-pads = (0pt, 0pt, 0pt, 0pt)
let-inline \ref key =
let opt = get-cross-reference (key ^ `:num`) in
match opt with
| None -> {?}
| Some(s) -> embed-string s
let-inline \ref-page key =
let opt = get-cross-reference (key ^ `:page`) in
match opt with
| None -> {?}
| Some(s) -> embed-string s
let font-size-normal = 10.5pt
let font-size-title = 16pt
let font-size-author = font-size-normal
let font-size-section = font-size-normal
let font-size-subsection = font-size-normal
let font-size-header = font-size-normal *' 0.9
let section-top-margin = 20pt
let section-bottom-margin = 12pt
let font-ratio-latin = 1.
let font-ratio-cjk = 0.92
let baselineskip = (font-size-normal *' font-ratio-cjk) *' 1.7
let font-latin-roman = (`lmroman` , font-ratio-latin, 0.)
let font-latin-italic = (`lmroman-it`, font-ratio-latin, 0.)
let font-latin-sans = (`lmroman-b` , font-ratio-latin, 0.)
let font-cjk-mincho = (`ipaexm` , font-ratio-cjk , 0.)
let font-cjk-gothic = (`ipaexg` , font-ratio-cjk , 0.)
let set-cjk-font font ctx =
ctx |> set-font HanIdeographic font
|> set-font Kana font
let get-standard-context wid =
get-initial-context wid (command \math)
|> set-dominant-wide-script Kana
|> set-language Kana Japanese
|> set-language HanIdeographic Japanese
|> set-dominant-narrow-script Latin
|> set-language Latin English
|> set-font Kana font-cjk-mincho
|> set-font HanIdeographic font-cjk-mincho
|> set-font Latin font-latin-roman
|> set-math-font `lmodern`
|> set-hyphen-penalty 100
let-mutable ref-float-boxes <- []
let height-of-float-boxes pageno =
% let () = display-message `get height` in
(!ref-float-boxes) |> List.fold-left (fun h (pn, bb) -> (
if pn < pageno then h +' (get-natural-length bb) else h
)) 0pt
let-mutable ref-figure <- 0
let-inline ctx \figure caption inner =
let () = ref-figure <- !ref-figure + 1 in
let s-num = embed-string (arabic (!ref-figure)) in
let bb-inner =
let d (_, _) _ _ _ = [] in
block-frame-breakable ctx (2pt, 2pt, 2pt, 2pt) (d, d, d, d) (fun ctx -> (
read-block ctx inner
+++ line-break true true ctx (inline-fil ++ read-inline ctx {図#s-num; #caption;} ++ inline-fil)
))
in
hook-page-break (fun pbinfo _ -> (
% let () = display-message (`register` ^ (arabic pbinfo#page-number)) in
ref-float-boxes <- (pbinfo#page-number, bb-inner) :: !ref-float-boxes
))
let-block ctx +make-title it-title it-author =
let ctx-title =
ctx |> set-font-size font-size-title
|> set-font Latin font-latin-roman
in
let ctx-author =
ctx |> set-font-size font-size-author
|> set-font Latin font-latin-roman
in
let ib-title = read-inline ctx-title it-title in
let ib-author = read-inline ctx-author it-author in
(line-break false false ctx-title (inline-fil ++ ib-title ++ inline-fil)) +++
(block-skip (font-size-normal *' 0.5)) +++
(line-break false false ctx-author (inline-fil ++ ib-author ++ inline-fil)) +++
(block-skip font-size-normal)
let make-section-title ctx =
ctx |> set-font-size font-size-section
|> set-font Latin font-latin-sans
|> set-cjk-font font-cjk-gothic
let make-subsection-title ctx =
ctx |> set-font-size font-size-subsection
|> set-font Latin font-latin-sans
|> set-cjk-font font-cjk-gothic
let-mutable toc-acc-ref <- []
let-mutable outline-ref <- []
let get-cross-reference-number label =
match get-cross-reference (label ^ `:num`) with
| None -> `?`
| Some(s) -> s
let get-cross-reference-page label =
match get-cross-reference (label ^ `:page`) with
| None -> `?`
| Some(s) -> s
let default-config =
(|
show-pages = true;
twoside = false;
top-space = 3cm;
bottom-space = 3cm;
gutter = 2.5cm;
fore-edge = 2.5cm;
paper-size = A4Paper;
header-sep = font-size-normal;
header-height = font-size-normal;
|)
let document record ?:configopt inner =
% -- mandatory designations --
let title = record#title in
let author = record#author in
% -- optional designations --
let config = Option.from default-config configopt in
% 基本版面
let paper-size = config#paper-size in
let (paper-width,paper-height) = match paper-size with
| A0Paper -> (841mm,1189mm)
| A1Paper -> (594mm,841mm)
| A2Paper -> (420mm,594mm)
| A3Paper -> (297mm,420mm)
| A4Paper -> (210mm,297mm)
| A5Paper -> (148mm,210mm)
| USLegal -> (8.5inch,14inch)
| USLetter -> (8.5inch,11inch)
| UserDefinedPaper(w,h) -> (w,h)
in
let text-length = paper-width -' (config#gutter +' config#fore-edge) in
let text-height = paper-height -' (config#top-space +' config#bottom-space) in
let header-length = text-length in
let get-x-origin pagenum =
if config#twoside && (pagenum mod 2 == 0) then
config#fore-edge
else
config#gutter
in
let pagecontf pbinfo =
let hgtfb = height-of-float-boxes pbinfo#page-number in
let v = config#top-space in
let h = get-x-origin(pbinfo#page-number) in
% let () = display-message (`hgtfb = ` ^ show-float(hgtfb /' 1pt)) in
(|
text-origin = (h, v +' hgtfb);
text-height = text-height -' hgtfb
|)
in
% -- constants
let thickness = 0.5pt in
let linegap = baselineskip -' (font-size-normal *' font-ratio-cjk) in
let ctx-doc = (get-standard-context text-length)
|> set-font-size font-size-normal
|> set-leading baselineskip
|> set-paragraph-margin linegap linegap
|> set-min-gap-of-lines 1pt
in
% -- title --
let bb-title =
if record#show-title then
read-block ctx-doc '<+make-title(title)(author);>
else
block-nil
in
% -- main --
let bb-main = read-block ctx-doc inner in
% -- table of contents --
let bb-toc =
if not record#show-toc then
block-nil
else
let bb-toc-title =
line-break true false ctx-doc (read-inline (make-section-title ctx-doc) {目次} ++ inline-fil)
in
let bb-toc-main =
(!toc-acc-ref) |> List.reverse |> List.fold-left (fun bbacc tocelem -> (
match tocelem with
| TOCElementSection(label, title) ->
let it-num = embed-string (get-cross-reference-number label) in
let it-page = embed-string (get-cross-reference-page label) in
bbacc +++ line-break true true ctx-doc
(inline-frame-breakable no-pads (Annot.link-to-location-frame label None)
(read-inline ctx-doc {#it-num;. #title;} ++ inline-fil ++ read-inline ctx-doc it-page))
| TOCElementSubsection(label, title) ->
let it-num = embed-string (get-cross-reference-number label) in
let it-page = embed-string (get-cross-reference-page label) in
bbacc +++ line-break true true ctx-doc
(inline-skip 20pt ++ (inline-frame-breakable no-pads
(Annot.link-to-location-frame label None)
(read-inline ctx-doc {#it-num;. #title;} ++ inline-fil ++ read-inline ctx-doc it-page)))
)) block-nil
in
bb-toc-title +++ bb-toc-main
in
% -- page settings --
let pagepartsf pbinfo =
let pageno = pbinfo#page-number in
let header =
let ctx =
get-standard-context header-length
|> set-paragraph-margin 0pt 0pt
|> set-font-size font-size-header
in
let ib-text =
if pageno == 1 then
inline-fil
else
(inline-fil ++ read-inline ctx title ++ inline-fil)
in
% let () = display-message `insert` in
let (bb-float-boxes, acc) =
(!ref-float-boxes) |> List.fold-left (fun (bbacc, acc) elem -> (
let (pn, bb) = elem in
if pn < pageno then
let bbs =
line-break true true (ctx |> set-paragraph-margin 0pt 12pt)
(inline-fil ++ embed-block-top ctx text-length (fun _ -> bb) ++ inline-fil)
% 'ctx' is a dummy context
in
(bbacc +++ bbs, acc)
else
(bbacc, elem :: acc)
)) (block-nil, [])
in
let () = ref-float-boxes <- acc in
line-break true true ctx ib-text
+++ bb-float-boxes
in
let footer =
if config#show-pages then
let ctx = get-standard-context header-length
|> set-font-size font-size-header
in
let it-pageno = embed-string (arabic pbinfo#page-number) in
line-break true true ctx
(inline-fil ++ (read-inline ctx {#it-pageno;}) ++ inline-fil)
else
block-nil
in
let xorigin = get-x-origin(pbinfo#page-number) in
(|
header-origin = (xorigin,config#top-space -' config#header-sep -' config#header-height);
header-content = header;
footer-origin = (xorigin,paper-height -' config#bottom-space +' config#header-sep +' config#header-height -' baselineskip +' font-size-normal);
footer-content = footer;
|)
in
let doc = page-break paper-size pagecontf pagepartsf (bb-title +++ bb-toc +++ bb-main) in
let () = register-outline (List.reverse !outline-ref) in
doc
let-mutable needs-indentation-ref <- true
let-mutable num-section <- 0
let-mutable num-subsection <- 0
let quad-indent ctx =
inline-skip (get-font-size ctx)
let-block ctx +p inner =
let needs-indentation =
if !needs-indentation-ref then true else
let () = needs-indentation-ref <- true in
false
in
let ib-inner = read-inline ctx inner in
let br-parag =
if needs-indentation then
(quad-indent ctx) ++ ib-inner ++ inline-fil
else
ib-inner ++ inline-fil
in
form-paragraph ctx br-parag
let-block ctx +pn inner =
let () = needs-indentation-ref <- true in
let ib-inner = read-inline ctx inner in
form-paragraph ctx (ib-inner ++ inline-fil)
let section-scheme ctx label title outline-title-opt inner =
let ctx-title = make-section-title ctx in
let () = num-section <- !num-section + 1 in
let () = num-subsection <- 0 in
let () = needs-indentation-ref <- true in
let s-num = arabic (!num-section) in
let () = register-cross-reference (label ^ `:num`) s-num in
let () = toc-acc-ref <- (TOCElementSection(label, title)) :: !toc-acc-ref in
let ib-num =
read-inline ctx-title (embed-string (s-num))
++ hook-page-break (fun pbinfo _ -> register-cross-reference (label ^ `:page`) (arabic pbinfo#page-number))
in
let ib-title = read-inline ctx-title title in
let outline-title = Option.from (extract-string ib-title) outline-title-opt in
let () = outline-ref <- (0, s-num ^ `. `# ^ outline-title, label, false) :: !outline-ref in
let bb-title =
block-frame-breakable ctx no-pads (Annot.register-location-frame label) (fun ctx -> (
(line-break true false (ctx |> set-paragraph-margin section-top-margin section-bottom-margin)
(ib-num ++ (inline-skip font-size-normal) ++ ib-title ++ (inline-fil)))))
in
let bb-inner = read-block ctx inner in
bb-title +++ bb-inner
let subsection-scheme ctx label title outline-title-opt inner =
let () = num-subsection <- !num-subsection + 1 in
let () = needs-indentation-ref <- false in
let s-num = arabic (!num-section) ^ `.` ^ arabic (!num-subsection) in
let () = register-cross-reference (label ^ `:num`) s-num in
let () = toc-acc-ref <- (TOCElementSubsection(label, title)) :: !toc-acc-ref in
let ctx-title = make-subsection-title ctx in
let ib-num =
read-inline ctx-title (embed-string (s-num ^ `.`))
++ hook-page-break (fun pbinfo _ -> register-cross-reference (label ^ `:page`) (arabic pbinfo#page-number))
in
let ib-title = read-inline ctx-title title in
let outline-title = Option.from (extract-string ib-title) outline-title-opt in
let () = outline-ref <- (1, s-num ^ `. `# ^ outline-title, label, false) :: !outline-ref in
let bb-title =
line-break true false (ctx |> set-paragraph-margin section-top-margin section-bottom-margin)
(inline-frame-breakable no-pads (Annot.register-location-frame label)
(ib-num ++ (inline-skip 10pt) ++ ib-title ++ (inline-fil)))
in
let bb-inner = read-block ctx inner in
bb-title +++ bb-inner
let-block ctx +section ?:labelopt ?:outline-title-opt title inner =
let label =
match labelopt with
| None -> generate-fresh-label ()
| Some(label) -> label
in
section-scheme ctx label title outline-title-opt inner
let-block ctx +subsection ?:labelopt ?:outline-title-opt title inner =
let label =
match labelopt with
| None -> generate-fresh-label ()
| Some(label) -> label
in
subsection-scheme ctx label title outline-title-opt inner
let-inline ctx \emph inner =
let ctx-emph =
ctx |> set-font Latin font-latin-italic
|> set-cjk-font font-cjk-gothic
in
read-inline ctx-emph inner
let-inline ctx \textbf inner =
let ctx-textbf =
ctx |> set-font HanIdeographic font-cjk-gothic
|> set-font Kana font-cjk-gothic
|> set-font Latin font-latin-sans
in
read-inline ctx-textbf inner
let theorem-beforeafter-space = baselineskip *' 0.5
let-mutable definition-counter <- 0
let theorem-protytype theorem-name counter ctx ?:title ?:label inner =
let font-size = get-font-size ctx in
let () = counter <- !counter + 1 in
let subtitle = match title with
| None -> inline-nil
| Some(s) -> (read-inline ctx (embed-string(`(`))) ++ (read-inline ctx s) ++ (read-inline ctx (embed-string(`)`)))
in
let () = match label with
| None -> ()
| Some(s) -> register-cross-reference (s ^ `:num`) (arabic !counter)
in
let subtitle-text = embed-string(theorem-name ^ (arabic !counter)) in
let ctx-gothic =
ctx |> set-font HanIdeographic font-cjk-gothic
|> set-font Kana font-cjk-gothic
|> set-font Latin font-latin-sans
in
let subtitle-box = (read-inline ctx-gothic {#subtitle-text;}) ++ subtitle ++ inline-skip (font-size) in
let inner-box = read-inline ctx inner in
let margin = theorem-beforeafter-space +' baselineskip -' font-size-normal in
let theorem-ctx = ctx
|> set-paragraph-margin margin margin
in
line-break true true theorem-ctx (subtitle-box ++ inner-box ++ inline-fil)
let-block ctx +definition = theorem-protytype `定義` definition-counter ctx
let-block ctx +theorem = theorem-protytype `定理` definition-counter ctx
let-block ctx +lemma = theorem-protytype `補題` definition-counter ctx
let-block ctx +assumption = theorem-protytype `仮定` definition-counter ctx
let-block ctx +corollary = theorem-protytype `系` definition-counter ctx
let-block ctx +proposition = theorem-protytype `命題` definition-counter ctx
let qedsymbol ctx =
let font-size = get-font-size ctx in
let w = font-size *' 0.5 in
let d = font-size *'0.12 in
let h = font-size *'0.88 in
let thickness = 0.5pt in
let color = Color.black in
inline-graphics w h d (fun (x,y) ->
[
stroke thickness color (Gr.rectangle (x,y -' d) (x +' w,y +' h));
]
)
let-block ctx +proof ?:title inner =
let font-size = get-font-size ctx in
let prooftitle = match title with
| None -> {証明}
| Some(s) -> s
in
let ctx-gothic =
ctx |> set-font HanIdeographic font-cjk-gothic
|> set-font Kana font-cjk-gothic
|> set-font Latin font-latin-sans
in
let ib-inner = (read-inline ctx-gothic {#prooftitle;}) ++ (inline-skip font-size) ++ (read-inline ctx inner) ++ inline-fil ++ (qedsymbol ctx) in
let margin = theorem-beforeafter-space +' baselineskip -' font-size-normal in
let theorem-ctx = ctx
|> set-paragraph-margin margin margin
in
line-break true true theorem-ctx ib-inner
let-block ctx +abstract inner =
let ctx-gothic =
ctx |> set-font HanIdeographic font-cjk-gothic
|> set-font Kana font-cjk-gothic
|> set-font Latin font-latin-sans
in
let indent = inline-skip (get-font-size ctx) in
(line-break true false ctx (inline-fil ++ (read-inline ctx-gothic {概要}) ++ inline-fil)) +++
(line-break false true ctx (indent ++ (read-inline ctx inner) ++ inline-fil)) +++
(block-skip 10pt)
end
let document = RIMS.document
% ad-hoc
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment