diff --git a/issues.md b/issues.md index 107b8f2..4b879f7 100644 --- a/issues.md +++ b/issues.md @@ -7,6 +7,7 @@ - explicit and implicit write support (policy, include readonly) - fix tests, todo!() and TODO: in code +- change search: multiple path indices for one cell - support type selector: `hial './src/tests/rust.rs^rust/:function_item'` - support rust/ts write: `hial './src/tests/rust.rs^rust/:function_item[-1]#label = "modified_fn_name"'` - set value on the command line diff --git a/src/base/error.rs b/src/base/error.rs index 6db998a..25bf4eb 100644 --- a/src/base/error.rs +++ b/src/base/error.rs @@ -291,10 +291,6 @@ impl GroupTrait for HErr { Err(self.clone()) } - fn get(&self, label: Value<'_>) -> Res { - Err(self.clone()) - } - fn get_all(&self, label: Value<'_>) -> Res { Err(self.clone()) } diff --git a/src/base/extra.rs b/src/base/extra.rs index 8237265..cf6d6fa 100644 --- a/src/base/extra.rs +++ b/src/base/extra.rs @@ -234,22 +234,6 @@ impl From for Cell { } } -impl fmt::Debug for Cell { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let orig = format!("{:?}", self.domain.origin).replace('\n', "\n\t"); - let root = format!("{:?}", self.domain.dyn_root).replace('\n', "\n\t"); - write!( - f, - "Cell{{\n\tdyn_cell={:?}, \n\tdomain={{ write_policy={:?}, is_dirty={}, root={}, origin={} }}", - self.dyn_cell, - self.domain.write_policy.get(), - self.domain.dirty.get(), - root, - orig, - ) - } -} - impl CellReaderTrait for CellReader { fn ty(&self) -> Res<&str> { dispatch_dyn_cell_reader!(&self.0, |x| { x.ty() }) @@ -649,18 +633,34 @@ impl Cell { } } +impl fmt::Debug for Cell { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let orig = format!("{:?}", self.domain.origin).replace('\n', "\n\t"); + let root = format!("{:?}", self.domain.dyn_root).replace('\n', "\n\t"); + write!( + f, + "Cell{{\n\tdyn_cell={:?}, \n\tdomain={{ write_policy={:?}, is_dirty={}, root={}, origin={} }}", + self.dyn_cell, + self.domain.write_policy.get(), + self.domain.dirty.get(), + root, + orig, + ) + } +} + impl fmt::Debug for Domain { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!( f, - "Domain{{ dyn_root={:?}, origin={:?} write_policy={:?}, is_dirty={} }}", + "Domain{{ write_policy={:?}, is_dirty={} root={:?}, origin={:?} }}", + self.write_policy.get(), + self.dirty.get(), self.dyn_root.get(), self.origin .as_ref() .map(|c| c.path().unwrap_or("".into())) .unwrap_or_default(), - self.write_policy.get(), - self.dirty.get() ) } } @@ -780,8 +780,12 @@ impl Group { GroupKind::Dyn { dyn_group, domain } => { dispatch_dyn_group!(dyn_group, |x| { Cell { - dyn_cell: match x.get(key) { - Ok(c) => DynCell::from(c), + dyn_cell: match x.get_all(key) { + Ok(mut iter) => match iter.next() { + Some(Ok(cell)) => DynCell::from(cell), + Some(Err(err)) => DynCell::from(err), + None => DynCell::from(noerr()), + }, Err(e) => DynCell::from(e), }, domain: Rc::clone(domain), @@ -831,8 +835,18 @@ impl Group { }, } } - GroupKind::Elevation(elevation_group) => CellIterator { - cell_iterator: CellIteratorKind::Elevation(elevation_group.get(key)), + GroupKind::Elevation(elevation_group) => match elevation_group.get(key) { + Ok(c) => { + if let Err(ref old_cell) = c.domain.dyn_root.set(c.dyn_cell.clone()) { + warning!("❗️cannot overwrite domain dyn_root: {:?}", old_cell); + } + CellIterator { + cell_iterator: CellIteratorKind::Elevation(Ok(c)), + } + } + Err(e) => CellIterator { + cell_iterator: CellIteratorKind::Elevation(Err(e)), + }, }, } } @@ -888,16 +902,26 @@ impl Iterator for CellIterator { }) } CellIteratorKind::Elevation(cell_res) => match cell_res { - Ok(cell) => Some(cell.clone()), - Err(err) => Some(Cell { - dyn_cell: DynCell::from(err.clone()), - domain: Rc::new(Domain { - write_policy: cell::Cell::new(WritePolicy::ReadOnly), - origin: None, - dyn_root: OnceCell::new(), - dirty: cell::Cell::new(false), - }), - }), + Ok(cell) => { + let cell = cell.clone(); + *cell_res = nores(); + Some(cell) + } + Err(err) => { + if err.kind == HErrKind::None { + None + } else { + Some(Cell { + dyn_cell: DynCell::from(err.clone()), + domain: Rc::new(Domain { + write_policy: cell::Cell::new(WritePolicy::ReadOnly), + origin: None, + dyn_root: OnceCell::new(), + dirty: cell::Cell::new(false), + }), + }) + } + } }, } } diff --git a/src/base/field.rs b/src/base/field.rs index b922f0f..30a8410 100644 --- a/src/base/field.rs +++ b/src/base/field.rs @@ -100,23 +100,20 @@ impl GroupTrait for FieldGroup { }) } - fn get(&self, label: Value) -> Res { - if let Value::Str(l) = label { - return match l { + fn get_all(&self, label: Value) -> Res { + let cell = if let Value::Str(l) = label { + match l { "value" => self.at(FieldType::Value as usize), "label" => self.at(FieldType::Label as usize), "type" => self.at(FieldType::Type as usize), "index" => self.at(FieldType::Index as usize), "serial" => self.at(FieldType::Serial as usize), - _ => nores(), - }; - } - nores() - } - - fn get_all(&self, label: Value) -> Res { - let cell = self.get(label)?; - Ok(std::iter::once(Ok(cell))) + _ => return nores(), + } + } else { + return nores(); + }; + Ok(std::iter::once(cell)) } } diff --git a/src/base/intra.rs b/src/base/intra.rs index b6606d7..0fb40f1 100644 --- a/src/base/intra.rs +++ b/src/base/intra.rs @@ -69,7 +69,6 @@ pub trait GroupTrait: Clone + Debug { self.len().map_or(false, |l| l == 0) } fn at(&self, index: usize) -> Res; - fn get(&self, label: Value<'_>) -> Res; fn get_all(&self, label: Value<'_>) -> Res; fn add(&mut self) -> Res<()> { @@ -100,10 +99,6 @@ impl GroupTrait for VoidGroup { nores() } - fn get(&self, key: Value) -> Res { - nores() - } - fn get_all(&self, label: Value) -> Res { nores() } diff --git a/src/interpretations/fs.rs b/src/interpretations/fs.rs index 46ed9a5..3514d66 100644 --- a/src/interpretations/fs.rs +++ b/src/interpretations/fs.rs @@ -472,8 +472,8 @@ impl GroupTrait for Group { } } - fn get(&self, key: Value) -> Res { - match self.ty { + fn get_all(&self, key: Value) -> Res { + let cell = match self.ty { GroupType::Folder => { let files = self .files @@ -498,12 +498,8 @@ impl GroupTrait for Group { nores() } } - } - } - - fn get_all(&self, key: Value) -> Res { - let cell = self.get(key)?; - Ok(std::iter::once(Ok(cell))) + }; + Ok(std::iter::once(cell)) } } diff --git a/src/interpretations/http.rs b/src/interpretations/http.rs index 0c6595c..2356302 100644 --- a/src/interpretations/http.rs +++ b/src/interpretations/http.rs @@ -301,8 +301,8 @@ impl GroupTrait for Group { } } - fn get(&self, key: Value) -> Res { - match (self.kind, key) { + fn get_all(&self, key: Value) -> Res { + let cell = match (self.kind, key) { (GroupKind::Attr, sel) if sel == "status" => Ok(Cell { group: self.clone(), pos: 0, @@ -336,11 +336,7 @@ impl GroupTrait for Group { } } _ => nores(), - } - } - - fn get_all(&self, key: Value) -> Res { - let cell = self.get(key); + }; Ok(std::iter::once(cell)) } } diff --git a/src/interpretations/json.rs b/src/interpretations/json.rs index 9176772..999e4bc 100644 --- a/src/interpretations/json.rs +++ b/src/interpretations/json.rs @@ -401,8 +401,8 @@ impl GroupTrait for Group { } } - fn get(&self, key: Value) -> Res { - match &self.nodes { + fn get_all(&self, key: Value) -> Res { + let cell = match &self.nodes { NodeGroup::Array(a) => nores(), NodeGroup::Object(o) => match key { Value::Str(k) => match o @@ -418,12 +418,8 @@ impl GroupTrait for Group { }, _ => nores(), }, - } - } - - fn get_all(&self, key: Value) -> Res { - let cell = self.get(key)?; - Ok(std::iter::once(Ok(cell))) + }; + Ok(std::iter::once(cell)) } } diff --git a/src/interpretations/toml.rs b/src/interpretations/toml.rs index 9a276c8..e0fd682 100644 --- a/src/interpretations/toml.rs +++ b/src/interpretations/toml.rs @@ -282,25 +282,6 @@ impl GroupTrait for Group { } } - fn get(&self, key: Value) -> Res { - match &self.nodes { - NodeGroup::Array(a) => nores(), - NodeGroup::Table(t) => match key { - Value::Str(k) => { - let t = t.read().ok_or_else(|| lockerr("cannot read group"))?; - match t.get_index_of(k) { - Some(pos) => Ok(Cell { - group: self.clone(), - pos, - }), - _ => nores(), - } - } - _ => nores(), - }, - } - } - fn len(&self) -> Res { Ok(match &self.nodes { NodeGroup::Array(a) => a.read().ok_or_else(|| lockerr("cannot read group"))?.len(), @@ -324,8 +305,23 @@ impl GroupTrait for Group { } fn get_all(&self, key: Value) -> Res { - let cell = self.get(key)?; - Ok(std::iter::once(Ok(cell))) + let cell = match &self.nodes { + NodeGroup::Array(a) => nores(), + NodeGroup::Table(t) => match key { + Value::Str(k) => { + let t = t.read().ok_or_else(|| lockerr("cannot read group"))?; + match t.get_index_of(k) { + Some(pos) => Ok(Cell { + group: self.clone(), + pos, + }), + _ => nores(), + } + } + _ => nores(), + }, + }; + Ok(std::iter::once(cell)) } } diff --git a/src/interpretations/treesitter.rs b/src/interpretations/treesitter.rs index 3397626..32aa56c 100644 --- a/src/interpretations/treesitter.rs +++ b/src/interpretations/treesitter.rs @@ -297,18 +297,19 @@ impl GroupTrait for Cell { }) } - fn get(&self, key: Value) -> Res { + fn get_all(&self, key: Value) -> Res { let mut cursor = self.cursor.clone(); if !cursor.goto_first_child() { return nores(); } for i in 0..self.cursor.node().child_count() { if key == cursor.field_name().unwrap_or_default() { - return Ok(Cell { + let cell = Cell { domain: self.domain.clone(), cursor, position: i, - }); + }; + return Ok(std::iter::once(Ok(cell))); } if !cursor.goto_next_sibling() { return nores(); @@ -316,9 +317,4 @@ impl GroupTrait for Cell { } nores() } - - fn get_all(&self, key: Value) -> Res { - let cell = self.get(key); - Ok(std::iter::once(cell)) - } } diff --git a/src/interpretations/xml.rs b/src/interpretations/xml.rs index a9273ef..c5581e7 100644 --- a/src/interpretations/xml.rs +++ b/src/interpretations/xml.rs @@ -586,8 +586,7 @@ impl Iterator for CellIterator { let cell = this.group.at(this.next_pos)?; this.next_pos += 1; let reader = cell.read()?; - let k = reader.label()?; - if this.key.as_value() == k { + if Some(this.key.as_value()) == reader.label().ok() { return Ok(cell); } } @@ -639,21 +638,6 @@ impl GroupTrait for Group { }) } - fn get(&self, key: Value) -> Res { - for i in 0..self.len()? { - if let Ok(cell) = self.at(i) { - if let Ok(reader) = cell.read() { - if let Ok(k) = reader.label() { - if key == k { - return Ok(cell); - } - } - } - } - } - nores() - } - fn get_all(&self, key: Value) -> Res { Ok(CellIterator { group: self.clone(), diff --git a/src/interpretations/yaml.rs b/src/interpretations/yaml.rs index 95006e3..63228f6 100644 --- a/src/interpretations/yaml.rs +++ b/src/interpretations/yaml.rs @@ -381,8 +381,8 @@ impl GroupTrait for Group { } } - fn get(&self, key: Value) -> Res { - match &self.nodes { + fn get_all(&self, key: Value) -> Res { + let cell = match &self.nodes { NodeGroup::Array(a) => nores(), NodeGroup::Object(o) => match key { Value::Str(k) => { @@ -397,12 +397,8 @@ impl GroupTrait for Group { } _ => nores(), }, - } - } - - fn get_all(&self, key: Value) -> Res { - let cell = self.get(key)?; - Ok(std::iter::once(Ok(cell))) + }; + Ok(std::iter::once(cell)) } } diff --git a/src/pathlang/search.rs b/src/pathlang/search.rs index 21ab08a..74236c6 100644 --- a/src/pathlang/search.rs +++ b/src/pathlang/search.rs @@ -123,14 +123,15 @@ impl<'s> Searcher<'s> { if path_index >= self.path.len() { return Some(Ok(parent)); } + let pi = &self.path[path_index]; ifdebug!(println!( - "test children of `{}` against index {}", + "test children of `{}` against `{}` (path index {})", parent.debug_string(), + pi, path_index )); - let pi = &self.path[path_index]; let group = match pi.relation { Relation::Sub => parent.sub(), Relation::Attr => parent.attr(), @@ -163,7 +164,7 @@ impl<'s> Searcher<'s> { Self::process_cell( &mut self.stack, &self.path, - &parent, + parent, path_index, true, &mut self.next_max_path_index, @@ -180,7 +181,7 @@ impl<'s> Searcher<'s> { group: Group, path_index: usize, next_max_path_index: &mut usize, - ) -> Option> { + ) { let pi = &path[path_index]; match (pi.selector, pi.index) { (Some(Selector::Star) | Some(Selector::DoubleStar), None) => { @@ -193,71 +194,77 @@ impl<'s> Searcher<'s> { Self::process_cell( stack, path, - &cell, + cell, path_index, pi.selector != Some(Selector::DoubleStar), next_max_path_index, ) } } - (selector, Some(index)) => { + (None | Some(Selector::Star) | Some(Selector::DoubleStar), Some(index)) => { ifdebug!(println!("get child by index")); let cell = guard_ok!(group.at(index).err(), err => { if err.kind != HErrKind::None { warning!("Error while searching: cannot get cell: {:?}", err); } - return None; + return ; }); - if let Some(Selector::Str(label)) = selector { - if cell.read().label().unwrap_or(Value::None) != Value::Str(label) { - ifdebug!(println!("cell by index but label does not match selector")); - return None; - } - } Self::process_cell( stack, path, - &cell, + cell, path_index, - selector != Some(Selector::DoubleStar), + pi.selector != Some(Selector::DoubleStar), next_max_path_index, ); } - (Some(Selector::Str(label)), None) => { + (Some(Selector::Str(label)), opt_index) => { ifdebug!(println!("iterating over children by label")); - let iter = guard_ok!(group.get_all(label).err(), err => { + let mut iter = guard_ok!(group.get_all(label).err(), err => { if err.kind != HErrKind::None { warning!("Error while searching: cannot get cell iterator: {:?}", err); } - return None; + return ; }); - for cell in iter { - Self::process_cell(stack, path, &cell, path_index, true, next_max_path_index) + if let Some(index) = opt_index { + if let Some(cell) = iter.nth(index) { + Self::process_cell(stack, path, cell, path_index, true, next_max_path_index) + } + } else { + for cell in iter { + Self::process_cell(stack, path, cell, path_index, true, next_max_path_index) + } } } (None, None) => { - return Some(userres("missing both selector and index in search")); + warning!("missing both selector and index in search"); } (Some(Selector::Top), _) => { - return Some(userres("Selector::Top not supported in search")); + warning!("Selector::Top not supported in search"); } } - None } fn process_cell( stack: &mut Vec, path: &[PathItem], - cell: &Cell, + cell: Cell, path_index: usize, advance_index: bool, next_max_path_index: &mut usize, ) { + let cell = guard_ok!(cell.err(), err => { + if err.kind != HErrKind::None { + warning!("Error while searching: cannot get cell: {:?}", err); + } + return; + }); + let pi = &path[path_index]; ifdebug!(println!("test: `{}` for {}", cell.debug_string(), pi)); - if !Self::eval_filters_match(cell, pi) { + if !Self::eval_filters_match(&cell, pi) { ifdebug!(println!("no match `{}` for {}", cell.debug_string(), pi)); return; } diff --git a/src/tests/nested.rs b/src/tests/nested.rs index 50fa62e..6270c92 100644 --- a/src/tests/nested.rs +++ b/src/tests/nested.rs @@ -1,7 +1,7 @@ -use crate::{base::*, utils::log::set_verbose}; +use crate::{base::*, pprint::pprint, utils::log::set_verbose}; #[test] -fn test_nested() -> Res<()> { +fn test_nested_0() -> Res<()> { set_verbose(true); let yxj = r#"{"one": ["mytext: This is my yaml string"]}"#; @@ -45,13 +45,13 @@ fn test_nested_mut() -> Res<()> { .sub() .get("mytext"); println!("4"); - assert_eq!(mytext.read().value()?, "yaml string"); } println!("5"); { let cell = text.to("^json/one/[0]^xml/root/a^yaml/mytext"); + pprint(&cell, 0, 0); println!("6"); assert_eq!(cell.read().value()?, "yaml string"); println!("7"); diff --git a/src/tests/search.rs b/src/tests/search.rs index 2a66fbd..f905b3f 100644 --- a/src/tests/search.rs +++ b/src/tests/search.rs @@ -111,6 +111,13 @@ fn search_simple_search() -> Res<()> { fn search_simple_search_with_index() -> Res<()> { const TREE: &str = r#" + + 1 + + + 2 + + 1 @@ -120,18 +127,19 @@ fn search_simple_search_with_index() -> Res<()> { 3 + "#; let root = Cell::from(TREE).be("xml"); pprint(&root, 0, 0); - let eval = str_eval(root.clone(), "/test/a[0]")?; + let eval = str_eval(root.clone(), "/test/a[0]/*")?; assert_eq!(eval, ["x:1"]); - let eval = str_eval(root.clone(), "/test/a[1]")?; + let eval = str_eval(root.clone(), "/test/a[1]/*")?; assert_eq!(eval, ["y:2"]); - let eval = str_eval(root.clone(), "/test/a[2]")?; + let eval = str_eval(root.clone(), "/test/a[2]/*")?; assert_eq!(eval, ["z:3"]); Ok(()) @@ -412,13 +420,13 @@ fn search_double_kleene_repeat() -> Res<()> { set_verbose(true); let root = Cell::from(TREE).be("yaml"); - // pprint(&root, 0, 0); - // let eval = str_eval(root.clone(), "/**/b/b")?; - // assert_eq!(eval, ["b:", "b:bval"]); + pprint(&root, 0, 0); + let eval = str_eval(root.clone(), "/**/b/b")?; + assert_eq!(eval, ["b:", "b:bval"]); pprint(&root, 0, 0); let eval = str_eval(root.clone(), "/**/b/**/b")?; - assert_eq!(eval, ["b:", "b:bval"]); + assert_eq!(eval, ["b:", "b:bval", "b:bval"]); // two ways to reach node b:bval Ok(()) }