94 lines
2.5 KiB
TypeScript
94 lines
2.5 KiB
TypeScript
|
'use strict'
|
||
|
import { Position, Range, TextEdit } from 'vscode-languageserver-types'
|
||
|
import { getEnd } from '../util/position'
|
||
|
import { getChangedPosition } from '../util/textedit'
|
||
|
import { isSurrondChange, SurrondChange, TextChange } from './util'
|
||
|
const logger = require('../util/logger')('cursors-range')
|
||
|
|
||
|
export default class TextRange {
|
||
|
private start: Position
|
||
|
private end: Position
|
||
|
private _text: string
|
||
|
|
||
|
constructor(line: number, character: number, text: string) {
|
||
|
this.start = Position.create(line, character)
|
||
|
this._text = text
|
||
|
this.end = getEnd(this.start, this._text)
|
||
|
}
|
||
|
|
||
|
public get position(): Position {
|
||
|
return this.start
|
||
|
}
|
||
|
|
||
|
public get line(): number {
|
||
|
return this.start.line
|
||
|
}
|
||
|
|
||
|
public get text(): string {
|
||
|
return this._text
|
||
|
}
|
||
|
|
||
|
public get range(): Range {
|
||
|
return Range.create(this.start, this.end)
|
||
|
}
|
||
|
|
||
|
public get textEdit(): TextEdit {
|
||
|
return {
|
||
|
range: this.range,
|
||
|
newText: this.text
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public applyChange(change: SurrondChange | TextChange): void {
|
||
|
if (isSurrondChange(change)) {
|
||
|
this.applySurrondChange(change)
|
||
|
} else {
|
||
|
this.applyTextChange(change)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public applySurrondChange(change: SurrondChange): void {
|
||
|
let { prepend, append } = change
|
||
|
let len = this._text.length
|
||
|
let text = this._text.substring(prepend[0], len - append[0])
|
||
|
this._text = `${prepend[1]}${text}${append[1]}`
|
||
|
}
|
||
|
|
||
|
public applyTextChange(change: TextChange): void {
|
||
|
let { text } = this
|
||
|
let { offset, remove, fromEnd, insert } = change
|
||
|
if (fromEnd) offset = -offset
|
||
|
let pre = text.slice(0, fromEnd && offset == 0 ? text.length : offset)
|
||
|
let after = text.slice(pre.length)
|
||
|
if (remove) after = after.slice(remove)
|
||
|
this._text = `${pre}${insert || ''}${after}`
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Adjust range
|
||
|
*/
|
||
|
public move(delta: number): void {
|
||
|
if (delta != 0) {
|
||
|
let { line, character } = this.start
|
||
|
this.start = Position.create(line, character + delta)
|
||
|
}
|
||
|
this.end = getEnd(this.start, this._text)
|
||
|
}
|
||
|
|
||
|
public adjustFromEdit(edit: TextEdit): number {
|
||
|
let changed = getChangedPosition(this.start, edit)
|
||
|
if (changed.line || changed.character) {
|
||
|
let { line, character } = this.start
|
||
|
this.start = Position.create(line + changed.line, character + changed.character)
|
||
|
this.end = getEnd(this.start, this._text)
|
||
|
}
|
||
|
return changed.character
|
||
|
}
|
||
|
|
||
|
public isBefore(range: TextRange): boolean {
|
||
|
let { position } = range
|
||
|
let { line, character } = this.start
|
||
|
return position.line == line && position.character > character
|
||
|
}
|
||
|
}
|