mirror of
https://github.com/nushell/nushell.git
synced 2024-12-24 16:09:11 +01:00
Minimal markdown syntax per element support. (#2997)
This commit is contained in:
parent
c1981dfc26
commit
fa928bd25d
@ -269,7 +269,7 @@ pub(crate) use to::To;
|
|||||||
pub(crate) use to_csv::ToCSV;
|
pub(crate) use to_csv::ToCSV;
|
||||||
pub(crate) use to_html::ToHTML;
|
pub(crate) use to_html::ToHTML;
|
||||||
pub(crate) use to_json::ToJSON;
|
pub(crate) use to_json::ToJSON;
|
||||||
pub(crate) use to_md::ToMarkdown;
|
pub(crate) use to_md::Command as ToMarkdown;
|
||||||
pub(crate) use to_toml::ToTOML;
|
pub(crate) use to_toml::ToTOML;
|
||||||
pub(crate) use to_tsv::ToTSV;
|
pub(crate) use to_tsv::ToTSV;
|
||||||
pub(crate) use to_url::ToURL;
|
pub(crate) use to_url::ToURL;
|
||||||
@ -327,6 +327,7 @@ mod tests {
|
|||||||
whole_stream_command(StrKebabCase),
|
whole_stream_command(StrKebabCase),
|
||||||
whole_stream_command(StrSnakeCase),
|
whole_stream_command(StrSnakeCase),
|
||||||
whole_stream_command(StrScreamingSnakeCase),
|
whole_stream_command(StrScreamingSnakeCase),
|
||||||
|
whole_stream_command(ToMarkdown),
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,13 +46,13 @@ impl WholeStreamCommand for Command {
|
|||||||
result: Some(vec![UntaggedValue::row(indexmap! {
|
result: Some(vec![UntaggedValue::row(indexmap! {
|
||||||
"File".to_string() => UntaggedValue::Table(vec![
|
"File".to_string() => UntaggedValue::Table(vec![
|
||||||
UntaggedValue::row(indexmap! {
|
UntaggedValue::row(indexmap! {
|
||||||
"name".to_string() => UntaggedValue::string("Andrés.txt").into(),
|
"name".to_string() => UntaggedValue::string("Andres.txt").into(),
|
||||||
"type".to_string() => UntaggedValue::string("File").into(),
|
"type".to_string() => UntaggedValue::string("File").into(),
|
||||||
"chickens".to_string() => UntaggedValue::int(10).into(),
|
"chickens".to_string() => UntaggedValue::int(10).into(),
|
||||||
"modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(),
|
"modified".to_string() => date("2019-07-23".tagged_unknown()).unwrap().into(),
|
||||||
}).into(),
|
}).into(),
|
||||||
UntaggedValue::row(indexmap! {
|
UntaggedValue::row(indexmap! {
|
||||||
"name".to_string() => UntaggedValue::string("Andrés.txt").into(),
|
"name".to_string() => UntaggedValue::string("Darren.txt").into(),
|
||||||
"type".to_string() => UntaggedValue::string("File").into(),
|
"type".to_string() => UntaggedValue::string("File").into(),
|
||||||
"chickens".to_string() => UntaggedValue::int(20).into(),
|
"chickens".to_string() => UntaggedValue::int(20).into(),
|
||||||
"modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(),
|
"modified".to_string() => date("2019-09-24".tagged_unknown()).unwrap().into(),
|
||||||
|
@ -54,7 +54,7 @@ impl WholeStreamCommand for Command {
|
|||||||
example: r#"ls | move type --before name | first"#,
|
example: r#"ls | move type --before name | first"#,
|
||||||
result: Some(vec![row! {
|
result: Some(vec![row! {
|
||||||
"type".into() => string("File"),
|
"type".into() => string("File"),
|
||||||
"name".into() => string("Andrés.txt"),
|
"name".into() => string("Andres.txt"),
|
||||||
"chickens".into() => int(10),
|
"chickens".into() => int(10),
|
||||||
"modified".into() => date("2019-07-23")
|
"modified".into() => date("2019-07-23")
|
||||||
}]),
|
}]),
|
||||||
@ -63,7 +63,7 @@ impl WholeStreamCommand for Command {
|
|||||||
description: "or move the column \"chickens\" after \"name\"",
|
description: "or move the column \"chickens\" after \"name\"",
|
||||||
example: r#"ls | move chickens --after name | first"#,
|
example: r#"ls | move chickens --after name | first"#,
|
||||||
result: Some(vec![row! {
|
result: Some(vec![row! {
|
||||||
"name".into() => string("Andrés.txt"),
|
"name".into() => string("Andres.txt"),
|
||||||
"chickens".into() => int(10),
|
"chickens".into() => int(10),
|
||||||
"type".into() => string("File"),
|
"type".into() => string("File"),
|
||||||
"modified".into() => date("2019-07-23")
|
"modified".into() => date("2019-07-23")
|
||||||
@ -74,7 +74,7 @@ impl WholeStreamCommand for Command {
|
|||||||
example: r#"ls | move name chickens --after type | first"#,
|
example: r#"ls | move name chickens --after type | first"#,
|
||||||
result: Some(vec![row! {
|
result: Some(vec![row! {
|
||||||
"type".into() => string("File"),
|
"type".into() => string("File"),
|
||||||
"name".into() => string("Andrés.txt"),
|
"name".into() => string("Andres.txt"),
|
||||||
"chickens".into() => int(10),
|
"chickens".into() => int(10),
|
||||||
"modified".into() => date("2019-07-23")
|
"modified".into() => date("2019-07-23")
|
||||||
}]),
|
}]),
|
||||||
|
@ -5,25 +5,33 @@ use nu_engine::WholeStreamCommand;
|
|||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Signature, UntaggedValue, Value};
|
||||||
|
|
||||||
pub struct ToMarkdown;
|
pub struct Command;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct ToMarkdownArgs {
|
pub struct Arguments {
|
||||||
pretty: bool,
|
pretty: bool,
|
||||||
|
#[serde(rename = "per-element")]
|
||||||
|
per_element: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl WholeStreamCommand for ToMarkdown {
|
impl WholeStreamCommand for Command {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
"to md"
|
"to md"
|
||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("to md").switch(
|
Signature::build("to md")
|
||||||
"pretty",
|
.switch(
|
||||||
"Formats the Markdown table to vertically align items",
|
"pretty",
|
||||||
Some('p'),
|
"Formats the Markdown table to vertically align items",
|
||||||
)
|
Some('p'),
|
||||||
|
)
|
||||||
|
.switch(
|
||||||
|
"per-element",
|
||||||
|
"treat each row as markdown syntax element",
|
||||||
|
Some('e'),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -37,30 +45,116 @@ impl WholeStreamCommand for ToMarkdown {
|
|||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![
|
vec![
|
||||||
Example {
|
Example {
|
||||||
description: "Outputs an unformatted md string representing the contents of ls",
|
description: "Outputs an unformatted table markdown string (default)",
|
||||||
example: "ls | to md",
|
example: "ls | to md",
|
||||||
result: None,
|
result: Some(vec![Value::from(one(r#"
|
||||||
|
|name|type|chickens|modified|
|
||||||
|
|-|-|-|-|
|
||||||
|
|Andres.txt|File|10|1 year ago|
|
||||||
|
|Jonathan|Dir|5|1 year ago|
|
||||||
|
|Darren.txt|File|20|1 year ago|
|
||||||
|
|Yehuda|Dir|4|1 year ago|
|
||||||
|
"#))]),
|
||||||
},
|
},
|
||||||
Example {
|
Example {
|
||||||
description: "Outputs a formatted md string representing the contents of ls",
|
description: "Optionally, output a formatted markdown string",
|
||||||
example: "ls | to md -p",
|
example: "ls | to md --pretty",
|
||||||
result: None,
|
result: Some(vec![Value::from(one(r#"
|
||||||
|
| name | type | chickens | modified |
|
||||||
|
| ---------- | ---- | -------- | ---------- |
|
||||||
|
| Andres.txt | File | 10 | 1 year ago |
|
||||||
|
| Jonathan | Dir | 5 | 1 year ago |
|
||||||
|
| Darren.txt | File | 20 | 1 year ago |
|
||||||
|
| Yehuda | Dir | 4 | 1 year ago |
|
||||||
|
"#))]),
|
||||||
},
|
},
|
||||||
|
Example {
|
||||||
|
description: "Treat each row as a markdown element",
|
||||||
|
example: "echo [[H1]; [\"Welcome to Nushell\"]] | append $(ls | first 2) | to md --per-element --pretty",
|
||||||
|
result: Some(vec![Value::from(one(r#"
|
||||||
|
# Welcome to Nushell
|
||||||
|
| name | type | chickens | modified |
|
||||||
|
| ---------- | ---- | -------- | ---------- |
|
||||||
|
| Andres.txt | File | 10 | 1 year ago |
|
||||||
|
| Jonathan | Dir | 5 | 1 year ago |
|
||||||
|
"#))]),
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn to_md(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
async fn to_md(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||||
let name_tag = args.call_info.name_tag.clone();
|
let name_tag = args.call_info.name_tag.clone();
|
||||||
let (ToMarkdownArgs { pretty }, input) = args.process().await?;
|
let (arguments, input) = args.process().await?;
|
||||||
let input: Vec<Value> = input.collect().await;
|
|
||||||
let headers = nu_protocol::merge_descriptors(&input);
|
|
||||||
|
|
||||||
|
let input: Vec<Value> = input.collect().await;
|
||||||
|
|
||||||
|
Ok(OutputStream::one(ReturnSuccess::value(
|
||||||
|
UntaggedValue::string(process(&input, arguments)).into_value(if input.is_empty() {
|
||||||
|
name_tag
|
||||||
|
} else {
|
||||||
|
input[0].tag()
|
||||||
|
}),
|
||||||
|
)))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process(
|
||||||
|
input: &[Value],
|
||||||
|
Arguments {
|
||||||
|
pretty,
|
||||||
|
per_element,
|
||||||
|
}: Arguments,
|
||||||
|
) -> String {
|
||||||
|
if per_element {
|
||||||
|
input
|
||||||
|
.iter()
|
||||||
|
.map(|v| match &v.value {
|
||||||
|
UntaggedValue::Table(values) => table(values, pretty),
|
||||||
|
_ => fragment(v, pretty),
|
||||||
|
})
|
||||||
|
.collect::<String>()
|
||||||
|
} else {
|
||||||
|
table(&input, pretty)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fragment(input: &Value, pretty: bool) -> String {
|
||||||
|
let headers = input.data_descriptors();
|
||||||
|
let mut out = String::new();
|
||||||
|
|
||||||
|
if headers.len() == 1 {
|
||||||
|
let markup = match (&headers[0]).to_ascii_lowercase().as_ref() {
|
||||||
|
"h1" => "# ".to_string(),
|
||||||
|
"h2" => "## ".to_string(),
|
||||||
|
"h3" => "### ".to_string(),
|
||||||
|
"blockquote" => "> ".to_string(),
|
||||||
|
|
||||||
|
_ => return table(&[input.clone()], pretty),
|
||||||
|
};
|
||||||
|
|
||||||
|
out.push_str(&markup);
|
||||||
|
out.push_str(&format_leaf(input.get_data(&headers[0]).borrow()).plain_string(100_000));
|
||||||
|
} else if input.is_row() {
|
||||||
|
let string = match input.row_entries().next() {
|
||||||
|
Some(value) => value.1.as_string().unwrap_or_default(),
|
||||||
|
None => String::from(""),
|
||||||
|
};
|
||||||
|
|
||||||
|
out = format_leaf(&UntaggedValue::from(string)).plain_string(100_000)
|
||||||
|
} else {
|
||||||
|
out = format_leaf(&input.value).plain_string(100_000)
|
||||||
|
}
|
||||||
|
|
||||||
|
out.push('\n');
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_headers(headers: &[String]) -> (Vec<String>, Vec<usize>) {
|
||||||
let mut escaped_headers: Vec<String> = Vec::new();
|
let mut escaped_headers: Vec<String> = Vec::new();
|
||||||
let mut column_widths: Vec<usize> = Vec::new();
|
let mut column_widths: Vec<usize> = Vec::new();
|
||||||
|
|
||||||
if !headers.is_empty() && (headers.len() > 1 || !headers[0].is_empty()) {
|
if !headers.is_empty() && (headers.len() > 1 || !headers[0].is_empty()) {
|
||||||
for header in &headers {
|
for header in headers {
|
||||||
let escaped_header_string = htmlescape::encode_minimal(&header);
|
let escaped_header_string = htmlescape::encode_minimal(&header);
|
||||||
column_widths.push(escaped_header_string.len());
|
column_widths.push(escaped_header_string.len());
|
||||||
escaped_headers.push(escaped_header_string);
|
escaped_headers.push(escaped_header_string);
|
||||||
@ -69,9 +163,17 @@ async fn to_md(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
column_widths = vec![0; headers.len()]
|
column_widths = vec![0; headers.len()]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
(escaped_headers, column_widths)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn table(input: &[Value], pretty: bool) -> String {
|
||||||
|
let headers = nu_protocol::merge_descriptors(&input);
|
||||||
|
|
||||||
|
let (escaped_headers, mut column_widths) = collect_headers(&headers);
|
||||||
|
|
||||||
let mut escaped_rows: Vec<Vec<String>> = Vec::new();
|
let mut escaped_rows: Vec<Vec<String>> = Vec::new();
|
||||||
|
|
||||||
for row in &input {
|
for row in input {
|
||||||
let mut escaped_row: Vec<String> = Vec::new();
|
let mut escaped_row: Vec<String> = Vec::new();
|
||||||
|
|
||||||
match row.value.clone() {
|
match row.value.clone() {
|
||||||
@ -108,9 +210,7 @@ async fn to_md(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
|||||||
.to_string()
|
.to_string()
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(OutputStream::one(ReturnSuccess::value(
|
output_string
|
||||||
UntaggedValue::string(output_string).into_value(name_tag),
|
|
||||||
)))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_output_string(
|
fn get_output_string(
|
||||||
@ -201,15 +301,78 @@ fn get_padded_string(text: String, desired_length: usize, padding_character: cha
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn one(string: &str) -> String {
|
||||||
|
string
|
||||||
|
.lines()
|
||||||
|
.skip(1)
|
||||||
|
.map(|line| line.trim())
|
||||||
|
.collect::<Vec<&str>>()
|
||||||
|
.join("\n")
|
||||||
|
.trim_end()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::ShellError;
|
use super::{fragment, one, table};
|
||||||
use super::ToMarkdown;
|
use nu_protocol::{row, Value};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn examples_work_as_expected() -> Result<(), ShellError> {
|
fn render_h1() {
|
||||||
use crate::examples::test as test_examples;
|
let value = row! {"H1".into() => Value::from("Ecuador")};
|
||||||
|
|
||||||
Ok(test_examples(ToMarkdown {})?)
|
assert_eq!(fragment(&value, false), "# Ecuador\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_h2() {
|
||||||
|
let value = row! {"H2".into() => Value::from("Ecuador")};
|
||||||
|
|
||||||
|
assert_eq!(fragment(&value, false), "## Ecuador\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_h3() {
|
||||||
|
let value = row! {"H3".into() => Value::from("Ecuador")};
|
||||||
|
|
||||||
|
assert_eq!(fragment(&value, false), "### Ecuador\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_blockquote() {
|
||||||
|
let value = row! {"BLOCKQUOTE".into() => Value::from("Ecuador")};
|
||||||
|
|
||||||
|
assert_eq!(fragment(&value, false), "> Ecuador\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn render_table() {
|
||||||
|
let value = vec![
|
||||||
|
row! { "country".into() => Value::from("Ecuador")},
|
||||||
|
row! { "country".into() => Value::from("New Zealand")},
|
||||||
|
row! { "country".into() => Value::from("USA")},
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
table(&value, false),
|
||||||
|
one(r#"
|
||||||
|
|country|
|
||||||
|
|-|
|
||||||
|
|Ecuador|
|
||||||
|
|New Zealand|
|
||||||
|
|USA|
|
||||||
|
"#)
|
||||||
|
);
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
table(&value, true),
|
||||||
|
one(r#"
|
||||||
|
| country |
|
||||||
|
| ----------- |
|
||||||
|
| Ecuador |
|
||||||
|
| New Zealand |
|
||||||
|
| USA |
|
||||||
|
"#)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ use nu_protocol::{ShellTypeName, Value};
|
|||||||
use nu_source::AnchorLocation;
|
use nu_source::AnchorLocation;
|
||||||
|
|
||||||
use crate::commands::{
|
use crate::commands::{
|
||||||
BuildString, Each, Echo, First, Get, Keep, Last, Let, Nth, StrCollect, Wrap,
|
Append, BuildString, Each, Echo, First, Get, Keep, Last, Let, Nth, Select, StrCollect, Wrap,
|
||||||
};
|
};
|
||||||
use nu_engine::{run_block, whole_stream_command, Command, EvaluationContext, WholeStreamCommand};
|
use nu_engine::{run_block, whole_stream_command, Command, EvaluationContext, WholeStreamCommand};
|
||||||
use nu_stream::InputStream;
|
use nu_stream::InputStream;
|
||||||
@ -32,6 +32,7 @@ pub fn test_examples(cmd: Command) -> Result<(), ShellError> {
|
|||||||
// Command Doubles
|
// Command Doubles
|
||||||
whole_stream_command(DoubleLs {}),
|
whole_stream_command(DoubleLs {}),
|
||||||
// Minimal restricted commands to aid in testing
|
// Minimal restricted commands to aid in testing
|
||||||
|
whole_stream_command(Append {}),
|
||||||
whole_stream_command(Echo {}),
|
whole_stream_command(Echo {}),
|
||||||
whole_stream_command(BuildString {}),
|
whole_stream_command(BuildString {}),
|
||||||
whole_stream_command(First {}),
|
whole_stream_command(First {}),
|
||||||
@ -41,6 +42,7 @@ pub fn test_examples(cmd: Command) -> Result<(), ShellError> {
|
|||||||
whole_stream_command(Last {}),
|
whole_stream_command(Last {}),
|
||||||
whole_stream_command(Nth {}),
|
whole_stream_command(Nth {}),
|
||||||
whole_stream_command(Let {}),
|
whole_stream_command(Let {}),
|
||||||
|
whole_stream_command(Select),
|
||||||
whole_stream_command(StrCollect),
|
whole_stream_command(StrCollect),
|
||||||
whole_stream_command(Wrap),
|
whole_stream_command(Wrap),
|
||||||
cmd,
|
cmd,
|
||||||
@ -100,6 +102,7 @@ pub fn test(cmd: impl WholeStreamCommand + 'static) -> Result<(), ShellError> {
|
|||||||
whole_stream_command(Each {}),
|
whole_stream_command(Each {}),
|
||||||
whole_stream_command(Let {}),
|
whole_stream_command(Let {}),
|
||||||
whole_stream_command(cmd),
|
whole_stream_command(cmd),
|
||||||
|
whole_stream_command(Select),
|
||||||
whole_stream_command(StrCollect),
|
whole_stream_command(StrCollect),
|
||||||
whole_stream_command(Wrap),
|
whole_stream_command(Wrap),
|
||||||
]);
|
]);
|
||||||
@ -153,6 +156,7 @@ pub fn test_anchors(cmd: Command) -> Result<(), ShellError> {
|
|||||||
whole_stream_command(StubOpen {}),
|
whole_stream_command(StubOpen {}),
|
||||||
whole_stream_command(DoubleEcho {}),
|
whole_stream_command(DoubleEcho {}),
|
||||||
whole_stream_command(DoubleLs {}),
|
whole_stream_command(DoubleLs {}),
|
||||||
|
whole_stream_command(Append {}),
|
||||||
whole_stream_command(BuildString {}),
|
whole_stream_command(BuildString {}),
|
||||||
whole_stream_command(First {}),
|
whole_stream_command(First {}),
|
||||||
whole_stream_command(Get {}),
|
whole_stream_command(Get {}),
|
||||||
@ -161,6 +165,7 @@ pub fn test_anchors(cmd: Command) -> Result<(), ShellError> {
|
|||||||
whole_stream_command(Last {}),
|
whole_stream_command(Last {}),
|
||||||
whole_stream_command(Nth {}),
|
whole_stream_command(Nth {}),
|
||||||
whole_stream_command(Let {}),
|
whole_stream_command(Let {}),
|
||||||
|
whole_stream_command(Select),
|
||||||
whole_stream_command(StrCollect),
|
whole_stream_command(StrCollect),
|
||||||
whole_stream_command(Wrap),
|
whole_stream_command(Wrap),
|
||||||
cmd,
|
cmd,
|
||||||
@ -172,21 +177,24 @@ pub fn test_anchors(cmd: Command) -> Result<(), ShellError> {
|
|||||||
let mut ctx = base_context.clone();
|
let mut ctx = base_context.clone();
|
||||||
|
|
||||||
let block = parse_line(&pipeline_with_anchor, &ctx)?;
|
let block = parse_line(&pipeline_with_anchor, &ctx)?;
|
||||||
let result = block_on(evaluate_block(block, &mut ctx))?;
|
|
||||||
|
|
||||||
ctx.with_errors(|reasons| reasons.iter().cloned().take(1).next())
|
if let Some(_) = &sample_pipeline.result {
|
||||||
.map_or(Ok(()), Err)?;
|
let result = block_on(evaluate_block(block, &mut ctx))?;
|
||||||
|
|
||||||
for actual in result.iter() {
|
ctx.with_errors(|reasons| reasons.iter().cloned().take(1).next())
|
||||||
if !is_anchor_carried(actual, mock_path()) {
|
.map_or(Ok(()), Err)?;
|
||||||
let failed_call = format!("command: {}\n", pipeline_with_anchor);
|
|
||||||
|
|
||||||
panic!(
|
for actual in result.iter() {
|
||||||
"example command didn't carry anchor tag correctly.\n {} {:#?} {:#?}",
|
if !is_anchor_carried(actual, mock_path()) {
|
||||||
failed_call,
|
let failed_call = format!("command: {}\n", pipeline_with_anchor);
|
||||||
actual,
|
|
||||||
mock_path()
|
panic!(
|
||||||
);
|
"example command didn't carry anchor tag correctly.\n {} {:#?} {:#?}",
|
||||||
|
failed_call,
|
||||||
|
actual,
|
||||||
|
mock_path()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ pub mod ls {
|
|||||||
pub fn file_listing() -> Vec<Value> {
|
pub fn file_listing() -> Vec<Value> {
|
||||||
vec![
|
vec![
|
||||||
row! {
|
row! {
|
||||||
"name".to_string() => string("Andrés.txt"),
|
"name".to_string() => string("Andres.txt"),
|
||||||
"type".to_string() => string("File"),
|
"type".to_string() => string("File"),
|
||||||
"chickens".to_string() => int(10),
|
"chickens".to_string() => int(10),
|
||||||
"modified".to_string() => date("2019-07-23")
|
"modified".to_string() => date("2019-07-23")
|
||||||
@ -19,7 +19,7 @@ pub mod ls {
|
|||||||
"modified".to_string() => date("2019-07-23")
|
"modified".to_string() => date("2019-07-23")
|
||||||
},
|
},
|
||||||
row! {
|
row! {
|
||||||
"name".to_string() => string("Andrés.txt"),
|
"name".to_string() => string("Darren.txt"),
|
||||||
"type".to_string() => string("File"),
|
"type".to_string() => string("File"),
|
||||||
"chickens".to_string() => int(20),
|
"chickens".to_string() => int(20),
|
||||||
"modified".to_string() => date("2019-09-24")
|
"modified".to_string() => date("2019-09-24")
|
||||||
|
@ -5,7 +5,7 @@ fn md_empty() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: ".", pipeline(
|
cwd: ".", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo "{}" | from json | to md
|
echo [[]; []] | from json | to md
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -53,7 +53,7 @@ fn md_table() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: ".", pipeline(
|
cwd: ".", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo '{"name": "jason"}' | from json | to md
|
echo [[name]; [jason]] | to md
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
@ -65,9 +65,34 @@ fn md_table_pretty() {
|
|||||||
let actual = nu!(
|
let actual = nu!(
|
||||||
cwd: ".", pipeline(
|
cwd: ".", pipeline(
|
||||||
r#"
|
r#"
|
||||||
echo '{"name": "joseph"}' | from json | to md -p
|
echo [[name]; [joseph]] | to md -p
|
||||||
"#
|
"#
|
||||||
));
|
));
|
||||||
|
|
||||||
assert_eq!(actual.out, "| name || ------ || joseph |");
|
assert_eq!(actual.out, "| name || ------ || joseph |");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn md_combined() {
|
||||||
|
let actual = nu!(
|
||||||
|
cwd: ".", pipeline(
|
||||||
|
r#"
|
||||||
|
def title [] {
|
||||||
|
echo [[H1]; ["Nu top meals"]]
|
||||||
|
};
|
||||||
|
|
||||||
|
def meals [] {
|
||||||
|
echo [[dish]; [Arepa] [Taco] [Pizza]]
|
||||||
|
};
|
||||||
|
|
||||||
|
title
|
||||||
|
| append $(meals)
|
||||||
|
| to md --per-element --pretty
|
||||||
|
"#
|
||||||
|
));
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
actual.out,
|
||||||
|
"# Nu top meals| dish || ----- || Arepa || Taco || Pizza |"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
@ -920,6 +920,67 @@ impl DateTimeExt for DateTime<FixedOffset> {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
use indexmap::indexmap;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_merge_descriptors() {
|
||||||
|
let value = vec![
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"h1".into() => Value::from("Ecuador")
|
||||||
|
})
|
||||||
|
.into_untagged_value(),
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"h2".into() => Value::from("Ecuador")
|
||||||
|
})
|
||||||
|
.into_untagged_value(),
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"h3".into() => Value::from("Ecuador")
|
||||||
|
})
|
||||||
|
.into_untagged_value(),
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"h1".into() => Value::from("Ecuador"),
|
||||||
|
"h4".into() => Value::from("Ecuador"),
|
||||||
|
})
|
||||||
|
.into_untagged_value(),
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
merge_descriptors(&value),
|
||||||
|
vec![
|
||||||
|
String::from("h1"),
|
||||||
|
String::from("h2"),
|
||||||
|
String::from("h3"),
|
||||||
|
String::from("h4")
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_data_descriptors() {
|
||||||
|
let value = vec![
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"h1".into() => Value::from("Ecuador")
|
||||||
|
}),
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"h2".into() => Value::from("Ecuador")
|
||||||
|
}),
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"h3".into() => Value::from("Ecuador")
|
||||||
|
}),
|
||||||
|
UntaggedValue::row(indexmap! {
|
||||||
|
"h1".into() => Value::from("Ecuador"),
|
||||||
|
"h4".into() => Value::from("Ecuador"),
|
||||||
|
}),
|
||||||
|
];
|
||||||
|
|
||||||
|
assert_eq!(
|
||||||
|
value
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.data_descriptors().len())
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
vec![1, 1, 1, 2]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_decimal_from_float() {
|
fn test_decimal_from_float() {
|
||||||
|
Loading…
Reference in New Issue
Block a user