From eba2e564bb1243a0551fae6e9303dc3852ba3775 Mon Sep 17 00:00:00 2001 From: Andy Bunce Date: Thu, 13 Nov 2025 22:37:41 +0000 Subject: [PATCH] [mod] . --- src/doci.xqm | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++ test/doci.xq | 10 +++++++ 2 files changed, 95 insertions(+) create mode 100644 src/doci.xqm create mode 100644 test/doci.xq diff --git a/src/doci.xqm b/src/doci.xqm new file mode 100644 index 0000000..d853645 --- /dev/null +++ b/src/doci.xqm @@ -0,0 +1,85 @@ +(:~ handle textDocument + + @see https://codemirror.net/docs/ref/#state.Text + @author andy bunce + :) +module namespace doci = 'urn:doci'; + +declare record doci:doci( + lines as xs:string+, + length as xs:integer, + separator? as xs:string, + starts? as xs:integer+ +); + +declare record doci:line( + from as xs:integer, (:number The position of the start of the line. :) + to as xs:integer, (:The position at the end of the line (before the line break, + or at the end of document for the last line).:) + number as xs:integer, (: This line's line number (1-based).:) + text as xs:string (: The line's content. :) +); + +(:~ json numbers :) +declare type doci:num as (xs:integer|xs:double); + +(:~ +@param line Line position in a document (zero-based). +@param character Character offset on a line in a document (zero-based). +:) +declare record doci:Position( + line as doci:num, + character as doci:num +); + +(:~ +@param line Line position in a document (zero-based). +@param character Character offset on a line in a document (zero-based). +:) +declare record doci:Range( + start as doci:Position, + end as doci:Position +); + +(: create new doci from string :) +declare function doci:build($text as xs:string) +as doci:doci{ + let $ls:=doci:separator($text ) + let $lines:=tokenize($text, '(\r\n?|\n\r?)') + let $starts:=hof:scan-left($lines, 0, + fn($res,$line){$res+string-length($ls)+string-length($line)} + ) + return doci:doci( + lines:= $lines, + length:= string-length($text), + separator:=$ls, + starts:= $starts + ) +}; + +(: line separator, assume all same:) +declare function doci:separator($text as xs:string) +as xs:string?{ +switch () { + case contains($text," ") return " " + case contains($text," ") return " " + case contains($text," ") return " " + default return () +} +}; + +(: line from pos :) +declare function doci:lineAt($doci as doci:doci,$pos as xs:integer) +{ +let $line:=do-until( + {"min":1,"max":count($doci?lines)}, + fn($r){ + let $mid:=round(($r?min+$r?max) div 2,0,"away-from-zero") + return if ($doci?starts[$mid] lt $pos) + then map:put($r,"min",$mid) + else map:put($r,"max",$mid -1) +}, + fn($r){$r?max eq $r?min} + )?max + return $line +}; \ No newline at end of file diff --git a/test/doci.xq b/test/doci.xq new file mode 100644 index 0000000..f1e97e4 --- /dev/null +++ b/test/doci.xq @@ -0,0 +1,10 @@ +import module namespace doci = 'urn:doci' at "../src/doci.xqm"; + +declare variable $long:= +file:read-text("C:\Users\mrwhe\git\quodatum\basex-lsp\test\sample.docs\pdfbox.xqm"); +declare variable $text:=`ABV +ddddd +`; + + +doci:build($long)