const view = new lsp.EditorView({ extensions: lsp.baseExts, parent:document.getElementById("editor") }); let doc = `3+1`; var client; var extLint; function $(id) { return document.getElementById(id) }; // Load saved content from localStorage when the page loads window.addEventListener('load', () => { const savedText = localStorage.getItem('code'); if (savedText) { doc = savedText; } view.setState(lsp.EditorState.create({doc:doc, extensions: lsp.baseExts})); connect(); }); // Save content to localStorage when the page is about to unload window.addEventListener('beforeunload', () => { const doc = view.state.doc.toString(); localStorage.setItem('code', doc); }); $("connect").onclick = e => { e.preventDefault();connect()}; $("search").onclick = e => lsp.openSearchPanel(view); $("format").onclick = e => console.log("CMDS",lsp.listCommands(view)); $("lint").onclick = async e => { console.log("word", view.state.wordAt(1)); lsp.openLintPanel(view); }; $("sync").onclick = e => { client.sync(); console.log("XXXsync");}; $("load").onchange = e => { const url = e.target.value; if (url.length == 0) return fetch(url) .then(response => response.text()) .then(t => { view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: t } }) client.sync(); console.log("SYNC"); }); $("load").value = ""; }; function connect() { const server = $("iServer").value; const file = $("iFile").value; lsp.simpleWebSocketTransport(server) .then(transport => { transport.subscribe(incoming); transport.socket.onclose = (event) => connectStatus(false); transport.socket.oneror = (event) => $("msg").innerText = "sock error!"; client = new lsp.LSPClient().connect(transport); $("popConnect").hidePopover(); connectStatus(true); let extLsp = lsp.languageServerSupport(client, file, "xquery"); extLint = lsp.linter(null,{ autoPanel: true }); const doc = view.state.doc.toString(); const exts=[...lsp.baseExts, extLsp, extLint, lsp.debouncedChangeListener({ delay: 750, onChange: (content, state) => { console.log('Debounced change detected:'+content); client.sync(); }}) ]; const state =lsp.EditorState.create({doc: doc,extensions:exts}) view.setState(state); }) .catch(r => { connectStatus(false); alert("connection failed: " + server) }); }; function connectStatus(bool) { if (bool) { $("popcon").classList.remove("btn-danger") $("popcon").classList.add("btn-success") } else { $("popcon").classList.add("btn-danger") $("popcon").classList.remove("btn-success") } }; function incoming(msg) { const rpc = JSON.parse(msg); log(rpc); switch (rpc.method) { case "textDocument/publishDiagnostics": diags(rpc.params); break; default: return; } }; function log(rpc) { if (rpc.id) return const text = rpc.method; const li = document.createElement("li"); li.appendChild(document.createTextNode(text)); $("traffic").insertBefore(li, $("traffic").firstChild) }; function diags(params) { console.log("--", params) let plugin = lsp.LSPPlugin.get(view); const severities = ["error", "warning", "info", "hint"] // const diagnostics = params.diagnostics .map(({ range, message, severity, code }) => ({ from: plugin.fromPosition(range.start, view.state.doc), to: plugin.fromPosition(range.end, view.state.doc), severity: severities[severity - 1], message: ((typeof code === 'undefined') ? "" : `[${code}] `) + message, })) .filter( ({ from, to }) => from !== null && to !== null && from !== undefined && to !== undefined, ) .sort((a, b) => { switch (true) { case a.from < b.from: return -1; case a.from > b.from: return 1; } return 0; }); view.dispatch(lsp.setDiagnostics(view.state, diagnostics)); };