forked from extern/nushell
Add =~
and !~
operators on strings
`left =~ right` return true if left contains right, using Rust's `String::contains`. `!~` is the negated version. A new `apply_operator` function is added which decouples evaluation from `Value::compare`. This returns a `Value` and opens the door to implementing `+` for example, though it wouldn't be useful immediately. The `operator!` macro had to be changed slightly as it would choke on `~` in arguments.
This commit is contained in:
parent
e4226def16
commit
8f9dd6516e
@ -1,51 +0,0 @@
|
|||||||
use nu_source::ShellAnnotation;
|
|
||||||
use pretty::{Render, RenderAnnotated};
|
|
||||||
use std::io;
|
|
||||||
use termcolor::WriteColor;
|
|
||||||
|
|
||||||
pub struct TermColored<'a, W> {
|
|
||||||
color_stack: Vec<ShellAnnotation>,
|
|
||||||
upstream: &'a mut W,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, W> TermColored<'a, W> {
|
|
||||||
pub fn new(upstream: &'a mut W) -> TermColored<'a, W> {
|
|
||||||
TermColored {
|
|
||||||
color_stack: Vec::new(),
|
|
||||||
upstream,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, W> Render for TermColored<'a, W>
|
|
||||||
where
|
|
||||||
W: io::Write,
|
|
||||||
{
|
|
||||||
type Error = io::Error;
|
|
||||||
|
|
||||||
fn write_str(&mut self, s: &str) -> io::Result<usize> {
|
|
||||||
self.upstream.write(s.as_bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn write_str_all(&mut self, s: &str) -> io::Result<()> {
|
|
||||||
self.upstream.write_all(s.as_bytes())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, W> RenderAnnotated<ShellAnnotation> for TermColored<'a, W>
|
|
||||||
where
|
|
||||||
W: WriteColor,
|
|
||||||
{
|
|
||||||
fn push_annotation(&mut self, ann: &ShellAnnotation) -> Result<(), Self::Error> {
|
|
||||||
self.color_stack.push(*ann);
|
|
||||||
self.upstream.set_color(&(*ann).into())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn pop_annotation(&mut self) -> Result<(), Self::Error> {
|
|
||||||
self.color_stack.pop();
|
|
||||||
match self.color_stack.last() {
|
|
||||||
Some(previous) => self.upstream.set_color(&(*previous).into()),
|
|
||||||
None => self.upstream.reset(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -13,13 +13,7 @@ use crate::parse::parser::Number;
|
|||||||
use crate::parse::unit::Unit;
|
use crate::parse::unit::Unit;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use getset::Getters;
|
use getset::Getters;
|
||||||
#[cfg(not(coloring_in_tokens))]
|
|
||||||
use nu_errors::ShellError;
|
|
||||||
#[cfg(not(coloring_in_tokens))]
|
|
||||||
use nu_protocol::{EvaluatedArgs, Scope};
|
|
||||||
use nu_protocol::{PathMember, ShellTypeName};
|
use nu_protocol::{PathMember, ShellTypeName};
|
||||||
#[cfg(not(coloring_in_tokens))]
|
|
||||||
use nu_source::Text;
|
|
||||||
use nu_source::{
|
use nu_source::{
|
||||||
b, DebugDocBuilder, HasSpan, PrettyDebug, PrettyDebugWithSource, Span, Spanned, SpannedItem,
|
b, DebugDocBuilder, HasSpan, PrettyDebug, PrettyDebugWithSource, Span, Spanned, SpannedItem,
|
||||||
};
|
};
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
pub mod commands;
|
pub mod commands;
|
||||||
pub mod debug;
|
|
||||||
pub mod hir;
|
pub mod hir;
|
||||||
pub mod parse;
|
pub mod parse;
|
||||||
pub mod parse_command;
|
pub mod parse_command;
|
||||||
|
@ -11,5 +11,6 @@ pub use self::meta::{
|
|||||||
pub use self::pretty::{
|
pub use self::pretty::{
|
||||||
b, DebugDoc, DebugDocBuilder, PrettyDebug, PrettyDebugWithSource, ShellAnnotation,
|
b, DebugDoc, DebugDocBuilder, PrettyDebug, PrettyDebugWithSource, ShellAnnotation,
|
||||||
};
|
};
|
||||||
|
pub use self::term_colored::TermColored;
|
||||||
pub use self::text::Text;
|
pub use self::text::Text;
|
||||||
pub use self::tracable::{nom_input, NomSpan, TracableContext};
|
pub use self::tracable::{nom_input, NomSpan, TracableContext};
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::parser::hir;
|
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
|
use nu_parser::hir;
|
||||||
|
|
||||||
#[derive(new, Debug, Eq, PartialEq)]
|
#[derive(new, Debug, Eq, PartialEq)]
|
||||||
pub(crate) struct Command {
|
pub(crate) struct Command {
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
use super::ClassifiedInputStream;
|
use super::ClassifiedInputStream;
|
||||||
|
use crate::data::value;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use bytes::{BufMut, BytesMut};
|
use bytes::{BufMut, BytesMut};
|
||||||
use futures::stream::StreamExt;
|
use futures::stream::StreamExt;
|
||||||
use futures_codec::{Decoder, Encoder, Framed};
|
use futures_codec::{Decoder, Encoder, Framed};
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::Value;
|
||||||
use std::io::{Error, ErrorKind};
|
use std::io::{Error, ErrorKind};
|
||||||
use subprocess::Exec;
|
use subprocess::Exec;
|
||||||
|
|
||||||
@ -105,7 +108,7 @@ impl Command {
|
|||||||
let input_strings = inputs
|
let input_strings = inputs
|
||||||
.iter()
|
.iter()
|
||||||
.map(|i| {
|
.map(|i| {
|
||||||
i.as_string().map_err(|_| {
|
i.as_string().map(|s| s.to_string()).map_err(|_| {
|
||||||
let arg = self.args.iter().find(|arg| arg.arg.contains("$it"));
|
let arg = self.args.iter().find(|arg| arg.arg.contains("$it"));
|
||||||
if let Some(arg) = arg {
|
if let Some(arg) = arg {
|
||||||
ShellError::labeled_error(
|
ShellError::labeled_error(
|
||||||
@ -206,9 +209,8 @@ impl Command {
|
|||||||
let stdout = popen.stdout.take().unwrap();
|
let stdout = popen.stdout.take().unwrap();
|
||||||
let file = futures::io::AllowStdIo::new(stdout);
|
let file = futures::io::AllowStdIo::new(stdout);
|
||||||
let stream = Framed::new(file, LinesCodec {});
|
let stream = Framed::new(file, LinesCodec {});
|
||||||
let stream = stream.map(move |line| {
|
let stream =
|
||||||
UntaggedValue::string(line.unwrap()).into_value(&name_tag)
|
stream.map(move |line| value::string(line.unwrap()).into_value(&name_tag));
|
||||||
});
|
|
||||||
Ok(ClassifiedInputStream::from_input_stream(
|
Ok(ClassifiedInputStream::from_input_stream(
|
||||||
stream.boxed() as BoxStream<'static, Value>
|
stream.boxed() as BoxStream<'static, Value>
|
||||||
))
|
))
|
||||||
|
@ -1,7 +1,10 @@
|
|||||||
use crate::parser::hir;
|
use crate::data::value;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use derive_new::new;
|
use derive_new::new;
|
||||||
use log::{log_enabled, trace};
|
use log::{log_enabled, trace};
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_parser::hir;
|
||||||
|
use nu_protocol::{CommandAction, Primitive, ReturnSuccess, UntaggedValue, Value};
|
||||||
|
|
||||||
use super::ClassifiedInputStream;
|
use super::ClassifiedInputStream;
|
||||||
|
|
||||||
@ -77,7 +80,7 @@ impl Command {
|
|||||||
} => {
|
} => {
|
||||||
context.shell_manager.insert_at_current(Box::new(
|
context.shell_manager.insert_at_current(Box::new(
|
||||||
HelpShell::for_command(
|
HelpShell::for_command(
|
||||||
UntaggedValue::string(cmd).into_value(tag),
|
value::string(cmd).into_value(tag),
|
||||||
&context.registry(),
|
&context.registry(),
|
||||||
).unwrap(),
|
).unwrap(),
|
||||||
));
|
));
|
||||||
@ -126,12 +129,12 @@ impl Command {
|
|||||||
|
|
||||||
doc.render_raw(
|
doc.render_raw(
|
||||||
context.with_host(|host| host.width() - 5),
|
context.with_host(|host| host.width() - 5),
|
||||||
&mut crate::parser::debug::TermColored::new(&mut buffer),
|
&mut nu_source::TermColored::new(&mut buffer),
|
||||||
).unwrap();
|
).unwrap();
|
||||||
|
|
||||||
let value = String::from_utf8_lossy(buffer.as_slice());
|
let value = String::from_utf8_lossy(buffer.as_slice());
|
||||||
|
|
||||||
yield Ok(UntaggedValue::string(value).into_untagged_value())
|
yield Ok(value::string(value).into_untagged_value())
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::parser::{hir, TokenNode};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
|
use nu_parser::{hir, TokenNode};
|
||||||
|
|
||||||
mod dynamic;
|
mod dynamic;
|
||||||
mod external;
|
mod external;
|
||||||
@ -11,7 +11,6 @@ pub(crate) use dynamic::Command as DynamicCommand;
|
|||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
pub(crate) use external::{Command as ExternalCommand, ExternalArg, ExternalArgs, StreamNext};
|
pub(crate) use external::{Command as ExternalCommand, ExternalArg, ExternalArgs, StreamNext};
|
||||||
pub(crate) use internal::Command as InternalCommand;
|
pub(crate) use internal::Command as InternalCommand;
|
||||||
pub(crate) use pipeline::Pipeline as ClassifiedPipeline;
|
|
||||||
|
|
||||||
pub(crate) struct ClassifiedInputStream {
|
pub(crate) struct ClassifiedInputStream {
|
||||||
pub(crate) objects: InputStream,
|
pub(crate) objects: InputStream,
|
||||||
@ -21,7 +20,7 @@ pub(crate) struct ClassifiedInputStream {
|
|||||||
impl ClassifiedInputStream {
|
impl ClassifiedInputStream {
|
||||||
pub(crate) fn new() -> ClassifiedInputStream {
|
pub(crate) fn new() -> ClassifiedInputStream {
|
||||||
ClassifiedInputStream {
|
ClassifiedInputStream {
|
||||||
objects: vec![UntaggedValue::nothing().into_untagged_value()].into(),
|
objects: vec![crate::data::value::nothing().into_untagged_value()].into(),
|
||||||
stdin: None,
|
stdin: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_protocol::{Signature, SyntaxShape};
|
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -150,10 +150,10 @@ impl CompareValues {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn coerce_compare(
|
pub(crate) fn coerce_compare(
|
||||||
left: &Value,
|
left: &UntaggedValue,
|
||||||
right: &Value,
|
right: &UntaggedValue,
|
||||||
) -> Result<CompareValues, (&'static str, &'static str)> {
|
) -> Result<CompareValues, (&'static str, &'static str)> {
|
||||||
match (&left.value, &right.value) {
|
match (left, right) {
|
||||||
(UntaggedValue::Primitive(left), UntaggedValue::Primitive(right)) => {
|
(UntaggedValue::Primitive(left), UntaggedValue::Primitive(right)) => {
|
||||||
coerce_compare_primitive(left, right)
|
coerce_compare_primitive(left, right)
|
||||||
}
|
}
|
||||||
|
@ -98,8 +98,8 @@ pub fn nothing() -> UntaggedValue {
|
|||||||
|
|
||||||
pub fn compare_values(
|
pub fn compare_values(
|
||||||
operator: &Operator,
|
operator: &Operator,
|
||||||
left: &Value,
|
left: &UntaggedValue,
|
||||||
right: &Value,
|
right: &UntaggedValue,
|
||||||
) -> Result<bool, (&'static str, &'static str)> {
|
) -> Result<bool, (&'static str, &'static str)> {
|
||||||
match operator {
|
match operator {
|
||||||
_ => {
|
_ => {
|
||||||
|
@ -1,13 +1,7 @@
|
|||||||
use crate::context::CommandRegistry;
|
use crate::context::CommandRegistry;
|
||||||
use crate::data::base::Block;
|
use crate::data::base::Block;
|
||||||
use crate::data::value;
|
use crate::data::value;
|
||||||
use crate::errors::ArgumentError;
|
|
||||||
use crate::evaluate::operator::apply_operator;
|
use crate::evaluate::operator::apply_operator;
|
||||||
use crate::parser::hir::path::{ColumnPath, UnspannedPathMember};
|
|
||||||
use crate::parser::{
|
|
||||||
hir::{self, Expression, RawExpression},
|
|
||||||
CommandRegistry,
|
|
||||||
};
|
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::TaggedDictBuilder;
|
use crate::TaggedDictBuilder;
|
||||||
use log::trace;
|
use log::trace;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::data::base::{Primitive, UntaggedValue, Value};
|
use crate::data::value;
|
||||||
use crate::parser::Operator;
|
use nu_parser::Operator;
|
||||||
use crate::traits::ShellTypeName;
|
use nu_protocol::{Primitive, ShellTypeName, UntaggedValue, Value};
|
||||||
use std::ops::Not;
|
use std::ops::Not;
|
||||||
|
|
||||||
pub fn apply_operator(
|
pub fn apply_operator(
|
||||||
@ -14,12 +14,10 @@ pub fn apply_operator(
|
|||||||
| Operator::LessThan
|
| Operator::LessThan
|
||||||
| Operator::GreaterThan
|
| Operator::GreaterThan
|
||||||
| Operator::LessThanOrEqual
|
| Operator::LessThanOrEqual
|
||||||
| Operator::GreaterThanOrEqual => left.compare(op, right).map(UntaggedValue::boolean),
|
| Operator::GreaterThanOrEqual => left.compare(op, right).map(value::boolean),
|
||||||
Operator::Dot => Ok(UntaggedValue::boolean(false)),
|
Operator::Dot => Ok(value::boolean(false)),
|
||||||
Operator::Contains => contains(left, right).map(UntaggedValue::boolean),
|
Operator::Contains => contains(left, right).map(value::boolean),
|
||||||
Operator::NotContains => contains(left, right)
|
Operator::NotContains => contains(left, right).map(Not::not).map(value::boolean),
|
||||||
.map(Not::not)
|
|
||||||
.map(UntaggedValue::boolean),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user