Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions jdora/src/library/controller.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

use super::{control::Control, filter::ExactSubstringSearch, input::InputBuffer, internal::{node::try_resolve_node_path, node_path::NodePath}, mode::Mode, ExplorerState };

Expand Down Expand Up @@ -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();
Expand Down
10 changes: 10 additions & 0 deletions jdora/src/library/internal/README.md
Original file line number Diff line number Diff line change
@@ -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.
150 changes: 150 additions & 0 deletions jdora/src/library/internal/any.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
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}};

#[derive(Debug)]
pub enum AnyNode {
PrimitiveNode(Value),
IterableNodes(ListOfNodes),
NestedNode(Node),
}


#[derive(Debug)]
pub struct ParsedNodePacket {
pub key: String, // key from json
pub node: AnyNode, // Node with type information
}


impl AnyNode {
pub fn parse(serde_node: &Value, node_path: &NodePath) -> Vec<ParsedNodePacket> {
if let Value::Object(map) = &serde_node {
let mut children: Vec<ParsedNodePacket> = 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(_) => {
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(
ParsedNodePacket{
key: key.to_string(),
node: AnyNode::PrimitiveNode(val.clone()),
}
)
}
}
}
return children
} else if let Value::Array(list) = &serde_node {
let mut children: Vec<ParsedNodePacket> = 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 {
match self {
AnyNode::PrimitiveNode(_) => {
1 as u16
},
AnyNode::IterableNodes(nodes) => {
nodes.calculate_num_lines()
},
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
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) {
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(_) => {
}
AnyNode::IterableNodes(list_of_nodes) => {
structures.extend(list_of_nodes.get_structures())
}
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(list_of_nodes) => {
curr_str+= &list_of_nodes.pprint();
}
AnyNode::NestedNode(node) => {
curr_str += &node.pprint();
}
}
curr_str
}
}
2 changes: 2 additions & 0 deletions jdora/src/library/internal/constants.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

pub const INDENT_SIZE: u16 = 4;
188 changes: 188 additions & 0 deletions jdora/src/library/internal/list_of_nodes.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
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<ParsedNodePacket>,
// hidden_children:
pub hidden_children: Vec<NodePathKey>,
}


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!("{} <collapsed>({} 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(_) => {
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())
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!("{} <collapsed>({} 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())
}
}


}

// 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()
}
pub fn pprint(&self) -> String {
let mut result = String::new();
for (str, _) in self.get_structures() { // unoptimised.
result += &str;
}
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
}
}
5 changes: 4 additions & 1 deletion jdora/src/library/internal/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
pub mod node;
pub mod node_path;
pub mod parser;
pub mod parser;
pub mod any;
pub mod list_of_nodes;
pub mod constants;
Loading