1
0
Fork 0
mirror of synced 2024-06-25 18:21:11 -04:00
ultimate-vim/sources_non_forked/coc.nvim/src/cursors/util.ts
2022-07-20 13:20:15 +08:00

111 lines
3.4 KiB
TypeScript

'use strict'
import { Range } from 'vscode-languageserver-protocol'
import Document from '../model/document'
import { equals } from '../util/object'
import { getWellformedRange } from '../util/textedit'
import type TextRange from './textRange'
export interface TextChange {
offset: number
remove: number
insert: string
fromEnd?: boolean
}
export interface SurrondChange {
/**
* delete count & insert text
*/
prepend: [number, string]
/**
* delete count & insert text
*/
append: [number, string]
}
/**
* Split to single line ranges
*/
export function splitRange(doc: Document, range: Range): Range[] {
let splited: Range[] = []
for (let i = range.start.line; i <= range.end.line; i++) {
let curr = doc.getline(i) || ''
let sc = i == range.start.line ? range.start.character : 0
let ec = i == range.end.line ? range.end.character : curr.length
if (sc == ec) continue
splited.push(Range.create(i, sc, i, ec))
}
return splited
}
/**
* Get ranges of visual block
*/
export function getVisualRanges(doc: Document, range: Range): Range[] {
let { start, end } = getWellformedRange(range)
let sc = start.character < end.character ? start.character : end.character
let ec = start.character < end.character ? end.character : start.character
let ranges: Range[] = []
for (let i = start.line; i <= end.line; i++) {
let line = doc.getline(i)
ranges.push(Range.create(i, sc, i, Math.min(line.length, ec)))
}
return ranges
}
export function isSurrondChange(change: TextChange | SurrondChange): change is SurrondChange {
return Array.isArray(change['prepend']) && Array.isArray(change['append'])
}
export function isTextChange(change: TextChange | SurrondChange): change is TextChange {
return typeof change['offset'] === 'number' && typeof change['remove'] === 'number'
}
export function getDelta(change: TextChange | SurrondChange): number {
if (isSurrondChange(change)) {
return change.append[1].length + change.prepend[1].length - change.append[0] - change.prepend[0]
}
return change.insert.length - change.remove
}
export function getChange(r: TextRange, range: Range, newText: string): TextChange | SurrondChange {
let text = r.text
if (equals(r.range, range)) {
// surrond
let idx = text.indexOf(newText)
if (idx !== -1) {
let prepend: [number, string] = [idx, '']
let append: [number, string] = [text.length - newText.length - idx, '']
return { prepend, append }
}
idx = newText.indexOf(text)
if (idx !== -1) {
let prepend: [number, string] = [0, newText.slice(0, idx)]
let append: [number, string] = [0, newText.slice(- (newText.length - text.length - idx))]
return { prepend, append }
}
}
if (equals(r.range.end, range.end)) {
// end change
let remove = range.end.character - range.start.character
return { offset: remove, remove, insert: newText, fromEnd: true }
}
let remove = range.end.character - range.start.character
let offset = range.start.character - r.range.start.character
return { offset, remove, insert: newText }
}
export function getBeforeCount(textRange: TextRange, ranges: TextRange[], exclude?: TextRange): number {
let n = 0
for (let idx = 0; idx < ranges.length; idx++) {
const r = ranges[idx]
if (r.position.line < textRange.position.line || r === exclude) continue
if (r.isBefore(textRange)) {
n++
continue
}
break
}
return n
}