Add a !LW recipe magic comment to set recipe

This commit is contained in:
James-Yu 2023-02-23 14:03:36 +08:00
parent f94300ac83
commit d31b667ab9
4 changed files with 59 additions and 11 deletions

2
.vscode/launch.json vendored
View File

@ -32,7 +32,7 @@
"preLaunchTask": "task-watch-all",
"env": {
"LATEXWORKSHOP_CI": "1",
"LATEXWORKSHOP_SUITE": "06"
"LATEXWORKSHOP_SUITE": ""
}
},
{

View File

@ -157,7 +157,9 @@ export class Builder {
* @param langId The language ID of the root file. This argument is used to
* determine whether the previous recipe can be applied to this root file.
* @param recipeName The name of recipe to be used. If `undefined`, the
* builder tries to determine on its own, in {@link createBuildTools}.
* builder tries to determine on its own, in {@link createBuildTools}. This
* parameter is given only when RECIPE command is invoked. For all other
* cases, it should be `undefined`.
*/
async build(rootFile: string, langId: string, recipeName?: string) {
logger.log(`Build root file ${rootFile}`)
@ -443,12 +445,12 @@ export class Builder {
let buildTools: Tool[] = []
const configuration = vscode.workspace.getConfiguration('latex-workshop', vscode.Uri.file(rootFile))
const [magicTex, magicBib] = this.findMagicPrograms(rootFile)
const magic = this.findMagicComments(rootFile)
if (recipeName === undefined && magicTex && !configuration.get('latex.build.forceRecipeUsage')) {
buildTools = this.createBuildMagic(rootFile, magicTex, magicBib)
if (recipeName === undefined && magic.tex && !configuration.get('latex.build.forceRecipeUsage')) {
buildTools = this.createBuildMagic(rootFile, magic.tex, magic.bib)
} else {
const recipe = this.findRecipe(rootFile, langId, recipeName)
const recipe = this.findRecipe(rootFile, langId, recipeName || magic.recipe)
if (recipe === undefined) {
return
}
@ -529,6 +531,10 @@ export class Builder {
return buildTools
}
/**
* @param recipeName This recipe name may from user selection of RECIPE
* command, or from the %! LW recipe magic command.
*/
private findRecipe(rootFile: string, langId: string, recipeName?: string): Recipe | undefined {
const configuration = vscode.workspace.getConfiguration('latex-workshop', vscode.Uri.file(rootFile))
@ -597,18 +603,16 @@ export class Builder {
}
}
private findMagicPrograms(rootFile: string): [Tool | undefined, Tool | undefined] {
private findMagicComments(rootFile: string): {tex?: Tool, bib?: Tool, recipe?: string} {
const regexTex = /^(?:%\s*!\s*T[Ee]X\s(?:TS-)?program\s*=\s*([^\s]*)$)/m
const regexBib = /^(?:%\s*!\s*BIB\s(?:TS-)?program\s*=\s*([^\s]*)$)/m
const regexTexOptions = /^(?:%\s*!\s*T[Ee]X\s(?:TS-)?options\s*=\s*(.*)$)/m
const regexBibOptions = /^(?:%\s*!\s*BIB\s(?:TS-)?options\s*=\s*(.*)$)/m
const regexRecipe = /^(?:%\s*!\s*LW\srecipe\s*=\s*(.*)$)/m
const content = fs.readFileSync(rootFile).toString()
const tex = content.match(regexTex)
const bib = content.match(regexBib)
let texCommand: Tool | undefined = undefined
let bibCommand: Tool | undefined = undefined
if (tex) {
texCommand = {
name: this.TEX_MAGIC_PROGRAM_NAME,
@ -622,6 +626,8 @@ export class Builder {
}
}
const bib = content.match(regexBib)
let bibCommand: Tool | undefined = undefined
if (bib) {
bibCommand = {
name: this.BIB_MAGIC_PROGRAM_NAME,
@ -635,7 +641,12 @@ export class Builder {
}
}
return [texCommand, bibCommand]
const recipe = content.match(regexRecipe)
if (recipe && recipe[1]) {
logger.log(`Found LW recipe '${recipe[1]}' by magic comment: ${recipe}.`)
}
return {tex: texCommand, bib: bibCommand, recipe: recipe?.[1]}
}
/**

5
test/fixtures/armory/magic_recipe.tex vendored Normal file
View File

@ -0,0 +1,5 @@
%! LW recipe = latexmk
\documentclass{article}
\begin{document}
abc
\end{document}

View File

@ -123,6 +123,38 @@ suite('Build TeX files test suite', () => {
assert.ok(!fs.existsSync(path.resolve(fixture, 'main.pdf')))
})
test.only('build with !LW recipe', async (fixture: string) => {
await vscode.workspace.getConfiguration('latex-workshop').update('latex.build.forceRecipeUsage', true)
const tools = [
{ name: 'touch', command: 'touch', args: ['fail.txt'], env: {} },
{ name: 'latexmk', command: 'latexmk', args: [ '-synctex=1', '-interaction=nonstopmode', '-file-line-error', '-pdf', '-outdir=%OUTDIR%', '%DOC%' ], env: {} }
]
const recipes = [{name: 'touch', tools: ['touch']}, {name: 'latexmk', tools: ['latexmk']}]
await vscode.workspace.getConfiguration('latex-workshop').update('latex.tools', tools)
await vscode.workspace.getConfiguration('latex-workshop').update('latex.recipes', recipes)
await test.load(fixture, [
{src: 'magic_recipe.tex', dst: 'main.tex'}
], {skipCache: true})
await test.build(fixture, 'main.tex')
assert.ok(fs.existsSync(path.resolve(fixture, 'main.pdf')))
})
test.only('build with invalid !LW recipe', async (fixture: string) => {
await vscode.workspace.getConfiguration('latex-workshop').update('latex.build.forceRecipeUsage', true)
const tools = [
{ name: 'touch', command: 'touch', args: ['success.txt'], env: {} },
{ name: 'latexmk', command: 'latexmk', args: [ '-synctex=1', '-interaction=nonstopmode', '-file-line-error', '-pdf', '-outdir=%OUTDIR%', '%DOC%' ], env: {} }
]
const recipes = [{name: 'touch', tools: ['touch']}, {name: 'latexmk_', tools: ['latexmk']}]
await vscode.workspace.getConfiguration('latex-workshop').update('latex.tools', tools)
await vscode.workspace.getConfiguration('latex-workshop').update('latex.recipes', recipes)
await test.load(fixture, [
{src: 'magic_recipe.tex', dst: 'main.tex'}
], {skipCache: true})
await test.build(fixture, 'main.tex')
assert.ok(!fs.existsSync(path.resolve(fixture, 'main.pdf')))
})
test.run('build with forceRecipeUsage: true', async (fixture: string) => {
await vscode.workspace.getConfiguration('latex-workshop').update('latex.build.forceRecipeUsage', true)
await test.load(fixture, [