From 15507f00fcf38948fee04e93a5654eaf7085d1c3 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Sat, 20 Jul 2019 14:27:10 +1200 Subject: [PATCH] Introduce CallInfo, which abstracts args, name_span, and source_map --- src/commands/autoview.rs | 2 +- src/commands/cd.rs | 2 +- src/commands/clip.rs | 2 +- src/commands/command.rs | 27 ++++++++++--------- src/commands/config.rs | 8 +++--- src/commands/first.rs | 2 +- src/commands/from_csv.rs | 14 ++++++---- src/commands/from_ini.rs | 2 +- src/commands/from_json.rs | 2 +- src/commands/from_toml.rs | 2 +- src/commands/from_xml.rs | 2 +- src/commands/from_yaml.rs | 2 +- src/commands/get.rs | 2 +- src/commands/lines.rs | 2 +- src/commands/ls.rs | 4 +-- src/commands/open.rs | 4 +-- src/commands/pick.rs | 2 +- src/commands/plugin.rs | 4 +-- src/commands/ps.rs | 2 +- src/commands/reject.rs | 4 +-- src/commands/rm.rs | 33 +++++++++++------------ src/commands/save.rs | 6 ++--- src/commands/skip_while.rs | 2 +- src/commands/split_column.rs | 4 +-- src/commands/split_row.rs | 4 +-- src/commands/sysinfo.rs | 19 +++++++------- src/commands/to_json.rs | 2 +- src/commands/to_toml.rs | 2 +- src/commands/to_yaml.rs | 2 +- src/context.rs | 18 ++++++++----- src/lib.rs | 3 ++- src/plugin.rs | 18 ++++++++----- src/plugins/binaryview.rs | 51 ++++++++++++++++++++++++++++++------ src/plugins/inc.rs | 14 +++++----- src/plugins/skip.rs | 16 +++++++---- src/plugins/tree.rs | 4 +-- 36 files changed, 173 insertions(+), 116 deletions(-) diff --git a/src/commands/autoview.rs b/src/commands/autoview.rs index d13d324f94..b092159829 100644 --- a/src/commands/autoview.rs +++ b/src/commands/autoview.rs @@ -14,7 +14,7 @@ pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> { { args.ctx.get_sink("binaryview").run(args)?; } else if is_single_text_value(&args.input) { - view_text_value(&args.input[0], &args.source_map); + view_text_value(&args.input[0], &args.call_info.source_map); } else if equal_shapes(&args.input) { args.ctx.get_sink("table").run(args)?; } else { diff --git a/src/commands/cd.rs b/src/commands/cd.rs index 246c4c40d1..b68a0deb70 100644 --- a/src/commands/cd.rs +++ b/src/commands/cd.rs @@ -13,7 +13,7 @@ pub fn cd(args: CommandArgs) -> Result { return Err(ShellError::maybe_labeled_error( "Can not change to home directory", "can not go to home", - args.name_span, + args.call_info.name_span, )) } }, diff --git a/src/commands/clip.rs b/src/commands/clip.rs index 96b6b7081e..32294bf776 100644 --- a/src/commands/clip.rs +++ b/src/commands/clip.rs @@ -16,7 +16,7 @@ pub fn clip(args: SinkCommandArgs) -> Result<(), ShellError> { } let string = i.as_string().map_err(labelled( - args.name_span, + args.call_info.name_span, "Given non-string data", "expected strings from pipeline", ))?; diff --git a/src/commands/command.rs b/src/commands/command.rs index 5bc2e08778..e5057c6cd1 100644 --- a/src/commands/command.rs +++ b/src/commands/command.rs @@ -12,49 +12,52 @@ use serde::{Deserialize, Serialize}; use std::path::PathBuf; use uuid::Uuid; +#[derive(Deserialize, Serialize, Debug)] +pub struct CallInfo { + pub args: Args, + pub source_map: SourceMap, + pub name_span: Option, +} + #[derive(Getters)] #[get = "crate"] pub struct CommandArgs { pub host: Arc>, pub env: Arc>, - pub name_span: Option, - pub source_map: SourceMap, - pub args: Args, + pub call_info: CallInfo, pub input: InputStream, } impl CommandArgs { pub fn nth(&self, pos: usize) -> Option<&Spanned> { - self.args.nth(pos) + self.call_info.args.nth(pos) } pub fn positional_iter(&self) -> impl Iterator> { - self.args.positional_iter() + self.call_info.args.positional_iter() } pub fn expect_nth(&self, pos: usize) -> Result<&Spanned, ShellError> { - self.args.expect_nth(pos) + self.call_info.args.expect_nth(pos) } pub fn len(&self) -> usize { - self.args.len() + self.call_info.args.len() } pub fn get(&self, name: &str) -> Option<&Spanned> { - self.args.get(name) + self.call_info.args.get(name) } #[allow(unused)] pub fn has(&self, name: &str) -> bool { - self.args.has(name) + self.call_info.args.has(name) } } pub struct SinkCommandArgs { pub ctx: Context, - pub name_span: Option, - pub source_map: SourceMap, - pub args: Args, + pub call_info: CallInfo, pub input: Vec>, } diff --git a/src/commands/config.rs b/src/commands/config.rs index 954cc08efc..7da3c91c66 100644 --- a/src/commands/config.rs +++ b/src/commands/config.rs @@ -39,10 +39,10 @@ impl Command for Config { } pub fn config(args: CommandArgs) -> Result { - let mut result = crate::object::config::config(args.name_span)?; + let mut result = crate::object::config::config(args.call_info.name_span)?; - trace!("{:#?}", args.args.positional); - trace!("{:#?}", args.args.named); + trace!("{:#?}", args.call_info.args.positional); + trace!("{:#?}", args.call_info.args.named); if let Some(v) = args.get("get") { let key = v.as_string()?; @@ -95,7 +95,7 @@ pub fn config(args: CommandArgs) -> Result { } if args.len() == 0 { - return Ok(vec![Value::Object(result.into()).spanned(args.name_span)].into()); + return Ok(vec![Value::Object(result.into()).spanned(args.call_info.name_span)].into()); } Err(ShellError::string(format!("Unimplemented"))) diff --git a/src/commands/first.rs b/src/commands/first.rs index 5a466a8cd5..aec66b3a62 100644 --- a/src/commands/first.rs +++ b/src/commands/first.rs @@ -8,7 +8,7 @@ pub fn first(args: CommandArgs) -> Result { return Err(ShellError::maybe_labeled_error( "First requires an amount", "needs parameter", - args.name_span, + args.call_info.name_span, )); } diff --git a/src/commands/from_csv.rs b/src/commands/from_csv.rs index c6e0fa9eca..9c70bf1edf 100644 --- a/src/commands/from_csv.rs +++ b/src/commands/from_csv.rs @@ -6,8 +6,9 @@ pub fn from_csv_string_to_value( s: String, span: impl Into, ) -> Result, Box> { - - let mut reader = ReaderBuilder::new().has_headers(false).from_reader(s.as_bytes()); + let mut reader = ReaderBuilder::new() + .has_headers(false) + .from_reader(s.as_bytes()); let span = span.into(); let mut fields: VecDeque = VecDeque::new(); @@ -28,9 +29,12 @@ pub fn from_csv_string_to_value( let row_values = row_values?; let mut row = SpannedDictBuilder::new(span); - + for (idx, entry) in row_values.iter().enumerate() { - row.insert_spanned(fields.get(idx).unwrap(), Value::Primitive(Primitive::String(String::from(entry))).spanned(span)); + row.insert_spanned( + fields.get(idx).unwrap(), + Value::Primitive(Primitive::String(String::from(entry))).spanned(span), + ); } rows.insert_spanned(row.into_spanned_value()); @@ -45,7 +49,7 @@ pub fn from_csv_string_to_value( pub fn from_csv(args: CommandArgs) -> Result { let out = args.input; - let span = args.name_span; + let span = args.call_info.name_span; Ok(out .values diff --git a/src/commands/from_ini.rs b/src/commands/from_ini.rs index 340ad26e4f..193356dce8 100644 --- a/src/commands/from_ini.rs +++ b/src/commands/from_ini.rs @@ -39,7 +39,7 @@ pub fn from_ini_string_to_value( pub fn from_ini(args: CommandArgs) -> Result { let out = args.input; - let span = args.name_span; + let span = args.call_info.name_span; Ok(out .values .map(move |a| match a.item { diff --git a/src/commands/from_json.rs b/src/commands/from_json.rs index 36dae4b1b1..f3968dd120 100644 --- a/src/commands/from_json.rs +++ b/src/commands/from_json.rs @@ -45,7 +45,7 @@ pub fn from_json_string_to_value( pub fn from_json(args: CommandArgs) -> Result { let out = args.input; - let span = args.name_span; + let span = args.call_info.name_span; Ok(out .values .map(move |a| match a.item { diff --git a/src/commands/from_toml.rs b/src/commands/from_toml.rs index 1745548eeb..cf650dd99f 100644 --- a/src/commands/from_toml.rs +++ b/src/commands/from_toml.rs @@ -43,7 +43,7 @@ pub fn from_toml_string_to_value( pub fn from_toml(args: CommandArgs) -> Result { let out = args.input; - let span = args.name_span; + let span = args.call_info.name_span; Ok(out .values .map(move |a| match a.item { diff --git a/src/commands/from_xml.rs b/src/commands/from_xml.rs index db56cb830d..cc221df33e 100644 --- a/src/commands/from_xml.rs +++ b/src/commands/from_xml.rs @@ -61,7 +61,7 @@ pub fn from_xml_string_to_value( pub fn from_xml(args: CommandArgs) -> Result { let out = args.input; - let span = args.name_span; + let span = args.call_info.name_span; Ok(out .values .map(move |a| match a.item { diff --git a/src/commands/from_yaml.rs b/src/commands/from_yaml.rs index 12121037bc..475926d4ab 100644 --- a/src/commands/from_yaml.rs +++ b/src/commands/from_yaml.rs @@ -50,7 +50,7 @@ pub fn from_yaml_string_to_value( pub fn from_yaml(args: CommandArgs) -> Result { let out = args.input; - let span = args.name_span; + let span = args.call_info.name_span; Ok(out .values .map(move |a| match a.item { diff --git a/src/commands/get.rs b/src/commands/get.rs index e6d1de26b1..6cdea2e1fb 100644 --- a/src/commands/get.rs +++ b/src/commands/get.rs @@ -26,7 +26,7 @@ pub fn get(args: CommandArgs) -> Result { return Err(ShellError::maybe_labeled_error( "Get requires a field or field path", "needs parameter", - args.name_span, + args.call_info.name_span, )); } diff --git a/src/commands/lines.rs b/src/commands/lines.rs index 12cd0c020e..219f4d39db 100644 --- a/src/commands/lines.rs +++ b/src/commands/lines.rs @@ -7,7 +7,7 @@ use log::trace; pub fn lines(args: CommandArgs) -> Result { let input = args.input; - let span = args.name_span; + let span = args.call_info.name_span; let stream = input .values diff --git a/src/commands/ls.rs b/src/commands/ls.rs index 17843e69e5..72ef4883b9 100644 --- a/src/commands/ls.rs +++ b/src/commands/ls.rs @@ -30,7 +30,7 @@ pub fn ls(args: CommandArgs) -> Result { return Err(ShellError::maybe_labeled_error( e.to_string(), e.to_string(), - args.name_span, + args.call_info.name_span, )); } } @@ -40,7 +40,7 @@ pub fn ls(args: CommandArgs) -> Result { let mut shell_entries = VecDeque::new(); for entry in entries { - let value = dir_entry_dict(&entry?, args.name_span)?; + let value = dir_entry_dict(&entry?, args.call_info.name_span)?; shell_entries.push_back(ReturnSuccess::value(value)) } Ok(shell_entries.to_output_stream()) diff --git a/src/commands/open.rs b/src/commands/open.rs index 0f5f3021a8..60b11a72a5 100644 --- a/src/commands/open.rs +++ b/src/commands/open.rs @@ -10,7 +10,7 @@ use uuid::Uuid; command! { Open as open(args, path: Spanned, --raw: Switch,) { - let span = args.name_span; + let span = args.call_info.name_span; let cwd = args .env @@ -48,7 +48,7 @@ command! { )?) ), - other => stream.push_back(ReturnSuccess::value(other.spanned(span))), + other => stream.push_back(ReturnSuccess::value(other.spanned(contents_span))), }; stream diff --git a/src/commands/pick.rs b/src/commands/pick.rs index 0d53ce9942..b28660c2a1 100644 --- a/src/commands/pick.rs +++ b/src/commands/pick.rs @@ -7,7 +7,7 @@ pub fn pick(args: CommandArgs) -> Result { return Err(ShellError::maybe_labeled_error( "Pick requires fields", "needs parameter", - args.name_span, + args.call_info.name_span, )); } diff --git a/src/commands/plugin.rs b/src/commands/plugin.rs index a27f1944af..62507ed31f 100644 --- a/src/commands/plugin.rs +++ b/src/commands/plugin.rs @@ -84,7 +84,7 @@ pub fn filter_plugin(path: String, args: CommandArgs) -> Result Result Result<(), ShellError> { //use subprocess::Exec; - let request = JsonRpc::new("sink", (args.args, args.input)); + let request = JsonRpc::new("sink", (args.call_info, args.input)); let request_raw = serde_json::to_string(&request).unwrap(); let mut tmpfile = tempfile::NamedTempFile::new()?; let _ = writeln!(tmpfile, "{}", request_raw); diff --git a/src/commands/ps.rs b/src/commands/ps.rs index 14b9ba27fa..2924785a8a 100644 --- a/src/commands/ps.rs +++ b/src/commands/ps.rs @@ -10,7 +10,7 @@ pub fn ps(args: CommandArgs) -> Result { let list = list .into_iter() - .map(|(_, process)| process_dict(process, args.name_span)) + .map(|(_, process)| process_dict(process, args.call_info.name_span)) .collect::>(); Ok(list.from_input_stream()) diff --git a/src/commands/reject.rs b/src/commands/reject.rs index 362df135db..7752076295 100644 --- a/src/commands/reject.rs +++ b/src/commands/reject.rs @@ -3,13 +3,13 @@ use crate::object::base::reject_fields; use crate::prelude::*; pub fn reject(args: CommandArgs) -> Result { - let name_span = args.name_span; + let name_span = args.call_info.name_span; if args.len() == 0 { return Err(ShellError::maybe_labeled_error( "Reject requires fields", "needs parameter", - args.name_span, + args.call_info.name_span, )); } diff --git a/src/commands/rm.rs b/src/commands/rm.rs index 776d27d179..5760a34440 100644 --- a/src/commands/rm.rs +++ b/src/commands/rm.rs @@ -1,7 +1,7 @@ use crate::errors::ShellError; -use crate::prelude::*; -use crate::parser::registry::{CommandConfig, NamedType, PositionalType}; use crate::parser::hir::SyntaxType; +use crate::parser::registry::{CommandConfig, NamedType, PositionalType}; +use crate::prelude::*; use indexmap::IndexMap; pub struct Remove; @@ -31,28 +31,25 @@ impl Command for Remove { } pub fn rm(args: CommandArgs) -> Result { - let mut full_path = args.env - .lock() - .unwrap() - .path() - .to_path_buf(); + let mut full_path = args.env.lock().unwrap().path().to_path_buf(); - - match args.nth(0) - .ok_or_else(|| ShellError::string(&format!("No file or directory specified")))? - .as_string()? - .as_str() { - "." | ".." => return Err(ShellError::string("\".\" and \"..\" may not be removed")), - file => full_path.push(file), + match args + .nth(0) + .ok_or_else(|| ShellError::string(&format!("No file or directory specified")))? + .as_string()? + .as_str() + { + "." | ".." => return Err(ShellError::string("\".\" and \"..\" may not be removed")), + file => full_path.push(file), } - if full_path.is_dir() { if !args.has("recursive") { return Err(ShellError::labeled_error( - "is a directory", - "", - args.name_span.unwrap())); + "is a directory", + "", + args.call_info.name_span.unwrap(), + )); } std::fs::remove_dir_all(&full_path).expect("can not remove directory"); } else if full_path.is_file() { diff --git a/src/commands/save.rs b/src/commands/save.rs index 312e7a2cb0..a9545651ad 100644 --- a/src/commands/save.rs +++ b/src/commands/save.rs @@ -8,15 +8,15 @@ use crate::parser::Spanned; use std::path::{Path, PathBuf}; pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> { - if args.args.positional.is_none() { + if args.call_info.args.positional.is_none() { return Err(ShellError::maybe_labeled_error( "Save requires a filepath", "needs path", - args.name_span, + args.call_info.name_span, )); } - let positional = match args.args.positional { + let positional = match args.call_info.args.positional { None => return Err(ShellError::string("save requires a filepath")), Some(p) => p, }; diff --git a/src/commands/skip_while.rs b/src/commands/skip_while.rs index 605747e694..c0aa0f3b07 100644 --- a/src/commands/skip_while.rs +++ b/src/commands/skip_while.rs @@ -30,7 +30,7 @@ pub fn skip_while(args: CommandArgs) -> Result { return Err(ShellError::maybe_labeled_error( "Where requires a condition", "needs condition", - args.name_span, + args.call_info.name_span, )); } diff --git a/src/commands/split_column.rs b/src/commands/split_column.rs index cf34230376..90c12b8f88 100644 --- a/src/commands/split_column.rs +++ b/src/commands/split_column.rs @@ -5,13 +5,13 @@ use log::trace; pub fn split_column(args: CommandArgs) -> Result { let positional: Vec<_> = args.positional_iter().cloned().collect(); - let span = args.name_span; + let span = args.call_info.name_span; if positional.len() == 0 { return Err(ShellError::maybe_labeled_error( "Split-column needs more information", "needs parameter (eg split-column \",\")", - args.name_span, + args.call_info.name_span, )); } diff --git a/src/commands/split_row.rs b/src/commands/split_row.rs index 06637ff05e..fb530ac8a4 100644 --- a/src/commands/split_row.rs +++ b/src/commands/split_row.rs @@ -6,13 +6,13 @@ use log::trace; pub fn split_row(args: CommandArgs) -> Result { let positional: Vec> = args.positional_iter().cloned().collect(); - let span = args.name_span; + let span = args.call_info.name_span; if positional.len() == 0 { return Err(ShellError::maybe_labeled_error( "Split-row needs more information", "needs parameter (eg split-row \"\\n\")", - args.name_span, + args.call_info.name_span, )); } diff --git a/src/commands/sysinfo.rs b/src/commands/sysinfo.rs index 421980dca6..425505936f 100644 --- a/src/commands/sysinfo.rs +++ b/src/commands/sysinfo.rs @@ -7,10 +7,11 @@ use sys_info::*; use sysinfo::{ComponentExt, DiskExt, NetworkExt, RefreshKind, SystemExt}; pub fn sysinfo(args: CommandArgs) -> Result { - let mut idx = SpannedDictBuilder::new(args.name_span); + let name_span = args.call_info.name_span; + let mut idx = SpannedDictBuilder::new(name_span); if let (Ok(name), Ok(version)) = (os_type(), os_release()) { - let mut os_idx = SpannedDictBuilder::new(args.name_span); + let mut os_idx = SpannedDictBuilder::new(name_span); os_idx.insert("name", Primitive::String(name)); os_idx.insert("version", Primitive::String(version)); @@ -18,7 +19,7 @@ pub fn sysinfo(args: CommandArgs) -> Result { } if let (Ok(num_cpu), Ok(cpu_speed)) = (cpu_num(), cpu_speed()) { - let mut cpu_idx = SpannedDictBuilder::new(args.name_span); + let mut cpu_idx = SpannedDictBuilder::new(name_span); cpu_idx.insert("num", Primitive::Int(num_cpu as i64)); cpu_idx.insert("speed", Primitive::Int(cpu_speed as i64)); @@ -26,7 +27,7 @@ pub fn sysinfo(args: CommandArgs) -> Result { } if let Ok(x) = loadavg() { - let mut load_idx = SpannedDictBuilder::new(args.name_span); + let mut load_idx = SpannedDictBuilder::new(name_span); load_idx.insert("1min", Primitive::Float(OF64::from(x.one))); load_idx.insert("5min", Primitive::Float(OF64::from(x.five))); @@ -36,7 +37,7 @@ pub fn sysinfo(args: CommandArgs) -> Result { } if let Ok(x) = mem_info() { - let mut mem_idx = SpannedDictBuilder::new(args.name_span); + let mut mem_idx = SpannedDictBuilder::new(name_span); mem_idx.insert("total", Primitive::Bytes(x.total as u64 * 1024)); mem_idx.insert("free", Primitive::Bytes(x.free as u64 * 1024)); @@ -70,7 +71,7 @@ pub fn sysinfo(args: CommandArgs) -> Result { #[cfg(not(windows))] { if let Ok(x) = boottime() { - let mut boottime_idx = SpannedDictBuilder::new(args.name_span); + let mut boottime_idx = SpannedDictBuilder::new(name_span); boottime_idx.insert("days", Primitive::Int(x.tv_sec / (24 * 3600))); boottime_idx.insert("hours", Primitive::Int((x.tv_sec / 3600) % 24)); boottime_idx.insert("mins", Primitive::Int((x.tv_sec / 60) % 60)); @@ -84,7 +85,7 @@ pub fn sysinfo(args: CommandArgs) -> Result { if components_list.len() > 0 { let mut v: Vec> = vec![]; for component in components_list { - let mut component_idx = SpannedDictBuilder::new(args.name_span); + let mut component_idx = SpannedDictBuilder::new(name_span); component_idx.insert("name", Primitive::String(component.get_label().to_string())); component_idx.insert( "temp", @@ -107,7 +108,7 @@ pub fn sysinfo(args: CommandArgs) -> Result { let mut v = vec![]; for disk in disks { - let mut disk_idx = SpannedDictBuilder::new(args.name_span); + let mut disk_idx = SpannedDictBuilder::new(name_span); disk_idx.insert("name", Value::string(disk.get_name().to_string_lossy())); disk_idx.insert("available", Value::bytes(disk.get_available_space())); disk_idx.insert("total", Value::bytes(disk.get_total_space())); @@ -121,7 +122,7 @@ pub fn sysinfo(args: CommandArgs) -> Result { let incoming = network.get_income(); let outgoing = network.get_outcome(); - let mut network_idx = SpannedDictBuilder::new(args.name_span); + let mut network_idx = SpannedDictBuilder::new(name_span); network_idx.insert("incoming", Value::bytes(incoming)); network_idx.insert("outgoing", Value::bytes(outgoing)); idx.insert_spanned("network", network_idx); diff --git a/src/commands/to_json.rs b/src/commands/to_json.rs index c6ace91032..5cd4c913ce 100644 --- a/src/commands/to_json.rs +++ b/src/commands/to_json.rs @@ -42,7 +42,7 @@ pub fn value_to_json_value(v: &Value) -> serde_json::Value { pub fn to_json(args: CommandArgs) -> Result { let out = args.input; - let name_span = args.name_span; + let name_span = args.call_info.name_span; Ok(out .values .map( diff --git a/src/commands/to_toml.rs b/src/commands/to_toml.rs index 6ffbe6ba38..354976a87c 100644 --- a/src/commands/to_toml.rs +++ b/src/commands/to_toml.rs @@ -32,7 +32,7 @@ pub fn value_to_toml_value(v: &Value) -> toml::Value { pub fn to_toml(args: CommandArgs) -> Result { let out = args.input; - let name_span = args.name_span; + let name_span = args.call_info.name_span; Ok(out .values diff --git a/src/commands/to_yaml.rs b/src/commands/to_yaml.rs index 1a64898bac..66db5afa40 100644 --- a/src/commands/to_yaml.rs +++ b/src/commands/to_yaml.rs @@ -40,7 +40,7 @@ pub fn value_to_yaml_value(v: &Value) -> serde_yaml::Value { pub fn to_yaml(args: CommandArgs) -> Result { let out = args.input; - let name_span = args.name_span; + let name_span = args.call_info.name_span; Ok(out .values .map( diff --git a/src/context.rs b/src/context.rs index 94d15aab56..9be7463a0f 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,4 +1,4 @@ -use crate::commands::command::{Sink, SinkCommandArgs}; +use crate::commands::command::{CallInfo, Sink, SinkCommandArgs}; use crate::parser::{ registry::{Args, CommandConfig, CommandRegistry}, Span, @@ -88,9 +88,11 @@ impl Context { ) -> Result<(), ShellError> { let command_args = SinkCommandArgs { ctx: self.clone(), - name_span, - source_map: self.source_map.clone(), - args, + call_info: CallInfo { + name_span, + source_map: self.source_map.clone(), + args, + }, input, }; @@ -120,9 +122,11 @@ impl Context { let command_args = CommandArgs { host: self.host.clone(), env: self.env.clone(), - name_span, - source_map, - args, + call_info: CallInfo { + name_span, + source_map, + args, + }, input, }; diff --git a/src/lib.rs b/src/lib.rs index 13a48915ce..f5f7f90f79 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -24,7 +24,8 @@ mod plugin; mod shell; mod stream; -pub use crate::commands::command::{ReturnSuccess, ReturnValue}; +pub use crate::commands::command::{CallInfo, ReturnSuccess, ReturnValue}; +pub use crate::context::SpanSource; pub use crate::env::host::BasicHost; pub use crate::parser::parse::span::SpannedItem; pub use crate::parser::Spanned; diff --git a/src/plugin.rs b/src/plugin.rs index 4126b9d08f..fdc6c8a6c0 100644 --- a/src/plugin.rs +++ b/src/plugin.rs @@ -1,11 +1,11 @@ -use crate::{Args, CommandConfig, ReturnValue, ShellError, Spanned, Value}; +use crate::{CallInfo, CommandConfig, ReturnValue, ShellError, Spanned, Value}; use serde::{Deserialize, Serialize}; use std::io; pub trait Plugin { fn config(&mut self) -> Result; #[allow(unused)] - fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> { + fn begin_filter(&mut self, call_info: CallInfo) -> Result<(), ShellError> { Err(ShellError::string( "`begin_filter` not implemented in plugin", )) @@ -15,7 +15,7 @@ pub trait Plugin { Err(ShellError::string("`filter` not implemented in plugin")) } #[allow(unused)] - fn sink(&mut self, args: Args, input: Vec>) {} + fn sink(&mut self, call_info: CallInfo, input: Vec>) {} fn quit(&mut self) { return; @@ -134,8 +134,14 @@ fn send_response(result: T) { #[allow(non_camel_case_types)] pub enum NuCommand { config, - begin_filter { params: Args }, - filter { params: Spanned }, - sink { params: (Args, Vec>) }, + begin_filter { + params: CallInfo, + }, + filter { + params: Spanned, + }, + sink { + params: (CallInfo, Vec>), + }, quit, } diff --git a/src/plugins/binaryview.rs b/src/plugins/binaryview.rs index 8c525f3886..b71a8a88a0 100644 --- a/src/plugins/binaryview.rs +++ b/src/plugins/binaryview.rs @@ -1,6 +1,10 @@ +#![feature(option_flattening)] use crossterm::{cursor, terminal, Attribute, RawScreen}; use indexmap::IndexMap; -use nu::{serve_plugin, Args, CommandConfig, NamedType, Plugin, ShellError, Spanned, Value}; +use nu::{ + serve_plugin, CallInfo, CommandConfig, NamedType, Plugin, ShellError, SpanSource, Spanned, + Value, +}; use pretty_hex::*; struct BinaryView; @@ -25,14 +29,15 @@ impl Plugin for BinaryView { }) } - fn sink(&mut self, args: Args, input: Vec>) { + fn sink(&mut self, call_info: CallInfo, input: Vec>) { for v in input { match v { Spanned { item: Value::Binary(b), - .. + span, } => { - let _ = view_binary(&b, args.has("lores")); + let source = span.source.map(|x| call_info.source_map.get(&x)).flatten(); + let _ = view_binary(&b, source, call_info.args.has("lores")); } _ => {} } @@ -40,17 +45,21 @@ impl Plugin for BinaryView { } } -fn view_binary(b: &[u8], lores_mode: bool) -> Result<(), Box> { +fn view_binary( + b: &[u8], + source: Option<&SpanSource>, + lores_mode: bool, +) -> Result<(), Box> { if b.len() > 3 { match (b[0], b[1], b[2]) { (0x4e, 0x45, 0x53) => { - view_contents_interactive(b, lores_mode)?; + view_contents_interactive(b, source, lores_mode)?; return Ok(()); } _ => {} } } - view_contents(b, lores_mode)?; + view_contents(b, source, lores_mode)?; Ok(()) } @@ -247,7 +256,11 @@ fn load_from_jpg_buffer(buffer: &[u8]) -> Option<(RawImageBuffer)> { }) } -pub fn view_contents(buffer: &[u8], lores_mode: bool) -> Result<(), Box> { +pub fn view_contents( + buffer: &[u8], + _source: Option<&SpanSource>, + lores_mode: bool, +) -> Result<(), Box> { let mut raw_image_buffer = load_from_png_buffer(buffer); if raw_image_buffer.is_none() { @@ -332,14 +345,29 @@ pub fn view_contents(buffer: &[u8], lores_mode: bool) -> Result<(), Box, lores_mode: bool, ) -> Result<(), Box> { use rawkey::{KeyCode, RawKey}; + let sav_path = if let Some(SpanSource::File(f)) = source { + let mut path = std::path::PathBuf::from(f); + path.set_extension("sav"); + Some(path) + } else { + None + }; + let mut nes = neso::Nes::new(48000.0); let rawkey = RawKey::new(); nes.load_rom(&buffer); + if let Some(ref sav_path) = sav_path { + if let Ok(contents) = std::fs::read(sav_path) { + let _ = nes.load_state(&contents); + } + } + nes.reset(); if let Ok(_raw) = RawScreen::into_raw_mode() { @@ -403,6 +431,13 @@ pub fn view_contents_interactive( } } + if let Some(ref sav_path) = sav_path { + let buffer = nes.save_state(); + if let Ok(buffer) = buffer { + let _ = std::fs::write(sav_path, buffer); + } + } + let cursor = cursor(); let _ = cursor.show(); diff --git a/src/plugins/inc.rs b/src/plugins/inc.rs index 8d69f91d5d..f03edc985f 100644 --- a/src/plugins/inc.rs +++ b/src/plugins/inc.rs @@ -1,7 +1,7 @@ use indexmap::IndexMap; use nu::{ - serve_plugin, Args, CommandConfig, NamedType, Plugin, PositionalType, Primitive, ReturnSuccess, - ReturnValue, ShellError, Spanned, SpannedItem, Value, + serve_plugin, CallInfo, CommandConfig, NamedType, Plugin, PositionalType, Primitive, + ReturnSuccess, ReturnValue, ShellError, Spanned, SpannedItem, Value, }; struct Inc { @@ -99,18 +99,18 @@ impl Plugin for Inc { rest_positional: true, }) } - fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> { - if args.has("major") { + fn begin_filter(&mut self, call_info: CallInfo) -> Result<(), ShellError> { + if call_info.args.has("major") { self.major = true; } - if args.has("minor") { + if call_info.args.has("minor") { self.minor = true; } - if args.has("patch") { + if call_info.args.has("patch") { self.patch = true; } - if let Some(args) = args.positional { + if let Some(args) = call_info.args.positional { for arg in args { match arg { Spanned { diff --git a/src/plugins/skip.rs b/src/plugins/skip.rs index 0a1fdf7a9f..e7a4f6003a 100644 --- a/src/plugins/skip.rs +++ b/src/plugins/skip.rs @@ -1,7 +1,7 @@ use indexmap::IndexMap; use nu::{ - serve_plugin, Args, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, - Spanned, Value, + serve_plugin, CallInfo, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue, + ShellError, Spanned, Value, }; struct NewSkip { @@ -24,8 +24,8 @@ impl Plugin for NewSkip { rest_positional: true, }) } - fn begin_filter(&mut self, args: Args) -> Result<(), ShellError> { - if let Some(args) = args.positional { + fn begin_filter(&mut self, call_info: CallInfo) -> Result<(), ShellError> { + if let Some(args) = call_info.args.positional { for arg in args { match arg { Spanned { @@ -34,7 +34,13 @@ impl Plugin for NewSkip { } => { self.skip_amount = i; } - _ => return Err(ShellError::labeled_error("Unrecognized type in params", "expected an integer", arg.span)), + _ => { + return Err(ShellError::labeled_error( + "Unrecognized type in params", + "expected an integer", + arg.span, + )) + } } } } diff --git a/src/plugins/tree.rs b/src/plugins/tree.rs index cfaf269909..b2bc9e1ca5 100644 --- a/src/plugins/tree.rs +++ b/src/plugins/tree.rs @@ -1,6 +1,6 @@ use derive_new::new; use indexmap::IndexMap; -use nu::{serve_plugin, Args, CommandConfig, Plugin, ShellError, Spanned, Value}; +use nu::{serve_plugin, CallInfo, CommandConfig, Plugin, ShellError, Spanned, Value}; use ptree::item::StringItem; use ptree::output::print_tree_with; use ptree::print_config::PrintConfig; @@ -91,7 +91,7 @@ impl Plugin for TreeViewer { }) } - fn sink(&mut self, _args: Args, input: Vec>) { + fn sink(&mut self, _call_info: CallInfo, input: Vec>) { if input.len() > 0 { for i in input.iter() { let view = TreeView::from_value(&i);