mirror of
https://github.com/TheRealOwenRees/pgn_to_tex.git
synced 2026-07-23 12:06:58 +00:00
79155255f6
* copy project root files * import previously created code and rename where needed * fix license and lint * main is now just a JS wrapper * minified main.cjs rather than copying to a newly named file
116 lines
4.1 KiB
OCaml
116 lines
4.1 KiB
OCaml
open Ast
|
|
open Latex_helpers
|
|
|
|
(* convert PGN headers to title tex *)
|
|
let tags_to_tex tags =
|
|
let get_tag_value key tags ~default =
|
|
match List.find_opt (fun t -> t.key = key) tags with
|
|
| Some t -> t.value
|
|
| None -> default
|
|
in
|
|
|
|
let white = get_tag_value "White" tags ~default:"" in
|
|
let black = get_tag_value "Black" tags ~default:"" in
|
|
let event = get_tag_value "Event" tags ~default:"" in
|
|
let date = get_tag_value "Date" tags ~default:"" in
|
|
let white_elo = get_tag_value "WhiteElo" tags ~default:"" in
|
|
let black_elo = get_tag_value "BlackElo" tags ~default:"" in
|
|
let site = get_tag_value "Site" tags ~default:"" in
|
|
let title = get_tag_value "Title" tags ~default:"" in
|
|
let subtitle = get_tag_value "Subtitle" tags ~default:"" in
|
|
let author = get_tag_value "Author" tags ~default:"" in
|
|
|
|
let title_tex = build_title_string event title subtitle in
|
|
let author_tex = build_author_string author white black white_elo black_elo in
|
|
|
|
title_tex ^ "\n" ^ author_tex ^ "\n"
|
|
^ build_date_site_string date site
|
|
^ "\\maketitle\n\\newchessgame"
|
|
|
|
let rec item_to_tex is_mainline ply ?(diagram_data = MoveMap.empty) = function
|
|
| Number n -> if is_mainline then "\\textbf{" ^ n ^ "}" else n
|
|
| Move m ->
|
|
if is_mainline then "\\textbf{" ^ escape_tex m ^ "}" else escape_tex m
|
|
| Comment c ->
|
|
if is_mainline then "\\newline " ^ escape_tex c ^ "\\par"
|
|
else escape_tex c
|
|
| Result r -> "\\textbf{" ^ r ^ "}"
|
|
| Variation v -> "( " ^ render_game false ~diagram_data v ^ " )"
|
|
| Nag g -> " " ^ Nag.nag_to_tex g ^ "{}"
|
|
| Clock c -> c
|
|
|
|
and render_game is_mainline ?(diagram_data = MoveMap.empty) ?(clock = false)
|
|
items =
|
|
let rec aux ply interrupted ?(white_time = "0:00") ?(black_time = "0:00") =
|
|
function
|
|
| [] -> ""
|
|
| Comment c :: Move m :: tail when is_mainline && ply mod 2 != 0 ->
|
|
let next_ply = ply + 1 in
|
|
let rendered_comment = "\\newline " ^ escape_tex c ^ "\\par" in
|
|
let rendered_move = "\\textbf{\\ldots{}" ^ escape_tex m ^ "}" in
|
|
let diag_str =
|
|
match get_diagram next_ply diagram_data with
|
|
| Some s -> s
|
|
| None -> ""
|
|
in
|
|
let has_diag = diag_str <> "" in
|
|
rendered_comment ^ " " ^ rendered_move ^ diag_str ^ " "
|
|
^ aux next_ply has_diag tail
|
|
| head :: tail -> (
|
|
match head with
|
|
| Clock c ->
|
|
if ply mod 2 = 0 then
|
|
aux ply interrupted ~white_time ~black_time:c tail
|
|
else aux ply interrupted ~white_time:c ~black_time tail
|
|
| _ ->
|
|
let is_move = match head with Move _ -> true | _ -> false in
|
|
|
|
let next_ply =
|
|
match head with Move _ when is_mainline -> ply + 1 | _ -> ply
|
|
in
|
|
|
|
let prefix =
|
|
if is_move && is_mainline && next_ply mod 2 == 0 && interrupted
|
|
then "\\ldots{}"
|
|
else ""
|
|
in
|
|
|
|
let rendered_head =
|
|
let raw_head =
|
|
item_to_tex is_mainline next_ply ~diagram_data head
|
|
in
|
|
if prefix <> "" && raw_head <> "" then
|
|
"\\textbf{" ^ prefix ^ "}" ^ raw_head
|
|
else raw_head
|
|
in
|
|
|
|
let diag_str =
|
|
if is_move && is_mainline then
|
|
get_diagram next_ply diagram_data ~clock ~white_time ~black_time
|
|
else None
|
|
in
|
|
|
|
let diag_output = match diag_str with Some s -> s | None -> "" in
|
|
let is_comment = match head with Comment _ -> true | _ -> false in
|
|
let next_interrupted = diag_output <> "" || is_comment in
|
|
let rest =
|
|
aux next_ply next_interrupted ~white_time ~black_time tail
|
|
in
|
|
|
|
if rendered_head = "" then rest
|
|
else
|
|
rendered_head ^ diag_output ^ if rest = "" then "" else " " ^ rest
|
|
)
|
|
in
|
|
String.trim (aux 0 false items)
|
|
|
|
let game_to_tex game ~diagram_data ~clock =
|
|
let header_tex = tags_to_tex game.tags in
|
|
let content_tex = render_game true ~diagram_data ~clock game.content in
|
|
|
|
let result_tex =
|
|
match game.result with Some r -> " \\textbf{" ^ r ^ "}" | None -> ""
|
|
in
|
|
|
|
header_tex ^ "\n" ^ content_tex ^ result_tex
|