mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 08:55:40 +02:00
feat: add ansi style reset codes (#16099)
<!-- if this PR closes one or more issues, you can automatically link the PR with them by using one of the [*linking keywords*](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword), e.g. - this PR should close #xxxx - fixes #xxxx you can also mention related issues, PRs or discussions! --> # Description This is so the styling can be set and reset without resetting the color. NB. I don't have any domain or language knowledge here so am trying to stick with existing patterns but it might be good to find out why code like `Style::new().bold().prefix()` was used instead of just the raw SGR (Select Graphic Rendition) codes (eg. `"\x1b[1m"`) # User-Facing Changes <!-- List of all changes that impact the user experience here. This helps us keep track of breaking changes. --> # Tests + Formatting <!-- Don't forget to add tests that cover your changes. Make sure you've run and fixed any issues with these commands: - `cargo fmt --all -- --check` to check standard code formatting (`cargo fmt --all` applies these changes) - `cargo clippy --workspace -- -D warnings -D clippy::unwrap_used` to check that you're using the standard code style - `cargo test --workspace` to check that all tests pass (on Windows make sure to [enable developer mode](https://learn.microsoft.com/en-us/windows/apps/get-started/developer-mode-features-and-debugging)) - `cargo run -- -c "use toolkit.nu; toolkit test stdlib"` to run the tests for the standard library > **Note** > from `nushell` you can also use the `toolkit` as follows > ```bash > use toolkit.nu # or use an `env_change` hook to activate it automatically > toolkit check pr > ``` --> # After Submitting <!-- If your PR had any user-facing changes, update [the documentation](https://github.com/nushell/nushell.github.io) after the PR is merged, if necessary. This will help us keep the docs up to date. -->
This commit is contained in:
@ -425,17 +425,37 @@ static CODE_LIST: LazyLock<Vec<AnsiCode>> = LazyLock::new(|| { vec![
|
||||
AnsiCode { short_name: Some("grey89"), long_name: "xterm_grey89", code: Color::Fixed(254).prefix().to_string()},
|
||||
AnsiCode { short_name: Some("grey93"), long_name: "xterm_grey93", code: Color::Fixed(255).prefix().to_string()},
|
||||
|
||||
// Attributes
|
||||
// Attribute, SGR (Select Graphic Rendition) style codes
|
||||
AnsiCode { short_name: Some("n"), long_name: "attr_normal", code: Color::Green.suffix().to_string()},
|
||||
AnsiCode { short_name: Some("bo"), long_name: "attr_bold", code: Style::new().bold().prefix().to_string()},
|
||||
AnsiCode { short_name: Some("d"), long_name: "attr_dimmed", code: Style::new().dimmed().prefix().to_string()},
|
||||
AnsiCode { short_name: Some("i"), long_name: "attr_italic", code: Style::new().italic().prefix().to_string()},
|
||||
AnsiCode { short_name: Some("u"), long_name: "attr_underline", code: Style::new().underline().prefix().to_string()},
|
||||
|
||||
// NOTE: Most modern terminals ignore SGR codes 5 & 6 as they are considered distracting or even
|
||||
// seizure-triggering for some users. We're including them here for completeness and compatibility with older terminals.
|
||||
AnsiCode { short_name: Some("bl"), long_name: "attr_blink", code: Style::new().blink().prefix().to_string()},
|
||||
AnsiCode { short_name: Some("bf"), long_name: "attr_blink_fast", code: "\x1b[6m".to_owned()},
|
||||
|
||||
AnsiCode { short_name: Some("re"), long_name: "attr_reverse", code: Style::new().reverse().prefix().to_string()},
|
||||
AnsiCode { short_name: Some("h"), long_name: "attr_hidden", code: Style::new().hidden().prefix().to_string()},
|
||||
AnsiCode { short_name: Some("s"), long_name: "attr_strike", code: Style::new().strikethrough().prefix().to_string()},
|
||||
|
||||
// NOTE: Double underline (SGR 21) is not widely supported and may be interpreted as "reset bold" in some terminals.
|
||||
// For resetting bold or dim text, use SGR 22 instead.
|
||||
AnsiCode{ short_name: Some("du"), long_name: "attr_double_underline", code: "\x1b[21m".to_owned()},
|
||||
|
||||
// Reset SGR (Select Graphic Rendition) codes...
|
||||
AnsiCode{ short_name: Some("rst"), long_name: "reset", code: "\x1b[0m".to_owned()},
|
||||
AnsiCode{ short_name: Some("rst_bo"), long_name: "reset_bold", code: "\x1b[22m".to_owned()},
|
||||
AnsiCode{ short_name: Some("rst_d"), long_name: "reset_dimmed", code: "\x1b[22m".to_owned()},
|
||||
AnsiCode{ short_name: Some("rst_i"), long_name: "reset_italic", code: "\x1b[23m".to_owned()},
|
||||
AnsiCode{ short_name: Some("rst_u"), long_name: "reset_underline", code: "\x1b[24m".to_owned()},
|
||||
AnsiCode{ short_name: Some("rst_bl"), long_name: "reset_blink", code: "\x1b[25m".to_owned()},
|
||||
// NB. SGR 26 was reserved in the spec but never used
|
||||
AnsiCode{ short_name: Some("rst_re"), long_name: "reset_reverse", code: "\x1b[27m".to_owned()},
|
||||
AnsiCode{ short_name: Some("rst_h"), long_name: "reset_hidden", code: "\x1b[28m".to_owned()},
|
||||
AnsiCode{ short_name: Some("rst_s"), long_name: "reset_strike", code: "\x1b[29m".to_owned()},
|
||||
|
||||
// Reference for ansi codes https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
|
||||
// Another good reference http://ascii-table.com/ansi-escape-sequences.php
|
||||
@ -571,21 +591,30 @@ Escape sequences usual values:
|
||||
│ 17 │ background │ 49 │ │ default │
|
||||
╰────┴────────────┴────────┴────────┴─────────╯
|
||||
|
||||
Escape sequences attributes:
|
||||
╭───┬────┬──────────────┬──────────────────────────────╮
|
||||
│ # │ id │ abbreviation │ description │
|
||||
├───┼────┼──────────────┼──────────────────────────────┤
|
||||
│ 0 │ 0 │ │ reset / normal display │
|
||||
│ 1 │ 1 │ b │ bold or increased intensity │
|
||||
│ 2 │ 2 │ d │ faint or decreased intensity │
|
||||
│ 3 │ 3 │ i │ italic on (non-mono font) │
|
||||
│ 4 │ 4 │ u │ underline on │
|
||||
│ 5 │ 5 │ l │ slow blink on │
|
||||
│ 6 │ 6 │ │ fast blink on │
|
||||
│ 7 │ 7 │ r │ reverse video on │
|
||||
│ 8 │ 8 │ h │ nondisplayed (invisible) on │
|
||||
│ 9 │ 9 │ s │ strike-through on │
|
||||
╰───┴────┴──────────────┴──────────────────────────────╯
|
||||
Escape sequences style attributes:
|
||||
╭────┬────┬──────────────┬─────────────────────────────────────────╮
|
||||
│ # │ id │ abbreviation │ description │
|
||||
├────┼────┼──────────────┼─────────────────────────────────────────┤
|
||||
│ 0 │ 0 │ rst │ reset / normal display │
|
||||
│ 1 │ 1 │ bo │ bold on │
|
||||
│ 2 │ 2 │ d │ dimmed on │
|
||||
│ 3 │ 3 │ i │ italic on (non-mono font) │
|
||||
│ 4 │ 4 │ u │ underline on │
|
||||
│ 5 │ 5 │ bl │ blink on │
|
||||
│ 6 │ 6 │ bf │ fast blink on │
|
||||
│ 7 │ 7 │ r │ reverse video on │
|
||||
│ 8 │ 8 │ h │ hidden (invisible) on │
|
||||
│ 9 │ 9 │ s │ strike-through on │
|
||||
│ 10 │ 21 │ rst_bo │ bold or dimmed off │
|
||||
│ 11 │ 22 │ du │ double underline (not widely supported) │
|
||||
│ 12 │ 23 │ rst_i │ italic off (non-mono font) │
|
||||
│ 13 │ 24 │ rst_u │ underline off │
|
||||
│ 14 │ 25 │ rst_bl │ blink off │
|
||||
│ 15 │ 26 │ │ <reserved> │
|
||||
│ 16 │ 27 │ rst_r │ reverse video off │
|
||||
│ 17 │ 28 │ rst_h │ hidden (invisible) off │
|
||||
│ 18 │ 29 │ rst_s │ strike-through off │
|
||||
╰────┴────┴──────────────┴─────────────────────────────────────────╯
|
||||
|
||||
Operating system commands:
|
||||
╭───┬─────┬───────────────────────────────────────╮
|
||||
@ -610,7 +639,7 @@ Operating system commands:
|
||||
result: Some(Value::test_string("\u{1b}[32m")),
|
||||
},
|
||||
Example {
|
||||
description: "Reset the color",
|
||||
description: "Reset all styles and colors",
|
||||
example: r#"ansi reset"#,
|
||||
result: Some(Value::test_string("\u{1b}[0m")),
|
||||
},
|
||||
@ -623,11 +652,18 @@ Operating system commands:
|
||||
},
|
||||
Example {
|
||||
description: "The same example as above with short names",
|
||||
example: r#"$'(ansi rb)Hello(ansi reset) (ansi gd)Nu(ansi reset) (ansi pi)World(ansi reset)'"#,
|
||||
example: r#"$'(ansi rb)Hello(ansi rst) (ansi gd)Nu(ansi rst) (ansi pi)World(ansi rst)'"#,
|
||||
result: Some(Value::test_string(
|
||||
"\u{1b}[1;31mHello\u{1b}[0m \u{1b}[2;32mNu\u{1b}[0m \u{1b}[3;35mWorld\u{1b}[0m",
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Avoid resetting color when setting/resetting different style codes",
|
||||
example: r#"$'Set color to (ansi g)GREEN then style to (ansi bo)BOLD(ansi rst_bo) or (ansi d)DIMMED(ansi rst_d) or (ansi i)ITALICS(ansi rst_i) or (ansi u)UNDERLINE(ansi rst_u) or (ansi re)REVERSE(ansi rst_re) or (ansi h)HIDDEN(ansi rst_h) or (ansi s)STRIKE(ansi rst_s) then (ansi rst)reset everything'"#,
|
||||
result: Some(Value::test_string(
|
||||
"Set color to \u{1b}[32mGREEN then style to \u{1b}[1mBOLD\u{1b}[22m or \u{1b}[2mDIMMED\u{1b}[22m or \u{1b}[3mITALICS\u{1b}[23m or \u{1b}[4mUNDERLINE\u{1b}[24m or \u{1b}[7mREVERSE\u{1b}[27m or \u{1b}[8mHIDDEN\u{1b}[28m or \u{1b}[9mSTRIKE\u{1b}[29m then \u{1b}[0mreset everything",
|
||||
)),
|
||||
},
|
||||
Example {
|
||||
description: "Use escape codes, without the '\\x1b['",
|
||||
example: r#"$"(ansi --escape '3;93;41m')Hello(ansi reset)" # italic bright yellow on red background"#,
|
||||
|
@ -11,7 +11,7 @@ fn test_ansi_shows_error_on_escape() {
|
||||
fn test_ansi_list_outputs_table() {
|
||||
let actual = nu!("ansi --list | length");
|
||||
|
||||
assert_eq!(actual.out, "429");
|
||||
assert_eq!(actual.out, "440");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
Reference in New Issue
Block a user