(:~ 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 ); (:~ @param line Line position in a document (zero-based). @param character Character offset on a line in a document (zero-based). :) declare record pos:Range( start as pos:Position, end as pos:Position ); 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, $index 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 < $index } 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, $index - $s?off) }; (:~ from: number The start position of the relevant text. to: number The end position. May be equal to from, though actually covering text is preferable. severity: "error" | "hint" | "info" | "warning" The severity of the problem. This will influence how it is displayed. markClass⁠?: string When given, add an extra CSS class to parts of the code that this diagnostic applies to. source⁠?: string An optional source string indicating where the diagnostic is coming from. You can put the name of your linter here, if applicable. message: string The message associated with this diagnostic. renderMessage⁠?: fn(view: EditorView) → Node An optional custom rendering function that displays the message as a DOM node. actions⁠?: readonly Action[] An optional array of actions that can be taken on this diagnostic. :) declare record pos:nostic( range as pos:Range, severity as xs:integer, (: enum('error', 'hint', 'info', 'warning') :) message as xs:string );