Merge pull request #244 from nushell/more_helpers

Add more helper functions
This commit is contained in:
JT 2021-10-20 19:11:58 +13:00 committed by GitHub
commit 1c52919103
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 98 additions and 121 deletions

1
Cargo.lock generated
View File

@ -596,6 +596,7 @@ dependencies = [
name = "nu-engine" name = "nu-engine"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"chrono",
"itertools", "itertools",
"nu-parser", "nu-parser",
"nu-path", "nu-path",

View File

@ -55,26 +55,17 @@ impl Command for SubCommand {
Example { Example {
description: "Convert string to integer", description: "Convert string to integer",
example: "'2' | into int", example: "'2' | into int",
result: Some(Value::Int { result: Some(Value::test_int(2)),
val: 2,
span: Span::unknown(),
}),
}, },
Example { Example {
description: "Convert decimal to integer", description: "Convert decimal to integer",
example: "5.9 | into int", example: "5.9 | into int",
result: Some(Value::Int { result: Some(Value::test_int(5)),
val: 5,
span: Span::unknown(),
}),
}, },
Example { Example {
description: "Convert decimal string to integer", description: "Convert decimal string to integer",
example: "'5.9' | into int", example: "'5.9' | into int",
result: Some(Value::Int { result: Some(Value::test_int(5)),
val: 5,
span: Span::unknown(),
}),
}, },
Example { Example {
description: "Convert file size to integer", description: "Convert file size to integer",
@ -88,18 +79,9 @@ impl Command for SubCommand {
description: "Convert bool to integer", description: "Convert bool to integer",
example: "[$false, $true] | into int", example: "[$false, $true] | into int",
result: Some(Value::Stream { result: Some(Value::Stream {
stream: vec![ stream: vec![Value::test_int(0), Value::test_int(1)]
Value::Int { .into_iter()
val: 0, .into_value_stream(),
span: Span::unknown(),
},
Value::Int {
val: 1,
span: Span::unknown(),
},
]
.into_iter()
.into_value_stream(),
span: Span::unknown(), span: Span::unknown(),
}), }),
}, },

View File

@ -34,7 +34,10 @@ impl Command for Git {
Ok(val) => { Ok(val) => {
let result = val.stdout; let result = val.stdout;
Ok(Value::string(&String::from_utf8_lossy(&result), call.head)) Ok(Value::String {
val: String::from_utf8_lossy(&result).to_string(),
span: call.head,
})
} }
Err(_err) => { Err(_err) => {
// FIXME: Move this to an external signature and add better error handling // FIXME: Move this to an external signature and add better error handling

View File

@ -49,7 +49,10 @@ impl Command for GitCheckout {
Ok(val) => { Ok(val) => {
let result = val.stdout; let result = val.stdout;
Ok(Value::string(&String::from_utf8_lossy(&result), call.head)) Ok(Value::String {
val: String::from_utf8_lossy(&result).to_string(),
span: call.head,
})
} }
Err(_err) => { Err(_err) => {
// FIXME: Move this to an external signature and add better error handling // FIXME: Move this to an external signature and add better error handling

View File

@ -42,7 +42,7 @@ impl Command for Lines {
let iter = lines.into_iter().filter_map(move |s| { let iter = lines.into_iter().filter_map(move |s| {
if !s.is_empty() { if !s.is_empty() {
Some(Value::String { val: s, span }) Some(Value::string(s, span))
} else { } else {
None None
} }

View File

@ -25,26 +25,11 @@ impl Command for SubCommand {
example: "'hello' | split chars", example: "'hello' | split chars",
result: Some(Value::List { result: Some(Value::List {
vals: vec![ vals: vec![
Value::String { Value::test_string("h"),
val: "h".into(), Value::test_string("e"),
span: Span::unknown(), Value::test_string("l"),
}, Value::test_string("l"),
Value::String { Value::test_string("o"),
val: "e".into(),
span: Span::unknown(),
},
Value::String {
val: "l".into(),
span: Span::unknown(),
},
Value::String {
val: "l".into(),
span: Span::unknown(),
},
Value::String {
val: "o".into(),
span: Span::unknown(),
},
], ],
span: Span::unknown(), span: Span::unknown(),
}), }),
@ -74,10 +59,7 @@ fn split_chars_helper(v: &Value, name: Span) -> Vec<Value> {
s.chars() s.chars()
.collect::<Vec<_>>() .collect::<Vec<_>>()
.into_iter() .into_iter()
.map(move |x| Value::String { .map(move |x| Value::string(x, v_span))
val: x.to_string(),
span: v_span,
})
.collect() .collect()
} else { } else {
vec![Value::Error { vec![Value::Error {

View File

@ -86,18 +86,12 @@ fn split_column_helper(
for (&k, v) in split_result.iter().zip(&gen_columns) { for (&k, v) in split_result.iter().zip(&gen_columns) {
cols.push(v.to_string()); cols.push(v.to_string());
vals.push(Value::String { vals.push(Value::string(k, head));
val: k.into(),
span: head,
});
} }
} else { } else {
for (&k, v) in split_result.iter().zip(&positional) { for (&k, v) in split_result.iter().zip(&positional) {
cols.push(v.into()); cols.push(v.into());
vals.push(Value::String { vals.push(Value::string(k, head));
val: k.into(),
span: head,
})
} }
} }
Value::List { Value::List {

View File

@ -55,10 +55,7 @@ fn split_row_helper(v: &Value, separator: &Spanned<String>, name: Span) -> Vec<V
s.split(&splitter) s.split(&splitter)
.filter_map(|s| { .filter_map(|s| {
if s.trim() != "" { if s.trim() != "" {
Some(Value::String { Some(Value::string(s, v_span))
val: s.into(),
span: v_span,
})
} else { } else {
None None
} }

View File

@ -8,3 +8,4 @@ nu-parser = { path = "../nu-parser" }
nu-protocol = { path = "../nu-protocol" } nu-protocol = { path = "../nu-protocol" }
nu-path = { path = "../nu-path" } nu-path = { path = "../nu-path" }
itertools = "0.10.1" itertools = "0.10.1"
chrono = { version="0.4.19", features=["serde"] }

View File

@ -1,5 +1,6 @@
// use std::path::PathBuf; // use std::path::PathBuf;
use chrono::{DateTime, FixedOffset};
// use nu_path::expand_path; // use nu_path::expand_path;
use nu_protocol::ast::{CellPath, PathMember}; use nu_protocol::ast::{CellPath, PathMember};
use nu_protocol::ShellError; use nu_protocol::ShellError;
@ -134,27 +135,26 @@ impl FromValue for Spanned<bool> {
} }
} }
// impl FromValue for DateTime<FixedOffset> { impl FromValue for DateTime<FixedOffset> {
// fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
// match v { match v {
// Value { Value::Date { val, .. } => Ok(*val),
// value: UntaggedValue::Primitive(Primitive::Date(d)), v => Err(ShellError::CantConvert("date".into(), v.span()?)),
// .. }
// } => Ok(*d), }
// Value { }
// value: UntaggedValue::Row(_),
// .. impl FromValue for Spanned<DateTime<FixedOffset>> {
// } => { fn from_value(v: &Value) -> Result<Self, ShellError> {
// let mut shell_error = ShellError::type_error("date", v.spanned_type_name()); match v {
// shell_error.notes.push( Value::Date { val, span } => Ok(Spanned {
// "Note: you can access columns using dot. eg) $it.column or (ls).column".into(), item: *val,
// ); span: *span,
// Err(shell_error) }),
// } v => Err(ShellError::CantConvert("date".into(), v.span()?)),
// v => Err(ShellError::type_error("date", v.spanned_type_name())), }
// } }
// } }
// }
impl FromValue for Range { impl FromValue for Range {
fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
@ -177,31 +177,15 @@ impl FromValue for Spanned<Range> {
} }
} }
// impl FromValue for Vec<u8> { impl FromValue for Vec<u8> {
// fn from_value(v: &Value) -> Result<Self, ShellError> { fn from_value(v: &Value) -> Result<Self, ShellError> {
// match v { match v {
// Value { Value::Binary { val, .. } => Ok(val.clone()),
// value: UntaggedValue::Primitive(Primitive::Binary(b)), Value::String { val, .. } => Ok(val.bytes().collect()),
// .. v => Err(ShellError::CantConvert("binary data".into(), v.span()?)),
// } => Ok(b.clone()), }
// Value { }
// value: UntaggedValue::Primitive(Primitive::String(s)), }
// ..
// } => Ok(s.bytes().collect()),
// Value {
// value: UntaggedValue::Row(_),
// ..
// } => {
// let mut shell_error = ShellError::type_error("binary data", v.spanned_type_name());
// shell_error.notes.push(
// "Note: you can access columns using dot. eg) $it.column or (ls).column".into(),
// );
// Err(shell_error)
// }
// v => Err(ShellError::type_error("binary data", v.spanned_type_name())),
// }
// }
// }
// impl FromValue for Dictionary { // impl FromValue for Dictionary {
// fn from_value(v: &Value) -> Result<Self, ShellError> { // fn from_value(v: &Value) -> Result<Self, ShellError> {

View File

@ -19,6 +19,10 @@ pub enum ShellError {
rhs_span: Span, rhs_span: Span,
}, },
#[error("Operator overflow.")]
#[diagnostic(code(nu::shell::operator_overflow), url(docsrs))]
OperatorOverflow(String, #[label = "{0}"] Span),
#[error("Pipeline mismatch.")] #[error("Pipeline mismatch.")]
#[diagnostic(code(nu::shell::pipeline_mismatch), url(docsrs))] #[diagnostic(code(nu::shell::pipeline_mismatch), url(docsrs))]
PipelineMismatch { PipelineMismatch {

View File

@ -363,13 +363,6 @@ impl Value {
Ok(current) Ok(current)
} }
pub fn string(s: &str, span: Span) -> Value {
Value::String {
val: s.into(),
span,
}
}
pub fn is_true(&self) -> bool { pub fn is_true(&self) -> bool {
matches!(self, Value::Bool { val: true, .. }) matches!(self, Value::Bool { val: true, .. })
} }
@ -438,6 +431,33 @@ impl Value {
}, },
} }
} }
pub fn string(val: impl Into<String>, span: Span) -> Value {
Value::String {
val: val.into(),
span,
}
}
pub fn int(val: i64, span: Span) -> Value {
Value::Int { val, span }
}
// Only use these for test data. Span::unknown() should not be used in user data
pub fn test_string(s: impl Into<String>) -> Value {
Value::String {
val: s.into(),
span: Span::unknown(),
}
}
// Only use these for test data. Span::unknown() should not be used in user data
pub fn test_int(val: i64) -> Value {
Value::Int {
val,
span: Span::unknown(),
}
}
} }
impl PartialOrd for Value { impl PartialOrd for Value {
@ -528,10 +548,16 @@ impl Value {
let span = span(&[self.span()?, rhs.span()?]); let span = span(&[self.span()?, rhs.span()?]);
match (self, rhs) { match (self, rhs) {
(Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => Ok(Value::Int { (Value::Int { val: lhs, .. }, Value::Int { val: rhs, .. }) => {
val: lhs + rhs, if let Some(val) = lhs.checked_add(*rhs) {
span, Ok(Value::Int { val, span })
}), } else {
Err(ShellError::OperatorOverflow(
"add operation overflowed".into(),
span,
))
}
}
(Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float { (Value::Int { val: lhs, .. }, Value::Float { val: rhs, .. }) => Ok(Value::Float {
val: *lhs as f64 + *rhs, val: *lhs as f64 + *rhs,
span, span,