forked from extern/nushell
WIP
This commit is contained in:
parent
71adfb4cdc
commit
7b68739b52
@ -231,7 +231,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
||||
let last = env.back().unwrap();
|
||||
(last.obj().clone(), last.path().display().to_string())
|
||||
};
|
||||
let readline = match obj {
|
||||
let readline = match obj.item {
|
||||
Value::Filesystem => rl.readline(&format!(
|
||||
"{}{}> ",
|
||||
cwd,
|
||||
@ -396,7 +396,7 @@ async fn process_line(readline: Result<String, ReadlineError>, ctx: &mut Context
|
||||
}
|
||||
|
||||
(Some(ClassifiedCommand::Sink(left)), None) => {
|
||||
let input_vec: Vec<Value> = input.objects.into_vec().await;
|
||||
let input_vec: Vec<Spanned<Value>> = input.objects.into_vec().await;
|
||||
if let Err(err) = left.run(ctx, input_vec) {
|
||||
return LineResult::Error(line.clone(), err);
|
||||
}
|
||||
|
@ -22,7 +22,7 @@ pub fn autoview(args: SinkCommandArgs) -> Result<(), ShellError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn equal_shapes(input: &Vec<Value>) -> bool {
|
||||
fn equal_shapes(input: &Vec<Spanned<Value>>) -> bool {
|
||||
let mut items = input.iter();
|
||||
|
||||
let item = match items.next() {
|
||||
|
@ -6,8 +6,9 @@ use std::path::PathBuf;
|
||||
pub fn cd(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let env = args.env.lock().unwrap();
|
||||
let latest = env.back().unwrap();
|
||||
let obj = latest.obj;
|
||||
|
||||
match latest.obj {
|
||||
match obj.item {
|
||||
Value::Filesystem => {
|
||||
let cwd = latest.path().to_path_buf();
|
||||
|
||||
|
@ -59,24 +59,6 @@ impl ClassifiedInputStream {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn into_vec(self) -> impl std::future::Future<Output = Vec<Value>> {
|
||||
self.objects.into_vec()
|
||||
}
|
||||
|
||||
crate fn from_vec(stream: VecDeque<Value>) -> ClassifiedInputStream {
|
||||
ClassifiedInputStream {
|
||||
objects: stream.into(),
|
||||
stdin: None,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn from_list(stream: Vec<Value>) -> ClassifiedInputStream {
|
||||
ClassifiedInputStream {
|
||||
objects: stream.into(),
|
||||
stdin: None,
|
||||
}
|
||||
}
|
||||
|
||||
crate fn from_input_stream(stream: impl Into<InputStream>) -> ClassifiedInputStream {
|
||||
ClassifiedInputStream {
|
||||
objects: stream.into(),
|
||||
@ -111,7 +93,11 @@ crate struct SinkCommand {
|
||||
}
|
||||
|
||||
impl SinkCommand {
|
||||
crate fn run(self, context: &mut Context, input: Vec<Value>) -> Result<(), ShellError> {
|
||||
crate fn run(
|
||||
self,
|
||||
context: &mut Context,
|
||||
input: Vec<Spanned<Value>>,
|
||||
) -> Result<(), ShellError> {
|
||||
context.run_sink(self.command, self.name_span.clone(), self.args, input)
|
||||
}
|
||||
}
|
||||
@ -160,7 +146,11 @@ impl InternalCommand {
|
||||
}
|
||||
CommandAction::Exit => match context.env.lock().unwrap().pop_back() {
|
||||
Some(Environment {
|
||||
obj: Value::Filesystem,
|
||||
obj:
|
||||
Spanned {
|
||||
item: Value::Filesystem,
|
||||
..
|
||||
},
|
||||
..
|
||||
}) => std::process::exit(0),
|
||||
None => std::process::exit(-1),
|
||||
@ -199,7 +189,7 @@ impl ExternalCommand {
|
||||
stream_next: StreamNext,
|
||||
) -> Result<ClassifiedInputStream, ShellError> {
|
||||
let stdin = input.stdin;
|
||||
let inputs: Vec<Value> = input.objects.into_vec().await;
|
||||
let inputs: Vec<Spanned<Value>> = input.objects.into_vec().await;
|
||||
|
||||
trace!("-> {}", self.name);
|
||||
trace!("inputs = {:?}", inputs);
|
||||
|
@ -7,7 +7,7 @@ use crate::parser::{
|
||||
use crate::prelude::*;
|
||||
use getset::Getters;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{ops::Try, path::PathBuf};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Getters)]
|
||||
#[get = "crate"]
|
||||
@ -49,26 +49,26 @@ pub struct SinkCommandArgs {
|
||||
pub ctx: Context,
|
||||
pub name_span: Option<Span>,
|
||||
pub args: Args,
|
||||
pub input: Vec<Value>,
|
||||
pub input: Vec<Spanned<Value>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum CommandAction {
|
||||
ChangePath(PathBuf),
|
||||
Enter(Value),
|
||||
Enter(Spanned<Value>),
|
||||
Exit,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub enum ReturnSuccess {
|
||||
Value(Value),
|
||||
Value(Spanned<Value>),
|
||||
Action(CommandAction),
|
||||
}
|
||||
|
||||
pub type ReturnValue = Result<ReturnSuccess, ShellError>;
|
||||
|
||||
impl From<Value> for ReturnValue {
|
||||
fn from(input: Value) -> ReturnValue {
|
||||
impl From<Spanned<Value>> for ReturnValue {
|
||||
fn from(input: Spanned<Value>) -> ReturnValue {
|
||||
Ok(ReturnSuccess::Value(input))
|
||||
}
|
||||
}
|
||||
@ -78,8 +78,12 @@ impl ReturnSuccess {
|
||||
Ok(ReturnSuccess::Action(CommandAction::ChangePath(path)))
|
||||
}
|
||||
|
||||
pub fn value(input: Value) -> ReturnValue {
|
||||
Ok(ReturnSuccess::Value(input))
|
||||
pub fn value(input: impl Into<Spanned<Value>>) -> ReturnValue {
|
||||
Ok(ReturnSuccess::Value(input.into()))
|
||||
}
|
||||
|
||||
pub fn spanned_value(input: Value, span: Span) -> ReturnValue {
|
||||
Ok(ReturnSuccess::Value(Spanned::from_item(input, span)))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,4 +1,3 @@
|
||||
#[macro_use]
|
||||
use crate::prelude::*;
|
||||
|
||||
use crate::errors::ShellError;
|
||||
@ -44,7 +43,7 @@ impl Command for Config {
|
||||
}
|
||||
|
||||
pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let mut result = crate::object::config::config()?;
|
||||
let mut result = crate::object::config::config(args.name_span)?;
|
||||
|
||||
trace!("{:#?}", args.args.positional);
|
||||
trace!("{:#?}", args.args.named);
|
||||
@ -56,7 +55,7 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
.ok_or_else(|| ShellError::string(&format!("Missing key {} in config", key)))?;
|
||||
|
||||
return Ok(
|
||||
vec![value.clone()].into(), // futures::stream::once(futures::future::ready(ReturnSuccess::Value(value.clone()))).into(),
|
||||
stream![value.clone()], // futures::stream::once(futures::future::ready(ReturnSuccess::Value(value.clone()))).into(),
|
||||
);
|
||||
}
|
||||
|
||||
@ -66,16 +65,21 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
config::write_config(&result)?;
|
||||
|
||||
return Ok(stream![Value::Object(result.into())].from_input_stream());
|
||||
return Ok(
|
||||
stream![Spanned::from_item(Value::Object(result.into()), v.span())]
|
||||
.from_input_stream(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(_) = args.get("clear") {
|
||||
if let Some(c) = args.get("clear") {
|
||||
result.clear();
|
||||
|
||||
config::write_config(&result)?;
|
||||
|
||||
return Ok(stream![Value::Object(result.into())].from_input_stream());
|
||||
return Ok(
|
||||
stream![Spanned::from_item(Value::Object(result.into()), c.span())].from_input_stream(),
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(v) = args.get("remove") {
|
||||
@ -90,7 +94,7 @@ pub fn config(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
)));
|
||||
}
|
||||
|
||||
let obj = VecDeque::from_iter(vec![Value::Object(result.into())]);
|
||||
let obj = VecDeque::from_iter(vec![Value::Object(result.into()).spanned(v)]);
|
||||
return Ok(obj.from_input_stream());
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,7 @@ pub fn enter(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
let full_path = PathBuf::from(cwd);
|
||||
|
||||
let (file_extension, contents) = match &args.expect_nth(0)?.item {
|
||||
let (file_extension, contents, contents_span) = match &args.expect_nth(0)?.item {
|
||||
Value::Primitive(Primitive::String(s)) => fetch(&full_path, s, args.expect_nth(0)?.span)?,
|
||||
_ => {
|
||||
return Err(ShellError::labeled_error(
|
||||
@ -90,7 +90,7 @@ pub fn enter(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
};
|
||||
|
||||
stream.push_back(Ok(ReturnSuccess::Action(CommandAction::Enter(
|
||||
parse_as_value(file_extension, contents, span)?,
|
||||
parse_as_value(file_extension, contents, contents_span, span)?,
|
||||
))));
|
||||
|
||||
Ok(stream.into())
|
||||
|
@ -31,9 +31,9 @@ pub fn from_ini(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let span = args.name_span;
|
||||
Ok(out
|
||||
.values
|
||||
.map(move |a| match a {
|
||||
.map(move |a| match a.item {
|
||||
Value::Primitive(Primitive::String(s)) => match from_ini_string_to_value(s) {
|
||||
Ok(x) => Ok(ReturnSuccess::Value(x)),
|
||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||
Err(e) => Err(ShellError::maybe_labeled_error(
|
||||
"Could not parse as INI",
|
||||
format!("{:#?}", e),
|
||||
|
@ -12,7 +12,7 @@ fn convert_json_value_to_nu_value(v: &serde_hjson::Value) -> Value {
|
||||
serde_hjson::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))),
|
||||
serde_hjson::Value::Array(a) => Value::List(
|
||||
a.iter()
|
||||
.map(|x| convert_json_value_to_nu_value(x))
|
||||
.map(|x| convert_json_value_to_nu_value(x).spanned_unknown())
|
||||
.collect(),
|
||||
),
|
||||
serde_hjson::Value::Object(o) => {
|
||||
@ -35,9 +35,9 @@ pub fn from_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let span = args.name_span;
|
||||
Ok(out
|
||||
.values
|
||||
.map(move |a| match a {
|
||||
.map(move |a| match a.item {
|
||||
Value::Primitive(Primitive::String(s)) => match from_json_string_to_value(s) {
|
||||
Ok(x) => ReturnSuccess::value(x),
|
||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||
"Could not parse as JSON",
|
||||
"piped data failed JSON parse",
|
||||
|
@ -10,7 +10,7 @@ fn convert_toml_value_to_nu_value(v: &toml::Value) -> Value {
|
||||
toml::Value::String(s) => Value::Primitive(Primitive::String(String::from(s))),
|
||||
toml::Value::Array(a) => Value::List(
|
||||
a.iter()
|
||||
.map(|x| convert_toml_value_to_nu_value(x))
|
||||
.map(|x| convert_toml_value_to_nu_value(x).spanned_unknown())
|
||||
.collect(),
|
||||
),
|
||||
toml::Value::Datetime(dt) => Value::Primitive(Primitive::String(dt.to_string())),
|
||||
@ -34,9 +34,9 @@ pub fn from_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let span = args.name_span;
|
||||
Ok(out
|
||||
.values
|
||||
.map(move |a| match a {
|
||||
.map(move |a| match a.item {
|
||||
Value::Primitive(Primitive::String(s)) => match from_toml_string_to_value(s) {
|
||||
Ok(x) => ReturnSuccess::value(x),
|
||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||
"Could not parse as TOML",
|
||||
"piped data failed TOML parse",
|
||||
|
@ -10,7 +10,7 @@ fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>) -> Value {
|
||||
children_values.push(from_node_to_value(&c));
|
||||
}
|
||||
|
||||
let children_values: Vec<Value> = children_values
|
||||
let children_values: Vec<Spanned<Value>> = children_values
|
||||
.into_iter()
|
||||
.filter(|x| match x {
|
||||
Value::Primitive(Primitive::String(f)) => {
|
||||
@ -22,6 +22,7 @@ fn from_node_to_value<'a, 'd>(n: &roxmltree::Node<'a, 'd>) -> Value {
|
||||
}
|
||||
_ => true,
|
||||
})
|
||||
.map(|v| v.spanned_unknown())
|
||||
.collect();
|
||||
|
||||
let mut collected = Dictionary::default();
|
||||
@ -53,9 +54,9 @@ pub fn from_xml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let span = args.name_span;
|
||||
Ok(out
|
||||
.values
|
||||
.map(move |a| match a {
|
||||
.map(move |a| match a.item {
|
||||
Value::Primitive(Primitive::String(s)) => match from_xml_string_to_value(s) {
|
||||
Ok(x) => ReturnSuccess::value(x),
|
||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||
"Could not parse as XML",
|
||||
"piped data failed XML parse",
|
||||
|
@ -14,7 +14,7 @@ fn convert_yaml_value_to_nu_value(v: &serde_yaml::Value) -> Value {
|
||||
serde_yaml::Value::String(s) => Value::string(s),
|
||||
serde_yaml::Value::Sequence(a) => Value::List(
|
||||
a.iter()
|
||||
.map(|x| convert_yaml_value_to_nu_value(x))
|
||||
.map(|x| convert_yaml_value_to_nu_value(x).spanned_unknown())
|
||||
.collect(),
|
||||
),
|
||||
serde_yaml::Value::Mapping(t) => {
|
||||
@ -44,9 +44,9 @@ pub fn from_yaml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let span = args.name_span;
|
||||
Ok(out
|
||||
.values
|
||||
.map(move |a| match a {
|
||||
.map(move |a| match a.item {
|
||||
Value::Primitive(Primitive::String(s)) => match from_yaml_string_to_value(s) {
|
||||
Ok(x) => ReturnSuccess::value(x),
|
||||
Ok(x) => ReturnSuccess::value(x.spanned(a.span)),
|
||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||
"Could not parse as YAML",
|
||||
"piped data failed YAML parse",
|
||||
|
@ -3,7 +3,7 @@ use crate::object::Value;
|
||||
use crate::parser::Span;
|
||||
use crate::prelude::*;
|
||||
|
||||
fn get_member(path: &str, span: Span, obj: &Value) -> Result<Value, ShellError> {
|
||||
fn get_member(path: &str, span: Span, obj: &Spanned<Value>) -> Result<Spanned<Value>, ShellError> {
|
||||
let mut current = obj;
|
||||
for p in path.split(".") {
|
||||
match current.get_data_by_key(p) {
|
||||
@ -18,7 +18,7 @@ fn get_member(path: &str, span: Span, obj: &Value) -> Result<Value, ShellError>
|
||||
}
|
||||
}
|
||||
|
||||
Ok(current.copy())
|
||||
Ok(current.clone())
|
||||
}
|
||||
|
||||
pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
@ -56,12 +56,15 @@ pub fn get(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let mut result = VecDeque::new();
|
||||
for field in &fields {
|
||||
match get_member(&field.0, field.1, &item) {
|
||||
Ok(Value::List(l)) => {
|
||||
Ok(Spanned {
|
||||
item: Value::List(l),
|
||||
..
|
||||
}) => {
|
||||
for item in l {
|
||||
result.push_back(ReturnSuccess::value(item.copy()));
|
||||
result.push_back(ReturnSuccess::value(item.clone()));
|
||||
}
|
||||
}
|
||||
Ok(x) => result.push_back(ReturnSuccess::value(x.copy())),
|
||||
Ok(x) => result.push_back(ReturnSuccess::value(x.clone())),
|
||||
Err(_) => {}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ pub fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
let stream = input
|
||||
.values
|
||||
.map(move |v| match v {
|
||||
.map(move |v| match v.item {
|
||||
Value::Primitive(Primitive::String(s)) => {
|
||||
let split_result: Vec<_> = s.lines().filter(|s| s.trim() != "").collect();
|
||||
|
||||
@ -19,9 +19,9 @@ pub fn lines(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
let mut result = VecDeque::new();
|
||||
for s in split_result {
|
||||
result.push_back(ReturnSuccess::value(Value::Primitive(Primitive::String(
|
||||
s.into(),
|
||||
))));
|
||||
result.push_back(ReturnSuccess::value(
|
||||
Value::Primitive(Primitive::String(s.into())).spanned_unknown(),
|
||||
));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
@ -18,7 +18,7 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match obj {
|
||||
match obj.item {
|
||||
Value::Filesystem => {
|
||||
let entries = std::fs::read_dir(&full_path);
|
||||
|
||||
@ -45,7 +45,7 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
for entry in entries {
|
||||
let value = Value::Object(dir_entry_dict(&entry?)?);
|
||||
shell_entries.push_back(ReturnSuccess::value(value))
|
||||
shell_entries.push_back(ReturnSuccess::value(value.spanned_unknown()))
|
||||
}
|
||||
Ok(shell_entries.to_output_stream())
|
||||
}
|
||||
@ -125,9 +125,12 @@ pub fn ls(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
}
|
||||
}
|
||||
match viewed {
|
||||
Value::List(l) => {
|
||||
Spanned {
|
||||
item: Value::List(l),
|
||||
..
|
||||
} => {
|
||||
for item in l {
|
||||
entries.push_back(ReturnSuccess::value(item.copy()));
|
||||
entries.push_back(ReturnSuccess::value(item.clone()));
|
||||
}
|
||||
}
|
||||
x => {
|
||||
|
@ -49,7 +49,7 @@ macro_rules! command {
|
||||
positional: vec![$($mandatory_positional)*],
|
||||
rest_positional: false,
|
||||
named: {
|
||||
use $crate::parser::registry::{NamedType, NamedValue};
|
||||
use $crate::parser::registry::NamedType;
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut named: indexmap::IndexMap<String, NamedType> = indexmap::IndexMap::new();
|
||||
@ -261,10 +261,10 @@ macro_rules! command {
|
||||
|
||||
Extract {
|
||||
$($extract:tt)* {
|
||||
use std::convert::TryInto;
|
||||
use $crate::object::types::ExtractType;
|
||||
let value = $args.expect_nth($($positional_count)*)?;
|
||||
let value = $param_kind.check(value)?;
|
||||
value.extract()
|
||||
// let value = $param_kind.check(value)?;
|
||||
$param_kind::extract(value)?
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -21,7 +21,7 @@ command! {
|
||||
|
||||
let full_path = PathBuf::from(cwd);
|
||||
|
||||
let (file_extension, contents) = match &args.expect_nth(0)?.item {
|
||||
let (file_extension, contents, contents_span) = match &args.expect_nth(0)?.item {
|
||||
Value::Primitive(Primitive::String(s)) => fetch(&full_path, s, args.expect_nth(0)?.span)?,
|
||||
_ => {
|
||||
return Err(ShellError::labeled_error(
|
||||
@ -64,6 +64,7 @@ command! {
|
||||
stream.push_back(ReturnSuccess::value(parse_as_value(
|
||||
file_extension,
|
||||
contents,
|
||||
contents_span,
|
||||
span,
|
||||
)?));
|
||||
|
||||
@ -75,7 +76,7 @@ pub fn fetch(
|
||||
cwd: &PathBuf,
|
||||
location: &str,
|
||||
span: Span,
|
||||
) -> Result<(Option<String>, String), ShellError> {
|
||||
) -> Result<(Option<String>, String, Span), ShellError> {
|
||||
let mut cwd = cwd.clone();
|
||||
if location.starts_with("http:") || location.starts_with("https:") {
|
||||
let response = reqwest::get(location);
|
||||
@ -106,7 +107,7 @@ pub fn fetch(
|
||||
None => path_extension,
|
||||
};
|
||||
|
||||
Ok((extension, Value::string(s)))
|
||||
Ok((extension, s, span))
|
||||
}
|
||||
Err(_) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
@ -131,7 +132,8 @@ pub fn fetch(
|
||||
Ok(s) => Ok((
|
||||
cwd.extension()
|
||||
.map(|name| name.to_string_lossy().to_string()),
|
||||
Value::string(s),
|
||||
s,
|
||||
span,
|
||||
)),
|
||||
Err(_) => Ok((None, Value::Binary(bytes))),
|
||||
},
|
||||
@ -149,10 +151,12 @@ pub fn fetch(
|
||||
pub fn parse_as_value(
|
||||
extension: Option<String>,
|
||||
contents: String,
|
||||
contents_span: Span,
|
||||
name_span: Option<Span>,
|
||||
) -> Result<Value, ShellError> {
|
||||
) -> Result<Spanned<Value>, ShellError> {
|
||||
match extension {
|
||||
Some(x) if x == "toml" => crate::commands::from_toml::from_toml_string_to_value(contents)
|
||||
.map(|c| c.spanned(contents_span))
|
||||
.map_err(move |_| {
|
||||
ShellError::maybe_labeled_error(
|
||||
"Could not open as TOML",
|
||||
@ -161,6 +165,7 @@ pub fn parse_as_value(
|
||||
)
|
||||
}),
|
||||
Some(x) if x == "json" => crate::commands::from_json::from_json_string_to_value(contents)
|
||||
.map(|c| c.spanned(contents_span))
|
||||
.map_err(move |_| {
|
||||
ShellError::maybe_labeled_error(
|
||||
"Could not open as JSON",
|
||||
@ -169,6 +174,7 @@ pub fn parse_as_value(
|
||||
)
|
||||
}),
|
||||
Some(x) if x == "ini" => crate::commands::from_ini::from_ini_string_to_value(contents)
|
||||
.map(|c| c.spanned(contents_span))
|
||||
.map_err(move |_| {
|
||||
ShellError::maybe_labeled_error(
|
||||
"Could not open as INI",
|
||||
@ -177,6 +183,7 @@ pub fn parse_as_value(
|
||||
)
|
||||
}),
|
||||
Some(x) if x == "xml" => crate::commands::from_xml::from_xml_string_to_value(contents)
|
||||
.map(|c| c.spanned(contents_span))
|
||||
.map_err(move |_| {
|
||||
ShellError::maybe_labeled_error(
|
||||
"Could not open as XML",
|
||||
@ -185,6 +192,7 @@ pub fn parse_as_value(
|
||||
)
|
||||
}),
|
||||
Some(x) if x == "yml" => crate::commands::from_yaml::from_yaml_string_to_value(contents)
|
||||
.map(|c| c.spanned(contents_span))
|
||||
.map_err(move |_| {
|
||||
ShellError::maybe_labeled_error(
|
||||
"Could not open as YAML",
|
||||
@ -193,6 +201,7 @@ pub fn parse_as_value(
|
||||
)
|
||||
}),
|
||||
Some(x) if x == "yaml" => crate::commands::from_yaml::from_yaml_string_to_value(contents)
|
||||
.map(|c| c.spanned(contents_span))
|
||||
.map_err(move |_| {
|
||||
ShellError::maybe_labeled_error(
|
||||
"Could not open as YAML",
|
||||
@ -200,6 +209,6 @@ pub fn parse_as_value(
|
||||
name_span,
|
||||
)
|
||||
}),
|
||||
_ => Ok(Value::string(contents)),
|
||||
_ => Ok(Value::string(contents).spanned(contents_span)),
|
||||
}
|
||||
}
|
||||
|
@ -14,11 +14,11 @@ pub fn pick(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
let fields: Result<Vec<String>, _> = args.positional_iter().map(|a| a.as_string()).collect();
|
||||
let fields = fields?;
|
||||
let input = args.input;
|
||||
|
||||
let objects = args
|
||||
.input
|
||||
let objects = input
|
||||
.values
|
||||
.map(move |item| Value::Object(select_fields(&item, &fields)));
|
||||
.map(move |value| Value::Object(select_fields(&value.item, &fields)).spanned(value.span));
|
||||
|
||||
Ok(objects.from_input_stream())
|
||||
}
|
||||
|
@ -50,14 +50,17 @@ pub fn filter_plugin(path: String, args: CommandArgs) -> Result<OutputStream, Sh
|
||||
stdin.write(format!("{}\n", request_raw).as_bytes())?;
|
||||
}
|
||||
|
||||
let mut eos = VecDeque::new();
|
||||
eos.push_back(Value::Primitive(Primitive::EndOfStream));
|
||||
let mut eos: VecDeque<Spanned<Value>> = VecDeque::new();
|
||||
eos.push_back(Value::Primitive(Primitive::EndOfStream).spanned_unknown());
|
||||
|
||||
let stream = args
|
||||
.input
|
||||
.chain(eos)
|
||||
.map(move |v| match v {
|
||||
Value::Primitive(Primitive::EndOfStream) => {
|
||||
Spanned {
|
||||
item: Value::Primitive(Primitive::EndOfStream),
|
||||
..
|
||||
} => {
|
||||
let stdin = child.stdin.as_mut().expect("Failed to open stdin");
|
||||
let stdout = child.stdout.as_mut().expect("Failed to open stdout");
|
||||
|
||||
|
@ -4,14 +4,14 @@ use crate::object::Value;
|
||||
use crate::prelude::*;
|
||||
use sysinfo::{RefreshKind, SystemExt};
|
||||
|
||||
pub fn ps(_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
pub fn ps(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let mut system = sysinfo::System::new_with_specifics(RefreshKind::new().with_processes());
|
||||
system.refresh_processes();
|
||||
let list = system.get_process_list();
|
||||
|
||||
let list = list
|
||||
.into_iter()
|
||||
.map(|(_, process)| Value::Object(process_dict(process)))
|
||||
.map(|(item, process)| Value::Object(process_dict(process)).spanned(args.name_span))
|
||||
.collect::<VecDeque<_>>();
|
||||
|
||||
Ok(list.from_input_stream())
|
||||
|
@ -18,7 +18,7 @@ pub fn reject(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let stream = args
|
||||
.input
|
||||
.values
|
||||
.map(move |item| Value::Object(reject_fields(&item, &fields)));
|
||||
.map(move |item| Value::Object(reject_fields(&item, &fields)).spanned(args.name_span));
|
||||
|
||||
Ok(stream.from_input_stream())
|
||||
}
|
||||
|
@ -24,20 +24,20 @@ pub fn size(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
let mut contents = String::new();
|
||||
|
||||
let mut list = VecDeque::new();
|
||||
for name in args.positional_iter() {
|
||||
let name = name.as_string()?;
|
||||
let mut list: VecDeque<ReturnValue> = VecDeque::new();
|
||||
for spanned_name in args.positional_iter() {
|
||||
let name = spanned_name.as_string()?;
|
||||
let path = cwd.join(&name);
|
||||
let mut file = File::open(path)?;
|
||||
file.read_to_string(&mut contents)?;
|
||||
list.push_back(count(&name, &contents));
|
||||
list.push_back(count(&name, &contents).spanned(spanned_name).into());
|
||||
contents.clear();
|
||||
}
|
||||
|
||||
Ok(list.to_output_stream())
|
||||
}
|
||||
|
||||
fn count(name: &str, contents: &str) -> ReturnValue {
|
||||
fn count(name: &str, contents: &str) -> Value {
|
||||
let mut lines: i64 = 0;
|
||||
let mut words: i64 = 0;
|
||||
let mut chars: i64 = 0;
|
||||
@ -69,5 +69,5 @@ fn count(name: &str, contents: &str) -> ReturnValue {
|
||||
dict.add("chars", Value::int(chars));
|
||||
dict.add("max length", Value::int(bytes));
|
||||
|
||||
ReturnSuccess::value(Value::Object(dict))
|
||||
Value::Object(dict)
|
||||
}
|
||||
|
@ -11,8 +11,8 @@ pub fn sort_by(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
vec.sort_by_key(|item| {
|
||||
fields
|
||||
.iter()
|
||||
.map(|f| item.get_data_by_key(f).map(|i| i.copy()))
|
||||
.collect::<Vec<Option<Value>>>()
|
||||
.map(|f| item.get_data_by_key(f).map(|i| i.clone()))
|
||||
.collect::<Vec<Option<Spanned<Value>>>>()
|
||||
});
|
||||
|
||||
vec.into_iter().collect::<VecDeque<_>>()
|
||||
|
@ -21,7 +21,7 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
Ok(input
|
||||
.values
|
||||
.map(move |v| match v {
|
||||
.map(move |v| match v.item {
|
||||
Value::Primitive(Primitive::String(s)) => {
|
||||
let splitter = positional[0].as_string().unwrap().replace("\\n", "\n");
|
||||
trace!("splitting with {:?}", splitter);
|
||||
@ -40,7 +40,7 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
for (&k, v) in split_result.iter().zip(gen_columns.iter()) {
|
||||
dict.add(v.clone(), Value::Primitive(Primitive::String(k.into())));
|
||||
}
|
||||
ReturnSuccess::value(Value::Object(dict))
|
||||
ReturnSuccess::value(Value::Object(dict).spanned(v.span))
|
||||
} else if split_result.len() == (positional.len() - 1) {
|
||||
let mut dict = crate::object::Dictionary::default();
|
||||
for (&k, v) in split_result.iter().zip(positional.iter().skip(1)) {
|
||||
@ -49,7 +49,7 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
Value::Primitive(Primitive::String(k.into())),
|
||||
);
|
||||
}
|
||||
ReturnSuccess::value(Value::Object(dict))
|
||||
ReturnSuccess::value(Value::Object(dict).spanned(v.span))
|
||||
} else {
|
||||
let mut dict = crate::object::Dictionary::default();
|
||||
for k in positional.iter().skip(1) {
|
||||
@ -58,7 +58,7 @@ pub fn split_column(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
Value::Primitive(Primitive::String("".into())),
|
||||
);
|
||||
}
|
||||
ReturnSuccess::value(Value::Object(dict))
|
||||
ReturnSuccess::value(Value::Object(dict).spanned(v.span))
|
||||
}
|
||||
}
|
||||
_ => Err(ShellError::maybe_labeled_error(
|
||||
|
@ -22,7 +22,7 @@ pub fn split_row(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
let stream = input
|
||||
.values
|
||||
.map(move |v| match v {
|
||||
.map(move |v| match v.item {
|
||||
Value::Primitive(Primitive::String(s)) => {
|
||||
let splitter = positional[0].as_string().unwrap().replace("\\n", "\n");
|
||||
trace!("splitting with {:?}", splitter);
|
||||
@ -32,9 +32,9 @@ pub fn split_row(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
let mut result = VecDeque::new();
|
||||
for s in split_result {
|
||||
result.push_back(ReturnSuccess::value(Value::Primitive(Primitive::String(
|
||||
s.into(),
|
||||
))));
|
||||
result.push_back(ReturnSuccess::value(
|
||||
Value::Primitive(Primitive::String(s.into())).spanned(v.span),
|
||||
));
|
||||
}
|
||||
result
|
||||
}
|
||||
|
@ -1,95 +1,53 @@
|
||||
use crate::errors::ShellError;
|
||||
use crate::object::base::OF64;
|
||||
use crate::object::Dictionary;
|
||||
use crate::object::SpannedDictBuilder;
|
||||
use crate::object::{Primitive, Value};
|
||||
use crate::prelude::*;
|
||||
use log::trace;
|
||||
use sys_info::*;
|
||||
use sysinfo::{ComponentExt, DiskExt, NetworkExt, RefreshKind, SystemExt};
|
||||
|
||||
pub fn sysinfo(_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let mut idx = indexmap::IndexMap::new();
|
||||
pub fn sysinfo(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let mut idx = SpannedDictBuilder::new(args.name_span);
|
||||
|
||||
if let (Ok(name), Ok(version)) = (os_type(), os_release()) {
|
||||
let mut os_idx = indexmap::IndexMap::new();
|
||||
os_idx.insert(
|
||||
"name".to_string(),
|
||||
Value::Primitive(Primitive::String(name)),
|
||||
);
|
||||
os_idx.insert(
|
||||
"version".to_string(),
|
||||
Value::Primitive(Primitive::String(version)),
|
||||
);
|
||||
let mut os_idx = SpannedDictBuilder::new(args.name_span);
|
||||
os_idx.insert("name", Primitive::String(name));
|
||||
os_idx.insert("version", Primitive::String(version));
|
||||
|
||||
idx.insert("os".to_string(), Value::Object(Dictionary::from(os_idx)));
|
||||
idx.insert_spanned("os", os_idx.into_spanned_value());
|
||||
}
|
||||
|
||||
if let (Ok(num_cpu), Ok(cpu_speed)) = (cpu_num(), cpu_speed()) {
|
||||
let mut cpu_idx = indexmap::IndexMap::new();
|
||||
cpu_idx.insert(
|
||||
"num".to_string(),
|
||||
Value::Primitive(Primitive::Int(num_cpu as i64)),
|
||||
);
|
||||
cpu_idx.insert(
|
||||
"speed".to_string(),
|
||||
Value::Primitive(Primitive::Int(cpu_speed as i64)),
|
||||
);
|
||||
let mut cpu_idx = SpannedDictBuilder::new(args.name_span);
|
||||
cpu_idx.insert("num", Primitive::Int(num_cpu as i64));
|
||||
cpu_idx.insert("speed", Primitive::Int(cpu_speed as i64));
|
||||
|
||||
idx.insert("cpu".to_string(), Value::Object(Dictionary::from(cpu_idx)));
|
||||
idx.insert_spanned("cpu", cpu_idx);
|
||||
}
|
||||
|
||||
if let Ok(x) = loadavg() {
|
||||
let mut load_idx = indexmap::IndexMap::new();
|
||||
load_idx.insert(
|
||||
"1min".to_string(),
|
||||
Value::Primitive(Primitive::Float(OF64::from(x.one))),
|
||||
);
|
||||
load_idx.insert(
|
||||
"5min".to_string(),
|
||||
Value::Primitive(Primitive::Float(OF64::from(x.five))),
|
||||
);
|
||||
load_idx.insert(
|
||||
"15min".to_string(),
|
||||
Value::Primitive(Primitive::Float(OF64::from(x.fifteen))),
|
||||
);
|
||||
let mut load_idx = SpannedDictBuilder::new(args.name_span);
|
||||
|
||||
idx.insert(
|
||||
"load avg".to_string(),
|
||||
Value::Object(Dictionary::from(load_idx)),
|
||||
);
|
||||
load_idx.insert("1min", Primitive::Float(OF64::from(x.one)));
|
||||
load_idx.insert("5min", Primitive::Float(OF64::from(x.five)));
|
||||
load_idx.insert("15min", Primitive::Float(OF64::from(x.fifteen)));
|
||||
|
||||
idx.insert_spanned("load avg", load_idx);
|
||||
}
|
||||
|
||||
if let Ok(x) = mem_info() {
|
||||
let mut mem_idx = indexmap::IndexMap::new();
|
||||
mem_idx.insert(
|
||||
"total".to_string(),
|
||||
Value::Primitive(Primitive::Bytes(x.total as u64 * 1024)),
|
||||
);
|
||||
mem_idx.insert(
|
||||
"free".to_string(),
|
||||
Value::Primitive(Primitive::Bytes(x.free as u64 * 1024)),
|
||||
);
|
||||
mem_idx.insert(
|
||||
"avail".to_string(),
|
||||
Value::Primitive(Primitive::Bytes(x.avail as u64 * 1024)),
|
||||
);
|
||||
mem_idx.insert(
|
||||
"buffers".to_string(),
|
||||
Value::Primitive(Primitive::Bytes(x.buffers as u64 * 1024)),
|
||||
);
|
||||
mem_idx.insert(
|
||||
"cached".to_string(),
|
||||
Value::Primitive(Primitive::Bytes(x.cached as u64 * 1024)),
|
||||
);
|
||||
mem_idx.insert(
|
||||
"swap total".to_string(),
|
||||
Value::Primitive(Primitive::Bytes(x.swap_total as u64 * 1024)),
|
||||
);
|
||||
mem_idx.insert(
|
||||
"swap free".to_string(),
|
||||
Value::Primitive(Primitive::Bytes(x.swap_free as u64 * 1024)),
|
||||
);
|
||||
let mut mem_idx = SpannedDictBuilder::new(args.name_span);
|
||||
|
||||
idx.insert("mem".to_string(), Value::Object(Dictionary::from(mem_idx)));
|
||||
mem_idx.insert("total", Primitive::Bytes(x.total as u64 * 1024));
|
||||
mem_idx.insert("free", Primitive::Bytes(x.free as u64 * 1024));
|
||||
mem_idx.insert("avail", Primitive::Bytes(x.avail as u64 * 1024));
|
||||
mem_idx.insert("buffers", Primitive::Bytes(x.buffers as u64 * 1024));
|
||||
mem_idx.insert("cached", Primitive::Bytes(x.cached as u64 * 1024));
|
||||
mem_idx.insert("swap total", Primitive::Bytes(x.swap_total as u64 * 1024));
|
||||
mem_idx.insert("swap free", Primitive::Bytes(x.swap_free as u64 * 1024));
|
||||
|
||||
idx.insert_spanned("mem", mem_idx);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -107,57 +65,42 @@ pub fn sysinfo(_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
*/
|
||||
|
||||
if let Ok(x) = hostname() {
|
||||
idx.insert(
|
||||
"hostname".to_string(),
|
||||
Value::Primitive(Primitive::String(x)),
|
||||
);
|
||||
idx.insert("hostname", Primitive::String(x));
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
{
|
||||
if let Ok(x) = boottime() {
|
||||
let mut boottime_idx = indexmap::IndexMap::new();
|
||||
boottime_idx.insert(
|
||||
"days".to_string(),
|
||||
Value::Primitive(Primitive::Int(x.tv_sec / (24 * 3600))),
|
||||
);
|
||||
boottime_idx.insert(
|
||||
"hours".to_string(),
|
||||
Value::Primitive(Primitive::Int((x.tv_sec / 3600) % 24)),
|
||||
);
|
||||
boottime_idx.insert(
|
||||
"mins".to_string(),
|
||||
Value::Primitive(Primitive::Int((x.tv_sec / 60) % 60)),
|
||||
);
|
||||
let mut boottime_idx = SpannedDictBuilder::new(args.name_span);
|
||||
boottime_idx.insert("days", Primitive::Int(x.tv_sec / (24 * 3600)));
|
||||
boottime_idx.insert("hours", Primitive::Int((x.tv_sec / 3600) % 24));
|
||||
boottime_idx.insert("mins", Primitive::Int((x.tv_sec / 60) % 60));
|
||||
|
||||
idx.insert(
|
||||
"uptime".to_string(),
|
||||
Value::Object(Dictionary::from(boottime_idx)),
|
||||
);
|
||||
idx.insert("uptime", boottime_idx);
|
||||
}
|
||||
}
|
||||
|
||||
let system = sysinfo::System::new_with_specifics(RefreshKind::everything().without_processes());
|
||||
let components_list = system.get_components_list();
|
||||
if components_list.len() > 0 {
|
||||
let mut v = vec![];
|
||||
let mut v: Vec<Spanned<Value>> = vec![];
|
||||
for component in components_list {
|
||||
let mut component_idx = indexmap::IndexMap::new();
|
||||
let mut component_idx = SpannedDictBuilder::new(args.name_span);
|
||||
component_idx.insert("name", Primitive::String(component.get_label().to_string()));
|
||||
component_idx.insert(
|
||||
"name".to_string(),
|
||||
Value::string(component.get_label().to_string()),
|
||||
"temp",
|
||||
Primitive::Float(OF64::from(component.get_temperature() as f64)),
|
||||
);
|
||||
component_idx.insert(
|
||||
"temp".to_string(),
|
||||
Value::float(component.get_temperature() as f64),
|
||||
"max",
|
||||
Primitive::Float(OF64::from(component.get_max() as f64)),
|
||||
);
|
||||
component_idx.insert("max".to_string(), Value::float(component.get_max() as f64));
|
||||
if let Some(critical) = component.get_critical() {
|
||||
component_idx.insert("critical".to_string(), Value::float(critical as f64));
|
||||
component_idx.insert("critical", Primitive::Float(OF64::from(critical as f64)));
|
||||
}
|
||||
v.push(Value::Object(Dictionary::from(component_idx)));
|
||||
v.push(component_idx.into());
|
||||
}
|
||||
idx.insert("temps".to_string(), Value::List(v));
|
||||
idx.insert("temps", Value::List(v));
|
||||
}
|
||||
|
||||
let disks = system.get_disks();
|
||||
@ -165,38 +108,26 @@ pub fn sysinfo(_args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let mut v = vec![];
|
||||
|
||||
for disk in disks {
|
||||
let mut disk_idx = indexmap::IndexMap::new();
|
||||
disk_idx.insert(
|
||||
"name".to_string(),
|
||||
Value::string(disk.get_name().to_string_lossy()),
|
||||
);
|
||||
disk_idx.insert(
|
||||
"available".to_string(),
|
||||
Value::bytes(disk.get_available_space()),
|
||||
);
|
||||
disk_idx.insert("total".to_string(), Value::bytes(disk.get_total_space()));
|
||||
v.push(Value::Object(Dictionary::from(disk_idx)));
|
||||
let mut disk_idx = SpannedDictBuilder::new(args.name_span);
|
||||
disk_idx.insert("name", Value::string(disk.get_name().to_string_lossy()));
|
||||
disk_idx.insert("available", Value::bytes(disk.get_available_space()));
|
||||
disk_idx.insert("total", Value::bytes(disk.get_total_space()));
|
||||
v.push(disk_idx.into());
|
||||
}
|
||||
|
||||
idx.insert("disks".to_string(), Value::List(v));
|
||||
idx.insert("disks", Value::List(v));
|
||||
}
|
||||
|
||||
let network = system.get_network();
|
||||
let incoming = network.get_income();
|
||||
let outgoing = network.get_outcome();
|
||||
|
||||
let mut network_idx = indexmap::IndexMap::new();
|
||||
network_idx.insert("incoming".to_string(), Value::bytes(incoming));
|
||||
network_idx.insert("outgoing".to_string(), Value::bytes(outgoing));
|
||||
idx.insert(
|
||||
"network".to_string(),
|
||||
Value::Object(Dictionary::from(network_idx)),
|
||||
);
|
||||
let mut network_idx = SpannedDictBuilder::new(args.name_span);
|
||||
network_idx.insert("incoming", Value::bytes(incoming));
|
||||
network_idx.insert("outgoing", Value::bytes(outgoing));
|
||||
idx.insert_spanned("network", network_idx);
|
||||
|
||||
// println!("{:#?}", system.get_network());
|
||||
|
||||
let mut stream = VecDeque::new();
|
||||
stream.push_back(Value::Object(Dictionary::from(idx)));
|
||||
let mut stream = stream![idx.into_spanned_value()];
|
||||
|
||||
Ok(stream.from_input_stream())
|
||||
}
|
||||
|
@ -5,7 +5,7 @@ pub fn to_array(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let out = args.input.values.collect();
|
||||
|
||||
Ok(out
|
||||
.map(|vec: Vec<_>| stream![Value::List(vec)])
|
||||
.map(|vec: Vec<_>| stream![Value::List(vec).spanned_unknown()]) // TODO: args.input should have a span
|
||||
.flatten_stream()
|
||||
.from_input_stream())
|
||||
}
|
||||
|
@ -45,15 +45,16 @@ pub fn to_json(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let out = args.input;
|
||||
let span = args.name_span;
|
||||
Ok(out
|
||||
.map(
|
||||
move |a| match serde_json::to_string(&value_to_json_value(&a)) {
|
||||
Ok(x) => Ok(ReturnValue::Value(Value::Primitive(Primitive::String(x)))),
|
||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||
"Can not convert to JSON string",
|
||||
"can not convert piped data to JSON string",
|
||||
span,
|
||||
)),
|
||||
},
|
||||
)
|
||||
.boxed())
|
||||
.values
|
||||
.map(move |a| match serde_json::to_string(&a) {
|
||||
Ok(x) => {
|
||||
ReturnSuccess::value(Value::Primitive(Primitive::String(x)).spanned(args.name_span))
|
||||
}
|
||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||
"Can not convert to JSON string",
|
||||
"can not convert piped data to JSON string",
|
||||
span,
|
||||
)),
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
|
@ -37,7 +37,9 @@ pub fn to_toml(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
Ok(out
|
||||
.values
|
||||
.map(move |a| match toml::to_string(&a) {
|
||||
Ok(x) => ReturnSuccess::value(Value::Primitive(Primitive::String(x))),
|
||||
Ok(x) => {
|
||||
ReturnSuccess::value(Value::Primitive(Primitive::String(x)).spanned(args.name_span))
|
||||
}
|
||||
Err(_) => Err(ShellError::maybe_labeled_error(
|
||||
"Can not convert to TOML string",
|
||||
"can not convert piped data to TOML string",
|
||||
|
@ -10,15 +10,14 @@ pub fn trim(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
|
||||
Ok(input
|
||||
.values
|
||||
.map(move |v| match v {
|
||||
Value::Primitive(Primitive::String(s)) => {
|
||||
ReturnSuccess::value(Value::Primitive(Primitive::String(s.trim().into())))
|
||||
}
|
||||
_ => Err(ShellError::maybe_labeled_error(
|
||||
"Expected string values from pipeline",
|
||||
"expects strings from pipeline",
|
||||
span,
|
||||
)),
|
||||
})
|
||||
.map(move |v| ReturnSuccess::value(String::check(&v)?.clone()))
|
||||
// Value::Primitive(Primitive::String(s)) => {
|
||||
// ReturnSuccess::value(Value::Primitive(Primitive::String(s.trim().into())))
|
||||
// }
|
||||
// _ => Err(ShellError::maybe_labeled_error(
|
||||
// "Expected string values from pipeline",
|
||||
// "expects strings from pipeline",
|
||||
// span,
|
||||
// )),
|
||||
.to_output_stream())
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::errors::ShellError;
|
||||
use crate::object::types::*;
|
||||
use crate::object::Block;
|
||||
use crate::prelude::*;
|
||||
use futures::future::ready;
|
||||
use log::trace;
|
||||
@ -13,7 +13,7 @@ command! {
|
||||
|
||||
let return_value = match result {
|
||||
Err(err) => Some(Err(err)),
|
||||
Ok(v) if v.is_true() => Some(Ok(ReturnSuccess::Value(item.copy()))),
|
||||
Ok(v) if v.is_true() => Some(Ok(ReturnSuccess::Value(item.clone()))),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
|
@ -54,7 +54,7 @@ impl Context {
|
||||
command: Arc<dyn Sink>,
|
||||
name_span: Option<Span>,
|
||||
args: Args,
|
||||
input: Vec<Value>,
|
||||
input: Vec<Spanned<Value>>,
|
||||
) -> Result<(), ShellError> {
|
||||
let command_args = SinkCommandArgs {
|
||||
ctx: self.clone(),
|
||||
|
7
src/env/environment.rs
vendored
7
src/env/environment.rs
vendored
@ -1,9 +1,10 @@
|
||||
use crate::object::base::Value;
|
||||
use crate::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Environment {
|
||||
crate obj: Value,
|
||||
crate obj: Spanned<Value>,
|
||||
crate path: PathBuf,
|
||||
}
|
||||
|
||||
@ -12,7 +13,7 @@ impl Environment {
|
||||
let path = std::env::current_dir()?;
|
||||
|
||||
Ok(Environment {
|
||||
obj: Value::Filesystem,
|
||||
obj: Value::Filesystem.spanned_unknown(),
|
||||
path,
|
||||
})
|
||||
}
|
||||
@ -21,7 +22,7 @@ impl Environment {
|
||||
self.path.as_path()
|
||||
}
|
||||
|
||||
pub fn obj(&self) -> &Value {
|
||||
pub fn obj(&self) -> &Spanned<Value> {
|
||||
&self.obj
|
||||
}
|
||||
}
|
||||
|
@ -48,7 +48,7 @@ pub fn labelled(
|
||||
) -> impl FnOnce(ShellError) -> ShellError + 'a {
|
||||
let span = span.into();
|
||||
|
||||
move |error| ShellError::maybe_labeled_error(heading, span_message, span)
|
||||
move |_| ShellError::maybe_labeled_error(heading, span_message, span)
|
||||
}
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Serialize, Deserialize)]
|
||||
@ -247,10 +247,6 @@ impl ShellError {
|
||||
crate fn unexpected(title: impl Into<String>) -> ShellError {
|
||||
ShellError::string(&format!("Unexpected: {}", title.into()))
|
||||
}
|
||||
|
||||
crate fn copy_error(&self) -> ShellError {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -10,15 +10,15 @@ use indexmap::IndexMap;
|
||||
|
||||
#[derive(new)]
|
||||
crate struct Scope {
|
||||
it: Value,
|
||||
it: Spanned<Value>,
|
||||
#[new(default)]
|
||||
vars: IndexMap<String, Value>,
|
||||
vars: IndexMap<String, Spanned<Value>>,
|
||||
}
|
||||
|
||||
impl Scope {
|
||||
crate fn empty() -> Scope {
|
||||
Scope {
|
||||
it: Value::nothing(),
|
||||
it: Value::nothing().spanned_unknown(),
|
||||
vars: IndexMap::new(),
|
||||
}
|
||||
}
|
||||
@ -64,8 +64,10 @@ crate fn evaluate_baseline_expr(
|
||||
})
|
||||
}
|
||||
Some(next) => {
|
||||
item =
|
||||
Spanned::from_item(next.clone(), (expr.span().start, name.span().end))
|
||||
item = Spanned::from_item(
|
||||
next.clone().item,
|
||||
(expr.span().start, name.span().end),
|
||||
)
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -93,14 +95,11 @@ fn evaluate_reference(
|
||||
source: &Text,
|
||||
) -> Result<Spanned<Value>, ShellError> {
|
||||
match name {
|
||||
hir::Variable::It(span) => Ok(Spanned::from_item(scope.it.copy(), span)),
|
||||
hir::Variable::Other(span) => Ok(Spanned::from_item(
|
||||
scope
|
||||
.vars
|
||||
.get(span.slice(source))
|
||||
.map(|v| v.copy())
|
||||
.unwrap_or_else(|| Value::nothing()),
|
||||
span,
|
||||
)),
|
||||
hir::Variable::It(span) => Ok(Spanned::from_item(scope.it.item, span)),
|
||||
hir::Variable::Other(span) => Ok(scope
|
||||
.vars
|
||||
.get(span.slice(source))
|
||||
.map(|v| v.clone())
|
||||
.unwrap_or_else(|| Value::nothing().spanned(span))),
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,7 @@ pub struct TableView {
|
||||
}
|
||||
|
||||
impl TableView {
|
||||
fn merge_descriptors(values: &[Value]) -> Vec<String> {
|
||||
fn merge_descriptors(values: &[Spanned<Value>]) -> Vec<String> {
|
||||
let mut ret = vec![];
|
||||
for value in values {
|
||||
for desc in value.data_descriptors() {
|
||||
@ -25,7 +25,7 @@ impl TableView {
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn from_list(values: &[Value]) -> Option<TableView> {
|
||||
pub fn from_list(values: &[Spanned<Value>]) -> Option<TableView> {
|
||||
if values.len() == 0 {
|
||||
return None;
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ pub struct VTableView {
|
||||
}
|
||||
|
||||
impl VTableView {
|
||||
pub fn from_list(values: &[Value]) -> Option<VTableView> {
|
||||
pub fn from_list(values: &[Spanned<Value>]) -> Option<VTableView> {
|
||||
if values.len() == 0 {
|
||||
return None;
|
||||
}
|
||||
|
@ -2,9 +2,10 @@ crate mod base;
|
||||
crate mod config;
|
||||
crate mod dict;
|
||||
crate mod files;
|
||||
crate mod into;
|
||||
crate mod process;
|
||||
crate mod types;
|
||||
|
||||
crate use base::{Primitive, Value};
|
||||
crate use dict::Dictionary;
|
||||
crate use base::{Block, Primitive, Switch, Value};
|
||||
crate use dict::{Dictionary, SpannedDictBuilder};
|
||||
crate use files::dir_entry_dict;
|
||||
|
@ -153,8 +153,8 @@ impl Deserialize<'de> for Block {
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn invoke(&self, value: &Value) -> Result<Spanned<Value>, ShellError> {
|
||||
let scope = Scope::new(value.copy());
|
||||
pub fn invoke(&self, value: &Spanned<Value>) -> Result<Spanned<Value>, ShellError> {
|
||||
let scope = Scope::new(value.clone());
|
||||
|
||||
if self.expressions.len() == 0 {
|
||||
return Ok(Spanned::from_item(Value::nothing(), self.span));
|
||||
@ -174,20 +174,19 @@ impl Block {
|
||||
pub enum Value {
|
||||
Primitive(Primitive),
|
||||
Object(crate::object::Dictionary),
|
||||
List(Vec<Value>),
|
||||
Binary(Vec<u8>),
|
||||
|
||||
List(Vec<Spanned<Value>>),
|
||||
#[allow(unused)]
|
||||
Block(Block),
|
||||
Filesystem,
|
||||
}
|
||||
|
||||
pub fn debug_list(values: &'a Vec<Value>) -> ValuesDebug<'a> {
|
||||
pub fn debug_list(values: &'a Vec<Spanned<Value>>) -> ValuesDebug<'a> {
|
||||
ValuesDebug { values }
|
||||
}
|
||||
|
||||
pub struct ValuesDebug<'a> {
|
||||
values: &'a Vec<Value>,
|
||||
values: &'a Vec<Spanned<Value>>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ValuesDebug<'a> {
|
||||
@ -199,12 +198,12 @@ impl fmt::Debug for ValuesDebug<'a> {
|
||||
}
|
||||
|
||||
pub struct ValueDebug<'a> {
|
||||
value: &'a Value,
|
||||
value: &'a Spanned<Value>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for ValueDebug<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.value {
|
||||
match self.value.item() {
|
||||
Value::Primitive(p) => p.debug(f),
|
||||
Value::Object(o) => o.debug(f),
|
||||
Value::List(l) => debug_list(l).fmt(f),
|
||||
@ -281,6 +280,12 @@ impl std::convert::TryFrom<Option<&'a Spanned<Value>>> for Switch {
|
||||
}
|
||||
}
|
||||
|
||||
impl Spanned<Value> {
|
||||
crate fn debug(&'a self) -> ValueDebug<'a> {
|
||||
ValueDebug { value: self }
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
crate fn type_name(&self) -> String {
|
||||
match self {
|
||||
@ -314,13 +319,16 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_data_by_key(&'a self, name: &str) -> Option<&Value> {
|
||||
crate fn get_data_by_key(&'a self, name: &str) -> Option<&Spanned<Value>> {
|
||||
match self {
|
||||
Value::Object(o) => o.get_data_by_key(name),
|
||||
Value::List(l) => {
|
||||
for item in l {
|
||||
match item {
|
||||
Value::Object(o) => match o.get_data_by_key(name) {
|
||||
Spanned {
|
||||
item: Value::Object(o),
|
||||
..
|
||||
} => match o.get_data_by_key(name) {
|
||||
Some(v) => return Some(v),
|
||||
None => {}
|
||||
},
|
||||
@ -333,7 +341,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_data_by_index(&'a self, idx: usize) -> Option<&Value> {
|
||||
crate fn get_data_by_index(&'a self, idx: usize) -> Option<&Spanned<Value>> {
|
||||
match self {
|
||||
Value::List(l) => l.iter().nth(idx),
|
||||
_ => None,
|
||||
@ -352,20 +360,6 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn copy(&self) -> Value {
|
||||
match self {
|
||||
Value::Primitive(p) => Value::Primitive(p.clone()),
|
||||
Value::Object(o) => Value::Object(o.copy_dict()),
|
||||
Value::Block(b) => Value::Block(b.clone()),
|
||||
Value::List(l) => {
|
||||
let list = l.iter().map(|i| i.copy()).collect();
|
||||
Value::List(list)
|
||||
}
|
||||
Value::Filesystem => Value::Filesystem,
|
||||
Value::Binary(b) => Value::Binary(b.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
crate fn format_leaf(&self, desc: Option<&String>) -> String {
|
||||
match self {
|
||||
Value::Primitive(p) => p.format(desc),
|
||||
@ -417,7 +411,7 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn as_pair(&self) -> Result<(Value, Value), ShellError> {
|
||||
crate fn as_pair(&self) -> Result<(Spanned<Value>, Spanned<Value>), ShellError> {
|
||||
match self {
|
||||
Value::List(list) if list.len() == 2 => Ok((list[0].clone(), list[1].clone())),
|
||||
other => Err(ShellError::string(format!(
|
||||
@ -509,11 +503,6 @@ impl Value {
|
||||
pub fn nothing() -> Value {
|
||||
Value::Primitive(Primitive::Nothing)
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn list(values: impl Into<Vec<Value>>) -> Value {
|
||||
Value::List(values.into())
|
||||
}
|
||||
}
|
||||
|
||||
crate fn select_fields(obj: &Value, fields: &[String]) -> crate::object::Dictionary {
|
||||
@ -522,9 +511,9 @@ crate fn select_fields(obj: &Value, fields: &[String]) -> crate::object::Diction
|
||||
let descs = obj.data_descriptors();
|
||||
|
||||
for field in fields {
|
||||
match descs.iter().find(|d| *d == field) {
|
||||
match descs.iter().find(|d| d.name.is_string(field)) {
|
||||
None => out.add(field, Value::nothing()),
|
||||
Some(desc) => out.add(desc.clone(), obj.get_data(desc).borrow().copy()),
|
||||
Some(desc) => out.add(desc.clone(), obj.get_data(desc).borrow().clone()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -539,7 +528,7 @@ crate fn reject_fields(obj: &Value, fields: &[String]) -> crate::object::Diction
|
||||
for desc in descs {
|
||||
match desc {
|
||||
x if fields.iter().any(|field| *field == x) => continue,
|
||||
_ => out.add(desc.clone(), obj.get_data(&desc).borrow().copy()),
|
||||
_ => out.add(desc.clone(), obj.get_data(&desc).borrow().clone()),
|
||||
}
|
||||
}
|
||||
|
||||
@ -552,7 +541,7 @@ crate fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool {
|
||||
match descs.iter().find(|d| *d == field) {
|
||||
None => false,
|
||||
Some(desc) => {
|
||||
let v = obj.get_data(desc).borrow().copy();
|
||||
let v = obj.get_data(desc).borrow().clone();
|
||||
|
||||
match v {
|
||||
Value::Primitive(Primitive::Boolean(b)) => match (op, rhs) {
|
||||
|
@ -16,24 +16,31 @@ const APP_INFO: AppInfo = AppInfo {
|
||||
#[derive(Deserialize, Serialize)]
|
||||
struct Config {
|
||||
#[serde(flatten)]
|
||||
extra: IndexMap<String, Value>,
|
||||
extra: IndexMap<String, Spanned<Value>>,
|
||||
}
|
||||
|
||||
crate fn write_config(map: &IndexMap<String, Value>) -> Result<(), ShellError> {
|
||||
crate fn write_config(config: &IndexMap<String, Spanned<Value>>) -> Result<(), ShellError> {
|
||||
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
||||
.map_err(|err| ShellError::string(&format!("Couldn't open config file:\n{}", err)))?;
|
||||
|
||||
let filename = location.join("config.toml");
|
||||
touch(&filename)?;
|
||||
|
||||
let contents = toml::to_string(&Config { extra: map.clone() })?;
|
||||
let contents = toml::to_string(&Config {
|
||||
extra: config
|
||||
.iter()
|
||||
.map(|(k, v)| (k.clone(), v.item.clone()))
|
||||
.collect(),
|
||||
})?;
|
||||
|
||||
fs::write(&filename, &contents)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
crate fn config() -> Result<IndexMap<String, Value>, ShellError> {
|
||||
crate fn config(span: impl Into<Span>) -> Result<IndexMap<String, Spanned<Value>>, ShellError> {
|
||||
let span = span.into();
|
||||
|
||||
let location = app_root(AppDataType::UserConfig, &APP_INFO)
|
||||
.map_err(|err| ShellError::string(&format!("Couldn't open config file:\n{}", err)))?;
|
||||
|
||||
@ -43,9 +50,11 @@ crate fn config() -> Result<IndexMap<String, Value>, ShellError> {
|
||||
trace!("config file = {}", filename.display());
|
||||
|
||||
let contents = fs::read_to_string(filename)
|
||||
.map(|v| v.spanned(span))
|
||||
.map_err(|err| ShellError::string(&format!("Couldn't read config file:\n{}", err)))?;
|
||||
|
||||
let parsed: Config = toml::from_str(&contents)
|
||||
.map(|v| v.spanned(span))
|
||||
.map_err(|err| ShellError::string(&format!("Couldn't parse config file:\n{}", err)))?;
|
||||
|
||||
Ok(parsed.extra)
|
||||
|
@ -9,7 +9,7 @@ use std::fmt;
|
||||
|
||||
#[derive(Debug, Default, Eq, PartialEq, Serialize, Deserialize, Clone, new)]
|
||||
pub struct Dictionary {
|
||||
pub entries: IndexMap<String, Value>,
|
||||
pub entries: IndexMap<String, Spanned<Value>>,
|
||||
}
|
||||
|
||||
impl PartialOrd for Dictionary {
|
||||
@ -28,8 +28,8 @@ impl PartialOrd for Dictionary {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<IndexMap<String, Value>> for Dictionary {
|
||||
fn from(input: IndexMap<String, Value>) -> Dictionary {
|
||||
impl From<IndexMap<String, Spanned<Value>>> for Dictionary {
|
||||
fn from(input: IndexMap<String, Spanned<Value>>) -> Dictionary {
|
||||
let mut out = IndexMap::default();
|
||||
|
||||
for (key, value) in input {
|
||||
@ -93,7 +93,7 @@ impl Dictionary {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn get_data_by_key(&self, name: &str) -> Option<&Value> {
|
||||
crate fn get_data_by_key(&self, name: &str) -> Option<&Spanned<Value>> {
|
||||
match self
|
||||
.entries
|
||||
.iter()
|
||||
@ -114,3 +114,41 @@ impl Dictionary {
|
||||
debug.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct SpannedDictBuilder {
|
||||
span: Span,
|
||||
dict: IndexMap<DataDescriptor, Spanned<Value>>,
|
||||
}
|
||||
|
||||
impl SpannedDictBuilder {
|
||||
pub fn new(span: impl Into<Span>) -> SpannedDictBuilder {
|
||||
SpannedDictBuilder {
|
||||
span: span.into(),
|
||||
dict: IndexMap::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: impl Into<DataDescriptor>, value: impl Into<Value>) {
|
||||
self.dict
|
||||
.insert(key.into(), value.into().spanned(self.span));
|
||||
}
|
||||
|
||||
pub fn insert_spanned(
|
||||
&mut self,
|
||||
key: impl Into<DataDescriptor>,
|
||||
value: impl Into<Spanned<Value>>,
|
||||
) {
|
||||
self.dict.insert(key.into(), value.into());
|
||||
}
|
||||
|
||||
pub fn into_spanned_value(self) -> Spanned<Value> {
|
||||
Value::Object(Dictionary { entries: self.dict }).spanned(self.span)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<SpannedDictBuilder> for Spanned<Value> {
|
||||
fn from(input: SpannedDictBuilder) -> Spanned<Value> {
|
||||
input.into_spanned_value()
|
||||
}
|
||||
}
|
||||
|
23
src/object/into.rs
Normal file
23
src/object/into.rs
Normal file
@ -0,0 +1,23 @@
|
||||
use crate::object::{Primitive, Value};
|
||||
use crate::prelude::*;
|
||||
|
||||
impl From<Primitive> for Value {
|
||||
fn from(input: Primitive) -> Value {
|
||||
Value::Primitive(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Value {
|
||||
fn from(input: String) -> Value {
|
||||
Value::Primitive(Primitive::String(input))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Into<Value>> Spanned<T> {
|
||||
pub fn into_spanned_value(self) -> Spanned<Value> {
|
||||
let Spanned { item, span } = self;
|
||||
|
||||
let value = item.into();
|
||||
value.spanned(span)
|
||||
}
|
||||
}
|
@ -2,29 +2,44 @@ use crate::object::base as value;
|
||||
use crate::parser::hir;
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
use serde_derive::{Deserialize, Serialize};
|
||||
use serde_derive::Deserialize;
|
||||
|
||||
pub trait Type: std::fmt::Debug + Send {
|
||||
type Extractor: ExtractType;
|
||||
|
||||
fn name(&self) -> &'static str;
|
||||
fn check(&self, value: Spanned<Value>) -> Result<Spanned<Value>, ShellError>;
|
||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError>;
|
||||
fn coerce(&self) -> Option<hir::ExpressionKindHint> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
pub trait ExtractType<T>: Type {
|
||||
fn extract(value: Value) -> T;
|
||||
pub trait ExtractType: Sized {
|
||||
fn extract(value: &Spanned<Value>) -> Result<Self, ShellError>;
|
||||
fn check(value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
|
||||
pub struct Any;
|
||||
|
||||
impl Type for Any {
|
||||
type Extractor = Spanned<Value>;
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"Any"
|
||||
}
|
||||
|
||||
fn check(&self, value: Spanned<Value>) -> Result<Spanned<Value>, ShellError> {
|
||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType for Spanned<Value> {
|
||||
fn extract(value: &Spanned<Value>) -> Result<Self, ShellError> {
|
||||
Ok(value.clone())
|
||||
}
|
||||
|
||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
@ -33,11 +48,13 @@ impl Type for Any {
|
||||
pub struct Integer;
|
||||
|
||||
impl Type for Integer {
|
||||
type Extractor = i64;
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"Integer"
|
||||
}
|
||||
|
||||
fn check(&self, value: Spanned<Value>) -> Result<Spanned<Value>, ShellError> {
|
||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||
match value {
|
||||
v @ Spanned {
|
||||
item: Value::Primitive(Primitive::Int(_)),
|
||||
@ -48,11 +65,67 @@ impl Type for Integer {
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType<i64> for Integer {
|
||||
fn extract(value: Value) -> i64 {
|
||||
impl ExtractType for i64 {
|
||||
fn extract(value: &Spanned<Value>) -> Result<i64, ShellError> {
|
||||
match value {
|
||||
Value::Primitive(Primitive::Int(int)) => int,
|
||||
_ => unreachable!("invariant: must check before extract"),
|
||||
&Spanned {
|
||||
item: Value::Primitive(Primitive::Int(int)),
|
||||
..
|
||||
} => Ok(int),
|
||||
other => Err(ShellError::type_error("Integer", other.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||
match value {
|
||||
v @ Spanned {
|
||||
item: Value::Primitive(Primitive::Int(_)),
|
||||
..
|
||||
} => Ok(v),
|
||||
other => Err(ShellError::type_error("Integer", other.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Clone, Eq, PartialEq, Hash, Ord, PartialOrd, new)]
|
||||
pub struct NuString;
|
||||
|
||||
impl Type for NuString {
|
||||
type Extractor = String;
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"Integer"
|
||||
}
|
||||
|
||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||
match value {
|
||||
v @ Spanned {
|
||||
item: Value::Primitive(Primitive::Int(_)),
|
||||
..
|
||||
} => Ok(v),
|
||||
other => Err(ShellError::type_error("Integer", other.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType for String {
|
||||
fn extract(value: &Spanned<Value>) -> Result<String, ShellError> {
|
||||
match value {
|
||||
Spanned {
|
||||
item: Value::Primitive(Primitive::String(string)),
|
||||
..
|
||||
} => Ok(string.clone()),
|
||||
other => Err(ShellError::type_error("String", other.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||
match value {
|
||||
v @ Spanned {
|
||||
item: Value::Primitive(Primitive::Int(_)),
|
||||
..
|
||||
} => Ok(v),
|
||||
other => Err(ShellError::type_error("Integer", other.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -61,11 +134,13 @@ impl ExtractType<i64> for Integer {
|
||||
pub struct Block;
|
||||
|
||||
impl Type for Block {
|
||||
type Extractor = value::Block;
|
||||
|
||||
fn name(&self) -> &'static str {
|
||||
"Block"
|
||||
}
|
||||
|
||||
fn check(&self, value: Spanned<Value>) -> Result<Spanned<Value>, ShellError> {
|
||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||
match value {
|
||||
v @ Spanned {
|
||||
item: Value::Block(_),
|
||||
@ -76,11 +151,24 @@ impl Type for Block {
|
||||
}
|
||||
}
|
||||
|
||||
impl ExtractType<value::Block> for Block {
|
||||
fn extract(value: Value) -> value::Block {
|
||||
impl ExtractType for value::Block {
|
||||
fn extract(value: &Spanned<Value>) -> Result<value::Block, ShellError> {
|
||||
match value {
|
||||
Value::Block(block) => block,
|
||||
_ => unreachable!("invariant: must check before extract"),
|
||||
Spanned {
|
||||
item: Value::Block(block),
|
||||
..
|
||||
} => Ok(block.clone()),
|
||||
other => Err(ShellError::type_error("Block", other.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
|
||||
fn check(&self, value: &'value Spanned<Value>) -> Result<&'value Spanned<Value>, ShellError> {
|
||||
match value {
|
||||
v @ Spanned {
|
||||
item: Value::Block(_),
|
||||
..
|
||||
} => Ok(v),
|
||||
other => Err(ShellError::type_error("Block", other.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ crate use parse::flag::Flag;
|
||||
crate use parse::operator::Operator;
|
||||
crate use parse::parser::{nom_input, pipeline};
|
||||
crate use parse::pipeline::{Pipeline, PipelineElement};
|
||||
pub use parse::span::{Span, Spanned};
|
||||
pub use parse::span::{Span, Spanned, SpannedItem};
|
||||
crate use parse::text::Text;
|
||||
crate use parse::token_tree::{DelimitedNode, Delimiter, PathNode, TokenNode};
|
||||
crate use parse::tokens::{RawToken, Token};
|
||||
|
@ -16,6 +16,13 @@ pub trait SpannedItem: Sized {
|
||||
fn spanned(self, span: impl Into<Span>) -> Spanned<Self> {
|
||||
Spanned::from_item(self, span.into())
|
||||
}
|
||||
|
||||
// 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
|
||||
// have the infrastructure to make that work.
|
||||
fn spanned_unknown(self) -> Spanned<Self> {
|
||||
Spanned::from_item(self, (0, 0))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SpannedItem for T {}
|
||||
@ -64,6 +71,15 @@ pub struct Span {
|
||||
// source: &'source str,
|
||||
}
|
||||
|
||||
impl From<Option<Span>> for Span {
|
||||
fn from(input: Option<Span>) -> Span {
|
||||
match input {
|
||||
None => Span { start: 0, end: 0 },
|
||||
Some(span) => span,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> From<&Spanned<T>> for Span {
|
||||
fn from(input: &Spanned<T>) -> Span {
|
||||
input.span
|
||||
@ -113,6 +129,14 @@ impl From<&std::ops::Range<usize>> for Span {
|
||||
}
|
||||
|
||||
impl Span {
|
||||
pub fn unknown() -> Span {
|
||||
Span { start: 0, end: 0 }
|
||||
}
|
||||
|
||||
pub fn is_unknown(&self) -> bool {
|
||||
self.start == 0 && self.end == 0
|
||||
}
|
||||
|
||||
pub fn slice(&self, source: &'a str) -> &'a str {
|
||||
&source[self.start..self.end]
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ crate use crate::env::{Environment, Host};
|
||||
crate use crate::errors::ShellError;
|
||||
crate use crate::object::types::{ExtractType, Type};
|
||||
crate use crate::object::{Primitive, Value};
|
||||
crate use crate::parser::{Span, Spanned};
|
||||
crate use crate::parser::{Span, Spanned, SpannedItem};
|
||||
crate use crate::stream::{InputStream, OutputStream};
|
||||
crate use crate::Text;
|
||||
crate use futures::stream::BoxStream;
|
||||
@ -58,7 +58,7 @@ pub trait FromInputStream {
|
||||
|
||||
impl<T> FromInputStream for T
|
||||
where
|
||||
T: Stream<Item = Value> + Send + 'static,
|
||||
T: Stream<Item = Spanned<Value>> + Send + 'static,
|
||||
{
|
||||
fn from_input_stream(self) -> OutputStream {
|
||||
OutputStream {
|
||||
|
@ -1,15 +1,15 @@
|
||||
use crate::prelude::*;
|
||||
|
||||
pub struct InputStream {
|
||||
crate values: BoxStream<'static, Value>,
|
||||
crate values: BoxStream<'static, Spanned<Value>>,
|
||||
}
|
||||
|
||||
impl InputStream {
|
||||
pub fn into_vec(self) -> impl Future<Output = Vec<Value>> {
|
||||
pub fn into_vec(self) -> impl Future<Output = Vec<Spanned<Value>>> {
|
||||
self.values.collect()
|
||||
}
|
||||
|
||||
pub fn from_stream(input: impl Stream<Item = Value> + Send + 'static) -> InputStream {
|
||||
pub fn from_stream(input: impl Stream<Item = Spanned<Value>> + Send + 'static) -> InputStream {
|
||||
InputStream {
|
||||
values: input.boxed(),
|
||||
}
|
||||
@ -22,8 +22,8 @@ impl From<BoxStream<'static, Value>> for InputStream {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<VecDeque<Value>> for InputStream {
|
||||
fn from(input: VecDeque<Value>) -> InputStream {
|
||||
impl From<VecDeque<Spanned<Value>>> for InputStream {
|
||||
fn from(input: VecDeque<Spanned<Value>>) -> InputStream {
|
||||
InputStream {
|
||||
values: input.boxed(),
|
||||
}
|
||||
@ -46,13 +46,7 @@ pub struct OutputStream {
|
||||
}
|
||||
|
||||
impl OutputStream {
|
||||
pub fn from_stream(input: impl Stream<Item = ReturnValue> + Send + 'static) -> OutputStream {
|
||||
OutputStream {
|
||||
values: input.boxed(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_input(input: impl Stream<Item = Value> + Send + 'static) -> OutputStream {
|
||||
pub fn from_input(input: impl Stream<Item = Spanned<Value>> + Send + 'static) -> OutputStream {
|
||||
OutputStream {
|
||||
values: input.map(ReturnSuccess::value).boxed(),
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user