use crate::{
Language,
tree::{GreenNode, GreenTree},
};
#[derive(Debug, Clone)]
pub struct Cursor<'a, L: Language> {
current: GreenTree<'a, L>,
offset: usize,
stack: Vec<(&'a GreenNode<'a, L>, usize, usize)>,
}
impl<'a, L: Language> Cursor<'a, L> {
pub fn new(root: &'a GreenNode<'a, L>) -> Self {
Self { current: GreenTree::Node(root), offset: 0, stack: Vec::with_capacity(16) }
}
#[inline]
pub fn current(&self) -> GreenTree<'a, L> {
self.current
}
#[inline]
pub fn as_node(&self) -> Option<&'a GreenNode<'a, L>> {
match self.current {
GreenTree::Node(n) => Some(n),
GreenTree::Leaf(_) => None,
}
}
#[inline]
pub fn offset(&self) -> usize {
self.offset
}
#[inline]
pub fn len(&self) -> usize {
self.current.len() as usize
}
#[inline]
pub fn end_offset(&self) -> usize {
self.offset + self.len()
}
pub fn step_into(&mut self) -> bool {
match self.current {
GreenTree::Node(node) => {
if let Some(first_child) = node.children.first() {
self.stack.push((node, 0, self.offset));
self.current = *first_child;
true
}
else {
false
}
}
GreenTree::Leaf(_) => false,
}
}
pub fn step_over(&mut self) -> bool {
if let Some((parent, idx, _parent_offset)) = self.stack.last() {
let next_idx = idx + 1;
if let Some(sibling) = parent.children.get(next_idx) {
self.offset += self.current.len() as usize;
let last = self.stack.last_mut().unwrap();
last.1 = next_idx;
self.current = *sibling;
true
}
else {
false
}
}
else {
false
}
}
pub fn step_out(&mut self) -> bool {
if let Some((parent, _, parent_offset)) = self.stack.pop() {
self.current = GreenTree::Node(parent);
self.offset = parent_offset;
true
}
else {
false
}
}
pub fn step(&mut self) -> bool {
if self.step_into() {
return true;
}
if self.step_over() {
return true;
}
while self.step_out() {
if self.step_over() {
return true;
}
}
false
}
pub fn step_next(&mut self) -> bool {
if self.step_over() {
true
}
else {
while self.step_out() {
if self.step_over() {
return true;
}
}
false
}
}
}