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