WIP
This commit is contained in:
commit
52ea14cb25
35
src/cli.rs
35
src/cli.rs
|
@ -161,7 +161,10 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||||
command("from-xml", Box::new(from_xml::from_xml)),
|
command("from-xml", Box::new(from_xml::from_xml)),
|
||||||
command("from-yaml", Box::new(from_yaml::from_yaml)),
|
command("from-yaml", Box::new(from_yaml::from_yaml)),
|
||||||
command("get", Box::new(get::get)),
|
command("get", Box::new(get::get)),
|
||||||
|
command("enter", Box::new(enter::enter)),
|
||||||
command("exit", Box::new(exit::exit)),
|
command("exit", Box::new(exit::exit)),
|
||||||
|
command("next", Box::new(next::next)),
|
||||||
|
command("prev", Box::new(prev::prev)),
|
||||||
command("lines", Box::new(lines::lines)),
|
command("lines", Box::new(lines::lines)),
|
||||||
command("pick", Box::new(pick::pick)),
|
command("pick", Box::new(pick::pick)),
|
||||||
command("split-column", Box::new(split_column::split_column)),
|
command("split-column", Box::new(split_column::split_column)),
|
||||||
|
@ -196,15 +199,15 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||||
let _ = load_plugins(&mut context);
|
let _ = 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());
|
||||||
let mut rl: Editor<crate::shell::Helper> = Editor::with_config(config);
|
let mut rl: Editor<_> = Editor::with_config(config);
|
||||||
|
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
{
|
{
|
||||||
let _ = ansi_term::enable_ansi_support();
|
let _ = ansi_term::enable_ansi_support();
|
||||||
}
|
}
|
||||||
|
|
||||||
rl.set_helper(Some(h));
|
//rl.set_helper(Some(h));
|
||||||
let _ = rl.load_history("history.txt");
|
let _ = rl.load_history("history.txt");
|
||||||
|
|
||||||
let ctrl_c = Arc::new(AtomicBool::new(false));
|
let ctrl_c = Arc::new(AtomicBool::new(false));
|
||||||
|
@ -221,9 +224,19 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let cwd = {
|
let cwd = {
|
||||||
let env = context.env.lock().unwrap();
|
context
|
||||||
env.path().display().to_string()
|
.env
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.path()
|
||||||
|
.display()
|
||||||
|
.to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
rl.set_helper(Some(crate::shell::Helper::new(context.env.clone())));
|
||||||
|
|
||||||
let readline = rl.readline(&format!(
|
let readline = rl.readline(&format!(
|
||||||
"{}{}> ",
|
"{}{}> ",
|
||||||
cwd,
|
cwd,
|
||||||
|
@ -348,7 +361,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
||||||
Some(ClassifiedCommand::External(_)) => {}
|
Some(ClassifiedCommand::External(_)) => {}
|
||||||
_ => pipeline.commands.push(ClassifiedCommand::Sink(SinkCommand {
|
_ => pipeline.commands.push(ClassifiedCommand::Sink(SinkCommand {
|
||||||
command: sink("autoview", Box::new(autoview::autoview)),
|
command: sink("autoview", Box::new(autoview::autoview)),
|
||||||
name_span: None,
|
name_span: Span::unknown(),
|
||||||
args: registry::Args {
|
args: registry::Args {
|
||||||
positional: None,
|
positional: None,
|
||||||
named: None,
|
named: None,
|
||||||
|
@ -382,7 +395,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
||||||
}
|
}
|
||||||
|
|
||||||
(Some(ClassifiedCommand::Sink(SinkCommand { name_span, .. })), Some(_)) => {
|
(Some(ClassifiedCommand::Sink(SinkCommand { name_span, .. })), Some(_)) => {
|
||||||
return LineResult::Error(line.clone(), ShellError::maybe_labeled_error("Commands like table, save, and autoview must come last in the pipeline", "must come last", name_span));
|
return LineResult::Error(line.clone(), ShellError::labeled_error("Commands like table, save, and autoview must come last in the pipeline", "must come last", name_span));
|
||||||
}
|
}
|
||||||
|
|
||||||
(Some(ClassifiedCommand::Sink(left)), None) => {
|
(Some(ClassifiedCommand::Sink(left)), None) => {
|
||||||
|
@ -496,7 +509,7 @@ fn classify_command(
|
||||||
|
|
||||||
Ok(ClassifiedCommand::Internal(InternalCommand {
|
Ok(ClassifiedCommand::Internal(InternalCommand {
|
||||||
command,
|
command,
|
||||||
name_span: Some(head.span().clone()),
|
name_span: head.span().clone(),
|
||||||
args,
|
args,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -510,7 +523,7 @@ fn classify_command(
|
||||||
|
|
||||||
Ok(ClassifiedCommand::Sink(SinkCommand {
|
Ok(ClassifiedCommand::Sink(SinkCommand {
|
||||||
command,
|
command,
|
||||||
name_span: Some(head.span().clone()),
|
name_span: head.span().clone(),
|
||||||
args,
|
args,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -521,7 +534,7 @@ fn classify_command(
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|i| match i {
|
.filter_map(|i| match i {
|
||||||
TokenNode::Whitespace(_) => None,
|
TokenNode::Whitespace(_) => None,
|
||||||
other => Some(Tagged::from_item(
|
other => Some(Tagged::from_simple_spanned_item(
|
||||||
other.as_external_arg(source),
|
other.as_external_arg(source),
|
||||||
other.span(),
|
other.span(),
|
||||||
)),
|
)),
|
||||||
|
@ -532,7 +545,7 @@ fn classify_command(
|
||||||
|
|
||||||
Ok(ClassifiedCommand::External(ExternalCommand {
|
Ok(ClassifiedCommand::External(ExternalCommand {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
name_span: Some(head.span().clone()),
|
name_span: head.span().clone(),
|
||||||
args: arg_list_strings,
|
args: arg_list_strings,
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ crate mod command;
|
||||||
crate mod config;
|
crate mod config;
|
||||||
crate mod cp;
|
crate mod cp;
|
||||||
crate mod date;
|
crate mod date;
|
||||||
|
crate mod enter;
|
||||||
crate mod exit;
|
crate mod exit;
|
||||||
crate mod first;
|
crate mod first;
|
||||||
crate mod from_csv;
|
crate mod from_csv;
|
||||||
|
@ -21,9 +22,11 @@ crate mod from_yaml;
|
||||||
crate mod get;
|
crate mod get;
|
||||||
crate mod lines;
|
crate mod lines;
|
||||||
crate mod ls;
|
crate mod ls;
|
||||||
|
crate mod next;
|
||||||
crate mod open;
|
crate mod open;
|
||||||
crate mod pick;
|
crate mod pick;
|
||||||
crate mod plugin;
|
crate mod plugin;
|
||||||
|
crate mod prev;
|
||||||
crate mod ps;
|
crate mod ps;
|
||||||
crate mod reject;
|
crate mod reject;
|
||||||
crate mod rm;
|
crate mod rm;
|
||||||
|
|
|
@ -5,5 +5,5 @@ use crate::shell::shell::Shell;
|
||||||
pub fn cd(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn cd(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let env = args.env.lock().unwrap();
|
let env = args.env.lock().unwrap();
|
||||||
|
|
||||||
env.cd(args.call_info, args.input)
|
env.last().unwrap().cd(args.call_info, args.input)
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,7 +99,7 @@ impl ClassifiedCommand {
|
||||||
|
|
||||||
crate struct SinkCommand {
|
crate struct SinkCommand {
|
||||||
crate command: Arc<dyn Sink>,
|
crate command: Arc<dyn Sink>,
|
||||||
crate name_span: Option<Span>,
|
crate name_span: Span,
|
||||||
crate args: Args,
|
crate args: Args,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ impl SinkCommand {
|
||||||
|
|
||||||
crate struct InternalCommand {
|
crate struct InternalCommand {
|
||||||
crate command: Arc<dyn Command>,
|
crate command: Arc<dyn Command>,
|
||||||
crate name_span: Option<Span>,
|
crate name_span: Span,
|
||||||
crate args: Args,
|
crate args: Args,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -145,12 +145,35 @@ impl InternalCommand {
|
||||||
match item? {
|
match item? {
|
||||||
ReturnSuccess::Action(action) => match action {
|
ReturnSuccess::Action(action) => match action {
|
||||||
CommandAction::ChangePath(path) => {
|
CommandAction::ChangePath(path) => {
|
||||||
context.env.lock().unwrap().path = path;
|
let result = context
|
||||||
|
.env
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.last_mut()
|
||||||
|
.unwrap()
|
||||||
|
.set_path(path);
|
||||||
}
|
}
|
||||||
CommandAction::AddSpanSource(uuid, span_source) => {
|
CommandAction::AddSpanSource(uuid, span_source) => {
|
||||||
context.add_span_source(uuid, span_source);
|
context.add_span_source(uuid, span_source);
|
||||||
}
|
}
|
||||||
CommandAction::Exit => std::process::exit(0),
|
CommandAction::Exit => std::process::exit(0),
|
||||||
|
CommandAction::Enter(location) => {
|
||||||
|
context
|
||||||
|
.env
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.push(Box::new(Environment::with_location(location)?));
|
||||||
|
}
|
||||||
|
CommandAction::PreviousShell => {
|
||||||
|
let mut x = context.env.lock().unwrap();
|
||||||
|
let shell = x.pop().unwrap();
|
||||||
|
x.insert(0, shell);
|
||||||
|
}
|
||||||
|
CommandAction::NextShell => {
|
||||||
|
let mut x = context.env.lock().unwrap();
|
||||||
|
let shell = x.remove(0);
|
||||||
|
x.push(shell);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
ReturnSuccess::Value(v) => {
|
ReturnSuccess::Value(v) => {
|
||||||
|
@ -166,7 +189,7 @@ impl InternalCommand {
|
||||||
crate struct ExternalCommand {
|
crate struct ExternalCommand {
|
||||||
crate name: String,
|
crate name: String,
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
crate name_span: Option<Span>,
|
crate name_span: Span,
|
||||||
crate args: Vec<Tagged<String>>,
|
crate args: Vec<Tagged<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,7 +263,10 @@ impl ExternalCommand {
|
||||||
} else {
|
} else {
|
||||||
for arg in &self.args {
|
for arg in &self.args {
|
||||||
let arg_chars: Vec<_> = arg.chars().collect();
|
let arg_chars: Vec<_> = arg.chars().collect();
|
||||||
if arg_chars.len() > 1 && arg_chars[0] == '"' && arg_chars[arg_chars.len() - 1] == '"' {
|
if arg_chars.len() > 1
|
||||||
|
&& arg_chars[0] == '"'
|
||||||
|
&& arg_chars[arg_chars.len() - 1] == '"'
|
||||||
|
{
|
||||||
// quoted string
|
// quoted string
|
||||||
let new_arg: String = arg_chars[1..arg_chars.len() - 1].iter().collect();
|
let new_arg: String = arg_chars[1..arg_chars.len() - 1].iter().collect();
|
||||||
process = process.arg(new_arg);
|
process = process.arg(new_arg);
|
||||||
|
@ -258,13 +284,13 @@ impl ExternalCommand {
|
||||||
let mut first = true;
|
let mut first = true;
|
||||||
for i in &inputs {
|
for i in &inputs {
|
||||||
if i.as_string().is_err() {
|
if i.as_string().is_err() {
|
||||||
let mut span = None;
|
let mut span = name_span;
|
||||||
for arg in &self.args {
|
for arg in &self.args {
|
||||||
if arg.item.contains("$it") {
|
if arg.item.contains("$it") {
|
||||||
span = Some(arg.span());
|
span = arg.span();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"External $it needs string data",
|
"External $it needs string data",
|
||||||
"given object instead of string data",
|
"given object instead of string data",
|
||||||
span,
|
span,
|
||||||
|
@ -295,7 +321,7 @@ impl ExternalCommand {
|
||||||
|
|
||||||
process = Exec::shell(new_arg_string);
|
process = Exec::shell(new_arg_string);
|
||||||
}
|
}
|
||||||
process = process.cwd(context.env.lock().unwrap().path());
|
process = process.cwd(context.env.lock().unwrap().last().unwrap().path());
|
||||||
|
|
||||||
let mut process = match stream_next {
|
let mut process = match stream_next {
|
||||||
StreamNext::Last => process,
|
StreamNext::Last => process,
|
||||||
|
@ -323,7 +349,9 @@ impl ExternalCommand {
|
||||||
let stdout = popen.stdout.take().unwrap();
|
let stdout = popen.stdout.take().unwrap();
|
||||||
let file = futures::io::AllowStdIo::new(stdout);
|
let file = futures::io::AllowStdIo::new(stdout);
|
||||||
let stream = Framed::new(file, LinesCodec {});
|
let stream = Framed::new(file, LinesCodec {});
|
||||||
let stream = stream.map(move |line| Value::string(line.unwrap()).tagged(name_span));
|
let stream = stream.map(move |line| {
|
||||||
|
Tagged::from_simple_spanned_item(Value::string(line.unwrap()), name_span)
|
||||||
|
});
|
||||||
Ok(ClassifiedInputStream::from_input_stream(
|
Ok(ClassifiedInputStream::from_input_stream(
|
||||||
stream.boxed() as BoxStream<'static, Tagged<Value>>
|
stream.boxed() as BoxStream<'static, Tagged<Value>>
|
||||||
))
|
))
|
||||||
|
|
|
@ -4,6 +4,7 @@ use crate::errors::ShellError;
|
||||||
use crate::object::Value;
|
use crate::object::Value;
|
||||||
use crate::parser::registry::{self, Args};
|
use crate::parser::registry::{self, Args};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::shell::shell::Shell;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
@ -13,14 +14,14 @@ use uuid::Uuid;
|
||||||
pub struct CallInfo {
|
pub struct CallInfo {
|
||||||
pub args: Args,
|
pub args: Args,
|
||||||
pub source_map: SourceMap,
|
pub source_map: SourceMap,
|
||||||
pub name_span: Option<Span>,
|
pub name_span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Getters)]
|
#[derive(Getters)]
|
||||||
#[get = "crate"]
|
#[get = "crate"]
|
||||||
pub struct CommandArgs {
|
pub struct CommandArgs {
|
||||||
pub host: Arc<Mutex<dyn Host + Send>>,
|
pub host: Arc<Mutex<dyn Host + Send>>,
|
||||||
pub env: Arc<Mutex<Environment>>,
|
pub env: Arc<Mutex<Vec<Box<dyn Shell>>>>,
|
||||||
pub call_info: CallInfo,
|
pub call_info: CallInfo,
|
||||||
pub input: InputStream,
|
pub input: InputStream,
|
||||||
}
|
}
|
||||||
|
@ -63,6 +64,9 @@ pub enum CommandAction {
|
||||||
ChangePath(PathBuf),
|
ChangePath(PathBuf),
|
||||||
AddSpanSource(Uuid, SpanSource),
|
AddSpanSource(Uuid, SpanSource),
|
||||||
Exit,
|
Exit,
|
||||||
|
Enter(String),
|
||||||
|
PreviousShell,
|
||||||
|
NextShell,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
|
@ -93,7 +97,9 @@ impl ReturnSuccess {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_value(input: Value, span: Span) -> ReturnValue {
|
pub fn spanned_value(input: Value, span: Span) -> ReturnValue {
|
||||||
Ok(ReturnSuccess::Value(Tagged::from_item(input, span)))
|
Ok(ReturnSuccess::Value(Tagged::from_simple_spanned_item(
|
||||||
|
input, span,
|
||||||
|
)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,10 +61,11 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
|
||||||
config::write_config(&result)?;
|
config::write_config(&result)?;
|
||||||
|
|
||||||
return Ok(
|
return Ok(stream![Tagged::from_simple_spanned_item(
|
||||||
stream![Tagged::from_item(Value::Object(result.into()), v.span())]
|
Value::Object(result.into()),
|
||||||
.from_input_stream(),
|
v.span()
|
||||||
);
|
)]
|
||||||
|
.from_input_stream());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,9 +74,11 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
|
||||||
config::write_config(&result)?;
|
config::write_config(&result)?;
|
||||||
|
|
||||||
return Ok(
|
return Ok(stream![Tagged::from_simple_spanned_item(
|
||||||
stream![Tagged::from_item(Value::Object(result.into()), c.span())].from_input_stream(),
|
Value::Object(result.into()),
|
||||||
);
|
c.span()
|
||||||
|
)]
|
||||||
|
.from_input_stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(v) = args.get("remove") {
|
if let Some(v) = args.get("remove") {
|
||||||
|
@ -90,12 +93,14 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
)));
|
)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let obj = VecDeque::from_iter(vec![Value::Object(result.into()).tagged(v)]);
|
let obj = VecDeque::from_iter(vec![Value::Object(result.into()).simple_spanned(v)]);
|
||||||
return Ok(obj.from_input_stream());
|
return Ok(obj.from_input_stream());
|
||||||
}
|
}
|
||||||
|
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Ok(vec![Value::Object(result.into()).tagged(args.call_info.name_span)].into());
|
return Ok(
|
||||||
|
vec![Value::Object(result.into()).simple_spanned(args.call_info.name_span)].into(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(ShellError::string(format!("Unimplemented")))
|
Err(ShellError::string(format!("Unimplemented")))
|
||||||
|
|
|
@ -32,8 +32,22 @@ impl Command for Copycp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn cp(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn cp(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let mut source = args.env.lock().unwrap().path().to_path_buf();
|
let mut source = args
|
||||||
let mut destination = args.env.lock().unwrap().path().to_path_buf();
|
.env
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.path()
|
||||||
|
.to_path_buf();
|
||||||
|
let mut destination = args
|
||||||
|
.env
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.path()
|
||||||
|
.to_path_buf();
|
||||||
|
|
||||||
let mut dst = String::new();
|
let mut dst = String::new();
|
||||||
|
|
||||||
|
|
|
@ -42,41 +42,41 @@ where
|
||||||
|
|
||||||
indexmap.insert(
|
indexmap.insert(
|
||||||
"year".to_string(),
|
"year".to_string(),
|
||||||
Tagged::from_item(Value::int(dt.year()), span),
|
Tagged::from_simple_spanned_item(Value::int(dt.year()), span),
|
||||||
);
|
);
|
||||||
indexmap.insert(
|
indexmap.insert(
|
||||||
"month".to_string(),
|
"month".to_string(),
|
||||||
Tagged::from_item(Value::int(dt.month()), span),
|
Tagged::from_simple_spanned_item(Value::int(dt.month()), span),
|
||||||
);
|
);
|
||||||
indexmap.insert(
|
indexmap.insert(
|
||||||
"day".to_string(),
|
"day".to_string(),
|
||||||
Tagged::from_item(Value::int(dt.day()), span),
|
Tagged::from_simple_spanned_item(Value::int(dt.day()), span),
|
||||||
);
|
);
|
||||||
indexmap.insert(
|
indexmap.insert(
|
||||||
"hour".to_string(),
|
"hour".to_string(),
|
||||||
Tagged::from_item(Value::int(dt.hour()), span),
|
Tagged::from_simple_spanned_item(Value::int(dt.hour()), span),
|
||||||
);
|
);
|
||||||
indexmap.insert(
|
indexmap.insert(
|
||||||
"minute".to_string(),
|
"minute".to_string(),
|
||||||
Tagged::from_item(Value::int(dt.minute()), span),
|
Tagged::from_simple_spanned_item(Value::int(dt.minute()), span),
|
||||||
);
|
);
|
||||||
indexmap.insert(
|
indexmap.insert(
|
||||||
"second".to_string(),
|
"second".to_string(),
|
||||||
Tagged::from_item(Value::int(dt.second()), span),
|
Tagged::from_simple_spanned_item(Value::int(dt.second()), span),
|
||||||
);
|
);
|
||||||
|
|
||||||
let tz = dt.offset();
|
let tz = dt.offset();
|
||||||
indexmap.insert(
|
indexmap.insert(
|
||||||
"timezone".to_string(),
|
"timezone".to_string(),
|
||||||
Tagged::from_item(Value::string(format!("{}", tz)), span),
|
Tagged::from_simple_spanned_item(Value::string(format!("{}", tz)), span),
|
||||||
);
|
);
|
||||||
|
|
||||||
Tagged::from_item(Value::Object(Dictionary::from(indexmap)), span)
|
Tagged::from_simple_spanned_item(Value::Object(Dictionary::from(indexmap)), span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn date(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn date(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let mut date_out = VecDeque::new();
|
let mut date_out = VecDeque::new();
|
||||||
let span = args.call_info.name_span.unwrap();
|
let span = args.call_info.name_span;
|
||||||
|
|
||||||
let value = if args.has("utc") {
|
let value = if args.has("utc") {
|
||||||
let utc: DateTime<Utc> = Utc::now();
|
let utc: DateTime<Utc> = Utc::now();
|
||||||
|
|
17
src/commands/enter.rs
Normal file
17
src/commands/enter.rs
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
use crate::commands::command::CommandAction;
|
||||||
|
use crate::errors::ShellError;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub fn enter(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
if args.len() == 0 {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
|
"First requires an amount",
|
||||||
|
"needs parameter",
|
||||||
|
args.call_info.name_span,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let location = args.expect_nth(0)?.as_string()?;
|
||||||
|
|
||||||
|
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::Enter(location)))].into())
|
||||||
|
}
|
|
@ -5,7 +5,7 @@ use crate::prelude::*;
|
||||||
|
|
||||||
pub fn first(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn first(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"First requires an amount",
|
"First requires an amount",
|
||||||
"needs parameter",
|
"needs parameter",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
|
|
@ -4,12 +4,12 @@ use csv::ReaderBuilder;
|
||||||
|
|
||||||
pub fn from_csv_string_to_value(
|
pub fn from_csv_string_to_value(
|
||||||
s: String,
|
s: String,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
|
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
|
||||||
let mut reader = ReaderBuilder::new()
|
let mut reader = ReaderBuilder::new()
|
||||||
.has_headers(false)
|
.has_headers(false)
|
||||||
.from_reader(s.as_bytes());
|
.from_reader(s.as_bytes());
|
||||||
let span = span.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
let mut fields: VecDeque<String> = VecDeque::new();
|
let mut fields: VecDeque<String> = VecDeque::new();
|
||||||
let mut iter = reader.records();
|
let mut iter = reader.records();
|
||||||
|
@ -27,12 +27,12 @@ pub fn from_csv_string_to_value(
|
||||||
if let Some(row_values) = iter.next() {
|
if let Some(row_values) = iter.next() {
|
||||||
let row_values = row_values?;
|
let row_values = row_values?;
|
||||||
|
|
||||||
let mut row = TaggedDictBuilder::new(span);
|
let mut row = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
for (idx, entry) in row_values.iter().enumerate() {
|
for (idx, entry) in row_values.iter().enumerate() {
|
||||||
row.insert_tagged(
|
row.insert_tagged(
|
||||||
fields.get(idx).unwrap(),
|
fields.get(idx).unwrap(),
|
||||||
Value::Primitive(Primitive::String(String::from(entry))).tagged(span),
|
Value::Primitive(Primitive::String(String::from(entry))).tagged(tag),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ pub fn from_csv_string_to_value(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Tagged::from_item(Value::List(rows), span))
|
Ok(Tagged::from_item(Value::List(rows), tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@ -52,22 +52,26 @@ pub fn from_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| {
|
.map(move |a| {
|
||||||
let value_span = a.span();
|
let value_tag = a.tag();
|
||||||
match a.item {
|
match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => {
|
Value::Primitive(Primitive::String(s)) => {
|
||||||
match from_csv_string_to_value(s, value_span) {
|
match from_csv_string_to_value(s, value_tag) {
|
||||||
Ok(x) => ReturnSuccess::value(x),
|
Ok(x) => ReturnSuccess::value(x),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as CSV",
|
"Could not parse as CSV",
|
||||||
"piped data failed CSV parse",
|
"input cannot be parsed as CSV",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
value_tag.span,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::maybe_labeled_error(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected string values from pipeline",
|
"Expected a string from pipeline",
|
||||||
"expects strings from pipeline",
|
"requires string input",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
a.span(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,9 +4,9 @@ use std::collections::HashMap;
|
||||||
|
|
||||||
fn convert_ini_second_to_nu_value(
|
fn convert_ini_second_to_nu_value(
|
||||||
v: &HashMap<String, String>,
|
v: &HashMap<String, String>,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> Tagged<Value> {
|
) -> Tagged<Value> {
|
||||||
let mut second = TaggedDictBuilder::new(span);
|
let mut second = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
for (key, value) in v.into_iter() {
|
for (key, value) in v.into_iter() {
|
||||||
second.insert(key.clone(), Primitive::String(value.clone()));
|
second.insert(key.clone(), Primitive::String(value.clone()));
|
||||||
|
@ -17,13 +17,13 @@ fn convert_ini_second_to_nu_value(
|
||||||
|
|
||||||
fn convert_ini_top_to_nu_value(
|
fn convert_ini_top_to_nu_value(
|
||||||
v: &HashMap<String, HashMap<String, String>>,
|
v: &HashMap<String, HashMap<String, String>>,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> Tagged<Value> {
|
) -> Tagged<Value> {
|
||||||
let span = span.into();
|
let tag = tag.into();
|
||||||
let mut top_level = TaggedDictBuilder::new(span);
|
let mut top_level = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
for (key, value) in v.iter() {
|
for (key, value) in v.iter() {
|
||||||
top_level.insert_tagged(key.clone(), convert_ini_second_to_nu_value(value, span));
|
top_level.insert_tagged(key.clone(), convert_ini_second_to_nu_value(value, tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
top_level.into_tagged_value()
|
top_level.into_tagged_value()
|
||||||
|
@ -31,10 +31,10 @@ fn convert_ini_top_to_nu_value(
|
||||||
|
|
||||||
pub fn from_ini_string_to_value(
|
pub fn from_ini_string_to_value(
|
||||||
s: String,
|
s: String,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
|
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
|
||||||
let v: HashMap<String, HashMap<String, String>> = serde_ini::from_str(&s)?;
|
let v: HashMap<String, HashMap<String, String>> = serde_ini::from_str(&s)?;
|
||||||
Ok(convert_ini_top_to_nu_value(&v, span))
|
Ok(convert_ini_top_to_nu_value(&v, tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@ -43,22 +43,26 @@ pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| {
|
.map(move |a| {
|
||||||
let value_span = a.span();
|
let value_tag = a.tag();
|
||||||
match a.item {
|
match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => {
|
Value::Primitive(Primitive::String(s)) => {
|
||||||
match from_ini_string_to_value(s, value_span) {
|
match from_ini_string_to_value(s, value_tag) {
|
||||||
Ok(x) => ReturnSuccess::value(x),
|
Ok(x) => ReturnSuccess::value(x),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as INI",
|
"Could not parse as INI",
|
||||||
"piped data failed INI parse",
|
"input cannot be parsed as INI",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
value_tag.span,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::maybe_labeled_error(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected string values from pipeline",
|
"Expected a string from pipeline",
|
||||||
"expects strings from pipeline",
|
"requires string input",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
a.span(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,32 +2,32 @@ use crate::object::base::OF64;
|
||||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn convert_json_value_to_nu_value(v: &serde_hjson::Value, span: impl Into<Span>) -> Tagged<Value> {
|
fn convert_json_value_to_nu_value(v: &serde_hjson::Value, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let span = span.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
serde_hjson::Value::Null => {
|
serde_hjson::Value::Null => {
|
||||||
Value::Primitive(Primitive::String(String::from(""))).tagged(span)
|
Value::Primitive(Primitive::String(String::from(""))).tagged(tag)
|
||||||
}
|
}
|
||||||
serde_hjson::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(span),
|
serde_hjson::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
|
||||||
serde_hjson::Value::F64(n) => {
|
serde_hjson::Value::F64(n) => {
|
||||||
Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(span)
|
Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(tag)
|
||||||
}
|
}
|
||||||
serde_hjson::Value::U64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(span),
|
serde_hjson::Value::U64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
|
||||||
serde_hjson::Value::I64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(span),
|
serde_hjson::Value::I64(n) => Value::Primitive(Primitive::Int(*n as i64)).tagged(tag),
|
||||||
serde_hjson::Value::String(s) => {
|
serde_hjson::Value::String(s) => {
|
||||||
Value::Primitive(Primitive::String(String::from(s))).tagged(span)
|
Value::Primitive(Primitive::String(String::from(s))).tagged(tag)
|
||||||
}
|
}
|
||||||
serde_hjson::Value::Array(a) => Value::List(
|
serde_hjson::Value::Array(a) => Value::List(
|
||||||
a.iter()
|
a.iter()
|
||||||
.map(|x| convert_json_value_to_nu_value(x, span))
|
.map(|x| convert_json_value_to_nu_value(x, tag))
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
.tagged(span),
|
.tagged(tag),
|
||||||
serde_hjson::Value::Object(o) => {
|
serde_hjson::Value::Object(o) => {
|
||||||
let mut collected = TaggedDictBuilder::new(span);
|
let mut collected = TaggedDictBuilder::new(tag);
|
||||||
for (k, v) in o.iter() {
|
for (k, v) in o.iter() {
|
||||||
collected.insert_tagged(k.clone(), convert_json_value_to_nu_value(v, span));
|
collected.insert_tagged(k.clone(), convert_json_value_to_nu_value(v, tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
collected.into_tagged_value()
|
collected.into_tagged_value()
|
||||||
|
@ -37,10 +37,10 @@ fn convert_json_value_to_nu_value(v: &serde_hjson::Value, span: impl Into<Span>)
|
||||||
|
|
||||||
pub fn from_json_string_to_value(
|
pub fn from_json_string_to_value(
|
||||||
s: String,
|
s: String,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> serde_hjson::Result<Tagged<Value>> {
|
) -> serde_hjson::Result<Tagged<Value>> {
|
||||||
let v: serde_hjson::Value = serde_hjson::from_str(&s)?;
|
let v: serde_hjson::Value = serde_hjson::from_str(&s)?;
|
||||||
Ok(convert_json_value_to_nu_value(&v, span))
|
Ok(convert_json_value_to_nu_value(&v, tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@ -49,22 +49,26 @@ pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| {
|
.map(move |a| {
|
||||||
let value_span = a.span();
|
let value_tag = a.tag();
|
||||||
match a.item {
|
match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => {
|
Value::Primitive(Primitive::String(s)) => {
|
||||||
match from_json_string_to_value(s, value_span) {
|
match from_json_string_to_value(s, value_tag) {
|
||||||
Ok(x) => ReturnSuccess::value(x),
|
Ok(x) => ReturnSuccess::value(x),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as JSON",
|
"Could not parse as JSON",
|
||||||
"piped data failed JSON parse",
|
"input cannot be parsed as JSON",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
value_tag.span,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::maybe_labeled_error(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected string values from pipeline",
|
"Expected a string from pipeline",
|
||||||
"expects strings from pipeline",
|
"requires string input",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
a.span(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -2,28 +2,28 @@ use crate::object::base::OF64;
|
||||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn convert_toml_value_to_nu_value(v: &toml::Value, span: impl Into<Span>) -> Tagged<Value> {
|
fn convert_toml_value_to_nu_value(v: &toml::Value, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let span = span.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
toml::Value::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(span),
|
toml::Value::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
|
||||||
toml::Value::Integer(n) => Value::Primitive(Primitive::Int(*n)).tagged(span),
|
toml::Value::Integer(n) => Value::Primitive(Primitive::Int(*n)).tagged(tag),
|
||||||
toml::Value::Float(n) => Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(span),
|
toml::Value::Float(n) => Value::Primitive(Primitive::Float(OF64::from(*n))).tagged(tag),
|
||||||
toml::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(span),
|
toml::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))).tagged(tag),
|
||||||
toml::Value::Array(a) => Value::List(
|
toml::Value::Array(a) => Value::List(
|
||||||
a.iter()
|
a.iter()
|
||||||
.map(|x| convert_toml_value_to_nu_value(x, span))
|
.map(|x| convert_toml_value_to_nu_value(x, tag))
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
.tagged(span),
|
.tagged(tag),
|
||||||
toml::Value::Datetime(dt) => {
|
toml::Value::Datetime(dt) => {
|
||||||
Value::Primitive(Primitive::String(dt.to_string())).tagged(span)
|
Value::Primitive(Primitive::String(dt.to_string())).tagged(tag)
|
||||||
}
|
}
|
||||||
toml::Value::Table(t) => {
|
toml::Value::Table(t) => {
|
||||||
let mut collected = TaggedDictBuilder::new(span);
|
let mut collected = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
for (k, v) in t.iter() {
|
for (k, v) in t.iter() {
|
||||||
collected.insert_tagged(k.clone(), convert_toml_value_to_nu_value(v, span));
|
collected.insert_tagged(k.clone(), convert_toml_value_to_nu_value(v, tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
collected.into_tagged_value()
|
collected.into_tagged_value()
|
||||||
|
@ -33,10 +33,10 @@ fn convert_toml_value_to_nu_value(v: &toml::Value, span: impl Into<Span>) -> Tag
|
||||||
|
|
||||||
pub fn from_toml_string_to_value(
|
pub fn from_toml_string_to_value(
|
||||||
s: String,
|
s: String,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
|
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
|
||||||
let v: toml::Value = s.parse::<toml::Value>()?;
|
let v: toml::Value = s.parse::<toml::Value>()?;
|
||||||
Ok(convert_toml_value_to_nu_value(&v, span))
|
Ok(convert_toml_value_to_nu_value(&v, tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@ -45,22 +45,26 @@ pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| {
|
.map(move |a| {
|
||||||
let value_span = a.span();
|
let value_tag = a.tag();
|
||||||
match a.item {
|
match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => {
|
Value::Primitive(Primitive::String(s)) => {
|
||||||
match from_toml_string_to_value(s, value_span) {
|
match from_toml_string_to_value(s, value_tag) {
|
||||||
Ok(x) => ReturnSuccess::value(x),
|
Ok(x) => ReturnSuccess::value(x),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as TOML",
|
"Could not parse as TOML",
|
||||||
"piped data failed TOML parse",
|
"input cannot be parsed as TOML",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
value_tag.span,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::maybe_labeled_error(
|
x => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected string values from pipeline",
|
"Expected a string from pipeline",
|
||||||
"expects strings from pipeline",
|
"requires string input",
|
||||||
span,
|
span,
|
||||||
|
format!("{} originates from here", x.type_name()),
|
||||||
|
value_tag.span,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, span: impl Into<Span>) -> Tagged<Value> {
|
fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let span = span.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
if n.is_element() {
|
if n.is_element() {
|
||||||
let name = n.tag_name().name().trim().to_string();
|
let name = n.tag_name().name().trim().to_string();
|
||||||
|
|
||||||
let mut children_values = vec![];
|
let mut children_values = vec![];
|
||||||
for c in n.children() {
|
for c in n.children() {
|
||||||
children_values.push(from_node_to_value(&c, span));
|
children_values.push(from_node_to_value(&c, tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
let children_values: Vec<Tagged<Value>> = children_values
|
let children_values: Vec<Tagged<Value>> = children_values
|
||||||
|
@ -29,31 +29,31 @@ fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>, span: impl Into<Span>
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let mut collected = TaggedDictBuilder::new(span);
|
let mut collected = TaggedDictBuilder::new(tag);
|
||||||
collected.insert(name.clone(), Value::List(children_values));
|
collected.insert(name.clone(), Value::List(children_values));
|
||||||
|
|
||||||
collected.into_tagged_value()
|
collected.into_tagged_value()
|
||||||
} else if n.is_comment() {
|
} else if n.is_comment() {
|
||||||
Value::string("<comment>").tagged(span)
|
Value::string("<comment>").tagged(tag)
|
||||||
} else if n.is_pi() {
|
} else if n.is_pi() {
|
||||||
Value::string("<processing_instruction>").tagged(span)
|
Value::string("<processing_instruction>").tagged(tag)
|
||||||
} else if n.is_text() {
|
} else if n.is_text() {
|
||||||
Value::string(n.text().unwrap()).tagged(span)
|
Value::string(n.text().unwrap()).tagged(tag)
|
||||||
} else {
|
} else {
|
||||||
Value::string("<unknown>").tagged(span)
|
Value::string("<unknown>").tagged(tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_document_to_value(d: &roxmltree::Document, span: impl Into<Span>) -> Tagged<Value> {
|
fn from_document_to_value(d: &roxmltree::Document, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
from_node_to_value(&d.root_element(), span)
|
from_node_to_value(&d.root_element(), tag)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_xml_string_to_value(
|
pub fn from_xml_string_to_value(
|
||||||
s: String,
|
s: String,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
|
) -> Result<Tagged<Value>, Box<dyn std::error::Error>> {
|
||||||
let parsed = roxmltree::Document::parse(&s)?;
|
let parsed = roxmltree::Document::parse(&s)?;
|
||||||
Ok(from_document_to_value(&parsed, span))
|
Ok(from_document_to_value(&parsed, tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@ -61,20 +61,29 @@ pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let span = args.call_info.name_span;
|
let span = args.call_info.name_span;
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match a.item {
|
.map(move |a| {
|
||||||
Value::Primitive(Primitive::String(s)) => match from_xml_string_to_value(s, span) {
|
let value_tag = a.tag();
|
||||||
Ok(x) => ReturnSuccess::value(x),
|
match a.item {
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Value::Primitive(Primitive::String(s)) => {
|
||||||
"Could not parse as XML",
|
match from_xml_string_to_value(s, value_tag) {
|
||||||
"piped data failed XML parse",
|
Ok(x) => ReturnSuccess::value(x),
|
||||||
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
||||||
|
"Could not parse as XML",
|
||||||
|
"input cannot be parsed as XML",
|
||||||
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
value_tag.span,
|
||||||
|
)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
|
"Expected a string from pipeline",
|
||||||
|
"requires string input",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
a.span(),
|
||||||
)),
|
)),
|
||||||
},
|
}
|
||||||
_ => Err(ShellError::maybe_labeled_error(
|
|
||||||
"Expected string values from pipeline",
|
|
||||||
"expects strings from pipeline",
|
|
||||||
span,
|
|
||||||
)),
|
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,31 +2,31 @@ use crate::object::base::OF64;
|
||||||
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
use crate::object::{Primitive, TaggedDictBuilder, Value};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, span: impl Into<Span>) -> Tagged<Value> {
|
fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let span = span.into();
|
let tag = tag.into();
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
serde_yaml::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(span),
|
serde_yaml::Value::Bool(b) => Value::Primitive(Primitive::Boolean(*b)).tagged(tag),
|
||||||
serde_yaml::Value::Number(n) if n.is_i64() => {
|
serde_yaml::Value::Number(n) if n.is_i64() => {
|
||||||
Value::Primitive(Primitive::Int(n.as_i64().unwrap())).tagged(span)
|
Value::Primitive(Primitive::Int(n.as_i64().unwrap())).tagged(tag)
|
||||||
}
|
}
|
||||||
serde_yaml::Value::Number(n) if n.is_f64() => {
|
serde_yaml::Value::Number(n) if n.is_f64() => {
|
||||||
Value::Primitive(Primitive::Float(OF64::from(n.as_f64().unwrap()))).tagged(span)
|
Value::Primitive(Primitive::Float(OF64::from(n.as_f64().unwrap()))).tagged(tag)
|
||||||
}
|
}
|
||||||
serde_yaml::Value::String(s) => Value::string(s).tagged(span),
|
serde_yaml::Value::String(s) => Value::string(s).tagged(tag),
|
||||||
serde_yaml::Value::Sequence(a) => Value::List(
|
serde_yaml::Value::Sequence(a) => Value::List(
|
||||||
a.iter()
|
a.iter()
|
||||||
.map(|x| convert_yaml_value_to_nu_value(x, span))
|
.map(|x| convert_yaml_value_to_nu_value(x, tag))
|
||||||
.collect(),
|
.collect(),
|
||||||
)
|
)
|
||||||
.tagged(span),
|
.tagged(tag),
|
||||||
serde_yaml::Value::Mapping(t) => {
|
serde_yaml::Value::Mapping(t) => {
|
||||||
let mut collected = TaggedDictBuilder::new(span);
|
let mut collected = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
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.insert_tagged(k.clone(), convert_yaml_value_to_nu_value(v, span));
|
collected.insert_tagged(k.clone(), convert_yaml_value_to_nu_value(v, tag));
|
||||||
}
|
}
|
||||||
_ => unimplemented!("Unknown key type"),
|
_ => unimplemented!("Unknown key type"),
|
||||||
}
|
}
|
||||||
|
@ -34,17 +34,17 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value, span: impl Into<Span>)
|
||||||
|
|
||||||
collected.into_tagged_value()
|
collected.into_tagged_value()
|
||||||
}
|
}
|
||||||
serde_yaml::Value::Null => Value::Primitive(Primitive::Nothing).tagged(span),
|
serde_yaml::Value::Null => Value::Primitive(Primitive::Nothing).tagged(tag),
|
||||||
x => unimplemented!("Unsupported yaml case: {:?}", x),
|
x => unimplemented!("Unsupported yaml case: {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_yaml_string_to_value(
|
pub fn from_yaml_string_to_value(
|
||||||
s: String,
|
s: String,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> serde_yaml::Result<Tagged<Value>> {
|
) -> serde_yaml::Result<Tagged<Value>> {
|
||||||
let v: serde_yaml::Value = serde_yaml::from_str(&s)?;
|
let v: serde_yaml::Value = serde_yaml::from_str(&s)?;
|
||||||
Ok(convert_yaml_value_to_nu_value(&v, span))
|
Ok(convert_yaml_value_to_nu_value(&v, tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
@ -53,22 +53,26 @@ pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| {
|
.map(move |a| {
|
||||||
let value_span = a.span();
|
let value_tag = a.tag();
|
||||||
match a.item {
|
match a.item {
|
||||||
Value::Primitive(Primitive::String(s)) => {
|
Value::Primitive(Primitive::String(s)) => {
|
||||||
match from_yaml_string_to_value(s, value_span) {
|
match from_yaml_string_to_value(s, value_tag) {
|
||||||
Ok(x) => ReturnSuccess::value(x),
|
Ok(x) => ReturnSuccess::value(x),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Err(_) => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Could not parse as YAML",
|
"Could not parse as YAML",
|
||||||
"piped data failed YAML parse",
|
"input cannot be parsed as YAML",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
value_tag.span,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::maybe_labeled_error(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected string values from pipeline",
|
"Expected a string from pipeline",
|
||||||
"expects strings from pipeline",
|
"requires string input",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
a.span(),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
|
@ -22,7 +22,7 @@ fn get_member(path: &str, span: Span, obj: &Tagged<Value>) -> Result<Tagged<Valu
|
||||||
|
|
||||||
pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Get requires a field or field path",
|
"Get requires a field or field path",
|
||||||
"needs parameter",
|
"needs parameter",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
|
|
@ -27,10 +27,12 @@ pub fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut result = VecDeque::new();
|
let mut result = VecDeque::new();
|
||||||
result.push_back(Err(ShellError::maybe_labeled_error(
|
result.push_back(Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected string values from pipeline",
|
"Expected a string from pipeline",
|
||||||
"expects strings from pipeline",
|
"requires string input",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
v.span(),
|
||||||
)));
|
)));
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,8 @@
|
||||||
use crate::errors::ShellError;
|
use crate::errors::ShellError;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::shell::shell::Shell;
|
|
||||||
|
|
||||||
pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let env = args.env.lock().unwrap();
|
let env = args.env.lock().unwrap();
|
||||||
|
|
||||||
env.ls(args.call_info, args.input)
|
env.last().unwrap().ls(args.call_info, args.input)
|
||||||
}
|
}
|
||||||
|
|
7
src/commands/next.rs
Normal file
7
src/commands/next.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use crate::commands::command::CommandAction;
|
||||||
|
use crate::errors::ShellError;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub fn next(_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::NextShell))].into())
|
||||||
|
}
|
|
@ -15,14 +15,16 @@ command! {
|
||||||
.env
|
.env
|
||||||
.lock()
|
.lock()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
.path()
|
.path()
|
||||||
.to_path_buf();
|
.to_path_buf();
|
||||||
|
|
||||||
let full_path = PathBuf::from(cwd);
|
let full_path = PathBuf::from(cwd);
|
||||||
|
|
||||||
let path_str = path.to_str().ok_or(ShellError::type_error("Path", "invalid path".tagged(path.span())))?;
|
let path_str = path.to_str().ok_or(ShellError::type_error("Path", "invalid path".tagged(path.tag())))?;
|
||||||
|
|
||||||
let (file_extension, contents, contents_span, span_source) = fetch(&full_path, path_str, path.span())?;
|
let (file_extension, contents, contents_tag, span_source) = fetch(&full_path, path_str, path.span())?;
|
||||||
|
|
||||||
let file_extension = if raw.is_present() {
|
let file_extension = if raw.is_present() {
|
||||||
None
|
None
|
||||||
|
@ -32,7 +34,7 @@ command! {
|
||||||
|
|
||||||
let mut stream = VecDeque::new();
|
let mut stream = VecDeque::new();
|
||||||
|
|
||||||
if let Some(uuid) = contents_span.source {
|
if let Some(uuid) = contents_tag.origin {
|
||||||
// If we have loaded something, track its source
|
// If we have loaded something, track its source
|
||||||
stream.push_back(ReturnSuccess::action(CommandAction::AddSpanSource(uuid, span_source)))
|
stream.push_back(ReturnSuccess::action(CommandAction::AddSpanSource(uuid, span_source)))
|
||||||
}
|
}
|
||||||
|
@ -42,7 +44,7 @@ command! {
|
||||||
let value = parse_as_value(
|
let value = parse_as_value(
|
||||||
file_extension,
|
file_extension,
|
||||||
string,
|
string,
|
||||||
contents_span,
|
contents_tag,
|
||||||
span,
|
span,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
@ -56,7 +58,7 @@ command! {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
other => stream.push_back(ReturnSuccess::value(other.tagged(contents_span))),
|
other => stream.push_back(ReturnSuccess::value(other.tagged(contents_tag))),
|
||||||
};
|
};
|
||||||
|
|
||||||
stream
|
stream
|
||||||
|
@ -67,7 +69,7 @@ pub fn fetch(
|
||||||
cwd: &PathBuf,
|
cwd: &PathBuf,
|
||||||
location: &str,
|
location: &str,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Result<(Option<String>, Value, Span, SpanSource), ShellError> {
|
) -> Result<(Option<String>, Value, Tag, SpanSource), ShellError> {
|
||||||
let mut cwd = cwd.clone();
|
let mut cwd = cwd.clone();
|
||||||
if location.starts_with("http:") || location.starts_with("https:") {
|
if location.starts_with("http:") || location.starts_with("https:") {
|
||||||
let response = reqwest::get(location);
|
let response = reqwest::get(location);
|
||||||
|
@ -79,13 +81,19 @@ pub fn fetch(
|
||||||
(mime::APPLICATION, mime::XML) => Ok((
|
(mime::APPLICATION, mime::XML) => Ok((
|
||||||
Some("xml".to_string()),
|
Some("xml".to_string()),
|
||||||
Value::string(r.text().unwrap()),
|
Value::string(r.text().unwrap()),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::Url(r.url().to_string()),
|
SpanSource::Url(r.url().to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::APPLICATION, mime::JSON) => Ok((
|
(mime::APPLICATION, mime::JSON) => Ok((
|
||||||
Some("json".to_string()),
|
Some("json".to_string()),
|
||||||
Value::string(r.text().unwrap()),
|
Value::string(r.text().unwrap()),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::Url(r.url().to_string()),
|
SpanSource::Url(r.url().to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::APPLICATION, mime::OCTET_STREAM) => {
|
(mime::APPLICATION, mime::OCTET_STREAM) => {
|
||||||
|
@ -100,7 +108,10 @@ pub fn fetch(
|
||||||
Ok((
|
Ok((
|
||||||
None,
|
None,
|
||||||
Value::Binary(buf),
|
Value::Binary(buf),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::Url(r.url().to_string()),
|
SpanSource::Url(r.url().to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -116,14 +127,20 @@ pub fn fetch(
|
||||||
Ok((
|
Ok((
|
||||||
Some(image_ty.to_string()),
|
Some(image_ty.to_string()),
|
||||||
Value::Binary(buf),
|
Value::Binary(buf),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::Url(r.url().to_string()),
|
SpanSource::Url(r.url().to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
(mime::TEXT, mime::HTML) => Ok((
|
(mime::TEXT, mime::HTML) => Ok((
|
||||||
Some("html".to_string()),
|
Some("html".to_string()),
|
||||||
Value::string(r.text().unwrap()),
|
Value::string(r.text().unwrap()),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::Url(r.url().to_string()),
|
SpanSource::Url(r.url().to_string()),
|
||||||
)),
|
)),
|
||||||
(mime::TEXT, mime::PLAIN) => {
|
(mime::TEXT, mime::PLAIN) => {
|
||||||
|
@ -141,7 +158,10 @@ pub fn fetch(
|
||||||
Ok((
|
Ok((
|
||||||
path_extension,
|
path_extension,
|
||||||
Value::string(r.text().unwrap()),
|
Value::string(r.text().unwrap()),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::Url(r.url().to_string()),
|
SpanSource::Url(r.url().to_string()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -151,7 +171,10 @@ pub fn fetch(
|
||||||
"Not yet supported MIME type: {} {}",
|
"Not yet supported MIME type: {} {}",
|
||||||
ty, sub_ty
|
ty, sub_ty
|
||||||
)),
|
)),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::Url(r.url().to_string()),
|
SpanSource::Url(r.url().to_string()),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
|
@ -159,7 +182,10 @@ pub fn fetch(
|
||||||
None => Ok((
|
None => Ok((
|
||||||
None,
|
None,
|
||||||
Value::string(format!("No content type found")),
|
Value::string(format!("No content type found")),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::Url(r.url().to_string()),
|
SpanSource::Url(r.url().to_string()),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
|
@ -179,13 +205,19 @@ pub fn fetch(
|
||||||
cwd.extension()
|
cwd.extension()
|
||||||
.map(|name| name.to_string_lossy().to_string()),
|
.map(|name| name.to_string_lossy().to_string()),
|
||||||
Value::string(s),
|
Value::string(s),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
)),
|
)),
|
||||||
Err(_) => Ok((
|
Err(_) => Ok((
|
||||||
None,
|
None,
|
||||||
Value::Binary(bytes),
|
Value::Binary(bytes),
|
||||||
Span::unknown_with_uuid(Uuid::new_v4()),
|
Tag {
|
||||||
|
span,
|
||||||
|
origin: Some(Uuid::new_v4()),
|
||||||
|
},
|
||||||
SpanSource::File(cwd.to_string_lossy().to_string()),
|
SpanSource::File(cwd.to_string_lossy().to_string()),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
|
@ -203,69 +235,57 @@ pub fn fetch(
|
||||||
pub fn parse_as_value(
|
pub fn parse_as_value(
|
||||||
extension: Option<String>,
|
extension: Option<String>,
|
||||||
contents: String,
|
contents: String,
|
||||||
contents_span: Span,
|
contents_tag: Tag,
|
||||||
name_span: Option<Span>,
|
name_span: Span,
|
||||||
) -> Result<Tagged<Value>, ShellError> {
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
match extension {
|
match extension {
|
||||||
Some(x) if x == "csv" => {
|
Some(x) if x == "csv" => crate::commands::from_csv::from_csv_string_to_value(
|
||||||
crate::commands::from_csv::from_csv_string_to_value(contents, contents_span)
|
contents,
|
||||||
.map(|c| c.tagged(contents_span))
|
contents_tag,
|
||||||
.map_err(move |_| {
|
)
|
||||||
ShellError::maybe_labeled_error(
|
.map_err(move |_| {
|
||||||
"Could not open as CSV",
|
ShellError::labeled_error("Could not open as CSV", "could not open as CSV", name_span)
|
||||||
"could not open as CSV",
|
}),
|
||||||
name_span,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Some(x) if x == "toml" => {
|
Some(x) if x == "toml" => {
|
||||||
crate::commands::from_toml::from_toml_string_to_value(contents, contents_span)
|
crate::commands::from_toml::from_toml_string_to_value(contents, contents_tag).map_err(
|
||||||
.map(|c| c.tagged(contents_span))
|
move |_| {
|
||||||
.map_err(move |_| {
|
ShellError::labeled_error(
|
||||||
ShellError::maybe_labeled_error(
|
|
||||||
"Could not open as TOML",
|
"Could not open as TOML",
|
||||||
"could not open as TOML",
|
"could not open as TOML",
|
||||||
name_span,
|
name_span,
|
||||||
)
|
)
|
||||||
})
|
|
||||||
}
|
|
||||||
Some(x) if x == "json" => {
|
|
||||||
crate::commands::from_json::from_json_string_to_value(contents, contents_span)
|
|
||||||
.map(|c| c.tagged(contents_span))
|
|
||||||
.map_err(move |_| {
|
|
||||||
ShellError::maybe_labeled_error(
|
|
||||||
"Could not open as JSON",
|
|
||||||
"could not open as JSON",
|
|
||||||
name_span,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Some(x) if x == "ini" => {
|
|
||||||
crate::commands::from_ini::from_ini_string_to_value(contents, contents_span)
|
|
||||||
.map(|c| c.tagged(contents_span))
|
|
||||||
.map_err(move |_| {
|
|
||||||
ShellError::maybe_labeled_error(
|
|
||||||
"Could not open as INI",
|
|
||||||
"could not open as INI",
|
|
||||||
name_span,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Some(x) if x == "xml" => {
|
|
||||||
crate::commands::from_xml::from_xml_string_to_value(contents, contents_span).map_err(
|
|
||||||
move |_| {
|
|
||||||
ShellError::maybe_labeled_error(
|
|
||||||
"Could not open as XML",
|
|
||||||
"could not open as XML",
|
|
||||||
name_span,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Some(x) if x == "yml" => {
|
Some(x) if x == "json" => {
|
||||||
crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_span).map_err(
|
crate::commands::from_json::from_json_string_to_value(contents, contents_tag).map_err(
|
||||||
move |_| {
|
move |_| {
|
||||||
ShellError::maybe_labeled_error(
|
ShellError::labeled_error(
|
||||||
|
"Could not open as JSON",
|
||||||
|
"could not open as JSON",
|
||||||
|
name_span,
|
||||||
|
)
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Some(x) if x == "ini" => crate::commands::from_ini::from_ini_string_to_value(
|
||||||
|
contents,
|
||||||
|
contents_tag,
|
||||||
|
)
|
||||||
|
.map_err(move |_| {
|
||||||
|
ShellError::labeled_error("Could not open as INI", "could not open as INI", name_span)
|
||||||
|
}),
|
||||||
|
Some(x) if x == "xml" => crate::commands::from_xml::from_xml_string_to_value(
|
||||||
|
contents,
|
||||||
|
contents_tag,
|
||||||
|
)
|
||||||
|
.map_err(move |_| {
|
||||||
|
ShellError::labeled_error("Could not open as XML", "could not open as XML", name_span)
|
||||||
|
}),
|
||||||
|
Some(x) if x == "yml" => {
|
||||||
|
crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_tag).map_err(
|
||||||
|
move |_| {
|
||||||
|
ShellError::labeled_error(
|
||||||
"Could not open as YAML",
|
"Could not open as YAML",
|
||||||
"could not open as YAML",
|
"could not open as YAML",
|
||||||
name_span,
|
name_span,
|
||||||
|
@ -274,9 +294,9 @@ pub fn parse_as_value(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Some(x) if x == "yaml" => {
|
Some(x) if x == "yaml" => {
|
||||||
crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_span).map_err(
|
crate::commands::from_yaml::from_yaml_string_to_value(contents, contents_tag).map_err(
|
||||||
move |_| {
|
move |_| {
|
||||||
ShellError::maybe_labeled_error(
|
ShellError::labeled_error(
|
||||||
"Could not open as YAML",
|
"Could not open as YAML",
|
||||||
"could not open as YAML",
|
"could not open as YAML",
|
||||||
name_span,
|
name_span,
|
||||||
|
@ -284,6 +304,6 @@ pub fn parse_as_value(
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
_ => Ok(Value::string(contents).tagged(contents_span)),
|
_ => Ok(Value::string(contents).tagged(contents_tag)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use crate::prelude::*;
|
||||||
|
|
||||||
pub fn pick(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn pick(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Pick requires fields",
|
"Pick requires fields",
|
||||||
"needs parameter",
|
"needs parameter",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
@ -17,7 +17,7 @@ pub fn pick(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
|
||||||
let objects = input
|
let objects = input
|
||||||
.values
|
.values
|
||||||
.map(move |value| select_fields(&value.item, &fields, value.span()));
|
.map(move |value| select_fields(&value.item, &fields, value.tag()));
|
||||||
|
|
||||||
Ok(objects.from_input_stream())
|
Ok(objects.from_input_stream())
|
||||||
}
|
}
|
||||||
|
|
7
src/commands/prev.rs
Normal file
7
src/commands/prev.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use crate::commands::command::CommandAction;
|
||||||
|
use crate::errors::ShellError;
|
||||||
|
use crate::prelude::*;
|
||||||
|
|
||||||
|
pub fn prev(_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
Ok(vec![Ok(ReturnSuccess::Action(CommandAction::PreviousShell))].into())
|
||||||
|
}
|
|
@ -10,7 +10,7 @@ pub fn ps(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
|
|
||||||
let list = list
|
let list = list
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|(_, process)| process_dict(process, args.call_info.name_span))
|
.map(|(_, process)| process_dict(process, Tag::unknown_origin(args.call_info.name_span)))
|
||||||
.collect::<VecDeque<_>>();
|
.collect::<VecDeque<_>>();
|
||||||
|
|
||||||
Ok(list.from_input_stream())
|
Ok(list.from_input_stream())
|
||||||
|
|
|
@ -3,10 +3,8 @@ use crate::object::base::reject_fields;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
|
||||||
pub fn reject(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn reject(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let name_span = args.call_info.name_span;
|
|
||||||
|
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Reject requires fields",
|
"Reject requires fields",
|
||||||
"needs parameter",
|
"needs parameter",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
@ -16,11 +14,10 @@ pub fn reject(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let fields: Result<Vec<String>, _> = args.positional_iter().map(|a| a.as_string()).collect();
|
let fields: Result<Vec<String>, _> = args.positional_iter().map(|a| a.as_string()).collect();
|
||||||
let fields = fields?;
|
let fields = fields?;
|
||||||
|
|
||||||
let stream = args.input.values.map(move |item| {
|
let stream = args
|
||||||
reject_fields(&item, &fields, item.span())
|
.input
|
||||||
.into_tagged_value()
|
.values
|
||||||
.tagged(name_span)
|
.map(move |item| reject_fields(&item, &fields, item.tag()).into_tagged_value());
|
||||||
});
|
|
||||||
|
|
||||||
Ok(stream.from_input_stream())
|
Ok(stream.from_input_stream())
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,14 @@ impl Command for Remove {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rm(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn rm(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let mut full_path = args.env.lock().unwrap().path().to_path_buf();
|
let mut full_path = args
|
||||||
|
.env
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.path()
|
||||||
|
.to_path_buf();
|
||||||
|
|
||||||
match args
|
match args
|
||||||
.nth(0)
|
.nth(0)
|
||||||
|
@ -61,7 +68,7 @@ pub fn rm(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"is a directory",
|
"is a directory",
|
||||||
"",
|
"",
|
||||||
args.call_info.name_span.unwrap(),
|
args.call_info.name_span,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
std::fs::remove_dir_all(&path).expect("can not remove directory");
|
std::fs::remove_dir_all(&path).expect("can not remove directory");
|
||||||
|
|
|
@ -9,7 +9,15 @@ use crate::SpanSource;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
|
pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||||
let cwd = args.ctx.env.lock().unwrap().path().to_path_buf();
|
let cwd = args
|
||||||
|
.ctx
|
||||||
|
.env
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.path()
|
||||||
|
.to_path_buf();
|
||||||
let mut full_path = PathBuf::from(cwd);
|
let mut full_path = PathBuf::from(cwd);
|
||||||
|
|
||||||
let save_raw = if args.call_info.args.has("raw") {
|
let save_raw = if args.call_info.args.has("raw") {
|
||||||
|
@ -21,18 +29,14 @@ pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||||
if args.call_info.args.positional.is_none() {
|
if args.call_info.args.positional.is_none() {
|
||||||
// If there is no filename, check the metadata for the origin filename
|
// If there is no filename, check the metadata for the origin filename
|
||||||
if args.input.len() > 0 {
|
if args.input.len() > 0 {
|
||||||
let span = args.input[0].span();
|
let origin = args.input[0].origin();
|
||||||
match span
|
match origin.map(|x| args.call_info.source_map.get(&x)).flatten() {
|
||||||
.source
|
|
||||||
.map(|x| args.call_info.source_map.get(&x))
|
|
||||||
.flatten()
|
|
||||||
{
|
|
||||||
Some(path) => match path {
|
Some(path) => match path {
|
||||||
SpanSource::File(file) => {
|
SpanSource::File(file) => {
|
||||||
full_path.push(Path::new(file));
|
full_path.push(Path::new(file));
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Save requires a filepath",
|
"Save requires a filepath",
|
||||||
"needs path",
|
"needs path",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
@ -40,7 +44,7 @@ pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Save requires a filepath",
|
"Save requires a filepath",
|
||||||
"needs path",
|
"needs path",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
@ -48,7 +52,7 @@ pub fn save(args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Save requires a filepath",
|
"Save requires a filepath",
|
||||||
"needs path",
|
"needs path",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
|
|
@ -4,20 +4,23 @@ use crate::prelude::*;
|
||||||
|
|
||||||
pub fn size(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn size(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let input = args.input;
|
let input = args.input;
|
||||||
|
let span = args.call_info.name_span;
|
||||||
Ok(input
|
Ok(input
|
||||||
.values
|
.values
|
||||||
.map(move |v| match v.item {
|
.map(move |v| match v.item {
|
||||||
Value::Primitive(Primitive::String(ref s)) => ReturnSuccess::value(count(s, v.span())),
|
Value::Primitive(Primitive::String(ref s)) => ReturnSuccess::value(count(s, v.tag())),
|
||||||
_ => Err(ShellError::maybe_labeled_error(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected string values from pipeline",
|
"Expected a string from pipeline",
|
||||||
"expects strings from pipeline",
|
"requires string input",
|
||||||
Some(v.span()),
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
v.span(),
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn count(contents: &str, span: impl Into<Span>) -> Tagged<Value> {
|
fn count(contents: &str, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let mut lines: i64 = 0;
|
let mut lines: i64 = 0;
|
||||||
let mut words: i64 = 0;
|
let mut words: i64 = 0;
|
||||||
let mut chars: i64 = 0;
|
let mut chars: i64 = 0;
|
||||||
|
@ -42,7 +45,7 @@ fn count(contents: &str, span: impl Into<Span>) -> Tagged<Value> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dict = TaggedDictBuilder::new(span);
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
//TODO: add back in name when we have it in the span
|
//TODO: add back in name when we have it in the span
|
||||||
//dict.insert("name", Value::string(name));
|
//dict.insert("name", Value::string(name));
|
||||||
dict.insert("lines", Value::int(lines));
|
dict.insert("lines", Value::int(lines));
|
||||||
|
|
|
@ -27,7 +27,7 @@ impl Command for SkipWhile {
|
||||||
|
|
||||||
pub fn skip_while(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
pub fn skip_while(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
if args.len() == 0 {
|
if args.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Where requires a condition",
|
"Where requires a condition",
|
||||||
"needs condition",
|
"needs condition",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let span = args.call_info.name_span;
|
let span = args.call_info.name_span;
|
||||||
|
|
||||||
if positional.len() == 0 {
|
if positional.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Split-column needs more information",
|
"Split-column needs more information",
|
||||||
"needs parameter (eg split-column \",\")",
|
"needs parameter (eg split-column \",\")",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
@ -34,14 +34,14 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
gen_columns.push(format!("Column{}", i + 1));
|
gen_columns.push(format!("Column{}", i + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut dict = TaggedDictBuilder::new(v.span());
|
let mut dict = TaggedDictBuilder::new(v.tag());
|
||||||
for (&k, v) in split_result.iter().zip(gen_columns.iter()) {
|
for (&k, v) in split_result.iter().zip(gen_columns.iter()) {
|
||||||
dict.insert(v.clone(), Primitive::String(k.into()));
|
dict.insert(v.clone(), Primitive::String(k.into()));
|
||||||
}
|
}
|
||||||
|
|
||||||
ReturnSuccess::value(dict.into_tagged_value())
|
ReturnSuccess::value(dict.into_tagged_value())
|
||||||
} else if split_result.len() == (positional.len() - 1) {
|
} else if split_result.len() == (positional.len() - 1) {
|
||||||
let mut dict = TaggedDictBuilder::new(v.span());
|
let mut dict = TaggedDictBuilder::new(v.tag());
|
||||||
for (&k, v) in split_result.iter().zip(positional.iter().skip(1)) {
|
for (&k, v) in split_result.iter().zip(positional.iter().skip(1)) {
|
||||||
dict.insert(
|
dict.insert(
|
||||||
v.as_string().unwrap(),
|
v.as_string().unwrap(),
|
||||||
|
@ -50,17 +50,19 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
}
|
}
|
||||||
ReturnSuccess::value(dict.into_tagged_value())
|
ReturnSuccess::value(dict.into_tagged_value())
|
||||||
} else {
|
} else {
|
||||||
let mut dict = TaggedDictBuilder::new(v.span());
|
let mut dict = TaggedDictBuilder::new(v.tag());
|
||||||
for k in positional.iter().skip(1) {
|
for k in positional.iter().skip(1) {
|
||||||
dict.insert(k.as_string().unwrap().trim(), Primitive::String("".into()));
|
dict.insert(k.as_string().unwrap().trim(), Primitive::String("".into()));
|
||||||
}
|
}
|
||||||
ReturnSuccess::value(dict.into_tagged_value())
|
ReturnSuccess::value(dict.into_tagged_value())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => Err(ShellError::maybe_labeled_error(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected string values from pipeline",
|
"Expected a string from pipeline",
|
||||||
"expects strings from pipeline",
|
"requires string input",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
v.span(),
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
|
|
|
@ -8,7 +8,7 @@ pub fn split_row(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let span = args.call_info.name_span;
|
let span = args.call_info.name_span;
|
||||||
|
|
||||||
if positional.len() == 0 {
|
if positional.len() == 0 {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Split-row needs more information",
|
"Split-row needs more information",
|
||||||
"needs parameter (eg split-row \"\\n\")",
|
"needs parameter (eg split-row \"\\n\")",
|
||||||
args.call_info.name_span,
|
args.call_info.name_span,
|
||||||
|
@ -30,17 +30,19 @@ pub fn split_row(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let mut result = VecDeque::new();
|
let mut result = VecDeque::new();
|
||||||
for s in split_result {
|
for s in split_result {
|
||||||
result.push_back(ReturnSuccess::value(
|
result.push_back(ReturnSuccess::value(
|
||||||
Value::Primitive(Primitive::String(s.into())).tagged(v.span()),
|
Value::Primitive(Primitive::String(s.into())).tagged(v.tag()),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut result = VecDeque::new();
|
let mut result = VecDeque::new();
|
||||||
result.push_back(Err(ShellError::maybe_labeled_error(
|
result.push_back(Err(ShellError::labeled_error_with_secondary(
|
||||||
"Expected string values from pipeline",
|
"Expected a string from pipeline",
|
||||||
"expects strings from pipeline",
|
"requires string input",
|
||||||
span,
|
span,
|
||||||
|
"value originates from here",
|
||||||
|
v.span(),
|
||||||
)));
|
)));
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,18 +8,19 @@ pub fn tags(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
.input
|
.input
|
||||||
.values
|
.values
|
||||||
.map(move |v| {
|
.map(move |v| {
|
||||||
let mut tags = TaggedDictBuilder::new(v.span());
|
let mut tags = TaggedDictBuilder::new(v.tag());
|
||||||
{
|
{
|
||||||
|
let origin = v.origin();
|
||||||
let span = v.span();
|
let span = v.span();
|
||||||
let mut dict = TaggedDictBuilder::new(v.span());
|
let mut dict = TaggedDictBuilder::new(v.tag());
|
||||||
dict.insert("start", Value::int(span.start as i64));
|
dict.insert("start", Value::int(span.start as i64));
|
||||||
dict.insert("end", Value::int(span.end as i64));
|
dict.insert("end", Value::int(span.end as i64));
|
||||||
match span.source.map(|x| source_map.get(&x)).flatten() {
|
match origin.map(|x| source_map.get(&x)).flatten() {
|
||||||
Some(SpanSource::File(source)) => {
|
Some(SpanSource::File(source)) => {
|
||||||
dict.insert("source", Value::string(source));
|
dict.insert("origin", Value::string(source));
|
||||||
}
|
}
|
||||||
Some(SpanSource::Url(source)) => {
|
Some(SpanSource::Url(source)) => {
|
||||||
dict.insert("source", Value::string(source));
|
dict.insert("origin", Value::string(source));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,11 +42,15 @@ pub fn to_csv(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
Ok(out
|
Ok(out
|
||||||
.values
|
.values
|
||||||
.map(move |a| match to_string(&value_to_csv_value(&a.item)) {
|
.map(move |a| match to_string(&value_to_csv_value(&a.item)) {
|
||||||
Ok(x) => ReturnSuccess::value(Value::Primitive(Primitive::String(x)).tagged(name_span)),
|
Ok(x) => ReturnSuccess::value(
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
||||||
"Can not convert to CSV string",
|
),
|
||||||
"can not convert piped data to CSV string",
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
|
"Expected an object with CSV-compatible structure from pipeline",
|
||||||
|
"requires CSV-compatible input",
|
||||||
name_span,
|
name_span,
|
||||||
|
format!("{} originates from here", a.item.type_name()),
|
||||||
|
a.span(),
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
|
|
|
@ -48,13 +48,15 @@ pub fn to_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
.values
|
.values
|
||||||
.map(
|
.map(
|
||||||
move |a| match serde_json::to_string(&value_to_json_value(&a)) {
|
move |a| match serde_json::to_string(&value_to_json_value(&a)) {
|
||||||
Ok(x) => {
|
Ok(x) => ReturnSuccess::value(
|
||||||
ReturnSuccess::value(Value::Primitive(Primitive::String(x)).tagged(name_span))
|
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
||||||
}
|
),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Can not convert to JSON string",
|
"Expected an object with JSON-compatible structure from pipeline",
|
||||||
"can not convert piped data to JSON string",
|
"requires JSON-compatible input",
|
||||||
name_span,
|
name_span,
|
||||||
|
format!("{} originates from here", a.item.type_name()),
|
||||||
|
a.span(),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -42,13 +42,15 @@ pub fn to_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
.map(move |a| match toml::to_string(&value_to_toml_value(&a)) {
|
.map(move |a| match toml::to_string(&value_to_toml_value(&a)) {
|
||||||
Ok(val) => {
|
Ok(val) => {
|
||||||
return ReturnSuccess::value(
|
return ReturnSuccess::value(
|
||||||
Value::Primitive(Primitive::String(val)).tagged(name_span),
|
Value::Primitive(Primitive::String(val)).simple_spanned(name_span),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
Err(err) => Err(ShellError::type_error(
|
"Expected an object with TOML-compatible structure from pipeline",
|
||||||
"Can not convert to a TOML string",
|
"requires TOML-compatible input",
|
||||||
format!("{:?} - {:?}", a.type_name(), err).tagged(name_span),
|
name_span,
|
||||||
|
format!("{} originates from here", a.item.type_name()),
|
||||||
|
a.span(),
|
||||||
)),
|
)),
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
|
|
|
@ -46,13 +46,15 @@ pub fn to_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
.values
|
.values
|
||||||
.map(
|
.map(
|
||||||
move |a| match serde_yaml::to_string(&value_to_yaml_value(&a)) {
|
move |a| match serde_yaml::to_string(&value_to_yaml_value(&a)) {
|
||||||
Ok(x) => {
|
Ok(x) => ReturnSuccess::value(
|
||||||
ReturnSuccess::value(Value::Primitive(Primitive::String(x)).tagged(name_span))
|
Value::Primitive(Primitive::String(x)).simple_spanned(name_span),
|
||||||
}
|
),
|
||||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
_ => Err(ShellError::labeled_error_with_secondary(
|
||||||
"Can not convert to YAML string",
|
"Expected an object with YAML-compatible structure from pipeline",
|
||||||
"can not convert piped data to YAML string",
|
"requires YAML-compatible input",
|
||||||
name_span,
|
name_span,
|
||||||
|
format!("{} originates from here", a.item.type_name()),
|
||||||
|
a.span(),
|
||||||
)),
|
)),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -9,7 +9,7 @@ pub fn trim(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
.values
|
.values
|
||||||
.map(move |v| {
|
.map(move |v| {
|
||||||
let string = String::extract(&v)?;
|
let string = String::extract(&v)?;
|
||||||
ReturnSuccess::value(Value::string(string.trim()).tagged(v.span()))
|
ReturnSuccess::value(Value::string(string.trim()).simple_spanned(v.span()))
|
||||||
})
|
})
|
||||||
.to_output_stream())
|
.to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub struct Context {
|
||||||
sinks: IndexMap<String, Arc<dyn Sink>>,
|
sinks: IndexMap<String, Arc<dyn Sink>>,
|
||||||
crate source_map: SourceMap,
|
crate source_map: SourceMap,
|
||||||
crate host: Arc<Mutex<dyn Host + Send>>,
|
crate host: Arc<Mutex<dyn Host + Send>>,
|
||||||
crate env: Arc<Mutex<Environment>>,
|
crate env: Arc<Mutex<Vec<Box<dyn Shell>>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Context {
|
impl Context {
|
||||||
|
@ -48,7 +48,7 @@ impl Context {
|
||||||
sinks: indexmap::IndexMap::new(),
|
sinks: indexmap::IndexMap::new(),
|
||||||
source_map: SourceMap::new(),
|
source_map: SourceMap::new(),
|
||||||
host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
|
host: Arc::new(Mutex::new(crate::env::host::BasicHost)),
|
||||||
env: Arc::new(Mutex::new(Environment::basic()?)),
|
env: Arc::new(Mutex::new(vec![Box::new(Environment::basic()?)])),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ impl Context {
|
||||||
crate fn run_sink(
|
crate fn run_sink(
|
||||||
&mut self,
|
&mut self,
|
||||||
command: Arc<dyn Sink>,
|
command: Arc<dyn Sink>,
|
||||||
name_span: Option<Span>,
|
name_span: Span,
|
||||||
args: Args,
|
args: Args,
|
||||||
input: Vec<Tagged<Value>>,
|
input: Vec<Tagged<Value>>,
|
||||||
) -> Result<(), ShellError> {
|
) -> Result<(), ShellError> {
|
||||||
|
@ -111,7 +111,7 @@ impl Context {
|
||||||
crate fn run_command(
|
crate fn run_command(
|
||||||
&mut self,
|
&mut self,
|
||||||
command: Arc<dyn Command>,
|
command: Arc<dyn Command>,
|
||||||
name_span: Option<Span>,
|
name_span: Span,
|
||||||
source_map: SourceMap,
|
source_map: SourceMap,
|
||||||
args: Args,
|
args: Args,
|
||||||
input: InputStream,
|
input: InputStream,
|
||||||
|
|
87
src/env/environment.rs
vendored
87
src/env/environment.rs
vendored
|
@ -1,19 +1,53 @@
|
||||||
use crate::commands::command::CallInfo;
|
use crate::commands::command::CallInfo;
|
||||||
use crate::object::dir_entry_dict;
|
use crate::object::dir_entry_dict;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use crate::shell::completer::NuCompleter;
|
||||||
use crate::shell::shell::Shell;
|
use crate::shell::shell::Shell;
|
||||||
|
use rustyline::completion::{self, Completer, FilenameCompleter};
|
||||||
|
use rustyline::error::ReadlineError;
|
||||||
|
use rustyline::hint::{Hinter, HistoryHinter};
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct Environment {
|
pub struct Environment {
|
||||||
crate path: PathBuf,
|
crate path: PathBuf,
|
||||||
|
completer: NuCompleter,
|
||||||
|
hinter: HistoryHinter,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Clone for Environment {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Environment {
|
||||||
|
path: self.path.clone(),
|
||||||
|
completer: NuCompleter {
|
||||||
|
file_completer: FilenameCompleter::new(),
|
||||||
|
},
|
||||||
|
hinter: HistoryHinter {},
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Environment {
|
impl Environment {
|
||||||
pub fn basic() -> Result<Environment, std::io::Error> {
|
pub fn basic() -> Result<Environment, std::io::Error> {
|
||||||
let path = std::env::current_dir()?;
|
let path = std::env::current_dir()?;
|
||||||
|
|
||||||
Ok(Environment { path })
|
Ok(Environment {
|
||||||
|
path,
|
||||||
|
completer: NuCompleter {
|
||||||
|
file_completer: FilenameCompleter::new(),
|
||||||
|
},
|
||||||
|
hinter: HistoryHinter {},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn with_location(location: String) -> Result<Environment, std::io::Error> {
|
||||||
|
let path = std::path::PathBuf::from(location);
|
||||||
|
|
||||||
|
Ok(Environment {
|
||||||
|
path,
|
||||||
|
completer: NuCompleter {
|
||||||
|
file_completer: FilenameCompleter::new(),
|
||||||
|
},
|
||||||
|
hinter: HistoryHinter {},
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path(&self) -> &Path {
|
pub fn path(&self) -> &Path {
|
||||||
|
@ -24,12 +58,11 @@ impl Environment {
|
||||||
impl Shell for Environment {
|
impl Shell for Environment {
|
||||||
fn ls(&self, call_info: CallInfo, _input: InputStream) -> Result<OutputStream, ShellError> {
|
fn ls(&self, call_info: CallInfo, _input: InputStream) -> Result<OutputStream, ShellError> {
|
||||||
let cwd = self.path.clone();
|
let cwd = self.path.clone();
|
||||||
let mut full_path = PathBuf::from(&cwd);
|
let mut full_path = PathBuf::from(&self.path);
|
||||||
match &call_info.args.nth(0) {
|
match &call_info.args.nth(0) {
|
||||||
Some(Tagged { item: value, .. }) => full_path.push(Path::new(&value.as_string()?)),
|
Some(Tagged { item: value, .. }) => full_path.push(Path::new(&value.as_string()?)),
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries = glob::glob(&full_path.to_string_lossy());
|
let entries = glob::glob(&full_path.to_string_lossy());
|
||||||
|
|
||||||
if entries.is_err() {
|
if entries.is_err() {
|
||||||
|
@ -54,7 +87,7 @@ impl Shell for Environment {
|
||||||
s.span(),
|
s.span(),
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
e.to_string(),
|
e.to_string(),
|
||||||
call_info.name_span,
|
call_info.name_span,
|
||||||
|
@ -67,8 +100,11 @@ impl Shell for Environment {
|
||||||
let entry = entry?;
|
let entry = entry?;
|
||||||
let filepath = entry.path();
|
let filepath = entry.path();
|
||||||
let filename = filepath.strip_prefix(&cwd).unwrap();
|
let filename = filepath.strip_prefix(&cwd).unwrap();
|
||||||
let value =
|
let value = dir_entry_dict(
|
||||||
dir_entry_dict(filename, &entry.metadata()?, call_info.name_span)?;
|
filename,
|
||||||
|
&entry.metadata()?,
|
||||||
|
Tag::unknown_origin(call_info.name_span),
|
||||||
|
)?;
|
||||||
shell_entries.push_back(ReturnSuccess::value(value))
|
shell_entries.push_back(ReturnSuccess::value(value))
|
||||||
}
|
}
|
||||||
return Ok(shell_entries.to_output_stream());
|
return Ok(shell_entries.to_output_stream());
|
||||||
|
@ -81,7 +117,11 @@ impl Shell for Environment {
|
||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
let filename = entry.strip_prefix(&cwd).unwrap();
|
let filename = entry.strip_prefix(&cwd).unwrap();
|
||||||
let metadata = std::fs::metadata(&entry)?;
|
let metadata = std::fs::metadata(&entry)?;
|
||||||
let value = dir_entry_dict(filename, &metadata, call_info.name_span)?;
|
let value = dir_entry_dict(
|
||||||
|
filename,
|
||||||
|
&metadata,
|
||||||
|
Tag::unknown_origin(call_info.name_span),
|
||||||
|
)?;
|
||||||
shell_entries.push_back(ReturnSuccess::value(value))
|
shell_entries.push_back(ReturnSuccess::value(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -94,7 +134,7 @@ impl Shell for Environment {
|
||||||
None => match dirs::home_dir() {
|
None => match dirs::home_dir() {
|
||||||
Some(o) => o,
|
Some(o) => o,
|
||||||
_ => {
|
_ => {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Can not change to home directory",
|
"Can not change to home directory",
|
||||||
"can not go to home",
|
"can not go to home",
|
||||||
call_info.name_span,
|
call_info.name_span,
|
||||||
|
@ -134,4 +174,31 @@ impl Shell for Environment {
|
||||||
stream.push_back(ReturnSuccess::change_cwd(path));
|
stream.push_back(ReturnSuccess::change_cwd(path));
|
||||||
Ok(stream.into())
|
Ok(stream.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn path(&self) -> std::path::PathBuf {
|
||||||
|
self.path.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_path(&mut self, path: std::path::PathBuf) {
|
||||||
|
self.path = path;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Completer for Environment {
|
||||||
|
type Candidate = completion::Pair;
|
||||||
|
|
||||||
|
fn complete(
|
||||||
|
&self,
|
||||||
|
line: &str,
|
||||||
|
pos: usize,
|
||||||
|
ctx: &rustyline::Context<'_>,
|
||||||
|
) -> Result<(usize, Vec<completion::Pair>), ReadlineError> {
|
||||||
|
self.completer.complete(line, pos, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Hinter for Environment {
|
||||||
|
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
|
||||||
|
self.hinter.hint(line, pos, ctx)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,14 +15,11 @@ pub enum Description {
|
||||||
impl Description {
|
impl Description {
|
||||||
pub fn from(value: Tagged<impl Into<String>>) -> Description {
|
pub fn from(value: Tagged<impl Into<String>>) -> Description {
|
||||||
let value_span = value.span();
|
let value_span = value.span();
|
||||||
|
let value_tag = value.tag();
|
||||||
|
|
||||||
match value_span {
|
match value_span {
|
||||||
Span {
|
Span { start: 0, end: 0 } => Description::Synthetic(value.item.into()),
|
||||||
start: 0,
|
_ => Description::Source(Tagged::from_item(value.item.into(), value_tag)),
|
||||||
end: 0,
|
|
||||||
source: None,
|
|
||||||
} => Description::Synthetic(value.item.into()),
|
|
||||||
_ => Description::Source(Tagged::from_item(value.item.into(), value_span)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,13 +41,13 @@ pub enum ArgumentError {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn labelled(
|
pub fn labelled(
|
||||||
span: impl Into<Option<Span>>,
|
span: impl Into<Span>,
|
||||||
heading: &'a str,
|
heading: &'a str,
|
||||||
span_message: &'a str,
|
span_message: &'a str,
|
||||||
) -> impl FnOnce(ShellError) -> ShellError + 'a {
|
) -> impl FnOnce(ShellError) -> ShellError + 'a {
|
||||||
let span = span.into();
|
let span = span.into();
|
||||||
|
|
||||||
move |_| ShellError::maybe_labeled_error(heading, span_message, span)
|
move |_| ShellError::labeled_error(heading, span_message, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
||||||
|
@ -165,7 +162,7 @@ impl ShellError {
|
||||||
actual:
|
actual:
|
||||||
Tagged {
|
Tagged {
|
||||||
item: Some(actual),
|
item: Some(actual),
|
||||||
tag: Tag { span },
|
tag: Tag { span, .. },
|
||||||
},
|
},
|
||||||
} => Diagnostic::new(Severity::Error, "Type Error").with_label(
|
} => Diagnostic::new(Severity::Error, "Type Error").with_label(
|
||||||
Label::new_primary(span)
|
Label::new_primary(span)
|
||||||
|
@ -177,7 +174,7 @@ impl ShellError {
|
||||||
actual:
|
actual:
|
||||||
Tagged {
|
Tagged {
|
||||||
item: None,
|
item: None,
|
||||||
tag: Tag { span },
|
tag: Tag { span, .. },
|
||||||
},
|
},
|
||||||
} => Diagnostic::new(Severity::Error, "Type Error")
|
} => Diagnostic::new(Severity::Error, "Type Error")
|
||||||
.with_label(Label::new_primary(span).with_message(expected)),
|
.with_label(Label::new_primary(span).with_message(expected)),
|
||||||
|
@ -220,18 +217,20 @@ impl ShellError {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn maybe_labeled_error(
|
pub fn labeled_error_with_secondary(
|
||||||
msg: impl Into<String>,
|
msg: impl Into<String>,
|
||||||
label: impl Into<String>,
|
primary_label: impl Into<String>,
|
||||||
span: Option<Span>,
|
primary_span: Span,
|
||||||
|
secondary_label: impl Into<String>,
|
||||||
|
secondary_span: Span,
|
||||||
) -> ShellError {
|
) -> ShellError {
|
||||||
match span {
|
ShellError::diagnostic(
|
||||||
Some(span) => ShellError::diagnostic(
|
Diagnostic::new_error(msg.into())
|
||||||
Diagnostic::new(Severity::Error, msg.into())
|
.with_label(Label::new_primary(primary_span).with_message(primary_label.into()))
|
||||||
.with_label(Label::new_primary(span).with_message(label.into())),
|
.with_label(
|
||||||
),
|
Label::new_secondary(secondary_span).with_message(secondary_label.into()),
|
||||||
None => ShellError::string(msg),
|
),
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string(title: impl Into<String>) -> ShellError {
|
pub fn string(title: impl Into<String>) -> ShellError {
|
||||||
|
|
|
@ -38,14 +38,17 @@ crate fn evaluate_baseline_expr(
|
||||||
let right = evaluate_baseline_expr(binary.right(), registry, scope, source)?;
|
let right = evaluate_baseline_expr(binary.right(), registry, scope, source)?;
|
||||||
|
|
||||||
match left.compare(binary.op(), &*right) {
|
match left.compare(binary.op(), &*right) {
|
||||||
Ok(result) => Ok(Tagged::from_item(Value::boolean(result), expr.span())),
|
Ok(result) => Ok(Tagged::from_simple_spanned_item(
|
||||||
|
Value::boolean(result),
|
||||||
|
expr.span(),
|
||||||
|
)),
|
||||||
Err((left_type, right_type)) => Err(ShellError::coerce_error(
|
Err((left_type, right_type)) => Err(ShellError::coerce_error(
|
||||||
binary.left().copy_span(left_type),
|
binary.left().copy_span(left_type),
|
||||||
binary.right().copy_span(right_type),
|
binary.right().copy_span(right_type),
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RawExpression::Block(block) => Ok(Tagged::from_item(
|
RawExpression::Block(block) => Ok(Tagged::from_simple_spanned_item(
|
||||||
Value::Block(Block::new(block.clone(), source.clone(), expr.span())),
|
Value::Block(Block::new(block.clone(), source.clone(), expr.span())),
|
||||||
expr.span(),
|
expr.span(),
|
||||||
)),
|
)),
|
||||||
|
@ -64,7 +67,7 @@ crate fn evaluate_baseline_expr(
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Some(next) => {
|
Some(next) => {
|
||||||
item = Tagged::from_item(
|
item = Tagged::from_simple_spanned_item(
|
||||||
next.clone().item,
|
next.clone().item,
|
||||||
(expr.span().start, name.span().end),
|
(expr.span().start, name.span().end),
|
||||||
)
|
)
|
||||||
|
@ -72,7 +75,10 @@ crate fn evaluate_baseline_expr(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Tagged::from_item(item.item().clone(), expr.span()))
|
Ok(Tagged::from_simple_spanned_item(
|
||||||
|
item.item().clone(),
|
||||||
|
expr.span(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
RawExpression::Boolean(_boolean) => unimplemented!(),
|
RawExpression::Boolean(_boolean) => unimplemented!(),
|
||||||
}
|
}
|
||||||
|
@ -95,11 +101,11 @@ fn evaluate_reference(
|
||||||
source: &Text,
|
source: &Text,
|
||||||
) -> Result<Tagged<Value>, ShellError> {
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
match name {
|
match name {
|
||||||
hir::Variable::It(span) => Ok(Tagged::from_item(scope.it.item.clone(), span)),
|
hir::Variable::It(span) => Ok(scope.it.item.clone().simple_spanned(span)),
|
||||||
hir::Variable::Other(span) => Ok(scope
|
hir::Variable::Other(span) => Ok(scope
|
||||||
.vars
|
.vars
|
||||||
.get(span.slice(source))
|
.get(span.slice(source))
|
||||||
.map(|v| v.clone())
|
.map(|v| v.clone())
|
||||||
.unwrap_or_else(|| Value::nothing().tagged(span))),
|
.unwrap_or_else(|| Value::nothing().simple_spanned(span))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,7 +168,7 @@ impl Block {
|
||||||
let scope = Scope::new(value.clone());
|
let scope = Scope::new(value.clone());
|
||||||
|
|
||||||
if self.expressions.len() == 0 {
|
if self.expressions.len() == 0 {
|
||||||
return Ok(Tagged::from_item(Value::nothing(), self.span));
|
return Ok(Value::nothing().simple_spanned(self.span));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut last = None;
|
let mut last = None;
|
||||||
|
@ -227,7 +227,7 @@ impl fmt::Debug for ValueDebug<'a> {
|
||||||
impl Tagged<Value> {
|
impl Tagged<Value> {
|
||||||
crate fn tagged_type_name(&self) -> Tagged<String> {
|
crate fn tagged_type_name(&self) -> Tagged<String> {
|
||||||
let name = self.type_name();
|
let name = self.type_name();
|
||||||
Tagged::from_item(name, self.span())
|
Tagged::from_simple_spanned_item(name, self.span())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -352,7 +352,7 @@ impl Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_data_by_path(&'a self, span: Span, path: &str) -> Option<Tagged<&Value>> {
|
pub fn get_data_by_path(&'a self, tag: Tag, path: &str) -> Option<Tagged<&Value>> {
|
||||||
let mut current = self;
|
let mut current = self;
|
||||||
for p in path.split(".") {
|
for p in path.split(".") {
|
||||||
match current.get_data_by_key(p) {
|
match current.get_data_by_key(p) {
|
||||||
|
@ -361,12 +361,12 @@ impl Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(Tagged::from_item(current, span))
|
Some(Tagged::from_item(current, tag))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_data_at_path(
|
pub fn insert_data_at_path(
|
||||||
&'a self,
|
&'a self,
|
||||||
span: Span,
|
tag: Tag,
|
||||||
path: &str,
|
path: &str,
|
||||||
new_value: Value,
|
new_value: Value,
|
||||||
) -> Option<Tagged<Value>> {
|
) -> Option<Tagged<Value>> {
|
||||||
|
@ -384,13 +384,13 @@ impl Value {
|
||||||
Value::Object(o) => {
|
Value::Object(o) => {
|
||||||
o.entries.insert(
|
o.entries.insert(
|
||||||
split_path[idx + 1].to_string(),
|
split_path[idx + 1].to_string(),
|
||||||
Tagged::from_item(new_value, span),
|
Tagged::from_item(new_value, tag),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Some(Tagged::from_item(new_obj, span));
|
return Some(Tagged::from_item(new_obj, tag));
|
||||||
} else {
|
} else {
|
||||||
match next.item {
|
match next.item {
|
||||||
Value::Object(ref mut o) => {
|
Value::Object(ref mut o) => {
|
||||||
|
@ -410,7 +410,7 @@ impl Value {
|
||||||
|
|
||||||
pub fn replace_data_at_path(
|
pub fn replace_data_at_path(
|
||||||
&'a self,
|
&'a self,
|
||||||
span: Span,
|
tag: Tag,
|
||||||
path: &str,
|
path: &str,
|
||||||
replaced_value: Value,
|
replaced_value: Value,
|
||||||
) -> Option<Tagged<Value>> {
|
) -> Option<Tagged<Value>> {
|
||||||
|
@ -424,8 +424,8 @@ impl Value {
|
||||||
match current.entries.get_mut(split_path[idx]) {
|
match current.entries.get_mut(split_path[idx]) {
|
||||||
Some(next) => {
|
Some(next) => {
|
||||||
if idx == (split_path.len() - 1) {
|
if idx == (split_path.len() - 1) {
|
||||||
*next = Tagged::from_item(replaced_value, span);
|
*next = Tagged::from_item(replaced_value, tag);
|
||||||
return Some(Tagged::from_item(new_obj, span));
|
return Some(Tagged::from_item(new_obj, tag));
|
||||||
} else {
|
} else {
|
||||||
match next.item {
|
match next.item {
|
||||||
Value::Object(ref mut o) => {
|
Value::Object(ref mut o) => {
|
||||||
|
@ -601,8 +601,8 @@ impl Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn select_fields(obj: &Value, fields: &[String], span: impl Into<Span>) -> Tagged<Value> {
|
crate fn select_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let mut out = TaggedDictBuilder::new(span);
|
let mut out = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
|
|
||||||
|
@ -616,8 +616,8 @@ crate fn select_fields(obj: &Value, fields: &[String], span: impl Into<Span>) ->
|
||||||
out.into_tagged_value()
|
out.into_tagged_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn reject_fields(obj: &Value, fields: &[String], span: impl Into<Span>) -> Tagged<Value> {
|
crate fn reject_fields(obj: &Value, fields: &[String], tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let mut out = TaggedDictBuilder::new(span);
|
let mut out = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
|
|
||||||
|
|
|
@ -47,7 +47,7 @@ crate fn config(span: impl Into<Span>) -> Result<IndexMap<String, Tagged<Value>>
|
||||||
trace!("config file = {}", filename.display());
|
trace!("config file = {}", filename.display());
|
||||||
|
|
||||||
let contents = fs::read_to_string(filename)
|
let contents = fs::read_to_string(filename)
|
||||||
.map(|v| v.tagged(span))
|
.map(|v| v.simple_spanned(span))
|
||||||
.map_err(|err| ShellError::string(&format!("Couldn't read config file:\n{}", err)))?;
|
.map_err(|err| ShellError::string(&format!("Couldn't read config file:\n{}", err)))?;
|
||||||
|
|
||||||
let parsed: Config = toml::from_str(&contents)
|
let parsed: Config = toml::from_str(&contents)
|
||||||
|
|
|
@ -102,20 +102,20 @@ impl Dictionary {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TaggedListBuilder {
|
pub struct TaggedListBuilder {
|
||||||
span: Span,
|
tag: Tag,
|
||||||
list: Vec<Tagged<Value>>,
|
list: Vec<Tagged<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaggedListBuilder {
|
impl TaggedListBuilder {
|
||||||
pub fn new(span: impl Into<Span>) -> TaggedListBuilder {
|
pub fn new(tag: impl Into<Tag>) -> TaggedListBuilder {
|
||||||
TaggedListBuilder {
|
TaggedListBuilder {
|
||||||
span: span.into(),
|
tag: tag.into(),
|
||||||
list: vec![],
|
list: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn push(&mut self, value: impl Into<Value>) {
|
pub fn push(&mut self, value: impl Into<Value>) {
|
||||||
self.list.push(value.into().tagged(self.span));
|
self.list.push(value.into().tagged(self.tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_tagged(&mut self, value: impl Into<Tagged<Value>>) {
|
pub fn insert_tagged(&mut self, value: impl Into<Tagged<Value>>) {
|
||||||
|
@ -123,7 +123,7 @@ impl TaggedListBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_tagged_value(self) -> Tagged<Value> {
|
pub fn into_tagged_value(self) -> Tagged<Value> {
|
||||||
Value::List(self.list).tagged(self.span)
|
Value::List(self.list).tagged(self.tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,20 +135,20 @@ impl From<TaggedListBuilder> for Tagged<Value> {
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct TaggedDictBuilder {
|
pub struct TaggedDictBuilder {
|
||||||
span: Span,
|
tag: Tag,
|
||||||
dict: IndexMap<String, Tagged<Value>>,
|
dict: IndexMap<String, Tagged<Value>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaggedDictBuilder {
|
impl TaggedDictBuilder {
|
||||||
pub fn new(span: impl Into<Span>) -> TaggedDictBuilder {
|
pub fn new(tag: impl Into<Tag>) -> TaggedDictBuilder {
|
||||||
TaggedDictBuilder {
|
TaggedDictBuilder {
|
||||||
span: span.into(),
|
tag: tag.into(),
|
||||||
dict: IndexMap::default(),
|
dict: IndexMap::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) {
|
pub fn insert(&mut self, key: impl Into<String>, value: impl Into<Value>) {
|
||||||
self.dict.insert(key.into(), value.into().tagged(self.span));
|
self.dict.insert(key.into(), value.into().tagged(self.tag));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn insert_tagged(&mut self, key: impl Into<String>, value: impl Into<Tagged<Value>>) {
|
pub fn insert_tagged(&mut self, key: impl Into<String>, value: impl Into<Tagged<Value>>) {
|
||||||
|
@ -160,7 +160,7 @@ impl TaggedDictBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_tagged_dict(self) -> Tagged<Dictionary> {
|
pub fn into_tagged_dict(self) -> Tagged<Dictionary> {
|
||||||
Dictionary { entries: self.dict }.tagged(self.span)
|
Dictionary { entries: self.dict }.tagged(self.tag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -12,9 +12,9 @@ pub enum FileType {
|
||||||
crate fn dir_entry_dict(
|
crate fn dir_entry_dict(
|
||||||
filename: &std::path::Path,
|
filename: &std::path::Path,
|
||||||
metadata: &std::fs::Metadata,
|
metadata: &std::fs::Metadata,
|
||||||
span: impl Into<Span>,
|
tag: impl Into<Tag>,
|
||||||
) -> Result<Tagged<Value>, ShellError> {
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
let mut dict = TaggedDictBuilder::new(span);
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
dict.insert("name", Value::string(filename.to_string_lossy()));
|
dict.insert("name", Value::string(filename.to_string_lossy()));
|
||||||
|
|
||||||
let kind = if metadata.is_dir() {
|
let kind = if metadata.is_dir() {
|
||||||
|
|
|
@ -17,6 +17,6 @@ impl<T: Into<Value>> Tagged<T> {
|
||||||
pub fn into_tagged_value(self) -> Tagged<Value> {
|
pub fn into_tagged_value(self) -> Tagged<Value> {
|
||||||
let value_span = self.span();
|
let value_span = self.span();
|
||||||
let value = self.item.into();
|
let value = self.item.into();
|
||||||
value.tagged(value_span)
|
value.simple_spanned(value_span)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,25 +5,32 @@ use serde::Serialize;
|
||||||
use serde_derive::Deserialize;
|
use serde_derive::Deserialize;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
#[derive(
|
#[derive(new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
||||||
new, Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
|
|
||||||
)]
|
|
||||||
#[get = "crate"]
|
|
||||||
pub struct Tagged<T> {
|
pub struct Tagged<T> {
|
||||||
pub tag: Tag,
|
pub tag: Tag,
|
||||||
pub item: T,
|
pub item: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait TaggedItem: Sized {
|
pub trait TaggedItem: Sized {
|
||||||
fn tagged(self, span: impl Into<Span>) -> Tagged<Self> {
|
fn tagged(self, tag: impl Into<Tag>) -> Tagged<Self> {
|
||||||
Tagged::from_item(self, span.into())
|
Tagged::from_item(self, tag.into())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simple_spanned(self, span: impl Into<Span>) -> Tagged<Self> {
|
||||||
|
Tagged::from_simple_spanned_item(self, span.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, this is a temporary facility. In many cases, there are other useful spans that we
|
// For now, this is a temporary facility. In many cases, there are other useful spans that we
|
||||||
// could be using, such as the original source spans of JSON or Toml files, but we don't yet
|
// could be using, such as the original source spans of JSON or Toml files, but we don't yet
|
||||||
// have the infrastructure to make that work.
|
// have the infrastructure to make that work.
|
||||||
fn tagged_unknown(self) -> Tagged<Self> {
|
fn tagged_unknown(self) -> Tagged<Self> {
|
||||||
Tagged::from_item(self, (0, 0))
|
Tagged::from_item(
|
||||||
|
self,
|
||||||
|
Tag {
|
||||||
|
span: Span::unknown(),
|
||||||
|
origin: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,28 +45,44 @@ impl<T> std::ops::Deref for Tagged<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Tagged<T> {
|
impl<T> Tagged<T> {
|
||||||
pub fn tagged(self, span: impl Into<Span>) -> Tagged<T> {
|
pub fn spanned(self, span: impl Into<Span>) -> Tagged<T> {
|
||||||
Tagged::from_item(self.item, span.into())
|
Tagged::from_item(
|
||||||
|
self.item,
|
||||||
|
Tag {
|
||||||
|
span: span.into(),
|
||||||
|
origin: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_item(item: T, span: impl Into<Span>) -> Tagged<T> {
|
pub fn from_item(item: T, tag: impl Into<Tag>) -> Tagged<T> {
|
||||||
Tagged {
|
Tagged {
|
||||||
item,
|
item,
|
||||||
tag: Tag { span: span.into() },
|
tag: tag.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn from_simple_spanned_item(item: T, span: impl Into<Span>) -> Tagged<T> {
|
||||||
|
Tagged::from_item(
|
||||||
|
item,
|
||||||
|
Tag {
|
||||||
|
span: span.into(),
|
||||||
|
origin: None,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn map<U>(self, input: impl FnOnce(T) -> U) -> Tagged<U> {
|
pub fn map<U>(self, input: impl FnOnce(T) -> U) -> Tagged<U> {
|
||||||
let span = self.span();
|
let tag = self.tag();
|
||||||
|
|
||||||
let mapped = input(self.item);
|
let mapped = input(self.item);
|
||||||
Tagged::from_item(mapped, span)
|
Tagged::from_item(mapped, tag.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn copy_span<U>(&self, output: U) -> Tagged<U> {
|
crate fn copy_span<U>(&self, output: U) -> Tagged<U> {
|
||||||
let span = self.span();
|
let span = self.span();
|
||||||
|
|
||||||
Tagged::from_item(output, span)
|
Tagged::from_simple_spanned_item(output, span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn source(&self, source: &Text) -> Text {
|
pub fn source(&self, source: &Text) -> Text {
|
||||||
|
@ -69,6 +92,18 @@ impl<T> Tagged<T> {
|
||||||
pub fn span(&self) -> Span {
|
pub fn span(&self) -> Span {
|
||||||
self.tag.span
|
self.tag.span
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tag(&self) -> Tag {
|
||||||
|
self.tag
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn origin(&self) -> Option<uuid::Uuid> {
|
||||||
|
self.tag.origin
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn item(&self) -> &T {
|
||||||
|
&self.item
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> From<&Tagged<T>> for Span {
|
impl<T> From<&Tagged<T>> for Span {
|
||||||
|
@ -88,7 +123,6 @@ impl From<nom5_locate::LocatedSpan<&str>> for Span {
|
||||||
Span {
|
Span {
|
||||||
start: input.offset,
|
start: input.offset,
|
||||||
end: input.offset + input.fragment.len(),
|
end: input.offset + input.fragment.len(),
|
||||||
source: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -98,7 +132,6 @@ impl<T> From<(nom5_locate::LocatedSpan<T>, nom5_locate::LocatedSpan<T>)> for Spa
|
||||||
Span {
|
Span {
|
||||||
start: input.0.offset,
|
start: input.0.offset,
|
||||||
end: input.1.offset,
|
end: input.1.offset,
|
||||||
source: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -108,7 +141,6 @@ impl From<(usize, usize)> for Span {
|
||||||
Span {
|
Span {
|
||||||
start: input.0,
|
start: input.0,
|
||||||
end: input.1,
|
end: input.1,
|
||||||
source: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,7 +150,6 @@ impl From<&std::ops::Range<usize>> for Span {
|
||||||
Span {
|
Span {
|
||||||
start: input.start,
|
start: input.start,
|
||||||
end: input.end,
|
end: input.end,
|
||||||
source: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -127,24 +158,33 @@ impl From<&std::ops::Range<usize>> for Span {
|
||||||
Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
|
Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash, Getters,
|
||||||
)]
|
)]
|
||||||
pub struct Tag {
|
pub struct Tag {
|
||||||
|
pub origin: Option<Uuid>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Tag {
|
||||||
|
pub fn unknown_origin(span: Span) -> Tag {
|
||||||
|
Tag { origin: None, span }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unknown() -> Tag {
|
||||||
|
Tag {
|
||||||
|
origin: None,
|
||||||
|
span: Span::unknown(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Serialize, Deserialize, Hash)]
|
||||||
pub struct Span {
|
pub struct Span {
|
||||||
crate start: usize,
|
crate start: usize,
|
||||||
crate end: usize,
|
crate end: usize,
|
||||||
pub source: Option<Uuid>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Option<Span>> for Span {
|
impl From<Option<Span>> for Span {
|
||||||
fn from(input: Option<Span>) -> Span {
|
fn from(input: Option<Span>) -> Span {
|
||||||
match input {
|
match input {
|
||||||
None => Span {
|
None => Span { start: 0, end: 0 },
|
||||||
start: 0,
|
|
||||||
end: 0,
|
|
||||||
source: None,
|
|
||||||
},
|
|
||||||
Some(span) => span,
|
Some(span) => span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,13 +192,10 @@ impl From<Option<Span>> for Span {
|
||||||
|
|
||||||
impl Span {
|
impl Span {
|
||||||
pub fn unknown() -> Span {
|
pub fn unknown() -> Span {
|
||||||
Span {
|
Span { start: 0, end: 0 }
|
||||||
start: 0,
|
|
||||||
end: 0,
|
|
||||||
source: None,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
pub fn unknown_with_uuid(uuid: Uuid) -> Span {
|
pub fn unknown_with_uuid(uuid: Uuid) -> Span {
|
||||||
Span {
|
Span {
|
||||||
start: 0,
|
start: 0,
|
||||||
|
@ -166,6 +203,7 @@ impl Span {
|
||||||
source: Some(uuid),
|
source: Some(uuid),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
pub fn is_unknown(&self) -> bool {
|
pub fn is_unknown(&self) -> bool {
|
||||||
self.start == 0 && self.end == 0
|
self.start == 0 && self.end == 0
|
||||||
|
@ -181,7 +219,6 @@ impl language_reporting::ReportingSpan for Span {
|
||||||
Span {
|
Span {
|
||||||
start,
|
start,
|
||||||
end: self.end,
|
end: self.end,
|
||||||
source: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +226,6 @@ impl language_reporting::ReportingSpan for Span {
|
||||||
Span {
|
Span {
|
||||||
start: self.start,
|
start: self.start,
|
||||||
end,
|
end,
|
||||||
source: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,8 @@ use crate::prelude::*;
|
||||||
use itertools::join;
|
use itertools::join;
|
||||||
use sysinfo::ProcessExt;
|
use sysinfo::ProcessExt;
|
||||||
|
|
||||||
crate fn process_dict(proc: &sysinfo::Process, span: impl Into<Span>) -> Tagged<Value> {
|
crate fn process_dict(proc: &sysinfo::Process, tag: impl Into<Tag>) -> Tagged<Value> {
|
||||||
let mut dict = TaggedDictBuilder::new(span);
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
let cmd = proc.cmd();
|
let cmd = proc.cmd();
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub trait ExtractType: Sized {
|
||||||
|
|
||||||
impl<T: ExtractType> ExtractType for Tagged<T> {
|
impl<T: ExtractType> ExtractType for Tagged<T> {
|
||||||
fn extract(value: &Tagged<Value>) -> Result<Tagged<T>, ShellError> {
|
fn extract(value: &Tagged<Value>) -> Result<Tagged<T>, ShellError> {
|
||||||
Ok(T::extract(value)?.tagged(value.span()))
|
Ok(T::extract(value)?.tagged(value.tag()))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
fn check(value: &'value Tagged<Value>) -> Result<&'value Tagged<Value>, ShellError> {
|
||||||
|
|
|
@ -64,36 +64,36 @@ pub type Expression = Tagged<RawExpression>;
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
fn int(i: impl Into<i64>, span: impl Into<Span>) -> Expression {
|
fn int(i: impl Into<i64>, span: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_item(RawExpression::Literal(Literal::Integer(i.into())), span)
|
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Integer(i.into())), span)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn size(i: impl Into<i64>, unit: impl Into<Unit>, span: impl Into<Span>) -> Expression {
|
fn size(i: impl Into<i64>, unit: impl Into<Unit>, span: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_item(
|
Tagged::from_simple_spanned_item(
|
||||||
RawExpression::Literal(Literal::Size(i.into(), unit.into())),
|
RawExpression::Literal(Literal::Size(i.into(), unit.into())),
|
||||||
span,
|
span,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
fn string(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_item(
|
Tagged::from_simple_spanned_item(
|
||||||
RawExpression::Literal(Literal::String(inner.into())),
|
RawExpression::Literal(Literal::String(inner.into())),
|
||||||
outer.into(),
|
outer.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bare(span: impl Into<Span>) -> Expression {
|
fn bare(span: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_item(RawExpression::Literal(Literal::Bare), span.into())
|
Tagged::from_simple_spanned_item(RawExpression::Literal(Literal::Bare), span.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
fn variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_item(
|
Tagged::from_simple_spanned_item(
|
||||||
RawExpression::Variable(Variable::Other(inner.into())),
|
RawExpression::Variable(Variable::Other(inner.into())),
|
||||||
outer.into(),
|
outer.into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
fn it_variable(inner: impl Into<Span>, outer: impl Into<Span>) -> Expression {
|
||||||
Tagged::from_item(
|
Tagged::from_simple_spanned_item(
|
||||||
RawExpression::Variable(Variable::It(inner.into())),
|
RawExpression::Variable(Variable::It(inner.into())),
|
||||||
outer.into(),
|
outer.into(),
|
||||||
)
|
)
|
||||||
|
|
|
@ -61,7 +61,7 @@ pub fn baseline_parse_next_expr(
|
||||||
(SyntaxType::Path, token) => {
|
(SyntaxType::Path, token) => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"Path",
|
"Path",
|
||||||
token.type_name().tagged(token.span()),
|
token.type_name().simple_spanned(token.span()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,10 +81,10 @@ pub fn baseline_parse_next_expr(
|
||||||
|
|
||||||
let second = match tokens.next() {
|
let second = match tokens.next() {
|
||||||
None => {
|
None => {
|
||||||
return Err(ShellError::maybe_labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Expected something after an operator",
|
"Expected something after an operator",
|
||||||
"operator",
|
"operator",
|
||||||
Some(op.span()),
|
op.span(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
Some(token) => baseline_parse_semantic_token(token, registry, source)?,
|
Some(token) => baseline_parse_semantic_token(token, registry, source)?,
|
||||||
|
@ -97,7 +97,7 @@ pub fn baseline_parse_next_expr(
|
||||||
let span = (first.span().start, second.span().end);
|
let span = (first.span().start, second.span().end);
|
||||||
let binary = hir::Binary::new(first, op, second);
|
let binary = hir::Binary::new(first, op, second);
|
||||||
let binary = hir::RawExpression::Binary(Box::new(binary));
|
let binary = hir::RawExpression::Binary(Box::new(binary));
|
||||||
let binary = Tagged::from_item(binary, span);
|
let binary = Tagged::from_simple_spanned_item(binary, span);
|
||||||
|
|
||||||
Ok(binary)
|
Ok(binary)
|
||||||
}
|
}
|
||||||
|
@ -108,11 +108,12 @@ pub fn baseline_parse_next_expr(
|
||||||
let path: Tagged<hir::RawExpression> = match first {
|
let path: Tagged<hir::RawExpression> = match first {
|
||||||
Tagged {
|
Tagged {
|
||||||
item: hir::RawExpression::Literal(hir::Literal::Bare),
|
item: hir::RawExpression::Literal(hir::Literal::Bare),
|
||||||
tag: Tag { span },
|
tag: Tag { span, .. },
|
||||||
} => {
|
} => {
|
||||||
let string = Tagged::from_item(span.slice(source).to_string(), span);
|
let string =
|
||||||
|
Tagged::from_simple_spanned_item(span.slice(source).to_string(), span);
|
||||||
let path = hir::Path::new(
|
let path = hir::Path::new(
|
||||||
Tagged::from_item(
|
Tagged::from_simple_spanned_item(
|
||||||
// TODO: Deal with synthetic nodes that have no representation at all in source
|
// TODO: Deal with synthetic nodes that have no representation at all in source
|
||||||
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
||||||
(0, 0),
|
(0, 0),
|
||||||
|
@ -120,15 +121,16 @@ pub fn baseline_parse_next_expr(
|
||||||
vec![string],
|
vec![string],
|
||||||
);
|
);
|
||||||
let path = hir::RawExpression::Path(Box::new(path));
|
let path = hir::RawExpression::Path(Box::new(path));
|
||||||
Tagged::from_item(path, first.span())
|
Tagged::from_simple_spanned_item(path, first.span())
|
||||||
}
|
}
|
||||||
Tagged {
|
Tagged {
|
||||||
item: hir::RawExpression::Literal(hir::Literal::String(inner)),
|
item: hir::RawExpression::Literal(hir::Literal::String(inner)),
|
||||||
tag: Tag { span },
|
tag: Tag { span, .. },
|
||||||
} => {
|
} => {
|
||||||
let string = Tagged::from_item(inner.slice(source).to_string(), span);
|
let string =
|
||||||
|
Tagged::from_simple_spanned_item(inner.slice(source).to_string(), span);
|
||||||
let path = hir::Path::new(
|
let path = hir::Path::new(
|
||||||
Tagged::from_item(
|
Tagged::from_simple_spanned_item(
|
||||||
// TODO: Deal with synthetic nodes that have no representation at all in source
|
// TODO: Deal with synthetic nodes that have no representation at all in source
|
||||||
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
hir::RawExpression::Variable(hir::Variable::It(Span::from((0, 0)))),
|
||||||
(0, 0),
|
(0, 0),
|
||||||
|
@ -136,14 +138,14 @@ pub fn baseline_parse_next_expr(
|
||||||
vec![string],
|
vec![string],
|
||||||
);
|
);
|
||||||
let path = hir::RawExpression::Path(Box::new(path));
|
let path = hir::RawExpression::Path(Box::new(path));
|
||||||
Tagged::from_item(path, first.span())
|
Tagged::from_simple_spanned_item(path, first.span())
|
||||||
}
|
}
|
||||||
Tagged {
|
Tagged {
|
||||||
item: hir::RawExpression::Variable(..),
|
item: hir::RawExpression::Variable(..),
|
||||||
..
|
..
|
||||||
} => first,
|
} => first,
|
||||||
Tagged {
|
Tagged {
|
||||||
tag: Tag { span },
|
tag: Tag { span, .. },
|
||||||
item,
|
item,
|
||||||
} => {
|
} => {
|
||||||
return Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
|
@ -156,10 +158,10 @@ pub fn baseline_parse_next_expr(
|
||||||
|
|
||||||
let binary = hir::Binary::new(path, op, second);
|
let binary = hir::Binary::new(path, op, second);
|
||||||
let binary = hir::RawExpression::Binary(Box::new(binary));
|
let binary = hir::RawExpression::Binary(Box::new(binary));
|
||||||
let binary = Tagged::from_item(binary, span);
|
let binary = Tagged::from_simple_spanned_item(binary, span);
|
||||||
|
|
||||||
let block = hir::RawExpression::Block(vec![binary]);
|
let block = hir::RawExpression::Block(vec![binary]);
|
||||||
let block = Tagged::from_item(block, span);
|
let block = Tagged::from_simple_spanned_item(block, span);
|
||||||
|
|
||||||
Ok(block)
|
Ok(block)
|
||||||
}
|
}
|
||||||
|
@ -204,7 +206,7 @@ pub fn baseline_parse_delimited(
|
||||||
baseline_parse_tokens(&mut TokensIterator::new(children), registry, source)?;
|
baseline_parse_tokens(&mut TokensIterator::new(children), registry, source)?;
|
||||||
|
|
||||||
let expr = hir::RawExpression::Block(exprs);
|
let expr = hir::RawExpression::Block(exprs);
|
||||||
Ok(Tagged::from_item(expr, token.span()))
|
Ok(Tagged::from_simple_spanned_item(expr, token.span()))
|
||||||
}
|
}
|
||||||
Delimiter::Paren => unimplemented!(),
|
Delimiter::Paren => unimplemented!(),
|
||||||
Delimiter::Square => unimplemented!(),
|
Delimiter::Square => unimplemented!(),
|
||||||
|
@ -228,7 +230,7 @@ pub fn baseline_parse_path(
|
||||||
RawToken::Integer(_) | RawToken::Size(..) | RawToken::Variable(_) => {
|
RawToken::Integer(_) | RawToken::Size(..) | RawToken::Variable(_) => {
|
||||||
return Err(ShellError::type_error(
|
return Err(ShellError::type_error(
|
||||||
"String",
|
"String",
|
||||||
token.type_name().tagged(part),
|
token.type_name().simple_spanned(part),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -240,10 +242,10 @@ pub fn baseline_parse_path(
|
||||||
}
|
}
|
||||||
.to_string();
|
.to_string();
|
||||||
|
|
||||||
tail.push(string.tagged(part));
|
tail.push(string.simple_spanned(part));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(hir::path(head, tail).tagged(token).into())
|
Ok(hir::path(head, tail).simple_spanned(token).into())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, new)]
|
#[derive(Debug, new)]
|
||||||
|
|
|
@ -77,7 +77,7 @@ pub fn raw_integer(input: NomSpan) -> IResult<NomSpan, Tagged<i64>> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Tagged::from_item(int(num.fragment, neg), (start, end)),
|
Tagged::from_simple_spanned_item(int(num.fragment, neg), (start, end)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -231,7 +231,7 @@ pub fn raw_unit(input: NomSpan) -> IResult<NomSpan, Tagged<Unit>> {
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
input,
|
input,
|
||||||
Tagged::from_item(Unit::from(unit.fragment), (start, end)),
|
Tagged::from_simple_spanned_item(Unit::from(unit.fragment), (start, end)),
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -1029,7 +1029,7 @@ mod tests {
|
||||||
right: usize,
|
right: usize,
|
||||||
) -> TokenNode {
|
) -> TokenNode {
|
||||||
let node = DelimitedNode::new(delimiter, children);
|
let node = DelimitedNode::new(delimiter, children);
|
||||||
let spanned = Tagged::from_item(node, (left, right));
|
let spanned = Tagged::from_simple_spanned_item(node, (left, right));
|
||||||
TokenNode::Delimited(spanned)
|
TokenNode::Delimited(spanned)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1038,16 +1038,16 @@ mod tests {
|
||||||
Box::new(head),
|
Box::new(head),
|
||||||
tail.into_iter().map(TokenNode::Token).collect(),
|
tail.into_iter().map(TokenNode::Token).collect(),
|
||||||
);
|
);
|
||||||
let spanned = Tagged::from_item(node, (left, right));
|
let spanned = Tagged::from_simple_spanned_item(node, (left, right));
|
||||||
TokenNode::Path(spanned)
|
TokenNode::Path(spanned)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn leaf_token(token: RawToken, left: usize, right: usize) -> TokenNode {
|
fn leaf_token(token: RawToken, left: usize, right: usize) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_item(token, (left, right)))
|
TokenNode::Token(Tagged::from_simple_spanned_item(token, (left, right)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn token(token: RawToken, left: usize, right: usize) -> TokenNode {
|
fn token(token: RawToken, left: usize, right: usize) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_item(token, (left, right)))
|
TokenNode::Token(Tagged::from_simple_spanned_item(token, (left, right)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build<T>(block: CurriedNode<T>) -> T {
|
fn build<T>(block: CurriedNode<T>) -> T {
|
||||||
|
|
|
@ -92,7 +92,7 @@ impl TokenTreeBuilder {
|
||||||
input: (Vec<PipelineElement>, Option<Span>),
|
input: (Vec<PipelineElement>, Option<Span>),
|
||||||
span: impl Into<Span>,
|
span: impl Into<Span>,
|
||||||
) -> TokenNode {
|
) -> TokenNode {
|
||||||
TokenNode::Pipeline(Tagged::from_item(
|
TokenNode::Pipeline(Tagged::from_simple_spanned_item(
|
||||||
Pipeline::new(input.0, input.1.into()),
|
Pipeline::new(input.0, input.1.into()),
|
||||||
span,
|
span,
|
||||||
))
|
))
|
||||||
|
@ -111,7 +111,7 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_op(input: impl Into<Operator>, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_op(input: impl Into<Operator>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Operator(Tagged::from_item(input.into(), span.into()))
|
TokenNode::Operator(Tagged::from_simple_spanned_item(input.into(), span.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn string(input: impl Into<String>) -> CurriedToken {
|
pub fn string(input: impl Into<String>) -> CurriedToken {
|
||||||
|
@ -128,7 +128,7 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_string(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_string(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_item(
|
TokenNode::Token(Tagged::from_simple_spanned_item(
|
||||||
RawToken::String(input.into()),
|
RawToken::String(input.into()),
|
||||||
span.into(),
|
span.into(),
|
||||||
))
|
))
|
||||||
|
@ -146,7 +146,10 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_bare(input: impl Into<Span>) -> TokenNode {
|
pub fn spanned_bare(input: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_item(RawToken::Bare, input.into()))
|
TokenNode::Token(Tagged::from_simple_spanned_item(
|
||||||
|
RawToken::Bare,
|
||||||
|
input.into(),
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn int(input: impl Into<i64>) -> CurriedToken {
|
pub fn int(input: impl Into<i64>) -> CurriedToken {
|
||||||
|
@ -161,7 +164,10 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_int(input: impl Into<i64>, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_int(input: impl Into<i64>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Token(Token::from_item(RawToken::Integer(input.into()), span))
|
TokenNode::Token(Token::from_simple_spanned_item(
|
||||||
|
RawToken::Integer(input.into()),
|
||||||
|
span,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn size(int: impl Into<i64>, unit: impl Into<Unit>) -> CurriedToken {
|
pub fn size(int: impl Into<i64>, unit: impl Into<Unit>) -> CurriedToken {
|
||||||
|
@ -183,7 +189,10 @@ impl TokenTreeBuilder {
|
||||||
) -> TokenNode {
|
) -> TokenNode {
|
||||||
let (int, unit) = (input.0.into(), input.1.into());
|
let (int, unit) = (input.0.into(), input.1.into());
|
||||||
|
|
||||||
TokenNode::Token(Tagged::from_item(RawToken::Size(int, unit), span))
|
TokenNode::Token(Tagged::from_simple_spanned_item(
|
||||||
|
RawToken::Size(int, unit),
|
||||||
|
span,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path(head: CurriedToken, tail: Vec<CurriedToken>) -> CurriedToken {
|
pub fn path(head: CurriedToken, tail: Vec<CurriedToken>) -> CurriedToken {
|
||||||
|
@ -206,7 +215,7 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_path(input: (TokenNode, Vec<TokenNode>), span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_path(input: (TokenNode, Vec<TokenNode>), span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Path(Tagged::from_item(
|
TokenNode::Path(Tagged::from_simple_spanned_item(
|
||||||
PathNode::new(Box::new(input.0), input.1),
|
PathNode::new(Box::new(input.0), input.1),
|
||||||
span,
|
span,
|
||||||
))
|
))
|
||||||
|
@ -224,7 +233,7 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_var(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_var(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Token(Tagged::from_item(
|
TokenNode::Token(Tagged::from_simple_spanned_item(
|
||||||
RawToken::Variable(input.into()),
|
RawToken::Variable(input.into()),
|
||||||
span.into(),
|
span.into(),
|
||||||
))
|
))
|
||||||
|
@ -242,7 +251,7 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_flag(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_flag(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Flag(Tagged::from_item(
|
TokenNode::Flag(Tagged::from_simple_spanned_item(
|
||||||
Flag::new(FlagKind::Longhand, input.into()),
|
Flag::new(FlagKind::Longhand, input.into()),
|
||||||
span.into(),
|
span.into(),
|
||||||
))
|
))
|
||||||
|
@ -260,7 +269,7 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_shorthand(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_shorthand(input: impl Into<Span>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Flag(Tagged::from_item(
|
TokenNode::Flag(Tagged::from_simple_spanned_item(
|
||||||
Flag::new(FlagKind::Shorthand, input.into()),
|
Flag::new(FlagKind::Shorthand, input.into()),
|
||||||
span.into(),
|
span.into(),
|
||||||
))
|
))
|
||||||
|
@ -306,7 +315,7 @@ impl TokenTreeBuilder {
|
||||||
let head = input.next().unwrap();
|
let head = input.next().unwrap();
|
||||||
let tail = input.collect();
|
let tail = input.collect();
|
||||||
|
|
||||||
Tagged::from_item(CallNode::new(Box::new(head), tail), span)
|
Tagged::from_simple_spanned_item(CallNode::new(Box::new(head), tail), span)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parens(input: Vec<CurriedToken>) -> CurriedToken {
|
pub fn parens(input: Vec<CurriedToken>) -> CurriedToken {
|
||||||
|
@ -324,7 +333,7 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_parens(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_parens(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Delimited(Tagged::from_item(
|
TokenNode::Delimited(Tagged::from_simple_spanned_item(
|
||||||
DelimitedNode::new(Delimiter::Paren, input.into()),
|
DelimitedNode::new(Delimiter::Paren, input.into()),
|
||||||
span,
|
span,
|
||||||
))
|
))
|
||||||
|
@ -345,7 +354,7 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_square(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_square(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Delimited(Tagged::from_item(
|
TokenNode::Delimited(Tagged::from_simple_spanned_item(
|
||||||
DelimitedNode::new(Delimiter::Square, input.into()),
|
DelimitedNode::new(Delimiter::Square, input.into()),
|
||||||
span,
|
span,
|
||||||
))
|
))
|
||||||
|
@ -366,7 +375,7 @@ impl TokenTreeBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn spanned_brace(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
|
pub fn spanned_brace(input: impl Into<Vec<TokenNode>>, span: impl Into<Span>) -> TokenNode {
|
||||||
TokenNode::Delimited(Tagged::from_item(
|
TokenNode::Delimited(Tagged::from_simple_spanned_item(
|
||||||
DelimitedNode::new(Delimiter::Brace, input.into()),
|
DelimitedNode::new(Delimiter::Brace, input.into()),
|
||||||
span,
|
span,
|
||||||
))
|
))
|
||||||
|
|
|
@ -48,8 +48,8 @@ fn parse_command_head(head: &TokenNode) -> Result<hir::Expression, ShellError> {
|
||||||
|
|
||||||
TokenNode::Token(Tagged {
|
TokenNode::Token(Tagged {
|
||||||
item: RawToken::String(inner_span),
|
item: RawToken::String(inner_span),
|
||||||
tag: Tag { span },
|
tag: Tag { span, origin: None },
|
||||||
}) => Ok(Tagged::from_item(
|
}) => Ok(Tagged::from_simple_spanned_item(
|
||||||
hir::RawExpression::Literal(hir::Literal::String(*inner_span)),
|
hir::RawExpression::Literal(hir::Literal::String(*inner_span)),
|
||||||
*span,
|
*span,
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -252,8 +252,10 @@ fn evaluate_args(
|
||||||
for (name, value) in n.named.iter() {
|
for (name, value) in n.named.iter() {
|
||||||
match value {
|
match value {
|
||||||
hir::named::NamedValue::PresentSwitch(span) => {
|
hir::named::NamedValue::PresentSwitch(span) => {
|
||||||
results
|
results.insert(
|
||||||
.insert(name.clone(), Tagged::from_item(Value::boolean(true), *span));
|
name.clone(),
|
||||||
|
Tagged::from_simple_spanned_item(Value::boolean(true), *span),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
hir::named::NamedValue::Value(expr) => {
|
hir::named::NamedValue::Value(expr) => {
|
||||||
results.insert(
|
results.insert(
|
||||||
|
|
|
@ -17,10 +17,10 @@ impl Add {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
|
fn add(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
|
||||||
let value_span = value.span();
|
let value_tag = value.tag();
|
||||||
match (value.item, self.value.clone()) {
|
match (value.item, self.value.clone()) {
|
||||||
(obj @ Value::Object(_), Some(v)) => match &self.field {
|
(obj @ Value::Object(_), Some(v)) => match &self.field {
|
||||||
Some(f) => match obj.insert_data_at_path(value_span, &f, v) {
|
Some(f) => match obj.insert_data_at_path(value_tag, &f, v) {
|
||||||
Some(v) => return Ok(v),
|
Some(v) => return Ok(v),
|
||||||
None => {
|
None => {
|
||||||
return Err(ShellError::string(
|
return Err(ShellError::string(
|
||||||
|
|
|
@ -30,13 +30,10 @@ impl Plugin for BinaryView {
|
||||||
|
|
||||||
fn sink(&mut self, call_info: CallInfo, input: Vec<Tagged<Value>>) {
|
fn sink(&mut self, call_info: CallInfo, input: Vec<Tagged<Value>>) {
|
||||||
for v in input {
|
for v in input {
|
||||||
let value_span = v.span();
|
let value_origin = v.origin();
|
||||||
match v.item {
|
match v.item {
|
||||||
Value::Binary(b) => {
|
Value::Binary(b) => {
|
||||||
let source = value_span
|
let source = value_origin.map(|x| call_info.source_map.get(&x)).flatten();
|
||||||
.source
|
|
||||||
.map(|x| call_info.source_map.get(&x))
|
|
||||||
.flatten();
|
|
||||||
let _ = view_binary(&b, source, call_info.args.has("lores"));
|
let _ = view_binary(&b, source, call_info.args.has("lores"));
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -17,10 +17,10 @@ impl Edit {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn edit(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
|
fn edit(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
|
||||||
let value_span = value.span();
|
let value_tag = value.tag();
|
||||||
match (value.item, self.value.clone()) {
|
match (value.item, self.value.clone()) {
|
||||||
(obj @ Value::Object(_), Some(v)) => match &self.field {
|
(obj @ Value::Object(_), Some(v)) => match &self.field {
|
||||||
Some(f) => match obj.replace_data_at_path(value_span, &f, v) {
|
Some(f) => match obj.replace_data_at_path(value_tag, &f, v) {
|
||||||
Some(v) => return Ok(v),
|
Some(v) => return Ok(v),
|
||||||
None => {
|
None => {
|
||||||
return Err(ShellError::string(
|
return Err(ShellError::string(
|
||||||
|
|
|
@ -26,15 +26,15 @@ impl Inc {
|
||||||
field: &Option<String>,
|
field: &Option<String>,
|
||||||
) -> Result<Tagged<Value>, ShellError> {
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
match value.item {
|
match value.item {
|
||||||
Value::Primitive(Primitive::Int(i)) => Ok(Value::int(i + 1).tagged(value.span())),
|
Value::Primitive(Primitive::Int(i)) => Ok(Value::int(i + 1).tagged(value.tag())),
|
||||||
Value::Primitive(Primitive::Bytes(b)) => {
|
Value::Primitive(Primitive::Bytes(b)) => {
|
||||||
Ok(Value::bytes(b + 1 as u64).tagged(value.span()))
|
Ok(Value::bytes(b + 1 as u64).tagged(value.tag()))
|
||||||
}
|
}
|
||||||
Value::Primitive(Primitive::String(ref s)) => {
|
Value::Primitive(Primitive::String(ref s)) => {
|
||||||
if let Ok(i) = s.parse::<u64>() {
|
if let Ok(i) = s.parse::<u64>() {
|
||||||
Ok(Tagged::from_item(
|
Ok(Tagged::from_item(
|
||||||
Value::string(format!("{}", i + 1)),
|
Value::string(format!("{}", i + 1)),
|
||||||
value.span(),
|
value.tag(),
|
||||||
))
|
))
|
||||||
} else if let Ok(mut ver) = semver::Version::parse(&s) {
|
} else if let Ok(mut ver) = semver::Version::parse(&s) {
|
||||||
if self.major {
|
if self.major {
|
||||||
|
@ -47,7 +47,7 @@ impl Inc {
|
||||||
}
|
}
|
||||||
Ok(Tagged::from_item(
|
Ok(Tagged::from_item(
|
||||||
Value::string(ver.to_string()),
|
Value::string(ver.to_string()),
|
||||||
value.span(),
|
value.tag(),
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Err(ShellError::string("string could not be incremented"))
|
Err(ShellError::string("string could not be incremented"))
|
||||||
|
@ -55,7 +55,7 @@ impl Inc {
|
||||||
}
|
}
|
||||||
Value::Object(_) => match field {
|
Value::Object(_) => match field {
|
||||||
Some(f) => {
|
Some(f) => {
|
||||||
let replacement = match value.item.get_data_by_path(value.span(), f) {
|
let replacement = match value.item.get_data_by_path(value.tag(), f) {
|
||||||
Some(result) => self.inc(result.map(|x| x.clone()), &None)?,
|
Some(result) => self.inc(result.map(|x| x.clone()), &None)?,
|
||||||
None => {
|
None => {
|
||||||
return Err(ShellError::string("inc could not find field to replace"))
|
return Err(ShellError::string("inc could not find field to replace"))
|
||||||
|
@ -63,7 +63,7 @@ impl Inc {
|
||||||
};
|
};
|
||||||
match value
|
match value
|
||||||
.item
|
.item
|
||||||
.replace_data_at_path(value.span(), f, replacement.item.clone())
|
.replace_data_at_path(value.tag(), f, replacement.item.clone())
|
||||||
{
|
{
|
||||||
Some(v) => return Ok(v),
|
Some(v) => return Ok(v),
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -86,11 +86,11 @@ impl Str {
|
||||||
) -> Result<Tagged<Value>, ShellError> {
|
) -> Result<Tagged<Value>, ShellError> {
|
||||||
match value.item {
|
match value.item {
|
||||||
Value::Primitive(Primitive::String(ref s)) => {
|
Value::Primitive(Primitive::String(ref s)) => {
|
||||||
Ok(Tagged::from_item(self.apply(&s), value.span()))
|
Ok(Tagged::from_item(self.apply(&s), value.tag()))
|
||||||
}
|
}
|
||||||
Value::Object(_) => match field {
|
Value::Object(_) => match field {
|
||||||
Some(f) => {
|
Some(f) => {
|
||||||
let replacement = match value.item.get_data_by_path(value.span(), f) {
|
let replacement = match value.item.get_data_by_path(value.tag(), f) {
|
||||||
Some(result) => self.strutils(result.map(|x| x.clone()), &None)?,
|
Some(result) => self.strutils(result.map(|x| x.clone()), &None)?,
|
||||||
None => {
|
None => {
|
||||||
return Err(ShellError::string("str could not find field to replace"))
|
return Err(ShellError::string("str could not find field to replace"))
|
||||||
|
@ -98,7 +98,7 @@ impl Str {
|
||||||
};
|
};
|
||||||
match value
|
match value
|
||||||
.item
|
.item
|
||||||
.replace_data_at_path(value.span(), f, replacement.item.clone())
|
.replace_data_at_path(value.tag(), f, replacement.item.clone())
|
||||||
{
|
{
|
||||||
Some(v) => return Ok(v),
|
Some(v) => return Ok(v),
|
||||||
None => {
|
None => {
|
||||||
|
@ -194,7 +194,7 @@ mod tests {
|
||||||
use super::Str;
|
use super::Str;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu::{
|
use nu::{
|
||||||
Args, CallInfo, Plugin, ReturnSuccess, SourceMap, Span, Tagged, TaggedDictBuilder,
|
Args, CallInfo, Plugin, ReturnSuccess, SourceMap, Span, Tag, Tagged, TaggedDictBuilder,
|
||||||
TaggedItem, Value,
|
TaggedItem, Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -214,28 +214,28 @@ mod tests {
|
||||||
fn with_long_flag(&mut self, name: &str) -> &mut Self {
|
fn with_long_flag(&mut self, name: &str) -> &mut Self {
|
||||||
self.flags.insert(
|
self.flags.insert(
|
||||||
name.to_string(),
|
name.to_string(),
|
||||||
Value::boolean(true).tagged(Span::unknown()),
|
Value::boolean(true).simple_spanned(Span::unknown()),
|
||||||
);
|
);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn with_parameter(&mut self, name: &str) -> &mut Self {
|
fn with_parameter(&mut self, name: &str) -> &mut Self {
|
||||||
self.positionals
|
self.positionals
|
||||||
.push(Value::string(name.to_string()).tagged(Span::unknown()));
|
.push(Value::string(name.to_string()).simple_spanned(Span::unknown()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(&self) -> CallInfo {
|
fn create(&self, name_span: Span) -> CallInfo {
|
||||||
CallInfo {
|
CallInfo {
|
||||||
args: Args::new(Some(self.positionals.clone()), Some(self.flags.clone())),
|
args: Args::new(Some(self.positionals.clone()), Some(self.flags.clone())),
|
||||||
source_map: SourceMap::new(),
|
source_map: SourceMap::new(),
|
||||||
name_span: None,
|
name_span,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sample_record(key: &str, value: &str) -> Tagged<Value> {
|
fn sample_record(key: &str, value: &str) -> Tagged<Value> {
|
||||||
let mut record = TaggedDictBuilder::new(Span::unknown());
|
let mut record = TaggedDictBuilder::new(Tag::unknown());
|
||||||
record.insert(key.clone(), Value::string(value));
|
record.insert(key.clone(), Value::string(value));
|
||||||
record.into_tagged_value()
|
record.into_tagged_value()
|
||||||
}
|
}
|
||||||
|
@ -256,7 +256,11 @@ mod tests {
|
||||||
let mut plugin = Str::new();
|
let mut plugin = Str::new();
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(CallStub::new().with_long_flag("downcase").create())
|
.begin_filter(
|
||||||
|
CallStub::new()
|
||||||
|
.with_long_flag("downcase")
|
||||||
|
.create(Span::unknown())
|
||||||
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(plugin.action.is_some());
|
assert!(plugin.action.is_some());
|
||||||
}
|
}
|
||||||
|
@ -266,7 +270,11 @@ mod tests {
|
||||||
let mut plugin = Str::new();
|
let mut plugin = Str::new();
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(CallStub::new().with_long_flag("upcase").create())
|
.begin_filter(
|
||||||
|
CallStub::new()
|
||||||
|
.with_long_flag("upcase")
|
||||||
|
.create(Span::unknown())
|
||||||
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(plugin.action.is_some());
|
assert!(plugin.action.is_some());
|
||||||
}
|
}
|
||||||
|
@ -276,7 +284,11 @@ mod tests {
|
||||||
let mut plugin = Str::new();
|
let mut plugin = Str::new();
|
||||||
|
|
||||||
assert!(plugin
|
assert!(plugin
|
||||||
.begin_filter(CallStub::new().with_long_flag("to-int").create())
|
.begin_filter(
|
||||||
|
CallStub::new()
|
||||||
|
.with_long_flag("to-int")
|
||||||
|
.create(Span::unknown())
|
||||||
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
assert!(plugin.action.is_some());
|
assert!(plugin.action.is_some());
|
||||||
}
|
}
|
||||||
|
@ -289,7 +301,7 @@ mod tests {
|
||||||
.begin_filter(
|
.begin_filter(
|
||||||
CallStub::new()
|
CallStub::new()
|
||||||
.with_parameter("package.description")
|
.with_parameter("package.description")
|
||||||
.create()
|
.create(Span::unknown())
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
|
@ -306,7 +318,7 @@ mod tests {
|
||||||
.with_long_flag("upcase")
|
.with_long_flag("upcase")
|
||||||
.with_long_flag("downcase")
|
.with_long_flag("downcase")
|
||||||
.with_long_flag("to-int")
|
.with_long_flag("to-int")
|
||||||
.create(),
|
.create(Span::unknown()),
|
||||||
)
|
)
|
||||||
.is_err());
|
.is_err());
|
||||||
assert_eq!(plugin.error, Some("can only apply one".to_string()));
|
assert_eq!(plugin.error, Some("can only apply one".to_string()));
|
||||||
|
@ -342,7 +354,7 @@ mod tests {
|
||||||
CallStub::new()
|
CallStub::new()
|
||||||
.with_long_flag("upcase")
|
.with_long_flag("upcase")
|
||||||
.with_parameter("name")
|
.with_parameter("name")
|
||||||
.create()
|
.create(Span::unknown())
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
|
@ -370,7 +382,7 @@ mod tests {
|
||||||
CallStub::new()
|
CallStub::new()
|
||||||
.with_long_flag("downcase")
|
.with_long_flag("downcase")
|
||||||
.with_parameter("name")
|
.with_parameter("name")
|
||||||
.create()
|
.create(Span::unknown())
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
|
@ -398,7 +410,7 @@ mod tests {
|
||||||
CallStub::new()
|
CallStub::new()
|
||||||
.with_long_flag("to-int")
|
.with_long_flag("to-int")
|
||||||
.with_parameter("Nu_birthday")
|
.with_parameter("Nu_birthday")
|
||||||
.create()
|
.create(Span::unknown())
|
||||||
)
|
)
|
||||||
.is_ok());
|
.is_ok());
|
||||||
|
|
||||||
|
|
|
@ -18,10 +18,11 @@ impl Sum {
|
||||||
match self.total {
|
match self.total {
|
||||||
Some(Tagged {
|
Some(Tagged {
|
||||||
item: Value::Primitive(Primitive::Int(j)),
|
item: Value::Primitive(Primitive::Int(j)),
|
||||||
tag: Tag { span },
|
tag: Tag { span, .. },
|
||||||
}) => {
|
}) => {
|
||||||
//TODO: handle overflow
|
//TODO: handle overflow
|
||||||
self.total = Some(Tagged::from_item(Value::int(i + j), span));
|
self.total =
|
||||||
|
Some(Tagged::from_simple_spanned_item(Value::int(i + j), span));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
@ -37,10 +38,11 @@ impl Sum {
|
||||||
match self.total {
|
match self.total {
|
||||||
Some(Tagged {
|
Some(Tagged {
|
||||||
item: Value::Primitive(Primitive::Bytes(j)),
|
item: Value::Primitive(Primitive::Bytes(j)),
|
||||||
tag: Tag { span },
|
tag: Tag { span, .. },
|
||||||
}) => {
|
}) => {
|
||||||
//TODO: handle overflow
|
//TODO: handle overflow
|
||||||
self.total = Some(Tagged::from_item(Value::bytes(b + j), span));
|
self.total =
|
||||||
|
Some(Tagged::from_simple_spanned_item(Value::bytes(b + j), span));
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
|
|
|
@ -6,7 +6,7 @@ use heim::{disk, memory};
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
use nu::{
|
use nu::{
|
||||||
serve_plugin, CallInfo, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue,
|
serve_plugin, CallInfo, CommandConfig, Plugin, Primitive, ReturnSuccess, ReturnValue,
|
||||||
ShellError, Span, Tagged, TaggedDictBuilder, Value, OF64,
|
ShellError, Tag, Tagged, TaggedDictBuilder, Value, OF64,
|
||||||
};
|
};
|
||||||
use std::ffi::OsStr;
|
use std::ffi::OsStr;
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ impl Sys {
|
||||||
|
|
||||||
//TODO: add more error checking
|
//TODO: add more error checking
|
||||||
|
|
||||||
async fn cpu(span: Span) -> Option<Tagged<Value>> {
|
async fn cpu(tag: Tag) -> Option<Tagged<Value>> {
|
||||||
if let (Ok(num_cpu), Ok(cpu_speed)) = (sys_info::cpu_num(), sys_info::cpu_speed()) {
|
if let (Ok(num_cpu), Ok(cpu_speed)) = (sys_info::cpu_num(), sys_info::cpu_speed()) {
|
||||||
let mut cpu_idx = TaggedDictBuilder::new(span);
|
let mut cpu_idx = TaggedDictBuilder::new(tag);
|
||||||
cpu_idx.insert("cores", Primitive::Int(num_cpu as i64));
|
cpu_idx.insert("cores", Primitive::Int(num_cpu as i64));
|
||||||
cpu_idx.insert("speed", Primitive::Int(cpu_speed as i64));
|
cpu_idx.insert("speed", Primitive::Int(cpu_speed as i64));
|
||||||
Some(cpu_idx.into_tagged_value())
|
Some(cpu_idx.into_tagged_value())
|
||||||
|
@ -30,8 +30,8 @@ async fn cpu(span: Span) -> Option<Tagged<Value>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn mem(span: Span) -> Tagged<Value> {
|
async fn mem(tag: Tag) -> Tagged<Value> {
|
||||||
let mut dict = TaggedDictBuilder::new(span);
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
if let Ok(memory) = memory::memory().await {
|
if let Ok(memory) = memory::memory().await {
|
||||||
dict.insert("total", Value::bytes(memory.total().get()));
|
dict.insert("total", Value::bytes(memory.total().get()));
|
||||||
|
@ -45,8 +45,8 @@ async fn mem(span: Span) -> Tagged<Value> {
|
||||||
dict.into_tagged_value()
|
dict.into_tagged_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn host(span: Span) -> Tagged<Value> {
|
async fn host(tag: Tag) -> Tagged<Value> {
|
||||||
let mut dict = TaggedDictBuilder::new(span);
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
// OS
|
// OS
|
||||||
if let Ok(platform) = heim::host::platform().await {
|
if let Ok(platform) = heim::host::platform().await {
|
||||||
|
@ -58,7 +58,7 @@ async fn host(span: Span) -> Tagged<Value> {
|
||||||
|
|
||||||
// Uptime
|
// Uptime
|
||||||
if let Ok(uptime) = heim::host::uptime().await {
|
if let Ok(uptime) = heim::host::uptime().await {
|
||||||
let mut uptime_dict = TaggedDictBuilder::new(span);
|
let mut uptime_dict = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
let uptime = uptime.get().round() as i64;
|
let uptime = uptime.get().round() as i64;
|
||||||
let days = uptime / (60 * 60 * 24);
|
let days = uptime / (60 * 60 * 24);
|
||||||
|
@ -79,7 +79,7 @@ async fn host(span: Span) -> Tagged<Value> {
|
||||||
let mut user_vec = vec![];
|
let mut user_vec = vec![];
|
||||||
while let Some(user) = users.next().await {
|
while let Some(user) = users.next().await {
|
||||||
if let Ok(user) = user {
|
if let Ok(user) = user {
|
||||||
user_vec.push(Tagged::from_item(Value::string(user.username()), span));
|
user_vec.push(Tagged::from_item(Value::string(user.username()), tag));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let user_list = Value::List(user_vec);
|
let user_list = Value::List(user_vec);
|
||||||
|
@ -88,12 +88,12 @@ async fn host(span: Span) -> Tagged<Value> {
|
||||||
dict.into_tagged_value()
|
dict.into_tagged_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn disks(span: Span) -> Value {
|
async fn disks(tag: Tag) -> Value {
|
||||||
let mut output = vec![];
|
let mut output = vec![];
|
||||||
let mut partitions = disk::partitions_physical();
|
let mut partitions = disk::partitions_physical();
|
||||||
while let Some(part) = partitions.next().await {
|
while let Some(part) = partitions.next().await {
|
||||||
if let Ok(part) = part {
|
if let Ok(part) = part {
|
||||||
let mut dict = TaggedDictBuilder::new(span);
|
let mut dict = TaggedDictBuilder::new(tag);
|
||||||
dict.insert(
|
dict.insert(
|
||||||
"device",
|
"device",
|
||||||
Value::string(
|
Value::string(
|
||||||
|
@ -117,14 +117,14 @@ async fn disks(span: Span) -> Value {
|
||||||
Value::List(output)
|
Value::List(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn temp(span: Span) -> Value {
|
async fn temp(tag: Tag) -> Value {
|
||||||
use sysinfo::{ComponentExt, RefreshKind, SystemExt};
|
use sysinfo::{ComponentExt, RefreshKind, SystemExt};
|
||||||
let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_system());
|
let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_system());
|
||||||
let components_list = system.get_components_list();
|
let components_list = system.get_components_list();
|
||||||
if components_list.len() > 0 {
|
if components_list.len() > 0 {
|
||||||
let mut v: Vec<Tagged<Value>> = vec![];
|
let mut v: Vec<Tagged<Value>> = vec![];
|
||||||
for component in components_list {
|
for component in components_list {
|
||||||
let mut component_idx = TaggedDictBuilder::new(span);
|
let mut component_idx = TaggedDictBuilder::new(tag);
|
||||||
component_idx.insert("name", Primitive::String(component.get_label().to_string()));
|
component_idx.insert("name", Primitive::String(component.get_label().to_string()));
|
||||||
component_idx.insert(
|
component_idx.insert(
|
||||||
"temp",
|
"temp",
|
||||||
|
@ -145,7 +145,7 @@ async fn temp(span: Span) -> Value {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn net(span: Span) -> Tagged<Value> {
|
async fn net(tag: Tag) -> Tagged<Value> {
|
||||||
use sysinfo::{NetworkExt, RefreshKind, SystemExt};
|
use sysinfo::{NetworkExt, RefreshKind, SystemExt};
|
||||||
let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_network());
|
let system = sysinfo::System::new_with_specifics(RefreshKind::new().with_network());
|
||||||
|
|
||||||
|
@ -153,23 +153,23 @@ async fn net(span: Span) -> Tagged<Value> {
|
||||||
let incoming = network.get_income();
|
let incoming = network.get_income();
|
||||||
let outgoing = network.get_outcome();
|
let outgoing = network.get_outcome();
|
||||||
|
|
||||||
let mut network_idx = TaggedDictBuilder::new(span);
|
let mut network_idx = TaggedDictBuilder::new(tag);
|
||||||
network_idx.insert("incoming", Value::bytes(incoming));
|
network_idx.insert("incoming", Value::bytes(incoming));
|
||||||
network_idx.insert("outgoing", Value::bytes(outgoing));
|
network_idx.insert("outgoing", Value::bytes(outgoing));
|
||||||
network_idx.into_tagged_value()
|
network_idx.into_tagged_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sysinfo(span: Span) -> Vec<Tagged<Value>> {
|
async fn sysinfo(tag: Tag) -> Vec<Tagged<Value>> {
|
||||||
let mut sysinfo = TaggedDictBuilder::new(span);
|
let mut sysinfo = TaggedDictBuilder::new(tag);
|
||||||
|
|
||||||
sysinfo.insert_tagged("host", host(span).await);
|
sysinfo.insert_tagged("host", host(tag).await);
|
||||||
if let Some(cpu) = cpu(span).await {
|
if let Some(cpu) = cpu(tag).await {
|
||||||
sysinfo.insert_tagged("cpu", cpu);
|
sysinfo.insert_tagged("cpu", cpu);
|
||||||
}
|
}
|
||||||
sysinfo.insert("disks", disks(span).await);
|
sysinfo.insert("disks", disks(tag).await);
|
||||||
sysinfo.insert_tagged("mem", mem(span).await);
|
sysinfo.insert_tagged("mem", mem(tag).await);
|
||||||
sysinfo.insert("temp", temp(span).await);
|
sysinfo.insert("temp", temp(tag).await);
|
||||||
sysinfo.insert_tagged("net", net(span).await);
|
sysinfo.insert_tagged("net", net(tag).await);
|
||||||
|
|
||||||
vec![sysinfo.into_tagged_value()]
|
vec![sysinfo.into_tagged_value()]
|
||||||
}
|
}
|
||||||
|
@ -186,12 +186,10 @@ impl Plugin for Sys {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
||||||
Ok(block_on(sysinfo(
|
Ok(block_on(sysinfo(Tag::unknown_origin(callinfo.name_span)))
|
||||||
callinfo.name_span.unwrap_or_else(|| Span::unknown()),
|
.into_iter()
|
||||||
))
|
.map(|x| ReturnSuccess::value(x))
|
||||||
.into_iter()
|
.collect())
|
||||||
.map(|x| ReturnSuccess::value(x))
|
|
||||||
.collect())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter(&mut self, _: Tagged<Value>) -> Result<Vec<ReturnValue>, ShellError> {
|
fn filter(&mut self, _: Tagged<Value>) -> Result<Vec<ReturnValue>, ShellError> {
|
||||||
|
|
|
@ -210,10 +210,10 @@ fn scroll_view(s: &str) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn view_text_value(value: &Tagged<Value>, source_map: &SourceMap) {
|
fn view_text_value(value: &Tagged<Value>, source_map: &SourceMap) {
|
||||||
let value_span = value.span();
|
let value_origin = value.origin();
|
||||||
match value.item {
|
match value.item {
|
||||||
Value::Primitive(Primitive::String(ref s)) => {
|
Value::Primitive(Primitive::String(ref s)) => {
|
||||||
let source = value_span.source.map(|x| source_map.get(&x)).flatten();
|
let source = value_origin.map(|x| source_map.get(&x)).flatten();
|
||||||
|
|
||||||
if let Some(source) = source {
|
if let Some(source) = source {
|
||||||
let extension: Option<String> = match source {
|
let extension: Option<String> = match source {
|
||||||
|
|
|
@ -43,6 +43,7 @@ crate use crate::errors::ShellError;
|
||||||
crate use crate::object::meta::{Tag, Tagged, TaggedItem};
|
crate use crate::object::meta::{Tag, Tagged, TaggedItem};
|
||||||
crate use crate::object::types::ExtractType;
|
crate use crate::object::types::ExtractType;
|
||||||
crate use crate::object::{Primitive, Value};
|
crate use crate::object::{Primitive, Value};
|
||||||
|
crate use crate::shell::shell::Shell;
|
||||||
crate use crate::stream::{InputStream, OutputStream};
|
crate use crate::stream::{InputStream, OutputStream};
|
||||||
crate use crate::Span;
|
crate use crate::Span;
|
||||||
crate use crate::Text;
|
crate use crate::Text;
|
||||||
|
|
|
@ -7,7 +7,7 @@ use rustyline::line_buffer::LineBuffer;
|
||||||
#[derive(new)]
|
#[derive(new)]
|
||||||
crate struct NuCompleter {
|
crate struct NuCompleter {
|
||||||
pub file_completer: FilenameCompleter,
|
pub file_completer: FilenameCompleter,
|
||||||
pub commands: indexmap::IndexMap<String, Arc<dyn Command>>,
|
//pub commands: indexmap::IndexMap<String, Arc<dyn Command>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Completer for NuCompleter {
|
impl Completer for NuCompleter {
|
||||||
|
@ -19,7 +19,7 @@ impl Completer for NuCompleter {
|
||||||
pos: usize,
|
pos: usize,
|
||||||
context: &rustyline::Context,
|
context: &rustyline::Context,
|
||||||
) -> rustyline::Result<(usize, Vec<completion::Pair>)> {
|
) -> rustyline::Result<(usize, Vec<completion::Pair>)> {
|
||||||
let commands: Vec<String> = self.commands.keys().cloned().collect();
|
//let commands: Vec<String> = self.commands.keys().cloned().collect();
|
||||||
|
|
||||||
let mut completions = self.file_completer.complete(line, pos, context)?.1;
|
let mut completions = self.file_completer.complete(line, pos, context)?.1;
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ impl Completer for NuCompleter {
|
||||||
replace_pos -= 1;
|
replace_pos -= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
for command in commands.iter() {
|
for command in commands.iter() {
|
||||||
let mut pos = replace_pos;
|
let mut pos = replace_pos;
|
||||||
let mut matched = true;
|
let mut matched = true;
|
||||||
|
@ -73,6 +74,7 @@ impl Completer for NuCompleter {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
Ok((replace_pos, completions))
|
Ok((replace_pos, completions))
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,30 +2,23 @@ use crate::parser::nom_input;
|
||||||
use crate::parser::parse::token_tree::TokenNode;
|
use crate::parser::parse::token_tree::TokenNode;
|
||||||
use crate::parser::parse::tokens::RawToken;
|
use crate::parser::parse::tokens::RawToken;
|
||||||
use crate::parser::{Pipeline, PipelineElement};
|
use crate::parser::{Pipeline, PipelineElement};
|
||||||
use crate::prelude::*;
|
use crate::shell::shell::Shell;
|
||||||
use crate::shell::completer::NuCompleter;
|
|
||||||
use crate::Tagged;
|
use crate::Tagged;
|
||||||
use ansi_term::Color;
|
use ansi_term::Color;
|
||||||
use rustyline::completion::{self, Completer, FilenameCompleter};
|
use rustyline::completion::{self, Completer};
|
||||||
use rustyline::error::ReadlineError;
|
use rustyline::error::ReadlineError;
|
||||||
use rustyline::highlight::Highlighter;
|
use rustyline::highlight::Highlighter;
|
||||||
use rustyline::hint::{Hinter, HistoryHinter};
|
use rustyline::hint::Hinter;
|
||||||
use std::borrow::Cow::{self, Owned};
|
use std::borrow::Cow::{self, Owned};
|
||||||
|
use std::sync::{Arc, Mutex};
|
||||||
|
|
||||||
crate struct Helper {
|
crate struct Helper {
|
||||||
completer: NuCompleter,
|
helper: Arc<Mutex<Vec<Box<dyn Shell>>>>,
|
||||||
hinter: HistoryHinter,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Helper {
|
impl Helper {
|
||||||
crate fn new(commands: indexmap::IndexMap<String, Arc<dyn Command>>) -> Helper {
|
crate fn new(helper: Arc<Mutex<Vec<Box<dyn Shell>>>>) -> Helper {
|
||||||
Helper {
|
Helper { helper }
|
||||||
completer: NuCompleter {
|
|
||||||
file_completer: FilenameCompleter::new(),
|
|
||||||
commands,
|
|
||||||
},
|
|
||||||
hinter: HistoryHinter {},
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,13 +31,23 @@ impl Completer for Helper {
|
||||||
pos: usize,
|
pos: usize,
|
||||||
ctx: &rustyline::Context<'_>,
|
ctx: &rustyline::Context<'_>,
|
||||||
) -> Result<(usize, Vec<completion::Pair>), ReadlineError> {
|
) -> Result<(usize, Vec<completion::Pair>), ReadlineError> {
|
||||||
self.completer.complete(line, pos, ctx)
|
self.helper
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.complete(line, pos, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Hinter for Helper {
|
impl Hinter for Helper {
|
||||||
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
|
fn hint(&self, line: &str, pos: usize, ctx: &rustyline::Context<'_>) -> Option<String> {
|
||||||
self.hinter.hint(line, pos, ctx)
|
self.helper
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.last()
|
||||||
|
.unwrap()
|
||||||
|
.hint(line, pos, ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user