Skip to content

Commit

Permalink
Merge pull request #4397 from James-Yu/context-aware-latex-format
Browse files Browse the repository at this point in the history
When formatting a selection of latex, consider the leading spaces
  • Loading branch information
James-Yu authored Sep 19, 2024
2 parents 00d64a7 + 81bf1ca commit 460246f
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 17 deletions.
26 changes: 22 additions & 4 deletions src/lint/latex-formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,30 @@ class FormattingProvider implements vscode.DocumentFormattingEditProvider, vscod
return undefined
}

public provideDocumentFormattingEdits(document: vscode.TextDocument, _options: vscode.FormattingOptions, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.TextEdit[]> {
return this.formatter?.formatDocument(document) ?? []
public async provideDocumentFormattingEdits(document: vscode.TextDocument, _options: vscode.FormattingOptions, _token: vscode.CancellationToken): Promise<vscode.TextEdit[]> {
const edit = await this.formatter?.formatDocument(document)
if (edit === undefined) {
return []
}
return [ edit ]
}

public provideDocumentRangeFormattingEdits(document: vscode.TextDocument, range: vscode.Range, _options: vscode.FormattingOptions, _token: vscode.CancellationToken): vscode.ProviderResult<vscode.TextEdit[]> {
return this.formatter?.formatDocument(document, range) ?? []
public async provideDocumentRangeFormattingEdits(document: vscode.TextDocument, range: vscode.Range, _options: vscode.FormattingOptions, _token: vscode.CancellationToken): Promise<vscode.TextEdit[]> {
const edit = await this.formatter?.formatDocument(document, range)
if (edit === undefined) {
return []
}
const useSpaces = vscode.window.activeTextEditor?.options.insertSpaces ?? true
const firstLine = document.lineAt(range.start.line)
// Replace all new line characters with new line and spaces, so that
// the indentations are added from the second line.
edit.newText = edit.newText.replaceAll('\n', '\n' + (useSpaces ? ' ' : '\\t').repeat(firstLine.firstNonWhitespaceCharacterIndex))
if (firstLine.firstNonWhitespaceCharacterIndex > range.start.character) {
// \s\s\s|\sf(x)=ax+b
// In this case, the first line need some leading whitespaces.
edit.newText = ' '.repeat(firstLine.firstNonWhitespaceCharacterIndex - range.start.character) + edit.newText
}
return [ edit ]
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/lint/latex-formatter/latexindent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ let formatting: boolean = false

lw.onConfigChange('formatting.latexindent.path', () => formatter = '')

async function formatDocument(document: vscode.TextDocument, range?: vscode.Range): Promise<vscode.TextEdit[]> {
async function formatDocument(document: vscode.TextDocument, range?: vscode.Range): Promise<vscode.TextEdit | undefined> {
if (formatting) {
logger.log('Formatting in progress. Aborted.')
}
Expand All @@ -42,7 +42,7 @@ async function formatDocument(document: vscode.TextDocument, range?: vscode.Rang
formatter = ''
logger.log(`Can not find ${formatter} in PATH: ${process.env.PATH}`)
void logger.showErrorMessage('Can not find latexindent in PATH.')
return []
return undefined
}
}
const edit = await format(document, range)
Expand Down Expand Up @@ -113,7 +113,7 @@ function checkPath(): Thenable<boolean> {
})
}

function format(document: vscode.TextDocument, range?: vscode.Range): Thenable<vscode.TextEdit[]> {
function format(document: vscode.TextDocument, range?: vscode.Range): Thenable<vscode.TextEdit | undefined> {
return new Promise((resolve, _reject) => {
const configuration = vscode.workspace.getConfiguration('latex-workshop')
const useDocker = configuration.get('docker.enabled') as boolean
Expand Down Expand Up @@ -165,24 +165,24 @@ function format(document: vscode.TextDocument, range?: vscode.Range): Thenable<v
void logger.showErrorMessage('Formatting failed. Please refer to LaTeX Workshop Output for details.')
logger.log(`Formatting failed: ${err.message}`)
logger.log(`stderr: ${stderrBuffer.join('')}`)
resolve([])
resolve(undefined)
})
worker.on('close', code => {
removeTemporaryFiles()
if (code !== 0) {
void logger.showErrorMessage('Formatting failed. Please refer to LaTeX Workshop Output for details.')
logger.log(`Formatting failed with exit code ${code}`)
logger.log(`stderr: ${stderrBuffer.join('')}`)
return resolve([])
return resolve(undefined)
}
const stdout = stdoutBuffer.join('')
if (stdout !== '') {
const edit = [vscode.TextEdit.replace(range ?? document.validateRange(new vscode.Range(0, 0, Number.MAX_VALUE, Number.MAX_VALUE)), stdout)]
const edit = vscode.TextEdit.replace(range ?? document.validateRange(new vscode.Range(0, 0, Number.MAX_VALUE, Number.MAX_VALUE)), stdout)
logger.log('Formatted ' + document.fileName)
return resolve(edit)
}

return resolve([])
return resolve(undefined)
})
})
}
10 changes: 5 additions & 5 deletions src/lint/latex-formatter/tex-fmt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const texfmt: LaTeXFormatter = {
formatDocument
}

async function formatDocument(document: vscode.TextDocument, range?: vscode.Range): Promise<vscode.TextEdit[]> {
async function formatDocument(document: vscode.TextDocument, range?: vscode.Range): Promise<vscode.TextEdit | undefined> {
const config = vscode.workspace.getConfiguration('latex-workshop')
const program = config.get('formatting.tex-fmt.path') as string
const args = ['--stdin']
Expand All @@ -23,25 +23,25 @@ async function formatDocument(document: vscode.TextDocument, range?: vscode.Rang
stdout += msg
})

const promise = new Promise<vscode.TextEdit[]>(resolve => {
const promise = new Promise<vscode.TextEdit | undefined>(resolve => {
process.on('error', err => {
logger.logError(`Failed to run ${program}`, err)
logger.showErrorMessage(`Failed to run ${program}. See extension log for more information.`)
resolve([])
resolve(undefined)
})

process.on('exit', code => {
if (code !== 0) {
logger.log(`${program} returned ${code} .`)
logger.showErrorMessage(`${program} returned ${code} . Be cautious on the edits.`)
resolve([])
resolve(undefined)
}
// tex-fmt adds an extra newline at the end
if (stdout.endsWith('\n\n')) {
stdout = stdout.slice(0, -1)
}
logger.log(`Formatted using ${program} .`)
resolve([ vscode.TextEdit.replace(range ?? document.validateRange(new vscode.Range(0, 0, Number.MAX_VALUE, Number.MAX_VALUE)), stdout) ])
resolve(vscode.TextEdit.replace(range ?? document.validateRange(new vscode.Range(0, 0, Number.MAX_VALUE, Number.MAX_VALUE)), stdout))
})
})

Expand Down
2 changes: 1 addition & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export interface LaTeXLinter {
}

export interface LaTeXFormatter {
formatDocument(document: vscode.TextDocument, range?: vscode.Range): Promise<vscode.TextEdit[]>
formatDocument(document: vscode.TextDocument, range?: vscode.Range): Promise<vscode.TextEdit | undefined>
}

export enum TeXElementType { Environment, Macro, Section, SectionAst, SubFile, BibItem, BibField }
Expand Down

0 comments on commit 460246f

Please sign in to comment.