(:~ handle textDocument messages : @author andy bunce :) module namespace lsp-text = 'lsp-text'; import module namespace docs="lsp/docs" at "docs.xqm"; import module namespace rpc = 'rpc' at 'jsonrpc.xqm'; import module namespace lspt = 'lsp-typedefs' at 'lsp-typedefs.xqm'; import module namespace pos="lsp/position" at "position.xqm"; declare variable $lsp-text:methods:=map{ "textDocument/didOpen": lsp-text:didOpen#1, "textDocument/didChange": lsp-text:didChange#1, "textDocument/didClose" : lsp-text:method-unknown#1, "textDocument/hover": lsp-text:hover#1, "textDocument/completion": lsp-text:completion#1, "textDocument/formatting" : lsp-text:format#1, "textDocument/documentSymbol" : lsp-text:symbols#1 }; declare variable lsp-text:word-reg:="[A-Z]|_|[a-z]|[À-Ö]|[Ø-ö]|[ø-˿]|[Ͱ-ͽ]|[Ϳ-῿]|[‌-‍]|[⁰-↏]|[Ⰰ-⿯]|[、-퟿]|[豈-﷏]|[ﷰ-�]"; (:~ hover :) declare function lsp-text:hover($json as map(*)) as map(*) { let $pos:=$json?params?position let $uri:= $json?params?textDocument?uri let $word:="TODO" let $r:= [ `At { pos:ln-col($pos) }, uri: {$uri}, [path](https://quodatum.github.io/basex-xqparse/i-BaseX.xhtml#EQName) WordAt: {$word}` ] return rpc:result($json,{"contents":$r}) }; (:~ symbols :) declare function lsp-text:symbols($json as map(*)) as map(*)? { let $uri:=$json?params?textDocument?uri let $text:=docs:get(ws:id(), $uri, "textDocument")?text let $fr:=pos:full-range($text) (: dummy data :) let $nameRange:=$fr let $result:=map:for-each($lspt:SymbolKindMap, fn($k,$v){ lspt:DocumentSymbol($k,$v,$fr,$nameRange,"todo description") })=>array:build() return rpc:result($json,$result)=>trace("SSS") }; declare function lsp-text:completion($json as map(*)) as map(*)? { let $doc:=$json?params?textDocument?uri let $result:=() return rpc:result($json,$result) }; declare function lsp-text:format($json as map(*)) as map(*)? { let $uri:=$json?params?textDocument?uri let $text:=docs:get(ws:id(), $uri, "textDocument")?text let $xml:=docs:get(ws:id(), $uri, "parse") return if($xml/self::ERROR) then rpc:error("Syntax errors found.",$json) else let $xml:=$xml update {lsp-text:tidy(.)} let $result:=[{ "range":pos:full-range($text), "newText": string($xml) }] return rpc:result($json,$result) }; (:~ didOpen method response :) declare function lsp-text:didOpen($json as map(*)) as map(*)? { let $uri:=docs:open(ws:id(),$json?params)=>prof:time("⏱️ doc:save ") return docs:parse(ws:id(),$uri) }; (:~ didChange method response :) declare function lsp-text:didChange($json as map(*)) as map(*)? { let $uri:=docs:change(ws:id(),$json?params)=>prof:time("⏱️ doc:change ") return docs:parse(ws:id(),$uri) }; (:~ unknown method response :) declare function lsp-text:method-unknown($json as map(*)) as map(*)? { let $_:=trace($json?method,"unknown") return () }; (:~ ensure spaces around := :) declare %updating function lsp-text:tidy($doc){ for $a in $doc//TOKEN[.=":="] let $before:= $a/preceding-sibling::node()[1] let $after:= $a/following-sibling::node()[1] return ( if($before instance of element(*)) then insert node " " before $a else (), if($after instance of element(*)) then insert node " " after $a else () ) };