Struct afrim_memory::Cursor

source ·
pub struct Cursor { /* private fields */ }
Expand description

The Cursor permits to keep a track of the different positions while moving in the text buffer.

'\0' - 'k' - '\0' - 'w' - '\0'  '\0'  '\0' - '\'' - 'n' - 'i' - '7' |--> 0
                           |    /|    /                             |
                           |   / |   /                              |
                          'e' / 'e' /                               |--> 1
                           | /   | /                                |
                          '2'   '2'                                 |--> 2
                                                                    |
                                                                    | depth
                                                                    v

§Example

use afrim_memory::{Cursor, Node};
use std::rc::Rc;

let text_buffer = Node::default();
text_buffer.insert(vec!['e', '2'], "é".to_owned());
text_buffer.insert(vec!['i', '7'], "ǐ".to_owned());

// We build our cursor.
let memory = Rc::new(text_buffer);
let mut cursor = Cursor::new(memory, 16);
let input = "nkwe2e2'ni7";
input.chars().for_each(|c| { cursor.hit(c); });

assert_eq!(
    cursor.to_sequence(),
    vec![
        'k', '\0', 'w', '\0', 'e', '2', '\0', 'e', '2', '\0',
        '\'', '\0', 'n', '\0', 'i', '7'
    ]
);

Note the partitioning of this input. The cursor can browse through the memory based on an input and save a track of his positions. It’s useful when we want handle backspace operations in an input method engine.

Implementations§

source§

impl Cursor

source

pub fn new(root: Rc<Node>, capacity: usize) -> Self

Initializes the cursor of a text buffer.

capacity is the number of hit that the cursor can track. The cursor follows the FIFO rule. If the capacity is exceeded, the oldest hit will be discarded.

Note: Be careful when you set this capacity. We recommend to select a capacity equal or greater than the maximun sequence length that you want handle.

§Example
use afrim_memory::{Cursor, Node};
use std::rc::Rc;

let text_buffer = Node::default();
let memory = Rc::new(text_buffer);

// A cursor of our text buffer.
let cursor = Cursor::new(memory, 16);

Note: It’s recommended to initialize the text buffer with Node::default to evict unexpected behaviors.

source

pub fn hit(&mut self, character: char) -> Option<String>

Enters a character in the sequence and returns his corresponding out.

Permits to simulate the user typing in the input method engine. For each character entered, the cursor will move through the text buffer in looking of the corresponding sequence. If the sequence is got (end on a value), his value will be returned.

§Example
use afrim_memory::{Cursor, Node};
use std::rc::Rc;

let text_buffer = Node::default();
text_buffer.insert(vec!['o', 'e'], "œ".to_owned());
let memory = Rc::new(text_buffer);

let mut cursor = Cursor::new(memory, 16);
// let input= "coeur";
assert_eq!(cursor.hit('c'), None);
assert_eq!(cursor.hit('o'), None);
assert_eq!(cursor.hit('e'), Some("œ".to_owned()));
assert_eq!(cursor.hit('u'), None);
assert_eq!(cursor.hit('r'), None);

assert_eq!(cursor.to_sequence(), vec!['\0', 'c', '\0', 'o', 'e', '\0', 'u', '\0', 'r']);

Note:

  • The \0 at the index 0, marks the beginning of a new sequence and the end of a old. It also represents the root node.
  • A character don’t necessary need to be in the text buffer. The cursor will create a tempory node to represent it in his internal memory. All characters not present in the text buffer will be at the same depth that the root node.
source

pub fn undo(&mut self) -> Option<String>

Removes the last node and returns his corresponding out. Or simplily, undo the previous hit.

Useful to simulate a backspace operation.

§Example
use afrim_memory::{Cursor, Node};
use std::rc::Rc;

let text_buffer = Node::default();
text_buffer.insert(vec!['o', 'e'], "œ".to_owned());
let memory = Rc::new(text_buffer);

let mut cursor = Cursor::new(memory, 16);
// let input = "coeur";
assert_eq!(cursor.hit('c'), None);
assert_eq!(cursor.hit('o'), None);
assert_eq!(cursor.hit('e'), Some("œ".to_owned()));
assert_eq!(cursor.hit('u'), None);
assert_eq!(cursor.hit('r'), None);

// Undo
assert_eq!(cursor.undo(), None);
assert_eq!(cursor.undo(), None);
assert_eq!(cursor.undo(), Some("œ".to_owned()));
assert_eq!(cursor.undo(), None);
assert_eq!(cursor.undo(), None);

assert_eq!(cursor.to_sequence(), vec!['\0']);

Note: Look at the \0 at the end. It represents the root node, and the start of a new sequence. Even if you remove it until obtain an empty buffer, the cursor will add it before each new sequence. You can considere it as a delimiter between two sequences. But if you want clear or verify if the buffer is empty, you can use Cursor::clear or Cursor::is_empty.

source

pub fn state(&self) -> (Option<String>, usize, char)

Returns the current state of the cursor.

Permits to know the current position in the memory and also the last hit.

§Example
use afrim_memory::{Cursor, Node};
use std::rc::Rc;

let text_buffer = Node::default();
text_buffer.insert(vec!['o', '/'], "ø".to_owned());
let memory = Rc::new(text_buffer);

let mut cursor = Cursor::new(memory, 8);
// The cursor starts always at the root node.
assert_eq!(cursor.state(), (None, 0, '\0'));
cursor.hit('o');
assert_eq!(cursor.state(), (None, 1, 'o'));
source

pub fn to_sequence(&self) -> Vec<char>

Returns the current sequence in the cursor.

It’s always useful to know what is inside the memory of the cursor for debugging / logging. The

§Example
use afrim_memory::{Cursor, Node};
use std::rc::Rc;

let text_buffer = Node::default();
text_buffer.insert(vec!['.', '.', 'z'], "z̈".to_owned());
let memory = Rc::new(text_buffer);

let mut cursor = Cursor::new(memory, 8);
"z..z".chars().for_each(|c| { cursor.hit(c); });

assert_eq!(cursor.to_sequence(), vec!['\0', 'z', '\0', '.', '.', 'z']);
source

pub fn clear(&mut self)

Clear the memory of the cursor.

In clearing the internal buffer, all the tracking information will be lost.

§Example
use afrim_memory::{Cursor, Node};
use std::rc::Rc;

let text_buffer = Node::default();
let memory = Rc::new(text_buffer);
let mut cursor = Cursor::new(memory, 8);

"hello".chars().for_each(|c| { cursor.hit(c); });
assert!(!cursor.is_empty());

cursor.clear();
assert!(cursor.is_empty());
source

pub fn is_empty(&self) -> bool

Verify if the cursor is empty.

§Example
use afrim_memory::{Cursor, Node};
use std::rc::Rc;

let text_buffer = Node::default();
let memory = Rc::new(text_buffer);

let mut cursor = Cursor::new(memory, 8);
assert!(cursor.is_empty());

cursor.hit('a');
assert!(!cursor.is_empty());

Trait Implementations§

source§

impl Clone for Cursor

source§

fn clone(&self) -> Cursor

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for Cursor

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

§

impl !RefUnwindSafe for Cursor

§

impl !Send for Cursor

§

impl !Sync for Cursor

§

impl Unpin for Cursor

§

impl !UnwindSafe for Cursor

Blanket Implementations§

source§

impl<T> Any for T
where T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

source§

impl<T, U> Into<U> for T
where U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

source§

impl<T> ToOwned for T
where T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.