From abc5a00c2fb36622f25d92781fa3b91a598dd8f4 Mon Sep 17 00:00:00 2001 From: Louis Gesbert Date: Tue, 14 Mar 2023 16:57:14 +0100 Subject: [PATCH] Compile LaTeX code using minted without the Python venv This is a hack, but not a dirty one: a new command `catala pygmentize` is added, which is just a wrapper around `pygmentize` that calls it with the proper lexers defined. The point is that this needs no installation, just a stock `pygmentize` installation and the `catala` binary. --- INSTALL.md | 7 ++-- compiler/catala_utils/cli.ml | 4 ++ compiler/driver.ml | 4 ++ compiler/literate/literate_common.ml | 21 ++++++----- compiler/literate/literate_common.mli | 4 ++ compiler/literate/pygmentize.ml | 54 +++++++++++++++++++++++++++ compiler/literate/pygmentize.mli | 19 ++++++++++ doc/syntax/syntax_en.tex | 2 + doc/syntax/syntax_fr.tex | 2 + 9 files changed, 104 insertions(+), 13 deletions(-) create mode 100644 compiler/literate/pygmentize.ml create mode 100644 compiler/literate/pygmentize.mli diff --git a/INSTALL.md b/INSTALL.md index ec25ac4a..e10ff1a3 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -72,11 +72,10 @@ Next, install all the packages that Catala depends on with make dependencies This should ensure everything is set up for developing on the Catala compiler! + The Python dependencies are installed inside a local virtual environment -(`venv`). The Makefile rules will use it automatically when building the syntax -cheat-sheet, for example, but if you need to otherwise colorise Catala code, or -use generated Python code, you should run the following command once in every -new shell session: +(`venv`). To use it, for example to run Python code generated by Catala, you +should run the following command once in every new shell session: . _python_venv/bin/activate diff --git a/compiler/catala_utils/cli.ml b/compiler/catala_utils/cli.ml index bf177021..b00d5f26 100644 --- a/compiler/catala_utils/cli.ml +++ b/compiler/catala_utils/cli.ml @@ -378,6 +378,10 @@ let info = "Prints a debugging verbatim of the statement calculus intermediate \ representation of the Catala program. Use the $(b,-s) option to \ restrict the output to a particular scope." ); + `I + ( "$(b,pygmentize)", + "This special command is a wrapper around the $(b,pygmentize) \ + command that enables support for colorising Catala code." ); `S Manpage.s_authors; `P "The authors are listed by alphabetical order."; `P "Nicolas Chataing "; diff --git a/compiler/driver.ml b/compiler/driver.ml index c72fb3c1..a29f4e5c 100644 --- a/compiler/driver.ml +++ b/compiler/driver.ml @@ -403,6 +403,10 @@ let driver source_file (options : Cli.options) : int = -1 let main () = + if + Array.length Sys.argv >= 2 + && String.lowercase_ascii Sys.argv.(1) = "pygmentize" + then Literate.Pygmentize.exec (); let return_code = Cmdliner.Cmd.eval' (Cmdliner.Cmd.v Cli.info (Cli.catala_t (fun f -> driver (FileName f)))) diff --git a/compiler/literate/literate_common.ml b/compiler/literate/literate_common.ml index e089f07a..278c529b 100644 --- a/compiler/literate/literate_common.ml +++ b/compiler/literate/literate_common.ml @@ -125,6 +125,16 @@ let check_exceeding_lines "%s" String.(sub s max_len (len_s - max_len))))) +let with_pygmentize_lexer lang f = + let lexer_py = + let lexer_fname = "lexer_" ^ Cli.language_code lang ^ ".py" in + match Pygment_lexers.read lexer_fname with + | None -> failwith "Pygments lexer not found for this language" + | Some lexer -> lexer + in + File.with_temp_file "pygments_lexer_" ".py" ~contents:lexer_py + @@ fun pyg_lexer -> f ["-l"; pyg_lexer; "-x"] + let call_pygmentize ?lang args = let cmd = "pygmentize" in let check_exit n = @@ -137,12 +147,5 @@ let call_pygmentize ?lang args = match lang with | None -> File.process_out ~check_exit cmd args | Some lang -> - let lexer_py = - let lexer_fname = "lexer_" ^ Cli.language_code lang ^ ".py" in - match Pygment_lexers.read lexer_fname with - | None -> failwith "Pygments lexer not found for this language" - | Some lexer -> lexer - in - File.with_temp_file "pygments_lexer_" ".py" ~contents:lexer_py - @@ fun pyg_lexer -> - File.process_out ~check_exit cmd ("-l" :: pyg_lexer :: "-x" :: args) + with_pygmentize_lexer lang + @@ fun lex_args -> File.process_out ~check_exit cmd (lex_args @ args) diff --git a/compiler/literate/literate_common.mli b/compiler/literate/literate_common.mli index 4164a2fa..f7f62194 100644 --- a/compiler/literate/literate_common.mli +++ b/compiler/literate/literate_common.mli @@ -51,3 +51,7 @@ val call_pygmentize : ?lang:Cli.backend_lang -> string list -> string (** Calls the [pygmentize] command with the given arguments, and returns the results as a string. If [lang] is specified, the proper arguments for the Catala lexer are already passed. *) + +val with_pygmentize_lexer : Cli.backend_lang -> (string list -> 'a) -> 'a +(** Creates the required lexer file and returns the corresponding [pygmentize] + command-line arguments *) diff --git a/compiler/literate/pygmentize.ml b/compiler/literate/pygmentize.ml new file mode 100644 index 00000000..c7e002b5 --- /dev/null +++ b/compiler/literate/pygmentize.ml @@ -0,0 +1,54 @@ +(* This file is part of the Catala compiler, a specification language for tax + and social benefits computation rules. Copyright (C) 2020 Inria, contributor: + Louis Gesbert + + 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + 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. *) + +open Catala_utils +open Literate_common + +let lang_of_ext s = + if String.starts_with ~prefix:"catala_" s then + match s with + | "catala_en" -> Some Cli.En + | "catala_fr" -> Some Cli.Fr + | "catala_pl" -> Some Cli.Pl + | _ -> failwith "Unknown Catala dialect" + else None + +let exec () = + let args = List.tl (Array.to_list Sys.argv) in + let rec find_lang acc = function + | "-l" :: lang :: r -> Some lang, List.rev_append acc r + | x :: r -> find_lang (x :: acc) r + | [] -> None, List.rev acc + in + let lang, args = find_lang [] args in + let catala_lang = + match lang with + | Some l -> lang_of_ext l + | None -> + List.find_map + (fun s -> + match Filename.extension s with + | "" -> None + | e -> lang_of_ext (String.sub e 1 (String.length e - 1))) + args + in + match catala_lang with + | None -> Unix.execvp "pygmentize" (Array.of_list args) + | Some lang -> + with_pygmentize_lexer lang + @@ fun lex_args -> + Unix.execvp "pygmentize" + (Array.of_list (("pygmentize" :: lex_args) @ List.tl args)) diff --git a/compiler/literate/pygmentize.mli b/compiler/literate/pygmentize.mli new file mode 100644 index 00000000..ca0ed472 --- /dev/null +++ b/compiler/literate/pygmentize.mli @@ -0,0 +1,19 @@ +(* This file is part of the Catala compiler, a specification language for tax + and social benefits computation rules. Copyright (C) 2020 Inria, contributor: + Louis Gesbert + + 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 + + http://www.apache.org/licenses/LICENSE-2.0 + + 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. *) + +val exec : unit -> unit +(** Wrapper around the [pygmentize] binary with support for Catala. Reads the + arguments directly from Sys.argv *) diff --git a/doc/syntax/syntax_en.tex b/doc/syntax/syntax_en.tex index 7fbce6b0..df32c3ac 100644 --- a/doc/syntax/syntax_en.tex +++ b/doc/syntax/syntax_en.tex @@ -26,6 +26,8 @@ \setlist[itemize]{noitemsep, topsep=0pt} +\renewcommand{\MintedPygmentize}{../../_build/default/compiler/catala.exe pygmentize} + % backquote dejavu fix \makeatletter \chardef\straightquote@code=\catcode`' diff --git a/doc/syntax/syntax_fr.tex b/doc/syntax/syntax_fr.tex index 7aec5a4b..ee0a5100 100644 --- a/doc/syntax/syntax_fr.tex +++ b/doc/syntax/syntax_fr.tex @@ -26,6 +26,8 @@ \setlist[itemize]{noitemsep, topsep=0pt} +\renewcommand{\MintedPygmentize}{../../_build/default/compiler/catala.exe pygmentize} + % backquote dejavu fix \makeatletter \chardef\straightquote@code=\catcode`'