Skip to content

Commit

Permalink
feat(clafrica): Implement a cursor
Browse files Browse the repository at this point in the history
  • Loading branch information
pythonbrad committed Apr 30, 2023
1 parent 974d01f commit ef5c2e2
Show file tree
Hide file tree
Showing 2 changed files with 116 additions and 3 deletions.
14 changes: 14 additions & 0 deletions clafrica/data/sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
2a_ á̠
2aa áá
2af_ ɑ̠́
2aff ɑ́ɑ́
2ai_ έ̠
2ee éé
2ia íá
2iaf íɑ́
2ie íé
2ii íí
2oo óó
2ua úá
2uaf úɑ́
2uuaf ʉ́ɑ́
105 changes: 102 additions & 3 deletions clafrica/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,112 @@
use clafrica_lib::bst;
use std::{fmt, rc::Rc};

struct Cursor<'a> {
stack: Vec<&'a str>,
node: &'a bst::Node,
stack: Vec<Rc<bst::Node>>,
root: Rc<bst::Node>,
on_hit: &'a dyn Fn(String),
on_undo: &'a dyn Fn(String),
}

impl Cursor<'_> {
fn hit(&mut self, character: char) {
let root = Rc::clone(&self.root);
let node = self
.stack
.last()
.unwrap_or(&root)
.goto(character)
.unwrap_or(root);

node.take().map(self.on_hit);
self.stack.push(node);
}

fn undo(&mut self) {
let node = self.stack.pop();

node.and_then(|node| node.take().map(self.on_undo));
}

fn to_path(&self) -> Vec<Option<String>> {
self.stack.iter().map(|node| node.take()).collect()
}
}

fn run() {
unimplemented!();
}

#[cfg(test)]
mod tests {}
mod tests {
#[test]
fn test_cursor() {
use crate::Cursor;
use clafrica_lib::utils;
use std::rc::Rc;

macro_rules! hit {
( $cursor:ident $( $c:expr ),* ) => (
$( $cursor.hit($c); )*
);
}

macro_rules! undo {
( $cursor:ident $occ:expr ) => {
(0..$occ).into_iter().for_each(|_| $cursor.undo());
};
}

let data = utils::load_data("data/sample.txt").expect("Failed to load the clafrica code");
let root = utils::build_map(
data.iter()
.map(|e| [e[0].as_str(), e[1].as_str()])
.collect(),
);

let mut cursor = Cursor {
stack: Vec::with_capacity(10),
root: Rc::new(root),
on_hit: &|_| (),
on_undo: &|_| (),
};

hit!(cursor '2', 'i', 'a', 'f');
assert_eq!(
cursor.to_path(),
vec![None, None, Some("íá".to_owned()), Some("íɑ́".to_owned())]
);

undo!(cursor 1);
assert_eq!(cursor.to_path(), vec![None, None, Some("íá".to_owned())]);

undo!(cursor 1);
cursor.hit('e');
assert_eq!(cursor.to_path(), vec![None, None, Some("íé".to_owned())]);

undo!(cursor 2);
hit!(cursor 'o', 'o');
assert_eq!(cursor.to_path(), vec![None, None, Some("óó".to_owned())]);

undo!(cursor 3);
assert_eq!(cursor.to_path(), vec![]);

hit!(
cursor
'2', 'i', 'e', '2', 'a', '_', '2', 'a', 'a',
'2', 'a', 'i', '_', '2', 'a', 'f', 'f', '2',
'o', 'o', '2', 'i', 'a', 'f', '2', 'i', 'a',
'2', 'u', 'a', '2', 'e', 'e', '2', 'u', 'u',
'a', 'f', '2', 'a', 'f', '_', '2', 'i', 'i',
'2', 'u', 'a', 'f', '2', 'i', 'a', 'f'
);
assert_eq!(
cursor
.to_path()
.into_iter()
.filter_map(|e| e)
.collect::<Vec<_>>(),
vec!["íé", "áá", "ɑ́ɑ́", "íá", "íɑ́", "úá", "ʉ́ɑ́", "íí", "íá", "íɑ́"]
);
}
}

0 comments on commit ef5c2e2

Please sign in to comment.