[add] initial handler stuff
This commit is contained in:
parent
7deb653208
commit
9533519b8a
10 changed files with 284 additions and 187 deletions
56
webapp/lsp/handlers.xqm
Normal file
56
webapp/lsp/handlers.xqm
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
(: tools to analyse xml parse tree
|
||||
@author Andy Bunce
|
||||
:)
|
||||
module namespace hnd="lsp/handlers";
|
||||
import module namespace pos="lsp/position" at "position.xqm";
|
||||
|
||||
declare record hnd:hand(
|
||||
result as item()*,
|
||||
skipchildren as xs:boolean
|
||||
);
|
||||
|
||||
declare function hnd:default-handler($el as element(*),$state)
|
||||
as function(*){
|
||||
fn(){hnd:hand($state,false())}
|
||||
};
|
||||
|
||||
declare function hnd:get-handler($el as element(*),$state)
|
||||
as function(*)
|
||||
{ function-lookup(xs:QName(name($el)),2)
|
||||
otherwise hnd:default-handler($el,$state)
|
||||
};
|
||||
|
||||
declare function hnd:diags($parse as element(),$diags:=())
|
||||
{
|
||||
let $h:= hnd:get-handler($parse,$diags)($parse,$diags)
|
||||
return if($h?skipchildren)
|
||||
then $h?result
|
||||
else fold-left($parse/*,$diags,
|
||||
fn($r,$this){
|
||||
hnd:diags($this,$r)
|
||||
})
|
||||
};
|
||||
|
||||
declare record hnd:symbol (
|
||||
name as xs:string,
|
||||
type as xs:string,
|
||||
range-name? as pos:Range,
|
||||
range-full? as pos:Range,
|
||||
children? as array(hnd:symbol)
|
||||
);
|
||||
|
||||
declare function hnd:symbols($parse as element(),$syms as hnd:symbol* :=() )
|
||||
{
|
||||
'todo'
|
||||
};
|
||||
|
||||
declare function hnd:anotated-declaration($parse as element(),$syms)
|
||||
as hnd:hand
|
||||
{
|
||||
let $sym:=hnd:symbol(
|
||||
$parse/token,
|
||||
"AA"
|
||||
)
|
||||
return hnd:hand(($syms,$sym),true())
|
||||
};
|
||||
|
||||
|
|
@ -8075,6 +8075,29 @@ var lsp = (function (exports) {
|
|||
return pos;
|
||||
}
|
||||
}
|
||||
function skipAtomsForSelection(atoms, sel) {
|
||||
let ranges = null;
|
||||
for (let i = 0; i < sel.ranges.length; i++) {
|
||||
let range = sel.ranges[i], updated = null;
|
||||
if (range.empty) {
|
||||
let pos = skipAtomicRanges(atoms, range.from, 0);
|
||||
if (pos != range.from)
|
||||
updated = EditorSelection.cursor(pos, -1);
|
||||
}
|
||||
else {
|
||||
let from = skipAtomicRanges(atoms, range.from, -1);
|
||||
let to = skipAtomicRanges(atoms, range.to, 1);
|
||||
if (from != range.from || to != range.to)
|
||||
updated = EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
|
||||
}
|
||||
if (updated) {
|
||||
if (!ranges)
|
||||
ranges = sel.ranges.slice();
|
||||
ranges[i] = updated;
|
||||
}
|
||||
}
|
||||
return ranges ? EditorSelection.create(ranges, sel.mainIndex) : sel;
|
||||
}
|
||||
function skipAtoms(view, oldPos, pos) {
|
||||
let newPos = skipAtomicRanges(view.state.facet(atomicRanges).map(f => f(view)), pos.from, oldPos.head > pos.from ? -1 : 1);
|
||||
return newPos == pos.from ? pos : EditorSelection.cursor(newPos, newPos < pos.from ? 1 : -1);
|
||||
|
|
@ -8310,6 +8333,8 @@ var lsp = (function (exports) {
|
|||
if (view.inputState.lastSelectionOrigin == "select")
|
||||
scrollIntoView = true;
|
||||
userEvent = view.inputState.lastSelectionOrigin;
|
||||
if (userEvent == "select.pointer")
|
||||
newSel = skipAtomsForSelection(view.state.facet(atomicRanges).map(f => f(view)), newSel);
|
||||
}
|
||||
view.dispatch({ selection: newSel, scrollIntoView, userEvent });
|
||||
return true;
|
||||
|
|
@ -8787,31 +8812,8 @@ var lsp = (function (exports) {
|
|||
if (this.dragging === false)
|
||||
this.select(this.lastEvent);
|
||||
}
|
||||
skipAtoms(sel) {
|
||||
let ranges = null;
|
||||
for (let i = 0; i < sel.ranges.length; i++) {
|
||||
let range = sel.ranges[i], updated = null;
|
||||
if (range.empty) {
|
||||
let pos = skipAtomicRanges(this.atoms, range.from, 0);
|
||||
if (pos != range.from)
|
||||
updated = EditorSelection.cursor(pos, -1);
|
||||
}
|
||||
else {
|
||||
let from = skipAtomicRanges(this.atoms, range.from, -1);
|
||||
let to = skipAtomicRanges(this.atoms, range.to, 1);
|
||||
if (from != range.from || to != range.to)
|
||||
updated = EditorSelection.range(range.from == range.anchor ? from : to, range.from == range.head ? from : to);
|
||||
}
|
||||
if (updated) {
|
||||
if (!ranges)
|
||||
ranges = sel.ranges.slice();
|
||||
ranges[i] = updated;
|
||||
}
|
||||
}
|
||||
return ranges ? EditorSelection.create(ranges, sel.mainIndex) : sel;
|
||||
}
|
||||
select(event) {
|
||||
let { view } = this, selection = this.skipAtoms(this.style.get(event, this.extend, this.multiple));
|
||||
let { view } = this, selection = skipAtomsForSelection(this.atoms, this.style.get(event, this.extend, this.multiple));
|
||||
if (this.mustSelect || !selection.eq(view.state.selection, this.dragging === false))
|
||||
this.view.dispatch({
|
||||
selection,
|
||||
|
|
@ -8964,6 +8966,9 @@ var lsp = (function (exports) {
|
|||
return mouseSel.dragging === false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
view.inputState.setSelectionOrigin("select.pointer");
|
||||
}
|
||||
return false;
|
||||
};
|
||||
function rangeForClick(view, pos, bias, type) {
|
||||
|
|
@ -12288,7 +12293,7 @@ var lsp = (function (exports) {
|
|||
}
|
||||
/**
|
||||
Find the line block (see
|
||||
[`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt) at the given
|
||||
[`lineBlockAt`](https://codemirror.net/6/docs/ref/#view.EditorView.lineBlockAt)) at the given
|
||||
height, again interpreted relative to the [top of the
|
||||
document](https://codemirror.net/6/docs/ref/#view.EditorView.documentTop).
|
||||
*/
|
||||
|
|
@ -13075,7 +13080,7 @@ var lsp = (function (exports) {
|
|||
// Ctrl-Alt may be used for AltGr on Windows
|
||||
!(browser.windows && event.ctrlKey && event.altKey) &&
|
||||
// Alt-combinations on macOS tend to be typed characters
|
||||
!(browser.mac && event.altKey && !event.ctrlKey) &&
|
||||
!(browser.mac && event.altKey && !(event.ctrlKey || event.metaKey)) &&
|
||||
(baseName = base[event.keyCode]) && baseName != name) {
|
||||
if (runFor(scopeObj[prefix + modifiers(baseName, event, true)])) {
|
||||
handled = true;
|
||||
|
|
@ -23971,16 +23976,20 @@ var lsp = (function (exports) {
|
|||
*/
|
||||
function insertCompletionText(state, text, from, to) {
|
||||
let { main } = state.selection, fromOff = from - main.from, toOff = to - main.from;
|
||||
return Object.assign(Object.assign({}, state.changeByRange(range => {
|
||||
if (range != main && from != to &&
|
||||
state.sliceDoc(range.from + fromOff, range.from + toOff) != state.sliceDoc(from, to))
|
||||
return { range };
|
||||
let lines = state.toText(text);
|
||||
return {
|
||||
changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: lines },
|
||||
range: EditorSelection.cursor(range.from + fromOff + lines.length)
|
||||
};
|
||||
})), { scrollIntoView: true, userEvent: "input.complete" });
|
||||
return {
|
||||
...state.changeByRange(range => {
|
||||
if (range != main && from != to &&
|
||||
state.sliceDoc(range.from + fromOff, range.from + toOff) != state.sliceDoc(from, to))
|
||||
return { range };
|
||||
let lines = state.toText(text);
|
||||
return {
|
||||
changes: { from: range.from + fromOff, to: to == main.from ? range.to : range.from + toOff, insert: lines },
|
||||
range: EditorSelection.cursor(range.from + fromOff + lines.length)
|
||||
};
|
||||
}),
|
||||
scrollIntoView: true,
|
||||
userEvent: "input.complete"
|
||||
};
|
||||
}
|
||||
const SourceCache = /*@__PURE__*/new WeakMap();
|
||||
function asSource(source) {
|
||||
|
|
@ -24625,7 +24634,7 @@ var lsp = (function (exports) {
|
|||
}, prev ? prev.timestamp : Date.now(), selected, false);
|
||||
}
|
||||
map(changes) {
|
||||
return new CompletionDialog(this.options, this.attrs, Object.assign(Object.assign({}, this.tooltip), { pos: changes.mapPos(this.tooltip.pos) }), this.timestamp, this.selected, this.disabled);
|
||||
return new CompletionDialog(this.options, this.attrs, { ...this.tooltip, pos: changes.mapPos(this.tooltip.pos) }, this.timestamp, this.selected, this.disabled);
|
||||
}
|
||||
setDisabled() {
|
||||
return new CompletionDialog(this.options, this.attrs, this.tooltip, this.timestamp, this.selected, true);
|
||||
|
|
@ -24810,7 +24819,10 @@ var lsp = (function (exports) {
|
|||
if (!(result instanceof ActiveResult))
|
||||
return false;
|
||||
if (typeof apply == "string")
|
||||
view.dispatch(Object.assign(Object.assign({}, insertCompletionText(view.state, apply, result.from, result.to)), { annotations: pickedCompletion.of(option.completion) }));
|
||||
view.dispatch({
|
||||
...insertCompletionText(view.state, apply, result.from, result.to),
|
||||
annotations: pickedCompletion.of(option.completion)
|
||||
});
|
||||
else
|
||||
apply(view, option.completion, result.from, result.to);
|
||||
return true;
|
||||
|
|
@ -25227,7 +25239,7 @@ var lsp = (function (exports) {
|
|||
let fields = [];
|
||||
let lines = [], positions = [], m;
|
||||
for (let line of template.split(/\r\n?|\n/)) {
|
||||
while (m = /[#$]\{(?:(\d+)(?::([^}]*))?|((?:\\[{}]|[^}])*))\}/.exec(line)) {
|
||||
while (m = /[#$]\{(?:(\d+)(?::([^{}]*))?|((?:\\[{}]|[^{}])*))\}/.exec(line)) {
|
||||
let seq = m[1] ? +m[1] : null, rawName = m[2] || m[3] || "", found = -1;
|
||||
let name = rawName.replace(/\\[{}]/g, m => m[1]);
|
||||
for (let i = 0; i < fields.length; i++) {
|
||||
|
|
@ -25244,6 +25256,12 @@ var lsp = (function (exports) {
|
|||
if (pos.field >= found)
|
||||
pos.field++;
|
||||
}
|
||||
for (let pos of positions)
|
||||
if (pos.line == lines.length && pos.from > m.index) {
|
||||
let snip = m[2] ? 3 + (m[1] || "").length : 2;
|
||||
pos.from -= snip;
|
||||
pos.to -= snip;
|
||||
}
|
||||
positions.push(new FieldPos(found, lines.length, m.index, m.index + name.length));
|
||||
line = line.slice(0, m.index) + rawName + line.slice(m.index + m[0].length);
|
||||
}
|
||||
|
|
@ -25273,7 +25291,7 @@ var lsp = (function (exports) {
|
|||
constructor(ranges, active) {
|
||||
this.ranges = ranges;
|
||||
this.active = active;
|
||||
this.deco = Decoration.set(ranges.map(r => (r.from == r.to ? fieldMarker : fieldRange).range(r.from, r.to)));
|
||||
this.deco = Decoration.set(ranges.map(r => (r.from == r.to ? fieldMarker : fieldRange).range(r.from, r.to)), true);
|
||||
}
|
||||
map(changes) {
|
||||
let ranges = [];
|
||||
|
|
@ -25690,17 +25708,18 @@ var lsp = (function (exports) {
|
|||
/**
|
||||
Basic keybindings for autocompletion.
|
||||
|
||||
- Ctrl-Space (and Alt-\` on macOS): [`startCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.startCompletion)
|
||||
- Ctrl-Space (and Alt-\` or Alt-i on macOS): [`startCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.startCompletion)
|
||||
- Escape: [`closeCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.closeCompletion)
|
||||
- ArrowDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true)`
|
||||
- ArrowUp: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(false)`
|
||||
- PageDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true, "page")`
|
||||
- PageDown: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(true, "page")`
|
||||
- PageUp: [`moveCompletionSelection`](https://codemirror.net/6/docs/ref/#autocomplete.moveCompletionSelection)`(false, "page")`
|
||||
- Enter: [`acceptCompletion`](https://codemirror.net/6/docs/ref/#autocomplete.acceptCompletion)
|
||||
*/
|
||||
const completionKeymap = [
|
||||
{ key: "Ctrl-Space", run: startCompletion },
|
||||
{ mac: "Alt-`", run: startCompletion },
|
||||
{ mac: "Alt-i", run: startCompletion },
|
||||
{ key: "Escape", run: closeCompletion },
|
||||
{ key: "ArrowDown", run: /*@__PURE__*/moveCompletionSelection(true) },
|
||||
{ key: "ArrowUp", run: /*@__PURE__*/moveCompletionSelection(false) },
|
||||
|
|
@ -29545,6 +29564,27 @@ ${text}</tr>
|
|||
function toSeverity(sev) {
|
||||
return sev == 1 ? "error" : sev == 2 ? "warning" : sev == 3 ? "info" : "hint";
|
||||
}
|
||||
const autoSync = /*@__PURE__*/ViewPlugin.fromClass(class {
|
||||
constructor() {
|
||||
this.pending = -1;
|
||||
}
|
||||
update(update) {
|
||||
if (update.docChanged) {
|
||||
if (this.pending > -1)
|
||||
clearTimeout(this.pending);
|
||||
this.pending = setTimeout(() => {
|
||||
this.pending = -1;
|
||||
let plugin = LSPPlugin.get(update.view);
|
||||
if (plugin)
|
||||
plugin.client.sync();
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
destroy() {
|
||||
if (this.pending > -1)
|
||||
clearTimeout(this.pending);
|
||||
}
|
||||
});
|
||||
function serverDiagnostics() {
|
||||
return {
|
||||
clientCapabilities: { textDocument: { publishDiagnostics: { versionSupport: true } } },
|
||||
|
|
@ -29567,7 +29607,8 @@ ${text}</tr>
|
|||
})));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
},
|
||||
editorExtension: autoSync
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -83,21 +83,18 @@ function connect() {
|
|||
$("popConnect").hidePopover();
|
||||
connectStatus(true);
|
||||
let extLsp = client.plugin(file, "xquery");
|
||||
let up = lsp.debouncedChangeListener({
|
||||
delay: 750,
|
||||
onChange: (content, state) => {
|
||||
console.log('Debounced change detected:');
|
||||
client.sync();
|
||||
}
|
||||
})
|
||||
|
||||
view.dispatch({
|
||||
effects: lsp.StateEffect.appendConfig.of(
|
||||
[lsp.linter(null, { autoPanel: true }), ...extLsp, up,
|
||||
lsp.keymap.of([...lsp.formatKeymap])])
|
||||
[lsp.linter(null, { autoPanel: true }), ...extLsp,
|
||||
lsp.keymap.of([...lsp.formatKeymap])])
|
||||
})
|
||||
})
|
||||
.catch(r => { connectStatus(false); alert("connection failed: " + server) });
|
||||
.catch(e => {
|
||||
console.log(e);
|
||||
connectStatus(false);
|
||||
alert("connection failed: " + server)
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
|
|
@ -114,7 +111,6 @@ function connectStatus(bool) {
|
|||
function incoming(msg) {
|
||||
const rpc = JSON.parse(msg);
|
||||
log(rpc);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue