Skip to content

Commit

Permalink
feat: add text iter (#400)
Browse files Browse the repository at this point in the history
* feat: add text iter

* doc: fix return error

* doc: add callback explain

* perf: change to iterate spans
  • Loading branch information
Lampese authored Jul 13, 2024
1 parent 00e9c8d commit 2f95480
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 0 deletions.
18 changes: 18 additions & 0 deletions crates/loro-internal/src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1345,6 +1345,24 @@ impl TextHandler {
}
}

pub fn iter(&self, mut callback: impl FnMut(&str) -> bool) -> () {
match &self.inner {
MaybeDetached::Detached(t) => {
let t = t.try_lock().unwrap();
for span in t.value.iter() {
if !callback(span.text.as_str()) {
return;
}
}
}
MaybeDetached::Attached(a) => {
a.with_state(|state| -> () {
state.as_richtext_state_mut().unwrap().iter(callback);
});
}
}
}

/// `pos` is a Event Index:
///
/// - if feature="wasm", pos is a UTF-16 index
Expand Down
8 changes: 8 additions & 0 deletions crates/loro-internal/src/state/richtext_state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ impl RichtextState {
}
}

pub(crate) fn iter(&mut self, mut callback: impl FnMut(&str) -> bool) -> () {
for span in self.state.get_mut().iter() {
if !callback(span.text.as_str()) {
return;
}
}
}

fn get_style_start(
&mut self,
style_starts: &mut FxHashMap<Arc<StyleOp>, Pos>,
Expand Down
38 changes: 38 additions & 0 deletions crates/loro-internal/tests/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1104,3 +1104,41 @@ fn test_delete_utf8_panic_out_bound_len() {
text.insert(0, "Hello").unwrap();
text.delete_utf8(1, 10).unwrap();
}

#[test]
fn test_text_iter() {
let mut str = String::new();
let doc = LoroDoc::new_auto_commit();
let text = doc.get_text("text");
text.insert(0, "Hello").unwrap();
text.insert(1, "Hello").unwrap();
text.iter(|s| {
str.push_str(s);
return true;
});
assert_eq!(str, "HHelloello");
str = String::new();
let mut i = 0;
text.iter(|s| {
if i == 1 {
return false;
}
str.push_str(s);
i = i + 1;
return true;
});
assert_eq!(str, "H");
}

#[test]
fn test_text_iter_detached() {
let mut str = String::new();
let text = TextHandler::new_detached();
text.insert(0, "Hello").unwrap();
text.insert(1, "Hello").unwrap();
text.iter(|s| {
str.push_str(s);
return true;
});
assert_eq!(str, "HHelloello");
}
22 changes: 22 additions & 0 deletions crates/loro-wasm/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1500,6 +1500,28 @@ impl LoroText {
JsValue::from_str("Text").into()
}

/// Iterate each span(internal storage unit) of the text.
///
/// The callback function will be called for each span in the text.
/// If the callback returns `false`, the iteration will stop.
///
/// @example
/// ```ts
/// import { Loro } from "loro-crdt";
///
/// const doc = new Loro();
/// const text = doc.getText("text");
/// text.insert(0, "Hello")
/// text.iter((str) => (console.log(str), true));
/// ```
pub fn iter(&self, callback: &js_sys::Function) {
let context = JsValue::NULL;
self.handler.iter(|c| {
let result = callback.call1(&context, &JsValue::from(c)).unwrap();
result.as_bool().unwrap()
})
}

/// Insert some string at index.
///
/// @example
Expand Down
8 changes: 8 additions & 0 deletions crates/loro/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -978,6 +978,14 @@ impl LoroText {
self.handler.id().clone()
}

/// Iterate each span(internal storage unit) of the text.
///
/// The callback function will be called for each character in the text.
/// If the callback returns `false`, the iteration will stop.
pub fn iter(&self, callback: impl FnMut(&str) -> bool) -> () {
self.handler.iter(callback);
}

/// Insert a string at the given unicode position.
pub fn insert(&self, pos: usize, s: &str) -> LoroResult<()> {
self.handler.insert(pos, s)
Expand Down
11 changes: 11 additions & 0 deletions loro-js/tests/richtext.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,17 @@ describe("richtext", () => {
expect(text.toDelta()).toStrictEqual([
{ insert: "你b"},
]);
});

it("Text iter", () => {
const doc = new Loro();
const text = doc.getText('t');
text.insert(0, "你好");
let str = "";
text.iter((s : string)=>{
str = str + s;
return true;
});
expect(text.toString(), "你好");
});
});

0 comments on commit 2f95480

Please sign in to comment.