Skip to content

Commit

Permalink
latex-output-dir
Browse files Browse the repository at this point in the history
Add support for specifying a latex output directory. The output direct will contain the latex intermediates and resulting pdf.
  • Loading branch information
dragonstyle committed Feb 4, 2021
1 parent 3ef6b69 commit c981664
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 37 deletions.
20 changes: 11 additions & 9 deletions src/command/render/latekmk/latex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,9 @@ export async function runPdfEngine(
): Promise<LatexCommandReponse> {
// Input and log paths
const [cwd, stem] = dirAndStem(input);
const output = join(outputDir || cwd, `${stem}.pdf`);
const log = join(outputDir || cwd, `${stem}.log`);
const targetDir = outputDir ? join(cwd, outputDir) : cwd;
const output = join(targetDir, `${stem}.pdf`);
const log = join(targetDir, `${stem}.log`);

// Clean any log file or output from previous runs
[log, output].forEach((file) => {
Expand Down Expand Up @@ -75,9 +76,9 @@ export async function runPdfEngine(
const result = await runLatexCommand(
engine.pdfEngine,
args,
cwd,
pkgMgr,
quiet,
cwd,
);

// Success, return result
Expand Down Expand Up @@ -107,9 +108,9 @@ export async function runIndexEngine(
const result = await runLatexCommand(
engine || "makeindex",
[...(args || []), basename(input)],
cwd,
pkgMgr,
quiet,
cwd,
);

return {
Expand All @@ -122,11 +123,12 @@ export async function runIndexEngine(
export async function runBibEngine(
engine: string,
input: string,
cwd: string,
pkgMgr?: PackageManager,
quiet?: boolean,
): Promise<LatexCommandReponse> {
const [cwd, stem] = dirAndStem(input);
const log = join(cwd, `${stem}.blg`);
const [dir, stem] = dirAndStem(input);
const log = join(dir, `${stem}.blg`);

// Clean any log file from previous runs
if (existsSync(log)) {
Expand All @@ -135,10 +137,10 @@ export async function runBibEngine(

const result = await runLatexCommand(
engine,
[basename(input)],
cwd,
[input],
pkgMgr,
quiet,
cwd,
);
return {
result,
Expand All @@ -149,9 +151,9 @@ export async function runBibEngine(
async function runLatexCommand(
latexCmd: string,
args: string[],
cwd: string,
pkMgr?: PackageManager,
quiet?: boolean,
cwd?: string,
): Promise<ProcessResult> {
const runOptions: Deno.RunOptions = {
cmd: [latexCmd, ...args],
Expand Down
29 changes: 21 additions & 8 deletions src/command/render/latekmk/latexmk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
kLatexClean,
kLatexMaxRuns,
kLatexMinRuns,
kLatexOutputDir,
kOutputExt,
kOutputFile,
} from "../../../config/constants.ts";
Expand All @@ -25,13 +26,7 @@ import { PdfEngine, pdfEngine } from "../../../config/pdf.ts";

import { PandocOptions } from "../pandoc.ts";
import { RenderOptions } from "../render.ts";
import {
kStdOut,
removePandocArgs,
removePandocToArg,
RenderFlags,
replacePandocArg,
} from "../flags.ts";
import { kStdOut, RenderFlags, replacePandocArg } from "../flags.ts";
import { OutputRecipe } from "../output.ts";
import { generatePdf } from "./pdf.ts";

Expand Down Expand Up @@ -97,6 +92,9 @@ export function quartoLatexmkOutputRecipe(
pandoc[kOutputFile] = output;
}

// The directory for PDF output
const outputDir = format.render[kLatexOutputDir];

// when pandoc is done, we need to run latexmk and then copy the
// ouptut to the user's requested destination
const complete = async (pandocOptions: PandocOptions) => {
Expand All @@ -108,6 +106,7 @@ export function quartoLatexmkOutputRecipe(
autoMk: format.render[kLatexAutoMk],
minRuns: format.render[kLatexMinRuns],
maxRuns: format.render[kLatexMaxRuns],
outputDir: outputDir,
clean: !options.flags?.debug && format.render[kLatexClean] !== false,
quiet: pandocOptions.flags?.quiet,
};
Expand All @@ -123,16 +122,30 @@ export function quartoLatexmkOutputRecipe(

// copy (or write for stdout) compiled pdf to final output location
if (finalOutput) {
const compilePdf = join(inputDir, texStem + ".pdf");
const compilePdf = outputDir
? join(inputDir, outputDir, texStem + ".pdf")
: join(inputDir, texStem + ".pdf");
if (finalOutput === kStdOut) {
writeFileToStdout(compilePdf);
Deno.removeSync(compilePdf);
} else {
const outputPdf = expandPath(finalOutput);

if (normalize(compilePdf) !== normalize(outputPdf)) {
Deno.renameSync(compilePdf, outputPdf);
}
}

// Clean the output directory if it is empty
if (outputDir) {
try {
// Remove the outputDir if it is empty
Deno.removeSync(outputDir, { recursive: false });
} catch {
// This is ok, just means the directory wasn't empty
}
}

return finalOutput;
} else {
return texStem + ".pdf";
Expand Down
39 changes: 19 additions & 20 deletions src/command/render/latekmk/pdf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
*
*/

import { basename, dirname, extname, join } from "path/mod.ts";
import { dirname, join } from "path/mod.ts";
import { existsSync } from "fs/mod.ts";

import { message } from "../../../core/console.ts";
Expand Down Expand Up @@ -37,12 +37,8 @@ export async function generatePdf(mkOptions: LatexmkOptions) {
}

// Get the working directory and file name stem
const [workingDir, inputStem] = mkOptions.outputDir
? [
mkOptions.outputDir,
basename(mkOptions.input, extname(mkOptions.input)),
]
: dirAndStem(mkOptions.input);
const [cwd, stem] = dirAndStem(mkOptions.input);
const workingDir = mkOptions.outputDir ? join(cwd, mkOptions.outputDir) : cwd;

// Ensure that working directory exists
if (!existsSync(workingDir)) {
Expand All @@ -69,7 +65,7 @@ export async function generatePdf(mkOptions: LatexmkOptions) {
// Generate the index information, if needed
const indexCreated = await makeIndexIntermediates(
workingDir,
inputStem,
stem,
pkgMgr,
mkOptions.engine.indexEngine,
mkOptions.engine.indexEngineOpts,
Expand All @@ -78,10 +74,10 @@ export async function generatePdf(mkOptions: LatexmkOptions) {

// Generate the bibliography intermediaries
const bibliographyCreated = await makeBibliographyIntermediates(
workingDir,
inputStem,
mkOptions.input,
mkOptions.engine.bibEngine || "citeproc",
pkgMgr,
mkOptions.outputDir,
mkOptions.quiet,
);

Expand All @@ -104,7 +100,7 @@ export async function generatePdf(mkOptions: LatexmkOptions) {

// cleanup if requested
if (mkOptions.clean) {
cleanup(workingDir, inputStem);
cleanup(workingDir, stem);
}

if (!mkOptions.quiet) {
Expand Down Expand Up @@ -265,10 +261,10 @@ async function makeIndexIntermediates(
}

async function makeBibliographyIntermediates(
dir: string,
stem: string,
input: string,
engine: string,
pkgMgr: PackageManager,
outputDir?: string,
quiet?: boolean,
) {
// Generate bibliography (including potentially installing missing packages)
Expand All @@ -277,32 +273,35 @@ async function makeBibliographyIntermediates(
// processing (including explicitly calling the processing tool)
const bibCommand = engine === "natbib" ? "bibtex" : "biber";

const [cwd, stem] = dirAndStem(input);

while (true) {
// If biber, look for a bcf file, otherwise look for aux file
const auxBibFile = bibCommand === "biber"
? join(dir, `${stem}.bcf`)
: join(dir, `${stem}.aux`);
const auxBibFile = bibCommand === "biber" ? `${stem}.bcf` : `${stem}.aux`;
const auxBibPath = outputDir ? join(outputDir, auxBibFile) : auxBibFile;
const auxBibFullPath = join(cwd, auxBibPath);
const requiresProcessing = bibCommand === "biber"
? true
: containsBiblioData(auxBibFile);
: containsBiblioData(auxBibFullPath);

if (existsSync(auxBibFile) && requiresProcessing) {
if (existsSync(auxBibFullPath) && requiresProcessing) {
if (!quiet) {
message("\ngenerating bibliography", kPdfGenerateMessageOptions);
}

// If natbib, only use bibtex, otherwise, could use biber or bibtex
const response = await runBibEngine(
bibCommand,
auxBibFile,
auxBibPath,
cwd,
pkgMgr,
quiet,
);

if (response.result.code !== 0 && pkgMgr.autoInstall) {
// Biblio generation failed, see whether we should install anything to try to resolve
// Find the missing packages
const log = join(dir, `${stem}.blg`);
const log = join(dirname(auxBibFullPath), `${stem}.blg`);

if (existsSync(log)) {
const logOutput = Deno.readTextFileSync(log);
Expand Down
2 changes: 2 additions & 0 deletions src/config/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export const kLatexMakeIndex = "latex-makeindex";
export const kLatexMakeIndexOpts = "latex-makeindex-opts";

export const kLatexTlmgrOpts = "latex-tlmgr-opts";
export const kLatexOutputDir = "latex-output-dir";

export const kRenderDefaultsKeys = [
kKeepMd,
Expand All @@ -107,6 +108,7 @@ export const kRenderDefaultsKeys = [
kLatexMakeIndex,
kLatexMakeIndexOpts,
kLatexTlmgrOpts,
kLatexOutputDir,
];

// 'defaults' fields
Expand Down
3 changes: 3 additions & 0 deletions src/config/format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import {
kLatexMakeIndexOpts,
kLatexMaxRuns,
kLatexMinRuns,
kLatexOutputDir,
kLatexTlmgrOpts,
kListings,
kMarkdownHeadings,
Expand Down Expand Up @@ -97,6 +98,7 @@ export interface FormatRender {
[kLatexMakeIndex]?: string;
[kLatexMakeIndexOpts]?: string[];
[kLatexTlmgrOpts]?: string[];
[kLatexOutputDir]?: string;
}

export interface FormatExecution {
Expand Down Expand Up @@ -514,6 +516,7 @@ function defaultFormat(): Format {
[kLatexMakeIndex]: "makeindex",
[kLatexMakeIndexOpts]: [],
[kLatexTlmgrOpts]: [],
[kLatexOutputDir]: undefined,
},
pandoc: {
from: "markdown",
Expand Down

0 comments on commit c981664

Please sign in to comment.