Add tree sink

This commit is contained in:
Jonathan Turner
2019-06-07 19:50:26 +12:00
parent 090ec031a9
commit 7c794dc189
11 changed files with 284 additions and 9 deletions

View File

@ -1,6 +1,6 @@
use crate::commands::autoview;
use crate::commands::classified::SinkCommand;
use crate::commands::command::sink;
use crate::commands::{autoview, tree};
use crate::prelude::*;
@ -72,7 +72,10 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
command("sort-by", sort_by::sort_by),
]);
context.add_sinks(vec![sink("autoview", autoview::autoview)]);
context.add_sinks(vec![
sink("autoview", autoview::autoview),
sink("tree", tree::tree),
]);
}
let config = Config::builder().color_mode(ColorMode::Forced).build();

View File

@ -22,11 +22,12 @@ crate mod split_row;
crate mod to_array;
crate mod to_json;
crate mod to_toml;
crate mod tree;
crate mod trim;
crate mod view;
crate mod where_;
crate use command::command;
crate use config::Config;
crate use to_array::stream_to_array;
crate use where_::Where;

43
src/commands/autoview.rs Normal file
View File

@ -0,0 +1,43 @@
use crate::commands::command::SinkCommandArgs;
use crate::errors::ShellError;
use crate::format::{GenericView, TableView};
use crate::prelude::*;
pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
if args.input.len() > 0 {
if equal_shapes(&args.input) {
let mut host = args.ctx.host.lock().unwrap();
let view = TableView::from_list(&args.input).unwrap();
handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
} else {
let mut host = args.ctx.host.lock().unwrap();
for i in args.input.iter() {
let view = GenericView::new(&i);
handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
host.stdout("");
}
}
}
Ok(())
}
fn equal_shapes(input: &Vec<Value>) -> bool {
let mut items = input.iter();
let item = match items.next() {
Some(item) => item,
None => return false,
};
let desc = item.data_descriptors();
for item in items {
if desc != item.data_descriptors() {
return false;
}
}
true
}

View File

@ -1,5 +1,5 @@
use crate::prelude::*;
use crate::{EntriesListView, GenericView};
use crate::{EntriesListView, GenericView, TreeView};
use futures::stream::{self, StreamExt};
use std::sync::{Arc, Mutex};

17
src/commands/tree.rs Normal file
View File

@ -0,0 +1,17 @@
use crate::commands::command::SinkCommandArgs;
use crate::errors::ShellError;
use crate::format::TreeView;
use crate::prelude::*;
pub fn tree(args: SinkCommandArgs) -> Result<(), ShellError> {
if args.input.len() > 0 {
let mut host = args.ctx.host.lock().unwrap();
for i in args.input.iter() {
let view = TreeView::from_value(&i);
handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
host.stdout("");
}
}
Ok(())
}

View File

@ -2,6 +2,7 @@ crate mod entries;
crate mod generic;
crate mod list;
crate mod table;
crate mod tree;
use crate::prelude::*;
@ -9,6 +10,7 @@ crate use entries::{EntriesListView, EntriesView};
crate use generic::GenericView;
crate use list::ListView;
crate use table::TableView;
crate use tree::TreeView;
crate trait RenderView {
fn render_view(&self, host: &mut dyn Host) -> Result<(), ShellError>;

View File

@ -1,4 +1,4 @@
use crate::format::{EntriesView, ListView, RenderView, TableView};
use crate::format::{EntriesView, ListView, RenderView, TableView, TreeView};
use crate::object::Value;
use crate::prelude::*;
use derive_new::new;

83
src/format/tree.rs Normal file
View File

@ -0,0 +1,83 @@
use crate::format::RenderView;
use crate::prelude::*;
use derive_new::new;
use ptree::item::StringItem;
use ptree::output::print_tree_with;
use ptree::print_config::PrintConfig;
use ptree::style::{Color, Style};
use ptree::TreeBuilder;
// An entries list is printed like this:
//
// name : ...
// name2 : ...
// another_name : ...
#[derive(new)]
pub struct TreeView {
//entries: Vec<(crate::object::DescriptorName, Value)>,
tree: StringItem,
}
impl TreeView {
fn from_value_helper(value: &Value, mut builder: &mut TreeBuilder) {
match value {
Value::Primitive(p) => builder = builder.add_empty_child(p.format(None)),
Value::Object(o) => {
for (k, v) in o.entries.iter() {
builder = builder.begin_child(k.name.display().to_string());
Self::from_value_helper(v, builder);
builder = builder.end_child();
}
}
Value::List(l) => {
for elem in l.iter() {
Self::from_value_helper(elem, builder);
}
}
Value::Block(_) => {}
Value::Error(_) => {}
}
}
crate fn from_value(value: &Value) -> TreeView {
let descs = value.data_descriptors();
let mut tree = TreeBuilder::new("".to_string());
let mut builder = &mut tree;
for desc in descs {
let value = value.get_data(&desc);
builder = builder.begin_child(desc.name.display().to_string());
Self::from_value_helper(value.borrow(), &mut builder);
builder = builder.end_child();
//entries.push((desc.name.clone(), value.borrow().copy()))
}
TreeView::new(builder.build())
}
}
impl RenderView for TreeView {
fn render_view(&self, _host: &mut dyn Host) -> Result<(), ShellError> {
// Set up the print configuration
let config = {
let mut config = PrintConfig::from_env();
config.branch = Style {
foreground: Some(Color::Green),
dimmed: true,
..Style::default()
};
config.leaf = Style {
bold: true,
..Style::default()
};
//config.characters = UTF_CHARS_BOLD.into();
config.indent = 4;
config
};
// Print out the tree using custom formatting
print_tree_with(&self.tree, &config)?;
Ok(())
}
}

View File

@ -4,13 +4,13 @@ use crate::object::DataDescriptor;
use crate::object::{Primitive, Value};
use derive_new::new;
use indexmap::IndexMap;
use serde::ser::{Serialize, SerializeMap, Serializer};
use serde_derive::Deserialize;
use serde::ser::{Serialize, Serializer, SerializeMap};
use std::cmp::{Ordering, PartialOrd};
#[derive(Debug, Default, Eq, PartialEq, Deserialize, Clone, new)]
pub struct Dictionary {
entries: IndexMap<DataDescriptor, Value>,
pub entries: IndexMap<DataDescriptor, Value>,
}
impl PartialOrd for Dictionary {
@ -28,8 +28,8 @@ impl Serialize for Dictionary {
let mut map = serializer.serialize_map(Some(self.entries.len()))?;
for (k, v) in self.entries.iter() {
match v {
Value::Object(_) => {},
_ => map.serialize_entry(k, v)?
Value::Object(_) => {}
_ => map.serialize_entry(k, v)?,
}
}
for (k, v) in self.entries.iter() {