From 7af9fcde8d6a4935701642e50ddca89512951169 Mon Sep 17 00:00:00 2001 From: Jerome Lelong Date: Sun, 29 Mar 2020 15:25:15 +0200 Subject: [PATCH 1/8] Activate clean and view keybindings for .rnw Related to #2005 --- package.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index 9b927938b..0477d3d47 100644 --- a/package.json +++ b/package.json @@ -395,13 +395,13 @@ "key": "ctrl+l alt+c", "mac": "cmd+l alt+c", "command": "latex-workshop.clean", - "when": "editorLangId == 'latex' && config.latex-workshop.bind.altKeymap.enabled" + "when": "editorLangId =~ /latex|rsweave/ && config.latex-workshop.bind.altKeymap.enabled" }, { "key": "ctrl+l alt+v", "mac": "cmd+l alt+v", "command": "latex-workshop.view", - "when": "editorLangId == 'latex' && config.latex-workshop.bind.altKeymap.enabled" + "when": "editorLangId =~ /latex|rsweave/ && config.latex-workshop.bind.altKeymap.enabled" }, { "key": "ctrl+l alt+j", @@ -425,13 +425,13 @@ "key": "ctrl+alt+c", "mac": "cmd+alt+c", "command": "latex-workshop.clean", - "when": "editorLangId == 'latex' && !config.latex-workshop.bind.altKeymap.enabled" + "when": "editorLangId =~ /latex|rsweave/ && !config.latex-workshop.bind.altKeymap.enabled" }, { "key": "ctrl+alt+v", "mac": "cmd+alt+v", "command": "latex-workshop.view", - "when": "editorLangId == 'latex' && !config.latex-workshop.bind.altKeymap.enabled" + "when": "editorLangId =~ /latex|rsweave/ && !config.latex-workshop.bind.altKeymap.enabled" }, { "key": "ctrl+alt+j", From 9d25ba3c2e20391b5f5efac740d94faa33b77a9e Mon Sep 17 00:00:00 2001 From: Jerome Lelong Date: Sun, 29 Mar 2020 23:04:58 +0200 Subject: [PATCH 2/8] Consider rnw files in findRoot --- package.json | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index 0477d3d47..19f6e7700 100644 --- a/package.json +++ b/package.json @@ -815,7 +815,9 @@ "type": "string" }, "default": [ - "**/*.tex" + "**/*.tex", + "**/*.rnw", + "**/*.Rnw" ], "markdownDescription": "Patterns of files to consider for the root detection mechanism.\nRelative paths are computed from the workspace folder. To detect the root file and the tex file tree, we parse all the `.tex` listed here.\nIf you want to specify all `.tex` files inside directory, say `foo`, and all its subdirectories recursively, you need to use `**/foo/**/*.tex`. If you only want to match `.tex` files at the top level of the workspace, use `*.tex`. For more details the [wiki](https://github.com/James-Yu/LaTeX-Workshop/wiki/Multi-File-Projects)." }, From ec5d9af5ea5138f23d69bb4d285d487f7c6c51a5 Mon Sep 17 00:00:00 2001 From: Jerome Lelong Date: Sun, 29 Mar 2020 23:08:10 +0200 Subject: [PATCH 3/8] Accept SweaveInput to input a file This is how .rnw files can be included. It is used to discover the TeX children. --- src/components/manager.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/manager.ts b/src/components/manager.ts index 778c9f60e..9430e99fa 100644 --- a/src/components/manager.ts +++ b/src/components/manager.ts @@ -448,7 +448,7 @@ export class Manager { // Update children of current file if (this.cachedContent[file] === undefined) { this.cachedContent[file] = {content, element: {}, bibs: [], children: []} - const inputReg = /(?:\\(?:input|InputIfFileExists|include|subfile|(?:(?:sub)?(?:import|inputfrom|includefrom)\*?{([^}]*)}))(?:\[[^[\]{}]*\])?){([^}]*)}/g + const inputReg = /(?:\\(?:input|InputIfFileExists|include|SweaveInput|subfile|(?:(?:sub)?(?:import|inputfrom|includefrom)\*?{([^}]*)}))(?:\[[^[\]{}]*\])?){([^}]*)}/g while (true) { const result = inputReg.exec(content) if (!result) { @@ -482,7 +482,7 @@ export class Manager { } private parseInputFiles(content: string, baseFile: string) { - const inputReg = /(?:\\(?:input|InputIfFileExists|include|subfile|(?:(?:sub)?(?:import|inputfrom|includefrom)\*?{([^}]*)}))(?:\[[^[\]{}]*\])?){([^}]*)}/g + const inputReg = /(?:\\(?:input|InputIfFileExists|include|SweaveInput|subfile|(?:(?:sub)?(?:import|inputfrom|includefrom)\*?{([^}]*)}))(?:\[[^[\]{}]*\])?){([^}]*)}/g while (true) { const result = inputReg.exec(content) if (!result) { From cc14427bdba06a960095c95669ccaa345f73f1e4 Mon Sep 17 00:00:00 2001 From: Jerome Lelong Date: Mon, 30 Mar 2020 22:59:51 +0200 Subject: [PATCH 4/8] Compile .rnw files using the build method- ctrl+alt+b is activated for rsweave languageId- If no recipe is specified, the first recipe whose name contains rnwor rsweave is used. --- package.json | 4 +-- src/commander.ts | 11 ++++--- src/components/builder.ts | 24 ++++++++++---- src/components/manager.ts | 67 ++++++++++++++++++++++++++------------- 4 files changed, 71 insertions(+), 35 deletions(-) diff --git a/package.json b/package.json index 19f6e7700..23be8a5c2 100644 --- a/package.json +++ b/package.json @@ -389,7 +389,7 @@ "key": "ctrl+l alt+b", "mac": "cmd+l alt+b", "command": "latex-workshop.build", - "when": "editorLangId == 'latex' && config.latex-workshop.bind.altKeymap.enabled" + "when": "editorLangId =~ /latex|rsweave/ && config.latex-workshop.bind.altKeymap.enabled" }, { "key": "ctrl+l alt+c", @@ -419,7 +419,7 @@ "key": "ctrl+alt+b", "mac": "cmd+alt+b", "command": "latex-workshop.build", - "when": "editorLangId == 'latex' && !config.latex-workshop.bind.altKeymap.enabled" + "when": "editorLangId =~ /latex|rsweave/ && !config.latex-workshop.bind.altKeymap.enabled" }, { "key": "ctrl+alt+c", diff --git a/src/commander.ts b/src/commander.ts index 7af9491b4..8f5508278 100644 --- a/src/commander.ts +++ b/src/commander.ts @@ -65,7 +65,7 @@ export class Commander { .catch(err => this.extension.logger.addLogMessage(`Error reading data: ${err}.`)) } - async build(skipSelection: boolean = false, rootFile: string | undefined = undefined, recipe: string | undefined = undefined) { + async build(skipSelection: boolean = false, rootFile: string | undefined = undefined, languageId: string | undefined = undefined, recipe: string | undefined = undefined) { this.extension.logger.addLogMessage('BUILD command invoked.') if (!vscode.window.activeTextEditor) { return @@ -76,13 +76,14 @@ export class Commander { const externalBuildArgs = configuration.get('latex.external.build.args') as string[] if (rootFile === undefined && this.extension.manager.hasTexId(vscode.window.activeTextEditor.document.languageId)) { rootFile = await this.extension.manager.findRoot() + languageId = this.extension.manager.rootFileLanguageId } if (externalBuildCommand) { const pwd = path.dirname(rootFile ? rootFile : vscode.window.activeTextEditor.document.fileName) await this.extension.builder.buildWithExternalCommand(externalBuildCommand, externalBuildArgs, pwd, rootFile) return } - if (rootFile === undefined) { + if (rootFile === undefined || languageId === undefined) { this.extension.logger.addLogMessage('Cannot find LaTeX root file.') return } @@ -95,7 +96,7 @@ export class Commander { } } this.extension.logger.addLogMessage(`Building root file: ${pickedRootFile}`) - await this.extension.builder.build(pickedRootFile, recipe) + await this.extension.builder.build(pickedRootFile, languageId, recipe) } async revealOutputDir() { @@ -120,7 +121,7 @@ export class Commander { return } if (recipe) { - this.build(false, undefined, recipe) + this.build(false, undefined, undefined, recipe) return } vscode.window.showQuickPick(recipes.map(candidate => candidate.name), { @@ -129,7 +130,7 @@ export class Commander { if (!selected) { return } - this.build(false, undefined, selected) + this.build(false, undefined, undefined, selected) }) } diff --git a/src/components/builder.ts b/src/components/builder.ts index 0dff47797..a6cde1bb9 100644 --- a/src/components/builder.ts +++ b/src/components/builder.ts @@ -22,6 +22,7 @@ export class Builder { waitingForBuildToFinishMutex: Mutex isMiktex: boolean = false previouslyUsedRecipe: {name: string, tools: (string | StepCommand)[]} | undefined + previousLanguageId: string | undefined constructor(extension: Extension) { this.extension = extension @@ -158,8 +159,8 @@ export class Builder { }) } - buildInitiator(rootFile: string, recipe: string | undefined = undefined, releaseBuildMutex: () => void) { - const steps = this.createSteps(rootFile, recipe) + buildInitiator(rootFile: string, languageId: string, recipe: string | undefined = undefined, releaseBuildMutex: () => void) { + const steps = this.createSteps(rootFile, languageId, recipe) if (steps === undefined) { this.extension.logger.addLogMessage('Invalid toolchain.') return @@ -167,7 +168,7 @@ export class Builder { this.buildStep(rootFile, steps, 0, recipe || 'Build', releaseBuildMutex) // use 'Build' as default name } - async build(rootFile: string, recipe: string | undefined = undefined) { + async build(rootFile: string, languageId: string, recipe: string | undefined = undefined) { if (this.isWaitingForBuildToFinish()) { this.extension.logger.addLogMessage('Another LaTeX build processing is already waiting for the current LaTeX build to finish. Exit.') return @@ -215,7 +216,7 @@ export class Builder { fs.ensureDirSync(path.resolve(outDir, relativePath)) }) } - this.buildInitiator(rootFile, recipe, releaseBuildMutex) + this.buildInitiator(rootFile, languageId, recipe, releaseBuildMutex) } catch (e) { this.extension.buildInfo.buildEnded() releaseBuildMutex() @@ -379,7 +380,7 @@ export class Builder { } } - createSteps(rootFile: string, recipeName: string | undefined): StepCommand[] | undefined { + createSteps(rootFile: string, languageId: string, recipeName: string | undefined): StepCommand[] | undefined { let steps: StepCommand[] = [] const configuration = vscode.workspace.getConfiguration('latex-workshop') @@ -406,7 +407,10 @@ export class Builder { return undefined } let recipe = recipes[0] - if ((configuration.get('latex.recipe.default') as string === 'lastUsed') && (this.previouslyUsedRecipe !== undefined)) { + if (this.previousLanguageId !== languageId) { + this.previouslyUsedRecipe = undefined + } + if ((configuration.get('latex.recipe.default') as string === 'lastUsed') && (this.previouslyUsedRecipe !== undefined) ) { recipe = this.previouslyUsedRecipe } if (recipeName) { @@ -416,7 +420,15 @@ export class Builder { } recipe = candidates[0] } + if (!recipeName && languageId === 'rsweave') { + const candidates = recipes.filter(candidate => candidate.name.toLowerCase().match('rnw|rsweave')) + if (candidates.length < 1) { + this.extension.logger.showErrorMessage(`Failed to resolve build recipe: ${recipeName}`) + } + recipe = candidates[0] + } this.previouslyUsedRecipe = recipe + this.previousLanguageId = languageId recipe.tools.forEach(tool => { if (typeof tool === 'string') { diff --git a/src/components/manager.ts b/src/components/manager.ts index 9430e99fa..f819a18e8 100644 --- a/src/components/manager.ts +++ b/src/components/manager.ts @@ -105,6 +105,25 @@ export class Manager { this.localRootFiles[this.workspaceRootDir] = localRoot } + private rootFilesLanguageIds: { [key: string]: string | undefined } = {} + get rootFileLanguageId() { + return this.rootFilesLanguageIds[this.workspaceRootDir] + } + set rootFileLanguageId(id: string | undefined) { + this.rootFilesLanguageIds[this.workspaceRootDir] = id + } + + private inferLanguageId(filename: string): string | undefined { + const ext = path.extname(filename) + if (ext === '.tex') { + return 'latex' + } else if (['.rnw', 'Rnw', '.rtex', '.Rtex'].includes(ext)) { + return 'rsweave' + } else { + return undefined + } + } + tex2pdf(texPath: string, respectOutDir: boolean = true) { let outDir = './' if (respectOutDir) { @@ -161,13 +180,16 @@ export class Manager { () => this.findRootInWorkspace() ] for (const method of findMethods) { - const rootFile = await method() + const res = await method() + const rootFile = res[0] + const languageId = res[1] if (rootFile === undefined) { continue } if (this.rootFile !== rootFile) { this.extension.logger.addLogMessage(`Root file changed from: ${this.rootFile} to ${rootFile}. Find all dependencies.`) this.rootFile = rootFile + this.rootFileLanguageId = languageId this.initiateFileWatcher() this.initiateBibWatcher() this.parseFileAndSubs(this.rootFile) // finish the parsing is required for subsequent refreshes. @@ -181,19 +203,19 @@ export class Manager { return undefined } - private findRootFromCurrentRoot(): string | undefined { + private findRootFromCurrentRoot(): [string | undefined, string | undefined] { if (!vscode.window.activeTextEditor || this.rootFile === undefined) { - return undefined + return [undefined, undefined] } if (this.getIncludedTeX().includes(vscode.window.activeTextEditor.document.fileName)) { - return this.rootFile + return [this.rootFile, vscode.window.activeTextEditor.document.languageId] } - return undefined + return [undefined, undefined] } - private findRootFromMagic(): string | undefined { + private findRootFromMagic(): [string | undefined, string | undefined] { if (!vscode.window.activeTextEditor) { - return undefined + return [undefined, undefined] } const regex = /^(?:%\s*!\s*T[Ee]X\sroot\s*=\s*(.*\.tex)$)/m let content = vscode.window.activeTextEditor.document.getText() @@ -217,7 +239,7 @@ export class Manager { file = path.resolve(path.dirname(file), result[1]) if (fileStack.includes(file)) { this.extension.logger.addLogMessage(`Looped root file by magic comment found: ${file}, stop here.`) - return file + return [file, this.inferLanguageId(file)] } else { fileStack.push(file) this.extension.logger.addLogMessage(`Recursively found root file by magic comment: ${file}`) @@ -231,14 +253,14 @@ export class Manager { content = fs.readFileSync(file).toString() result = content.match(regex) } - return file + return [file, this.inferLanguageId(file)] } - return undefined + return [undefined, undefined] } - private findRootFromActive(): string | undefined { + private findRootFromActive(): [string | undefined, string | undefined] { if (!vscode.window.activeTextEditor) { - return undefined + return [undefined, undefined] } const regex = /\\begin{document}/m const content = utils.stripComments(vscode.window.activeTextEditor.document.getText(), '%') @@ -246,15 +268,16 @@ export class Manager { if (result) { const rootSubFile = this.findSubFiles(content) const file = vscode.window.activeTextEditor.document.fileName + const languageId = vscode.window.activeTextEditor.document.languageId if (rootSubFile) { this.localRootFile = file - return rootSubFile + return [rootSubFile, languageId] } else { this.extension.logger.addLogMessage(`Found root file from active editor: ${file}`) - return file + return [file, languageId] } } - return undefined + return [undefined, undefined] } private findSubFiles(content: string): string | undefined { @@ -275,11 +298,11 @@ export class Manager { return undefined } - private async findRootInWorkspace(): Promise { + private async findRootInWorkspace(): Promise<[string | undefined, string | undefined]> { const regex = /\\begin{document}/m if (!this.workspaceRootDir) { - return undefined + return [undefined, undefined] } const configuration = vscode.workspace.getConfiguration('latex-workshop') @@ -298,7 +321,7 @@ export class Manager { const children = this.getTeXChildren(file.fsPath, file.fsPath, [], content) if (vscode.window.activeTextEditor && children.includes(vscode.window.activeTextEditor.document.fileName)) { this.extension.logger.addLogMessage(`Found root file from parent: ${file.fsPath}`) - return file.fsPath + return [file.fsPath, this.inferLanguageId(file.fsPath)] } // Not including the active file, yet can still be a root candidate candidates.push(file.fsPath) @@ -306,10 +329,10 @@ export class Manager { } if (candidates.length > 0) { this.extension.logger.addLogMessage(`Found files that might be root, choose the first one: ${candidates}`) - return candidates[0] + return [candidates[0], this.inferLanguageId(candidates[0])] } } catch (e) {} - return undefined + return [undefined, undefined] } /** @@ -784,9 +807,9 @@ export class Manager { } this.extension.logger.addLogMessage(`${file} changed. Auto build project.`) if (!bibChanged && this.localRootFile && configuration.get('latex.rootFile.useSubFile')) { - this.extension.commander.build(true, this.localRootFile) + this.extension.commander.build(true, this.localRootFile, this.rootFileLanguageId) } else { - this.extension.commander.build(true, this.rootFile) + this.extension.commander.build(true, this.rootFile, this.rootFileLanguageId) } } From 16373dd2ac488efd9119885f76fc381ccd9218e3 Mon Sep 17 00:00:00 2001 From: Jerome Lelong Date: Tue, 31 Mar 2020 09:24:19 +0200 Subject: [PATCH 5/8] Declare .snw and .Snw as rsweave filetypes --- package.json | 4 +++- src/components/manager.ts | 6 +++--- syntax/RSweave.tmLanguage.json | 6 +++++- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 23be8a5c2..0140af4bf 100644 --- a/package.json +++ b/package.json @@ -132,7 +132,9 @@ ".rnw", ".Rnw", ".Rtex", - ".rtex" + ".rtex", + ".snw", + ".Snw" ], "configuration": "./syntax/syntax-rsweave.json" } diff --git a/src/components/manager.ts b/src/components/manager.ts index f819a18e8..0107c8a72 100644 --- a/src/components/manager.ts +++ b/src/components/manager.ts @@ -117,7 +117,7 @@ export class Manager { const ext = path.extname(filename) if (ext === '.tex') { return 'latex' - } else if (['.rnw', 'Rnw', '.rtex', '.Rtex'].includes(ext)) { + } else if (['.rnw', 'Rnw', '.rtex', '.Rtex', '.snw', '.Snw'].includes(ext)) { return 'rsweave' } else { return undefined @@ -710,7 +710,7 @@ export class Manager { private onWatchingNewFile(file: string) { this.extension.logger.addLogMessage(`Adding ${file} to file watcher.`) - if (['.tex', '.bib', '.rnw', '.Rnw', '.rtex', '.Rtex'].includes(path.extname(file)) && + if (['.tex', '.bib', '.rnw', '.Rnw', '.rtex', '.Rtex', '.snw', '.Snw'].includes(path.extname(file)) && !file.includes('expl3-code.tex')) { this.updateCompleterOnChange(file) } @@ -719,7 +719,7 @@ export class Manager { private onWatchedFileChanged(file: string) { this.extension.logger.addLogMessage(`File watcher: responding to change in ${file}`) // It is possible for either tex or non-tex files in the watcher. - if (['.tex', '.bib', '.rnw', '.Rnw', '.rtex', '.Rtex'].includes(path.extname(file)) && + if (['.tex', '.bib', '.rnw', '.Rnw', '.rtex', '.Rtex', '.snw', '.Snw'].includes(path.extname(file)) && !file.includes('expl3-code.tex')) { this.parseFileAndSubs(file, true) this.updateCompleterOnChange(file) diff --git a/syntax/RSweave.tmLanguage.json b/syntax/RSweave.tmLanguage.json index f50d90ac2..bbbaa3fb0 100644 --- a/syntax/RSweave.tmLanguage.json +++ b/syntax/RSweave.tmLanguage.json @@ -3,7 +3,11 @@ "scopeName": "text.tex.latex.rsweave", "fileTypes": [ "rnw", - "Rnw" + "Rnw", + "rtex", + "Rtex", + "snw", + "Snw" ], "patterns": [ { From 0bf0108a66588b8950e6dada1e5a0b9ea324d31b Mon Sep 17 00:00:00 2001 From: Jerome Lelong Date: Tue, 31 Mar 2020 17:40:11 +0200 Subject: [PATCH 6/8] Modify placeholders and add two more In %DOC% and %DOCFILE%, we now remove any extesion, not only .tex The new two placeholders %DOC_EXT% and %DOCFILE_EXT% are respectively the root file full path and the root file name with the extension kept. --- src/components/builder.ts | 12 +++++++++--- src/components/locator.ts | 8 ++++++-- src/components/manager.ts | 8 +++++--- src/providers/latexformatter.ts | 8 +++++--- 4 files changed, 25 insertions(+), 11 deletions(-) diff --git a/src/components/builder.ts b/src/components/builder.ts index a6cde1bb9..0397f01c4 100644 --- a/src/components/builder.ts +++ b/src/components/builder.ts @@ -529,13 +529,19 @@ export class Builder { return (arg: string) => { const docker = vscode.workspace.getConfiguration('latex-workshop').get('docker.enabled') - const doc = rootFile.replace(/\.tex$/, '').split(path.sep).join('/') - const docfile = path.basename(rootFile, '.tex').split(path.sep).join('/') + const rootFileParsed = path.parse(rootFile) + const docfile = rootFileParsed.name + const docfileExt = rootFileParsed.base + const dir = path.normalize(rootFileParsed.dir).split(path.sep).join('/') + const doc = path.join(dir, docfile) + const docExt = path.join(dir, docfileExt) const outDir = this.extension.manager.getOutDir(rootFile) return arg.replace(/%DOC%/g, docker ? docfile : doc) + .replace(/%DOC_EXT%/g, docker ? docfileExt : docExt) + .replace(/%DOCFILE_EXT%/g, docfileExt) .replace(/%DOCFILE%/g, docfile) - .replace(/%DIR%/g, path.dirname(rootFile).split(path.sep).join('/')) + .replace(/%DIR%/g, dir) .replace(/%TMPDIR%/g, tmpDir) .replace(/%OUTDIR%/g, outDir) } diff --git a/src/components/locator.ts b/src/components/locator.ts index b547c004d..e835fab01 100644 --- a/src/components/locator.ts +++ b/src/components/locator.ts @@ -431,9 +431,13 @@ export class Locator { const configuration = vscode.workspace.getConfiguration('latex-workshop') const command = configuration.get('view.pdf.external.synctex.command') as string let args = configuration.get('view.pdf.external.synctex.args') as string[] + const rootFileParsed = path.parse(rootFile) + const docfile = rootFileParsed.name + const dir = path.normalize(rootFileParsed.dir).split(path.sep).join('/') + const doc = path.join(dir, docfile) if (args) { - args = args.map(arg => arg.replace(/%DOC%/g, rootFile.replace(/\.tex$/, '').split(path.sep).join('/')) - .replace(/%DOCFILE%/g, path.basename(rootFile, '.tex').split(path.sep).join('/')) + args = args.map(arg => arg.replace(/%DOC%/g, doc) + .replace(/%DOCFILE%/g, docfile) .replace(/%PDF%/g, pdfFile) .replace(/%LINE%/g, line.toString()) .replace(/%TEX%/g, texFile)) diff --git a/src/components/manager.ts b/src/components/manager.ts index 0107c8a72..930d4f368 100644 --- a/src/components/manager.ts +++ b/src/components/manager.ts @@ -70,14 +70,16 @@ export class Manager { return './' } - const doc = texPath.replace(/\.tex$/, '') - const docfile = path.basename(texPath, '.tex') + const texPathParsed = path.parse(texPath) + const docfile = texPathParsed.name + const dir = path.normalize(texPathParsed.dir).split(path.sep).join('/') + const doc = path.join(dir, docfile) const configuration = vscode.workspace.getConfiguration('latex-workshop') const docker = configuration.get('docker.enabled') const outDir = configuration.get('latex.outDir') as string const out = outDir.replace(/%DOC%/g, docker ? docfile : doc) .replace(/%DOCFILE%/g, docfile) - .replace(/%DIR%/g, docker ? './' : path.dirname(texPath)) + .replace(/%DIR%/g, docker ? './' : dir) .replace(/%TMPDIR%/g, this.extension.builder.tmpDir) return path.normalize(out).split(path.sep).join('/') diff --git a/src/providers/latexformatter.ts b/src/providers/latexformatter.ts index 276d25899..058974b4e 100644 --- a/src/providers/latexformatter.ts +++ b/src/providers/latexformatter.ts @@ -129,14 +129,16 @@ export class LaTexFormatter { const temporaryFile = documentDirectory + path.sep + '__latexindent_temp.tex' fs.writeFileSync(temporaryFile, textToFormat) - const doc = document.fileName.replace(/\.tex$/, '').split(path.sep).join('/') - const docfile = path.basename(document.fileName, '.tex').split(path.sep).join('/') + const fileNameParsed = path.parse(document.fileName) + const docfile = fileNameParsed.name + const dir = path.normalize(fileNameParsed.dir).split(path.sep).join('/') + const doc = path.join(dir, docfile) // generate command line arguments const args = this.formatterArgs.map(arg => arg // taken from ../components/builder.ts .replace(/%DOC%/g, useDocker ? docfile : doc) .replace(/%DOCFILE%/g, docfile) - .replace(/%DIR%/g, useDocker ? '.' : path.dirname(document.fileName).split(path.sep).join('/')) + .replace(/%DIR%/g, useDocker ? '.' : dir) // latexformatter.ts specific tokens .replace(/%TMPFILE%/g, useDocker ? path.basename(temporaryFile) : temporaryFile.split(path.sep).join('/')) .replace(/%INDENT%/g, indent)) From d454bcfade67847459cec4c8c76d3571fb1331e1 Mon Sep 17 00:00:00 2001 From: Jerome Lelong Date: Tue, 31 Mar 2020 17:45:06 +0200 Subject: [PATCH 7/8] Use knit + latexmk to compile .rnw files --- package.json | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 0140af4bf..3f74545f7 100644 --- a/package.json +++ b/package.json @@ -662,7 +662,8 @@ { "name": "Compile Rnw files", "tools": [ - "rnw2pdf" + "rnw2tex", + "latexmk" ] } ], @@ -738,11 +739,11 @@ "env": {} }, { - "name": "rnw2pdf", + "name": "rnw2tex", "command": "Rscript", "args": [ "-e", - "knitr::knit2pdf('%DOCFILE%')" + "knitr::opts_knit$set(concordance = TRUE); knitr::knit('%DOCFILE_EXT%')" ], "env": {} } From 8f632a337cc378e8487cb68d6870a9df221e5729 Mon Sep 17 00:00:00 2001 From: Jerome Lelong Date: Fri, 3 Apr 2020 09:35:50 +0200 Subject: [PATCH 8/8] Refactor the inference of languageId --- src/components/manager.ts | 52 +++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/src/components/manager.ts b/src/components/manager.ts index 930d4f368..e2c218783 100644 --- a/src/components/manager.ts +++ b/src/components/manager.ts @@ -39,6 +39,7 @@ export class Manager { private pdfsWatched: string[] = [] private bibsWatched: string[] = [] private watcherOptions: chokidar.WatchOptions + private rsweaveExt: string[] = ['.rnw', '.Rnw', '.rtex', '.Rtex', '.snw', '.Snw'] constructor(extension: Extension) { this.extension = extension @@ -119,7 +120,7 @@ export class Manager { const ext = path.extname(filename) if (ext === '.tex') { return 'latex' - } else if (['.rnw', 'Rnw', '.rtex', '.Rtex', '.snw', '.Snw'].includes(ext)) { + } else if (this.rsweaveExt.includes(ext)) { return 'rsweave' } else { return undefined @@ -182,16 +183,14 @@ export class Manager { () => this.findRootInWorkspace() ] for (const method of findMethods) { - const res = await method() - const rootFile = res[0] - const languageId = res[1] + const rootFile = await method() if (rootFile === undefined) { continue } if (this.rootFile !== rootFile) { this.extension.logger.addLogMessage(`Root file changed from: ${this.rootFile} to ${rootFile}. Find all dependencies.`) this.rootFile = rootFile - this.rootFileLanguageId = languageId + this.rootFileLanguageId = this.inferLanguageId(rootFile) this.initiateFileWatcher() this.initiateBibWatcher() this.parseFileAndSubs(this.rootFile) // finish the parsing is required for subsequent refreshes. @@ -205,19 +204,19 @@ export class Manager { return undefined } - private findRootFromCurrentRoot(): [string | undefined, string | undefined] { + private findRootFromCurrentRoot(): string | undefined { if (!vscode.window.activeTextEditor || this.rootFile === undefined) { - return [undefined, undefined] + return undefined } if (this.getIncludedTeX().includes(vscode.window.activeTextEditor.document.fileName)) { - return [this.rootFile, vscode.window.activeTextEditor.document.languageId] + return this.rootFile } - return [undefined, undefined] + return undefined } - private findRootFromMagic(): [string | undefined, string | undefined] { + private findRootFromMagic(): string | undefined { if (!vscode.window.activeTextEditor) { - return [undefined, undefined] + return undefined } const regex = /^(?:%\s*!\s*T[Ee]X\sroot\s*=\s*(.*\.tex)$)/m let content = vscode.window.activeTextEditor.document.getText() @@ -241,7 +240,7 @@ export class Manager { file = path.resolve(path.dirname(file), result[1]) if (fileStack.includes(file)) { this.extension.logger.addLogMessage(`Looped root file by magic comment found: ${file}, stop here.`) - return [file, this.inferLanguageId(file)] + return file } else { fileStack.push(file) this.extension.logger.addLogMessage(`Recursively found root file by magic comment: ${file}`) @@ -255,14 +254,14 @@ export class Manager { content = fs.readFileSync(file).toString() result = content.match(regex) } - return [file, this.inferLanguageId(file)] + return file } - return [undefined, undefined] + return undefined } - private findRootFromActive(): [string | undefined, string | undefined] { + private findRootFromActive(): string | undefined { if (!vscode.window.activeTextEditor) { - return [undefined, undefined] + return undefined } const regex = /\\begin{document}/m const content = utils.stripComments(vscode.window.activeTextEditor.document.getText(), '%') @@ -270,16 +269,15 @@ export class Manager { if (result) { const rootSubFile = this.findSubFiles(content) const file = vscode.window.activeTextEditor.document.fileName - const languageId = vscode.window.activeTextEditor.document.languageId if (rootSubFile) { this.localRootFile = file - return [rootSubFile, languageId] + return rootSubFile } else { this.extension.logger.addLogMessage(`Found root file from active editor: ${file}`) - return [file, languageId] + return file } } - return [undefined, undefined] + return undefined } private findSubFiles(content: string): string | undefined { @@ -300,11 +298,11 @@ export class Manager { return undefined } - private async findRootInWorkspace(): Promise<[string | undefined, string | undefined]> { + private async findRootInWorkspace(): Promise { const regex = /\\begin{document}/m if (!this.workspaceRootDir) { - return [undefined, undefined] + return undefined } const configuration = vscode.workspace.getConfiguration('latex-workshop') @@ -323,7 +321,7 @@ export class Manager { const children = this.getTeXChildren(file.fsPath, file.fsPath, [], content) if (vscode.window.activeTextEditor && children.includes(vscode.window.activeTextEditor.document.fileName)) { this.extension.logger.addLogMessage(`Found root file from parent: ${file.fsPath}`) - return [file.fsPath, this.inferLanguageId(file.fsPath)] + return file.fsPath } // Not including the active file, yet can still be a root candidate candidates.push(file.fsPath) @@ -331,10 +329,10 @@ export class Manager { } if (candidates.length > 0) { this.extension.logger.addLogMessage(`Found files that might be root, choose the first one: ${candidates}`) - return [candidates[0], this.inferLanguageId(candidates[0])] + return candidates[0] } } catch (e) {} - return [undefined, undefined] + return undefined } /** @@ -712,7 +710,7 @@ export class Manager { private onWatchingNewFile(file: string) { this.extension.logger.addLogMessage(`Adding ${file} to file watcher.`) - if (['.tex', '.bib', '.rnw', '.Rnw', '.rtex', '.Rtex', '.snw', '.Snw'].includes(path.extname(file)) && + if (['.tex', '.bib'].concat(this.rsweaveExt).includes(path.extname(file)) && !file.includes('expl3-code.tex')) { this.updateCompleterOnChange(file) } @@ -721,7 +719,7 @@ export class Manager { private onWatchedFileChanged(file: string) { this.extension.logger.addLogMessage(`File watcher: responding to change in ${file}`) // It is possible for either tex or non-tex files in the watcher. - if (['.tex', '.bib', '.rnw', '.Rnw', '.rtex', '.Rtex', '.snw', '.Snw'].includes(path.extname(file)) && + if (['.tex', '.bib'].concat(this.rsweaveExt).includes(path.extname(file)) && !file.includes('expl3-code.tex')) { this.parseFileAndSubs(file, true) this.updateCompleterOnChange(file)