forked from extern/nushell
Add tree sink
This commit is contained in:
@ -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();
|
||||
|
@ -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
43
src/commands/autoview.rs
Normal 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
|
||||
}
|
@ -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
17
src/commands/tree.rs
Normal 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(())
|
||||
}
|
@ -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>;
|
||||
|
@ -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
83
src/format/tree.rs
Normal 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(())
|
||||
}
|
||||
}
|
@ -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() {
|
||||
|
Reference in New Issue
Block a user