mirror of
https://github.com/nushell/nushell
synced 2025-01-14 14:14:13 +00:00
WIP now load plugins automatically
This commit is contained in:
parent
75ddfe9f5a
commit
0180769971
25 changed files with 348 additions and 329 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -1492,6 +1492,7 @@ dependencies = [
|
||||||
"toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"toml-query 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"toml-query 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"walkdir 2.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|
|
@ -63,6 +63,7 @@ serde_ini = "0.2.0"
|
||||||
subprocess = "0.1.18"
|
subprocess = "0.1.18"
|
||||||
sys-info = "0.5.7"
|
sys-info = "0.5.7"
|
||||||
mime = "0.3.13"
|
mime = "0.3.13"
|
||||||
|
walkdir = "2.2.8"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions = "0.6.1"
|
pretty_assertions = "0.6.1"
|
||||||
|
@ -79,6 +80,10 @@ path = "src/plugins/sum.rs"
|
||||||
name = "nu_plugin_inc"
|
name = "nu_plugin_inc"
|
||||||
path = "src/plugins/inc.rs"
|
path = "src/plugins/inc.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "nu_plugin_newskip"
|
||||||
|
path = "src/plugins/newskip.rs"
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nu"
|
name = "nu"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
201
src/cli.rs
201
src/cli.rs
|
@ -1,30 +1,31 @@
|
||||||
use crate::commands::autoview;
|
use crate::commands::autoview;
|
||||||
use crate::commands::classified::SinkCommand;
|
use crate::commands::classified::SinkCommand;
|
||||||
use crate::commands::command::sink;
|
|
||||||
|
|
||||||
use crate::prelude::*;
|
|
||||||
|
|
||||||
use crate::commands::classified::{
|
use crate::commands::classified::{
|
||||||
ClassifiedCommand, ClassifiedInputStream, ClassifiedPipeline, ExternalCommand, InternalCommand,
|
ClassifiedCommand, ClassifiedInputStream, ClassifiedPipeline, ExternalCommand, InternalCommand,
|
||||||
StreamNext,
|
StreamNext,
|
||||||
};
|
};
|
||||||
|
use crate::commands::command::sink;
|
||||||
|
use crate::commands::plugin::{JsonRpc, NuResult};
|
||||||
use crate::context::Context;
|
use crate::context::Context;
|
||||||
crate use crate::errors::ShellError;
|
crate use crate::errors::ShellError;
|
||||||
use crate::evaluate::Scope;
|
use crate::evaluate::Scope;
|
||||||
use crate::parser::parse::span::Spanned;
|
|
||||||
use crate::parser::registry;
|
|
||||||
use crate::parser::{Pipeline, PipelineElement, TokenNode};
|
|
||||||
|
|
||||||
use crate::git::current_branch;
|
use crate::git::current_branch;
|
||||||
use crate::object::Value;
|
use crate::object::Value;
|
||||||
|
use crate::parser::parse::span::Spanned;
|
||||||
|
use crate::parser::registry;
|
||||||
|
use crate::parser::registry::CommandConfig;
|
||||||
|
use crate::parser::{Pipeline, PipelineElement, TokenNode};
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
use log::{debug, trace};
|
use log::{debug, trace};
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
use rustyline::{self, ColorMode, Config, Editor};
|
use rustyline::{self, ColorMode, Config, Editor};
|
||||||
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
use std::io::{BufRead, BufReader, Write};
|
||||||
use std::iter::Iterator;
|
use std::iter::Iterator;
|
||||||
use std::sync::atomic::{AtomicBool, Ordering};
|
use std::sync::atomic::{AtomicBool, Ordering};
|
||||||
|
use walkdir::WalkDir;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum MaybeOwned<'a, T> {
|
pub enum MaybeOwned<'a, T> {
|
||||||
|
@ -41,6 +42,112 @@ impl<T> MaybeOwned<'a, T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn load_plugin(fname: &str, context: &mut Context) -> Result<(), ShellError> {
|
||||||
|
use crate::commands::{command, plugin};
|
||||||
|
|
||||||
|
println!("fname: {}", fname);
|
||||||
|
let mut child = std::process::Command::new(fname)
|
||||||
|
.stdin(std::process::Stdio::piped())
|
||||||
|
.stdout(std::process::Stdio::piped())
|
||||||
|
.spawn()
|
||||||
|
.expect("Failed to spawn child process");
|
||||||
|
|
||||||
|
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
||||||
|
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
||||||
|
|
||||||
|
let mut reader = BufReader::new(stdout);
|
||||||
|
|
||||||
|
println!("Sending out config request");
|
||||||
|
|
||||||
|
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 mut input = String::new();
|
||||||
|
match reader.read_line(&mut input) {
|
||||||
|
Ok(_) => {
|
||||||
|
println!("Got a response!: {}", input);
|
||||||
|
let response =
|
||||||
|
serde_json::from_str::<JsonRpc<Result<CommandConfig, ShellError>>>(&input);
|
||||||
|
match response {
|
||||||
|
Ok(jrpc) => match jrpc.params {
|
||||||
|
Ok(params) => {
|
||||||
|
println!("Loaded: {}", params.name);
|
||||||
|
if params.is_filter {
|
||||||
|
let fname = fname.to_string();
|
||||||
|
context.add_commands(vec![command(
|
||||||
|
¶ms.name,
|
||||||
|
Box::new(move |x| plugin::filter_plugin(fname.clone(), x)),
|
||||||
|
)]);
|
||||||
|
Ok(())
|
||||||
|
} else if params.is_sink {
|
||||||
|
let fname = fname.to_string();
|
||||||
|
context.add_sinks(vec![sink(
|
||||||
|
¶ms.name,
|
||||||
|
Box::new(move |x| plugin::sink_plugin(fname.clone(), x)),
|
||||||
|
)]);
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => Err(e),
|
||||||
|
},
|
||||||
|
Err(e) => Err(ShellError::string(format!("Error: {:?}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => Err(ShellError::string(format!("Error: {:?}", e))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_plugins(context: &mut Context) -> Result<(), ShellError> {
|
||||||
|
match env::var_os("PATH") {
|
||||||
|
Some(paths) => {
|
||||||
|
//println!("{:?}", paths);
|
||||||
|
for path in env::split_paths(&paths) {
|
||||||
|
match std::fs::read_dir(path) {
|
||||||
|
Ok(path) => {
|
||||||
|
for entry in path {
|
||||||
|
let entry = entry.unwrap();
|
||||||
|
let filename = entry.file_name();
|
||||||
|
let f_name = filename.to_string_lossy();
|
||||||
|
if f_name.starts_with("nu_plugin_") && !f_name.ends_with(".d") {
|
||||||
|
//println!("Found: {}", f_name);
|
||||||
|
load_plugin(&f_name, context)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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");
|
||||||
|
|
||||||
|
match std::fs::read_dir(path) {
|
||||||
|
Ok(path) => {
|
||||||
|
for entry in path {
|
||||||
|
let entry = entry.unwrap();
|
||||||
|
let filename = entry.file_name();
|
||||||
|
let f_name = filename.to_string_lossy();
|
||||||
|
println!("looking at: {}", f_name);
|
||||||
|
if f_name.starts_with("nu_plugin_") && !f_name.ends_with(".d") {
|
||||||
|
println!("Found: {}", f_name);
|
||||||
|
load_plugin(&entry.path().to_string_lossy(), context)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn cli() -> Result<(), Box<dyn Error>> {
|
pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||||
let mut context = Context::basic()?;
|
let mut context = Context::basic()?;
|
||||||
|
|
||||||
|
@ -48,51 +155,55 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||||
use crate::commands::*;
|
use crate::commands::*;
|
||||||
|
|
||||||
context.add_commands(vec![
|
context.add_commands(vec![
|
||||||
command("ps", ps::ps),
|
command("ps", Box::new(ps::ps)),
|
||||||
command("ls", ls::ls),
|
command("ls", Box::new(ls::ls)),
|
||||||
command("sysinfo", sysinfo::sysinfo),
|
command("sysinfo", Box::new(sysinfo::sysinfo)),
|
||||||
command("cd", cd::cd),
|
command("cd", Box::new(cd::cd)),
|
||||||
command("view", view::view),
|
command("view", Box::new(view::view)),
|
||||||
command("skip", skip::skip),
|
command("skip", Box::new(skip::skip)),
|
||||||
command("first", first::first),
|
command("first", Box::new(first::first)),
|
||||||
command("size", size::size),
|
command("size", Box::new(size::size)),
|
||||||
command("from-ini", from_ini::from_ini),
|
command("from-ini", Box::new(from_ini::from_ini)),
|
||||||
command("from-json", from_json::from_json),
|
command("from-json", Box::new(from_json::from_json)),
|
||||||
command("from-toml", from_toml::from_toml),
|
command("from-toml", Box::new(from_toml::from_toml)),
|
||||||
command("from-xml", from_xml::from_xml),
|
command("from-xml", Box::new(from_xml::from_xml)),
|
||||||
command("from-yaml", from_yaml::from_yaml),
|
command("from-yaml", Box::new(from_yaml::from_yaml)),
|
||||||
command("get", get::get),
|
command("get", Box::new(get::get)),
|
||||||
command("enter", enter::enter),
|
command("enter", Box::new(enter::enter)),
|
||||||
command("exit", exit::exit),
|
command("exit", Box::new(exit::exit)),
|
||||||
command("lines", lines::lines),
|
command("lines", Box::new(lines::lines)),
|
||||||
command("pick", pick::pick),
|
command("pick", Box::new(pick::pick)),
|
||||||
command("split-column", split_column::split_column),
|
command("split-column", Box::new(split_column::split_column)),
|
||||||
command("split-row", split_row::split_row),
|
command("split-row", Box::new(split_row::split_row)),
|
||||||
command("lines", lines::lines),
|
command("lines", Box::new(lines::lines)),
|
||||||
command("reject", reject::reject),
|
command("reject", Box::new(reject::reject)),
|
||||||
command("trim", trim::trim),
|
command("trim", Box::new(trim::trim)),
|
||||||
command("to-array", to_array::to_array),
|
command("to-array", Box::new(to_array::to_array)),
|
||||||
command("to-json", to_json::to_json),
|
command("to-json", Box::new(to_json::to_json)),
|
||||||
command("to-toml", to_toml::to_toml),
|
command("to-toml", Box::new(to_toml::to_toml)),
|
||||||
command("sort-by", sort_by::sort_by),
|
command("sort-by", Box::new(sort_by::sort_by)),
|
||||||
Arc::new(Open),
|
Arc::new(Open),
|
||||||
Arc::new(Where),
|
Arc::new(Where),
|
||||||
Arc::new(Config),
|
Arc::new(Config),
|
||||||
Arc::new(SkipWhile),
|
Arc::new(SkipWhile),
|
||||||
command("sort-by", sort_by::sort_by),
|
command("sort-by", Box::new(sort_by::sort_by)),
|
||||||
|
/*
|
||||||
command("inc", |x| plugin::filter_plugin("inc".into(), x)),
|
command("inc", |x| plugin::filter_plugin("inc".into(), x)),
|
||||||
|
command("newskip", |x| plugin::filter_plugin("newskip".into(), x)),
|
||||||
|
*/
|
||||||
]);
|
]);
|
||||||
|
|
||||||
context.add_sinks(vec![
|
context.add_sinks(vec![
|
||||||
sink("autoview", autoview::autoview),
|
sink("autoview", Box::new(autoview::autoview)),
|
||||||
sink("clip", clip::clip),
|
sink("clip", Box::new(clip::clip)),
|
||||||
sink("save", save::save),
|
sink("save", Box::new(save::save)),
|
||||||
sink("table", table::table),
|
sink("table", Box::new(table::table)),
|
||||||
sink("tree", tree::tree),
|
sink("tree", Box::new(tree::tree)),
|
||||||
sink("vtable", vtable::vtable),
|
sink("vtable", Box::new(vtable::vtable)),
|
||||||
sink("sum", |x| plugin::sink_plugin("sum".into(), x)),
|
//sink("sum", |x| plugin::sink_plugin("sum".into(), x)),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
load_plugins(&mut context);
|
||||||
|
|
||||||
let config = Config::builder().color_mode(ColorMode::Forced).build();
|
let config = Config::builder().color_mode(ColorMode::Forced).build();
|
||||||
let h = crate::shell::Helper::new(context.clone_commands());
|
let h = crate::shell::Helper::new(context.clone_commands());
|
||||||
|
@ -250,7 +361,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
||||||
Some(ClassifiedCommand::Sink(_)) => {}
|
Some(ClassifiedCommand::Sink(_)) => {}
|
||||||
Some(ClassifiedCommand::External(_)) => {}
|
Some(ClassifiedCommand::External(_)) => {}
|
||||||
_ => pipeline.commands.push(ClassifiedCommand::Sink(SinkCommand {
|
_ => pipeline.commands.push(ClassifiedCommand::Sink(SinkCommand {
|
||||||
command: sink("autoview", autoview::autoview),
|
command: sink("autoview", Box::new(autoview::autoview)),
|
||||||
name_span: None,
|
name_span: None,
|
||||||
args: registry::Args {
|
args: registry::Args {
|
||||||
positional: None,
|
positional: None,
|
||||||
|
|
|
@ -111,7 +111,7 @@ pub trait Sink {
|
||||||
|
|
||||||
pub struct FnCommand {
|
pub struct FnCommand {
|
||||||
name: String,
|
name: String,
|
||||||
func: fn(CommandArgs) -> Result<OutputStream, ShellError>,
|
func: Box<dyn Fn(CommandArgs) -> Result<OutputStream, ShellError>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Command for FnCommand {
|
impl Command for FnCommand {
|
||||||
|
@ -126,7 +126,7 @@ impl Command for FnCommand {
|
||||||
|
|
||||||
pub fn command(
|
pub fn command(
|
||||||
name: &str,
|
name: &str,
|
||||||
func: fn(CommandArgs) -> Result<OutputStream, ShellError>,
|
func: Box<dyn Fn(CommandArgs) -> Result<OutputStream, ShellError>>,
|
||||||
) -> Arc<dyn Command> {
|
) -> Arc<dyn Command> {
|
||||||
Arc::new(FnCommand {
|
Arc::new(FnCommand {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
|
@ -136,7 +136,7 @@ pub fn command(
|
||||||
|
|
||||||
pub struct FnSink {
|
pub struct FnSink {
|
||||||
name: String,
|
name: String,
|
||||||
func: fn(SinkCommandArgs) -> Result<(), ShellError>,
|
func: Box<dyn Fn(SinkCommandArgs) -> Result<(), ShellError>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Sink for FnSink {
|
impl Sink for FnSink {
|
||||||
|
@ -149,7 +149,10 @@ impl Sink for FnSink {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sink(name: &str, func: fn(SinkCommandArgs) -> Result<(), ShellError>) -> Arc<dyn Sink> {
|
pub fn sink(
|
||||||
|
name: &str,
|
||||||
|
func: Box<dyn Fn(SinkCommandArgs) -> Result<(), ShellError>>,
|
||||||
|
) -> Arc<dyn Sink> {
|
||||||
Arc::new(FnSink {
|
Arc::new(FnSink {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
func,
|
func,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::object::{DataDescriptor, Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
@ -7,7 +7,7 @@ fn convert_ini_second_to_nu_value(v: &HashMap<String, String>) -> Value {
|
||||||
let mut second = Dictionary::new(IndexMap::new());
|
let mut second = Dictionary::new(IndexMap::new());
|
||||||
for (key, value) in v.into_iter() {
|
for (key, value) in v.into_iter() {
|
||||||
second.add(
|
second.add(
|
||||||
DataDescriptor::from(key.as_str()),
|
key.clone(),
|
||||||
Value::Primitive(Primitive::String(value.clone())),
|
Value::Primitive(Primitive::String(value.clone())),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -16,10 +16,7 @@ fn convert_ini_second_to_nu_value(v: &HashMap<String, String>) -> Value {
|
||||||
fn convert_ini_top_to_nu_value(v: &HashMap<String, HashMap<String, String>>) -> Value {
|
fn convert_ini_top_to_nu_value(v: &HashMap<String, HashMap<String, String>>) -> Value {
|
||||||
let mut top_level = Dictionary::new(IndexMap::new());
|
let mut top_level = Dictionary::new(IndexMap::new());
|
||||||
for (key, value) in v.iter() {
|
for (key, value) in v.iter() {
|
||||||
top_level.add(
|
top_level.add(key.clone(), convert_ini_second_to_nu_value(value));
|
||||||
DataDescriptor::from(key.as_str()),
|
|
||||||
convert_ini_second_to_nu_value(value),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Value::Object(top_level)
|
Value::Object(top_level)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::object::base::OF64;
|
use crate::object::base::OF64;
|
||||||
use crate::object::{DataDescriptor, Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn convert_json_value_to_nu_value(v: &serde_hjson::Value) -> Value {
|
fn convert_json_value_to_nu_value(v: &serde_hjson::Value) -> Value {
|
||||||
|
@ -18,10 +18,7 @@ fn convert_json_value_to_nu_value(v: &serde_hjson::Value) -> Value {
|
||||||
serde_hjson::Value::Object(o) => {
|
serde_hjson::Value::Object(o) => {
|
||||||
let mut collected = Dictionary::default();
|
let mut collected = Dictionary::default();
|
||||||
for (k, v) in o.iter() {
|
for (k, v) in o.iter() {
|
||||||
collected.add(
|
collected.add(k.clone(), convert_json_value_to_nu_value(v));
|
||||||
DataDescriptor::from(k.clone()),
|
|
||||||
convert_json_value_to_nu_value(v),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Value::Object(collected)
|
Value::Object(collected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::object::base::OF64;
|
use crate::object::base::OF64;
|
||||||
use crate::object::{DataDescriptor, Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn convert_toml_value_to_nu_value(v: &toml::Value) -> Value {
|
fn convert_toml_value_to_nu_value(v: &toml::Value) -> Value {
|
||||||
|
@ -17,10 +17,7 @@ fn convert_toml_value_to_nu_value(v: &toml::Value) -> Value {
|
||||||
toml::Value::Table(t) => {
|
toml::Value::Table(t) => {
|
||||||
let mut collected = Dictionary::default();
|
let mut collected = Dictionary::default();
|
||||||
for (k, v) in t.iter() {
|
for (k, v) in t.iter() {
|
||||||
collected.add(
|
collected.add(k.clone(), convert_toml_value_to_nu_value(v));
|
||||||
DataDescriptor::from(k.clone()),
|
|
||||||
convert_toml_value_to_nu_value(v),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
Value::Object(collected)
|
Value::Object(collected)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::object::{DataDescriptor, Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>) -> Value {
|
fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>) -> Value {
|
||||||
|
@ -25,10 +25,7 @@ fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>) -> Value {
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut collected = Dictionary::default();
|
let mut collected = Dictionary::default();
|
||||||
collected.add(
|
collected.add(name.clone(), Value::List(children_values));
|
||||||
DataDescriptor::from(name.clone()),
|
|
||||||
Value::List(children_values),
|
|
||||||
);
|
|
||||||
|
|
||||||
Value::Object(collected)
|
Value::Object(collected)
|
||||||
} else if n.is_comment() {
|
} else if n.is_comment() {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::object::base::OF64;
|
use crate::object::base::OF64;
|
||||||
use crate::object::{DataDescriptor, Dictionary, Primitive, Value};
|
use crate::object::{Dictionary, Primitive, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value) -> Value {
|
fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value) -> Value {
|
||||||
|
@ -22,10 +22,7 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value) -> Value {
|
||||||
for (k, v) in t.iter() {
|
for (k, v) in t.iter() {
|
||||||
match k {
|
match k {
|
||||||
serde_yaml::Value::String(k) => {
|
serde_yaml::Value::String(k) => {
|
||||||
collected.add(
|
collected.add(k.clone(), convert_yaml_value_to_nu_value(v));
|
||||||
DataDescriptor::from(k.clone()),
|
|
||||||
convert_yaml_value_to_nu_value(v),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => unimplemented!("Unknown key type"),
|
_ => unimplemented!("Unknown key type"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,17 +32,17 @@ pub enum NuResult {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filter_plugin(plugin_name: String, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn filter_plugin(path: String, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let mut path = std::path::PathBuf::from(".");
|
//let mut path = std::path::PathBuf::from(".");
|
||||||
path.push("target");
|
//path.push("target");
|
||||||
path.push("debug");
|
//path.push("debug");
|
||||||
path.push(format!("nu_plugin_{}", plugin_name));
|
//path.push(format!("nu_plugin_{}", plugin_name));
|
||||||
|
|
||||||
path = if path.exists() {
|
// path = if path.exists() {
|
||||||
path
|
// path
|
||||||
} else {
|
// } else {
|
||||||
std::path::PathBuf::from(format!("nu_plugin_{}", plugin_name))
|
// std::path::PathBuf::from(format!("nu_plugin_{}", plugin_name))
|
||||||
};
|
// };
|
||||||
|
|
||||||
let mut child = std::process::Command::new(path)
|
let mut child = std::process::Command::new(path)
|
||||||
.stdin(std::process::Stdio::piped())
|
.stdin(std::process::Stdio::piped())
|
||||||
|
@ -129,17 +129,17 @@ pub fn filter_plugin(plugin_name: String, args: CommandArgs) -> Result<OutputStr
|
||||||
Ok(stream.boxed())
|
Ok(stream.boxed())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sink_plugin(plugin_name: String, args: SinkCommandArgs) -> Result<(), ShellError> {
|
pub fn sink_plugin(path: String, args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||||
let mut path = std::path::PathBuf::from(".");
|
// let mut path = std::path::PathBuf::from(".");
|
||||||
path.push("target");
|
// path.push("target");
|
||||||
path.push("debug");
|
// path.push("debug");
|
||||||
path.push(format!("nu_plugin_{}", plugin_name));
|
// path.push(format!("nu_plugin_{}", plugin_name));
|
||||||
|
|
||||||
path = if path.exists() {
|
// path = if path.exists() {
|
||||||
path
|
// path
|
||||||
} else {
|
// } else {
|
||||||
std::path::PathBuf::from(format!("nu_plugin_{}", plugin_name))
|
// std::path::PathBuf::from(format!("nu_plugin_{}", plugin_name))
|
||||||
};
|
// };
|
||||||
|
|
||||||
let mut child = std::process::Command::new(path)
|
let mut child = std::process::Command::new(path)
|
||||||
.stdin(std::process::Stdio::piped())
|
.stdin(std::process::Stdio::piped())
|
||||||
|
|
|
@ -27,7 +27,7 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value {
|
||||||
Value::Object(o) => {
|
Value::Object(o) => {
|
||||||
let mut m = serde_json::Map::new();
|
let mut m = serde_json::Map::new();
|
||||||
for (k, v) in o.entries.iter() {
|
for (k, v) in o.entries.iter() {
|
||||||
m.insert(k.name.display().to_string(), value_to_json_value(v));
|
m.insert(k.clone(), value_to_json_value(v));
|
||||||
}
|
}
|
||||||
serde_json::Value::Object(m)
|
serde_json::Value::Object(m)
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value {
|
||||||
Value::Object(o) => {
|
Value::Object(o) => {
|
||||||
let mut m = toml::map::Map::new();
|
let mut m = toml::map::Map::new();
|
||||||
for (k, v) in o.entries.iter() {
|
for (k, v) in o.entries.iter() {
|
||||||
m.insert(k.name.display().to_string(), value_to_toml_value(v));
|
m.insert(k.clone(), value_to_toml_value(v));
|
||||||
}
|
}
|
||||||
toml::Value::Table(m)
|
toml::Value::Table(m)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use derive_new::new;
|
||||||
// another_name : ...
|
// another_name : ...
|
||||||
#[derive(new)]
|
#[derive(new)]
|
||||||
pub struct EntriesView {
|
pub struct EntriesView {
|
||||||
entries: Vec<(crate::object::DescriptorName, String)>,
|
entries: Vec<(String, String)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EntriesView {
|
impl EntriesView {
|
||||||
|
@ -23,7 +23,7 @@ impl EntriesView {
|
||||||
|
|
||||||
let formatted_value = value.borrow().format_leaf(None);
|
let formatted_value = value.borrow().format_leaf(None);
|
||||||
|
|
||||||
entries.push((desc.name.clone(), formatted_value))
|
entries.push((desc.clone(), formatted_value))
|
||||||
}
|
}
|
||||||
|
|
||||||
EntriesView::new(entries)
|
EntriesView::new(entries)
|
||||||
|
@ -36,20 +36,10 @@ impl RenderView for EntriesView {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let max_name_size: usize = self
|
let max_name_size: usize = self.entries.iter().map(|(n, _)| n.len()).max().unwrap();
|
||||||
.entries
|
|
||||||
.iter()
|
|
||||||
.map(|(n, _)| n.display().len())
|
|
||||||
.max()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
for (name, value) in &self.entries {
|
for (name, value) in &self.entries {
|
||||||
println!(
|
println!("{:width$} : {}", name, value, width = max_name_size)
|
||||||
"{:width$} : {}",
|
|
||||||
name.display(),
|
|
||||||
value,
|
|
||||||
width = max_name_size
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::format::RenderView;
|
use crate::format::RenderView;
|
||||||
use crate::object::{DataDescriptor, Value};
|
use crate::object::Value;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use prettytable::format::{FormatBuilder, LinePosition, LineSeparator};
|
use prettytable::format::{FormatBuilder, LinePosition, LineSeparator};
|
||||||
|
@ -8,12 +8,12 @@ use prettytable::{color, Attr, Cell, Row, Table};
|
||||||
|
|
||||||
#[derive(new)]
|
#[derive(new)]
|
||||||
pub struct TableView {
|
pub struct TableView {
|
||||||
headers: Vec<DataDescriptor>,
|
headers: Vec<String>,
|
||||||
entries: Vec<Vec<String>>,
|
entries: Vec<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableView {
|
impl TableView {
|
||||||
fn merge_descriptors(values: &[Value]) -> Vec<DataDescriptor> {
|
fn merge_descriptors(values: &[Value]) -> Vec<String> {
|
||||||
let mut ret = vec![];
|
let mut ret = vec![];
|
||||||
for value in values {
|
for value in values {
|
||||||
for desc in value.data_descriptors() {
|
for desc in value.data_descriptors() {
|
||||||
|
@ -30,10 +30,10 @@ impl TableView {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let headers = TableView::merge_descriptors(values);
|
let mut headers = TableView::merge_descriptors(values);
|
||||||
|
|
||||||
if headers.len() == 0 {
|
if headers.len() == 0 {
|
||||||
return None;
|
headers.push("value".to_string());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut entries = vec![];
|
let mut entries = vec![];
|
||||||
|
@ -74,7 +74,7 @@ impl RenderView for TableView {
|
||||||
.headers
|
.headers
|
||||||
.iter()
|
.iter()
|
||||||
.map(|h| {
|
.map(|h| {
|
||||||
Cell::new(h.display_header())
|
Cell::new(h)
|
||||||
.with_style(Attr::ForegroundColor(color::GREEN))
|
.with_style(Attr::ForegroundColor(color::GREEN))
|
||||||
.with_style(Attr::Bold)
|
.with_style(Attr::Bold)
|
||||||
})
|
})
|
||||||
|
|
|
@ -26,7 +26,7 @@ impl TreeView {
|
||||||
}
|
}
|
||||||
Value::Object(o) => {
|
Value::Object(o) => {
|
||||||
for (k, v) in o.entries.iter() {
|
for (k, v) in o.entries.iter() {
|
||||||
builder = builder.begin_child(k.name.display().to_string());
|
builder = builder.begin_child(k.clone());
|
||||||
Self::from_value_helper(v, builder);
|
Self::from_value_helper(v, builder);
|
||||||
builder = builder.end_child();
|
builder = builder.end_child();
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ impl TreeView {
|
||||||
|
|
||||||
for desc in descs {
|
for desc in descs {
|
||||||
let value = value.get_data(&desc);
|
let value = value.get_data(&desc);
|
||||||
builder = builder.begin_child(desc.name.display().to_string());
|
builder = builder.begin_child(desc.clone());
|
||||||
Self::from_value_helper(value.borrow(), &mut builder);
|
Self::from_value_helper(value.borrow(), &mut builder);
|
||||||
builder = builder.end_child();
|
builder = builder.end_child();
|
||||||
//entries.push((desc.name.clone(), value.borrow().copy()))
|
//entries.push((desc.name.clone(), value.borrow().copy()))
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use crate::format::RenderView;
|
use crate::format::RenderView;
|
||||||
use crate::object::{DescriptorName, Value};
|
use crate::object::Value;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use prettytable::format::{FormatBuilder, LinePosition, LineSeparator};
|
use prettytable::format::{FormatBuilder, LinePosition, LineSeparator};
|
||||||
|
@ -29,11 +29,7 @@ impl VTableView {
|
||||||
for header in headers {
|
for header in headers {
|
||||||
let mut row = vec![];
|
let mut row = vec![];
|
||||||
|
|
||||||
if let DescriptorName::String(s) = &header.name {
|
row.push(header.clone());
|
||||||
row.push(s.clone());
|
|
||||||
} else {
|
|
||||||
row.push("value".to_string());
|
|
||||||
}
|
|
||||||
for value in values {
|
for value in values {
|
||||||
row.push(value.get_data(&header).borrow().format_leaf(Some(&header)));
|
row.push(value.get_data(&header).borrow().format_leaf(Some(&header)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,4 +28,4 @@ pub use cli::cli;
|
||||||
pub use errors::ShellError;
|
pub use errors::ShellError;
|
||||||
pub use object::base::{Primitive, Value};
|
pub use object::base::{Primitive, Value};
|
||||||
pub use parser::parse::text::Text;
|
pub use parser::parse::text::Text;
|
||||||
pub use parser::registry::{Args, CommandConfig};
|
pub use parser::registry::{Args, CommandConfig, NamedType, PositionalType};
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
crate mod base;
|
crate mod base;
|
||||||
crate mod config;
|
crate mod config;
|
||||||
crate mod desc;
|
|
||||||
crate mod dict;
|
crate mod dict;
|
||||||
crate mod files;
|
crate mod files;
|
||||||
crate mod process;
|
crate mod process;
|
||||||
crate mod types;
|
crate mod types;
|
||||||
|
|
||||||
crate use base::{Primitive, Value};
|
crate use base::{Primitive, Value};
|
||||||
crate use desc::{DataDescriptor, DescriptorName};
|
|
||||||
crate use dict::Dictionary;
|
crate use dict::Dictionary;
|
||||||
crate use files::dir_entry_dict;
|
crate use files::dir_entry_dict;
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
use crate::evaluate::{evaluate_baseline_expr, Scope};
|
||||||
use crate::object::DataDescriptor;
|
|
||||||
use crate::parser::{hir, Operator, Span, Spanned};
|
use crate::parser::{hir, Operator, Span, Spanned};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::Text;
|
use crate::Text;
|
||||||
|
@ -76,7 +75,7 @@ impl Primitive {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn format(&self, field_name: Option<&DataDescriptor>) -> String {
|
crate fn format(&self, field_name: Option<&String>) -> String {
|
||||||
match self {
|
match self {
|
||||||
Primitive::Nothing => format!("{}", Color::Black.bold().paint("-")),
|
Primitive::Nothing => format!("{}", Color::Black.bold().paint("-")),
|
||||||
Primitive::EndOfStream => format!("{}", Color::Black.bold().paint("-")),
|
Primitive::EndOfStream => format!("{}", Color::Black.bold().paint("-")),
|
||||||
|
@ -100,8 +99,8 @@ impl Primitive {
|
||||||
Primitive::Boolean(b) => match (b, field_name) {
|
Primitive::Boolean(b) => match (b, field_name) {
|
||||||
(true, None) => format!("Yes"),
|
(true, None) => format!("Yes"),
|
||||||
(false, None) => format!("No"),
|
(false, None) => format!("No"),
|
||||||
(true, Some(s)) if s.is_string_name() => format!("{}", s.display_header()),
|
(true, Some(s)) if !s.is_empty() => format!("{}", s),
|
||||||
(false, Some(s)) if s.is_string_name() => format!(""),
|
(false, Some(s)) if !s.is_empty() => format!(""),
|
||||||
(true, Some(_)) => format!("Yes"),
|
(true, Some(_)) => format!("Yes"),
|
||||||
(false, Some(_)) => format!("No"),
|
(false, Some(_)) => format!("No"),
|
||||||
},
|
},
|
||||||
|
@ -245,13 +244,18 @@ impl Value {
|
||||||
ValueDebug { value: self }
|
ValueDebug { value: self }
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn data_descriptors(&self) -> Vec<DataDescriptor> {
|
crate fn data_descriptors(&self) -> Vec<String> {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(_) => vec![DataDescriptor::value_of()],
|
Value::Primitive(_) => vec![],
|
||||||
Value::Object(o) => o.data_descriptors(),
|
Value::Object(o) => o
|
||||||
Value::Block(_) => vec![DataDescriptor::value_of()],
|
.entries
|
||||||
|
.keys()
|
||||||
|
.into_iter()
|
||||||
|
.map(|x| x.to_string())
|
||||||
|
.collect(),
|
||||||
|
Value::Block(_) => vec![],
|
||||||
Value::List(_) => vec![],
|
Value::List(_) => vec![],
|
||||||
Value::Error(_) => vec![DataDescriptor::value_of()],
|
Value::Error(_) => vec![],
|
||||||
Value::Filesystem => vec![],
|
Value::Filesystem => vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -282,7 +286,7 @@ impl Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn get_data(&'a self, desc: &DataDescriptor) -> MaybeOwned<'a, Value> {
|
crate fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
|
||||||
match self {
|
match self {
|
||||||
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
|
p @ Value::Primitive(_) => MaybeOwned::Borrowed(p),
|
||||||
p @ Value::Filesystem => MaybeOwned::Borrowed(p),
|
p @ Value::Filesystem => MaybeOwned::Borrowed(p),
|
||||||
|
@ -307,7 +311,7 @@ impl Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn format_leaf(&self, desc: Option<&DataDescriptor>) -> String {
|
crate fn format_leaf(&self, desc: Option<&String>) -> String {
|
||||||
match self {
|
match self {
|
||||||
Value::Primitive(p) => p.format(desc),
|
Value::Primitive(p) => p.format(desc),
|
||||||
Value::Block(b) => itertools::join(
|
Value::Block(b) => itertools::join(
|
||||||
|
@ -471,9 +475,9 @@ crate fn select_fields(obj: &Value, fields: &[String]) -> crate::object::Diction
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
|
|
||||||
for field in fields {
|
for field in fields {
|
||||||
match descs.iter().find(|d| d.name.is_string(field)) {
|
match descs.iter().find(|d| *d == field) {
|
||||||
None => out.add(DataDescriptor::for_string_name(field), Value::nothing()),
|
None => out.add(field, Value::nothing()),
|
||||||
Some(desc) => out.add(desc.copy(), obj.get_data(desc).borrow().copy()),
|
Some(desc) => out.add(desc.clone(), obj.get_data(desc).borrow().copy()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,10 +490,9 @@ crate fn reject_fields(obj: &Value, fields: &[String]) -> crate::object::Diction
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
|
|
||||||
for desc in descs {
|
for desc in descs {
|
||||||
match desc.name.as_string() {
|
match desc {
|
||||||
None => continue,
|
x if fields.iter().any(|field| *field == x) => continue,
|
||||||
Some(s) if fields.iter().any(|field| field == s) => continue,
|
_ => out.add(desc.clone(), obj.get_data(&desc).borrow().copy()),
|
||||||
Some(_) => out.add(desc.copy(), obj.get_data(&desc).borrow().copy()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -499,7 +502,7 @@ crate fn reject_fields(obj: &Value, fields: &[String]) -> crate::object::Diction
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool {
|
crate fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool {
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
match descs.iter().find(|d| d.name.is_string(field)) {
|
match descs.iter().find(|d| *d == field) {
|
||||||
None => false,
|
None => false,
|
||||||
Some(desc) => {
|
Some(desc) => {
|
||||||
let v = obj.get_data(desc).borrow().copy();
|
let v = obj.get_data(desc).borrow().copy();
|
||||||
|
|
|
@ -1,134 +0,0 @@
|
||||||
use crate::object::types::Type;
|
|
||||||
use crate::Text;
|
|
||||||
use derive_new::new;
|
|
||||||
use serde::{Deserialize, Serialize, Serializer};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
|
||||||
pub enum DescriptorName {
|
|
||||||
String(String),
|
|
||||||
ValueOf,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DescriptorName {
|
|
||||||
crate fn display(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
DescriptorName::String(s) => s,
|
|
||||||
DescriptorName::ValueOf => "value",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn debug(&self) -> &str {
|
|
||||||
match self {
|
|
||||||
DescriptorName::String(s) => s,
|
|
||||||
DescriptorName::ValueOf => "[[value]]",
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn as_string(&self) -> Option<&str> {
|
|
||||||
match self {
|
|
||||||
DescriptorName::String(s) => Some(s),
|
|
||||||
DescriptorName::ValueOf => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn is_string(&self, string: &str) -> bool {
|
|
||||||
match self {
|
|
||||||
DescriptorName::String(s) => s == string,
|
|
||||||
DescriptorName::ValueOf => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
|
|
||||||
pub struct DataDescriptor {
|
|
||||||
crate name: DescriptorName,
|
|
||||||
crate readonly: bool,
|
|
||||||
crate ty: Type,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DataDescriptor {
|
|
||||||
crate fn display_header(&self) -> &str {
|
|
||||||
self.name.display()
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn is_string_name(&self) -> bool {
|
|
||||||
match self.name {
|
|
||||||
DescriptorName::String(_) => true,
|
|
||||||
DescriptorName::ValueOf => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Serialize for DataDescriptor {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
match self.name {
|
|
||||||
DescriptorName::String(ref s) => serializer.serialize_str(s),
|
|
||||||
DescriptorName::ValueOf => serializer.serialize_str("value"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<&str> for DataDescriptor {
|
|
||||||
fn from(input: &str) -> DataDescriptor {
|
|
||||||
DataDescriptor {
|
|
||||||
name: DescriptorName::String(input.to_string()),
|
|
||||||
readonly: true,
|
|
||||||
ty: Type::Any,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<String> for DataDescriptor {
|
|
||||||
fn from(input: String) -> DataDescriptor {
|
|
||||||
DataDescriptor {
|
|
||||||
name: DescriptorName::String(input),
|
|
||||||
readonly: true,
|
|
||||||
ty: Type::Any,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<Text> for DataDescriptor {
|
|
||||||
fn from(input: Text) -> DataDescriptor {
|
|
||||||
DataDescriptor {
|
|
||||||
name: DescriptorName::String(input.to_string()),
|
|
||||||
readonly: true,
|
|
||||||
ty: Type::Any,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DescriptorName {
|
|
||||||
crate fn for_string_name(name: impl AsRef<str>) -> DescriptorName {
|
|
||||||
DescriptorName::String(name.as_ref().into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DataDescriptor {
|
|
||||||
crate fn value_of() -> DataDescriptor {
|
|
||||||
DataDescriptor {
|
|
||||||
name: DescriptorName::ValueOf,
|
|
||||||
readonly: true,
|
|
||||||
ty: Type::Any,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn for_name(name: impl Into<DescriptorName>) -> DataDescriptor {
|
|
||||||
DataDescriptor {
|
|
||||||
name: name.into(),
|
|
||||||
readonly: true,
|
|
||||||
ty: Type::Any,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn for_string_name(name: impl AsRef<str>) -> DataDescriptor {
|
|
||||||
DataDescriptor::for_name(DescriptorName::for_string_name(name))
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn copy(&self) -> DataDescriptor {
|
|
||||||
self.clone()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +1,21 @@
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
use crate::object::DataDescriptor;
|
|
||||||
use crate::object::{Primitive, Value};
|
use crate::object::{Primitive, Value};
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use serde::ser::{Serialize, SerializeMap, Serializer};
|
use serde::{Deserialize, Serialize};
|
||||||
use serde_derive::Deserialize;
|
|
||||||
use std::cmp::{Ordering, PartialOrd};
|
use std::cmp::{Ordering, PartialOrd};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
#[derive(Debug, Default, Eq, PartialEq, Deserialize, Clone, new)]
|
#[derive(Debug, Default, Eq, PartialEq, Serialize, Deserialize, Clone, new)]
|
||||||
pub struct Dictionary {
|
pub struct Dictionary {
|
||||||
pub entries: IndexMap<DataDescriptor, Value>,
|
pub entries: IndexMap<String, Value>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PartialOrd for Dictionary {
|
impl PartialOrd for Dictionary {
|
||||||
fn partial_cmp(&self, other: &Dictionary) -> Option<Ordering> {
|
fn partial_cmp(&self, other: &Dictionary) -> Option<Ordering> {
|
||||||
let this: Vec<&DataDescriptor> = self.entries.keys().collect();
|
let this: Vec<&String> = self.entries.keys().collect();
|
||||||
let that: Vec<&DataDescriptor> = other.entries.keys().collect();
|
let that: Vec<&String> = other.entries.keys().collect();
|
||||||
|
|
||||||
if this != that {
|
if this != that {
|
||||||
return this.partial_cmp(&that);
|
return this.partial_cmp(&that);
|
||||||
|
@ -30,34 +28,12 @@ impl PartialOrd for Dictionary {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Serialize for Dictionary {
|
|
||||||
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|
||||||
where
|
|
||||||
S: Serializer,
|
|
||||||
{
|
|
||||||
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)?,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (k, v) in self.entries.iter() {
|
|
||||||
match v {
|
|
||||||
Value::Object(_) => map.serialize_entry(k, v)?,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
map.end()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl From<IndexMap<String, Value>> for Dictionary {
|
impl From<IndexMap<String, Value>> for Dictionary {
|
||||||
fn from(input: IndexMap<String, Value>) -> Dictionary {
|
fn from(input: IndexMap<String, Value>) -> Dictionary {
|
||||||
let mut out = IndexMap::default();
|
let mut out = IndexMap::default();
|
||||||
|
|
||||||
for (key, value) in input {
|
for (key, value) in input {
|
||||||
out.insert(DataDescriptor::for_string_name(key), value);
|
out.insert(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
Dictionary::new(out)
|
Dictionary::new(out)
|
||||||
|
@ -66,8 +42,8 @@ impl From<IndexMap<String, Value>> for Dictionary {
|
||||||
|
|
||||||
impl Ord for Dictionary {
|
impl Ord for Dictionary {
|
||||||
fn cmp(&self, other: &Dictionary) -> Ordering {
|
fn cmp(&self, other: &Dictionary) -> Ordering {
|
||||||
let this: Vec<&DataDescriptor> = self.entries.keys().collect();
|
let this: Vec<&String> = self.entries.keys().collect();
|
||||||
let that: Vec<&DataDescriptor> = other.entries.keys().collect();
|
let that: Vec<&String> = other.entries.keys().collect();
|
||||||
|
|
||||||
if this != that {
|
if this != that {
|
||||||
return this.cmp(&that);
|
return this.cmp(&that);
|
||||||
|
@ -96,7 +72,7 @@ impl PartialEq<Value> for Dictionary {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Dictionary {
|
impl Dictionary {
|
||||||
crate fn add(&mut self, name: impl Into<DataDescriptor>, value: Value) {
|
crate fn add(&mut self, name: impl Into<String>, value: Value) {
|
||||||
self.entries.insert(name.into(), value);
|
self.entries.insert(name.into(), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,17 +80,13 @@ impl Dictionary {
|
||||||
let mut out = Dictionary::default();
|
let mut out = Dictionary::default();
|
||||||
|
|
||||||
for (key, value) in self.entries.iter() {
|
for (key, value) in self.entries.iter() {
|
||||||
out.add(key.copy(), value.copy());
|
out.add(key.clone(), value.copy());
|
||||||
}
|
}
|
||||||
|
|
||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn data_descriptors(&self) -> Vec<DataDescriptor> {
|
crate fn get_data(&'a self, desc: &String) -> MaybeOwned<'a, Value> {
|
||||||
self.entries.iter().map(|(name, _)| name.copy()).collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn get_data(&'a self, desc: &DataDescriptor) -> MaybeOwned<'a, Value> {
|
|
||||||
match self.entries.get(desc) {
|
match self.entries.get(desc) {
|
||||||
Some(v) => MaybeOwned::Borrowed(v),
|
Some(v) => MaybeOwned::Borrowed(v),
|
||||||
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),
|
None => MaybeOwned::Owned(Value::Primitive(Primitive::Nothing)),
|
||||||
|
@ -125,7 +97,7 @@ impl Dictionary {
|
||||||
match self
|
match self
|
||||||
.entries
|
.entries
|
||||||
.iter()
|
.iter()
|
||||||
.find(|(desc_name, _)| desc_name.name.is_string(name))
|
.find(|(desc_name, _)| *desc_name == name)
|
||||||
{
|
{
|
||||||
Some((_, v)) => Some(v),
|
Some((_, v)) => Some(v),
|
||||||
None => None,
|
None => None,
|
||||||
|
@ -136,7 +108,7 @@ impl Dictionary {
|
||||||
let mut debug = f.debug_struct("Dictionary");
|
let mut debug = f.debug_struct("Dictionary");
|
||||||
|
|
||||||
for (desc, value) in self.entries.iter() {
|
for (desc, value) in self.entries.iter() {
|
||||||
debug.field(desc.name.debug(), &value.debug());
|
debug.field(desc, &value.debug());
|
||||||
}
|
}
|
||||||
|
|
||||||
debug.finish()
|
debug.finish()
|
||||||
|
|
|
@ -3,9 +3,7 @@ use serde::{Deserialize, Serialize};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
|
||||||
pub trait Plugin {
|
pub trait Plugin {
|
||||||
fn config(&mut self) -> Result<CommandConfig, ShellError> {
|
fn config(&mut self) -> Result<CommandConfig, ShellError>;
|
||||||
Err(ShellError::string("`config` not implemented in plugin"))
|
|
||||||
}
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> {
|
fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> {
|
||||||
Err(ShellError::string(
|
Err(ShellError::string(
|
||||||
|
@ -50,8 +48,8 @@ pub fn serve_plugin(plugin: &mut dyn Plugin) {
|
||||||
}
|
}
|
||||||
e => {
|
e => {
|
||||||
send_response(ShellError::string(format!(
|
send_response(ShellError::string(format!(
|
||||||
"Could not handle plugin message: {:?}",
|
"Could not handle plugin message: {} {:?}",
|
||||||
e,
|
input, e
|
||||||
)));
|
)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,8 @@
|
||||||
use nu::{serve_plugin, Args, Plugin, Primitive, ReturnValue, ShellError, Spanned, Value};
|
use indexmap::IndexMap;
|
||||||
|
use nu::{
|
||||||
|
serve_plugin, Args, CommandConfig, Plugin, PositionalType, Primitive, ReturnValue, ShellError,
|
||||||
|
Spanned, Value,
|
||||||
|
};
|
||||||
|
|
||||||
struct Inc {
|
struct Inc {
|
||||||
inc_by: i64,
|
inc_by: i64,
|
||||||
|
@ -10,6 +14,19 @@ impl Inc {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plugin for Inc {
|
impl Plugin for Inc {
|
||||||
|
fn config(&mut self) -> Result<CommandConfig, ShellError> {
|
||||||
|
Ok(CommandConfig {
|
||||||
|
name: "inc".to_string(),
|
||||||
|
mandatory_positional: vec![],
|
||||||
|
optional_positional: vec![PositionalType::Value("Increment".into())],
|
||||||
|
can_load: vec![],
|
||||||
|
can_save: vec![],
|
||||||
|
is_filter: true,
|
||||||
|
is_sink: false,
|
||||||
|
named: IndexMap::new(),
|
||||||
|
rest_positional: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> {
|
fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> {
|
||||||
if let Some(args) = args.positional {
|
if let Some(args) = args.positional {
|
||||||
for arg in args {
|
for arg in args {
|
||||||
|
|
59
src/plugins/newskip.rs
Normal file
59
src/plugins/newskip.rs
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
use indexmap::IndexMap;
|
||||||
|
use nu::{
|
||||||
|
serve_plugin, Args, CommandConfig, Plugin, Primitive, ReturnValue, ShellError, Spanned, Value,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct NewSkip {
|
||||||
|
skip_amount: i64,
|
||||||
|
}
|
||||||
|
impl NewSkip {
|
||||||
|
fn new() -> NewSkip {
|
||||||
|
NewSkip { skip_amount: 0 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Plugin for NewSkip {
|
||||||
|
fn config(&mut self) -> Result<CommandConfig, ShellError> {
|
||||||
|
Ok(CommandConfig {
|
||||||
|
name: "skip".to_string(),
|
||||||
|
mandatory_positional: vec![],
|
||||||
|
optional_positional: vec![],
|
||||||
|
can_load: vec![],
|
||||||
|
can_save: vec![],
|
||||||
|
is_filter: true,
|
||||||
|
is_sink: false,
|
||||||
|
named: IndexMap::new(),
|
||||||
|
rest_positional: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> {
|
||||||
|
if let Some(args) = args.positional {
|
||||||
|
for arg in args {
|
||||||
|
match arg {
|
||||||
|
Spanned {
|
||||||
|
item: Value::Primitive(Primitive::Int(i)),
|
||||||
|
..
|
||||||
|
} => {
|
||||||
|
self.skip_amount = i;
|
||||||
|
}
|
||||||
|
_ => return Err(ShellError::string("Unrecognized type in params")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn filter(&mut self, input: Value) -> Result<Vec<ReturnValue>, ShellError> {
|
||||||
|
if self.skip_amount == 0 {
|
||||||
|
Ok(vec![ReturnValue::Value(input)])
|
||||||
|
} else {
|
||||||
|
self.skip_amount -= 1;
|
||||||
|
Ok(vec![])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
serve_plugin(&mut NewSkip::new());
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
use nu::{serve_plugin, Args, Plugin, Primitive, Value};
|
use indexmap::IndexMap;
|
||||||
|
use nu::{serve_plugin, Args, CommandConfig, Plugin, Primitive, ShellError, Value};
|
||||||
|
|
||||||
struct Sum;
|
struct Sum;
|
||||||
|
|
||||||
|
@ -9,6 +10,20 @@ impl Sum {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Plugin for Sum {
|
impl Plugin for Sum {
|
||||||
|
fn config(&mut self) -> Result<CommandConfig, ShellError> {
|
||||||
|
Ok(CommandConfig {
|
||||||
|
name: "sum".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>) {
|
fn sink(&mut self, _args: Args, input: Vec<Value>) {
|
||||||
let mut total = 0i64;
|
let mut total = 0i64;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue