Files
superwork/vscode/webview-ui/src/codeReader/segments.ts
T

50 lines
2.0 KiB
TypeScript

import type { Inline, Segment } from './types'
/** 取 segments 拼起来的文字里 [from, to) 这一段,每个字保留原来的词性。 */
export function sliceSegments(segments: Segment[], from: number, to: number): Segment[] {
const out: Segment[] = []
let offset = 0
for (const segment of segments) {
const start = Math.max(from, offset)
const end = Math.min(to, offset + segment.text.length)
if (start < end)
out.push({ text: segment.text.slice(start - offset, end - offset), role: segment.role })
offset += segment.text.length
if (offset >= to)
break
}
return out
}
/**
* 给输入框里改过的文字上色:`tokens` 是 `code` 的着色,和 `code` 相同的开头、结尾沿用原来的词性,
* 中间改动的部分先不着色,等扩展端按新代码着色的文档到了再换成准确的。
*/
export function recolor(tokens: Segment[], code: string, text: string): Segment[] {
if (text === code)
return tokens
const shorter = Math.min(code.length, text.length)
let head = 0
while (head < shorter && code[head] === text[head])
head++
let tail = 0
while (tail < shorter - head && code[code.length - 1 - tail] === text[text.length - 1 - tail])
tail++
const changed = text.slice(head, text.length - tail)
return [
...sliceSegments(tokens, 0, head),
...(changed ? [{ text: changed, role: 'plain' as const }] : []),
...sliceSegments(tokens, code.length - tail, code.length),
]
}
/** 着色的词拼成的文字(给折叠按钮的说明用);框写成框头加框里的文字。 */
export function inlineText(pieces: Inline[]): string {
return pieces.map(piece => 'role' in piece ? piece.text : `${piece.label} ${inlineText(piece.segments)}`).join('')
}
/** 文字里有没有 offset 处的那个名字,框里的也算。 */
export function showsOffset(pieces: Inline[], offset: number): boolean {
return pieces.some(piece => 'role' in piece ? piece.offset === offset : showsOffset(piece.segments, offset))
}