diff --git a/README.md b/README.md index 6ec0e0f613..b318a5dbcb 100644 --- a/README.md +++ b/README.md @@ -1877,6 +1877,30 @@ A number of constants are predefined: | `HEX`1.27.0 | `"0123456789abcdef"` | | `HEXLOWER`1.27.0 | `"0123456789abcdef"` | | `HEXUPPER`1.27.0 | `"0123456789ABCDEF"` | +| `CLEAR`master | `"\ec"` | +| `NORMAL`master | `"\e[0m"` | +| `BOLD`master | `"\e[1m"` | +| `ITALIC`master | `"\e[3m"` | +| `UNDERLINE`master | `"\e[4m"` | +| `INVERT`master | `"\e[7m"` | +| `HIDE`master | `"\e[8m"` | +| `STRIKETHROUGH`master | `"\e[9m"` | +| `BLACK`master | `"\e[30m"` | +| `RED`master | `"\e[31m"` | +| `GREEN`master | `"\e[32m"` | +| `YELLOW`master | `"\e[33m"` | +| `BLUE`master | `"\e[34m"` | +| `MAGENTA`master | `"\e[35m"` | +| `CYAN`master | `"\e[36m"` | +| `WHITE`master | `"\e[37m"` | +| `BG_BLACK`master | `"\e[40m"` | +| `BG_RED`master | `"\e[41m"` | +| `BG_GREEN`master | `"\e[42m"` | +| `BG_YELLOW`master | `"\e[43m"` | +| `BG_BLUE`master | `"\e[44m"` | +| `BG_MAGENTA`master | `"\e[45m"` | +| `BG_CYAN`master | `"\e[46m"` | +| `BG_WHITE`master | `"\e[47m"` | ```just @foo: @@ -1888,9 +1912,29 @@ $ just foo 0123456789abcdef ``` +Constants starting with `\e` are +[ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_escape_code). + +`CLEAR` clears the screen, similar to the `clear` command. The rest are of the +form `\e[Nm`, where `N` is an integer, and set terminal display attributes. + +Terminal display attribute escape sequences can be combined, for example text +weight `BOLD`, text style `STRIKETHROUGH`, foreground color `CYAN`, and +background color `BG_BLUE`. They should be followed by `NORMAL`, to reset the +terminal back to normal. + +Escape sequences should be quoted, since `[` is treated as a special character +by some shells. + +```just +@foo: + echo '{{BOLD + STRIKETHROUGH + CYAN + BG_BLUE}}Hi!{{NORMAL}}' +``` + ### Attributes -Recipes, `mod` statements, and aliases may be annotated with attributes that change their behavior. +Recipes, `mod` statements, and aliases may be annotated with attributes that +change their behavior. | Name | Type | Description | |------|------|-------------| diff --git a/justfile b/justfile index 5ab153626e..e975d506fb 100755 --- a/justfile +++ b/justfile @@ -169,6 +169,10 @@ build-book: mdbook build book/en mdbook build book/zh +[group: 'dev'] +print-readme-constants-table: + cargo test constants::tests::readme_table -- --nocapture + # run all polyglot recipes [group: 'demo'] polyglot: _python _js _perl _sh _ruby diff --git a/src/constants.rs b/src/constants.rs index e9007ea771..5dd17681bf 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,15 +1,58 @@ use super::*; +const CONSTANTS: [(&str, &str, &str); 27] = [ + ("HEX", "0123456789abcdef", "1.27.0"), + ("HEXLOWER", "0123456789abcdef", "1.27.0"), + ("HEXUPPER", "0123456789ABCDEF", "1.27.0"), + ("CLEAR", "\x1bc", "master"), + ("NORMAL", "\x1b[0m", "master"), + ("BOLD", "\x1b[1m", "master"), + ("ITALIC", "\x1b[3m", "master"), + ("UNDERLINE", "\x1b[4m", "master"), + ("INVERT", "\x1b[7m", "master"), + ("HIDE", "\x1b[8m", "master"), + ("STRIKETHROUGH", "\x1b[9m", "master"), + ("BLACK", "\x1b[30m", "master"), + ("RED", "\x1b[31m", "master"), + ("GREEN", "\x1b[32m", "master"), + ("YELLOW", "\x1b[33m", "master"), + ("BLUE", "\x1b[34m", "master"), + ("MAGENTA", "\x1b[35m", "master"), + ("CYAN", "\x1b[36m", "master"), + ("WHITE", "\x1b[37m", "master"), + ("BG_BLACK", "\x1b[40m", "master"), + ("BG_RED", "\x1b[41m", "master"), + ("BG_GREEN", "\x1b[42m", "master"), + ("BG_YELLOW", "\x1b[43m", "master"), + ("BG_BLUE", "\x1b[44m", "master"), + ("BG_MAGENTA", "\x1b[45m", "master"), + ("BG_CYAN", "\x1b[46m", "master"), + ("BG_WHITE", "\x1b[47m", "master"), +]; + pub(crate) fn constants() -> &'static HashMap<&'static str, &'static str> { - static CONSTANTS: OnceLock> = OnceLock::new(); - - CONSTANTS.get_or_init(|| { - vec![ - ("HEX", "0123456789abcdef"), - ("HEXLOWER", "0123456789abcdef"), - ("HEXUPPER", "0123456789ABCDEF"), - ] - .into_iter() - .collect() + static MAP: OnceLock> = OnceLock::new(); + MAP.get_or_init(|| { + CONSTANTS + .into_iter() + .map(|(name, value, _version)| (name, value)) + .collect() }) } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn readme_table() { + println!("| Name | Value |"); + println!("|------|-------------|"); + for (name, value, version) in CONSTANTS { + println!( + "| `{name}`{version} | `\"{}\"` |", + value.replace('\x1b', "\\e") + ); + } + } +}