From 7b1a15b2238016df968228f7e97e5d84e849f981 Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Mon, 20 Jul 2020 07:57:29 -0500 Subject: [PATCH 1/5] Campbell colors (#2219) * added campbell theme to html colors * updated test results. had to make change for ci. * hopefully the last changes for this stupid test :) * moved tests to html.rs * remove unnecessary using statement. * still fighting with tests and tests are winning. --- crates/nu-cli/src/commands/to_html.rs | 207 +++++++++--------- .../nu-cli/tests/format_conversions/html.rs | 81 ++++++- 2 files changed, 181 insertions(+), 107 deletions(-) diff --git a/crates/nu-cli/src/commands/to_html.rs b/crates/nu-cli/src/commands/to_html.rs index 9f5924935de0d..a433966c02e86 100644 --- a/crates/nu-cli/src/commands/to_html.rs +++ b/crates/nu-cli/src/commands/to_html.rs @@ -15,6 +15,7 @@ pub struct ToHTMLArgs { html_color: bool, no_color: bool, dark_bg: bool, + use_campbell: bool, } #[async_trait] @@ -32,6 +33,11 @@ impl WholeStreamCommand for ToHTML { "indicate your background color is a darker color", Some('d'), ) + .switch( + "use_campbell", + "use microsoft's windows terminal color scheme named campell", + Some('c'), + ) } fn usage(&self) -> &str { @@ -47,43 +53,60 @@ impl WholeStreamCommand for ToHTML { } } -fn get_colors(is_dark: bool) -> HashMap<&'static str, String> { - // Currently now using bold_white and bold_black. - // This is not theming but it is kind of a start. The intent here is to use the - // regular terminal colors which appear on black for most people and are very - // high contrast. But when there's a light background, use something that works - // better for it. - +fn get_campbell_theme(is_dark: bool) -> HashMap<&'static str, String> { // for reference here is Microsoft's Campbell Theme // taken from here // https://docs.microsoft.com/en-us/windows/terminal/customize-settings/color-schemes - // { - // "name" : "Campbell", - - // "cursorColor": "#FFFFFF", - // "selectionBackground": "#FFFFFF", - - // "background" : "#0C0C0C", - // "foreground" : "#CCCCCC", - - // "black" : "#0C0C0C", - // "blue" : "#0037DA", - // "cyan" : "#3A96DD", - // "green" : "#13A10E", - // "purple" : "#881798", - // "red" : "#C50F1F", - // "white" : "#CCCCCC", - // "yellow" : "#C19C00", - // "brightBlack" : "#767676", - // "brightBlue" : "#3B78FF", - // "brightCyan" : "#61D6D6", - // "brightGreen" : "#16C60C", - // "brightPurple" : "#B4009E", - // "brightRed" : "#E74856", - // "brightWhite" : "#F2F2F2", - // "brightYellow" : "#F9F1A5" - // }, + let mut hm: HashMap<&str, String> = HashMap::new(); + if is_dark { + hm.insert("bold_black", "#767676".to_string()); + hm.insert("bold_red", "#E74856".to_string()); + hm.insert("bold_green", "#16C60C".to_string()); + hm.insert("bold_yellow", "#F9F1A5".to_string()); + hm.insert("bold_blue", "#3B78FF".to_string()); + hm.insert("bold_magenta", "#B4009E".to_string()); + hm.insert("bold_cyan", "#61D6D6".to_string()); + hm.insert("bold_white", "#F2F2F2".to_string()); + + hm.insert("black", "#0C0C0C".to_string()); + hm.insert("red", "#C50F1F".to_string()); + hm.insert("green", "#13A10E".to_string()); + hm.insert("yellow", "#C19C00".to_string()); + hm.insert("blue", "#0037DA".to_string()); + hm.insert("magenta", "#881798".to_string()); + hm.insert("cyan", "#3A96DD".to_string()); + hm.insert("white", "#CCCCCC".to_string()); + + hm.insert("background", "#0C0C0C".to_string()); + hm.insert("foreground", "#CCCCCC".to_string()); + } else { + hm.insert("bold_black", "#767676".to_string()); + hm.insert("bold_red", "#E74856".to_string()); + hm.insert("bold_green", "#16C60C".to_string()); + hm.insert("bold_yellow", "#F9F1A5".to_string()); + hm.insert("bold_blue", "#3B78FF".to_string()); + hm.insert("bold_magenta", "#B4009E".to_string()); + hm.insert("bold_cyan", "#61D6D6".to_string()); + hm.insert("bold_white", "#F2F2F2".to_string()); + + hm.insert("black", "#0C0C0C".to_string()); + hm.insert("red", "#C50F1F".to_string()); + hm.insert("green", "#13A10E".to_string()); + hm.insert("yellow", "#C19C00".to_string()); + hm.insert("blue", "#0037DA".to_string()); + hm.insert("magenta", "#881798".to_string()); + hm.insert("cyan", "#3A96DD".to_string()); + hm.insert("white", "#CCCCCC".to_string()); + + hm.insert("background", "#CCCCCC".to_string()); + hm.insert("foreground", "#0C0C0C".to_string()); + } + + hm +} + +fn get_default_theme(is_dark: bool) -> HashMap<&'static str, String> { let mut hm: HashMap<&str, String> = HashMap::new(); if is_dark { @@ -133,6 +156,20 @@ fn get_colors(is_dark: bool) -> HashMap<&'static str, String> { hm } +fn get_colors(is_dark: bool, use_campbell: bool) -> HashMap<&'static str, String> { + // Currently now using bold_white and bold_black. + // This is not theming but it is kind of a start. The intent here is to use the + // regular terminal colors which appear on black for most people and are very + // high contrast. But when there's a light background, use something that works + // better for it. + + if use_campbell { + get_campbell_theme(is_dark) + } else { + get_default_theme(is_dark) + } +} + async fn to_html( args: CommandArgs, registry: &CommandRegistry, @@ -144,22 +181,26 @@ async fn to_html( html_color, no_color, dark_bg, + use_campbell, }, input, ) = args.process(®istry).await?; let input: Vec = input.collect().await; let headers = nu_protocol::merge_descriptors(&input); let mut output_string = "".to_string(); - let mut hm: HashMap = HashMap::new(); - - // if the user wants a dark background, that means the background will be black - // and the foreground will be white, otherwise it's the reverse. I think this - // is the best we can do until we get to color themes. - if dark_bg { - output_string.push_str(""); - } else { - output_string.push_str(""); - } + let mut regex_hm: HashMap = HashMap::new(); + let color_hm = get_colors(dark_bg, use_campbell); + + // change the color of the page + output_string.push_str(&format!( + r"", + color_hm + .get("background") + .expect("Error getting background color"), + color_hm + .get("foreground") + .expect("Error getting foreground color") + )); // Add grid lines to html // let mut output_string = "Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
> cd

Change to your home directory (alternate version)
> cd ~

Change to the previous directory
> cd -

".to_string(); - let cd_help_expected_result = r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
>
cd

Change to your home directory (alternate version)
>
cd
~

Change to the previous directory
>
cd
-

".to_string(); - let is_dark = false; - setup_html_color_regexes(&mut hm, is_dark); - assert_eq!(cd_help_expected_result, run_regexes(&hm, &cd_help)); - } - - #[test] - fn test_cd_html_color_flag_dark_true() { - let mut hm: HashMap = HashMap::new(); - let cd_help = r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
> cd

Change to your home directory (alternate version)
> cd ~

Change to the previous directory
> cd -

".to_string(); - let cd_help_expected_result = r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
>
cd

Change to your home directory (alternate version)
>
cd
~

Change to the previous directory
>
cd
-

".to_string(); - let is_dark = true; - setup_html_color_regexes(&mut hm, is_dark); - assert_eq!(cd_help_expected_result, run_regexes(&hm, &cd_help)); - } - - #[test] - fn test_no_color_flag() { - let mut hm: HashMap = HashMap::new(); - let cd_help = r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
> cd

Change to your home directory (alternate version)
> cd ~

Change to the previous directory
> cd -

".to_string(); - let cd_help_expected_result = r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
> cd

Change to your home directory (alternate version)
> cd ~

Change to the previous directory
> cd -

".to_string(); - setup_no_color_regexes(&mut hm); - assert_eq!(cd_help_expected_result, run_regexes(&hm, &cd_help)); - } - - #[test] - fn test_html_color_where_flag_dark_true() { - let mut hm: HashMap = HashMap::new(); - let where_help = r"Filter table to match the condition.

Usage:
> where <condition> {flags}

Parameters:
<condition> the condition that must match

Flags:
-h, --help: Display this help message

Examples:
List all files in the current directory with sizes greater than 2kb
> ls | where size > 2kb

List only the files in the current directory
> ls | where type == File

List all files with names that contain "Car"
> ls | where name =~ "Car"

List all files that were modified in the last two months
> ls | where modified <= 2M

".to_string(); - let where_help_exptected_results = r"Filter table to match the condition.

Usage:
> where <condition> {flags}

Parameters:
<condition> the condition that must match

Flags:
-h, --help: Display this help message

Examples:
List all files in the current directory with sizes greater than 2kb
> ls | where size > 2kb

List only the files in the current directory
>
ls
| where type == File

List all files with names that contain "Car"
>
ls
| where name =~ "Car"

List all files that were modified in the last two months
>
ls
| where modified <= 2M

".to_string(); - let is_dark = true; - setup_html_color_regexes(&mut hm, is_dark); - assert_eq!(where_help_exptected_results, run_regexes(&hm, &where_help)); - } - - #[test] - fn test_html_color_where_flag_dark_false() { - let mut hm: HashMap = HashMap::new(); - let where_help = r"Filter table to match the condition.

Usage:
> where <condition> {flags}

Parameters:
<condition> the condition that must match

Flags:
-h, --help: Display this help message

Examples:
List all files in the current directory with sizes greater than 2kb
> ls | where size > 2kb

List only the files in the current directory
> ls | where type == File

List all files with names that contain "Car"
> ls | where name =~ "Car"

List all files that were modified in the last two months
> ls | where modified <= 2M

".to_string(); - let where_help_exptected_results = r"Filter table to match the condition.

Usage:
> where <condition> {flags}

Parameters:
<condition> the condition that must match

Flags:
-h, --help: Display this help message

Examples:
List all files in the current directory with sizes greater than 2kb
> ls | where size > 2kb

List only the files in the current directory
>
ls
| where type == File

List all files with names that contain "Car"
>
ls
| where name =~ "Car"

List all files that were modified in the last two months
>
ls
| where modified <= 2M

".to_string(); - let is_dark = false; - setup_html_color_regexes(&mut hm, is_dark); - assert_eq!(where_help_exptected_results, run_regexes(&hm, &where_help)); - } } diff --git a/crates/nu-cli/tests/format_conversions/html.rs b/crates/nu-cli/tests/format_conversions/html.rs index c892130aef176..684e2d68c8c96 100644 --- a/crates/nu-cli/tests/format_conversions/html.rs +++ b/crates/nu-cli/tests/format_conversions/html.rs @@ -11,7 +11,7 @@ fn out_html_simple() { assert_eq!( actual.out, - "3" + r"3" ); } @@ -20,12 +20,87 @@ fn out_html_table() { let actual = nu!( cwd: ".", pipeline( r#" - echo '{"name": "jason"}' | from json | to html + echo '{"name": "darren"}' | from json | to html "# )); assert_eq!( actual.out, - "
name
jason
" + r"
name
darren
" + ); +} + +#[test] +fn test_cd_html_color_flag_dark_false() { + let actual = nu!( + cwd: ".", pipeline( + r#" + cd --help | to html --html_color + "# + ) + ); + assert_eq!( + actual.out, + r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
>
cd

Change to your home directory (alternate version)
>
cd
~

Change to the previous directory
>
cd
-

" + ); +} + +#[test] +fn test_cd_html_color_flag_dark_true() { + let actual = nu!( + cwd: ".", pipeline( + r#" + cd --help | to html --html_color --dark_bg + "# + ) + ); + assert_eq!( + actual.out, + r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
>
cd

Change to your home directory (alternate version)
>
cd
~

Change to the previous directory
>
cd
-

" + ); +} + +#[test] +fn test_no_color_flag() { + let actual = nu!( + cwd: ".", pipeline( + r#" + cd --help | to html --no_color + "# + ) + ); + assert_eq!( + actual.out, + r"Change to a new path.

Usage:
> cd (directory) {flags}

Parameters:
(directory) the directory to change to

Flags:
-h, --help: Display this help message

Examples:
Change to a new directory called 'dirname'
> cd dirname

Change to your home directory
> cd

Change to your home directory (alternate version)
> cd ~

Change to the previous directory
> cd -

" + ); +} + +#[test] +fn test_html_color_where_flag_dark_true() { + let actual = nu!( + cwd: ".", pipeline( + r#" + where --help | to html --html_color --dark_bg + "# + ) + ); + assert_eq!( + actual.out, + r"Filter table to match the condition.

Usage:
> where <condition> {flags}

Parameters:
<condition> the condition that must match

Flags:
-h, --help: Display this help message

Examples:
List all files in the current directory with sizes greater than 2kb
> ls | where size > 2kb

List only the files in the current directory
>
ls
| where type == File

List all files with names that contain "Car"
>
ls
| where name =~ "Car"

List all files that were modified in the last two months
>
ls
| where modified <= 2M

" + ); +} + +#[test] +fn test_html_color_where_flag_dark_false() { + let actual = nu!( + cwd: ".", pipeline( + r#" + where --help | to html --html_color + "# + ) + ); + assert_eq!( + actual.out, + r"Filter table to match the condition.

Usage:
> where <condition> {flags}

Parameters:
<condition> the condition that must match

Flags:
-h, --help: Display this help message

Examples:
List all files in the current directory with sizes greater than 2kb
> ls | where size > 2kb

List only the files in the current directory
>
ls
| where type == File

List all files with names that contain "Car"
>
ls
| where name =~ "Car"

List all files that were modified in the last two months
>
ls
| where modified <= 2M

" ); } From 6eb2c94209af69df0cf2e39b7f0624ea2300d7bb Mon Sep 17 00:00:00 2001 From: "Joseph T. Lyons" Date: Mon, 20 Jul 2020 13:31:58 -0400 Subject: [PATCH 2/5] Add flag for case-insensitive sort-by (#2225) * Add flag for case-insensitive sort-by * Fix test names * Fix documentation comments --- crates/nu-cli/src/commands/math/median.rs | 2 +- crates/nu-cli/src/commands/math/mode.rs | 2 +- crates/nu-cli/src/commands/sort_by.rs | 62 ++++++++++++++++-- crates/nu-cli/tests/commands/sort_by.rs | 68 ++++++++++++++++++++ crates/nu-protocol/src/value.rs | 5 ++ docs/commands/sort-by.md | 68 ++++++++++++++++++++ tests/fixtures/formats/sample-ls-output.json | 1 + 7 files changed, 201 insertions(+), 7 deletions(-) create mode 100644 tests/fixtures/formats/sample-ls-output.json diff --git a/crates/nu-cli/src/commands/math/median.rs b/crates/nu-cli/src/commands/math/median.rs index 36f223ba13941..4bd8aa7033f76 100644 --- a/crates/nu-cli/src/commands/math/median.rs +++ b/crates/nu-cli/src/commands/math/median.rs @@ -73,7 +73,7 @@ pub fn median(values: &[Value], name: &Tag) -> Result { sorted.push(item.clone()); } - crate::commands::sort_by::sort(&mut sorted, &[], name)?; + crate::commands::sort_by::sort(&mut sorted, &[], name, false)?; match take { Pick::Median => { diff --git a/crates/nu-cli/src/commands/math/mode.rs b/crates/nu-cli/src/commands/math/mode.rs index 2c894f7f98544..010bf19a011ba 100644 --- a/crates/nu-cli/src/commands/math/mode.rs +++ b/crates/nu-cli/src/commands/math/mode.rs @@ -77,7 +77,7 @@ pub fn mode(values: &[Value], name: &Tag) -> Result { } } - crate::commands::sort_by::sort(&mut modes, &[], name)?; + crate::commands::sort_by::sort(&mut modes, &[], name, false)?; Ok(UntaggedValue::Table(modes).into_value(name)) } diff --git a/crates/nu-cli/src/commands/sort_by.rs b/crates/nu-cli/src/commands/sort_by.rs index 37a0a05a94264..869853f4314ef 100644 --- a/crates/nu-cli/src/commands/sort_by.rs +++ b/crates/nu-cli/src/commands/sort_by.rs @@ -11,6 +11,7 @@ pub struct SortBy; #[derive(Deserialize)] pub struct SortByArgs { rest: Vec>, + insensitive: bool, } #[async_trait] @@ -20,7 +21,13 @@ impl WholeStreamCommand for SortBy { } fn signature(&self) -> Signature { - Signature::build("sort-by").rest(SyntaxShape::String, "the column(s) to sort by") + Signature::build("sort-by") + .switch( + "insensitive", + "Sort string-based columns case insensitively", + Some('i'), + ) + .rest(SyntaxShape::String, "the column(s) to sort by") } fn usage(&self) -> &str { @@ -57,6 +64,24 @@ impl WholeStreamCommand for SortBy { example: "ls | sort-by type size", result: None, }, + Example { + description: "Sort strings (case sensitive)", + example: "echo [airplane Truck Car] | sort-by", + result: Some(vec![ + UntaggedValue::string("Car").into(), + UntaggedValue::string("Truck").into(), + UntaggedValue::string("airplane").into(), + ]), + }, + Example { + description: "Sort strings (case insensitive)", + example: "echo [airplane Truck Car] | sort-by -i", + result: Some(vec![ + UntaggedValue::string("airplane").into(), + UntaggedValue::string("Car").into(), + UntaggedValue::string("Truck").into(), + ]), + }, ] } } @@ -68,10 +93,10 @@ async fn sort_by( let registry = registry.clone(); let tag = args.call_info.name_tag.clone(); - let (SortByArgs { rest }, mut input) = args.process(®istry).await?; + let (SortByArgs { rest, insensitive }, mut input) = args.process(®istry).await?; let mut vec = input.drain_vec().await; - sort(&mut vec, &rest, &tag)?; + sort(&mut vec, &rest, &tag, insensitive)?; Ok(futures::stream::iter(vec.into_iter()).to_output_stream()) } @@ -80,6 +105,7 @@ pub fn sort( vec: &mut [Value], keys: &[Tagged], tag: impl Into, + insensitive: bool, ) -> Result<(), ShellError> { let tag = tag.into(); @@ -107,12 +133,38 @@ pub fn sort( value: UntaggedValue::Primitive(_), .. } => { - vec.sort_by(|a, b| coerce_compare(a, b).expect("Unimplemented BUG: What about primitives that don't have an order defined?").compare()); + let should_sort_case_insensitively = insensitive && vec.iter().all(|x| x.is_string()); + + vec.sort_by(|a, b| { + if should_sort_case_insensitively { + let lowercase_a_string = a.expect_string().to_ascii_lowercase(); + let lowercase_b_string = b.expect_string().to_ascii_lowercase(); + + lowercase_a_string.cmp(&lowercase_b_string) + } else { + coerce_compare(a, b).expect("Unimplemented BUG: What about primitives that don't have an order defined?").compare() + } + }); } _ => { let calc_key = |item: &Value| { keys.iter() - .map(|f| get_data_by_key(item, f.borrow_spanned())) + .map(|f| { + let mut value_option = get_data_by_key(item, f.borrow_spanned()); + + if insensitive { + if let Some(value) = &value_option { + if let Ok(string_value) = value.as_string() { + value_option = Some( + UntaggedValue::string(string_value.to_ascii_lowercase()) + .into_value(value.tag.clone()), + ) + } + } + } + + value_option + }) .collect::>>() }; vec.sort_by_cached_key(calc_key); diff --git a/crates/nu-cli/tests/commands/sort_by.rs b/crates/nu-cli/tests/commands/sort_by.rs index 15bb44cd05970..4aa22524e5829 100644 --- a/crates/nu-cli/tests/commands/sort_by.rs +++ b/crates/nu-cli/tests/commands/sort_by.rs @@ -62,3 +62,71 @@ fn sort_primitive_values() { assert_eq!(actual.out, "authors = [\"The Nu Project Contributors\"]"); } + +#[test] +fn ls_sort_by_name_sensitive() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample-ls-output.json + | sort-by name + | select name + | to json + "# + )); + + let json_output = r#"[{"name":"B.txt"},{"name":"C"},{"name":"a.txt"}]"#; + + assert_eq!(actual.out, json_output); +} + +#[test] +fn ls_sort_by_name_insensitive() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample-ls-output.json + | sort-by -i name + | select name + | to json + "# + )); + + let json_output = r#"[{"name":"a.txt"},{"name":"B.txt"},{"name":"C"}]"#; + + assert_eq!(actual.out, json_output); +} + +#[test] +fn ls_sort_by_type_name_sensitive() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample-ls-output.json + | sort-by type name + | select name type + | to json + "# + )); + + let json_output = r#"[{"name":"C","type":"Dir"},{"name":"B.txt","type":"File"},{"name":"a.txt","type":"File"}]"#; + + assert_eq!(actual.out, json_output); +} + +#[test] +fn ls_sort_by_type_name_insensitive() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + open sample-ls-output.json + | sort-by -i type name + | select name type + | to json + "# + )); + + let json_output = r#"[{"name":"C","type":"Dir"},{"name":"a.txt","type":"File"},{"name":"B.txt","type":"File"}]"#; + + assert_eq!(actual.out, json_output); +} diff --git a/crates/nu-protocol/src/value.rs b/crates/nu-protocol/src/value.rs index c2e7964f13ac2..48e398d4aa3e7 100644 --- a/crates/nu-protocol/src/value.rs +++ b/crates/nu-protocol/src/value.rs @@ -85,6 +85,11 @@ impl UntaggedValue { matches!(self, UntaggedValue::Table(_)) } + /// Returns true if this value represents a string + pub fn is_string(&self) -> bool { + matches!(self, UntaggedValue::Primitive(Primitive::String(_))) + } + /// Returns true if the value represents something other than Nothing pub fn is_some(&self) -> bool { !self.is_none() diff --git a/docs/commands/sort-by.md b/docs/commands/sort-by.md index da7911d826d4b..82dfcdaaacc0b 100644 --- a/docs/commands/sort-by.md +++ b/docs/commands/sort-by.md @@ -5,6 +5,10 @@ The `sort-by` command sorts the table being displayed in the terminal by a chose `sort-by` takes multiple arguments (being the names of columns) sorting by each argument in order. +## Flags + +* `-i`, `--insensitive`: Sort string-based columns case insensitively + ## Examples ```shell @@ -53,3 +57,67 @@ The `sort-by` command sorts the table being displayed in the terminal by a chose 7 │ az │ File │ │ 18 B │ 5 minutes ago │ 5 minutes ago ━━━┷━━━━━━┷━━━━━━┷━━━━━━━━━━┷━━━━━━━━┷━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━ ``` + +Within the Nushell repository... + +```shell +> ls | sort-by --insensitive name +────┬────────────────────┬──────┬──────────┬────────────── + # │ name │ type │ size │ modified +────┼────────────────────┼──────┼──────────┼────────────── + 0 │ assets │ Dir │ 128 B │ 6 months ago + 1 │ build.rs │ File │ 78 B │ 5 months ago + 2 │ Cargo.lock │ File │ 118.3 KB │ 1 hour ago + 3 │ Cargo.toml │ File │ 5.5 KB │ 1 hour ago + 4 │ CODE_OF_CONDUCT.md │ File │ 3.4 KB │ 1 hour ago + 5 │ CONTRIBUTING.md │ File │ 1.3 KB │ 1 hour ago + 6 │ crates │ Dir │ 832 B │ 1 hour ago + 7 │ debian │ Dir │ 352 B │ 6 months ago + 8 │ docker │ Dir │ 288 B │ 4 months ago + 9 │ docs │ Dir │ 192 B │ 1 hour ago + 10 │ features.toml │ File │ 632 B │ 5 months ago + 11 │ images │ Dir │ 160 B │ 6 months ago + 12 │ LICENSE │ File │ 1.1 KB │ 4 months ago + 13 │ Makefile.toml │ File │ 449 B │ 6 months ago + 14 │ README.build.txt │ File │ 192 B │ 1 hour ago + 15 │ README.md │ File │ 16.0 KB │ 1 hour ago + 16 │ rustfmt.toml │ File │ 16 B │ 6 months ago + 17 │ src │ Dir │ 128 B │ 1 week ago + 18 │ target │ Dir │ 160 B │ 1 day ago + 19 │ tests │ Dir │ 192 B │ 4 months ago + 20 │ TODO.md │ File │ 0 B │ 1 week ago + 21 │ wix │ Dir │ 128 B │ 1 hour ago +────┴────────────────────┴──────┴──────────┴────────────── +``` + +Within the Nushell repository... + +```shell +> ls | sort-by --insensitive type name +────┬────────────────────┬──────┬──────────┬────────────── + # │ name │ type │ size │ modified +────┼────────────────────┼──────┼──────────┼────────────── + 0 │ assets │ Dir │ 128 B │ 6 months ago + 1 │ crates │ Dir │ 832 B │ 1 hour ago + 2 │ debian │ Dir │ 352 B │ 6 months ago + 3 │ docker │ Dir │ 288 B │ 4 months ago + 4 │ docs │ Dir │ 192 B │ 1 hour ago + 5 │ images │ Dir │ 160 B │ 6 months ago + 6 │ src │ Dir │ 128 B │ 1 week ago + 7 │ target │ Dir │ 160 B │ 1 day ago + 8 │ tests │ Dir │ 192 B │ 4 months ago + 9 │ wix │ Dir │ 128 B │ 1 hour ago + 10 │ build.rs │ File │ 78 B │ 5 months ago + 11 │ Cargo.lock │ File │ 118.3 KB │ 1 hour ago + 12 │ Cargo.toml │ File │ 5.5 KB │ 1 hour ago + 13 │ CODE_OF_CONDUCT.md │ File │ 3.4 KB │ 1 hour ago + 14 │ CONTRIBUTING.md │ File │ 1.3 KB │ 1 hour ago + 15 │ features.toml │ File │ 632 B │ 5 months ago + 16 │ LICENSE │ File │ 1.1 KB │ 4 months ago + 17 │ Makefile.toml │ File │ 449 B │ 6 months ago + 18 │ README.build.txt │ File │ 192 B │ 1 hour ago + 19 │ README.md │ File │ 16.0 KB │ 1 hour ago + 20 │ rustfmt.toml │ File │ 16 B │ 6 months ago + 21 │ TODO.md │ File │ 0 B │ 1 week ago +────┴────────────────────┴──────┴──────────┴────────────── +``` diff --git a/tests/fixtures/formats/sample-ls-output.json b/tests/fixtures/formats/sample-ls-output.json new file mode 100644 index 0000000000000..4636f0353df0e --- /dev/null +++ b/tests/fixtures/formats/sample-ls-output.json @@ -0,0 +1 @@ +[{"name":"a.txt","type":"File","size":3444,"modified":"2020-07-1918:26:30.560716967UTC"},{"name":"B.txt","type":"File","size":1341,"modified":"2020-07-1918:26:30.561021953UTC"},{"name":"C","type":"Dir","size":118253,"modified":"2020-07-1918:26:30.562092480UTC"}] From b9278bdfe15321466173dc78627f3210f9b81e5c Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Mon, 20 Jul 2020 14:25:38 -0500 Subject: [PATCH 3/5] Char example (#2231) * added ansi example * added another example * changed example * ansi changes here by mistake --- crates/nu-cli/src/commands/char_.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/crates/nu-cli/src/commands/char_.rs b/crates/nu-cli/src/commands/char_.rs index 91bc257cf845a..99ca9421bc473 100644 --- a/crates/nu-cli/src/commands/char_.rs +++ b/crates/nu-cli/src/commands/char_.rs @@ -30,11 +30,22 @@ impl WholeStreamCommand for Char { } fn examples(&self) -> Vec { - vec![Example { - description: "Output newline", - example: r#"char newline"#, - result: Some(vec![Value::from("\n")]), - }] + vec![ + Example { + description: "Output newline", + example: r#"char newline"#, + result: Some(vec![Value::from("\n")]), + }, + Example { + description: "Output prompt character, newline and a hamburger character", + example: r#"echo $(char prompt) $(char newline) $(char hamburger)"#, + result: Some(vec![ + UntaggedValue::string("\u{25b6}").into(), + UntaggedValue::string("\n").into(), + UntaggedValue::string("\u{2261}").into(), + ]), + }, + ] } async fn run( From aaed9c4e8aafb6155e8b316b320599ac6e6f60ac Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Mon, 20 Jul 2020 18:33:39 -0500 Subject: [PATCH 4/5] added ansi example (#2230) * added ansi example * added strcollect to example --- crates/nu-cli/src/commands/ansi.rs | 8 ++++++++ crates/nu-cli/src/examples.rs | 3 ++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/crates/nu-cli/src/commands/ansi.rs b/crates/nu-cli/src/commands/ansi.rs index 302710e34424f..6d105b02259ef 100644 --- a/crates/nu-cli/src/commands/ansi.rs +++ b/crates/nu-cli/src/commands/ansi.rs @@ -40,6 +40,14 @@ impl WholeStreamCommand for Ansi { example: r#"ansi reset"#, result: Some(vec![Value::from("\u{1b}[0m")]), }, + Example { + description: + "Use ansi to color text (rb = red bold, gb = green bold, pb = purple bold)", + example: r#"echo [$(ansi rb) Hello " " $(ansi gb) Nu " " $(ansi pb) World] | str collect"#, + result: Some(vec![Value::from( + "\u{1b}[1;31mHello \u{1b}[1;32mNu \u{1b}[1;35mWorld", + )]), + }, ] } diff --git a/crates/nu-cli/src/examples.rs b/crates/nu-cli/src/examples.rs index bb81029b25206..916606aafa03b 100644 --- a/crates/nu-cli/src/examples.rs +++ b/crates/nu-cli/src/examples.rs @@ -6,7 +6,7 @@ use nu_protocol::hir::ClassifiedBlock; use nu_protocol::{ShellTypeName, Value}; use crate::commands::classified::block::run_block; -use crate::commands::{whole_stream_command, BuildString, Echo}; +use crate::commands::{whole_stream_command, BuildString, Echo, StrCollect}; use crate::context::Context; use crate::stream::InputStream; use crate::WholeStreamCommand; @@ -19,6 +19,7 @@ pub fn test(cmd: impl WholeStreamCommand + 'static) { whole_stream_command(Echo {}), whole_stream_command(BuildString {}), whole_stream_command(cmd), + whole_stream_command(StrCollect), ]); for example in examples { From 32b875ada98d8e7e8d50db6966b3a198bedc38fa Mon Sep 17 00:00:00 2001 From: Darren Schroeder <343840+fdncred@users.noreply.github.com> Date: Mon, 20 Jul 2020 21:15:58 -0500 Subject: [PATCH 5/5] sample config settigns (#2233) --- docs/sample_config/config.toml | 35 ++++++ docs/sample_config/keybindings.yml | 189 +++++++++++++++++++++++++++++ 2 files changed, 224 insertions(+) create mode 100644 docs/sample_config/config.toml create mode 100644 docs/sample_config/keybindings.yml diff --git a/docs/sample_config/config.toml b/docs/sample_config/config.toml new file mode 100644 index 0000000000000..7e9a2a8bd86ce --- /dev/null +++ b/docs/sample_config/config.toml @@ -0,0 +1,35 @@ +completion_mode = "circular" +edit_mode = "vi" +history_size = 100000 +key_timeout = 500 + +disable_table_indexes = false +header_align = "l" +header_color = "c" +header_bold = true +nonzero_exit_errors = true +startup = ["alias la [path] {ls --full $path}", "alias nudown [] {fetch https://api.github.com/repos/nushell/nushell/releases | get assets | select name download_count}"] +table_mode = "other" +plugin_dirs = ["D:\\Src\\GitHub\\nu-plugin-lib\\samples\\Nu.Plugin.Len\\bin\\Debug\\netcoreapp3.1"] +pivot_mode = "auto" +ctrlc_exit = false +complete_from_path = true +rm_always_trash = true +use_starship = false +prompt = "echo [ $(ansi gb) $(pwd) $(ansi reset) \"(\" $(ansi cb) $(do -i { git rev-parse --abbrev-ref HEAD | trim }) $(ansi reset) \")\" $(char newline) $(ansi yb) $(date --format \"%m/%d/%Y %I:%M:%S%.3f %p\" --raw) $(ansi reset) \"> \" ] | str collect" + +[textview] +term_width = "default" +tab_width = 4 +colored_output = true +true_color = true +header = true +line_numbers = true +grid = false +vcs_modification_markers = true +snip = true +wrapping_mode = "NoWrapping" +use_italics = true +paging_mode = "QuitIfOneScreen" +pager = "less" +theme = "TwoDark" diff --git a/docs/sample_config/keybindings.yml b/docs/sample_config/keybindings.yml new file mode 100644 index 0000000000000..0f24cb75d483f --- /dev/null +++ b/docs/sample_config/keybindings.yml @@ -0,0 +1,189 @@ +# These are the common keys acrosso modes taken directly from Rustyline. If +# you want to change the keybinding you should change the letter after +# "key:". If you want to change the modifier you should change or add the +# modifier after "key:", such as: +# key: +# Ctrl: A +# Available modifiers are Ctrl, F (for function), Meta (escape-char, alt-char) + +# Common +# KeyPress::Home => Cmd::Move(Movement::BeginningOfLine), +- key: + Home: + binding: + Move: BeginningOfLine + +# KeyPress::End => Cmd::Move(Movement::EndOfLine), +- key: + End: + binding: + Move: EndOfLine + +# KeyPress::Left => { +# if positive { +# Cmd::Move(Movement::BackwardChar(n)) +# } else { +# Cmd::Move(Movement::ForwardChar(n)) +# } +# } +- key: + Left: #Left Arrow Key + binding: + Move: + BackwardChar: 1 + +# KeyPress::Right => { +# if positive { +# Cmd::Move(Movement::ForwardChar(n)) +# } else { +# Cmd::Move(Movement::BackwardChar(n)) +# } +# } +- key: + Right: #Right Arrow Key + binding: + Move: + ForwardChar: 1 + +# KeyPress::Ctrl('C') => Cmd::Interrupt, +- key: + Ctrl: C + binding: + Interrupt: + +# KeyPress::Ctrl('D') => Cmd::EndOfFile, +- key: + Ctrl: D + binding: + EndOfFile: + +# KeyPress::Delete => { +# if positive { +# Cmd::Kill(Movement::ForwardChar(n)) +# } else { +# Cmd::Kill(Movement::BackwardChar(n)) +# } +# } +- key: + Delete: + binding: + Kill: + ForwardChar: 1 + +# KeyPress::Ctrl('J') | +# KeyPress::Enter => Cmd::AcceptLine, +- key: + Ctrl: J + binding: + AcceptLine: +- key: + Enter: + binding: + AcceptLine: + +# KeyPress::Down => Cmd::LineDownOrNextHistory(1), +- key: + Down: #Down Arrow Key + binding: + LineDownOrNextHistory: 1 + +# KeyPress::Up => Cmd::LineUpOrPreviousHistory(1), +- key: + Up: #Up Arrow Key + binding: + LineUpOrPreviousHistory: 1 + +# KeyPress::Ctrl('R') => Cmd::ReverseSearchHistory, +- key: + Ctrl: R + binding: + ReverseSearchHistory: + +# KeyPress::Ctrl('S') => Cmd::ForwardSearchHistory, // most terminals override Ctrl+S to suspend execution +- key: + Ctrl: S + binding: + ForwardSearchHistory: + +# KeyPress::Ctrl('T') => Cmd::TransposeChars, +- key: + Ctrl: T + binding: + TransposeChars: + +# KeyPress::Ctrl('U') => { +# if positive { +# Cmd::Kill(Movement::BeginningOfLine) +# } else { +# Cmd::Kill(Movement::EndOfLine) +# } +# }, +- key: + Ctrl: U + binding: + Kill: BeginningOfLine + +# KeyPress::Ctrl('Q') | // most terminals override Ctrl+Q to resume execution +# KeyPress::Ctrl('V') => Cmd::QuotedInsert, +- key: + Ctrl: Q + binding: + QuotedInsert: +- key: + Ctrl: V + binding: + QuotedInsert: + +# KeyPress::Ctrl('W') => { +# if positive { +# Cmd::Kill(Movement::BackwardWord(n, Word::Big)) +# } else { +# Cmd::Kill(Movement::ForwardWord(n, At::AfterEnd, Word::Big)) +# } +# } +- key: + Ctrl: W + binding: + Kill: + BackwardWord: + repeat: 1 + word: Big + +# KeyPress::Ctrl('Y') => { +# if positive { +# Cmd::Yank(n, Anchor::Before) +# } else { +# Cmd::Unknown // TODO Validate +# } +# } +- key: + Ctrl: Y + binding: + Yank: + repeat: 1 + anchor: Before + +# KeyPress::Ctrl('Z') => Cmd::Suspend, +- key: + Ctrl: Z + binding: + Suspend: + +# KeyPress::Ctrl('_') => Cmd::Undo(n), +- key: + Ctrl: '_' + binding: + Undo: 1 + +# KeyPress::UnknownEscSeq => Cmd::Noop, +- key: + UnknownEscSeq: + binding: + Noop: + +# KeyPress::BracketedPasteStart => { +# let paste = rdr.read_pasted_text()?; +# Cmd::Insert(1, paste) +# }, +# _ => Cmd::Unknown, +# })