Merge pull request #1003 from andrasio/compact

Compact.
This commit is contained in:
Andrés N. Robalino 2019-11-23 22:03:20 -05:00 committed by GitHub
commit 91698b2657
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 117 additions and 1 deletions

View file

@ -268,6 +268,7 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat
| command | description | | command | description |
| ------------- | ------------- | | ------------- | ------------- |
| append row-data | Append a row to the end of the table | | append row-data | Append a row to the end of the table |
| compact ...columns | Remove rows where given columns are empty |
| count | Show the total number of rows | | count | Show the total number of rows |
| edit column-or-column-path value | Edit an existing column to have a new value | | edit column-or-column-path value | Edit an existing column to have a new value |
| embed column | Creates a new table of one column with the given name, and places the current table inside of it | | embed column | Creates a new table of one column with the given name, and places the current table inside of it |
@ -286,7 +287,7 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat
| reject ...columns | Remove the given columns from the table | | reject ...columns | Remove the given columns from the table |
| reverse | Reverses the table. | | reverse | Reverses the table. |
| skip amount | Skip a number of rows | | skip amount | Skip a number of rows |
| skip-while condition | Skips rows while the condition matches. | | skip-while condition | Skips rows while the condition matches |
| split-by column | Creates a new table with the data from the inner tables splitted by the column given | | split-by column | Creates a new table with the data from the inner tables splitted by the column given |
| sort-by ...columns | Sort by the given columns | | sort-by ...columns | Sort by the given columns |
| str (column) | Apply string function. Optionally use the column of a table | | str (column) | Apply string function. Optionally use the column of a table |

View file

@ -309,6 +309,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
per_item_command(Where), per_item_command(Where),
per_item_command(Echo), per_item_command(Echo),
whole_stream_command(Config), whole_stream_command(Config),
whole_stream_command(Compact),
whole_stream_command(SkipWhile), whole_stream_command(SkipWhile),
per_item_command(Enter), per_item_command(Enter),
per_item_command(Help), per_item_command(Help),

View file

@ -11,6 +11,7 @@ pub(crate) mod cd;
pub(crate) mod classified; pub(crate) mod classified;
pub(crate) mod clip; pub(crate) mod clip;
pub(crate) mod command; pub(crate) mod command;
pub(crate) mod compact;
pub(crate) mod config; pub(crate) mod config;
pub(crate) mod count; pub(crate) mod count;
pub(crate) mod cp; pub(crate) mod cp;
@ -98,6 +99,7 @@ pub(crate) use command::{
pub(crate) use append::Append; pub(crate) use append::Append;
pub(crate) use classified::ClassifiedCommand; pub(crate) use classified::ClassifiedCommand;
pub(crate) use compact::Compact;
pub(crate) use config::Config; pub(crate) use config::Config;
pub(crate) use count::Count; pub(crate) use count::Count;
pub(crate) use cp::Cpy; pub(crate) use cp::Cpy;

53
src/commands/compact.rs Normal file
View file

@ -0,0 +1,53 @@
use crate::commands::WholeStreamCommand;
use crate::errors::ShellError;
use crate::parser::registry::{CommandRegistry, Signature};
use crate::prelude::*;
use futures::stream::StreamExt;
pub struct Compact;
#[derive(Deserialize)]
pub struct CompactArgs {
rest: Vec<Tagged<String>>,
}
impl WholeStreamCommand for Compact {
fn name(&self) -> &str {
"compact"
}
fn signature(&self) -> Signature {
Signature::build("compact").rest(SyntaxShape::Any, "the columns to compact from the table")
}
fn usage(&self) -> &str {
"Creates a table with non-empty rows"
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, compact)?.run()
}
}
pub fn compact(
CompactArgs { rest: columns }: CompactArgs,
RunnableContext { input, .. }: RunnableContext,
) -> Result<OutputStream, ShellError> {
let objects = input.values.take_while(move |item| {
let keep = if columns.is_empty() {
item.is_some()
} else {
columns
.iter()
.all(|field| item.get_data(field).borrow().is_some())
};
futures::future::ready(keep)
});
Ok(objects.from_input_stream())
}

View file

@ -498,6 +498,17 @@ impl Value {
} }
} }
pub(crate) fn is_some(&self) -> bool {
!self.is_none()
}
pub(crate) fn is_none(&self) -> bool {
match self {
Value::Primitive(Primitive::Nothing) => true,
_ => false,
}
}
pub(crate) fn is_error(&self) -> bool { pub(crate) fn is_error(&self) -> bool {
match self { match self {
Value::Error(_err) => true, Value::Error(_err) => true,

View file

@ -3,6 +3,54 @@ mod helpers;
use helpers as h; use helpers as h;
use helpers::{Playground, Stub::*}; use helpers::{Playground, Stub::*};
#[test]
fn compact_rows_where_given_column_is_empty() {
Playground::setup("compact_test_1", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContentToBeTrimmed(
"los_tres_amigos.json",
r#"
{
"amigos": [
{"name": "Yehuda", "rusty_luck": 1},
{"name": "Jonathan", "rusty_luck": 1},
{"name": "Andres", "rusty_luck": 1},
{"name":"GorbyPuff"}
]
}
"#,
)]);
let actual = nu!(
cwd: dirs.test(), h::pipeline(
r#"
open los_tres_amigos.json
| get amigos
| compact rusty_luck
| count
| echo $it
"#
));
assert_eq!(actual, "3");
});
}
#[test]
fn compact_empty_rows_by_default() {
Playground::setup("compact_test_2", |dirs, _| {
let actual = nu!(
cwd: dirs.test(), h::pipeline(
r#"
echo "[1,2,3,14,null]"
| from-json
| compact
| count
| echo $it
"#
));
assert_eq!(actual, "4");
});
}
#[test] #[test]
fn group_by() { fn group_by() {
Playground::setup("group_by_test_1", |dirs, sandbox| { Playground::setup("group_by_test_1", |dirs, sandbox| {