feat(web)!: add API for editing points and ranges
This commit is contained in:
parent
a69367f739
commit
48a5077035
9 changed files with 264 additions and 33 deletions
|
|
@ -33,29 +33,6 @@ export interface Range {
|
|||
endIndex: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* A summary of a change to a text document.
|
||||
*/
|
||||
export interface Edit {
|
||||
/** The start position of the change. */
|
||||
startPosition: Point;
|
||||
|
||||
/** The end position of the change before the edit. */
|
||||
oldEndPosition: Point;
|
||||
|
||||
/** The end position of the change after the edit. */
|
||||
newEndPosition: Point;
|
||||
|
||||
/** The start index of the change. */
|
||||
startIndex: number;
|
||||
|
||||
/** The end index of the change before the edit. */
|
||||
oldEndIndex: number;
|
||||
|
||||
/** The end index of the change after the edit. */
|
||||
newEndIndex: number;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export const SIZE_OF_SHORT = 2;
|
||||
|
||||
|
|
|
|||
125
lib/binding_web/src/edit.ts
Normal file
125
lib/binding_web/src/edit.ts
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
import { Point, Range } from "./constants";
|
||||
|
||||
export class Edit {
|
||||
/** The start position of the change. */
|
||||
startPosition: Point;
|
||||
|
||||
/** The end position of the change before the edit. */
|
||||
oldEndPosition: Point;
|
||||
|
||||
/** The end position of the change after the edit. */
|
||||
newEndPosition: Point;
|
||||
|
||||
/** The start index of the change. */
|
||||
startIndex: number;
|
||||
|
||||
/** The end index of the change before the edit. */
|
||||
oldEndIndex: number;
|
||||
|
||||
/** The end index of the change after the edit. */
|
||||
newEndIndex: number;
|
||||
|
||||
constructor({
|
||||
startIndex,
|
||||
oldEndIndex,
|
||||
newEndIndex,
|
||||
startPosition,
|
||||
oldEndPosition,
|
||||
newEndPosition,
|
||||
}: {
|
||||
startIndex: number;
|
||||
oldEndIndex: number;
|
||||
newEndIndex: number;
|
||||
startPosition: Point;
|
||||
oldEndPosition: Point;
|
||||
newEndPosition: Point;
|
||||
}) {
|
||||
this.startIndex = startIndex >>> 0;
|
||||
this.oldEndIndex = oldEndIndex >>> 0;
|
||||
this.newEndIndex = newEndIndex >>> 0;
|
||||
this.startPosition = startPosition;
|
||||
this.oldEndPosition = oldEndPosition;
|
||||
this.newEndPosition = newEndPosition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a point and index to keep it in-sync with source code that has been edited.
|
||||
*
|
||||
* This function updates a single point's byte offset and row/column position
|
||||
* based on an edit operation. This is useful for editing points without
|
||||
* requiring a tree or node instance.
|
||||
*/
|
||||
editPoint(point: Point, index: number): { point: Point; index: number } {
|
||||
let newIndex = index;
|
||||
const newPoint = { ...point };
|
||||
|
||||
if (index >= this.oldEndIndex) {
|
||||
newIndex = this.newEndIndex + (index - this.oldEndIndex);
|
||||
const originalRow = point.row;
|
||||
newPoint.row = this.newEndPosition.row + (point.row - this.oldEndPosition.row);
|
||||
newPoint.column = originalRow === this.oldEndPosition.row
|
||||
? this.newEndPosition.column + (point.column - this.oldEndPosition.column)
|
||||
: point.column;
|
||||
} else if (index > this.startIndex) {
|
||||
newIndex = this.newEndIndex;
|
||||
newPoint.row = this.newEndPosition.row;
|
||||
newPoint.column = this.newEndPosition.column;
|
||||
}
|
||||
|
||||
return { point: newPoint, index: newIndex };
|
||||
}
|
||||
|
||||
/**
|
||||
* Edit a range to keep it in-sync with source code that has been edited.
|
||||
*
|
||||
* This function updates a range's start and end positions based on an edit
|
||||
* operation. This is useful for editing ranges without requiring a tree
|
||||
* or node instance.
|
||||
*/
|
||||
editRange(range: Range): Range {
|
||||
const newRange: Range = {
|
||||
startIndex: range.startIndex,
|
||||
startPosition: { ...range.startPosition },
|
||||
endIndex: range.endIndex,
|
||||
endPosition: { ...range.endPosition }
|
||||
};
|
||||
|
||||
if (range.endIndex >= this.oldEndIndex) {
|
||||
if (range.endIndex !== Number.MAX_SAFE_INTEGER) {
|
||||
newRange.endIndex = this.newEndIndex + (range.endIndex - this.oldEndIndex);
|
||||
newRange.endPosition = {
|
||||
row: this.newEndPosition.row + (range.endPosition.row - this.oldEndPosition.row),
|
||||
column: range.endPosition.row === this.oldEndPosition.row
|
||||
? this.newEndPosition.column + (range.endPosition.column - this.oldEndPosition.column)
|
||||
: range.endPosition.column,
|
||||
};
|
||||
if (newRange.endIndex < this.newEndIndex) {
|
||||
newRange.endIndex = Number.MAX_SAFE_INTEGER;
|
||||
newRange.endPosition = { row: Number.MAX_SAFE_INTEGER, column: Number.MAX_SAFE_INTEGER };
|
||||
}
|
||||
}
|
||||
} else if (range.endIndex > this.startIndex) {
|
||||
newRange.endIndex = this.startIndex;
|
||||
newRange.endPosition = { ...this.startPosition };
|
||||
}
|
||||
|
||||
if (range.startIndex >= this.oldEndIndex) {
|
||||
newRange.startIndex = this.newEndIndex + (range.startIndex - this.oldEndIndex);
|
||||
newRange.startPosition = {
|
||||
row: this.newEndPosition.row + (range.startPosition.row - this.oldEndPosition.row),
|
||||
column: range.startPosition.row === this.oldEndPosition.row
|
||||
? this.newEndPosition.column + (range.startPosition.column - this.oldEndPosition.column)
|
||||
: range.startPosition.column,
|
||||
};
|
||||
if (newRange.startIndex < this.newEndIndex) {
|
||||
newRange.startIndex = Number.MAX_SAFE_INTEGER;
|
||||
newRange.startPosition = { row: Number.MAX_SAFE_INTEGER, column: Number.MAX_SAFE_INTEGER };
|
||||
}
|
||||
} else if (range.startIndex > this.startIndex) {
|
||||
newRange.startIndex = this.startIndex;
|
||||
newRange.startPosition = { ...this.startPosition };
|
||||
}
|
||||
|
||||
return newRange;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,11 +1,11 @@
|
|||
export type {
|
||||
Point,
|
||||
Range,
|
||||
Edit,
|
||||
ParseCallback,
|
||||
ProgressCallback,
|
||||
LogCallback,
|
||||
} from './constants';
|
||||
export { Edit } from './edit';
|
||||
export {
|
||||
type ParseOptions,
|
||||
type ParseState,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { Edit, INTERNAL, Point, Range, SIZE_OF_INT, SIZE_OF_NODE, SIZE_OF_POINT, C } from "./constants";
|
||||
import { INTERNAL, Point, Range, SIZE_OF_INT, SIZE_OF_NODE, SIZE_OF_POINT, C } from "./constants";
|
||||
import { Node } from "./node";
|
||||
import { Tree } from "./tree";
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
|
|
@ -6,6 +6,7 @@ import { Query, QueryCapture, type QueryMatch } from "./query";
|
|||
import { TreeCursor } from "./tree_cursor";
|
||||
import { TRANSFER_BUFFER } from "./parser";
|
||||
import { LanguageMetadata } from "./language";
|
||||
import { Edit } from "./edit";
|
||||
|
||||
/**
|
||||
* @internal
|
||||
|
|
|
|||
|
|
@ -1,10 +1,11 @@
|
|||
import { INTERNAL, Internal, assertInternal, Point, Edit, SIZE_OF_INT, SIZE_OF_NODE, SIZE_OF_POINT, ZERO_POINT, isPoint, C } from './constants';
|
||||
import { INTERNAL, Internal, assertInternal, SIZE_OF_INT, SIZE_OF_NODE, SIZE_OF_POINT, ZERO_POINT, isPoint, C, Point } from './constants';
|
||||
import { getText, Tree } from './tree';
|
||||
import { TreeCursor } from './tree_cursor';
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
import { Language } from './language';
|
||||
import { marshalNode, marshalPoint, unmarshalNode, unmarshalPoint } from './marshal';
|
||||
import { TRANSFER_BUFFER } from './parser';
|
||||
import { Edit } from './edit';
|
||||
|
||||
/** A single node within a syntax {@link Tree}. */
|
||||
export class Node {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
import { INTERNAL, Internal, assertInternal, ParseCallback, Point, Range, Edit, SIZE_OF_NODE, SIZE_OF_INT, SIZE_OF_RANGE, C } from './constants';
|
||||
import { INTERNAL, Internal, assertInternal, ParseCallback, Point, Range, SIZE_OF_NODE, SIZE_OF_INT, SIZE_OF_RANGE, C } from './constants';
|
||||
import { Language } from './language';
|
||||
import { Node } from './node';
|
||||
import { TreeCursor } from './tree_cursor';
|
||||
import { marshalEdit, marshalPoint, unmarshalNode, unmarshalRange } from './marshal';
|
||||
import { TRANSFER_BUFFER } from './parser';
|
||||
import { Edit } from './edit';
|
||||
|
||||
/** @internal */
|
||||
export function getText(tree: Tree, startIndex: number, endIndex: number, startPosition: Point): string {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue