From d278c5de3b68c58921c6fa338090cb332bf97259 Mon Sep 17 00:00:00 2001 From: LuLaValva Date: Thu, 28 Mar 2024 13:18:10 -0700 Subject: [PATCH 1/2] feat: format with forced mode --- packages/language-server/src/service/index.ts | 2 +- .../src/service/marko/format.ts | 35 ++++++++++---- .../src/service/marko/index.ts | 22 +++++++-- packages/vscode/package.json | 8 ++++ packages/vscode/src/index.ts | 47 +++++++++++++++++++ 5 files changed, 99 insertions(+), 15 deletions(-) diff --git a/packages/language-server/src/service/index.ts b/packages/language-server/src/service/index.ts index b7ca3587..9a7a71fd 100644 --- a/packages/language-server/src/service/index.ts +++ b/packages/language-server/src/service/index.ts @@ -308,7 +308,7 @@ const service: Plugin = { return diagnostics; }, - format: MarkoPlugin.format, + format: MarkoPlugin.format!, }; function maxRange(a: Range | undefined, b: Range | undefined) { diff --git a/packages/language-server/src/service/marko/format.ts b/packages/language-server/src/service/marko/format.ts index 533a01db..96175edc 100644 --- a/packages/language-server/src/service/marko/format.ts +++ b/packages/language-server/src/service/marko/format.ts @@ -1,14 +1,25 @@ -import { TextEdit } from "vscode-languageserver"; +import { Project } from "@marko/language-tools"; import * as prettier from "prettier"; import * as markoPrettier from "prettier-plugin-marko"; -import { Project } from "@marko/language-tools"; +import { CancellationToken, TextEdit } from "vscode-languageserver"; +import { TextDocument } from "vscode-languageserver-textdocument"; import { START_POSITION } from "../../utils/constants"; -import { displayError } from "../../utils/messages"; import { getFSDir, getFSPath } from "../../utils/file"; +import { displayError } from "../../utils/messages"; import type { Plugin } from "../types"; -export const format: Plugin["format"] = async (doc, params, cancel) => { +export interface FormatOptions { + tabSize: number; + insertSpaces: boolean; + mode?: "concise" | "html"; +} + +export async function formatDocument( + doc: TextDocument, + formatOptions: FormatOptions, + cancel?: CancellationToken, +) { try { const dir = getFSDir(doc); const filepath = getFSPath(doc); @@ -17,8 +28,9 @@ export const format: Plugin["format"] = async (doc, params, cancel) => { parser: "marko", filepath, plugins: [markoPrettier], - tabWidth: params.options.tabSize, - useTabs: params.options.insertSpaces === false, + tabWidth: formatOptions.tabSize, + useTabs: formatOptions.insertSpaces === false, + markoSyntax: formatOptions.mode ?? "auto", ...(filepath ? await prettier .resolveConfig(filepath, { @@ -28,12 +40,12 @@ export const format: Plugin["format"] = async (doc, params, cancel) => { : null), }; - if (cancel.isCancellationRequested) return; - markoPrettier.setCompiler(Project.getCompiler(dir), Project.getConfig(dir)); + if (cancel?.isCancellationRequested) return; + // TODO: format selection - const ret = [ + return [ TextEdit.replace( { start: START_POSITION, @@ -42,8 +54,11 @@ export const format: Plugin["format"] = async (doc, params, cancel) => { await prettier.format(text, options), ), ]; - return ret; } catch (e) { displayError(e); } +} + +export const format: Plugin["format"] = async (doc, params, cancel) => { + return formatDocument(doc, params.options, cancel); }; diff --git a/packages/language-server/src/service/marko/index.ts b/packages/language-server/src/service/marko/index.ts index 514d53bb..12fbdc36 100644 --- a/packages/language-server/src/service/marko/index.ts +++ b/packages/language-server/src/service/marko/index.ts @@ -1,12 +1,13 @@ import type { Plugin } from "../types"; +import * as documents from "../../utils/text-documents"; import { doComplete } from "./complete"; -import { doValidate } from "./validate"; -import { doHover } from "./hover"; import { findDefinition } from "./definition"; import { findDocumentLinks } from "./document-links"; import { findDocumentSymbols } from "./document-symbols"; -import { format } from "./format"; +import { FormatOptions, format, formatDocument } from "./format"; +import { doHover } from "./hover"; +import { doValidate } from "./validate"; export default { doComplete, @@ -16,4 +17,17 @@ export default { findDocumentLinks, findDocumentSymbols, format, -} as Plugin; + commands: { + "$/formatWithMode": async ({ + doc: docURI, + options, + }: { + doc: string; + options: FormatOptions; + }) => { + const doc = documents.get(docURI)!; + const formatted = await formatDocument(doc, options); + return formatted; + }, + }, +} as Partial; diff --git a/packages/vscode/package.json b/packages/vscode/package.json index db1e61ca..f9a24a7a 100644 --- a/packages/vscode/package.json +++ b/packages/vscode/package.json @@ -31,6 +31,14 @@ { "command": "marko.showHtmlOutput", "title": "Marko: Debug: Show Extracted Static HTML Output" + }, + { + "command": "marko.formatToConciseMode", + "title": "Marko: Format: Force Concise Mode" + }, + { + "command": "marko.formatToHtmlMode", + "title": "Marko: Format: Force Html Mode" } ], "typescriptServerPlugins": [ diff --git a/packages/vscode/src/index.ts b/packages/vscode/src/index.ts index 639c5e53..fa40de0f 100644 --- a/packages/vscode/src/index.ts +++ b/packages/vscode/src/index.ts @@ -1,6 +1,10 @@ import { type ExtensionContext, + Position, + Range, + TextEdit, ViewColumn, + WorkspaceEdit, commands, window, workspace, @@ -113,6 +117,18 @@ export async function activate(ctx: ExtensionContext) { }), ); + ctx.subscriptions.push( + commands.registerCommand("marko.formatToConciseMode", async () => { + formatForced("concise"); + }), + ); + + ctx.subscriptions.push( + commands.registerCommand("marko.formatToHtmlMode", async () => { + formatForced("html"); + }), + ); + // Start the client. This will also launch the server await client.start(); } @@ -124,3 +140,34 @@ export function deactivate(): Thenable | void { return client.stop(); } + +async function formatForced(mode: "concise" | "html") { + const { activeTextEditor } = window; + if (!activeTextEditor) { + window.showErrorMessage("No open Marko file detected for formatting"); + return; + } + const edits: TextEdit[] = await client.sendRequest("$/formatWithMode", { + doc: activeTextEditor.document.uri.toString(), + options: { + tabSize: activeTextEditor.options.tabSize, + insertSpaces: activeTextEditor.options.insertSpaces, + mode, + }, + }); + + const workspaceEdit = new WorkspaceEdit(); + + for (const edit of edits) { + workspaceEdit.replace( + activeTextEditor.document.uri, + new Range( + new Position(edit.range.start.line, edit.range.start.character), + new Position(edit.range.end.line, edit.range.end.character), + ), + edit.newText, + ); + } + + await workspace.applyEdit(workspaceEdit); +} From 4b8b7236697bfc5a8c708b387060ac9cac3dd6fd Mon Sep 17 00:00:00 2001 From: LuLaValva Date: Thu, 28 Mar 2024 13:21:13 -0700 Subject: [PATCH 2/2] chore: add changeset --- .changeset/tall-pears-prove.md | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 .changeset/tall-pears-prove.md diff --git a/.changeset/tall-pears-prove.md b/.changeset/tall-pears-prove.md new file mode 100644 index 00000000..4bcd5743 --- /dev/null +++ b/.changeset/tall-pears-prove.md @@ -0,0 +1,7 @@ +--- +"@marko/language-server": minor +"@marko/language-tools": minor +"marko-vscode": minor +--- + +Allow formatting with forced mode