Path: blob/main/src/command/render/latexmk/quarto-latexmk.ts
3589 views
import { debug } from "../../../deno_ral/log.ts";1import {2Command,3CompletionsCommand,4HelpCommand,5} from "cliffy/command/mod.ts";6import { parse } from "flags";78import {9appendLogOptions,10cleanupLogger,11initializeLogger,12logError,13logOptions,14} from "../../../core/log.ts";15import { LatexmkOptions } from "./types.ts";16import { generatePdf } from "./pdf.ts";17import {18kExeDescription,19kExeName,20kExeVersion,21} from "./quarto-latexmk-metadata.ts";22import { exitWithCleanup } from "../../../core/cleanup.ts";23import { mainRunner } from "../../../core/main.ts";2425interface EngineOpts {26pdf: string[];27index: string[];28tlmgr: string[];29}3031function parseOpts(args: string[]): [string[], EngineOpts] {32const pdfOpts = parseEngineFlags("pdf-engine-opt", args);33const indexOpts = parseEngineFlags("index-engine-opt", pdfOpts.resultArgs);34const tlmgrOpts = parseEngineFlags("tlmgr-opt", indexOpts.resultArgs);35return [36tlmgrOpts.resultArgs,37{38pdf: pdfOpts.values,39index: indexOpts.values,40tlmgr: tlmgrOpts.values,41},42];43}4445function parseEngineFlags(optFlag: string, args: string[]) {46const values = [];47const resultArgs = [];4849for (const arg of args) {50if (arg.startsWith(`--${optFlag}=`)) {51const value = arg.split("=")[1];52values.push(value);53} else {54resultArgs.push(arg);55}56}57return { values, resultArgs };58}5960export async function pdf(args: string[]) {61// Parse any of the option flags62const [parsedArgs, engineOpts] = parseOpts(args);6364const pdfCommand = new Command()65.name(kExeName)66.arguments("<input:string>")67.version(kExeVersion + "\n")68.description(kExeDescription)69.option(70"--pdf-engine <engine>",71"The PDF engine to use",72)73.option(74"--pdf-engine-opt=<optionsfile:string>",75"Options passed to the pdf engine. Can be used multiple times - values will be passed in the order they appear in the command. These must be specified using an '='.",76)77.option(78"--index-engine <engine>",79"The index engine to use",80)81.option(82"--index-engine-opt=<optionsfile:string>",83"Options passed to the index engine. Can be used multiple times - values will be passed in the order they appear in the command. These must be specified using an '='.",84)85.option(86"--bib-engine <engine>",87"The bibliography engine to use",88)89.option(90"--no-auto-install",91"Disable automatic package installation",92)93.option(94"--tlmgr-opt=<optionsfile:string>",95"Options passed to the tlmgr engine. Can be used multiple times - values will be passed in the order they appear in the command. These must be specified using an '='.",96)97.option(98"--no-auto-mk",99"Disable the pdf generation loop",100)101.option(102"--min <min:number>",103"The minimum number of iterations",104)105.option(106"--max <max:number>",107"The maximum number of iterations",108)109.option("--output-dir <directory>", "The output directory")110.option("--no-clean", "Don't clean intermediaries")111.throwErrors()112.action(async (options: unknown, input: string) => {113const latexmkOptions = mkOptions(114input,115options as Record<string, unknown>,116engineOpts,117);118await generatePdf(latexmkOptions);119});120121await appendLogOptions(pdfCommand)122.command("help", new HelpCommand().global())123.command("completions", new CompletionsCommand()).hidden()124.parse(parsedArgs);125}126127if (import.meta.main) {128await mainRunner(async () => {129await pdf(Deno.args);130});131}132133function mkOptions(134input: string,135options: Record<string, unknown>,136engineOpts: EngineOpts,137): LatexmkOptions {138const engine = {139pdfEngine: options.pdfEngine as string || "pdflatex",140pdfEngineOpts: engineOpts.pdf,141bibEngine: bibEngine(options.bibEngine as string) || "biblatex",142indexEngine: options.indexEngine as string || "makeindex",143indexEngineOpts: engineOpts.index,144tlmgrOpts: engineOpts.tlmgr,145};146147const latexMkOptions = {148input,149engine,150autoInstall: options.autoInstall as boolean,151autoMk: options.autoMk as boolean,152minRuns: options.min as number,153maxRuns: options.max as number,154outputDir: options.outputDir as string,155clean: options.clean as boolean,156};157158// Debug message that show engine configuration (set --log-level debug to view)159debug(() => {160return JSON.stringify(latexMkOptions, undefined, 2);161});162163return latexMkOptions;164}165166function bibEngine(bibEngine?: string): "biblatex" | "natbib" {167if (bibEngine?.toLowerCase() === "natbib") {168return "natbib";169} else {170return "biblatex";171}172}173174175