72 lines
1.9 KiB
Go
72 lines
1.9 KiB
Go
package ls
|
|
|
|
import (
|
|
"cmp"
|
|
"slices"
|
|
"strings"
|
|
"unicode/utf8"
|
|
|
|
"efprojects.com/kitten-ipc/kitcom/internal/tsgo/core"
|
|
)
|
|
|
|
type LSPLineStarts []core.TextPos
|
|
|
|
type LSPLineMap struct {
|
|
LineStarts LSPLineStarts
|
|
AsciiOnly bool // TODO(jakebailey): collect ascii-only info per line
|
|
}
|
|
|
|
func ComputeLSPLineStarts(text string) *LSPLineMap {
|
|
// This is like core.ComputeLineStarts, but only considers "\n", "\r", and "\r\n" as line breaks,
|
|
// and reports when the text is ASCII-only.
|
|
lineStarts := make([]core.TextPos, 0, strings.Count(text, "\n")+1)
|
|
asciiOnly := true
|
|
|
|
textLen := core.TextPos(len(text))
|
|
var pos core.TextPos
|
|
var lineStart core.TextPos
|
|
for pos < textLen {
|
|
b := text[pos]
|
|
if b < utf8.RuneSelf {
|
|
pos++
|
|
switch b {
|
|
case '\r':
|
|
if pos < textLen && text[pos] == '\n' {
|
|
pos++
|
|
}
|
|
fallthrough
|
|
case '\n':
|
|
lineStarts = append(lineStarts, lineStart)
|
|
lineStart = pos
|
|
}
|
|
} else {
|
|
_, size := utf8.DecodeRuneInString(text[pos:])
|
|
pos += core.TextPos(size)
|
|
asciiOnly = false
|
|
}
|
|
}
|
|
lineStarts = append(lineStarts, lineStart)
|
|
|
|
return &LSPLineMap{
|
|
LineStarts: lineStarts,
|
|
AsciiOnly: asciiOnly,
|
|
}
|
|
}
|
|
|
|
func (lm *LSPLineMap) ComputeIndexOfLineStart(targetPos core.TextPos) int {
|
|
// port of computeLineOfPosition(lineStarts: readonly number[], position: number, lowerBound?: number): number {
|
|
lineNumber, ok := slices.BinarySearchFunc(lm.LineStarts, targetPos, func(p, t core.TextPos) int {
|
|
return cmp.Compare(int(p), int(t))
|
|
})
|
|
if !ok && lineNumber > 0 {
|
|
// If the actual position was not found, the binary search returns where the target line start would be inserted
|
|
// if the target was in the slice.
|
|
// e.g. if the line starts at [5, 10, 23, 80] and the position requested was 20
|
|
// then the search will return (3, false).
|
|
//
|
|
// We want the index of the previous line start, so we subtract 1.
|
|
lineNumber = lineNumber - 1
|
|
}
|
|
return lineNumber
|
|
}
|