From 2b6c383b3a168397927821a600bbda00ec667568 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 19:16:16 +1000 Subject: [PATCH 01/21] chore: adding test case for lists --- sample/b_.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 sample/b_.json diff --git a/sample/b_.json b/sample/b_.json new file mode 100644 index 0000000..c87e2f5 --- /dev/null +++ b/sample/b_.json @@ -0,0 +1,19 @@ +{ + "name": "abc", + "hello": 1, + "nested": [ + { + "attr": { + "bbb": 1 + } + }, + { + "attr": { + "bbb": 2 + } + } + ], + "another_nested": { + "b": "bbb" + } +} \ No newline at end of file From 701207da668ed40a24306410ab605508bc1917bc Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 19:44:13 +1000 Subject: [PATCH 02/21] feat: updating the core parsing logic for this refactor --- jdora/src/library/internal/README.md | 10 ++++ jdora/src/library/internal/node.rs | 85 +++++++++++++++++++--------- jdora/src/library/internal/parser.rs | 23 ++++++++ 3 files changed, 91 insertions(+), 27 deletions(-) create mode 100644 jdora/src/library/internal/README.md diff --git a/jdora/src/library/internal/README.md b/jdora/src/library/internal/README.md new file mode 100644 index 0000000..05abe35 --- /dev/null +++ b/jdora/src/library/internal/README.md @@ -0,0 +1,10 @@ +NOTES: +every node has indent level, node_path. +then its children are separated into: + +primitives +or children + +but I dont think it should do that. + +i need another, for lists. \ No newline at end of file diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index c268e32..e0f069c 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -11,71 +11,102 @@ const INDENT_SIZE: u16 = 4; // i only consider // Dictionaries as nodes. +#[derive(Debug)] +pub enum NodeType { + PrimitiveNode, + IterableNodes, + ChildNode, +} + +#[derive(Debug)] +pub struct ParsedNodePacket { + key: String, // key from json + node: Node, // Node with type information +} + + #[derive(Debug)] pub struct Node { // serde_node: Value, // forwards to serde node pub node_path: NodePath, + pub node_type: NodeType, pub indent_level: u16, - pub primitives: Vec<(String, Value)>, // primitive attributes + // pub primitives: Vec<(String, Value)>, // primitive attributes // NOTE i understand I don't handle lists well....at all right now... - pub children: Vec<(String, Node)>, + pub children: Vec, // hidden_children: pub hidden_children: Vec, } impl Node { - pub fn new(val: Value, node_path: NodePath) -> Option { - if !matches!(val, Value::Object(_)) { - return None - } + pub fn new(val: Value, node_path: NodePath, node_type: NodeType) -> Self { + // if !matches!(val, Value::Object(_)) { + // return None + // } - let (primitives, children) = Node::parse(&val, &node_path); + let children = Node::parse(&val, &node_path); Some(Self{ // serde_node: val, node_path: node_path.clone(), + node_type: node_type, indent_level: (node_path.path.len() as u16), - primitives: primitives, children: children, hidden_children: Vec::new(), }) } - pub fn parse(serde_node: &Value, node_path: &NodePath) -> ( - Vec<(String, Value)>, // primitives - Vec<(String, Node)>, // nested nodes - ){ + pub fn parse(serde_node: &Value, node_path: &NodePath) -> Vec { if let Value::Object(map) = &serde_node { - // node primitives - let mut primitives: Vec<(String, Value)> = Vec::new(); - let mut children: Vec<(String, Node)> = Vec::new(); + let mut children: Vec = Vec::new(); for (key, val) in map.iter() { match val { Value::Object(_) => { children.push( - ( - key.to_string(), - Node::new( + ParsedNodePacket{ + key: key.to_string(), + node: Node::new( val.clone(), node_path.push_and_clone( NodePathKey::DictKey(key.to_string()) - ) - ).unwrap() - ) + ), + NodeType::ChildNode, + ), + } ) } + Value::Array(_) => { + children.push( + ParsedNodePacket{ + key: key.to_string(), + node: Node::new( + val.clone(), + node_path.push_and_clone( + NodePathKey::DictKey(key.to_string()) + ), + NodeType::IterableNodes, + ), + } + ) + } _ => { - primitives.push( - (key.to_string(), val.clone()) + children.push( + ParsedNodePacket{ + key: key.to_string(), + node: Node::new( + val.clone(), + node_path.push_and_clone( + NodePathKey::DictKey(key.to_string()) + ), + NodeType::PrimitiveNode, + ), + } ) } } } - return ( - primitives, - children, - ) + return children } else { panic!("parse failed? node is not an object") } diff --git a/jdora/src/library/internal/parser.rs b/jdora/src/library/internal/parser.rs index bc347a8..5ee0ed1 100644 --- a/jdora/src/library/internal/parser.rs +++ b/jdora/src/library/internal/parser.rs @@ -96,4 +96,27 @@ mod tests { println!("{}", n.pprint()); assert!( 1 == 0 ); } + + #[test] + fn test_f() { + let data = r#" + { + "name": "abc", + "hello": 1, + "nested": [ + { + "attr": { + "bbb": 100 + } + } + ], + "another_nested": { + "b": "bbb" + } + }"#; + let mut n = parse(data); + println!("{:?}", n.get_structures()); + println!("{}", n.pprint()); + assert!( 1 == 0 ); + } } \ No newline at end of file From a92edfddf914e52ab026ec3cd6e777039d5dc683 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 20:11:44 +1000 Subject: [PATCH 03/21] feat: save more refactors --- jdora/src/library/internal/node.rs | 130 +++++++++++++++++------------ 1 file changed, 75 insertions(+), 55 deletions(-) diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index e0f069c..bbbf196 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -3,6 +3,8 @@ use std::primitive; use serde_json::{Map, Value}; +use crate::library::internal::node; + use super::node_path::{self, NodePath, NodePathKey}; @@ -12,16 +14,16 @@ const INDENT_SIZE: u16 = 4; // Dictionaries as nodes. #[derive(Debug)] -pub enum NodeType { - PrimitiveNode, - IterableNodes, - ChildNode, +pub enum AnyNode { + PrimitiveNode(Value), + IterableNodes(Vec), + NestedNode(Node), } #[derive(Debug)] pub struct ParsedNodePacket { key: String, // key from json - node: Node, // Node with type information + node: AnyNode, // Node with type information } @@ -29,7 +31,6 @@ pub struct ParsedNodePacket { pub struct Node { // serde_node: Value, // forwards to serde node pub node_path: NodePath, - pub node_type: NodeType, pub indent_level: u16, // pub primitives: Vec<(String, Value)>, // primitive attributes // NOTE i understand I don't handle lists well....at all right now... @@ -40,20 +41,19 @@ pub struct Node { } impl Node { - pub fn new(val: Value, node_path: NodePath, node_type: NodeType) -> Self { + pub fn new(val: Value, node_path: NodePath) -> Self { // if !matches!(val, Value::Object(_)) { // return None // } let children = Node::parse(&val, &node_path); - Some(Self{ + Self{ // serde_node: val, node_path: node_path.clone(), - node_type: node_type, indent_level: (node_path.path.len() as u16), children: children, hidden_children: Vec::new(), - }) + } } pub fn parse(serde_node: &Value, node_path: &NodePath) -> Vec { @@ -66,41 +66,34 @@ impl Node { children.push( ParsedNodePacket{ key: key.to_string(), - node: Node::new( + node: AnyNode::NestedNode(Node::new( val.clone(), node_path.push_and_clone( NodePathKey::DictKey(key.to_string()) ), - NodeType::ChildNode, - ), + )), } ) } Value::Array(_) => { - children.push( - ParsedNodePacket{ - key: key.to_string(), - node: Node::new( - val.clone(), - node_path.push_and_clone( - NodePathKey::DictKey(key.to_string()) - ), - NodeType::IterableNodes, - ), - } - ) + // TODO + // ParsedNodePacket{ + // key: key.to_string(), + // node: AnyNodeNode::new( + // val.clone(), + // node_path.push_and_clone( + // NodePathKey::DictKey(key.to_string()) + // ), + // NodeType::IterableNodes, + // ), + // } + // ) } _ => { children.push( ParsedNodePacket{ key: key.to_string(), - node: Node::new( - val.clone(), - node_path.push_and_clone( - NodePathKey::DictKey(key.to_string()) - ), - NodeType::PrimitiveNode, - ), + node: AnyNode::PrimitiveNode(val.clone()), } ) } @@ -131,24 +124,31 @@ impl Node { } // print primitives first - for prim_attr in self.primitives.iter() { - let (key, val) = prim_attr.clone(); - let formatted_str = format!( - "{}\"{}\":{},\n", - self.num_spaces((self.indent_level+1)*INDENT_SIZE) , - key.clone(), - val.to_string(), - ); - result.push( - ( - formatted_str, - self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + for prim_attr in self.primitives().iter() { + let key = prim_attr.key.clone(); + if let AnyNode::PrimitiveNode(value) = prim_attr.node { + let formatted_str = format!( + "{}\"{}\":{},\n", + self.num_spaces((self.indent_level+1)*INDENT_SIZE), + key.clone(), + value.to_string(), + ); + result.push( + ( + formatted_str, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) ) - ) + } else { + panic!("should be unreachable...") + } } - - for (idx, child ) in self.children.iter().enumerate() { - let (key, chld) = child; + + // handling more complex + // nested cases + for (idx, node_packet) in self.children.iter().enumerate() { + let key = node_packet.key; + let node = node_packet.node; let current_node_owned_formatted_string = format!( "{}\"{}\":", self.num_spaces((self.indent_level+1)*INDENT_SIZE), @@ -216,7 +216,7 @@ impl Node { // TODO handle hidden children let bracket_lines = 2_u16; - let primitive_len = self.primitives.len() as u16; + let primitive_len = self.primitives().len() as u16; let children_len = self .children .iter() @@ -224,11 +224,12 @@ impl Node { bracket_lines+primitive_len+children_len } - pub fn get_child(&self, key: &NodePathKey) -> Option<&Node> { + pub fn get_child(&self, key: &NodePathKey) -> Option<&AnyNode> { match key { NodePathKey::DictKey(k) => { - for child in &self.children { - let (key, node) = child; + for node_packet in &self.children { + let key = node_packet.key; + let node = node_packet.node; if *key == *k { return Some(node); } @@ -241,11 +242,12 @@ impl Node { } } } - pub fn get_child_mut(&mut self, key: &NodePathKey) -> Option<&mut Node> { + pub fn get_child_mut(&mut self, key: &NodePathKey) -> Option<&mut AnyNode> { match key { NodePathKey::DictKey(k) => { - for child in &mut self.children { - let (key, node) = child; + for node_packet in self.children.iter_mut() { + let key = node_packet.key; + let node = node_packet.node; if *key == *k { return Some(node); } @@ -259,6 +261,23 @@ impl Node { } } + pub fn primitives(&self) -> Vec<&ParsedNodePacket> { + return self.children.iter() + .filter(|p| + matches!(p.node, AnyNode::PrimitiveNode(_)) + ) + .map(|val| val) + .collect(); + } + pub fn nested_nodes(&self) -> Vec<&ParsedNodePacket> { + return self.children.iter() + .filter(|p| + matches!(p.node,AnyNode::NestedNode(_)) + ) + .map(|val| val) + .collect(); + } + pub fn toggle_hide_child(&mut self, child: &NodePathKey) { if let Some(idx) = self.hidden_children.iter().position(|item| item==child) { @@ -267,6 +286,7 @@ impl Node { self.hidden_children.push(child.clone()); } } + } From 8ca5ce6b1e62d0ddb225b7a549a0fe66ab054e93 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 20:21:26 +1000 Subject: [PATCH 04/21] feat: more updates major --- jdora/src/library/internal/node.rs | 126 +++++++++++++++++------------ 1 file changed, 75 insertions(+), 51 deletions(-) diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index bbbf196..3e5ed69 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -109,13 +109,13 @@ impl Node { /// for every line which will be sent to pprint /// associate the NodePath associated with this line. pub fn get_structures(&self) -> Vec<(String, NodePath)> { - let mut result: Vec<(String, NodePath)> = Vec::new(); + let mut results: Vec<(String, NodePath)> = Vec::new(); // NOTE: only do this for root nodepath if self.indent_level == 0 { // open brace let open_bracket_str = "{\n".to_string(); - result.push( + results.push( ( open_bracket_str, // this belongs to this node. self.node_path.clone() @@ -123,58 +123,68 @@ impl Node { ); } - // print primitives first - for prim_attr in self.primitives().iter() { - let key = prim_attr.key.clone(); - if let AnyNode::PrimitiveNode(value) = prim_attr.node { - let formatted_str = format!( - "{}\"{}\":{},\n", - self.num_spaces((self.indent_level+1)*INDENT_SIZE), - key.clone(), - value.to_string(), - ); - result.push( - ( - formatted_str, - self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) - ) - ) - } else { - panic!("should be unreachable...") - } - } + // // print primitives first + // for prim_attr in self.primitives().iter() { + // let key = prim_attr.key.clone(); + // if let AnyNode::PrimitiveNode(value) = prim_attr.node { + // let formatted_str = format!( + // "{}\"{}\":{},\n", + // self.num_spaces((self.indent_level+1)*INDENT_SIZE), + // key.clone(), + // value.to_string(), + // ); + // result.push( + // ( + // formatted_str, + // self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + // ) + // ) + // } else { + // panic!("should be unreachable...") + // } + // } // handling more complex // nested cases for (idx, node_packet) in self.children.iter().enumerate() { + // let current_node_owned_formatted_string = format!( + // "{}\"{}\":", + // self.num_spaces((self.indent_level+1)*INDENT_SIZE), + // key.clone(), + // ); + // // TODO handle lists... its gonna be a nightmare + // if self.hidden_children.contains(&NodePathKey::DictKey(key.clone())) { // TODO rework hidden children + // let res = format!("{} ({} lines) ▲\n", current_node_owned_formatted_string, child_node.calculate_num_lines()); + // result.push( + // ( + // res, + // self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + // ) + // ); + // } else { + // let res = format!("{} {{ ▼\n", current_node_owned_formatted_string); + // result.push( + // ( + // res, + // self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + // ) + // ); + // // recursively call children get_structures. + // let children_structures = child_node.get_structures(); + // for res in children_structures { + // result.push(res); + // } + // } + let key = node_packet.key; - let node = node_packet.node; - let current_node_owned_formatted_string = format!( - "{}\"{}\":", - self.num_spaces((self.indent_level+1)*INDENT_SIZE), - key.clone(), - ); - // TODO handle lists... its gonna be a nightmare - if self.hidden_children.contains(&NodePathKey::DictKey(key.clone())) { // TODO rework hidden children - let res = format!("{} ({} lines) ▲\n", current_node_owned_formatted_string, chld.calculate_num_lines()); - result.push( - ( - res, - self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) - ) - ); - } else { - let res = format!("{} {{ ▼\n", current_node_owned_formatted_string); - result.push( - ( - res, - self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) - ) - ); - // recursively call children get_structures. - let children_structures = chld.get_structures(); - for res in children_structures { - result.push(res); + let child_node = node_packet.node; + + match child_node { + AnyNode::IterableNodes(nodes) => {} + AnyNode::NestedNode(node) => {} + AnyNode::PrimitiveNode(value) => { + let result = self.get_structures_primitive(key.clone(), value); + results.push(result); } } @@ -186,14 +196,28 @@ impl Node { "{}}}\n", self.num_spaces(self.indent_level*INDENT_SIZE) ); - result.push( + results.push( ( closing_bracket_str, self.node_path.clone(), ) ); - result + results + } + + pub fn get_structures_primitive(&self, key: String, value: Value) -> (String, NodePath) { + let formatted_str = format!( + "{}\"{}\":{},\n", + self.num_spaces((self.indent_level+1)*INDENT_SIZE), + key.clone(), + value.to_string(), + ); + + return( + formatted_str, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) } pub fn pprint(&self) -> String { From ac7ac0598d24e5e934675889e966998769a03672 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 20:22:39 +1000 Subject: [PATCH 05/21] chore: update --- jdora/src/library/internal/node.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index 3e5ed69..2039b57 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -176,14 +176,14 @@ impl Node { // } // } - let key = node_packet.key; - let child_node = node_packet.node; + let key = &node_packet.key; + let child_node = &node_packet.node; match child_node { AnyNode::IterableNodes(nodes) => {} AnyNode::NestedNode(node) => {} AnyNode::PrimitiveNode(value) => { - let result = self.get_structures_primitive(key.clone(), value); + let result = self.get_structures_primitive(key.clone(), value.clone()); results.push(result); } } From 6f8a236921fcbdf3ef173f61dfbd2ab2453dfe1b Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 20:35:31 +1000 Subject: [PATCH 06/21] feat: fixing more compiler errors --- jdora/src/library/internal/node.rs | 68 +++++++++++++++++------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index 2039b57..7033d2f 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -252,10 +252,10 @@ impl Node { match key { NodePathKey::DictKey(k) => { for node_packet in &self.children { - let key = node_packet.key; - let node = node_packet.node; + let key = &node_packet.key; + let node = &node_packet.node; if *key == *k { - return Some(node); + return Some(&node); } } None @@ -270,8 +270,8 @@ impl Node { match key { NodePathKey::DictKey(k) => { for node_packet in self.children.iter_mut() { - let key = node_packet.key; - let node = node_packet.node; + let key = &node_packet.key; + let node = &mut node_packet.node; if *key == *k { return Some(node); } @@ -315,31 +315,41 @@ impl Node { -pub fn try_resolve_node_path<'a>(root_node: &'a Node, node_path: &NodePath) -> Option<&'a Node> { - let mut cur_node = root_node; - for path_key in &node_path.path { - if let Some(new_node) = cur_node.get_child(&path_key) { - cur_node = new_node - } else { - return None +pub fn try_resolve_node_path<'a>(root_node: &'a AnyNode, node_path: &NodePath) -> Option<&'a AnyNode> { + let mut cur_any_node = root_node; + match cur_any_node { + AnyNode::PrimitiveNode(_) => { + panic!("root node is a primitive????") + }, + AnyNode::IterableNodes(nodes) => { + // pass + None + }, + AnyNode::NestedNode(cur_node) => { + for path_key in &node_path.path { + if let Some(new_node) = cur_node.get_child(&path_key) { + return Some(new_node) + } else { + return None + } + } + None } } - - Some(cur_node) } -// returns a mutable reference, this is more necesary when we want to -// update the state of the resolved path -// the other one is more useful when we just wanna perform queries -pub fn try_resolve_node_path_mut<'a>(root_node: &'a mut Node, node_path: &NodePath) -> Option<&'a mut Node> { - let mut cur_node = root_node; - for path_key in &node_path.path { - if let Some(new_node) = cur_node.get_child_mut(&path_key) { - cur_node = new_node - } else { - return None - } - } - - Some(cur_node) -} \ No newline at end of file +// // returns a mutable reference, this is more necesary when we want to +// // update the state of the resolved path +// // the other one is more useful when we just wanna perform queries +// pub fn try_resolve_node_path_mut<'a>(root_node: &'a mut Node, node_path: &NodePath) -> Option<&'a mut AnyNode> { +// let mut cur_node = root_node; +// for path_key in &node_path.path { +// if let Some(new_node) = cur_node.get_child_mut(&path_key) { +// cur_node = new_node +// } else { +// return None +// } +// } + +// Some(cur_node) +// } \ No newline at end of file From 377bce951e00493d2c98c1c008527a1c0ea6396f Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 20:40:06 +1000 Subject: [PATCH 07/21] feat: shouldve fixed all compiler errors --- jdora/src/library/internal/node.rs | 18 +++++++++++++++++- jdora/src/library/internal/parser.rs | 4 ++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index 7033d2f..3c75045 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -20,6 +20,22 @@ pub enum AnyNode { NestedNode(Node), } +impl AnyNode { + pub fn calculate_num_lines(&self) -> u16 { + match self { + AnyNode::PrimitiveNode(_) => { + 1 as u16 + }, + AnyNode::IterableNodes(nodes) => { + 0 as u16 // TODO + }, + AnyNode::NestedNode(node) => { + node.calculate_num_lines() + } + } + } +} + #[derive(Debug)] pub struct ParsedNodePacket { key: String, // key from json @@ -244,7 +260,7 @@ impl Node { let children_len = self .children .iter() - .fold(0 as u16, |acc, &(_, ref child)| acc + child.calculate_num_lines()); + .fold(0 as u16, |acc, packet| acc + packet.node.calculate_num_lines()); bracket_lines+primitive_len+children_len } diff --git a/jdora/src/library/internal/parser.rs b/jdora/src/library/internal/parser.rs index 5ee0ed1..8c9635a 100644 --- a/jdora/src/library/internal/parser.rs +++ b/jdora/src/library/internal/parser.rs @@ -7,11 +7,11 @@ use super::{node::Node, node_path::NodePath}; pub fn parse(data: &str) -> Node { let v: Value = serde_json::from_str(data).unwrap(); - return Node::new(v, NodePath::new()).unwrap(); + return Node::new(v, NodePath::new()); } pub fn parse_bytes(data: &[u8]) -> Node { let v: Value = serde_json::from_slice(data).unwrap(); - return Node::new(v, NodePath::new()).unwrap(); + return Node::new(v, NodePath::new()); } From d9348a4542d74fb7d1bdcf0873dfcadd792cdc3c Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 20:42:34 +1000 Subject: [PATCH 08/21] feat: more updates, but theres alot of things broken... --- jdora/src/library/controller.rs | 4 ++- jdora/src/library/internal/node.rs | 40 +++++++++++++++++++----------- 2 files changed, 28 insertions(+), 16 deletions(-) diff --git a/jdora/src/library/controller.rs b/jdora/src/library/controller.rs index 77dc677..22206c7 100644 --- a/jdora/src/library/controller.rs +++ b/jdora/src/library/controller.rs @@ -78,7 +78,9 @@ impl Controller { // toggle collapse // safe to unwrap - resolved_node.unwrap().toggle_hide_child(&node_path_leaf.unwrap()); + resolved_node + .unwrap() + .toggle_hide_child(&node_path_leaf.unwrap()); // re calculate structures. state.root_node_structure = state.root_node_state.get_structures(); diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index 3c75045..6f1be72 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -354,18 +354,28 @@ pub fn try_resolve_node_path<'a>(root_node: &'a AnyNode, node_path: &NodePath) - } } -// // returns a mutable reference, this is more necesary when we want to -// // update the state of the resolved path -// // the other one is more useful when we just wanna perform queries -// pub fn try_resolve_node_path_mut<'a>(root_node: &'a mut Node, node_path: &NodePath) -> Option<&'a mut AnyNode> { -// let mut cur_node = root_node; -// for path_key in &node_path.path { -// if let Some(new_node) = cur_node.get_child_mut(&path_key) { -// cur_node = new_node -// } else { -// return None -// } -// } - -// Some(cur_node) -// } \ No newline at end of file +// returns a mutable reference, this is more necesary when we want to +// update the state of the resolved path +// the other one is more useful when we just wanna perform queries +pub fn try_resolve_node_path_mut<'a>(root_node: &'a mut AnyNode, node_path: &NodePath) -> Option<&'a mut AnyNode> { + let mut cur_any_node = root_node; + match cur_any_node { + AnyNode::PrimitiveNode(_) => { + panic!("root node is a primitive????") + }, + AnyNode::IterableNodes(nodes) => { + // pass + None + }, + AnyNode::NestedNode(cur_node) => { + for path_key in &node_path.path { + if let Some(new_node) = cur_node.get_child_mut(&path_key) { + return Some(new_node) + } else { + return None + } + } + None + } + } +} \ No newline at end of file From f1f5e00d3959c48acb97a929cf14ffae92bb2717 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 21:04:59 +1000 Subject: [PATCH 09/21] feat: passes basic compilation errors --- jdora/src/library/controller.rs | 2 +- jdora/src/library/internal/node.rs | 70 ++++++++++++++++++++++++++---- jdora/src/library/state.rs | 6 ++- 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/jdora/src/library/controller.rs b/jdora/src/library/controller.rs index 22206c7..1b2cd5e 100644 --- a/jdora/src/library/controller.rs +++ b/jdora/src/library/controller.rs @@ -2,7 +2,7 @@ use std::any::Any; use crossterm::cursor; -use crate::library::internal::node::try_resolve_node_path_mut; +use crate::library::internal::node::{try_resolve_node_path_mut, AnyNode}; use super::{control::Control, filter::ExactSubstringSearch, input::InputBuffer, internal::{node::try_resolve_node_path, node_path::NodePath}, mode::Mode, ExplorerState }; diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index 6f1be72..f48b365 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -34,6 +34,56 @@ impl AnyNode { } } } + + pub fn toggle_hide_child(&mut self, child: &NodePathKey) { + match self { + AnyNode::PrimitiveNode(_) => { + // do nothing + }, + AnyNode::IterableNodes(nodes) => { + // do nothing for now + }, + AnyNode::NestedNode(node) => { + if let Some(idx) = node.hidden_children.iter().position(|item| item==child) { + node.hidden_children.remove(idx); + } else { + node.hidden_children.push(child.clone()); + } + } + } + } + + pub fn get_structures(&self) -> Vec<(String, NodePath)> { + let mut structures: Vec<(String, NodePath)> = Vec::new(); + match self { + AnyNode::PrimitiveNode(_) => { + panic!("Cannot call this function on primitive.") + } + AnyNode::IterableNodes(nodes) => { + // TODO + } + AnyNode::NestedNode(node) => { + structures.extend(node.get_structures()); + } + } + structures + } + + pub fn pprint(&self) -> String { + let mut curr_str = String::new(); + match self { + AnyNode::PrimitiveNode(_) => { + panic!("Cannot call this function on primitive.") + } + AnyNode::IterableNodes(nodes) => { + // + } + AnyNode::NestedNode(node) => { + curr_str += &node.pprint(); + } + } + curr_str + } } #[derive(Debug)] @@ -125,6 +175,7 @@ impl Node { /// for every line which will be sent to pprint /// associate the NodePath associated with this line. pub fn get_structures(&self) -> Vec<(String, NodePath)> { + let mut results: Vec<(String, NodePath)> = Vec::new(); // NOTE: only do this for root nodepath @@ -319,20 +370,21 @@ impl Node { } - pub fn toggle_hide_child(&mut self, child: &NodePathKey) { - if let Some(idx) = self.hidden_children.iter().position(|item| item==child) { - self.hidden_children.remove(idx); - } else { - self.hidden_children.push(child.clone()); - } - } + + // pub fn toggle_hide_child(&mut self, child: &NodePathKey) { + // if let Some(idx) = self.hidden_children.iter().position(|item| item==child) { + // self.hidden_children.remove(idx); + // } else { + // self.hidden_children.push(child.clone()); + // } + // } } pub fn try_resolve_node_path<'a>(root_node: &'a AnyNode, node_path: &NodePath) -> Option<&'a AnyNode> { - let mut cur_any_node = root_node; + let cur_any_node = root_node; match cur_any_node { AnyNode::PrimitiveNode(_) => { panic!("root node is a primitive????") @@ -358,7 +410,7 @@ pub fn try_resolve_node_path<'a>(root_node: &'a AnyNode, node_path: &NodePath) - // update the state of the resolved path // the other one is more useful when we just wanna perform queries pub fn try_resolve_node_path_mut<'a>(root_node: &'a mut AnyNode, node_path: &NodePath) -> Option<&'a mut AnyNode> { - let mut cur_any_node = root_node; + let cur_any_node = root_node; match cur_any_node { AnyNode::PrimitiveNode(_) => { panic!("root node is a primitive????") diff --git a/jdora/src/library/state.rs b/jdora/src/library/state.rs index 7de2d2e..a96a566 100644 --- a/jdora/src/library/state.rs +++ b/jdora/src/library/state.rs @@ -4,13 +4,15 @@ use google_cloud_storage::client::Client; use ratatui::layout::Rect; use tui_input::Input; +use crate::library::internal::node::AnyNode; + use super::{input::InputHandler, internal::{node::Node, node_path::NodePath, parser::parse_bytes}, mode::Mode, ui::CELL_HEIGHT}; // very primitive state right now // not optimised and not cached. pub struct ExplorerState{ - pub root_node_state: Node, + pub root_node_state: AnyNode, pub root_node_structure: Vec<(String, NodePath)>, @@ -40,7 +42,7 @@ impl ExplorerState { file.read_to_end(&mut contents) .unwrap(); - let node = parse_bytes(&contents); + let node = AnyNode::NestedNode(parse_bytes(&contents)); // TODO: handle if the root node state was a list... return Self { root_node_structure: node.get_structures(), From 187a1b17d4ee917591914ae80dab41baf4e5b613 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 22:00:06 +1000 Subject: [PATCH 10/21] feat: theres parity with previous functionality, now I can start working on the list logic --- jdora/src/library/internal/node.rs | 81 ++++++++++++------------------ 1 file changed, 32 insertions(+), 49 deletions(-) diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index f48b365..d41e240 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -190,65 +190,48 @@ impl Node { ); } - // // print primitives first - // for prim_attr in self.primitives().iter() { - // let key = prim_attr.key.clone(); - // if let AnyNode::PrimitiveNode(value) = prim_attr.node { - // let formatted_str = format!( - // "{}\"{}\":{},\n", - // self.num_spaces((self.indent_level+1)*INDENT_SIZE), - // key.clone(), - // value.to_string(), - // ); - // result.push( - // ( - // formatted_str, - // self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) - // ) - // ) - // } else { - // panic!("should be unreachable...") - // } - // } // handling more complex // nested cases for (idx, node_packet) in self.children.iter().enumerate() { - // let current_node_owned_formatted_string = format!( - // "{}\"{}\":", - // self.num_spaces((self.indent_level+1)*INDENT_SIZE), - // key.clone(), - // ); - // // TODO handle lists... its gonna be a nightmare - // if self.hidden_children.contains(&NodePathKey::DictKey(key.clone())) { // TODO rework hidden children - // let res = format!("{} ({} lines) ▲\n", current_node_owned_formatted_string, child_node.calculate_num_lines()); - // result.push( - // ( - // res, - // self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) - // ) - // ); - // } else { - // let res = format!("{} {{ ▼\n", current_node_owned_formatted_string); - // result.push( - // ( - // res, - // self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) - // ) - // ); - // // recursively call children get_structures. - // let children_structures = child_node.get_structures(); - // for res in children_structures { - // result.push(res); - // } - // } + let key = &node_packet.key; let child_node = &node_packet.node; match child_node { AnyNode::IterableNodes(nodes) => {} - AnyNode::NestedNode(node) => {} + AnyNode::NestedNode(node) => { + let current_node_owned_formatted_string = format!( + "{}\"{}\":", + self.num_spaces((self.indent_level+1)*INDENT_SIZE), + key.clone(), + ); + // TODO handle lists... its gonna be a nightmare + if self.hidden_children.contains(&NodePathKey::DictKey(key.clone())) { // TODO rework hidden children + let res = format!("{} ({} lines) ▲\n", current_node_owned_formatted_string, child_node.calculate_num_lines()); + results.push( + ( + res, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) + ); + } else { + let res = format!("{} {{ ▼\n", current_node_owned_formatted_string); + results.push( + ( + res, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) + ); + // recursively call children get_structures. + let children_structures = child_node.get_structures(); + for res in children_structures { + results.push(res); + } + } + + } AnyNode::PrimitiveNode(value) => { let result = self.get_structures_primitive(key.clone(), value.clone()); results.push(result); From 87544897ec98fe717a4bc61395156a3379d32c68 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 22:11:52 +1000 Subject: [PATCH 11/21] feat: extracting out logic from enum into a separate file --- jdora/src/library/controller.rs | 2 +- jdora/src/library/internal/any.rs | 77 +++++++++++++++++++++++++++ jdora/src/library/internal/mod.rs | 3 +- jdora/src/library/internal/node.rs | 85 ++---------------------------- jdora/src/library/state.rs | 3 +- 5 files changed, 86 insertions(+), 84 deletions(-) create mode 100644 jdora/src/library/internal/any.rs diff --git a/jdora/src/library/controller.rs b/jdora/src/library/controller.rs index 1b2cd5e..ff07f0a 100644 --- a/jdora/src/library/controller.rs +++ b/jdora/src/library/controller.rs @@ -2,7 +2,7 @@ use std::any::Any; use crossterm::cursor; -use crate::library::internal::node::{try_resolve_node_path_mut, AnyNode}; +use crate::library::internal::node::{try_resolve_node_path_mut}; use super::{control::Control, filter::ExactSubstringSearch, input::InputBuffer, internal::{node::try_resolve_node_path, node_path::NodePath}, mode::Mode, ExplorerState }; diff --git a/jdora/src/library/internal/any.rs b/jdora/src/library/internal/any.rs new file mode 100644 index 0000000..43de520 --- /dev/null +++ b/jdora/src/library/internal/any.rs @@ -0,0 +1,77 @@ +use serde_json::Value; + +use crate::library::internal::{node::Node, node_path::{NodePath, NodePathKey}}; + +#[derive(Debug)] +pub enum AnyNode { + PrimitiveNode(Value), + IterableNodes(Vec), + NestedNode(Node), +} + +impl AnyNode { + pub fn calculate_num_lines(&self) -> u16 { + match self { + AnyNode::PrimitiveNode(_) => { + 1 as u16 + }, + AnyNode::IterableNodes(nodes) => { + 0 as u16 // TODO + }, + AnyNode::NestedNode(node) => { + node.calculate_num_lines() + } + } + } + + pub fn toggle_hide_child(&mut self, child: &NodePathKey) { + match self { + AnyNode::PrimitiveNode(_) => { + // do nothing + }, + AnyNode::IterableNodes(nodes) => { + // do nothing for now + }, + AnyNode::NestedNode(node) => { + if let Some(idx) = node.hidden_children.iter().position(|item| item==child) { + node.hidden_children.remove(idx); + } else { + node.hidden_children.push(child.clone()); + } + } + } + } + + pub fn get_structures(&self) -> Vec<(String, NodePath)> { + let mut structures: Vec<(String, NodePath)> = Vec::new(); + match self { + AnyNode::PrimitiveNode(_) => { + panic!("Cannot call this function on primitive.") + } + AnyNode::IterableNodes(nodes) => { + + + } + AnyNode::NestedNode(node) => { + structures.extend(node.get_structures()); + } + } + structures + } + + pub fn pprint(&self) -> String { + let mut curr_str = String::new(); + match self { + AnyNode::PrimitiveNode(_) => { + panic!("Cannot call this function on primitive.") + } + AnyNode::IterableNodes(nodes) => { + // + } + AnyNode::NestedNode(node) => { + curr_str += &node.pprint(); + } + } + curr_str + } +} diff --git a/jdora/src/library/internal/mod.rs b/jdora/src/library/internal/mod.rs index e1b06ef..f632bdb 100644 --- a/jdora/src/library/internal/mod.rs +++ b/jdora/src/library/internal/mod.rs @@ -1,3 +1,4 @@ pub mod node; pub mod node_path; -pub mod parser; \ No newline at end of file +pub mod parser; +pub mod any; \ No newline at end of file diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index d41e240..1ba5d34 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -3,7 +3,7 @@ use std::primitive; use serde_json::{Map, Value}; -use crate::library::internal::node; +use crate::library::internal::{any::AnyNode, node}; use super::node_path::{self, NodePath, NodePathKey}; @@ -13,78 +13,6 @@ const INDENT_SIZE: u16 = 4; // i only consider // Dictionaries as nodes. -#[derive(Debug)] -pub enum AnyNode { - PrimitiveNode(Value), - IterableNodes(Vec), - NestedNode(Node), -} - -impl AnyNode { - pub fn calculate_num_lines(&self) -> u16 { - match self { - AnyNode::PrimitiveNode(_) => { - 1 as u16 - }, - AnyNode::IterableNodes(nodes) => { - 0 as u16 // TODO - }, - AnyNode::NestedNode(node) => { - node.calculate_num_lines() - } - } - } - - pub fn toggle_hide_child(&mut self, child: &NodePathKey) { - match self { - AnyNode::PrimitiveNode(_) => { - // do nothing - }, - AnyNode::IterableNodes(nodes) => { - // do nothing for now - }, - AnyNode::NestedNode(node) => { - if let Some(idx) = node.hidden_children.iter().position(|item| item==child) { - node.hidden_children.remove(idx); - } else { - node.hidden_children.push(child.clone()); - } - } - } - } - - pub fn get_structures(&self) -> Vec<(String, NodePath)> { - let mut structures: Vec<(String, NodePath)> = Vec::new(); - match self { - AnyNode::PrimitiveNode(_) => { - panic!("Cannot call this function on primitive.") - } - AnyNode::IterableNodes(nodes) => { - // TODO - } - AnyNode::NestedNode(node) => { - structures.extend(node.get_structures()); - } - } - structures - } - - pub fn pprint(&self) -> String { - let mut curr_str = String::new(); - match self { - AnyNode::PrimitiveNode(_) => { - panic!("Cannot call this function on primitive.") - } - AnyNode::IterableNodes(nodes) => { - // - } - AnyNode::NestedNode(node) => { - curr_str += &node.pprint(); - } - } - curr_str - } -} #[derive(Debug)] pub struct ParsedNodePacket { @@ -95,11 +23,8 @@ pub struct ParsedNodePacket { #[derive(Debug)] pub struct Node { - // serde_node: Value, // forwards to serde node pub node_path: NodePath, pub indent_level: u16, - // pub primitives: Vec<(String, Value)>, // primitive attributes - // NOTE i understand I don't handle lists well....at all right now... pub children: Vec, // hidden_children: @@ -108,10 +33,6 @@ pub struct Node { impl Node { pub fn new(val: Value, node_path: NodePath) -> Self { - // if !matches!(val, Value::Object(_)) { - // return None - // } - let children = Node::parse(&val, &node_path); Self{ // serde_node: val, @@ -200,7 +121,9 @@ impl Node { let child_node = &node_packet.node; match child_node { - AnyNode::IterableNodes(nodes) => {} + AnyNode::IterableNodes(nodes) => { + // do nothing here, its to be handled by AnyNode + } AnyNode::NestedNode(node) => { let current_node_owned_formatted_string = format!( "{}\"{}\":", diff --git a/jdora/src/library/state.rs b/jdora/src/library/state.rs index a96a566..a2e325f 100644 --- a/jdora/src/library/state.rs +++ b/jdora/src/library/state.rs @@ -4,7 +4,8 @@ use google_cloud_storage::client::Client; use ratatui::layout::Rect; use tui_input::Input; -use crate::library::internal::node::AnyNode; + +use crate::library::internal::any::AnyNode; use super::{input::InputHandler, internal::{node::Node, node_path::NodePath, parser::parse_bytes}, mode::Mode, ui::CELL_HEIGHT}; From 815e5de29f30140a1d8c9c034a590cf896c96eb5 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 22:14:36 +1000 Subject: [PATCH 12/21] chore: more re-org --- jdora/src/library/internal/any.rs | 56 +++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/jdora/src/library/internal/any.rs b/jdora/src/library/internal/any.rs index 43de520..75b60ff 100644 --- a/jdora/src/library/internal/any.rs +++ b/jdora/src/library/internal/any.rs @@ -9,7 +9,63 @@ pub enum AnyNode { NestedNode(Node), } + +#[derive(Debug)] +pub struct ParsedNodePacket { + key: String, // key from json + node: AnyNode, // Node with type information +} + + impl AnyNode { + pub fn parse(serde_node: &Value, node_path: &NodePath) -> Vec { + if let Value::Object(map) = &serde_node { + let mut children: Vec = Vec::new(); + + for (key, val) in map.iter() { + match val { + Value::Object(_) => { + children.push( + ParsedNodePacket{ + key: key.to_string(), + node: AnyNode::NestedNode(Node::new( + val.clone(), + node_path.push_and_clone( + NodePathKey::DictKey(key.to_string()) + ), + )), + } + ) + } + Value::Array(_) => { + // TODO + // ParsedNodePacket{ + // key: key.to_string(), + // node: AnyNodeNode::new( + // val.clone(), + // node_path.push_and_clone( + // NodePathKey::DictKey(key.to_string()) + // ), + // NodeType::IterableNodes, + // ), + // } + // ) + } + _ => { + children.push( + ParsedNodePacket{ + key: key.to_string(), + node: AnyNode::PrimitiveNode(val.clone()), + } + ) + } + } + } + return children + } else { + panic!("parse failed? node is not an object") + } + } pub fn calculate_num_lines(&self) -> u16 { match self { AnyNode::PrimitiveNode(_) => { From ca5e6c017002c35c1e5a6156e7d4277aa57722db Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 22:15:50 +1000 Subject: [PATCH 13/21] chore: fix compile errors --- jdora/src/library/internal/any.rs | 4 +- jdora/src/library/internal/node.rs | 59 ++---------------------------- 2 files changed, 5 insertions(+), 58 deletions(-) diff --git a/jdora/src/library/internal/any.rs b/jdora/src/library/internal/any.rs index 75b60ff..c3d3842 100644 --- a/jdora/src/library/internal/any.rs +++ b/jdora/src/library/internal/any.rs @@ -12,8 +12,8 @@ pub enum AnyNode { #[derive(Debug)] pub struct ParsedNodePacket { - key: String, // key from json - node: AnyNode, // Node with type information + pub key: String, // key from json + pub node: AnyNode, // Node with type information } diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index 1ba5d34..5b78235 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -3,7 +3,7 @@ use std::primitive; use serde_json::{Map, Value}; -use crate::library::internal::{any::AnyNode, node}; +use crate::library::internal::{any::{AnyNode, ParsedNodePacket}, node}; use super::node_path::{self, NodePath, NodePathKey}; @@ -14,12 +14,6 @@ const INDENT_SIZE: u16 = 4; // Dictionaries as nodes. -#[derive(Debug)] -pub struct ParsedNodePacket { - key: String, // key from json - node: AnyNode, // Node with type information -} - #[derive(Debug)] pub struct Node { @@ -33,7 +27,7 @@ pub struct Node { impl Node { pub fn new(val: Value, node_path: NodePath) -> Self { - let children = Node::parse(&val, &node_path); + let children = AnyNode::parse(&val, &node_path); Self{ // serde_node: val, node_path: node_path.clone(), @@ -43,54 +37,7 @@ impl Node { } } - pub fn parse(serde_node: &Value, node_path: &NodePath) -> Vec { - if let Value::Object(map) = &serde_node { - let mut children: Vec = Vec::new(); - - for (key, val) in map.iter() { - match val { - Value::Object(_) => { - children.push( - ParsedNodePacket{ - key: key.to_string(), - node: AnyNode::NestedNode(Node::new( - val.clone(), - node_path.push_and_clone( - NodePathKey::DictKey(key.to_string()) - ), - )), - } - ) - } - Value::Array(_) => { - // TODO - // ParsedNodePacket{ - // key: key.to_string(), - // node: AnyNodeNode::new( - // val.clone(), - // node_path.push_and_clone( - // NodePathKey::DictKey(key.to_string()) - // ), - // NodeType::IterableNodes, - // ), - // } - // ) - } - _ => { - children.push( - ParsedNodePacket{ - key: key.to_string(), - node: AnyNode::PrimitiveNode(val.clone()), - } - ) - } - } - } - return children - } else { - panic!("parse failed? node is not an object") - } - } + /// /// for every line which will be sent to pprint From 3d76b7845df5083fc73d22deeb9dc6035283f75d Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 22:31:06 +1000 Subject: [PATCH 14/21] feat: update get_structures for list --- jdora/src/library/internal/constants.rs | 2 + jdora/src/library/internal/list_of_nodes.rs | 120 ++++++++++++++++++++ jdora/src/library/internal/mod.rs | 4 +- jdora/src/library/internal/node.rs | 3 +- 4 files changed, 126 insertions(+), 3 deletions(-) create mode 100644 jdora/src/library/internal/constants.rs create mode 100644 jdora/src/library/internal/list_of_nodes.rs diff --git a/jdora/src/library/internal/constants.rs b/jdora/src/library/internal/constants.rs new file mode 100644 index 0000000..512527c --- /dev/null +++ b/jdora/src/library/internal/constants.rs @@ -0,0 +1,2 @@ + +pub const INDENT_SIZE: u16 = 4; \ No newline at end of file diff --git a/jdora/src/library/internal/list_of_nodes.rs b/jdora/src/library/internal/list_of_nodes.rs new file mode 100644 index 0000000..a9a2f87 --- /dev/null +++ b/jdora/src/library/internal/list_of_nodes.rs @@ -0,0 +1,120 @@ +use std::any::Any; + +use serde_json::Value; + +use crate::library::internal::{any::{AnyNode, ParsedNodePacket}, constants::INDENT_SIZE, node_path::{NodePath, NodePathKey}}; + + +#[derive(Debug)] +pub struct ListOfNodes { + pub node_path: NodePath, + pub indent_level: u16, + + pub children: Vec, + // hidden_children: + pub hidden_children: Vec, +} + + +impl ListOfNodes { + pub fn new(val: Value, node_path: NodePath) -> Self { + let children = AnyNode::parse(&val, &node_path); + Self{ + node_path: node_path.clone(), + indent_level: (node_path.path.len() as u16), + children: children, + hidden_children: Vec::new(), + } + } + + /// for every line which will be sent to pprint + /// associate the NodePath associated with this line. + pub fn get_structures(&self) -> Vec<(String, NodePath)> { + + let mut results: Vec<(String, NodePath)> = Vec::new(); + + // NOTE: only do this for root nodepath + if self.indent_level == 0 { + // open brace + let open_bracket_str = "[\n".to_string(); + results.push( + ( + open_bracket_str, // this belongs to this node. + self.node_path.clone() + ) + ); + } + + + // handling more complex + // nested cases + for (idx, node_packet) in self.children.iter().enumerate() { + + + let key = &node_packet.key; + let child_node = &node_packet.node; + + match child_node { + AnyNode::IterableNodes(nodes) => { + // do nothing here, its to be handled by AnyNode + let current_node_owned_formatted_string = format!( + "{}\"{}\":", + self.num_spaces((self.indent_level+1)*INDENT_SIZE), + key.clone(), + ); + // TODO handle lists... its gonna be a nightmare + if self.hidden_children.contains(&NodePathKey::DictKey(key.clone())) { // TODO rework hidden children + let res = format!("{} ({} lines) ▲\n", current_node_owned_formatted_string, child_node.calculate_num_lines()); + results.push( + ( + res, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) + ); + } else { + let res = format!("{} [ ▼\n", current_node_owned_formatted_string); + results.push( + ( + res, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) + ); + // recursively call children get_structures. + let children_structures = child_node.get_structures(); + for res in children_structures { + results.push(res); + } + } + + } + AnyNode::NestedNode(_) => { + results.extend(child_node.get_structures()) + } // NOOP + AnyNode::PrimitiveNode(_) => { + results.extend(child_node.get_structures()) + } + } + + + } + + // print closing bracket + let closing_bracket_str = format!( + "{}]\n", + self.num_spaces(self.indent_level*INDENT_SIZE) + ); + results.push( + ( + closing_bracket_str, + self.node_path.clone(), + ) + ); + + results + } + + + fn num_spaces(&self, n: u16) -> String { + " ".repeat(n as usize).to_string() + } +} \ No newline at end of file diff --git a/jdora/src/library/internal/mod.rs b/jdora/src/library/internal/mod.rs index f632bdb..fdbd8b3 100644 --- a/jdora/src/library/internal/mod.rs +++ b/jdora/src/library/internal/mod.rs @@ -1,4 +1,6 @@ pub mod node; pub mod node_path; pub mod parser; -pub mod any; \ No newline at end of file +pub mod any; +pub mod list_of_nodes; +pub mod constants; \ No newline at end of file diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index 5b78235..d440712 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -3,12 +3,11 @@ use std::primitive; use serde_json::{Map, Value}; -use crate::library::internal::{any::{AnyNode, ParsedNodePacket}, node}; +use crate::library::internal::{any::{AnyNode, ParsedNodePacket}, constants::INDENT_SIZE, node}; use super::node_path::{self, NodePath, NodePathKey}; -const INDENT_SIZE: u16 = 4; // i only consider // Dictionaries as nodes. From 2254a5dec63f5bee957bd4c3d259f152b3f5dcb4 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 22:36:20 +1000 Subject: [PATCH 15/21] chore: fixed compiler errors, but it panicked --- jdora/src/library/internal/any.rs | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/jdora/src/library/internal/any.rs b/jdora/src/library/internal/any.rs index c3d3842..8ba95fa 100644 --- a/jdora/src/library/internal/any.rs +++ b/jdora/src/library/internal/any.rs @@ -1,11 +1,11 @@ use serde_json::Value; -use crate::library::internal::{node::Node, node_path::{NodePath, NodePathKey}}; +use crate::library::internal::{list_of_nodes::ListOfNodes, node::Node, node_path::{NodePath, NodePathKey}}; #[derive(Debug)] pub enum AnyNode { PrimitiveNode(Value), - IterableNodes(Vec), + IterableNodes(ListOfNodes), NestedNode(Node), } @@ -38,18 +38,17 @@ impl AnyNode { ) } Value::Array(_) => { - // TODO - // ParsedNodePacket{ - // key: key.to_string(), - // node: AnyNodeNode::new( - // val.clone(), - // node_path.push_and_clone( - // NodePathKey::DictKey(key.to_string()) - // ), - // NodeType::IterableNodes, - // ), - // } - // ) + children.push( + ParsedNodePacket { + key: key.to_string(), + node: AnyNode::IterableNodes(ListOfNodes::new( + val.clone(), + node_path.push_and_clone( + NodePathKey::DictKey(key.to_string()) + ), + )) + } + ) } _ => { children.push( From 353b7b9a0faa8c8b367320be3e80f08c232e2506 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 22:50:01 +1000 Subject: [PATCH 16/21] feat: adding additional parsing branch for list --- jdora/src/library/internal/any.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/jdora/src/library/internal/any.rs b/jdora/src/library/internal/any.rs index 8ba95fa..62dc1fb 100644 --- a/jdora/src/library/internal/any.rs +++ b/jdora/src/library/internal/any.rs @@ -21,7 +21,6 @@ impl AnyNode { pub fn parse(serde_node: &Value, node_path: &NodePath) -> Vec { if let Value::Object(map) = &serde_node { let mut children: Vec = Vec::new(); - for (key, val) in map.iter() { match val { Value::Object(_) => { @@ -61,8 +60,22 @@ impl AnyNode { } } return children - } else { - panic!("parse failed? node is not an object") + } else if let Value::Array(list) = &serde_node { + let mut children: Vec = Vec::new(); + for (idx, child) in list.iter().enumerate() { + children.extend( + AnyNode::parse( + &child, + &node_path.push_and_clone( + NodePathKey::ListIndex(idx) + ) + ) + ); + } + children + } + else { + panic!("parse failed? node is not an object: {}", serde_node) } } pub fn calculate_num_lines(&self) -> u16 { From fefcfb701743c50ceec6875aa11a8a8833561314 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 22:53:05 +1000 Subject: [PATCH 17/21] chore: more updates --- jdora/src/library/internal/any.rs | 5 +++-- jdora/src/library/internal/list_of_nodes.rs | 7 +++++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/jdora/src/library/internal/any.rs b/jdora/src/library/internal/any.rs index 62dc1fb..4afda38 100644 --- a/jdora/src/library/internal/any.rs +++ b/jdora/src/library/internal/any.rs @@ -1,3 +1,4 @@ +use google_cloud_storage::http::bucket_access_controls::list; use serde_json::Value; use crate::library::internal::{list_of_nodes::ListOfNodes, node::Node, node_path::{NodePath, NodePathKey}}; @@ -133,8 +134,8 @@ impl AnyNode { AnyNode::PrimitiveNode(_) => { panic!("Cannot call this function on primitive.") } - AnyNode::IterableNodes(nodes) => { - // + AnyNode::IterableNodes(list_of_nodes) => { + curr_str+= &list_of_nodes.pprint(); } AnyNode::NestedNode(node) => { curr_str += &node.pprint(); diff --git a/jdora/src/library/internal/list_of_nodes.rs b/jdora/src/library/internal/list_of_nodes.rs index a9a2f87..1fa1db8 100644 --- a/jdora/src/library/internal/list_of_nodes.rs +++ b/jdora/src/library/internal/list_of_nodes.rs @@ -117,4 +117,11 @@ impl ListOfNodes { fn num_spaces(&self, n: u16) -> String { " ".repeat(n as usize).to_string() } + pub fn pprint(&self) -> String { + let mut result = String::new(); + for (str, _) in self.get_structures() { // unoptimised. + result += &str; + } + result + } } \ No newline at end of file From 631062af7b04de9334d59d41cfa79a9e04a8d3b7 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 23:07:17 +1000 Subject: [PATCH 18/21] feat: making progress on pprint --- jdora/src/library/internal/any.rs | 7 +++--- jdora/src/library/internal/node.rs | 37 +++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 5 deletions(-) diff --git a/jdora/src/library/internal/any.rs b/jdora/src/library/internal/any.rs index 4afda38..4f9a33b 100644 --- a/jdora/src/library/internal/any.rs +++ b/jdora/src/library/internal/any.rs @@ -115,11 +115,9 @@ impl AnyNode { let mut structures: Vec<(String, NodePath)> = Vec::new(); match self { AnyNode::PrimitiveNode(_) => { - panic!("Cannot call this function on primitive.") } - AnyNode::IterableNodes(nodes) => { - - + AnyNode::IterableNodes(list_of_nodes) => { + structures.extend(list_of_nodes.get_structures()) } AnyNode::NestedNode(node) => { structures.extend(node.get_structures()); @@ -128,6 +126,7 @@ impl AnyNode { structures } + pub fn pprint(&self) -> String { let mut curr_str = String::new(); match self { diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index d440712..cf9ab73 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -68,7 +68,42 @@ impl Node { match child_node { AnyNode::IterableNodes(nodes) => { - // do nothing here, its to be handled by AnyNode + let current_node_owned_formatted_string = format!( + "{}\"{}\":", + self.num_spaces((self.indent_level+1)*INDENT_SIZE), + key.clone(), + ); + // TODO handle lists... its gonna be a nightmare + if self.hidden_children.contains(&NodePathKey::DictKey(key.clone())) { // TODO rework hidden children + let res = format!("{} ({} lines) ▲\n", current_node_owned_formatted_string, child_node.calculate_num_lines()); + results.push( + ( + res, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) + ); + } else { + let res = format!("{} [ ▼\n", current_node_owned_formatted_string); + results.push( + ( + res, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) + ); + results.extend(AnyNode::get_structures(child_node)); + } + + // print closing bracket + let closing_bracket_str = format!( + "{}}}\n", + self.num_spaces(self.indent_level*INDENT_SIZE) + ); + results.push( + ( + closing_bracket_str, + self.node_path.clone(), + ) + ); } AnyNode::NestedNode(node) => { let current_node_owned_formatted_string = format!( From a26a8413ac3bd72a1a0ba7d1fe6829aca9e31926 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 23:15:46 +1000 Subject: [PATCH 19/21] feat: formatting works, the code just doesnt read nice --- jdora/src/library/internal/list_of_nodes.rs | 7 +++++++ jdora/src/library/internal/node.rs | 2 -- sample/c_.json | 15 +++++++++++++++ 3 files changed, 22 insertions(+), 2 deletions(-) create mode 100644 sample/c_.json diff --git a/jdora/src/library/internal/list_of_nodes.rs b/jdora/src/library/internal/list_of_nodes.rs index 1fa1db8..9b9a603 100644 --- a/jdora/src/library/internal/list_of_nodes.rs +++ b/jdora/src/library/internal/list_of_nodes.rs @@ -88,6 +88,13 @@ impl ListOfNodes { } AnyNode::NestedNode(_) => { + let res = format!("{}{{ ▼\n", self.num_spaces((2+self.indent_level)*INDENT_SIZE)); + results.push( + ( + res, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) + ); results.extend(child_node.get_structures()) } // NOOP AnyNode::PrimitiveNode(_) => { diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index cf9ab73..6c7e93c 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -61,8 +61,6 @@ impl Node { // handling more complex // nested cases for (idx, node_packet) in self.children.iter().enumerate() { - - let key = &node_packet.key; let child_node = &node_packet.node; diff --git a/sample/c_.json b/sample/c_.json new file mode 100644 index 0000000..c904983 --- /dev/null +++ b/sample/c_.json @@ -0,0 +1,15 @@ +{ + "name": "abc", + "hello": 1, + "nested": [ + [ + 1,2,3,4,5 + ], + [ + 4,5,6,7,8 + ] + ], + "another_nested": { + "b": "bbb" + } +} \ No newline at end of file From 9a1f8c4fbca6a68fdbb3af1c20bd328e4080d966 Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 23:21:05 +1000 Subject: [PATCH 20/21] feat: formatting is ncie, the code is so crappy.... need to fix it up some other day when I have more focus --- jdora/src/library/internal/list_of_nodes.rs | 43 ++++++++++++++++++++- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/jdora/src/library/internal/list_of_nodes.rs b/jdora/src/library/internal/list_of_nodes.rs index 9b9a603..aebf343 100644 --- a/jdora/src/library/internal/list_of_nodes.rs +++ b/jdora/src/library/internal/list_of_nodes.rs @@ -88,14 +88,53 @@ impl ListOfNodes { } AnyNode::NestedNode(_) => { - let res = format!("{}{{ ▼\n", self.num_spaces((2+self.indent_level)*INDENT_SIZE)); + let res = format!("{}{{ ▼\n", self.num_spaces((1+self.indent_level)*INDENT_SIZE)); results.push( ( res, self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) ) ); - results.extend(child_node.get_structures()) + // results.extend(child_node.get_structures()) + let current_node_owned_formatted_string = format!( + "{}\"{}\":", + self.num_spaces((self.indent_level+2)*INDENT_SIZE), + key.clone(), + ); + // TODO handle lists... its gonna be a nightmare + if self.hidden_children.contains(&NodePathKey::DictKey(key.clone())) { // TODO rework hidden children + let res = format!("{} ({} lines) ▲\n", current_node_owned_formatted_string, child_node.calculate_num_lines()); + results.push( + ( + res, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) + ); + } else { + let res = format!("{} {{ ▼\n", current_node_owned_formatted_string); + results.push( + ( + res, + self.node_path.push_and_clone(NodePathKey::DictKey(key.clone())) + ) + ); + // recursively call children get_structures. + let children_structures = child_node.get_structures(); + for res in children_structures { + results.push(res); + } + } + // print closing bracket + let closing_bracket_str = format!( + "{}}}\n", + self.num_spaces((1+self.indent_level)*INDENT_SIZE) + ); + results.push( + ( + closing_bracket_str, + self.node_path.clone(), + ) + ); } // NOOP AnyNode::PrimitiveNode(_) => { results.extend(child_node.get_structures()) From 37e464a9c4e9cc435e662ce83118ef963721584d Mon Sep 17 00:00:00 2001 From: Jacky Date: Sun, 3 Aug 2025 23:27:06 +1000 Subject: [PATCH 21/21] feat: chore: updated values of calculate_num_lines but its now broken but whatever --- jdora/src/library/internal/any.rs | 7 ++++++- jdora/src/library/internal/list_of_nodes.rs | 15 +++++++++++++++ jdora/src/library/internal/node.rs | 3 +-- 3 files changed, 22 insertions(+), 3 deletions(-) diff --git a/jdora/src/library/internal/any.rs b/jdora/src/library/internal/any.rs index 4f9a33b..f28fb06 100644 --- a/jdora/src/library/internal/any.rs +++ b/jdora/src/library/internal/any.rs @@ -85,7 +85,7 @@ impl AnyNode { 1 as u16 }, AnyNode::IterableNodes(nodes) => { - 0 as u16 // TODO + nodes.calculate_num_lines() }, AnyNode::NestedNode(node) => { node.calculate_num_lines() @@ -100,6 +100,11 @@ impl AnyNode { }, AnyNode::IterableNodes(nodes) => { // do nothing for now + if let Some(idx) = nodes.hidden_children.iter().position(|item| item==child) { + nodes.hidden_children.remove(idx); + } else { + nodes.hidden_children.push(child.clone()); + } }, AnyNode::NestedNode(node) => { if let Some(idx) = node.hidden_children.iter().position(|item| item==child) { diff --git a/jdora/src/library/internal/list_of_nodes.rs b/jdora/src/library/internal/list_of_nodes.rs index aebf343..4272893 100644 --- a/jdora/src/library/internal/list_of_nodes.rs +++ b/jdora/src/library/internal/list_of_nodes.rs @@ -170,4 +170,19 @@ impl ListOfNodes { } result } + + // calculate how many lines it this node will consume + // this just counts size of primitive and recursively adds up children offset lengths. + pub fn calculate_num_lines(&self) -> u16 { + + // TODO handle hidden children + let bracket_lines = 2_u16; + + // let primitive_len = self.primitives().len() as u16; + let children_len = self + .children + .iter() + .fold(0 as u16, |acc, packet| acc + packet.node.calculate_num_lines()); + bracket_lines+children_len + } } \ No newline at end of file diff --git a/jdora/src/library/internal/node.rs b/jdora/src/library/internal/node.rs index 6c7e93c..b7ff91b 100644 --- a/jdora/src/library/internal/node.rs +++ b/jdora/src/library/internal/node.rs @@ -192,12 +192,11 @@ impl Node { // TODO handle hidden children let bracket_lines = 2_u16; - let primitive_len = self.primitives().len() as u16; let children_len = self .children .iter() .fold(0 as u16, |acc, packet| acc + packet.node.calculate_num_lines()); - bracket_lines+primitive_len+children_len + bracket_lines+children_len } pub fn get_child(&self, key: &NodePathKey) -> Option<&AnyNode> {