Merge branch 'master' of github.com:nushell/nushell
This commit is contained in:
commit
0728c23ec0
41
Cargo.lock
generated
41
Cargo.lock
generated
|
@ -863,6 +863,16 @@ dependencies = [
|
||||||
"dirs-sys",
|
"dirs-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-next"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1cbcf9241d9e8d106295bd496bbe2e9cffd5fa098f2a8c9e2bbcbf09773c11a8"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if",
|
||||||
|
"dirs-sys-next",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys"
|
name = "dirs-sys"
|
||||||
version = "0.3.4"
|
version = "0.3.4"
|
||||||
|
@ -875,6 +885,17 @@ dependencies = [
|
||||||
"winapi 0.3.8",
|
"winapi 0.3.8",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys-next"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9c60f7b8a8953926148223260454befb50c751d3c50e1c178c4fd1ace4083c9a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users",
|
||||||
|
"winapi 0.3.8",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "doc-comment"
|
name = "doc-comment"
|
||||||
version = "0.3.3"
|
version = "0.3.3"
|
||||||
|
@ -2175,7 +2196,6 @@ dependencies = [
|
||||||
"nu_plugin_fetch",
|
"nu_plugin_fetch",
|
||||||
"nu_plugin_inc",
|
"nu_plugin_inc",
|
||||||
"nu_plugin_match",
|
"nu_plugin_match",
|
||||||
"nu_plugin_parse",
|
|
||||||
"nu_plugin_post",
|
"nu_plugin_post",
|
||||||
"nu_plugin_ps",
|
"nu_plugin_ps",
|
||||||
"nu_plugin_start",
|
"nu_plugin_start",
|
||||||
|
@ -2476,19 +2496,6 @@ dependencies = [
|
||||||
"regex",
|
"regex",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "nu_plugin_parse"
|
|
||||||
version = "0.14.1"
|
|
||||||
dependencies = [
|
|
||||||
"futures 0.3.5",
|
|
||||||
"nu-build",
|
|
||||||
"nu-errors",
|
|
||||||
"nu-plugin",
|
|
||||||
"nu-protocol",
|
|
||||||
"nu-source",
|
|
||||||
"regex",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "nu_plugin_post"
|
name = "nu_plugin_post"
|
||||||
version = "0.14.1"
|
version = "0.14.1"
|
||||||
|
@ -3337,12 +3344,12 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustyline"
|
name = "rustyline"
|
||||||
version = "6.1.2"
|
version = "6.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1cd20b28d972040c627e209eb29f19c24a71a19d661cc5a220089176e20ee202"
|
checksum = "3358c21cbbc1a751892528db4e1de4b7a2b6a73f001e215aaba97d712cfa9777"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"dirs 2.0.2",
|
"dirs-next",
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"memchr",
|
"memchr",
|
||||||
|
|
|
@ -29,7 +29,6 @@ nu_plugin_binaryview = { version = "0.14.1", path = "./crates/nu_plugin_binaryvi
|
||||||
nu_plugin_fetch = { version = "0.14.1", path = "./crates/nu_plugin_fetch", optional=true }
|
nu_plugin_fetch = { version = "0.14.1", path = "./crates/nu_plugin_fetch", optional=true }
|
||||||
nu_plugin_inc = { version = "0.14.1", path = "./crates/nu_plugin_inc", optional=true }
|
nu_plugin_inc = { version = "0.14.1", path = "./crates/nu_plugin_inc", optional=true }
|
||||||
nu_plugin_match = { version = "0.14.1", path = "./crates/nu_plugin_match", optional=true }
|
nu_plugin_match = { version = "0.14.1", path = "./crates/nu_plugin_match", optional=true }
|
||||||
nu_plugin_parse = { version = "0.14.1", path = "./crates/nu_plugin_parse", optional=true }
|
|
||||||
nu_plugin_post = { version = "0.14.1", path = "./crates/nu_plugin_post", optional=true }
|
nu_plugin_post = { version = "0.14.1", path = "./crates/nu_plugin_post", optional=true }
|
||||||
nu_plugin_ps = { version = "0.14.1", path = "./crates/nu_plugin_ps", optional=true }
|
nu_plugin_ps = { version = "0.14.1", path = "./crates/nu_plugin_ps", optional=true }
|
||||||
nu_plugin_start = { version = "0.1.0", path = "./crates/nu_plugin_start", optional=true }
|
nu_plugin_start = { version = "0.1.0", path = "./crates/nu_plugin_start", optional=true }
|
||||||
|
@ -59,7 +58,7 @@ nu-build = { version = "0.14.1", path = "./crates/nu-build" }
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["sys", "ps", "textview", "inc"]
|
default = ["sys", "ps", "textview", "inc"]
|
||||||
stable = ["default", "starship-prompt", "binaryview", "match", "tree", "parse", "post", "fetch", "clipboard-cli", "trash-support", "start"]
|
stable = ["default", "starship-prompt", "binaryview", "match", "tree", "post", "fetch", "clipboard-cli", "trash-support", "start"]
|
||||||
|
|
||||||
# Default
|
# Default
|
||||||
textview = ["crossterm", "syntect", "url", "nu_plugin_textview"]
|
textview = ["crossterm", "syntect", "url", "nu_plugin_textview"]
|
||||||
|
@ -71,7 +70,6 @@ inc = ["semver", "nu_plugin_inc"]
|
||||||
binaryview = ["nu_plugin_binaryview"]
|
binaryview = ["nu_plugin_binaryview"]
|
||||||
fetch = ["nu_plugin_fetch"]
|
fetch = ["nu_plugin_fetch"]
|
||||||
match = ["nu_plugin_match"]
|
match = ["nu_plugin_match"]
|
||||||
parse = ["nu_plugin_parse"]
|
|
||||||
post = ["nu_plugin_post"]
|
post = ["nu_plugin_post"]
|
||||||
trace = ["nu-parser/trace"]
|
trace = ["nu-parser/trace"]
|
||||||
tree = ["nu_plugin_tree"]
|
tree = ["nu_plugin_tree"]
|
||||||
|
@ -120,11 +118,6 @@ name = "nu_plugin_stable_match"
|
||||||
path = "src/plugins/nu_plugin_stable_match.rs"
|
path = "src/plugins/nu_plugin_stable_match.rs"
|
||||||
required-features = ["match"]
|
required-features = ["match"]
|
||||||
|
|
||||||
[[bin]]
|
|
||||||
name = "nu_plugin_stable_parse"
|
|
||||||
path = "src/plugins/nu_plugin_stable_parse.rs"
|
|
||||||
required-features = ["parse"]
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "nu_plugin_stable_post"
|
name = "nu_plugin_stable_post"
|
||||||
path = "src/plugins/nu_plugin_stable_post.rs"
|
path = "src/plugins/nu_plugin_stable_post.rs"
|
||||||
|
|
|
@ -68,7 +68,7 @@ query_interface = "0.3.5"
|
||||||
rand = "0.7"
|
rand = "0.7"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
roxmltree = "0.11.0"
|
roxmltree = "0.11.0"
|
||||||
rustyline = "6.1.2"
|
rustyline = "6.2.0"
|
||||||
serde = { version = "1.0.110", features = ["derive"] }
|
serde = { version = "1.0.110", features = ["derive"] }
|
||||||
serde-hjson = "0.9.1"
|
serde-hjson = "0.9.1"
|
||||||
serde_bytes = "0.11.4"
|
serde_bytes = "0.11.4"
|
||||||
|
|
|
@ -291,6 +291,7 @@ pub fn create_default_context(
|
||||||
whole_stream_command(Lines),
|
whole_stream_command(Lines),
|
||||||
whole_stream_command(Trim),
|
whole_stream_command(Trim),
|
||||||
whole_stream_command(Echo),
|
whole_stream_command(Echo),
|
||||||
|
whole_stream_command(Parse),
|
||||||
whole_stream_command(Str),
|
whole_stream_command(Str),
|
||||||
whole_stream_command(StrToDecimal),
|
whole_stream_command(StrToDecimal),
|
||||||
whole_stream_command(StrToInteger),
|
whole_stream_command(StrToInteger),
|
||||||
|
|
|
@ -74,6 +74,7 @@ pub(crate) mod mv;
|
||||||
pub(crate) mod next;
|
pub(crate) mod next;
|
||||||
pub(crate) mod nth;
|
pub(crate) mod nth;
|
||||||
pub(crate) mod open;
|
pub(crate) mod open;
|
||||||
|
pub(crate) mod parse;
|
||||||
pub(crate) mod pivot;
|
pub(crate) mod pivot;
|
||||||
pub(crate) mod plugin;
|
pub(crate) mod plugin;
|
||||||
pub(crate) mod prepend;
|
pub(crate) mod prepend;
|
||||||
|
@ -203,6 +204,7 @@ pub(crate) use mv::Move;
|
||||||
pub(crate) use next::Next;
|
pub(crate) use next::Next;
|
||||||
pub(crate) use nth::Nth;
|
pub(crate) use nth::Nth;
|
||||||
pub(crate) use open::Open;
|
pub(crate) use open::Open;
|
||||||
|
pub(crate) use parse::Parse;
|
||||||
pub(crate) use pivot::Pivot;
|
pub(crate) use pivot::Pivot;
|
||||||
pub(crate) use prepend::Prepend;
|
pub(crate) use prepend::Prepend;
|
||||||
pub(crate) use prev::Previous;
|
pub(crate) use prev::Previous;
|
||||||
|
|
|
@ -182,8 +182,8 @@ pub fn get_help(cmd: &dyn WholeStreamCommand, registry: &CommandRegistry) -> Str
|
||||||
|
|
||||||
if !signature.positional.is_empty() || signature.rest_positional.is_some() {
|
if !signature.positional.is_empty() || signature.rest_positional.is_some() {
|
||||||
long_desc.push_str("\nParameters:\n");
|
long_desc.push_str("\nParameters:\n");
|
||||||
for positional in signature.positional {
|
for positional in &signature.positional {
|
||||||
match positional.0 {
|
match &positional.0 {
|
||||||
PositionalType::Mandatory(name, _m) => {
|
PositionalType::Mandatory(name, _m) => {
|
||||||
long_desc.push_str(&format!(" <{}> {}\n", name, positional.1));
|
long_desc.push_str(&format!(" <{}> {}\n", name, positional.1));
|
||||||
}
|
}
|
||||||
|
@ -193,75 +193,12 @@ pub fn get_help(cmd: &dyn WholeStreamCommand, registry: &CommandRegistry) -> Str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(rest_positional) = signature.rest_positional {
|
if let Some(rest_positional) = &signature.rest_positional {
|
||||||
long_desc.push_str(&format!(" ...args: {}\n", rest_positional.1));
|
long_desc.push_str(&format!(" ...args: {}\n", rest_positional.1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !signature.named.is_empty() {
|
if !signature.named.is_empty() {
|
||||||
long_desc.push_str("\nFlags:\n");
|
long_desc.push_str(&get_flags_section(&signature))
|
||||||
for (flag, ty) in signature.named {
|
|
||||||
let msg = match ty.0 {
|
|
||||||
NamedType::Switch(s) => {
|
|
||||||
if let Some(c) = s {
|
|
||||||
format!(
|
|
||||||
" -{}, --{}{} {}\n",
|
|
||||||
c,
|
|
||||||
flag,
|
|
||||||
if !ty.1.is_empty() { ":" } else { "" },
|
|
||||||
ty.1
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
" --{}{} {}\n",
|
|
||||||
flag,
|
|
||||||
if !ty.1.is_empty() { ":" } else { "" },
|
|
||||||
ty.1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NamedType::Mandatory(s, m) => {
|
|
||||||
if let Some(c) = s {
|
|
||||||
format!(
|
|
||||||
" -{}, --{} <{}> (required parameter){} {}\n",
|
|
||||||
c,
|
|
||||||
flag,
|
|
||||||
m.display(),
|
|
||||||
if !ty.1.is_empty() { ":" } else { "" },
|
|
||||||
ty.1
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
" --{} <{}> (required parameter){} {}\n",
|
|
||||||
flag,
|
|
||||||
m.display(),
|
|
||||||
if !ty.1.is_empty() { ":" } else { "" },
|
|
||||||
ty.1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
NamedType::Optional(s, o) => {
|
|
||||||
if let Some(c) = s {
|
|
||||||
format!(
|
|
||||||
" -{}, --{} <{}>{} {}\n",
|
|
||||||
c,
|
|
||||||
flag,
|
|
||||||
o.display(),
|
|
||||||
if !ty.1.is_empty() { ":" } else { "" },
|
|
||||||
ty.1
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
format!(
|
|
||||||
" --{} <{}>{} {}\n",
|
|
||||||
flag,
|
|
||||||
o.display(),
|
|
||||||
if !ty.1.is_empty() { ":" } else { "" },
|
|
||||||
ty.1
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
long_desc.push_str(&msg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let palette = crate::shell::palette::DefaultPalette {};
|
let palette = crate::shell::palette::DefaultPalette {};
|
||||||
|
@ -283,6 +220,75 @@ pub fn get_help(cmd: &dyn WholeStreamCommand, registry: &CommandRegistry) -> Str
|
||||||
long_desc
|
long_desc
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_flags_section(signature: &Signature) -> String {
|
||||||
|
let mut long_desc = String::new();
|
||||||
|
long_desc.push_str("\nFlags:\n");
|
||||||
|
for (flag, ty) in &signature.named {
|
||||||
|
let msg = match ty.0 {
|
||||||
|
NamedType::Switch(s) => {
|
||||||
|
if let Some(c) = s {
|
||||||
|
format!(
|
||||||
|
" -{}, --{}{} {}\n",
|
||||||
|
c,
|
||||||
|
flag,
|
||||||
|
if !ty.1.is_empty() { ":" } else { "" },
|
||||||
|
ty.1
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
" --{}{} {}\n",
|
||||||
|
flag,
|
||||||
|
if !ty.1.is_empty() { ":" } else { "" },
|
||||||
|
ty.1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NamedType::Mandatory(s, m) => {
|
||||||
|
if let Some(c) = s {
|
||||||
|
format!(
|
||||||
|
" -{}, --{} <{}> (required parameter){} {}\n",
|
||||||
|
c,
|
||||||
|
flag,
|
||||||
|
m.display(),
|
||||||
|
if !ty.1.is_empty() { ":" } else { "" },
|
||||||
|
ty.1
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
" --{} <{}> (required parameter){} {}\n",
|
||||||
|
flag,
|
||||||
|
m.display(),
|
||||||
|
if !ty.1.is_empty() { ":" } else { "" },
|
||||||
|
ty.1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
NamedType::Optional(s, o) => {
|
||||||
|
if let Some(c) = s {
|
||||||
|
format!(
|
||||||
|
" -{}, --{} <{}>{} {}\n",
|
||||||
|
c,
|
||||||
|
flag,
|
||||||
|
o.display(),
|
||||||
|
if !ty.1.is_empty() { ":" } else { "" },
|
||||||
|
ty.1
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
format!(
|
||||||
|
" --{} <{}>{} {}\n",
|
||||||
|
flag,
|
||||||
|
o.display(),
|
||||||
|
if !ty.1.is_empty() { ":" } else { "" },
|
||||||
|
ty.1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
long_desc.push_str(&msg);
|
||||||
|
}
|
||||||
|
long_desc
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Help;
|
use super::Help;
|
||||||
|
|
|
@ -32,7 +32,7 @@ impl WholeStreamCommand for Mkdir {
|
||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
mkdir(args, registry)
|
mkdir(args, registry).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
@ -44,20 +44,13 @@ impl WholeStreamCommand for Mkdir {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mkdir(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn mkdir(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let name = args.call_info.name_tag.clone();
|
||||||
let name = args.call_info.name_tag.clone();
|
let shell_manager = args.shell_manager.clone();
|
||||||
let shell_manager = args.shell_manager.clone();
|
let (args, _) = args.process(®istry).await?;
|
||||||
let (args, _) = args.process(®istry).await?;
|
|
||||||
let mut result = shell_manager.mkdir(args, name)?;
|
|
||||||
|
|
||||||
while let Some(item) = result.next().await {
|
shell_manager.mkdir(args, name)
|
||||||
yield item;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
175
crates/nu-cli/src/commands/parse/command.rs
Normal file
175
crates/nu-cli/src/commands/parse/command.rs
Normal file
|
@ -0,0 +1,175 @@
|
||||||
|
use crate::commands::WholeStreamCommand;
|
||||||
|
use crate::prelude::*;
|
||||||
|
use nu_errors::ShellError;
|
||||||
|
use nu_protocol::{Signature, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value};
|
||||||
|
use nu_source::Tagged;
|
||||||
|
|
||||||
|
use regex::Regex;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Arguments {
|
||||||
|
pattern: Tagged<String>,
|
||||||
|
regex: Tagged<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Command;
|
||||||
|
|
||||||
|
#[async_trait]
|
||||||
|
impl WholeStreamCommand for Command {
|
||||||
|
fn name(&self) -> &str {
|
||||||
|
"parse"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn signature(&self) -> Signature {
|
||||||
|
Signature::build("parse")
|
||||||
|
.required(
|
||||||
|
"pattern",
|
||||||
|
SyntaxShape::String,
|
||||||
|
"the pattern to match. Eg) \"{foo}: {bar}\"",
|
||||||
|
)
|
||||||
|
.switch("regex", "use full regex syntax for patterns", Some('r'))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn usage(&self) -> &str {
|
||||||
|
"Parse columns from string data using a simple pattern."
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn run(
|
||||||
|
&self,
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
operate(args, registry).await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn operate(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let name_tag = args.call_info.name_tag.clone();
|
||||||
|
let (Arguments { regex, pattern }, mut input) = args.process(®istry).await?;
|
||||||
|
|
||||||
|
let regex_pattern = if let Tagged { item: true, tag } = regex {
|
||||||
|
Regex::new(&pattern.item)
|
||||||
|
.map_err(|_| ShellError::labeled_error("Invalid regex", "invalid regex", tag.span))?
|
||||||
|
} else {
|
||||||
|
let parse_regex = build_regex(&pattern.item, name_tag.clone())?;
|
||||||
|
|
||||||
|
Regex::new(&parse_regex).map_err(|_| {
|
||||||
|
ShellError::labeled_error("Invalid pattern", "invalid pattern", name_tag.span)
|
||||||
|
})?
|
||||||
|
};
|
||||||
|
|
||||||
|
let columns = column_names(®ex_pattern);
|
||||||
|
let mut parsed: VecDeque<Value> = VecDeque::new();
|
||||||
|
|
||||||
|
while let Some(v) = input.next().await {
|
||||||
|
match v.as_string() {
|
||||||
|
Ok(s) => {
|
||||||
|
let results = regex_pattern.captures_iter(&s);
|
||||||
|
|
||||||
|
for c in results {
|
||||||
|
let mut dict = TaggedDictBuilder::new(&v.tag);
|
||||||
|
|
||||||
|
for (column_name, cap) in columns.iter().zip(c.iter().skip(1)) {
|
||||||
|
let cap_string = cap.map(|v| v.as_str()).unwrap_or("").to_string();
|
||||||
|
dict.insert_untagged(column_name, UntaggedValue::string(cap_string));
|
||||||
|
}
|
||||||
|
|
||||||
|
parsed.push_back(dict.into_value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => {
|
||||||
|
return Err(ShellError::labeled_error_with_secondary(
|
||||||
|
"Expected string input",
|
||||||
|
"expected string input",
|
||||||
|
&name_tag,
|
||||||
|
"value originated here",
|
||||||
|
v.tag,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(futures::stream::iter(parsed).to_output_stream())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_regex(input: &str, tag: Tag) -> Result<String, ShellError> {
|
||||||
|
let mut output = "(?s)\\A".to_string();
|
||||||
|
|
||||||
|
//let mut loop_input = input;
|
||||||
|
let mut loop_input = input.chars().peekable();
|
||||||
|
loop {
|
||||||
|
let mut before = String::new();
|
||||||
|
while let Some(c) = loop_input.next() {
|
||||||
|
if c == '{' {
|
||||||
|
// If '{{', still creating a plaintext parse command, but just for a single '{' char
|
||||||
|
if loop_input.peek() == Some(&'{') {
|
||||||
|
let _ = loop_input.next();
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
before.push(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
if !before.is_empty() {
|
||||||
|
output.push_str(®ex::escape(&before));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Look for column as we're now at one
|
||||||
|
let mut column = String::new();
|
||||||
|
while let Some(c) = loop_input.next() {
|
||||||
|
if c == '}' {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
column.push(c);
|
||||||
|
|
||||||
|
if loop_input.peek().is_none() {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
|
"Found opening `{` without an associated closing `}`",
|
||||||
|
"invalid parse pattern",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !column.is_empty() {
|
||||||
|
output.push_str("(?P<");
|
||||||
|
output.push_str(&column);
|
||||||
|
output.push_str(">.*?)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if before.is_empty() && column.is_empty() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
output.push_str("\\z");
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn column_names(regex: &Regex) -> Vec<String> {
|
||||||
|
regex
|
||||||
|
.capture_names()
|
||||||
|
.enumerate()
|
||||||
|
.skip(1)
|
||||||
|
.map(|(i, name)| {
|
||||||
|
name.map(String::from)
|
||||||
|
.unwrap_or_else(|| format!("Capture{}", i))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::Command;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn examples_work_as_expected() {
|
||||||
|
use crate::examples::test as test_examples;
|
||||||
|
|
||||||
|
test_examples(Command {})
|
||||||
|
}
|
||||||
|
}
|
3
crates/nu-cli/src/commands/parse/mod.rs
Normal file
3
crates/nu-cli/src/commands/parse/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
mod command;
|
||||||
|
|
||||||
|
pub use command::Command as Parse;
|
|
@ -49,7 +49,7 @@ impl WholeStreamCommand for Remove {
|
||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
rm(args, registry)
|
rm(args, registry).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
@ -73,27 +73,21 @@ impl WholeStreamCommand for Remove {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rm(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn rm(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let name = args.call_info.name_tag.clone();
|
||||||
let name = args.call_info.name_tag.clone();
|
let shell_manager = args.shell_manager.clone();
|
||||||
let shell_manager = args.shell_manager.clone();
|
let (args, _): (RemoveArgs, _) = args.process(®istry).await?;
|
||||||
let (args, _): (RemoveArgs, _) = args.process(®istry).await?;
|
|
||||||
let mut result = if args.trash.item && args.permanent.item {
|
|
||||||
OutputStream::one(Err(ShellError::labeled_error(
|
|
||||||
"only one of --permanent and --trash can be used",
|
|
||||||
"conflicting flags",
|
|
||||||
name
|
|
||||||
)))
|
|
||||||
} else {
|
|
||||||
shell_manager.rm(args, name)?
|
|
||||||
};
|
|
||||||
while let Some(item) = result.next().await {
|
|
||||||
yield item;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
if args.trash.item && args.permanent.item {
|
||||||
|
return Ok(OutputStream::one(Err(ShellError::labeled_error(
|
||||||
|
"only one of --permanent and --trash can be used",
|
||||||
|
"conflicting flags",
|
||||||
|
name,
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
|
||||||
|
shell_manager.rm(args, name)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -31,7 +31,7 @@ impl WholeStreamCommand for SortBy {
|
||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
sort_by(args, registry)
|
sort_by(args, registry).await
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
|
@ -60,51 +60,59 @@ impl WholeStreamCommand for SortBy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sort_by(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn sort_by(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let tag = args.call_info.name_tag.clone();
|
||||||
let (SortByArgs { rest }, mut input) = args.process(®istry).await?;
|
|
||||||
let mut vec = input.drain_vec().await;
|
|
||||||
|
|
||||||
if vec.is_empty() {
|
let (SortByArgs { rest }, mut input) = args.process(®istry).await?;
|
||||||
return;
|
let mut vec = input.drain_vec().await;
|
||||||
|
|
||||||
|
if vec.is_empty() {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
|
"Error performing sort-by command",
|
||||||
|
"sort-by error",
|
||||||
|
tag,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
for sort_arg in rest.iter() {
|
||||||
|
let match_test = get_data_by_key(&vec[0], sort_arg.borrow_spanned());
|
||||||
|
if match_test == None {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
|
"Can not find column to sort by",
|
||||||
|
"invalid column",
|
||||||
|
sort_arg.borrow_spanned().span,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for sort_arg in rest.iter() {
|
match &vec[0] {
|
||||||
let match_test = get_data_by_key(&vec[0], sort_arg.borrow_spanned());
|
Value {
|
||||||
if match_test == None {
|
value: UntaggedValue::Primitive(_),
|
||||||
yield Err(ShellError::labeled_error(
|
..
|
||||||
"Can not find column to sort by",
|
} => {
|
||||||
"invalid column",
|
vec.sort();
|
||||||
sort_arg.borrow_spanned().span,
|
|
||||||
));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
_ => {
|
||||||
match &vec[0] {
|
let calc_key = |item: &Value| {
|
||||||
Value {
|
rest.iter()
|
||||||
value: UntaggedValue::Primitive(_),
|
.map(|f| get_data_by_key(item, f.borrow_spanned()))
|
||||||
..
|
.collect::<Vec<Option<Value>>>()
|
||||||
} => {
|
};
|
||||||
vec.sort();
|
vec.sort_by_cached_key(calc_key);
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
let calc_key = |item: &Value| {
|
|
||||||
rest.iter()
|
|
||||||
.map(|f| get_data_by_key(item, f.borrow_spanned()))
|
|
||||||
.collect::<Vec<Option<Value>>>()
|
|
||||||
};
|
|
||||||
vec.sort_by_cached_key(calc_key);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
for item in vec {
|
|
||||||
yield item.into();
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
let mut values_vec_deque: VecDeque<Value> = VecDeque::new();
|
||||||
|
|
||||||
|
for item in vec {
|
||||||
|
values_vec_deque.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(futures::stream::iter(values_vec_deque).to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{
|
use nu_protocol::{
|
||||||
ReturnSuccess, Signature, SpannedTypeName, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
|
Signature, SpannedTypeName, SyntaxShape, TaggedDictBuilder, UntaggedValue, Value,
|
||||||
};
|
};
|
||||||
use nu_source::Tagged;
|
use nu_source::Tagged;
|
||||||
|
|
||||||
|
@ -36,32 +36,31 @@ impl WholeStreamCommand for SplitBy {
|
||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
split_by(args, registry)
|
split_by(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split_by(args: CommandArgs, registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
pub async fn split_by(
|
||||||
|
args: CommandArgs,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
let registry = registry.clone();
|
let registry = registry.clone();
|
||||||
let stream = async_stream! {
|
let name = args.call_info.name_tag.clone();
|
||||||
let name = args.call_info.name_tag.clone();
|
let (SplitByArgs { column_name }, input) = args.process(®istry).await?;
|
||||||
let (SplitByArgs { column_name }, mut input) = args.process(®istry).await?;
|
let values: Vec<Value> = input.collect().await;
|
||||||
let values: Vec<Value> = input.collect().await;
|
|
||||||
|
|
||||||
if values.len() > 1 || values.is_empty() {
|
if values.len() > 1 || values.is_empty() {
|
||||||
yield Err(ShellError::labeled_error(
|
return Err(ShellError::labeled_error(
|
||||||
"Expected table from pipeline",
|
"Expected table from pipeline",
|
||||||
"requires a table input",
|
"requires a table input",
|
||||||
column_name.span()
|
column_name.span(),
|
||||||
))
|
));
|
||||||
} else {
|
}
|
||||||
match split(&column_name, &values[0], name) {
|
|
||||||
Ok(split) => yield ReturnSuccess::value(split),
|
|
||||||
Err(err) => yield Err(err),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
match split(&column_name, &values[0], name) {
|
||||||
|
Ok(split) => Ok(OutputStream::one(split)),
|
||||||
|
Err(err) => Err(err),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn split(
|
pub fn split(
|
||||||
|
|
|
@ -26,21 +26,24 @@ impl WholeStreamCommand for Uniq {
|
||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
uniq(args, registry)
|
uniq(args, registry).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn uniq(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
async fn uniq(args: CommandArgs, _registry: &CommandRegistry) -> Result<OutputStream, ShellError> {
|
||||||
let stream = async_stream! {
|
let input = args.input;
|
||||||
let mut input = args.input;
|
let uniq_values: IndexSet<_> = input.collect().await;
|
||||||
let uniq_values: IndexSet<_> = input.collect().await;
|
|
||||||
|
|
||||||
for item in uniq_values.iter().map(|row| ReturnSuccess::value(row.clone())) {
|
let mut values_vec_deque = VecDeque::new();
|
||||||
yield item;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(stream.to_output_stream())
|
for item in uniq_values
|
||||||
|
.iter()
|
||||||
|
.map(|row| ReturnSuccess::value(row.clone()))
|
||||||
|
{
|
||||||
|
values_vec_deque.push_back(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(futures::stream::iter(values_vec_deque).to_output_stream())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
|
|
@ -1,21 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "nu_plugin_parse"
|
|
||||||
version = "0.14.1"
|
|
||||||
authors = ["The Nu Project Contributors"]
|
|
||||||
edition = "2018"
|
|
||||||
description = "A string parsing plugin for Nushell"
|
|
||||||
license = "MIT"
|
|
||||||
|
|
||||||
[lib]
|
|
||||||
doctest = false
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
nu-plugin = { path = "../nu-plugin", version = "0.14.1" }
|
|
||||||
nu-protocol = { path = "../nu-protocol", version = "0.14.1" }
|
|
||||||
nu-source = { path = "../nu-source", version = "0.14.1" }
|
|
||||||
nu-errors = { path = "../nu-errors", version = "0.14.1" }
|
|
||||||
futures = { version = "0.3", features = ["compat", "io-compat"] }
|
|
||||||
regex = "1"
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
nu-build = { version = "0.14.1", path = "../nu-build" }
|
|
|
@ -1,3 +0,0 @@
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
nu_build::build()
|
|
||||||
}
|
|
|
@ -1,4 +0,0 @@
|
||||||
mod nu;
|
|
||||||
mod parse;
|
|
||||||
|
|
||||||
pub use parse::Parse;
|
|
|
@ -1,7 +0,0 @@
|
||||||
use nu_plugin::serve_plugin;
|
|
||||||
use nu_plugin_parse::Parse;
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
|
||||||
serve_plugin(&mut Parse::new()?);
|
|
||||||
Ok(())
|
|
||||||
}
|
|
|
@ -1,159 +0,0 @@
|
||||||
use regex::{self, Regex};
|
|
||||||
|
|
||||||
use nu_errors::ShellError;
|
|
||||||
use nu_plugin::Plugin;
|
|
||||||
use nu_protocol::{
|
|
||||||
CallInfo, Primitive, ReturnSuccess, ReturnValue, ShellTypeName, Signature, SyntaxShape,
|
|
||||||
TaggedDictBuilder, UntaggedValue, Value,
|
|
||||||
};
|
|
||||||
use nu_source::Tag;
|
|
||||||
|
|
||||||
use crate::Parse;
|
|
||||||
|
|
||||||
impl Plugin for Parse {
|
|
||||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
|
||||||
Ok(Signature::build("parse")
|
|
||||||
.switch("regex", "use full regex syntax for patterns", Some('r'))
|
|
||||||
.required(
|
|
||||||
"pattern",
|
|
||||||
SyntaxShape::String,
|
|
||||||
"the pattern to match. Eg) \"{foo}: {bar}\"",
|
|
||||||
)
|
|
||||||
.filter())
|
|
||||||
}
|
|
||||||
|
|
||||||
fn begin_filter(&mut self, call_info: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
|
||||||
if let Some(ref args) = call_info.args.positional {
|
|
||||||
let value = &args[0];
|
|
||||||
match value {
|
|
||||||
Value {
|
|
||||||
value: UntaggedValue::Primitive(Primitive::String(s)),
|
|
||||||
tag,
|
|
||||||
} => {
|
|
||||||
self.pattern_tag = tag.clone();
|
|
||||||
self.regex = if call_info.args.has("regex") {
|
|
||||||
Regex::new(&s).map_err(|_| {
|
|
||||||
ShellError::labeled_error("Invalid regex", "invalid regex", tag.span)
|
|
||||||
})?
|
|
||||||
} else {
|
|
||||||
let parse_regex = build_regex(&s, tag.clone())?;
|
|
||||||
Regex::new(&parse_regex).map_err(|_| {
|
|
||||||
ShellError::labeled_error(
|
|
||||||
"Invalid pattern",
|
|
||||||
"invalid pattern",
|
|
||||||
tag.span,
|
|
||||||
)
|
|
||||||
})?
|
|
||||||
};
|
|
||||||
|
|
||||||
self.column_names = column_names(&self.regex);
|
|
||||||
}
|
|
||||||
Value { tag, .. } => {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
format!(
|
|
||||||
"Unexpected type in params (found `{}`, expected `String`)",
|
|
||||||
value.type_name()
|
|
||||||
),
|
|
||||||
"unexpected type",
|
|
||||||
tag,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(vec![])
|
|
||||||
}
|
|
||||||
|
|
||||||
fn filter(&mut self, input: Value) -> Result<Vec<ReturnValue>, ShellError> {
|
|
||||||
if let Ok(s) = input.as_string() {
|
|
||||||
Ok(self
|
|
||||||
.regex
|
|
||||||
.captures_iter(&s)
|
|
||||||
.map(|caps| {
|
|
||||||
let mut dict = TaggedDictBuilder::new(&input.tag);
|
|
||||||
for (column_name, cap) in self.column_names.iter().zip(caps.iter().skip(1)) {
|
|
||||||
let cap_string = cap.map(|v| v.as_str()).unwrap_or("").to_string();
|
|
||||||
dict.insert_untagged(column_name, UntaggedValue::string(cap_string));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(ReturnSuccess::Value(dict.into_value()))
|
|
||||||
})
|
|
||||||
.collect())
|
|
||||||
} else {
|
|
||||||
Err(ShellError::labeled_error_with_secondary(
|
|
||||||
"Expected string input",
|
|
||||||
"expected string input",
|
|
||||||
&self.name,
|
|
||||||
"value originated here",
|
|
||||||
input.tag,
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn build_regex(input: &str, tag: Tag) -> Result<String, ShellError> {
|
|
||||||
let mut output = "(?s)\\A".to_string();
|
|
||||||
|
|
||||||
//let mut loop_input = input;
|
|
||||||
let mut loop_input = input.chars().peekable();
|
|
||||||
loop {
|
|
||||||
let mut before = String::new();
|
|
||||||
while let Some(c) = loop_input.next() {
|
|
||||||
if c == '{' {
|
|
||||||
// If '{{', still creating a plaintext parse command, but just for a single '{' char
|
|
||||||
if loop_input.peek() == Some(&'{') {
|
|
||||||
let _ = loop_input.next();
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
before.push(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
if !before.is_empty() {
|
|
||||||
output.push_str(®ex::escape(&before));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look for column as we're now at one
|
|
||||||
let mut column = String::new();
|
|
||||||
while let Some(c) = loop_input.next() {
|
|
||||||
if c == '}' {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
column.push(c);
|
|
||||||
|
|
||||||
if loop_input.peek().is_none() {
|
|
||||||
return Err(ShellError::labeled_error(
|
|
||||||
"Found opening `{` without an associated closing `}`",
|
|
||||||
"invalid parse pattern",
|
|
||||||
tag,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !column.is_empty() {
|
|
||||||
output.push_str("(?P<");
|
|
||||||
output.push_str(&column);
|
|
||||||
output.push_str(">.*?)");
|
|
||||||
}
|
|
||||||
|
|
||||||
if before.is_empty() && column.is_empty() {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output.push_str("\\z");
|
|
||||||
Ok(output)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn column_names(regex: &Regex) -> Vec<String> {
|
|
||||||
regex
|
|
||||||
.capture_names()
|
|
||||||
.enumerate()
|
|
||||||
.skip(1)
|
|
||||||
.map(|(i, name)| {
|
|
||||||
name.map(String::from)
|
|
||||||
.unwrap_or_else(|| format!("Capture{}", i))
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
use nu_source::Tag;
|
|
||||||
use regex::Regex;
|
|
||||||
|
|
||||||
pub struct Parse {
|
|
||||||
pub regex: Regex,
|
|
||||||
pub name: Tag,
|
|
||||||
pub pattern_tag: Tag,
|
|
||||||
pub column_names: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Parse {
|
|
||||||
#[allow(clippy::trivial_regex)]
|
|
||||||
pub fn new() -> Result<Self, Box<dyn std::error::Error>> {
|
|
||||||
Ok(Parse {
|
|
||||||
regex: Regex::new("")?,
|
|
||||||
name: Tag::unknown(),
|
|
||||||
pattern_tag: Tag::unknown(),
|
|
||||||
column_names: vec![],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user