Merge pull request #1073 from jonathandturner/docker_wrap

Remove partial docker plugin. Embed->wrap
This commit is contained in:
Jonathan Turner 2019-12-08 21:08:03 -08:00 committed by GitHub
commit c9d9eec7f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 109 additions and 233 deletions

View File

@ -147,10 +147,6 @@ path = "src/plugins/sum.rs"
name = "nu_plugin_average" name = "nu_plugin_average"
path = "src/plugins/average.rs" path = "src/plugins/average.rs"
[[bin]]
name = "nu_plugin_embed"
path = "src/plugins/embed.rs"
[[bin]] [[bin]]
name = "nu_plugin_str" name = "nu_plugin_str"
path = "src/plugins/str.rs" path = "src/plugins/str.rs"
@ -168,11 +164,6 @@ name = "nu_plugin_tree"
path = "src/plugins/tree.rs" path = "src/plugins/tree.rs"
required-features = ["tree"] required-features = ["tree"]
[[bin]]
name = "nu_plugin_docker"
path = "src/plugins/docker.rs"
required-features = ["docker"]
[[bin]] [[bin]]
name = "nu" name = "nu"
path = "src/main.rs" path = "src/main.rs"

View File

@ -310,6 +310,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
whole_stream_command(Which), whole_stream_command(Which),
whole_stream_command(Debug), whole_stream_command(Debug),
whole_stream_command(Range), whole_stream_command(Range),
whole_stream_command(Wrap),
]); ]);
cfg_if::cfg_if! { cfg_if::cfg_if! {

View File

@ -93,6 +93,7 @@ pub(crate) mod version;
pub(crate) mod what; pub(crate) mod what;
pub(crate) mod where_; pub(crate) mod where_;
pub(crate) mod which_; pub(crate) mod which_;
pub(crate) mod wrap;
pub(crate) use autoview::Autoview; pub(crate) use autoview::Autoview;
pub(crate) use cd::CD; pub(crate) use cd::CD;
@ -186,3 +187,4 @@ pub(crate) use version::Version;
pub(crate) use what::What; pub(crate) use what::What;
pub(crate) use where_::Where; pub(crate) use where_::Where;
pub(crate) use which_::Which; pub(crate) use which_::Which;
pub(crate) use wrap::Wrap;

102
src/commands/wrap.rs Normal file
View File

@ -0,0 +1,102 @@
use crate::commands::WholeStreamCommand;
use crate::context::CommandRegistry;
use crate::prelude::*;
use indexmap::IndexMap;
use nu_errors::ShellError;
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
use nu_source::Tagged;
pub struct Wrap;
#[derive(Deserialize)]
struct WrapArgs {
column: Option<Tagged<String>>,
}
impl WholeStreamCommand for Wrap {
fn name(&self) -> &str {
"wrap"
}
fn signature(&self) -> Signature {
Signature::build("wrap").optional(
"column",
SyntaxShape::String,
"the name of the new column",
)
}
fn usage(&self) -> &str {
"Wraps the given data in a table."
}
fn run(
&self,
args: CommandArgs,
registry: &CommandRegistry,
) -> Result<OutputStream, ShellError> {
args.process(registry, wrap)?.run()
}
}
fn wrap(
WrapArgs { column }: WrapArgs,
context: RunnableContext,
) -> Result<OutputStream, ShellError> {
let mut input = context.input;
let stream = async_stream! {
let mut result_table = vec![];
let mut are_all_rows = true;
while let Some(value) = input.next().await {
match value {
Value {
value: UntaggedValue::Row(_),
..
} => {
result_table.push(value);
}
_ => {
are_all_rows = false;
let mut index_map = IndexMap::new();
index_map.insert(
match &column {
Some(key) => key.item.clone(),
None => "Column".into(),
},
value,
);
result_table.push(UntaggedValue::row(index_map).into_value(Tag::unknown()));
}
}
}
if are_all_rows {
let mut index_map = IndexMap::new();
index_map.insert(
match &column {
Some(key) => key.item.clone(),
None => "Column".into(),
},
UntaggedValue::table(&result_table).into_value(Tag::unknown()),
);
let row = UntaggedValue::row(index_map).into_untagged_value();
yield ReturnSuccess::value(row);
} else {
for item in result_table
.iter()
.map(|row| ReturnSuccess::value(row.clone())) {
yield item;
}
}
};
Ok(stream.to_output_stream())
}

View File

@ -1,115 +0,0 @@
use futures::executor::block_on;
use nu::{
serve_plugin, CallInfo, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError, Signature,
SyntaxShape, Tag, Tagged, TaggedDictBuilder, Value,
};
use std::process::Command;
use std::str;
struct Docker;
impl Docker {
fn new() -> Self {
Self
}
}
async fn docker(sub_command: &String, name: Tag) -> Result<Vec<Value>, ShellError> {
match sub_command.as_str() {
"ps" => docker_ps(name),
"images" => docker_images(name),
_ => Err(ShellError::labeled_error(
"Unsupported Docker command",
"unknown docker command",
name,
)),
}
}
fn process_docker_output(cmd_output: &str, tag: Tag) -> Result<Vec<Value>, ShellError> {
let columns: Vec<&str> = cmd_output.lines().collect();
let header: Vec<&str> = columns
.iter()
.take(1)
.next()
.unwrap()
.split_whitespace()
.collect();
let mut output = vec![];
for line in columns.iter().skip(1) {
let values: Vec<&str> = line
.trim_end()
.split(" ") // Some columns values contains spaces to split by two spaces
.filter(|s| s.trim() != "")
.collect();
let mut dict = TaggedDictBuilder::new(&tag);
for (i, v) in values.iter().enumerate() {
dict.insert(header[i].to_string(), value::string(v.trim().to_string()));
}
output.push(dict.into_value());
}
Ok(output)
}
pub fn docker_images(tag: Tag) -> Result<Vec<Value>, ShellError> {
let output = Command::new("docker")
.arg("images")
.output()
.expect("failed to execute process.");
let ps_output = str::from_utf8(&output.stdout).unwrap();
let out = process_docker_output(ps_output, tag);
out
}
pub fn docker_ps(tag: Tag) -> Result<Vec<Value>, ShellError> {
let output = Command::new("docker")
.arg("ps")
.output()
.expect("failed to execute process.");
let ps_output = str::from_utf8(&output.stdout).unwrap();
let out = process_docker_output(ps_output, tag);
out
}
impl Plugin for Docker {
fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("docker")
.required("sub_command", SyntaxShape::Member)
.filter())
}
fn begin_filter(&mut self, callinfo: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
if let Some(args) = callinfo.args.positional {
match &args[0] {
Value {
value: UntaggedValue::Primitive(Primitive::String(command)),
..
} => match block_on(docker(&command, args[0].tag())) {
Ok(v) => return Ok(v.into_iter().map(ReturnSuccess::value).collect()),
Err(e) => return Err(e),
},
_ => return Err(ShellError::type_error("string", args[0].tagged_type_name())),
}
}
Ok(vec![])
}
fn filter(&mut self, _: Value) -> Result<Vec<ReturnValue>, ShellError> {
Ok(vec![])
}
}
fn main() {
serve_plugin(&mut Docker::new());
}

View File

@ -1,105 +0,0 @@
#[macro_use]
extern crate indexmap;
use nu::{serve_plugin, Plugin};
use nu_errors::ShellError;
use nu_protocol::{
CallInfo, Primitive, ReturnSuccess, ReturnValue, Signature, SpannedTypeName, SyntaxShape,
UntaggedValue, Value,
};
use nu_source::Tag;
struct Embed {
field: Option<String>,
are_all_rows: bool,
values: Vec<Value>,
}
impl Embed {
fn new() -> Embed {
Embed {
field: None,
are_all_rows: true,
values: Vec::new(),
}
}
fn embed(&mut self, value: Value) -> Result<(), ShellError> {
match &value {
Value {
value: UntaggedValue::Row(_),
..
} => {
self.values.push(value);
}
_ => {
self.are_all_rows = false;
self.values.push(
UntaggedValue::row(indexmap! {
match &self.field {
Some(key) => key.clone(),
None => "Column".into()
} => value
})
.into_value(Tag::unknown()),
);
}
}
Ok(())
}
}
impl Plugin for Embed {
fn config(&mut self) -> Result<Signature, ShellError> {
Ok(Signature::build("embed")
.desc("Embeds a new field to the table.")
.optional("field", SyntaxShape::String, "the name of the new column")
.filter())
}
fn begin_filter(&mut self, call_info: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
if let Some(args) = call_info.args.positional {
match &args[0] {
Value {
value: UntaggedValue::Primitive(Primitive::String(s)),
..
} => {
self.field = Some(s.clone());
self.values = Vec::new();
}
value => return Err(ShellError::type_error("string", value.spanned_type_name())),
}
}
Ok(vec![])
}
fn filter(&mut self, input: Value) -> Result<Vec<ReturnValue>, ShellError> {
self.embed(input)?;
Ok(vec![])
}
fn end_filter(&mut self) -> Result<Vec<ReturnValue>, ShellError> {
if self.are_all_rows {
let row = UntaggedValue::row(indexmap! {
match &self.field {
Some(key) => key.clone(),
None => "Column".into(),
} => UntaggedValue::table(&self.values).into_value(Tag::unknown()),
})
.into_untagged_value();
Ok(vec![ReturnSuccess::value(row)])
} else {
Ok(self
.values
.iter()
.map(|row| ReturnSuccess::value(row.clone()))
.collect::<Vec<_>>())
}
}
}
fn main() {
serve_plugin(&mut Embed::new());
}

View File

@ -729,7 +729,7 @@ fn can_get_reverse_first() {
} }
#[test] #[test]
fn embed_rows_into_a_row() { fn wrap_rows_into_a_row() {
Playground::setup("embed_test_1", |dirs, sandbox| { Playground::setup("embed_test_1", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContentToBeTrimmed( sandbox.with_files(vec![FileWithContentToBeTrimmed(
"los_tres_caballeros.txt", "los_tres_caballeros.txt",
@ -746,7 +746,7 @@ fn embed_rows_into_a_row() {
r#" r#"
open los_tres_caballeros.txt open los_tres_caballeros.txt
| from-csv | from-csv
| embed caballeros | wrap caballeros
| get caballeros | get caballeros
| nth 0 | nth 0
| get last_name | get last_name
@ -759,7 +759,7 @@ fn embed_rows_into_a_row() {
} }
#[test] #[test]
fn embed_rows_into_a_table() { fn wrap_rows_into_a_table() {
Playground::setup("embed_test_2", |dirs, sandbox| { Playground::setup("embed_test_2", |dirs, sandbox| {
sandbox.with_files(vec![FileWithContentToBeTrimmed( sandbox.with_files(vec![FileWithContentToBeTrimmed(
"los_tres_caballeros.txt", "los_tres_caballeros.txt",
@ -777,7 +777,7 @@ fn embed_rows_into_a_table() {
open los_tres_caballeros.txt open los_tres_caballeros.txt
| from-csv | from-csv
| get last_name | get last_name
| embed caballero | wrap caballero
| nth 2 | nth 2
| get caballero | get caballero
| echo $it | echo $it