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;
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();
$("wordAt").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;
const icons = [
'symbol-file',
'symbol-class',
'symbol-namespace',
'symbol-structure',
'symbol-class',
'symbol-method',
'symbol-property',
'symbol-field',
'symbol-method-arrow',
'symbol-enum',
'symbol-interface',
'symbol-method',
'symbol-variable',
'symbol-constant',
'symbol-string',
'symbol-numeric',
'symbol-boolean',
'symbol-array',
'symbol-structure',
'symbol-key',
'dash',
'symbol-enum-member',
'symbol-misc',
'symbol-event',
'symbol-operator',
'symbol-parameter'
];
$("symList").setData(r, icons);
});
};
$("cmd").onclick = e => {
let cmds = lsp.listCommands(view);
let result="";
[...cmds.keys()].sort().forEach(key => {
result+=`
${key} ${cmds.get(key).key}`
});
$("popHelpInfo").innerHTML=``
$("popHelp").showPopover()
console.log(result)
};
$("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"); };
$("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 = "";
};
function updateSettings(event) {
event.preventDefault();
console.log("COPTS", lsp.curOpts);
const opts = {
lineWrap: $("lineWrap").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 text = rpc.method;
const li = document.createElement("li");
const n = $("traffic").childElementCount + " ";
li.appendChild(document.createTextNode(n + text));
$("traffic").insertBefore(li, $("traffic").firstChild)
};
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;
}
}
}