1
1
mirror of https://github.com/casey/just.git synced 2024-11-22 02:09:44 +03:00

Merge remote-tracking branch 'origin/master' into attributeset

This commit is contained in:
Casey Rodarmor 2024-11-11 15:39:46 -08:00
commit a9e568f92d
6 changed files with 170 additions and 18 deletions

View File

@ -401,7 +401,7 @@ Using package managers pre-installed on GitHub Actions runners on MacOS with
With [extractions/setup-just](https://github.com/extractions/setup-just):
```yaml
- uses: extractions/setup-just@v1
- uses: extractions/setup-just@v2
with:
just-version: 1.5.0 # optional semver specification, otherwise latest
```
@ -1578,11 +1578,11 @@ file.
and can be changed with `set shell := […]`.
`command` is passed as the first argument, so if the command is `'echo $@'`,
the full command line, with the default shell command `shell -cu` and `args`
the full command line, with the default shell command `sh -cu` and `args`
`'foo'` and `'bar'` will be:
```
'shell' '-cu' 'echo $@' 'echo $@' 'foo' 'bar'
'sh' '-cu' 'echo $@' 'echo $@' 'foo' 'bar'
```
This is so that `$@` works as expected, and `$1` refers to the first
@ -1877,6 +1877,30 @@ A number of constants are predefined:
| `HEX`<sup>1.27.0</sup> | `"0123456789abcdef"` |
| `HEXLOWER`<sup>1.27.0</sup> | `"0123456789abcdef"` |
| `HEXUPPER`<sup>1.27.0</sup> | `"0123456789ABCDEF"` |
| `CLEAR`<sup>master</sup> | `"\ec"` |
| `NORMAL`<sup>master</sup> | `"\e[0m"` |
| `BOLD`<sup>master</sup> | `"\e[1m"` |
| `ITALIC`<sup>master</sup> | `"\e[3m"` |
| `UNDERLINE`<sup>master</sup> | `"\e[4m"` |
| `INVERT`<sup>master</sup> | `"\e[7m"` |
| `HIDE`<sup>master</sup> | `"\e[8m"` |
| `STRIKETHROUGH`<sup>master</sup> | `"\e[9m"` |
| `BLACK`<sup>master</sup> | `"\e[30m"` |
| `RED`<sup>master</sup> | `"\e[31m"` |
| `GREEN`<sup>master</sup> | `"\e[32m"` |
| `YELLOW`<sup>master</sup> | `"\e[33m"` |
| `BLUE`<sup>master</sup> | `"\e[34m"` |
| `MAGENTA`<sup>master</sup> | `"\e[35m"` |
| `CYAN`<sup>master</sup> | `"\e[36m"` |
| `WHITE`<sup>master</sup> | `"\e[37m"` |
| `BG_BLACK`<sup>master</sup> | `"\e[40m"` |
| `BG_RED`<sup>master</sup> | `"\e[41m"` |
| `BG_GREEN`<sup>master</sup> | `"\e[42m"` |
| `BG_YELLOW`<sup>master</sup> | `"\e[43m"` |
| `BG_BLUE`<sup>master</sup> | `"\e[44m"` |
| `BG_MAGENTA`<sup>master</sup> | `"\e[45m"` |
| `BG_CYAN`<sup>master</sup> | `"\e[46m"` |
| `BG_WHITE`<sup>master</sup> | `"\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 |
|------|------|-------------|

View File

@ -29,7 +29,7 @@ fuzz:
run:
cargo run
# only run tests matching PATTERN
# only run tests matching `PATTERN`
[group: 'test']
filter PATTERN:
cargo test {{PATTERN}}
@ -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

View File

@ -66,6 +66,10 @@ impl Color {
self.restyle(Style::new().fg(Blue))
}
pub(crate) fn doc_backtick(self) -> Self {
self.restyle(Style::new().fg(White).on(Black))
}
pub(crate) fn error(self) -> Self {
self.restyle(Style::new().fg(Red).bold())
}

View File

@ -1,15 +1,58 @@
use super::*;
pub(crate) fn constants() -> &'static HashMap<&'static str, &'static str> {
static CONSTANTS: OnceLock<HashMap<&str, &str>> = OnceLock::new();
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"),
];
CONSTANTS.get_or_init(|| {
vec![
("HEX", "0123456789abcdef"),
("HEXLOWER", "0123456789abcdef"),
("HEXUPPER", "0123456789ABCDEF"),
]
.into_iter()
.collect()
pub(crate) fn constants() -> &'static HashMap<&'static str, &'static str> {
static MAP: OnceLock<HashMap<&str, &str>> = 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}`<sup>{version}</sup> | `\"{}\"` |",
value.replace('\x1b', "\\e")
);
}
}
}

View File

@ -2,6 +2,11 @@ use {super::*, clap_mangen::Man};
const INIT_JUSTFILE: &str = "default:\n echo 'Hello, world!'\n";
fn backtick_re() -> &'static Regex {
static BACKTICK_RE: OnceLock<Regex> = OnceLock::new();
BACKTICK_RE.get_or_init(|| Regex::new("(`.*?`)|(`[^`]*$)").unwrap())
}
#[derive(PartialEq, Clone, Debug)]
pub(crate) enum Subcommand {
Changelog,
@ -413,15 +418,31 @@ impl Subcommand {
) {
if let Some(doc) = doc {
if !doc.is_empty() && doc.lines().count() <= 1 {
let color = config.color.stdout();
print!(
"{:padding$}{} {}",
"{:padding$}{} ",
"",
config.color.stdout().doc().paint("#"),
config.color.stdout().doc().paint(doc),
color.doc().paint("#"),
padding = max_signature_width.saturating_sub(signature_widths[name]) + 1,
);
let mut end = 0;
for backtick in backtick_re().find_iter(doc) {
let prefix = &doc[end..backtick.start()];
if !prefix.is_empty() {
print!("{}", color.doc().paint(prefix));
}
print!("{}", color.doc_backtick().paint(backtick.as_str()));
end = backtick.end();
}
let suffix = &doc[end..];
if !suffix.is_empty() {
print!("{}", color.doc().paint(suffix));
}
}
}
println!();
}

View File

@ -438,3 +438,39 @@ fn no_space_before_submodules_not_following_groups() {
)
.run();
}
#[test]
fn backticks_highlighted() {
Test::new()
.justfile(
"
# Comment `` `with backticks` and trailing text
recipe:
",
)
.args(["--list", "--color=always"])
.stdout(
"
Available recipes:
recipe \u{1b}[34m#\u{1b}[0m \u{1b}[34mComment \u{1b}[0m\u{1b}[40;37m``\u{1b}[0m\u{1b}[34m \u{1b}[0m\u{1b}[40;37m`with backticks`\u{1b}[0m\u{1b}[34m and trailing text\u{1b}[0m
")
.run();
}
#[test]
fn unclosed_backticks() {
Test::new()
.justfile(
"
# Comment `with unclosed backick
recipe:
",
)
.args(["--list", "--color=always"])
.stdout(
"
Available recipes:
recipe \u{1b}[34m#\u{1b}[0m \u{1b}[34mComment \u{1b}[0m\u{1b}[40;37m`with unclosed backick\u{1b}[0m
")
.run();
}