Skip to content

Commit

Permalink
feat(json-crdt-extensions): 馃幐 improve mutations in persisted slices
Browse files Browse the repository at this point in the history
  • Loading branch information
streamich committed May 1, 2024
1 parent 7773bec commit d6d0193
Show file tree
Hide file tree
Showing 3 changed files with 47 additions and 44 deletions.
29 changes: 6 additions & 23 deletions src/json-crdt-extensions/peritext/editor/Cursor.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {Point} from '../rga/Point';
import {Range} from '../rga/Range';
import {CursorAnchor} from '../slice/constants';
import {PersistedSlice} from '../slice/PersistedSlice';

Expand All @@ -8,6 +7,8 @@ export class Cursor<T = string> extends PersistedSlice<T> {
return this.type as CursorAnchor;
}

// ---------------------------------------------------------------- mutations

public set anchorSide(value: CursorAnchor) {
this.update({type: value});
}
Expand All @@ -20,31 +21,15 @@ export class Cursor<T = string> extends PersistedSlice<T> {
return this.anchorSide === CursorAnchor.Start ? this.end : this.start;
}

public set(start: Point<T>, end?: Point<T>, anchorSide: CursorAnchor = this.anchorSide): void {
if (!end || end === start) end = start.clone();
super.set(start, end);
public set(start: Point<T>, end: Point<T> = start, anchorSide: CursorAnchor = this.anchorSide): void {
this.start = start;
this.end = end === start ? end.clone() : end;
this.update({
range: this,
type: anchorSide,
});
}

/** TODO: Move to {@link PersistedSlice}. */
public setAt(start: number, length: number = 0): void {
let at = start;
let len = length;
if (len < 0) {
at += len;
len = -len;
}
const range = Range.at<T>(this.rga, start, length);
const anchorSide = this.anchorSide;
this.update({
range,
type: anchorSide !== this.anchorSide ? anchorSide : undefined,
});
}

/**
* Move one of the edges of the cursor to a new point.
*
Expand All @@ -64,9 +49,7 @@ export class Cursor<T = string> extends PersistedSlice<T> {
public move(move: number): void {
const {start, end} = this;
start.move(move);
if (start !== end) {
end.move(move);
}
if (start !== end) end.move(move);
this.set(start, end);
}

Expand Down
44 changes: 24 additions & 20 deletions src/json-crdt-extensions/peritext/rga/Range.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,26 +119,16 @@ export class Range<T = string> implements Pick<Stateful, 'refresh'>, Printable {
return start2.cmp(end2) === 0;
}

/**
* Collapse the range to the start point and sets the anchor position to be
* "after" the character.
*/
public collapseToStart(): void {
this.start = this.start.clone();
this.start.refAfter();
this.end = this.start.clone();
public contains(range: Range<T>): boolean {
return this.start.cmpSpatial(range.start) <= 0 && this.end.cmpSpatial(range.end) >= 0;
}

/**
* Collapse the range to the end point and sets the anchor position to be
* "before" the character.
*/
public collapseToEnd(): void {
this.end = this.end.clone();
this.end.refAfter();
this.start = this.end.clone();
public containsPoint(point: Point<T>): boolean {
return this.start.cmpSpatial(point) <= 0 && this.end.cmpSpatial(point) >= 0;
}

// ---------------------------------------------------------------- mutations

public set(start: Point<T>, end: Point<T> = start): void {
this.start = start;
this.end = end === start ? end.clone() : end;
Expand All @@ -158,12 +148,26 @@ export class Range<T = string> implements Pick<Stateful, 'refresh'>, Printable {
this.set(point);
}

public contains(range: Range<T>): boolean {
return this.start.cmpSpatial(range.start) <= 0 && this.end.cmpSpatial(range.end) >= 0;
/**
* Collapse the range to the start point and sets the anchor position to be
* "after" the character.
*/
public collapseToStart(): void {
const start = this.start.clone();
start.refAfter();
const end = start.clone();
this.set(start, end);
}

public containsPoint(point: Point<T>): boolean {
return this.start.cmpSpatial(point) <= 0 && this.end.cmpSpatial(point) >= 0;
/**
* Collapse the range to the end point and sets the anchor position to be
* "before" the character.
*/
public collapseToEnd(): void {
const end = this.end.clone();
end.refAfter();
const start = this.end.clone();
this.set(start, end);
}

/**
Expand Down
18 changes: 17 additions & 1 deletion src/json-crdt-extensions/peritext/slice/PersistedSlice.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import {Range} from '../rga/Range';
import {updateNode} from '../../../json-crdt/hash';
import {printTree} from 'tree-dump/lib/printTree';
import {Anchor} from '../rga/constants';
import {SliceHeaderMask, SliceHeaderShift, SliceBehavior, SliceTupleIndex} from './constants';
import {SliceHeaderMask, SliceHeaderShift, SliceBehavior, SliceTupleIndex, CursorAnchor} from './constants';
import {CONST} from '../../../json-hash';
import {Timestamp, compare} from '../../../json-crdt-patch/clock';
import {VecNode} from '../../../json-crdt/nodes';
Expand Down Expand Up @@ -66,6 +66,22 @@ export class PersistedSlice<T = string> extends Range<T> implements MutableSlice
return this.model.api.wrap(this.tuple);
}

// ---------------------------------------------------------------- mutations

public set(start: Point<T>, end: Point<T> = start): void {
super.set(start, end);
this.update({range: this});
}

/**
* Expand range left and right to contain all invisible space: (1) tombstones,
* (2) anchors of non-deleted adjacent chunks.
*/
public expand(): void {
super.expand();
this.update({range: this});
}

// ------------------------------------------------------------- MutableSlice

public readonly id: ITimestampStruct;
Expand Down

0 comments on commit d6d0193

Please sign in to comment.