From 1e343ff00cf09b100b29c26aaa95dd57ea5a2b05 Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Fri, 20 Mar 2020 08:18:24 +1300 Subject: [PATCH] Add markdown output (#1503) --- crates/nu-cli/src/cli.rs | 1 + crates/nu-cli/src/commands.rs | 2 + crates/nu-cli/src/commands/to_html.rs | 4 +- crates/nu-cli/src/commands/to_md.rs | 77 +++++++++++++++++++ .../tests/format_conversions/markdown.rs | 25 ++++++ crates/nu-cli/tests/format_conversions/mod.rs | 1 + 6 files changed, 108 insertions(+), 2 deletions(-) create mode 100644 crates/nu-cli/src/commands/to_md.rs create mode 100644 crates/nu-cli/tests/format_conversions/markdown.rs diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index 664c5419bc..e4bafd20c4 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -321,6 +321,7 @@ pub fn create_default_context( whole_stream_command(ToJSON), whole_stream_command(ToSQLite), whole_stream_command(ToDB), + whole_stream_command(ToMarkdown), whole_stream_command(ToTOML), whole_stream_command(ToTSV), whole_stream_command(ToURL), diff --git a/crates/nu-cli/src/commands.rs b/crates/nu-cli/src/commands.rs index c9d363ec55..b97e68a88e 100644 --- a/crates/nu-cli/src/commands.rs +++ b/crates/nu-cli/src/commands.rs @@ -90,6 +90,7 @@ pub(crate) mod to_bson; pub(crate) mod to_csv; pub(crate) mod to_html; pub(crate) mod to_json; +pub(crate) mod to_md; pub(crate) mod to_sqlite; pub(crate) mod to_toml; pub(crate) mod to_tsv; @@ -196,6 +197,7 @@ pub(crate) use to_bson::ToBSON; pub(crate) use to_csv::ToCSV; pub(crate) use to_html::ToHTML; pub(crate) use to_json::ToJSON; +pub(crate) use to_md::ToMarkdown; pub(crate) use to_sqlite::ToDB; pub(crate) use to_sqlite::ToSQLite; pub(crate) use to_toml::ToTOML; diff --git a/crates/nu-cli/src/commands/to_html.rs b/crates/nu-cli/src/commands/to_html.rs index d7d70de3c9..ee33e3bada 100644 --- a/crates/nu-cli/src/commands/to_html.rs +++ b/crates/nu-cli/src/commands/to_html.rs @@ -60,7 +60,7 @@ fn to_html(args: CommandArgs, registry: &CommandRegistry) -> Result { let extension = f.split('.').last().map(String::from); match extension { - Some(s) if ["png", "jpg", "bmp", "gif", "tiff", "jpeg"].contains(&s.as_str()) => { + Some(s) if ["png", "jpg", "bmp", "gif", "tiff", "jpeg"].contains(&s.to_lowercase().as_str()) => { output_string.push_str(" Result { let extension = f.split('.').last().map(String::from); match extension { - Some(s) if s == "svg" => { + Some(s) if s.to_lowercase() == "svg" => { output_string.push_str(""); diff --git a/crates/nu-cli/src/commands/to_md.rs b/crates/nu-cli/src/commands/to_md.rs new file mode 100644 index 0000000000..f46d011b9a --- /dev/null +++ b/crates/nu-cli/src/commands/to_md.rs @@ -0,0 +1,77 @@ +use crate::commands::WholeStreamCommand; +use crate::data::value::format_leaf; +use crate::prelude::*; +use futures::StreamExt; +use nu_errors::ShellError; +use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value}; + +pub struct ToMarkdown; + +impl WholeStreamCommand for ToMarkdown { + fn name(&self) -> &str { + "to-md" + } + + fn signature(&self) -> Signature { + Signature::build("to-md") + } + + fn usage(&self) -> &str { + "Convert table into simple Markdown" + } + + fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + to_html(args, registry) + } +} + +fn to_html(args: CommandArgs, registry: &CommandRegistry) -> Result { + let args = args.evaluate_once(registry)?; + let name_tag = args.name_tag(); + //let name_span = name_tag.span; + let stream = async_stream! { + let input: Vec = args.input.values.collect().await; + let headers = nu_protocol::merge_descriptors(&input); + let mut output_string = String::new(); + + if !headers.is_empty() && (headers.len() > 1 || headers[0] != "") { + output_string.push_str("|"); + for header in &headers { + output_string.push_str(&htmlescape::encode_minimal(&header)); + output_string.push_str("|"); + } + output_string.push_str("\n|"); + for _ in &headers { + output_string.push_str("-"); + output_string.push_str("|"); + } + output_string.push_str("\n"); + } + + for row in input { + match row.value { + UntaggedValue::Row(row) => { + output_string.push_str("|"); + for header in &headers { + let data = row.get_data(header); + output_string.push_str(&format_leaf(data.borrow()).plain_string(100_000)); + output_string.push_str("|"); + } + output_string.push_str("\n"); + } + p => { + output_string.push_str(&(htmlescape::encode_minimal(&format_leaf(&p).plain_string(100_000)))); + output_string.push_str("\n"); + } + } + } + + yield ReturnSuccess::value(UntaggedValue::string(output_string).into_value(name_tag)); + }; + + Ok(stream.to_output_stream()) +} diff --git a/crates/nu-cli/tests/format_conversions/markdown.rs b/crates/nu-cli/tests/format_conversions/markdown.rs new file mode 100644 index 0000000000..c7800f3bb7 --- /dev/null +++ b/crates/nu-cli/tests/format_conversions/markdown.rs @@ -0,0 +1,25 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn out_md_simple() { + let actual = nu!( + cwd: ".", pipeline( + r#" + echo 3 | to-md + "# + )); + + assert_eq!(actual, "3"); +} + +#[test] +fn out_md_table() { + let actual = nu!( + cwd: ".", pipeline( + r#" + echo '{"name": "jason"}' | from-json | to-md + "# + )); + + assert_eq!(actual, "|name||-||jason|"); +} diff --git a/crates/nu-cli/tests/format_conversions/mod.rs b/crates/nu-cli/tests/format_conversions/mod.rs index 66c8e97b13..cfc042ed5b 100644 --- a/crates/nu-cli/tests/format_conversions/mod.rs +++ b/crates/nu-cli/tests/format_conversions/mod.rs @@ -2,6 +2,7 @@ mod bson; mod csv; mod html; mod json; +mod markdown; mod ods; mod sqlite; mod ssv;