Skip to content
This repository was archived by the owner on Jul 3, 2026. It is now read-only.

Commit a8947df

Browse files
committed
Improve LSP formatter options and extension handling
1 parent abfed3d commit a8947df

2 files changed

Lines changed: 85 additions & 3 deletions

File tree

src/cm/lsp/clientManager.js

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getIndentUnit, indentUnit } from "@codemirror/language";
12
import {
23
LSPClient,
34
LSPPlugin,
@@ -116,14 +117,18 @@ export class LspClientManager {
116117
const state = await this.#ensureClient(server, context);
117118
const capabilities = state.client.serverCapabilities;
118119
if (!capabilities?.documentFormattingProvider) continue;
120+
state.attach(uri, view);
119121
const plugin = LSPPlugin.get(view);
120122
if (!plugin) continue;
121123
plugin.client.sync();
122124
const edits = await state.client.request("textDocument/formatting", {
123125
textDocument: { uri },
124-
options,
126+
options: buildFormattingOptions(view, options),
125127
});
126-
if (!edits || !edits.length) continue;
128+
if (!edits || !edits.length) {
129+
plugin.client.sync();
130+
return true;
131+
}
127132
const applied = applyTextEdits(plugin, view, edits);
128133
if (applied) {
129134
plugin.client.sync();
@@ -373,6 +378,42 @@ function applyTextEdits(plugin, view, edits) {
373378
return true;
374379
}
375380

381+
function buildFormattingOptions(view, overrides = {}) {
382+
const state = view?.state;
383+
if (!state) return { ...overrides };
384+
385+
const unitValue = state.facet(indentUnit);
386+
const unit =
387+
typeof unitValue === "string" && unitValue.length
388+
? unitValue
389+
: String(unitValue || "\t");
390+
let tabSize = getIndentUnit(state);
391+
if (
392+
typeof tabSize !== "number" ||
393+
!Number.isFinite(tabSize) ||
394+
tabSize <= 0
395+
) {
396+
tabSize = resolveIndentWidth(unit);
397+
}
398+
const insertSpaces = !unit.includes("\t");
399+
400+
return {
401+
tabSize,
402+
insertSpaces,
403+
...overrides,
404+
};
405+
}
406+
407+
function resolveIndentWidth(unit) {
408+
if (typeof unit !== "string" || !unit.length) return 4;
409+
let width = 0;
410+
for (const ch of unit) {
411+
if (ch === "\t") return 4;
412+
width += 1;
413+
}
414+
return width || 4;
415+
}
416+
376417
const defaultManager = new LspClientManager();
377418

378419
export default defaultManager;

src/cm/lsp/formatter.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { getModes } from "cm/modelist";
12
import toast from "components/toast";
23
import lspClientManager from "./clientManager";
34
import serverRegistry from "./serverRegistry";
@@ -17,7 +18,9 @@ export function registerLspFormatter(acode) {
1718
if (lang) languages.add(String(lang));
1819
});
1920
});
20-
const extensions = languages.size ? Array.from(languages) : ["*"];
21+
const extensions = languages.size
22+
? collectFormatterExtensions(languages)
23+
: ["*"];
2124

2225
acode.registerFormatter(
2326
"lsp",
@@ -50,3 +53,41 @@ export function registerLspFormatter(acode) {
5053
"Language Server",
5154
);
5255
}
56+
57+
function collectFormatterExtensions(languages) {
58+
const extensions = new Set();
59+
const modeMap = new Map();
60+
61+
try {
62+
getModes().forEach((mode) => {
63+
const key = String(mode?.name || "")
64+
.trim()
65+
.toLowerCase();
66+
if (key) modeMap.set(key, mode);
67+
});
68+
} catch (_) {}
69+
70+
languages.forEach((language) => {
71+
const key = String(language || "")
72+
.trim()
73+
.toLowerCase();
74+
if (!key) return;
75+
extensions.add(key);
76+
const mode = modeMap.get(key);
77+
if (!mode?.extensions) return;
78+
String(mode.extensions)
79+
.split("|")
80+
.forEach((part) => {
81+
const ext = part.trim();
82+
if (ext && !ext.startsWith("^")) {
83+
extensions.add(ext);
84+
}
85+
});
86+
});
87+
88+
if (!extensions.size) {
89+
return ["*"];
90+
}
91+
92+
return Array.from(extensions);
93+
}

0 commit comments

Comments
 (0)