mirror of
https://github.com/nushell/nushell
synced 2024-12-26 13:03:07 +00:00
Merge pull request #1047 from jonathandturner/new_lines
Add new line primitive, bump version, allow bare filepaths
This commit is contained in:
commit
49f9253ca2
37 changed files with 170 additions and 129 deletions
2
Cargo.lock
generated
2
Cargo.lock
generated
|
@ -1878,7 +1878,7 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "nu"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
dependencies = [
|
||||
"ansi_term 0.12.1",
|
||||
"app_dirs",
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
[package]
|
||||
name = "nu"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
authors = ["Yehuda Katz <wycats@gmail.com>", "Jonathan Turner <jonathan.d.turner@gmail.com>", "Andrés N. Robalino <andres@androbtech.com>"]
|
||||
description = "A shell for the GitHub era"
|
||||
license = "MIT"
|
||||
|
|
|
@ -102,10 +102,17 @@ impl ExpandExpression for FilePathShape {
|
|||
token_nodes: &mut TokensIterator<'_>,
|
||||
context: &ExpandContext,
|
||||
) -> Result<hir::Expression, ParseError> {
|
||||
let atom = expand_atom(token_nodes, "file path", context, ExpansionRule::new())?;
|
||||
let atom = expand_atom(
|
||||
token_nodes,
|
||||
"file path",
|
||||
context,
|
||||
ExpansionRule::new().allow_external_word(),
|
||||
)?;
|
||||
|
||||
match atom.unspanned {
|
||||
UnspannedAtomicToken::Word { text: body } | UnspannedAtomicToken::String { body } => {
|
||||
UnspannedAtomicToken::Word { text: body }
|
||||
| UnspannedAtomicToken::ExternalWord { text: body }
|
||||
| UnspannedAtomicToken::String { body } => {
|
||||
let path = expand_file_path(body.slice(context.source), context);
|
||||
return Ok(hir::Expression::file_path(path, atom.span));
|
||||
}
|
||||
|
|
|
@ -84,11 +84,17 @@ impl ExpandExpression for PatternShape {
|
|||
token_nodes: &mut TokensIterator<'_>,
|
||||
context: &ExpandContext,
|
||||
) -> Result<hir::Expression, ParseError> {
|
||||
let atom = expand_atom(token_nodes, "pattern", context, ExpansionRule::new())?;
|
||||
let atom = expand_atom(
|
||||
token_nodes,
|
||||
"pattern",
|
||||
context,
|
||||
ExpansionRule::new().allow_external_word(),
|
||||
)?;
|
||||
|
||||
match atom.unspanned {
|
||||
UnspannedAtomicToken::Word { text: body }
|
||||
| UnspannedAtomicToken::String { body }
|
||||
| UnspannedAtomicToken::ExternalWord { text: body }
|
||||
| UnspannedAtomicToken::GlobPattern { pattern: body } => {
|
||||
let path = expand_file_path(body.slice(context.source), context);
|
||||
return Ok(hir::Expression::pattern(path.to_string_lossy(), atom.span));
|
||||
|
|
|
@ -132,9 +132,10 @@ impl Value {
|
|||
self.tag.clone()
|
||||
}
|
||||
|
||||
pub fn as_string(&self) -> Result<&str, ShellError> {
|
||||
pub fn as_string(&self) -> Result<String, ShellError> {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(Primitive::String(string)) => Ok(&string[..]),
|
||||
UntaggedValue::Primitive(Primitive::String(string)) => Ok(string.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(line)) => Ok(line.clone() + "\n"),
|
||||
_ => Err(ShellError::type_error("string", self.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ impl PrettyType for Primitive {
|
|||
Primitive::Decimal(_) => ty("decimal"),
|
||||
Primitive::Bytes(_) => ty("bytesize"),
|
||||
Primitive::String(_) => ty("string"),
|
||||
Primitive::Line(_) => ty("line"),
|
||||
Primitive::ColumnPath(_) => ty("column-path"),
|
||||
Primitive::Pattern(_) => ty("pattern"),
|
||||
Primitive::Boolean(_) => ty("boolean"),
|
||||
|
@ -52,6 +53,7 @@ impl PrettyDebug for Primitive {
|
|||
Primitive::Decimal(decimal) => prim(format_args!("{}", decimal)),
|
||||
Primitive::Bytes(bytes) => primitive_doc(bytes, "bytesize"),
|
||||
Primitive::String(string) => prim(string),
|
||||
Primitive::Line(string) => prim(string),
|
||||
Primitive::ColumnPath(path) => path.pretty(),
|
||||
Primitive::Pattern(pattern) => primitive_doc(pattern, "pattern"),
|
||||
Primitive::Boolean(boolean) => match boolean {
|
||||
|
|
|
@ -17,6 +17,7 @@ pub enum Primitive {
|
|||
Decimal(BigDecimal),
|
||||
Bytes(u64),
|
||||
String(String),
|
||||
Line(String),
|
||||
ColumnPath(ColumnPath),
|
||||
Pattern(String),
|
||||
Boolean(bool),
|
||||
|
@ -51,6 +52,7 @@ impl ShellTypeName for Primitive {
|
|||
Primitive::Decimal(_) => "decimal",
|
||||
Primitive::Bytes(_) => "bytes",
|
||||
Primitive::String(_) => "string",
|
||||
Primitive::Line(_) => "line",
|
||||
Primitive::ColumnPath(_) => "column path",
|
||||
Primitive::Pattern(_) => "pattern",
|
||||
Primitive::Boolean(_) => "boolean",
|
||||
|
|
|
@ -152,6 +152,25 @@ pub fn autoview(
|
|||
} => {
|
||||
outln!("{}", s);
|
||||
}
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Line(ref s)),
|
||||
tag: Tag { anchor, span },
|
||||
} if anchor.is_some() => {
|
||||
if let Some(text) = text {
|
||||
let mut stream = VecDeque::new();
|
||||
stream.push_back(value::string(s).into_value(Tag { anchor, span }));
|
||||
let result = text.run(raw.with_input(stream.into()), &context.commands);
|
||||
result.collect::<Vec<_>>().await;
|
||||
} else {
|
||||
outln!("{}\n", s);
|
||||
}
|
||||
}
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Line(s)),
|
||||
..
|
||||
} => {
|
||||
outln!("{}\n", s);
|
||||
}
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Path(s)),
|
||||
..
|
||||
|
|
|
@ -25,7 +25,7 @@ impl Encoder for LinesCodec {
|
|||
}
|
||||
|
||||
impl Decoder for LinesCodec {
|
||||
type Item = String;
|
||||
type Item = nu_protocol::UntaggedValue;
|
||||
type Error = Error;
|
||||
|
||||
fn decode(&mut self, src: &mut BytesMut) -> Result<Option<Self::Item>, Self::Error> {
|
||||
|
@ -33,12 +33,14 @@ impl Decoder for LinesCodec {
|
|||
Some(pos) if !src.is_empty() => {
|
||||
let buf = src.split_to(pos + 1);
|
||||
String::from_utf8(buf.to_vec())
|
||||
.map(value::line)
|
||||
.map(Some)
|
||||
.map_err(|e| Error::new(ErrorKind::InvalidData, e))
|
||||
}
|
||||
_ if !src.is_empty() => {
|
||||
let drained = src.take();
|
||||
String::from_utf8(drained.to_vec())
|
||||
.map(value::string)
|
||||
.map(Some)
|
||||
.map_err(|e| Error::new(ErrorKind::InvalidData, e))
|
||||
}
|
||||
|
@ -192,8 +194,7 @@ pub(crate) async fn run_external_command(
|
|||
let stdout = popen.stdout.take().unwrap();
|
||||
let file = futures::io::AllowStdIo::new(stdout);
|
||||
let stream = Framed::new(file, LinesCodec {});
|
||||
let stream =
|
||||
stream.map(move |line| value::string(line.unwrap()).into_value(&name_tag));
|
||||
let stream = stream.map(move |line| line.unwrap().into_value(&name_tag));
|
||||
Ok(ClassifiedInputStream::from_input_stream(
|
||||
stream.boxed() as BoxStream<'static, Value>
|
||||
))
|
||||
|
|
|
@ -56,19 +56,16 @@ pub fn from_delimited_data(
|
|||
for value in values {
|
||||
let value_tag = &value.tag;
|
||||
latest_tag = Some(value_tag.clone());
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_tag.clone(),
|
||||
"value originates from here",
|
||||
value_tag.clone(),
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -79,19 +79,16 @@ fn from_ini(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
|||
for value in values {
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,19 +83,17 @@ fn from_json(
|
|||
for value in values {
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -266,17 +266,17 @@ fn from_ssv(
|
|||
for value in values {
|
||||
let value_tag = value.tag.clone();
|
||||
latest_tag = Some(value_tag.clone());
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary (
|
||||
else {
|
||||
yield Err(ShellError::labeled_error_with_secondary (
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
&name,
|
||||
"value originates from here",
|
||||
&value_tag
|
||||
)),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -82,19 +82,17 @@ pub fn from_toml(
|
|||
for value in values {
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
match value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::data::value;
|
|||
use crate::data::TaggedDictBuilder;
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
use nu_protocol::{ReturnSuccess, Signature, Value};
|
||||
|
||||
pub struct FromURL;
|
||||
|
||||
|
@ -44,18 +44,16 @@ fn from_url(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
|||
for value in values {
|
||||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
match value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -96,19 +96,17 @@ fn from_xml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStrea
|
|||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
|
||||
match value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -110,19 +110,17 @@ fn from_yaml(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStre
|
|||
latest_tag = Some(value.tag.clone());
|
||||
let value_span = value.tag.span;
|
||||
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
if let Ok(s) = value.as_string() {
|
||||
concat_string.push_str(&s);
|
||||
concat_string.push_str("\n");
|
||||
}
|
||||
_ => yield Err(ShellError::labeled_error_with_secondary(
|
||||
else {
|
||||
yield Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
value_span,
|
||||
)),
|
||||
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,8 +38,8 @@ fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
|||
|
||||
let stream = input
|
||||
.values
|
||||
.map(move |v| match v.value {
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => {
|
||||
.map(move |v| {
|
||||
if let Ok(s) = v.as_string() {
|
||||
let split_result: Vec<_> = s.lines().filter(|s| s.trim() != "").collect();
|
||||
|
||||
trace!("split result = {:?}", split_result);
|
||||
|
@ -47,12 +47,11 @@ fn lines(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream,
|
|||
let mut result = VecDeque::new();
|
||||
for s in split_result {
|
||||
result.push_back(ReturnSuccess::value(
|
||||
UntaggedValue::Primitive(Primitive::String(s.into())).into_untagged_value(),
|
||||
UntaggedValue::Primitive(Primitive::Line(s.into())).into_untagged_value(),
|
||||
));
|
||||
}
|
||||
result
|
||||
}
|
||||
_ => {
|
||||
} else {
|
||||
let mut result = VecDeque::new();
|
||||
let value_span = v.tag.span;
|
||||
|
||||
|
|
|
@ -146,7 +146,7 @@ fn save(
|
|||
}
|
||||
_ => {
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save requires a filepath (1)",
|
||||
"Save requires a filepath",
|
||||
"needs path",
|
||||
name_tag.clone(),
|
||||
));
|
||||
|
@ -154,7 +154,7 @@ fn save(
|
|||
},
|
||||
None => {
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save requires a filepath (2)",
|
||||
"Save requires a filepath",
|
||||
"needs path",
|
||||
name_tag.clone(),
|
||||
));
|
||||
|
@ -162,7 +162,7 @@ fn save(
|
|||
}
|
||||
} else {
|
||||
yield Err(ShellError::labeled_error(
|
||||
"Save requires a filepath (3)",
|
||||
"Save requires a filepath",
|
||||
"needs path",
|
||||
name_tag.clone(),
|
||||
));
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
|||
use crate::data::{value, TaggedDictBuilder};
|
||||
use crate::prelude::*;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, ReturnSuccess, Signature, UntaggedValue, Value};
|
||||
use nu_protocol::{ReturnSuccess, Signature, Value};
|
||||
|
||||
pub struct Size;
|
||||
|
||||
|
@ -35,17 +35,18 @@ fn size(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream,
|
|||
|
||||
Ok(input
|
||||
.values
|
||||
.map(move |v| match v.value {
|
||||
UntaggedValue::Primitive(Primitive::String(ref s)) => {
|
||||
ReturnSuccess::value(count(s, &v.tag))
|
||||
}
|
||||
_ => Err(ShellError::labeled_error_with_secondary(
|
||||
.map(move |v| {
|
||||
if let Ok(s) = v.as_string() {
|
||||
ReturnSuccess::value(count(&s, &v.tag))
|
||||
} else {
|
||||
Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
v.tag.span,
|
||||
)),
|
||||
))
|
||||
}
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
|
|
|
@ -57,8 +57,8 @@ fn split_column(
|
|||
|
||||
Ok(input
|
||||
.values
|
||||
.map(move |v| match v.value {
|
||||
UntaggedValue::Primitive(Primitive::String(ref s)) => {
|
||||
.map(move |v| {
|
||||
if let Ok(s) = v.as_string() {
|
||||
let splitter = separator.replace("\\n", "\n");
|
||||
trace!("splitting with {:?}", splitter);
|
||||
|
||||
|
@ -104,14 +104,15 @@ fn split_column(
|
|||
}
|
||||
ReturnSuccess::value(dict.into_value())
|
||||
}
|
||||
}
|
||||
_ => Err(ShellError::labeled_error_with_secondary(
|
||||
} else {
|
||||
Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
"requires string input",
|
||||
name_span,
|
||||
"value originates from here",
|
||||
v.tag.span,
|
||||
)),
|
||||
))
|
||||
}
|
||||
})
|
||||
.to_output_stream())
|
||||
}
|
||||
|
|
|
@ -44,8 +44,8 @@ fn split_row(
|
|||
) -> Result<OutputStream, ShellError> {
|
||||
let stream = input
|
||||
.values
|
||||
.map(move |v| match v.value {
|
||||
UntaggedValue::Primitive(Primitive::String(ref s)) => {
|
||||
.map(move |v| {
|
||||
if let Ok(s) = v.as_string() {
|
||||
let splitter = separator.item.replace("\\n", "\n");
|
||||
trace!("splitting with {:?}", splitter);
|
||||
let split_result: Vec<_> = s.split(&splitter).filter(|s| s.trim() != "").collect();
|
||||
|
@ -59,8 +59,7 @@ fn split_row(
|
|||
));
|
||||
}
|
||||
result
|
||||
}
|
||||
_ => {
|
||||
} else {
|
||||
let mut result = VecDeque::new();
|
||||
result.push_back(Err(ShellError::labeled_error_with_secondary(
|
||||
"Expected a string from pipeline",
|
||||
|
|
|
@ -56,6 +56,7 @@ pub fn value_to_bson_value(v: &Value) -> Result<Bson, ShellError> {
|
|||
}
|
||||
UntaggedValue::Primitive(Primitive::Nothing) => Bson::Null,
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => Bson::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => Bson::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => Bson::Array(
|
||||
path.iter()
|
||||
.map(|x| match &x.unspanned {
|
||||
|
|
|
@ -137,6 +137,7 @@ fn to_string_tagged_value(v: &Value) -> Result<String, ShellError> {
|
|||
UntaggedValue::Primitive(Primitive::Path(_)) => Ok(v.as_string()?.to_string()),
|
||||
UntaggedValue::Table(_) => return Ok(String::from("[Table]")),
|
||||
UntaggedValue::Row(_) => return Ok(String::from("[Row]")),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => return Ok(s.to_string()),
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => return Ok(s.to_string()),
|
||||
_ => {
|
||||
return Err(ShellError::labeled_error(
|
||||
|
|
|
@ -54,6 +54,7 @@ pub fn value_to_json_value(v: &Value) -> Result<serde_json::Value, ShellError> {
|
|||
UntaggedValue::Primitive(Primitive::Nothing) => serde_json::Value::Null,
|
||||
UntaggedValue::Primitive(Primitive::Pattern(s)) => serde_json::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => serde_json::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => serde_json::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => serde_json::Value::Array(
|
||||
path.iter()
|
||||
.map(|x| match &x.unspanned {
|
||||
|
|
|
@ -94,6 +94,7 @@ fn nu_value_to_sqlite_string(v: Value) -> String {
|
|||
Primitive::Bytes(u) => format!("{}", u),
|
||||
Primitive::Pattern(s) => format!("'{}'", s.replace("'", "''")),
|
||||
Primitive::String(s) => format!("'{}'", s.replace("'", "''")),
|
||||
Primitive::Line(s) => format!("'{}'", s.replace("'", "''")),
|
||||
Primitive::Boolean(true) => "1".into(),
|
||||
Primitive::Boolean(_) => "0".into(),
|
||||
Primitive::Date(d) => format!("'{}'", d),
|
||||
|
|
|
@ -50,6 +50,7 @@ pub fn value_to_toml_value(v: &Value) -> Result<toml::Value, ShellError> {
|
|||
}
|
||||
UntaggedValue::Primitive(Primitive::Pattern(s)) => toml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => toml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => toml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Path(s)) => {
|
||||
toml::Value::String(s.display().to_string())
|
||||
}
|
||||
|
|
|
@ -51,6 +51,7 @@ pub fn value_to_yaml_value(v: &Value) -> Result<serde_yaml::Value, ShellError> {
|
|||
UntaggedValue::Primitive(Primitive::Nothing) => serde_yaml::Value::Null,
|
||||
UntaggedValue::Primitive(Primitive::Pattern(s)) => serde_yaml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::String(s)) => serde_yaml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::Line(s)) => serde_yaml::Value::String(s.clone()),
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(path)) => {
|
||||
let mut out = vec![];
|
||||
|
||||
|
|
|
@ -186,6 +186,9 @@ fn coerce_compare_primitive(
|
|||
CompareValues::Decimals(BigDecimal::from(*left), right.clone())
|
||||
}
|
||||
(String(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
(Line(left), String(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
(String(left), Line(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
(Line(left), Line(right)) => CompareValues::String(left.clone(), right.clone()),
|
||||
(Date(left), Date(right)) => CompareValues::Date(left.clone(), right.clone()),
|
||||
(Date(left), Duration(right)) => CompareValues::DateDuration(left.clone(), right.clone()),
|
||||
_ => return Err((left.type_name(), right.type_name())),
|
||||
|
|
|
@ -33,6 +33,7 @@ pub enum TypeShape {
|
|||
Decimal,
|
||||
Bytesize,
|
||||
String,
|
||||
Line,
|
||||
ColumnPath,
|
||||
Pattern,
|
||||
Boolean,
|
||||
|
@ -62,6 +63,7 @@ impl TypeShape {
|
|||
Primitive::Decimal(_) => TypeShape::Decimal,
|
||||
Primitive::Bytes(_) => TypeShape::Bytesize,
|
||||
Primitive::String(_) => TypeShape::String,
|
||||
Primitive::Line(_) => TypeShape::Line,
|
||||
Primitive::ColumnPath(_) => TypeShape::ColumnPath,
|
||||
Primitive::Pattern(_) => TypeShape::Pattern,
|
||||
Primitive::Boolean(_) => TypeShape::Boolean,
|
||||
|
@ -114,6 +116,7 @@ impl PrettyDebug for TypeShape {
|
|||
TypeShape::Decimal => ty("decimal"),
|
||||
TypeShape::Bytesize => ty("bytesize"),
|
||||
TypeShape::String => ty("string"),
|
||||
TypeShape::Line => ty("line"),
|
||||
TypeShape::ColumnPath => ty("column-path"),
|
||||
TypeShape::Pattern => ty("pattern"),
|
||||
TypeShape::Boolean => ty("boolean"),
|
||||
|
@ -208,6 +211,7 @@ pub enum InlineShape {
|
|||
Decimal(BigDecimal),
|
||||
Bytesize(u64),
|
||||
String(String),
|
||||
Line(String),
|
||||
ColumnPath(ColumnPath),
|
||||
Pattern(String),
|
||||
Boolean(bool),
|
||||
|
@ -242,6 +246,7 @@ impl InlineShape {
|
|||
Primitive::Decimal(decimal) => InlineShape::Decimal(decimal.clone()),
|
||||
Primitive::Bytes(bytesize) => InlineShape::Bytesize(*bytesize),
|
||||
Primitive::String(string) => InlineShape::String(string.clone()),
|
||||
Primitive::Line(string) => InlineShape::Line(string.clone()),
|
||||
Primitive::ColumnPath(path) => InlineShape::ColumnPath(path.clone()),
|
||||
Primitive::Pattern(pattern) => InlineShape::Pattern(pattern.clone()),
|
||||
Primitive::Boolean(boolean) => InlineShape::Boolean(*boolean),
|
||||
|
@ -327,6 +332,7 @@ impl PrettyDebug for FormatInlineShape {
|
|||
}
|
||||
}
|
||||
InlineShape::String(string) => b::primitive(format!("{}", string)),
|
||||
InlineShape::Line(string) => b::primitive(format!("{}", string)),
|
||||
InlineShape::ColumnPath(path) => {
|
||||
b::intersperse(path.iter().map(|member| member.pretty()), b::keyword("."))
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ pub fn format_primitive(primitive: &Primitive, field_name: Option<&String>) -> S
|
|||
Primitive::Decimal(decimal) => format!("{}", decimal),
|
||||
Primitive::Pattern(s) => format!("{}", s),
|
||||
Primitive::String(s) => format!("{}", s),
|
||||
Primitive::Line(s) => format!("{}", s),
|
||||
Primitive::ColumnPath(p) => {
|
||||
let mut members = p.iter();
|
||||
let mut f = String::new();
|
||||
|
|
|
@ -86,6 +86,10 @@ impl ExtractType for String {
|
|||
value: UntaggedValue::Primitive(Primitive::String(string)),
|
||||
..
|
||||
} => Ok(string.clone()),
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Line(string)),
|
||||
..
|
||||
} => Ok(string.clone()),
|
||||
other => Err(ShellError::type_error("String", other.spanned_type_name())),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@ pub fn string(s: impl Into<String>) -> UntaggedValue {
|
|||
UntaggedValue::Primitive(Primitive::String(s.into()))
|
||||
}
|
||||
|
||||
pub fn line(s: impl Into<String>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::Line(s.into()))
|
||||
}
|
||||
|
||||
pub fn column_path(s: Vec<impl Into<PathMember>>) -> UntaggedValue {
|
||||
UntaggedValue::Primitive(Primitive::ColumnPath(ColumnPath::new(
|
||||
s.into_iter().map(|p| p.into()).collect(),
|
||||
|
|
|
@ -72,16 +72,14 @@ impl Plugin for Match {
|
|||
tag,
|
||||
} => {
|
||||
if let Some(val) = dict.entries.get(&self.column) {
|
||||
match val {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||
..
|
||||
} => {
|
||||
flag = self.regex.is_match(s);
|
||||
}
|
||||
Value { tag, .. } => {
|
||||
return Err(ShellError::labeled_error("expected string", "value", tag));
|
||||
}
|
||||
if let Ok(s) = val.as_string() {
|
||||
flag = self.regex.is_match(&s);
|
||||
} else {
|
||||
return Err(ShellError::labeled_error(
|
||||
"expected string",
|
||||
"value",
|
||||
val.tag(),
|
||||
));
|
||||
}
|
||||
} else {
|
||||
return Err(ShellError::labeled_error(
|
||||
|
|
|
@ -129,15 +129,9 @@ impl Plugin for Parse {
|
|||
|
||||
fn filter(&mut self, input: Value) -> Result<Vec<ReturnValue>, ShellError> {
|
||||
let mut results = vec![];
|
||||
match &input {
|
||||
Value {
|
||||
tag,
|
||||
value: UntaggedValue::Primitive(Primitive::String(s)),
|
||||
} => {
|
||||
//self.full_input.push_str(&s);
|
||||
|
||||
if let Ok(s) = input.as_string() {
|
||||
for cap in self.regex.captures_iter(&s) {
|
||||
let mut dict = TaggedDictBuilder::new(tag);
|
||||
let mut dict = TaggedDictBuilder::new(input.tag());
|
||||
|
||||
for (idx, column_name) in self.column_names.iter().enumerate() {
|
||||
dict.insert_untagged(column_name, value::string(&cap[idx + 1].to_string()));
|
||||
|
@ -146,8 +140,6 @@ impl Plugin for Parse {
|
|||
results.push(ReturnSuccess::value(dict.into_value()));
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Ok(results)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -155,6 +155,9 @@ impl Str {
|
|||
UntaggedValue::Primitive(Primitive::String(ref s)) => {
|
||||
Ok(self.apply(&s)?.into_value(value.tag()))
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Line(ref s)) => {
|
||||
Ok(self.apply(&s)?.into_value(value.tag()))
|
||||
}
|
||||
UntaggedValue::Row(_) => match self.field {
|
||||
Some(ref f) => {
|
||||
let fields = f.clone();
|
||||
|
|
|
@ -30,6 +30,7 @@ fn converts_structured_table_to_csv_text() {
|
|||
r#"
|
||||
open csv_text_sample.txt
|
||||
| lines
|
||||
| trim
|
||||
| split-column "," a b c d origin
|
||||
| last 1
|
||||
| to-csv
|
||||
|
@ -60,6 +61,7 @@ fn converts_structured_table_to_csv_text_skipping_headers_after_conversion() {
|
|||
r#"
|
||||
open csv_text_sample.txt
|
||||
| lines
|
||||
| trim
|
||||
| split-column "," a b c d origin
|
||||
| last 1
|
||||
| to-csv --headerless
|
||||
|
|
Loading…
Reference in a new issue