mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 16:33:37 +01:00
Merge pull request #1073 from jonathandturner/docker_wrap
Remove partial docker plugin. Embed->wrap
This commit is contained in:
commit
c9d9eec7f8
@ -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"
|
||||||
|
@ -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! {
|
||||||
|
@ -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
102
src/commands/wrap.rs
Normal 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())
|
||||||
|
}
|
@ -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());
|
|
||||||
}
|
|
@ -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());
|
|
||||||
}
|
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user