diff --git a/README.md b/README.md index 14bf94e..7850658 100644 --- a/README.md +++ b/README.md @@ -20,14 +20,14 @@ Populate the `custom-format.formatters` setting. // Create our custom formatters "custom-format.formatters": [ { - // Whatever language id you need to format - "language": "javascript", + // Whatever language id you need to format - or a list of languages + "language": ["javascript", "typescript"], // The command that will be run to format files with the language id specified above "command": "node format.js $FILE" // $FILE is replaced with the path of the file to be formatted }, { - "language": "typescript", - "command": "node format-ts.js" + "language": "html", + "command": "node format-html.js" } ], @@ -53,9 +53,10 @@ If there is no content written to `stdout`, error or no error, the formatting of If the command exits with a non-zero code, the formatting of the file will be skipped. -Commands are executed in a subshell, not spawned directly. +Commands are executed in a subshell, not spawned directly, and are provided with the following environment variables: -Commands are provided with the environment variable, `FILE`, which is the absolute path to the file that is being formatted. +* `FILE`, which is the absolute path to the file that is being formatted. +* `FILETYPE`, which is the file type (language) as seen by the editor. Although it is possible to read from and write to `$FILE` directly, it is better to read from `stdin` and write to `stdout` because it mutates the editor state, not the filesystem state, which could differ. diff --git a/src/extension.ts b/src/extension.ts index be8df42..6005bab 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -7,7 +7,7 @@ import { runCommand } from './run-command' interface Formatter { command: string - language: string + language: string | string[] } export function activate(context: ExtensionContext) { @@ -42,27 +42,32 @@ export function activate(context: ExtensionContext) { break } - let disposable = languages.registerDocumentFormattingEditProvider(formatter.language, { - async provideDocumentFormattingEdits(document: TextDocument): Promise { - const rawText = document.getText() - const filename = document.uri.fsPath - const workspaceDir = getCwd(filename) - const formattedText = await runCommand(rawText, formatter.command, filename, workspaceDir) + const languages = Array.isArray(formatter.language) ? formatter.language : [formatter.language] - const lastLineNumber = document.lineCount - 1 - const lastLineChar = document.lineAt(lastLineNumber).text.length + for (let language of languages) { + let disposable = languages.registerDocumentFormattingEditProvider(language, { + async provideDocumentFormattingEdits(document: TextDocument): Promise { + const rawText = document.getText() + const filename = document.uri.fsPath + const filetype = document.languageId + const workspaceDir = getCwd(filename) + const formattedText = await runCommand(rawText, formatter.command, filename, filetype, workspaceDir) - const startPos = new Position(0, 0) - const endPos = new Position(lastLineNumber, lastLineChar) - const replaceRange = new Range(startPos, endPos) + const lastLineNumber = document.lineCount - 1 + const lastLineChar = document.lineAt(lastLineNumber).text.length - return [TextEdit.replace(replaceRange, formattedText)] - }, - }) + const startPos = new Position(0, 0) + const endPos = new Position(lastLineNumber, lastLineChar) + const replaceRange = new Range(startPos, endPos) - listeningLanguages.push(formatter.language) + return [TextEdit.replace(replaceRange, formattedText)] + }, + }) - context.subscriptions.push(disposable) + listeningLanguages.push(language) + + context.subscriptions.push(disposable) + } } log(`Formatting activated for the following languages: [${listeningLanguages.toLocaleString()}]`) diff --git a/src/run-command.ts b/src/run-command.ts index 73888ca..95f8c5e 100644 --- a/src/run-command.ts +++ b/src/run-command.ts @@ -12,12 +12,13 @@ function stripColor(input: string): string { return input.replace(regex, '') } -export async function runCommand(text: string, command: string, filename: string, workspacePath: string): Promise { - const args = command.replace(/\$FILE/g, filename).split(' ') - const file = args.shift() - - if (!file) return text - +export async function runCommand( + text: string, + command: string, + filename: string, + filetype: string, + workspacePath: string +): Promise { const errorOut = (error: string) => { logError(`Received an error while formatting ${filename}:\n> ${command}\nError:\n> ${error.replace(/\n/g, '\n> ')}`) } @@ -31,7 +32,7 @@ export async function runCommand(text: string, command: string, filename: string const child = childProcess.exec( command, - { cwd: workspacePath, env: { ...process.env, FILE: filename }, shell: process.env.SHELL }, + { cwd: workspacePath, env: { ...process.env, FILE: filename, FILETYPE: filetype }, shell: process.env.SHELL }, (error, stdout, stderr) => { if (error) { if (!didReject) reject(error)