const view = new lsp.EditorView({ extensions: lsp.baseExts, parent: document.getElementById("editor") }); let doc = "xquery version '3.1';\n(:~ comment:)\nmodule namespace pdfbox='ns';\n"; var client; var extLint; var workspace={ "file:///some/file.xqm":null }; 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; let svr = localStorage.getItem('lsp'); if (!svr) { let x = new URL(window.location.href); x.protocol = "ws"; x.pathname = "ws/lsp" svr = x.href; } $("iServer").value = svr; formFromStore('fSettings'); view.setState(lsp.EditorState.create({ doc: doc, extensions: lsp.baseExts })); lsp.updateCompartment(objectFromForm('fSettings')) 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); localStorage.setItem('lsp', $("iServer").value); }); $("connect").onclick = e => { e.preventDefault(); connect() }; $("search").onclick = e => lsp.openSearchPanel(view); $("fullscreen").onclick = e => $("editor").requestFullscreen(); $("bnWordAt").onclick = e => { let pos = view.state.selection.main.head; let w = view.state.wordAt(pos); alert("wordAt " + JSON.stringify(w)); }; $("symbols2").onclick = e => { client.sync(); client.request("textDocument/documentSymbol", { "textDocument": { "uri": $("iFile").value } }) .then(r => { console.log("symbols", r) $("symPanel").open = true; $("symList").setData(r); }); }; $("cmdList").onclick = e => { let cmds = lsp.listCommands(view); let result=""; [...cmds.keys()].sort().forEach(key => { result+=`
  • ${key} ${cmds.get(key).key}
  • ` }); $("popHelpInfo").innerHTML=`` $("popCmds").showPopover() }; $("symList").addEventListener("itemSelected", e => { const sel=e.detail.selectionRange; console.log("SYM selection range",sel); const an=17*e.detail.kind view.dispatch({selection: {anchor: an,head:an+34},scrollIntoView:true}); }); $("lint").onclick = async e => { console.log("word", view.state.wordAt(1)); lsp.openLintPanel(view); }; $("sync").onclick = e => { client.sync(); console.log("XXXsync"); }; // state a state $("bnSave").onclick = e => { workspace[iFile]=view.state; }; $("bnLoad").onclick = e => { const v=workspace[iFile];if(v)view.setState(v)}; // select local file $("bnRead").onclick = e => { $("fileElem").click(); }; $("fileElem").onchange= e=> { let fr = new FileReader(); fr.onload = function () { alert( fr.result); } fr.readAsText(e.target.files[0]); }; $("format").onclick = e => { console.log("FMT", lsp.formatDocument(view));}; $("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 = ""; }; $("msgIcon").onclick=e=>{ e.preventDefault(); alert("NOT YET") }; function updateSettings(event) { event.preventDefault(); console.log("COPTS", lsp.curOpts); const opts = { lineWrap: $("lineWrap").checked, highlightWhitespace: $("highlightWhitespace").checked, minimap: $("minimap").checked } console.log(opts) lsp.updateCompartment(opts); $('popSettings').hidePopover(); formToStore("fSettings"); }; $("fSettings").addEventListener("submit", updateSettings); function connect() { const server = $("iServer").value; const file = $("iFile").value; lsp.simpleWebSocketTransport(server) .then(transport => { transport.socket.onclose = (event) => connectStatus(false); transport.socket.oneror = (event) => $("msg").innerText = "sock error!"; transport.subscribe(incoming); client = new lsp.LSPClient({ extensions: lsp.languageServerExtensions() }); client.connect(transport); $("popConnect").hidePopover(); connectStatus(true); let extLsp = client.plugin(file, "xquery"); view.dispatch({ effects: lsp.StateEffect.appendConfig.of( [lsp.linter(null, { autoPanel: true }), ...extLsp, lsp.keymap.of([...lsp.formatKeymap])]) }) }) .catch(e => { console.log(e); connectStatus(false); alert("connection failed: " + server) }); }; function connectStatus(bool) { if (bool) { $("popcon").querySelector("i").classList.value = "codicon codicon-vm-active"; $("popcon").classList.remove("btn-danger") $("popcon").classList.add("btn-success") } else { $("popcon").querySelector("i").classList.value = "codicon codicon-vm-outline"; $("popcon").classList.add("btn-danger") $("popcon").classList.remove("btn-success") } }; function incoming(msg) { const rpc = JSON.parse(msg); log(rpc); }; function log(rpc) { console.log("<-", rpc) if (rpc.id) return; const when=(new Date()).toISOString(); const msg = {name:rpc.method, detail:when.substring(1+when.indexOf("T")), kind:23 /* event */ }; //name,details,kind $("msgList").setData([msg],true) }; function formFromStore(name) { let v = localStorage.getItem(name) if (!!v) formDeserialize($(name), v); }; function formToStore(name) { localStorage.setItem(name, formSerialize($(name))); }; function objectFromForm(name) { const data = new FormData($(name)); //https://stackabuse.com/convert-form-data-to-javascript-object/ return Object.fromEntries(data.entries()); } function formSerialize(form) { const data = new FormData(form); //https://stackoverflow.com/a/44033425/1869660 return new URLSearchParams(data).toString(); } function formDeserialize(form, data) { const entries = (new URLSearchParams(data)).entries(); for (const [key, val] of entries) { //http://javascript-coder.com/javascript-form/javascript-form-value.phtml const input = form.elements[key]; switch (input.type) { case 'checkbox': input.checked = !!val; break; default: input.value = val; break; } } }