From 9fb9adb6b4e58296b1008724cd830fa9c190fff6 Mon Sep 17 00:00:00 2001 From: rnxypke Date: Wed, 2 Oct 2019 20:56:28 +0200 Subject: [PATCH] add regex match plugin --- Cargo.lock | 1 + Cargo.toml | 5 +++ src/plugins/match.rs | 100 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 src/plugins/match.rs diff --git a/Cargo.lock b/Cargo.lock index 267876726..852fbd610 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1561,6 +1561,7 @@ dependencies = [ "prettytable-rs 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", "ptree 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "rawkey 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "roxmltree 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", "rusqlite 0.20.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustyline 5.0.3 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 6e59dcaad..f51ea06d8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -75,6 +75,7 @@ bigdecimal = { version = "0.1.0", features = ["serde"] } natural = "0.3.0" serde_urlencoded = "0.6.1" sublime_fuzzy = "0.5" +regex = "1" neso = { version = "0.5.0", optional = true } crossterm = { version = "0.10.2", optional = true } @@ -134,6 +135,10 @@ path = "src/plugins/str.rs" name = "nu_plugin_skip" path = "src/plugins/skip.rs" +[[bin]] +name = "nu_plugin_match" +path = "src/plugins/match.rs" + [[bin]] name = "nu_plugin_sys" path = "src/plugins/sys.rs" diff --git a/src/plugins/match.rs b/src/plugins/match.rs new file mode 100644 index 000000000..eee79c666 --- /dev/null +++ b/src/plugins/match.rs @@ -0,0 +1,100 @@ +use nu::{ + serve_plugin, CallInfo, CoerceInto, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, + Signature, SyntaxShape, Tagged, TaggedItem, Value, EvaluatedArgs, +}; +use indexmap::IndexMap; +use regex::Regex; + +struct Match { + column: String, + regex: Regex, +} + +impl Match { + fn new() -> Self { + Match { + column: String::new(), + regex: Regex::new("").unwrap(), + } + } +} + +impl Plugin for Match { + fn config(&mut self) -> Result { + Ok(Signature::build("match") + .desc("filter rows by regex") + .required("member", SyntaxShape::Member) + .required("regex", SyntaxShape::String) + .filter()) + } + fn begin_filter(&mut self, call_info: CallInfo) -> Result, ShellError> { + if let Some(args) = call_info.args.positional { + match &args[0] { + Tagged { + item: Value::Primitive(Primitive::String(s)), + .. + } => { + self.column = s.clone(); + } + _ => { + return Err(ShellError::string(format!( + "Unrecognized type in params: {:?}", args[0]))); + } + } + match &args[1] { + Tagged { + item: Value::Primitive(Primitive::String(s)), + .. + } => { + self.regex = Regex::new(s).unwrap(); + } + _ => { + return Err(ShellError::string(format!( + "Unrecognized type in params: {:?}", args[0]))); + } + } + } + Ok(vec![]) + } + + fn filter(&mut self, input: Tagged) -> Result, ShellError> { + let flag: bool; + match &input { + Tagged { + item: Value::Row(dict), + .. + } => { + if let Some(val) = dict.entries.get(&self.column) { + match val { + Tagged { + item: Value::Primitive(Primitive::String(s)), + .. + } => { + flag = self.regex.is_match(s); + } + _ => { + return Err(ShellError::string(format!( + "value is not a string! {:?}", &val))); + } + } + } else { + return Err(ShellError::string(format!( + "column not in row! {:?} {:?}", &self.column, dict))); + } + } + _ => { + return Err(ShellError::string(format!( + "Not a row! {:?}", &input))); + } + } + if flag { + Ok(vec![Ok(ReturnSuccess::Value(input))]) + } else { + Ok(vec![]) + } + } +} + +fn main() { + serve_plugin(&mut Match::new()); +}