forked from extern/nushell
Support broad range of escape sequences (#2719)
* WIP * changed to matches * fixed a bug with osc * changed back to if let because: clippy * fixed example test
This commit is contained in:
parent
ec77c572b9
commit
0f7e1d4d01
@ -3,12 +3,15 @@ use crate::prelude::*;
|
|||||||
use ansi_term::Color;
|
use ansi_term::Color;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct Ansi;
|
pub struct Ansi;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
struct AnsiArgs {
|
struct AnsiArgs {
|
||||||
color: Value,
|
color: Value,
|
||||||
|
escape: Option<Tagged<String>>,
|
||||||
|
osc: Option<Tagged<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@ -18,15 +21,70 @@ impl WholeStreamCommand for Ansi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("ansi").required(
|
Signature::build("ansi")
|
||||||
"color",
|
.optional(
|
||||||
SyntaxShape::Any,
|
"color",
|
||||||
"the name of the color to use or 'reset' to reset the color",
|
SyntaxShape::Any,
|
||||||
)
|
"the name of the color to use or 'reset' to reset the color",
|
||||||
|
)
|
||||||
|
.named(
|
||||||
|
"escape", // \x1b
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"escape sequence without the escape character(s)",
|
||||||
|
Some('e'),
|
||||||
|
)
|
||||||
|
.named(
|
||||||
|
"osc",
|
||||||
|
SyntaxShape::Any,
|
||||||
|
"operating system command (ocs) escape sequence without the escape character(s)",
|
||||||
|
Some('o'),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
"Output ANSI codes to change color"
|
r#"Output ANSI codes to change color
|
||||||
|
|
||||||
|
For escape sequences:
|
||||||
|
Escape: '\x1b[' is not required for --escape parameter
|
||||||
|
Format: #(;#)m
|
||||||
|
Example: 1;31m for bold red or 2;37;41m for dimmed white fg with red bg
|
||||||
|
There can be multiple text formatting sequence numbers
|
||||||
|
separated by a ; and ending with an m where the # is of the
|
||||||
|
following values:
|
||||||
|
attributes
|
||||||
|
0 reset / normal display
|
||||||
|
1 bold or increased intensity
|
||||||
|
2 faint or decreased intensity
|
||||||
|
3 italic on (non-mono font)
|
||||||
|
4 underline on
|
||||||
|
5 slow blink on
|
||||||
|
6 fast blink on
|
||||||
|
7 reverse video on
|
||||||
|
8 nondisplayed (invisible) on
|
||||||
|
9 strike-through on
|
||||||
|
|
||||||
|
foreground/bright colors background/bright colors
|
||||||
|
30/90 black 40/100 black
|
||||||
|
31/91 red 41/101 red
|
||||||
|
32/92 green 42/102 green
|
||||||
|
33/93 yellow 43/103 yellow
|
||||||
|
34/94 blue 44/104 blue
|
||||||
|
35/95 magenta 45/105 magenta
|
||||||
|
36/96 cyan 46/106 cyan
|
||||||
|
37/97 white 47/107 white
|
||||||
|
https://en.wikipedia.org/wiki/ANSI_escape_code
|
||||||
|
|
||||||
|
OSC: '\x1b]' is not required for --osc parameter
|
||||||
|
Example: echo [$(ansi -o '0') 'some title' $(char bel)] | str collect
|
||||||
|
Format: #
|
||||||
|
0 Set window title and icon name
|
||||||
|
1 Set icon name
|
||||||
|
2 Set window title
|
||||||
|
4 Set/read color palette
|
||||||
|
9 iTerm2 Grown notifications
|
||||||
|
10 Set foreground color (x11 color spec)
|
||||||
|
11 Set background color (x11 color spec)
|
||||||
|
... others"#
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
@ -49,6 +107,14 @@ impl WholeStreamCommand for Ansi {
|
|||||||
"\u{1b}[1;31mHello \u{1b}[1;32mNu \u{1b}[1;35mWorld",
|
"\u{1b}[1;31mHello \u{1b}[1;32mNu \u{1b}[1;35mWorld",
|
||||||
)]),
|
)]),
|
||||||
},
|
},
|
||||||
|
Example {
|
||||||
|
description:
|
||||||
|
"Use ansi to color text (rb = red bold, gb = green bold, pb = purple bold)",
|
||||||
|
example: r#"echo [$(ansi -e '3;93;41m') Hello $(ansi reset) " " $(ansi gb) Nu " " $(ansi pb) World] | str collect"#,
|
||||||
|
result: Some(vec![Value::from(
|
||||||
|
"\u{1b}[3;93;41mHello\u{1b}[0m \u{1b}[1;32mNu \u{1b}[1;35mWorld",
|
||||||
|
)]),
|
||||||
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,10 +123,41 @@ impl WholeStreamCommand for Ansi {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
let (AnsiArgs { color }, _) = args.process(®istry).await?;
|
let (AnsiArgs { color, escape, osc }, _) = args.process(®istry).await?;
|
||||||
|
|
||||||
|
if let Some(e) = escape {
|
||||||
|
let esc_vec: Vec<char> = e.item.chars().collect();
|
||||||
|
if esc_vec[0] == '\\' {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
|
"no need for escape characters",
|
||||||
|
"no need for escape characters",
|
||||||
|
e.tag(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
let output = format!("\x1b[{}", e.item);
|
||||||
|
return Ok(OutputStream::one(ReturnSuccess::value(
|
||||||
|
UntaggedValue::string(output).into_value(e.tag()),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(o) = osc {
|
||||||
|
let osc_vec: Vec<char> = o.item.chars().collect();
|
||||||
|
if osc_vec[0] == '\\' {
|
||||||
|
return Err(ShellError::labeled_error(
|
||||||
|
"no need for escape characters",
|
||||||
|
"no need for escape characters",
|
||||||
|
o.tag(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
//Operating system command aka osc ESC ] <- note the right brace, not left brace for osc
|
||||||
|
// OCS's need to end with a bell '\x07' char
|
||||||
|
let output = format!("\x1b]{};", o.item);
|
||||||
|
return Ok(OutputStream::one(ReturnSuccess::value(
|
||||||
|
UntaggedValue::string(output).into_value(o.tag()),
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
let color_string = color.as_string()?;
|
let color_string = color.as_string()?;
|
||||||
|
|
||||||
let ansi_code = str_to_ansi_color(color_string);
|
let ansi_code = str_to_ansi_color(color_string);
|
||||||
|
|
||||||
if let Some(output) = ansi_code {
|
if let Some(output) = ansi_code {
|
||||||
@ -74,6 +171,7 @@ impl WholeStreamCommand for Ansi {
|
|||||||
color.tag(),
|
color.tag(),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user