mirror of
https://github.com/loro-dev/loro.git
synced 2025-02-06 04:19:34 +00:00
refactor: rename stable pos to cursor (#317)
This commit is contained in:
parent
454b4088a6
commit
1918cd7ac3
11 changed files with 59 additions and 54 deletions
|
@ -5,7 +5,7 @@ use generic_btree::{
|
|||
use loro_common::{Counter, HasId, HasIdSpan, IdFull, IdSpan, Lamport, PeerID, ID};
|
||||
use rle::HasLength;
|
||||
|
||||
use crate::{stable_pos::AbsolutePosition, VersionVector};
|
||||
use crate::{cursor::AbsolutePosition, VersionVector};
|
||||
|
||||
use self::{crdt_rope::CrdtRope, id_to_cursor::IdToCursor};
|
||||
|
||||
|
@ -386,9 +386,9 @@ impl Tracker {
|
|||
return Some(AbsolutePosition {
|
||||
pos: index,
|
||||
side: if is_activated {
|
||||
crate::stable_pos::Side::Middle
|
||||
crate::cursor::Side::Middle
|
||||
} else {
|
||||
crate::stable_pos::Side::Left
|
||||
crate::cursor::Side::Left
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -18,11 +18,11 @@ use crate::{
|
|||
AnchorType, CrdtRopeDelta, RichtextChunk, RichtextChunkValue, RichtextTracker, StyleOp,
|
||||
},
|
||||
},
|
||||
cursor::AbsolutePosition,
|
||||
delta::{Delta, MapDelta, MapValue},
|
||||
event::InternalDiff,
|
||||
op::{RichOp, SliceRange, SliceRanges},
|
||||
span::{HasId, HasLamport},
|
||||
stable_pos::AbsolutePosition,
|
||||
version::Frontiers,
|
||||
InternalString, VersionVector,
|
||||
};
|
||||
|
@ -462,7 +462,7 @@ pub(crate) struct ListDiffCalculator {
|
|||
tracker: Box<RichtextTracker>,
|
||||
}
|
||||
impl ListDiffCalculator {
|
||||
pub(crate) fn get_id_latest_pos(&self, id: ID) -> Option<crate::stable_pos::AbsolutePosition> {
|
||||
pub(crate) fn get_id_latest_pos(&self, id: ID) -> Option<crate::cursor::AbsolutePosition> {
|
||||
self.tracker.get_target_id_latest_index_at_new_version(id)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,9 +7,9 @@ use crate::{
|
|||
richtext::{richtext_state::PosType, RichtextState, StyleOp, TextStyleInfoFlag},
|
||||
tree::tree_op::TreeOp,
|
||||
},
|
||||
cursor::{Cursor, Side},
|
||||
delta::{DeltaItem, StyleMeta, TreeDiffItem, TreeExternalDiff},
|
||||
op::ListSlice,
|
||||
stable_pos::{Cursor, Side},
|
||||
state::{ContainerState, State, TreeParentId},
|
||||
txn::EventHint,
|
||||
utils::{string_slice::StringSlice, utf16::count_utf16_len},
|
||||
|
|
|
@ -15,10 +15,10 @@ pub use handler::{BasicHandler, HandlerTrait, ListHandler, MapHandler, TextHandl
|
|||
pub use loro::LoroDoc;
|
||||
pub use oplog::OpLog;
|
||||
pub use state::DocState;
|
||||
pub mod cursor;
|
||||
pub mod loro;
|
||||
pub mod obs;
|
||||
pub mod oplog;
|
||||
pub mod stable_pos;
|
||||
pub mod txn;
|
||||
|
||||
pub mod change;
|
||||
|
|
|
@ -21,6 +21,7 @@ use crate::{
|
|||
idx::ContainerIdx, list::list_op::InnerListOp, richtext::config::StyleConfigMap,
|
||||
IntoContainerId,
|
||||
},
|
||||
cursor::{AbsolutePosition, CannotFindRelativePosition, Cursor, PosQueryResult},
|
||||
dag::DagUtils,
|
||||
encoding::{
|
||||
decode_snapshot, export_snapshot, parse_header_and_body, EncodeMode, ParsedHeaderAndBody,
|
||||
|
@ -30,7 +31,6 @@ use crate::{
|
|||
id::PeerID,
|
||||
op::InnerContent,
|
||||
oplog::dag::FrontiersNotIncluded,
|
||||
stable_pos::{AbsolutePosition, CannotFindRelativePosition, Cursor, PosQueryResult},
|
||||
version::Frontiers,
|
||||
HandlerTrait, InternalString, LoroError, VersionVector,
|
||||
};
|
||||
|
|
|
@ -14,6 +14,7 @@ use crate::{
|
|||
idx::ContainerIdx, list::list_op::ListOp, map::MapSet, richtext::config::StyleConfigMap,
|
||||
tree::tree_op::TreeOp, ContainerIdRaw,
|
||||
},
|
||||
cursor::Cursor,
|
||||
delta::DeltaItem,
|
||||
encoding::{StateSnapshotDecodeContext, StateSnapshotEncoder},
|
||||
event::{Diff, EventTriggerKind, Index, InternalContainerDiff, InternalDiff},
|
||||
|
@ -21,7 +22,6 @@ use crate::{
|
|||
handler::ValueOrHandler,
|
||||
id::PeerID,
|
||||
op::{ListSlice, Op, RawOp, RawOpContent},
|
||||
stable_pos::Cursor,
|
||||
txn::Transaction,
|
||||
version::Frontiers,
|
||||
ContainerDiff, ContainerType, DocDiff, InternalString, LoroValue,
|
||||
|
@ -1095,7 +1095,7 @@ impl DocState {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
if matches!(pos.side, crate::stable_pos::Side::Left) {
|
||||
if matches!(pos.side, crate::cursor::Side::Left) {
|
||||
return Some(0);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ use loro_internal::{
|
|||
change::Lamport,
|
||||
configure::{StyleConfig, StyleConfigMap},
|
||||
container::{richtext::ExpandType, ContainerID},
|
||||
cursor::{self, Side},
|
||||
encoding::ImportBlobMetadata,
|
||||
event::Index,
|
||||
handler::{
|
||||
|
@ -12,7 +13,6 @@ use loro_internal::{
|
|||
},
|
||||
id::{Counter, TreeID, ID},
|
||||
obs::SubID,
|
||||
stable_pos::{self, Side},
|
||||
version::Frontiers,
|
||||
ContainerType, DiffEvent, HandlerTrait, LoroDoc, LoroValue,
|
||||
VersionVector as InternalVersionVector,
|
||||
|
@ -136,8 +136,8 @@ extern "C" {
|
|||
pub type JsImportBlobMetadata;
|
||||
#[wasm_bindgen(typescript_type = "Side")]
|
||||
pub type JsSide;
|
||||
#[wasm_bindgen(typescript_type = "{ update?: StablePosition, offset: number, side: Side }")]
|
||||
pub type JsStablePosQueryAns;
|
||||
#[wasm_bindgen(typescript_type = "{ update?: Cursor, offset: number, side: Side }")]
|
||||
pub type JsCursorQueryAns;
|
||||
}
|
||||
|
||||
mod observer {
|
||||
|
@ -1135,14 +1135,14 @@ impl Loro {
|
|||
/// expect(ans.offset).toBe(1);
|
||||
/// }
|
||||
/// ```
|
||||
pub fn getCursorPos(&self, stable_pos: &StablePosition) -> JsResult<JsStablePosQueryAns> {
|
||||
pub fn getCursorPos(&self, cursor: &Cursor) -> JsResult<JsCursorQueryAns> {
|
||||
let ans = self
|
||||
.0
|
||||
.query_pos(&stable_pos.pos)
|
||||
.query_pos(&cursor.pos)
|
||||
.map_err(|e| JsError::new(&e.to_string()))?;
|
||||
|
||||
let obj = Object::new();
|
||||
let update = ans.update.map(|u| StablePosition { pos: u });
|
||||
let update = ans.update.map(|u| Cursor { pos: u });
|
||||
if let Some(update) = update {
|
||||
let update_value: JsValue = update.into();
|
||||
Reflect::set(&obj, &JsValue::from_str("update"), &update_value)?;
|
||||
|
@ -1505,7 +1505,7 @@ impl LoroText {
|
|||
}
|
||||
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub fn getCursor(&self, pos: usize, side: JsSide) -> Option<StablePosition> {
|
||||
pub fn getCursor(&self, pos: usize, side: JsSide) -> Option<Cursor> {
|
||||
let mut side_value = Side::Middle;
|
||||
if side.is_truthy() {
|
||||
let num = side.as_f64().expect("Side must be -1 | 0 | 1");
|
||||
|
@ -1513,7 +1513,7 @@ impl LoroText {
|
|||
}
|
||||
self.handler
|
||||
.get_cursor(pos, side_value)
|
||||
.map(|pos| StablePosition { pos })
|
||||
.map(|pos| Cursor { pos })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2131,7 +2131,7 @@ impl LoroList {
|
|||
}
|
||||
|
||||
#[wasm_bindgen(skip_typescript)]
|
||||
pub fn getCursor(&self, pos: usize, side: JsSide) -> Option<StablePosition> {
|
||||
pub fn getCursor(&self, pos: usize, side: JsSide) -> Option<Cursor> {
|
||||
let mut side_value = Side::Middle;
|
||||
if side.is_truthy() {
|
||||
let num = side.as_f64().expect("Side must be -1 | 0 | 1");
|
||||
|
@ -2139,7 +2139,7 @@ impl LoroList {
|
|||
}
|
||||
self.handler
|
||||
.get_cursor(pos, side_value)
|
||||
.map(|pos| StablePosition { pos })
|
||||
.map(|pos| Cursor { pos })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2569,12 +2569,12 @@ impl Default for LoroTree {
|
|||
|
||||
#[derive(Clone)]
|
||||
#[wasm_bindgen]
|
||||
pub struct StablePosition {
|
||||
pos: stable_pos::Cursor,
|
||||
pub struct Cursor {
|
||||
pos: cursor::Cursor,
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
impl StablePosition {
|
||||
impl Cursor {
|
||||
pub fn containerId(&self) -> JsContainerID {
|
||||
let js_value: JsValue = self.pos.container.to_string().into();
|
||||
JsContainerID::from(js_value)
|
||||
|
@ -2592,9 +2592,9 @@ impl StablePosition {
|
|||
|
||||
pub fn side(&self) -> JsSide {
|
||||
JsValue::from(match self.pos.side {
|
||||
stable_pos::Side::Left => -1,
|
||||
stable_pos::Side::Middle => 0,
|
||||
stable_pos::Side::Right => 1,
|
||||
cursor::Side::Left => -1,
|
||||
cursor::Side::Middle => 0,
|
||||
cursor::Side::Right => 1,
|
||||
})
|
||||
.into()
|
||||
}
|
||||
|
@ -2603,10 +2603,9 @@ impl StablePosition {
|
|||
self.pos.encode()
|
||||
}
|
||||
|
||||
pub fn decode(data: &[u8]) -> JsResult<StablePosition> {
|
||||
let pos =
|
||||
stable_pos::Cursor::decode(data).map_err(|e| JsValue::from_str(&e.to_string()))?;
|
||||
Ok(StablePosition { pos })
|
||||
pub fn decode(data: &[u8]) -> JsResult<Cursor> {
|
||||
let pos = cursor::Cursor::decode(data).map_err(|e| JsValue::from_str(&e.to_string()))?;
|
||||
Ok(Cursor { pos })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2940,19 +2939,19 @@ export interface ImportBlobMetadata {
|
|||
|
||||
interface LoroText {
|
||||
/**
|
||||
* Get a stable position representing the cursor position.
|
||||
* Get the cursor position at the given pos.
|
||||
*
|
||||
* When expressing the position of a cursor, using "index" can be unstable
|
||||
* because the cursor's position may change due to other deletions and insertions,
|
||||
* requiring updates with each edit. To stably represent a position or range within
|
||||
* a list structure, we can utilize the ID of each item/character on List CRDT or
|
||||
* Text CRDT for expression.
|
||||
*
|
||||
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
|
||||
* approach complicates tracking cursors since they rely on these IDs. The solution
|
||||
* recalculates position by replaying relevant history to update stable positions
|
||||
* accurately. To minimize the performance impact of history replay, the system
|
||||
* updates cursor info to reference only the IDs of currently present elements,
|
||||
*
|
||||
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
|
||||
* approach complicates tracking cursors since they rely on these IDs. The solution
|
||||
* recalculates position by replaying relevant history to update cursors
|
||||
* accurately. To minimize the performance impact of history replay, the system
|
||||
* updates cursor info to reference only the IDs of currently present elements,
|
||||
* thereby reducing the need for replay.
|
||||
*
|
||||
* @example
|
||||
|
@ -2973,24 +2972,24 @@ interface LoroText {
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
getCursor(pos: number, side?: Side): StablePosition | undefined;
|
||||
getCursor(pos: number, side?: Side): Cursor | undefined;
|
||||
}
|
||||
|
||||
interface LoroList {
|
||||
/**
|
||||
* Get a stable position representing the cursor position.
|
||||
* Get the cursor position at the given pos.
|
||||
*
|
||||
* When expressing the position of a cursor, using "index" can be unstable
|
||||
* because the cursor's position may change due to other deletions and insertions,
|
||||
* requiring updates with each edit. To stably represent a position or range within
|
||||
* a list structure, we can utilize the ID of each item/character on List CRDT or
|
||||
* Text CRDT for expression.
|
||||
*
|
||||
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
|
||||
* approach complicates tracking cursors since they rely on these IDs. The solution
|
||||
* recalculates position by replaying relevant history to update stable positions
|
||||
* accurately. To minimize the performance impact of history replay, the system
|
||||
* updates cursor info to reference only the IDs of currently present elements,
|
||||
*
|
||||
* Loro optimizes State metadata by not storing the IDs of deleted elements. This
|
||||
* approach complicates tracking cursors since they rely on these IDs. The solution
|
||||
* recalculates position by replaying relevant history to update cursors
|
||||
* accurately. To minimize the performance impact of history replay, the system
|
||||
* updates cursor info to reference only the IDs of currently present elements,
|
||||
* thereby reducing the need for replay.
|
||||
*
|
||||
* @example
|
||||
|
@ -3011,7 +3010,7 @@ interface LoroList {
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
getCursor(pos: number, side?: Side): StablePosition | undefined;
|
||||
getCursor(pos: number, side?: Side): Cursor | undefined;
|
||||
}
|
||||
|
||||
export type Side = -1 | 0 | 1;
|
||||
|
|
|
@ -3,13 +3,13 @@ use either::Either;
|
|||
use event::{DiffEvent, Subscriber};
|
||||
use loro_internal::change::Timestamp;
|
||||
use loro_internal::container::IntoContainerId;
|
||||
use loro_internal::cursor::CannotFindRelativePosition;
|
||||
use loro_internal::cursor::Cursor;
|
||||
use loro_internal::cursor::PosQueryResult;
|
||||
use loro_internal::cursor::Side;
|
||||
use loro_internal::encoding::ImportBlobMetadata;
|
||||
use loro_internal::handler::HandlerTrait;
|
||||
use loro_internal::handler::ValueOrHandler;
|
||||
use loro_internal::stable_pos::CannotFindRelativePosition;
|
||||
use loro_internal::stable_pos::Cursor;
|
||||
use loro_internal::stable_pos::PosQueryResult;
|
||||
use loro_internal::stable_pos::Side;
|
||||
use loro_internal::LoroDoc as InnerLoroDoc;
|
||||
use loro_internal::OpLog;
|
||||
|
||||
|
@ -596,7 +596,7 @@ impl LoroList {
|
|||
///
|
||||
/// ```
|
||||
/// use loro::LoroDoc;
|
||||
/// use loro_internal::stable_pos::Side;
|
||||
/// use loro_internal::cursor::Side;
|
||||
///
|
||||
/// let doc = LoroDoc::new();
|
||||
/// let list = doc.get_list("list");
|
||||
|
|
|
@ -49,7 +49,7 @@ fn readme_basic() {
|
|||
#[test]
|
||||
fn get_list_cursor_example() {
|
||||
use loro::LoroDoc;
|
||||
use loro_internal::stable_pos::Side;
|
||||
use loro_internal::cursor::Side;
|
||||
|
||||
let doc = LoroDoc::new();
|
||||
let list = doc.get_list("list");
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { describe, expect, it } from "vitest";
|
||||
import { Delta, Loro, TextDiff } from "../src";
|
||||
import { OpId, setDebug } from "loro-wasm";
|
||||
import { Cursor, OpId, setDebug } from "loro-wasm";
|
||||
|
||||
describe("richtext", () => {
|
||||
it("mark", () => {
|
||||
|
@ -237,12 +237,18 @@ describe("richtext", () => {
|
|||
expect(ans.update).toBeUndefined();
|
||||
}
|
||||
text.insert(0, "abc");
|
||||
const bytes = pos0!.encode();
|
||||
// Sending pos0 over the network
|
||||
const pos0decoded = Cursor.decode(bytes);
|
||||
const docA = new Loro();
|
||||
docA.import(doc.exportFrom());
|
||||
{
|
||||
const ans = doc.getCursorPos(pos0!);
|
||||
const ans = docA.getCursorPos(pos0decoded!);
|
||||
expect(ans.side).toBe(0);
|
||||
expect(ans.offset).toBe(3);
|
||||
expect(ans.update).toBeUndefined();
|
||||
}
|
||||
|
||||
// If "1" is removed from the text, the stable position should be updated
|
||||
text.delete(3, 1); // remove "1", "abc23"
|
||||
doc.commit();
|
||||
|
|
Loading…
Reference in a new issue