[add] apply-changes
This commit is contained in:
parent
cffeb0aa45
commit
08051d5281
4 changed files with 84 additions and 37 deletions
|
@ -1 +1,14 @@
|
||||||
json:doc("sample.msg/didChange/client2.json",{"format":"w3"})
|
import module namespace pos="lsp/position" at "../webapp/lsp/position.xqm";
|
||||||
|
|
||||||
|
declare variable $msg:=json:doc("sample.msg/didChange/client2.json",{"format":"w3"});
|
||||||
|
declare variable $text:=`12345678
|
||||||
|
bbbbb
|
||||||
|
cccccc`;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
(: return pos:resolvePosition($text,$p) :)
|
||||||
|
pos:apply-changes($text,$msg?params?contentChanges)
|
||||||
|
(: $msg?params?contentChanges :)
|
|
@ -5,15 +5,8 @@
|
||||||
:)
|
:)
|
||||||
module namespace docs="lsp/docs";
|
module namespace docs="lsp/docs";
|
||||||
import module namespace p="xq4" at "xq4.xqm";
|
import module namespace p="xq4" at "xq4.xqm";
|
||||||
|
import module namespace pos="lsp/position" at "position.xqm";
|
||||||
|
|
||||||
(:~
|
|
||||||
@param line Line position in a document (zero-based).
|
|
||||||
@param character Character offset on a line in a document (zero-based).
|
|
||||||
:)
|
|
||||||
declare record docs:Position(
|
|
||||||
line as xs:integer,
|
|
||||||
character as xs:integer
|
|
||||||
);
|
|
||||||
|
|
||||||
(: document info :)
|
(: document info :)
|
||||||
declare type docs:property as enum(
|
declare type docs:property as enum(
|
||||||
|
@ -58,29 +51,3 @@ return (
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
declare function docs:resolvePosition($text as xs:string, $pos as docs:Position)
|
|
||||||
as xs:integer
|
|
||||||
{
|
|
||||||
(: let line = 0, off = 0
|
|
||||||
while (line < pos.line) {
|
|
||||||
let next = text.indexOf("\n", off)
|
|
||||||
if (!next) throw new RangeError("Position out of bounds")
|
|
||||||
off = next + 1
|
|
||||||
line++
|
|
||||||
}
|
|
||||||
off += pos.character
|
|
||||||
if (off > string-length($text)) throw new RangeError("Position out of bounds")
|
|
||||||
return off :)
|
|
||||||
0
|
|
||||||
};
|
|
||||||
|
|
||||||
declare function docs:toPosition($text as xs:string, $pos as xs:integer)
|
|
||||||
as docs:Position {
|
|
||||||
(: for (let off = 0, line = 0;;) {
|
|
||||||
let next = text.indexOf("\n", off)
|
|
||||||
if (next < 0 || next >= pos) return {line, character: pos - off}
|
|
||||||
off = next + 1
|
|
||||||
line++
|
|
||||||
} :)
|
|
||||||
docs:Position(0,0)
|
|
||||||
};
|
|
|
@ -5,10 +5,10 @@ import module namespace docs="lsp/docs" at "docs.xqm";
|
||||||
declare variable $params as map(*) external;
|
declare variable $params as map(*) external;
|
||||||
declare variable $webSocket as xs:string external;
|
declare variable $webSocket as xs:string external;
|
||||||
|
|
||||||
prof:time(docs:save(
|
docs:save(
|
||||||
$webSocket,
|
$webSocket,
|
||||||
$params
|
$params
|
||||||
),"⏱️ doc:save "),
|
)=>prof:time("⏱️ doc:save "),
|
||||||
|
|
||||||
ws:send(
|
ws:send(
|
||||||
{"jsonrpc": "2.0",
|
{"jsonrpc": "2.0",
|
||||||
|
|
67
webapp/lsp/position.xqm
Normal file
67
webapp/lsp/position.xqm
Normal file
|
@ -0,0 +1,67 @@
|
||||||
|
(:~
|
||||||
|
text editing API
|
||||||
|
:)
|
||||||
|
module namespace pos="lsp/position";
|
||||||
|
|
||||||
|
(:~
|
||||||
|
@param line Line position in a document (zero-based).
|
||||||
|
@param character Character offset on a line in a document (zero-based).
|
||||||
|
:)
|
||||||
|
declare record pos:Position(
|
||||||
|
line as xs:integer,
|
||||||
|
character as xs:integer
|
||||||
|
);
|
||||||
|
|
||||||
|
declare function pos:apply-changes($text as xs:string, $chs as array(*))
|
||||||
|
as xs:string{
|
||||||
|
array:fold-left($chs,$text,pos:apply-change#2)
|
||||||
|
};
|
||||||
|
|
||||||
|
(:~ text updated with $ch changes from didChange :)
|
||||||
|
declare function pos:apply-change($text as xs:string, $ch as map(*))
|
||||||
|
as xs:string{
|
||||||
|
if(exists($ch?range))
|
||||||
|
then substring($text,1, pos:resolvePosition($text, $ch?range?start))
|
||||||
|
|| $ch?text ||
|
||||||
|
substring($text,pos:resolvePosition($text, $ch?range?end))
|
||||||
|
else $ch?text
|
||||||
|
};
|
||||||
|
|
||||||
|
(:~ find index from Position :)
|
||||||
|
declare function pos:resolvePosition($text as xs:string, $pos as map(*))
|
||||||
|
as xs:integer
|
||||||
|
{
|
||||||
|
let $nl:=characters($text)=>index-of(char("\n"))
|
||||||
|
let $s:= while-do(
|
||||||
|
map{"off":0,"line":0},
|
||||||
|
fn($r, $i){$r?line < $pos?line},
|
||||||
|
fn($r,$i){ let $next:=$nl[$i]
|
||||||
|
return if(empty($next))
|
||||||
|
then error(xs:QName("docs:range"),"bad line")
|
||||||
|
else {"off": $next+1,"line":$r?line+1}=>trace("AA ") }
|
||||||
|
)
|
||||||
|
let $off:= $s?off+$pos?character
|
||||||
|
return if($off>string-length($text))
|
||||||
|
then error(xs:QName("docs:range"),"bad offset")
|
||||||
|
else xs:integer($off)
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
(:~ convert index into Position :)
|
||||||
|
declare function pos:toPosition($text as xs:string, $pos as xs:integer)
|
||||||
|
as pos:Position {
|
||||||
|
let $nl:=characters($text)=>index-of(char("\n"))
|
||||||
|
let $predicate:=fn($r, $i){
|
||||||
|
let $next:=$nl[$i=>trace("I ")]
|
||||||
|
return exists($next) and $next < $pos
|
||||||
|
}
|
||||||
|
|
||||||
|
let $s:= while-do(
|
||||||
|
map{"off":0,"line":0},
|
||||||
|
$predicate,
|
||||||
|
fn($r,$i){ let $next:=$nl[$i] return {"off": $next+1,"line":$r?line+1}=>trace("AA ") }
|
||||||
|
)
|
||||||
|
return pos:Position($s?line, $pos - $s?off)
|
||||||
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue