Add binary type and tree sink

This commit is contained in:
Jonathan Turner 2019-07-04 17:11:56 +12:00
parent dc8545ce10
commit 65a0d27c8a
14 changed files with 181 additions and 38 deletions

View File

@ -84,6 +84,10 @@ path = "src/plugins/inc.rs"
name = "nu_plugin_newskip"
path = "src/plugins/newskip.rs"
[[bin]]
name = "nu_plugin_treeview"
path = "src/plugins/treeview.rs"
[[bin]]
name = "nu"
path = "src/main.rs"

View File

@ -34,7 +34,7 @@ pub enum MaybeOwned<'a, T> {
}
impl<T> MaybeOwned<'a, T> {
crate fn borrow(&self) -> &T {
pub fn borrow(&self) -> &T {
match self {
MaybeOwned::Owned(v) => v,
MaybeOwned::Borrowed(v) => v,
@ -59,6 +59,7 @@ fn load_plugin(path: &std::path::Path, context: &mut Context) -> Result<(), Shel
let request = JsonRpc::new("config", Vec::<Value>::new());
let request_raw = serde_json::to_string(&request).unwrap();
stdin.write(format!("{}\n", request_raw).as_bytes())?;
let path = dunce::canonicalize(path).unwrap();
let mut input = String::new();
match reader.read_line(&mut input) {
@ -129,14 +130,12 @@ fn load_plugins(context: &mut Context) -> Result<(), ShellError> {
None => println!("PATH is not defined in the environment."),
}
/*
// Also use our debug output for now
let mut path = std::path::PathBuf::from(".");
path.push("target");
path.push("debug");
let _ = load_plugins_in_dir(&path, context);
*/
Ok(())
}

View File

@ -5,11 +5,10 @@ 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));
if let Value::Binary(_) = args.input[0] {
println!("Binary");
} else if equal_shapes(&args.input) {
args.ctx.get_sink("table").run(args)?;
} else {
let mut host = args.ctx.host.lock().unwrap();
for i in args.input.iter() {

View File

@ -67,11 +67,16 @@ pub fn enter(args: CommandArgs) -> Result<OutputStream, ShellError> {
}
};
stream.push_back(ReturnValue::Action(CommandAction::Enter(parse_as_value(
file_extension,
contents,
span,
)?)));
match contents {
Value::Primitive(Primitive::String(x)) => {
stream.push_back(ReturnValue::Action(CommandAction::Enter(parse_as_value(
file_extension,
x,
span,
)?)));
}
x => stream.push_back(ReturnValue::Action(CommandAction::Enter(x))),
}
Ok(stream.boxed())
}

View File

@ -40,7 +40,7 @@ pub fn fetch(
cwd: &PathBuf,
location: &str,
span: Span,
) -> Result<(Option<String>, String), ShellError> {
) -> Result<(Option<String>, Value), ShellError> {
let mut cwd = cwd.clone();
if location.starts_with("http:") || location.starts_with("https:") {
let response = reqwest::get(location);
@ -71,7 +71,7 @@ pub fn fetch(
None => path_extension,
};
Ok((extension, s))
Ok((extension, Value::string(s)))
}
Err(_) => {
return Err(ShellError::labeled_error(
@ -91,12 +91,15 @@ pub fn fetch(
}
} else {
cwd.push(Path::new(location));
match std::fs::read_to_string(&cwd) {
Ok(s) => Ok((
cwd.extension()
.map(|name| name.to_string_lossy().to_string()),
s,
)),
match std::fs::read(&cwd) {
Ok(bytes) => match std::str::from_utf8(&bytes) {
Ok(s) => Ok((
cwd.extension()
.map(|name| name.to_string_lossy().to_string()),
Value::string(s),
)),
Err(_) => Ok((None, Value::Binary(bytes))),
},
Err(_) => {
return Err(ShellError::labeled_error(
"File cound not be opened",
@ -227,11 +230,12 @@ fn open(args: CommandArgs) -> Result<OutputStream, ShellError> {
}
};
stream.push_back(ReturnValue::Value(parse_as_value(
file_extension,
contents,
span,
)?));
match contents {
Value::Primitive(Primitive::String(x)) => {
stream.push_back(ReturnValue::Value(parse_as_value(file_extension, x, span)?));
}
x => stream.push_back(ReturnValue::Value(x)),
}
Ok(stream.boxed())
}

View File

@ -24,6 +24,13 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value {
}
Value::Error(e) => serde_json::Value::String(e.to_string()),
Value::Block(_) => serde_json::Value::Null,
Value::Binary(b) => serde_json::Value::Array(
b.iter()
.map(|x| {
serde_json::Value::Number(serde_json::Number::from_f64(*x as f64).unwrap())
})
.collect(),
),
Value::Object(o) => {
let mut m = serde_json::Map::new();
for (k, v) in o.entries.iter() {

View File

@ -18,6 +18,9 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value {
Value::List(l) => toml::Value::Array(l.iter().map(|x| value_to_toml_value(x)).collect()),
Value::Error(e) => toml::Value::String(e.to_string()),
Value::Block(_) => toml::Value::String("<Block>".to_string()),
Value::Binary(b) => {
toml::Value::Array(b.iter().map(|x| toml::Value::Integer(*x as i64)).collect())
}
Value::Object(o) => {
let mut m = toml::map::Map::new();
for (k, v) in o.entries.iter() {

2
src/env/host.rs vendored
View File

@ -40,7 +40,7 @@ impl Host for Box<dyn Host> {
}
#[derive(Debug)]
crate struct BasicHost;
pub struct BasicHost;
impl Host for BasicHost {
fn out_terminal(&self) -> Box<term::StdoutTerminal> {

View File

@ -41,6 +41,11 @@ impl RenderView for GenericView<'value> {
Ok(())
}
Value::Binary(_) => {
host.stdout("<Binary>");
Ok(())
}
Value::Filesystem => {
host.stdout("<filesystem>");
Ok(())

View File

@ -7,14 +7,8 @@ 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,
}
@ -39,6 +33,7 @@ impl TreeView {
Value::Block(_) => {}
Value::Error(_) => {}
Value::Filesystem => {}
Value::Binary(_) => {}
}
}
crate fn from_value(value: &Value) -> TreeView {
@ -73,7 +68,6 @@ impl RenderView for TreeView {
bold: true,
..Style::default()
};
//config.characters = UTF_CHARS_BOLD.into();
config.indent = 4;
config
};

View File

@ -21,6 +21,7 @@ mod shell;
mod stream;
pub use crate::commands::command::ReturnValue;
pub use crate::env::host::BasicHost;
pub use crate::parser::parse::span::SpannedItem;
pub use crate::parser::Spanned;
pub use crate::plugin::{serve_plugin, Plugin};

View File

@ -75,7 +75,7 @@ impl Primitive {
}
}
crate fn format(&self, field_name: Option<&String>) -> String {
pub fn format(&self, field_name: Option<&String>) -> String {
match self {
Primitive::Nothing => format!("{}", Color::Black.bold().paint("-")),
Primitive::EndOfStream => format!("{}", Color::Black.bold().paint("-")),
@ -180,6 +180,8 @@ pub enum Value {
Primitive(Primitive),
Object(crate::object::Dictionary),
List(Vec<Value>),
Binary(Vec<u8>),
#[allow(unused)]
Block(Block),
Filesystem,
@ -217,6 +219,7 @@ impl fmt::Debug for ValueDebug<'a> {
Value::Block(_) => write!(f, "[[block]]"),
Value::Error(err) => write!(f, "[[error :: {} ]]", err),
Value::Filesystem => write!(f, "[[filesystem]]"),
Value::Binary(_) => write!(f, "[[binary]]"),
}
}
}
@ -237,6 +240,7 @@ impl Value {
Value::Block(_) => format!("block"),
Value::Error(_) => format!("error"),
Value::Filesystem => format!("filesystem"),
Value::Binary(_) => format!("binary"),
}
}
@ -244,7 +248,7 @@ impl Value {
ValueDebug { value: self }
}
crate fn data_descriptors(&self) -> Vec<String> {
pub fn data_descriptors(&self) -> Vec<String> {
match self {
Value::Primitive(_) => vec![],
Value::Object(o) => o
@ -257,6 +261,7 @@ impl Value {
Value::List(_) => vec![],
Value::Error(_) => vec![],
Value::Filesystem => vec![],
Value::Binary(_) => vec![],
}
}
@ -286,7 +291,7 @@ impl Value {
}
}
crate fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
pub fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
match self {
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
p @ Value::Filesystem => MaybeOwned::Borrowed(p),
@ -294,6 +299,7 @@ impl Value {
Value::Block(_) => MaybeOwned::Owned(Value::nothing()),
Value::List(_) => MaybeOwned::Owned(Value::nothing()),
Value::Error(e) => MaybeOwned::Owned(Value::string(&format!("{:#?}", e))),
Value::Binary(_) => MaybeOwned::Owned(Value::nothing()),
}
}
@ -308,6 +314,7 @@ impl Value {
}
Value::Error(e) => Value::Error(Box::new(e.copy_error())),
Value::Filesystem => Value::Filesystem,
Value::Binary(b) => Value::Binary(b.clone()),
}
}
@ -324,6 +331,7 @@ impl Value {
Value::List(_) => format!("[list List]"),
Value::Error(e) => format!("{}", e),
Value::Filesystem => format!("<filesystem>"),
Value::Binary(_) => format!("<binary>"),
}
}

View File

@ -86,7 +86,7 @@ impl Dictionary {
out
}
crate fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
pub fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
match self.entries.get(desc) {
Some(v) => MaybeOwned::Borrowed(v),
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),

114
src/plugins/treeview.rs Normal file
View File

@ -0,0 +1,114 @@
use derive_new::new;
use indexmap::IndexMap;
use nu::{serve_plugin, Args, CommandConfig, Plugin, ShellError, Value};
use ptree::item::StringItem;
use ptree::output::print_tree_with;
use ptree::print_config::PrintConfig;
use ptree::style::{Color, Style};
use ptree::TreeBuilder;
#[derive(new)]
pub struct TreeView {
tree: StringItem,
}
impl TreeView {
fn from_value_helper(value: &Value, mut builder: &mut TreeBuilder) {
match value {
Value::Primitive(p) => {
let _ = builder.add_empty_child(p.format(None));
}
Value::Object(o) => {
for (k, v) in o.entries.iter() {
builder = builder.begin_child(k.clone());
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(_) => {}
Value::Filesystem => {}
Value::Binary(_) => {}
}
}
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.clone());
Self::from_value_helper(value.borrow(), &mut builder);
builder = builder.end_child();
//entries.push((desc.name.clone(), value.borrow().copy()))
}
TreeView::new(builder.build())
}
fn render_view(&self) -> 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(())
}
}
struct TreeViewer;
impl Plugin for TreeViewer {
fn config(&mut self) -> Result<CommandConfig, ShellError> {
Ok(CommandConfig {
name: "treeview".to_string(),
mandatory_positional: vec![],
optional_positional: vec![],
can_load: vec![],
can_save: vec![],
is_filter: false,
is_sink: true,
named: IndexMap::new(),
rest_positional: true,
})
}
fn sink(&mut self, _args: Args, input: Vec<Value>) {
if input.len() > 0 {
for i in input.iter() {
let view = TreeView::from_value(&i);
let _ = view.render_view();
//handle_unexpected(&mut *host, |host| crate::format::print_view(&view, host));
}
}
//Ok(())
}
}
fn main() {
serve_plugin(&mut TreeViewer);
}