Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: format with forced mode #264

Merged
merged 2 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/tall-pears-prove.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@marko/language-server": minor
"@marko/language-tools": minor
"marko-vscode": minor
---

Allow formatting with forced mode
2 changes: 1 addition & 1 deletion packages/language-server/src/service/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ const service: Plugin = {

return diagnostics;
},
format: MarkoPlugin.format,
format: MarkoPlugin.format!,
};

function maxRange(a: Range | undefined, b: Range | undefined) {
Expand Down
35 changes: 25 additions & 10 deletions packages/language-server/src/service/marko/format.ts
Original file line number Diff line number Diff line change
@@ -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);
Expand All @@ -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, {
Expand All @@ -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,
Expand All @@ -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);
};
22 changes: 18 additions & 4 deletions packages/language-server/src/service/marko/index.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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<Plugin>;
8 changes: 8 additions & 0 deletions packages/vscode/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down
47 changes: 47 additions & 0 deletions packages/vscode/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import {
type ExtensionContext,
Position,
Range,
TextEdit,
ViewColumn,
WorkspaceEdit,
commands,
window,
workspace,
Expand Down Expand Up @@ -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();
}
Expand All @@ -124,3 +140,34 @@ export function deactivate(): Thenable<void> | 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);
}
Loading