2020-04-16 18:47:35 +03:00
|
|
|
|
(* This file is part of the Catala compiler, a specification language for tax and social benefits
|
2021-05-27 19:56:47 +03:00
|
|
|
|
computation rules. Copyright (C) 2020 Inria, contributors: Denis Merigoux
|
|
|
|
|
<denis.merigoux@inria.fr>, Emile Rolley <emile.rolley@tuta.io>
|
2020-03-08 02:21:55 +03:00
|
|
|
|
|
2020-03-09 14:01:56 +03:00
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
|
|
|
|
|
in compliance with the License. You may obtain a copy of the License at
|
2020-03-08 02:21:55 +03:00
|
|
|
|
|
2020-03-09 14:01:56 +03:00
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
2020-03-08 02:21:55 +03:00
|
|
|
|
|
2020-03-09 14:01:56 +03:00
|
|
|
|
Unless required by applicable law or agreed to in writing, software distributed under the License
|
|
|
|
|
is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
|
|
|
|
|
or implied. See the License for the specific language governing permissions and limitations under
|
|
|
|
|
the License. *)
|
2020-03-08 02:21:55 +03:00
|
|
|
|
|
2020-03-09 14:01:56 +03:00
|
|
|
|
(** This modules weaves the source code and the legislative text together into a document that law
|
|
|
|
|
professionals can understand. *)
|
2020-03-08 02:21:55 +03:00
|
|
|
|
|
2021-01-21 23:33:04 +03:00
|
|
|
|
open Utils
|
2021-05-26 22:39:40 +03:00
|
|
|
|
open Literate_common
|
2020-11-23 11:22:47 +03:00
|
|
|
|
module A = Surface.Ast
|
2020-04-11 19:36:00 +03:00
|
|
|
|
module R = Re.Pcre
|
2020-04-20 09:13:57 +03:00
|
|
|
|
module C = Cli
|
2020-04-11 19:36:00 +03:00
|
|
|
|
|
2020-12-14 20:09:38 +03:00
|
|
|
|
(** {1 Helpers} *)
|
|
|
|
|
|
|
|
|
|
(** Espaces various LaTeX-sensitive characters *)
|
2020-04-11 19:36:00 +03:00
|
|
|
|
let pre_latexify (s : string) =
|
|
|
|
|
let percent = R.regexp "%" in
|
2020-04-16 10:07:21 +03:00
|
|
|
|
let s = R.substitute ~rex:percent ~subst:(fun _ -> "\\%") s in
|
2020-05-18 10:47:13 +03:00
|
|
|
|
let dollar = R.regexp "\\$" in
|
|
|
|
|
let s = R.substitute ~rex:dollar ~subst:(fun _ -> "\\$") s in
|
2020-04-16 10:07:21 +03:00
|
|
|
|
let premier = R.regexp "1er" in
|
|
|
|
|
let s = R.substitute ~rex:premier ~subst:(fun _ -> "1\\textsuperscript{er}") s in
|
2020-04-17 13:29:30 +03:00
|
|
|
|
let underscore = R.regexp "\\_" in
|
|
|
|
|
let s = R.substitute ~rex:underscore ~subst:(fun _ -> "\\_") s in
|
2020-04-16 10:07:21 +03:00
|
|
|
|
s
|
2020-03-08 02:21:55 +03:00
|
|
|
|
|
2020-12-14 20:09:38 +03:00
|
|
|
|
(** Usage: [wrap_latex source_files custom_pygments language fmt wrapped]
|
|
|
|
|
|
|
|
|
|
Prints an LaTeX complete documùent structure around the [wrapped] content. *)
|
2021-03-02 20:27:39 +03:00
|
|
|
|
let wrap_latex (source_files : string list) (language : C.backend_lang) (fmt : Format.formatter)
|
|
|
|
|
(wrapped : Format.formatter -> unit) =
|
2020-10-04 02:25:37 +03:00
|
|
|
|
Format.fprintf fmt
|
2020-04-19 20:56:27 +03:00
|
|
|
|
"\\documentclass[11pt, a4paper]{article}\n\n\
|
2020-04-17 13:29:30 +03:00
|
|
|
|
\\usepackage[T1]{fontenc}\n\
|
|
|
|
|
\\usepackage[utf8]{inputenc}\n\
|
2021-05-11 21:24:34 +03:00
|
|
|
|
\\usepackage{amssymb}\n\
|
2020-04-19 20:56:27 +03:00
|
|
|
|
\\usepackage[%s]{babel}\n\
|
2020-04-17 13:29:30 +03:00
|
|
|
|
\\usepackage{lmodern}\n\
|
|
|
|
|
\\usepackage{minted}\n\
|
2020-05-15 16:28:38 +03:00
|
|
|
|
\\usepackage{newunicodechar}\n\
|
2020-04-17 13:29:30 +03:00
|
|
|
|
\\usepackage{textcomp}\n\
|
|
|
|
|
\\usepackage[hidelinks]{hyperref}\n\
|
|
|
|
|
\\usepackage[dvipsnames]{xcolor}\n\
|
|
|
|
|
\\usepackage{fullpage}\n\
|
|
|
|
|
\\usepackage[many]{tcolorbox}\n\n\
|
2020-05-15 16:28:38 +03:00
|
|
|
|
\\newunicodechar{÷}{$\\div$}\n\
|
|
|
|
|
\\newunicodechar{×}{$\\times$}\n\
|
|
|
|
|
\\newunicodechar{≤}{$\\leqslant$}\n\
|
|
|
|
|
\\newunicodechar{≥}{$\\geqslant$}\n\
|
|
|
|
|
\\newunicodechar{→}{$\\rightarrow$}\n\
|
|
|
|
|
\\newunicodechar{≠}{$\\neq$}\n\n\
|
2021-03-10 17:58:01 +03:00
|
|
|
|
\\newcommand*\\FancyVerbStartString{```catala}\n\
|
|
|
|
|
\\newcommand*\\FancyVerbStopString{```}\n\n\
|
2020-04-17 13:29:30 +03:00
|
|
|
|
\\fvset{\n\
|
|
|
|
|
numbers=left,\n\
|
2020-04-19 20:04:11 +03:00
|
|
|
|
frame=lines,\n\
|
2020-04-19 20:56:27 +03:00
|
|
|
|
framesep=3mm,\n\
|
2020-04-19 20:04:11 +03:00
|
|
|
|
rulecolor=\\color{gray!70},\n\
|
2020-04-17 13:29:30 +03:00
|
|
|
|
firstnumber=last,\n\
|
|
|
|
|
codes={\\catcode`\\$=3\\catcode`\\^=7}\n\
|
|
|
|
|
}\n\n\
|
|
|
|
|
\\title{\n\
|
2020-04-19 20:56:27 +03:00
|
|
|
|
%s\n\
|
2020-04-17 13:29:30 +03:00
|
|
|
|
}\n\
|
|
|
|
|
\\author{\n\
|
2020-04-19 20:56:27 +03:00
|
|
|
|
%s Catala version %s\n\
|
2020-04-17 13:29:30 +03:00
|
|
|
|
}\n\
|
|
|
|
|
\\begin{document}\n\
|
|
|
|
|
\\maketitle\n\n\
|
2020-04-19 20:56:27 +03:00
|
|
|
|
%s : \n\
|
2020-04-17 13:29:30 +03:00
|
|
|
|
\\begin{itemize}%s\\end{itemize}\n\n\
|
2020-10-04 02:25:37 +03:00
|
|
|
|
\\[\\star\\star\\star\\]\\\\\n"
|
2021-05-26 22:18:18 +03:00
|
|
|
|
(match language with Fr -> "french" | En -> "english" | Pl -> "polish")
|
2021-05-26 22:39:40 +03:00
|
|
|
|
(literal_title language) (literal_generated_by language) Utils.Cli.version
|
|
|
|
|
(literal_source_files language)
|
2020-04-17 13:29:30 +03:00
|
|
|
|
(String.concat ","
|
2020-04-17 16:28:34 +03:00
|
|
|
|
(List.map
|
|
|
|
|
(fun filename ->
|
|
|
|
|
let mtime = (Unix.stat filename).Unix.st_mtime in
|
|
|
|
|
let ltime = Unix.localtime mtime in
|
|
|
|
|
let ftime =
|
2020-05-17 20:20:03 +03:00
|
|
|
|
Printf.sprintf "%d-%02d-%02d, %d:%02d" (1900 + ltime.Unix.tm_year)
|
|
|
|
|
(ltime.Unix.tm_mon + 1) ltime.Unix.tm_mday ltime.Unix.tm_hour ltime.Unix.tm_min
|
2020-04-17 16:28:34 +03:00
|
|
|
|
in
|
2020-04-19 20:56:27 +03:00
|
|
|
|
Printf.sprintf "\\item\\texttt{%s}, %s %s"
|
2020-04-19 19:39:16 +03:00
|
|
|
|
(pre_latexify (Filename.basename filename))
|
2021-05-26 22:39:40 +03:00
|
|
|
|
(literal_last_modification language)
|
2020-04-19 19:39:16 +03:00
|
|
|
|
ftime)
|
2020-10-04 02:25:37 +03:00
|
|
|
|
source_files));
|
|
|
|
|
wrapped fmt;
|
|
|
|
|
Format.fprintf fmt "\n\n\\end{document}"
|
2020-04-17 13:29:30 +03:00
|
|
|
|
|
2020-12-14 20:09:38 +03:00
|
|
|
|
(** Replaces math operators by their nice unicode counterparts *)
|
2020-05-15 12:27:38 +03:00
|
|
|
|
let math_syms_replace (c : string) : string =
|
2020-05-15 16:28:38 +03:00
|
|
|
|
let date = "\\d\\d/\\d\\d/\\d\\d\\d\\d" in
|
2020-05-17 16:23:48 +03:00
|
|
|
|
let syms = R.regexp (date ^ "|!=|<=|>=|--|->|\\*|/") in
|
2020-05-15 12:27:38 +03:00
|
|
|
|
let syms2cmd = function
|
2020-05-15 16:28:38 +03:00
|
|
|
|
| "!=" -> "≠"
|
|
|
|
|
| "<=" -> "≤"
|
|
|
|
|
| ">=" -> "≥"
|
|
|
|
|
| "--" -> "—"
|
|
|
|
|
| "->" -> "→"
|
|
|
|
|
| "*" -> "×"
|
|
|
|
|
| "/" -> "÷"
|
2020-05-15 12:27:38 +03:00
|
|
|
|
| s -> s
|
|
|
|
|
in
|
2020-05-15 16:28:38 +03:00
|
|
|
|
R.substitute ~rex:syms ~subst:syms2cmd c
|
2020-05-15 12:27:38 +03:00
|
|
|
|
|
2020-12-14 20:09:38 +03:00
|
|
|
|
(** {1 Weaving} *)
|
|
|
|
|
|
2020-10-04 02:25:37 +03:00
|
|
|
|
let rec law_structure_to_latex (language : C.backend_lang) (fmt : Format.formatter)
|
|
|
|
|
(i : A.law_structure) : unit =
|
|
|
|
|
match i with
|
|
|
|
|
| A.LawHeading (heading, children) ->
|
2021-05-15 02:16:08 +03:00
|
|
|
|
Format.fprintf fmt "\\%s*{%s}\n\n"
|
2021-03-23 12:59:43 +03:00
|
|
|
|
(match heading.law_heading_precedence with
|
2021-05-15 02:16:08 +03:00
|
|
|
|
| 0 -> "chapter"
|
|
|
|
|
| 1 -> "section"
|
|
|
|
|
| 2 -> "subsection"
|
|
|
|
|
| 4 -> "subsubsection"
|
|
|
|
|
| 5 -> "paragraph"
|
|
|
|
|
| _ -> "subparagraph")
|
|
|
|
|
(pre_latexify (Pos.unmark heading.law_heading_name));
|
2020-10-04 02:25:37 +03:00
|
|
|
|
Format.pp_print_list
|
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt "\n\n")
|
|
|
|
|
(law_structure_to_latex language) fmt children
|
2020-12-11 23:17:01 +03:00
|
|
|
|
| A.LawInclude (A.PdfFile ((file, _), page)) ->
|
|
|
|
|
let label = file ^ match page with None -> "" | Some p -> Format.sprintf "_page_%d," p in
|
|
|
|
|
Format.fprintf fmt
|
|
|
|
|
"\\begin{center}\\textit{Annexe incluse, retranscrite page \\pageref{%s}}\\end{center} \
|
|
|
|
|
\\begin{figure}[p]\\begin{center}\\includegraphics[%swidth=\\textwidth]{%s}\\label{%s}\\end{center}\\end{figure}"
|
|
|
|
|
label
|
|
|
|
|
(match page with None -> "" | Some p -> Format.sprintf "page=%d," p)
|
|
|
|
|
file label
|
|
|
|
|
| A.LawInclude (A.CatalaFile _ | A.LegislativeText _) -> ()
|
2021-05-15 02:16:08 +03:00
|
|
|
|
| A.LawText t -> Format.fprintf fmt "%s" (pre_latexify t)
|
|
|
|
|
| A.CodeBlock (_, c, false) ->
|
|
|
|
|
Format.fprintf fmt
|
|
|
|
|
"\\begin{minted}[label={\\hspace*{\\fill}\\texttt{%s}},firstnumber=%d]{%s}\n\
|
|
|
|
|
```catala%s```\n\
|
|
|
|
|
\\end{minted}"
|
|
|
|
|
(pre_latexify (Filename.basename (Pos.get_file (Pos.get_position c))))
|
|
|
|
|
(Pos.get_start_line (Pos.get_position c) - 1)
|
2021-05-26 22:39:40 +03:00
|
|
|
|
(get_language_extension language)
|
2021-05-15 02:16:08 +03:00
|
|
|
|
(math_syms_replace (Pos.unmark c))
|
|
|
|
|
| A.CodeBlock (_, c, true) ->
|
2021-05-10 00:06:59 +03:00
|
|
|
|
let metadata_title =
|
2021-05-26 22:18:18 +03:00
|
|
|
|
match language with Fr -> "Métadonnées" | En -> "Metadata" | Pl -> "Metadane"
|
2021-05-10 00:06:59 +03:00
|
|
|
|
in
|
2020-10-04 02:25:37 +03:00
|
|
|
|
Format.fprintf fmt
|
2020-04-10 13:02:05 +03:00
|
|
|
|
"\\begin{tcolorbox}[colframe=OliveGreen, breakable, \
|
2020-05-17 19:51:00 +03:00
|
|
|
|
title=\\textcolor{black}{\\texttt{%s}},title after \
|
|
|
|
|
break=\\textcolor{black}{\\texttt{%s}},before skip=1em, after skip=1em]\n\
|
2020-05-15 16:28:38 +03:00
|
|
|
|
\\begin{minted}[numbersep=9mm, firstnumber=%d, label={\\hspace*{\\fill}\\texttt{%s}}]{%s}\n\
|
2021-03-10 17:58:01 +03:00
|
|
|
|
```catala%s```\n\
|
2020-04-26 21:48:51 +03:00
|
|
|
|
\\end{minted}\n\
|
2020-04-10 13:02:05 +03:00
|
|
|
|
\\end{tcolorbox}"
|
2020-05-17 19:51:00 +03:00
|
|
|
|
metadata_title metadata_title
|
2020-12-17 22:09:33 +03:00
|
|
|
|
(Pos.get_start_line (Pos.get_position c) - 1)
|
2020-04-20 10:02:08 +03:00
|
|
|
|
(pre_latexify (Filename.basename (Pos.get_file (Pos.get_position c))))
|
2021-05-26 22:39:40 +03:00
|
|
|
|
(get_language_extension language)
|
2020-05-15 12:27:38 +03:00
|
|
|
|
(math_syms_replace (Pos.unmark c))
|
2020-03-08 02:21:55 +03:00
|
|
|
|
|
2020-12-14 20:09:38 +03:00
|
|
|
|
(** {1 API} *)
|
|
|
|
|
|
2020-10-04 02:25:37 +03:00
|
|
|
|
let ast_to_latex (language : C.backend_lang) (fmt : Format.formatter) (program : A.program) : unit =
|
|
|
|
|
Format.pp_print_list
|
|
|
|
|
~pp_sep:(fun fmt () -> Format.fprintf fmt "\n\n")
|
2021-05-15 02:16:08 +03:00
|
|
|
|
(law_structure_to_latex language) fmt program.program_items
|