basex-lsp/bundles/src/lsp.js
2025-08-22 17:37:26 +01:00

107 lines
No EOL
3.5 KiB
JavaScript

import { EditorState } from '@codemirror/state';
import { openSearchPanel, highlightSelectionMatches, searchKeymap } from '@codemirror/search';
import { openLintPanel, lintGutter, lintKeymap, linter, setDiagnostics, } from "@codemirror/lint"
import { indentWithTab, history, defaultKeymap, historyKeymap } from '@codemirror/commands';
import { foldGutter, indentOnInput, indentUnit, bracketMatching, foldKeymap, syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language';
import { closeBrackets, autocompletion, closeBracketsKeymap, completionKeymap } from '@codemirror/autocomplete';
import { lineNumbers, highlightActiveLineGutter, highlightSpecialChars, drawSelection, dropCursor, rectangularSelection, crosshairCursor, highlightActiveLine, keymap, EditorView } from '@codemirror/view';
// Theme
import { oneDark } from "@codemirror/theme-one-dark";
import { LSPClient, LSPPlugin, languageServerSupport } from "@codemirror/lsp-client";
// Language
import { xml } from "@codemirror/lang-xml";
// return promise with socket map or reject if no connect
function simpleWebSocketTransport(uri) {
let handlers = [];
return new Promise(function (resolve, reject) {
let sock = new WebSocket(uri);
sock.onmessage = e => { for (let h of handlers) h(e.data.toString()); };
sock.onerror = e => reject(e);
sock.onopen = () => resolve({
socket: sock,
send: (message) => sock.send(message),
subscribe: (handler) => handlers.push(handler),
unsubscribe: (handler) => handlers = handlers.filter(h => h != handler)
});
}
);
};
const baseExts = [
lineNumbers(),
highlightActiveLineGutter(),
highlightSpecialChars(),
history(),
foldGutter(),
lintGutter(),
drawSelection(),
indentUnit.of(" "),
EditorState.allowMultipleSelections.of(true),
EditorView.lineWrapping,
indentOnInput(),
bracketMatching(),
closeBrackets(),
autocompletion(),
rectangularSelection(),
crosshairCursor(),
highlightActiveLine(),
highlightSelectionMatches(),
keymap.of([
indentWithTab,
...closeBracketsKeymap,
...defaultKeymap,
...historyKeymap,
...foldKeymap,
...completionKeymap,
...searchKeymap,
...lintKeymap
]),
xml(),
syntaxHighlighting(defaultHighlightStyle, { fallback: true })
];
function createEditorState(initialContents, extensions, options = {}) {
if (options.oneDark)
extensions.push(oneDark);
return EditorState.create({
doc: initialContents,
extensions
});
}
function createEditorView(state, parent) {
return new EditorView({ state, parent });
}
class xqLinter {
constructor(parameters) {
this.fred = parameters;
}
}
function debouncedChangeListener({ delay = 750, onChange }) {
let timeoutId = null;
let lastContent = '';
return EditorView.updateListener.of(update => {
if (update.docChanged) {
const currentContent = update.state.doc.toString();
if (timeoutId) {
clearTimeout(timeoutId);
}
timeoutId = setTimeout(() => {
if (currentContent !== lastContent) {
lastContent = currentContent;
onChange(currentContent, update.state);
}
}, delay);
}
});
}
export { createEditorState, createEditorView, openSearchPanel, openLintPanel, languageServerSupport, baseExts, simpleWebSocketTransport, linter, LSPPlugin, setDiagnostics, xqLinter, LSPClient,debouncedChangeListener };