From 352309b0566519ffb64adba1848fbdefce878ab6 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 9 Sep 2022 20:21:22 +0200 Subject: [PATCH 01/18] Revert "Remove code that tries to handle ANSI escape inputs" This reverts commit 8174e022797924aec735ff440806920767f80496. Turns out it is needed for a common use case, see https://github.com/sharkdp/bat/issues/2307. It is not a clean revert, because I adjust CHANGELOG.md and also add a comment to the test. I also had to resolve a small `use` conflict. --- CHANGELOG.md | 2 + src/lib.rs | 1 + src/preprocessor.rs | 45 ++++--- src/printer.rs | 232 +++++++++++++++++++++---------------- src/vscreen.rs | 212 +++++++++++++++++++++++++++++++++ tests/integration_tests.rs | 20 ++++ 6 files changed, 396 insertions(+), 116 deletions(-) create mode 100644 src/vscreen.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index ce2c2c41..c8460faf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ ## Bugfixes +- Bring back pre-processing of ANSI escape characters to so that some common `bat` use cases starts working again. See #2308 (@Enselic) + ## Other ## Syntaxes diff --git a/src/lib.rs b/src/lib.rs index 4e3fcb95..0ca67bb9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,6 +46,7 @@ pub(crate) mod printer; pub mod style; pub(crate) mod syntax_mapping; mod terminal; +mod vscreen; pub(crate) mod wrapping; pub use pretty_printer::{Input, PrettyPrinter, Syntax}; diff --git a/src/preprocessor.rs b/src/preprocessor.rs index 6e775595..74590355 100644 --- a/src/preprocessor.rs +++ b/src/preprocessor.rs @@ -1,28 +1,37 @@ use std::fmt::Write; +use console::AnsiCodeIterator; + /// Expand tabs like an ANSI-enabled expand(1). -pub fn expand_tabs(mut text: &str, width: usize, cursor: &mut usize) -> String { - let mut buffer = String::with_capacity(text.len() * 2); +pub fn expand_tabs(line: &str, width: usize, cursor: &mut usize) -> String { + let mut buffer = String::with_capacity(line.len() * 2); - while let Some(index) = text.find('\t') { - // Add previous text. - if index > 0 { - *cursor += index; - buffer.push_str(&text[0..index]); + for chunk in AnsiCodeIterator::new(line) { + match chunk { + (text, true) => buffer.push_str(text), + (mut text, false) => { + while let Some(index) = text.find('\t') { + // Add previous text. + if index > 0 { + *cursor += index; + buffer.push_str(&text[0..index]); + } + + // Add tab. + let spaces = width - (*cursor % width); + *cursor += spaces; + buffer.push_str(&*" ".repeat(spaces)); + + // Next. + text = &text[index + 1..text.len()]; + } + + *cursor += text.len(); + buffer.push_str(text); + } } - - // Add tab. - let spaces = width - (*cursor % width); - *cursor += spaces; - buffer.push_str(&*" ".repeat(spaces)); - - // Next. - text = &text[index + 1..text.len()]; } - *cursor += text.len(); - buffer.push_str(text); - buffer } diff --git a/src/printer.rs b/src/printer.rs index 4f962df9..27c92b91 100644 --- a/src/printer.rs +++ b/src/printer.rs @@ -6,6 +6,8 @@ use ansi_term::Style; use bytesize::ByteSize; +use console::AnsiCodeIterator; + use syntect::easy::HighlightLines; use syntect::highlighting::Color; use syntect::highlighting::Theme; @@ -31,6 +33,7 @@ use crate::line_range::RangeCheckResult; use crate::preprocessor::{expand_tabs, replace_nonprintable}; use crate::style::StyleComponent; use crate::terminal::{as_terminal_escaped, to_ansi_color}; +use crate::vscreen::AnsiStyle; use crate::wrapping::WrappingMode; pub(crate) trait Printer { @@ -119,6 +122,7 @@ pub(crate) struct InteractivePrinter<'a> { config: &'a Config<'a>, decorations: Vec>, panel_width: usize, + ansi_style: AnsiStyle, content_type: Option, #[cfg(feature = "git")] pub line_changes: &'a Option, @@ -202,6 +206,7 @@ impl<'a> InteractivePrinter<'a> { config, decorations, content_type: input.reader.content_type, + ansi_style: AnsiStyle::new(), #[cfg(feature = "git")] line_changes, highlighter_from_set, @@ -480,7 +485,7 @@ impl<'a> Printer for InteractivePrinter<'a> { self.config.highlighted_lines.0.check(line_number) == RangeCheckResult::InRange; if highlight_this_line && self.config.theme == "ansi" { - write!(handle, "\x1B[4m")?; + self.ansi_style.update("^[4m"); } let background_color = self @@ -507,37 +512,51 @@ impl<'a> Printer for InteractivePrinter<'a> { let italics = self.config.use_italic_text; for &(style, region) in ®ions { - let text = &*self.preprocess(region, &mut cursor_total); - let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n'); + let ansi_iterator = AnsiCodeIterator::new(region); + for chunk in ansi_iterator { + match chunk { + // ANSI escape passthrough. + (ansi, true) => { + self.ansi_style.update(ansi); + write!(handle, "{}", ansi)?; + } - write!( - handle, - "{}", - as_terminal_escaped( - style, - text_trimmed, - true_color, - colored_output, - italics, - background_color - ) - )?; + // Regular text. + (text, false) => { + let text = &*self.preprocess(text, &mut cursor_total); + let text_trimmed = text.trim_end_matches(|c| c == '\r' || c == '\n'); - if text.len() != text_trimmed.len() { - if let Some(background_color) = background_color { - let ansi_style = Style { - background: to_ansi_color(background_color, true_color), - ..Default::default() - }; + write!( + handle, + "{}", + as_terminal_escaped( + style, + &format!("{}{}", self.ansi_style, text_trimmed), + true_color, + colored_output, + italics, + background_color + ) + )?; - let width = if cursor_total <= cursor_max { - cursor_max - cursor_total + 1 - } else { - 0 - }; - write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?; + if text.len() != text_trimmed.len() { + if let Some(background_color) = background_color { + let ansi_style = Style { + background: to_ansi_color(background_color, true_color), + ..Default::default() + }; + + let width = if cursor_total <= cursor_max { + cursor_max - cursor_total + 1 + } else { + 0 + }; + write!(handle, "{}", ansi_style.paint(" ".repeat(width)))?; + } + write!(handle, "{}", &text[text_trimmed.len()..])?; + } + } } - write!(handle, "{}", &text[text_trimmed.len()..])?; } } @@ -546,82 +565,98 @@ impl<'a> Printer for InteractivePrinter<'a> { } } else { for &(style, region) in ®ions { - let text = self.preprocess( - region.trim_end_matches(|c| c == '\r' || c == '\n'), - &mut cursor_total, - ); - - let mut max_width = cursor_max - cursor; - - // line buffer (avoid calling write! for every character) - let mut line_buf = String::with_capacity(max_width * 4); - - // Displayed width of line_buf - let mut current_width = 0; - - for c in text.chars() { - // calculate the displayed width for next character - let cw = c.width().unwrap_or(0); - current_width += cw; - - // if next character cannot be printed on this line, - // flush the buffer. - if current_width > max_width { - // Generate wrap padding if not already generated. - if panel_wrap.is_none() { - panel_wrap = if self.panel_width > 0 { - Some(format!( - "{} ", - self.decorations - .iter() - .map(|d| d.generate(line_number, true, self).text) - .collect::>() - .join(" ") - )) - } else { - Some("".to_string()) - } + let ansi_iterator = AnsiCodeIterator::new(region); + for chunk in ansi_iterator { + match chunk { + // ANSI escape passthrough. + (ansi, true) => { + self.ansi_style.update(ansi); + write!(handle, "{}", ansi)?; } - // It wraps. - write!( - handle, - "{}\n{}", - as_terminal_escaped( - style, - &line_buf, - self.config.true_color, - self.config.colored_output, - self.config.use_italic_text, - background_color - ), - panel_wrap.clone().unwrap() - )?; + // Regular text. + (text, false) => { + let text = self.preprocess( + text.trim_end_matches(|c| c == '\r' || c == '\n'), + &mut cursor_total, + ); - cursor = 0; - max_width = cursor_max; + let mut max_width = cursor_max - cursor; - line_buf.clear(); - current_width = cw; + // line buffer (avoid calling write! for every character) + let mut line_buf = String::with_capacity(max_width * 4); + + // Displayed width of line_buf + let mut current_width = 0; + + for c in text.chars() { + // calculate the displayed width for next character + let cw = c.width().unwrap_or(0); + current_width += cw; + + // if next character cannot be printed on this line, + // flush the buffer. + if current_width > max_width { + // Generate wrap padding if not already generated. + if panel_wrap.is_none() { + panel_wrap = if self.panel_width > 0 { + Some(format!( + "{} ", + self.decorations + .iter() + .map(|d| d + .generate(line_number, true, self) + .text) + .collect::>() + .join(" ") + )) + } else { + Some("".to_string()) + } + } + + // It wraps. + write!( + handle, + "{}\n{}", + as_terminal_escaped( + style, + &*format!("{}{}", self.ansi_style, line_buf), + self.config.true_color, + self.config.colored_output, + self.config.use_italic_text, + background_color + ), + panel_wrap.clone().unwrap() + )?; + + cursor = 0; + max_width = cursor_max; + + line_buf.clear(); + current_width = cw; + } + + line_buf.push(c); + } + + // flush the buffer + cursor += current_width; + write!( + handle, + "{}", + as_terminal_escaped( + style, + &*format!("{}{}", self.ansi_style, line_buf), + self.config.true_color, + self.config.colored_output, + self.config.use_italic_text, + background_color + ) + )?; + } } - - line_buf.push(c); } - - // flush the buffer - cursor += current_width; - write!( - handle, - "{}", - as_terminal_escaped( - style, - &line_buf, - self.config.true_color, - self.config.colored_output, - self.config.use_italic_text, - background_color - ) - )?; } if let Some(background_color) = background_color { @@ -640,6 +675,7 @@ impl<'a> Printer for InteractivePrinter<'a> { } if highlight_this_line && self.config.theme == "ansi" { + self.ansi_style.update("^[24m"); write!(handle, "\x1B[24m")?; } diff --git a/src/vscreen.rs b/src/vscreen.rs new file mode 100644 index 00000000..ea5d4da6 --- /dev/null +++ b/src/vscreen.rs @@ -0,0 +1,212 @@ +use std::fmt::{Display, Formatter}; + +// Wrapper to avoid unnecessary branching when input doesn't have ANSI escape sequences. +pub struct AnsiStyle { + attributes: Option, +} + +impl AnsiStyle { + pub fn new() -> Self { + AnsiStyle { attributes: None } + } + + pub fn update(&mut self, sequence: &str) -> bool { + match &mut self.attributes { + Some(a) => a.update(sequence), + None => { + self.attributes = Some(Attributes::new()); + self.attributes.as_mut().unwrap().update(sequence) + } + } + } +} + +impl Display for AnsiStyle { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + match self.attributes { + Some(ref a) => a.fmt(f), + None => Ok(()), + } + } +} + +struct Attributes { + foreground: String, + background: String, + underlined: String, + + /// The character set to use. + /// REGEX: `\^[()][AB0-3]` + charset: String, + + /// A buffer for unknown sequences. + unknown_buffer: String, + + /// ON: ^[1m + /// OFF: ^[22m + bold: String, + + /// ON: ^[2m + /// OFF: ^[22m + dim: String, + + /// ON: ^[4m + /// OFF: ^[24m + underline: String, + + /// ON: ^[3m + /// OFF: ^[23m + italic: String, + + /// ON: ^[9m + /// OFF: ^[29m + strike: String, +} + +impl Attributes { + pub fn new() -> Self { + Attributes { + foreground: "".to_owned(), + background: "".to_owned(), + underlined: "".to_owned(), + charset: "".to_owned(), + unknown_buffer: "".to_owned(), + bold: "".to_owned(), + dim: "".to_owned(), + underline: "".to_owned(), + italic: "".to_owned(), + strike: "".to_owned(), + } + } + + /// Update the attributes with an escape sequence. + /// Returns `false` if the sequence is unsupported. + pub fn update(&mut self, sequence: &str) -> bool { + let mut chars = sequence.char_indices().skip(1); + + if let Some((_, t)) = chars.next() { + match t { + '(' => self.update_with_charset('(', chars.map(|(_, c)| c)), + ')' => self.update_with_charset(')', chars.map(|(_, c)| c)), + '[' => { + if let Some((i, last)) = chars.last() { + // SAFETY: Always starts with ^[ and ends with m. + self.update_with_csi(last, &sequence[2..i]) + } else { + false + } + } + _ => self.update_with_unsupported(sequence), + } + } else { + false + } + } + + fn sgr_reset(&mut self) { + self.foreground.clear(); + self.background.clear(); + self.underlined.clear(); + self.bold.clear(); + self.dim.clear(); + self.underline.clear(); + self.italic.clear(); + self.strike.clear(); + } + + fn update_with_sgr(&mut self, parameters: &str) -> bool { + let mut iter = parameters + .split(';') + .map(|p| if p.is_empty() { "0" } else { p }) + .map(|p| p.parse::()) + .map(|p| p.unwrap_or(0)); // Treat errors as 0. + + while let Some(p) = iter.next() { + match p { + 0 => self.sgr_reset(), + 1 => self.bold = format!("\x1B[{}m", parameters), + 2 => self.dim = format!("\x1B[{}m", parameters), + 3 => self.italic = format!("\x1B[{}m", parameters), + 4 => self.underline = format!("\x1B[{}m", parameters), + 23 => self.italic.clear(), + 24 => self.underline.clear(), + 22 => { + self.bold.clear(); + self.dim.clear(); + } + 30..=39 => self.foreground = Self::parse_color(p, &mut iter), + 40..=49 => self.background = Self::parse_color(p, &mut iter), + 58..=59 => self.underlined = Self::parse_color(p, &mut iter), + 90..=97 => self.foreground = Self::parse_color(p, &mut iter), + 100..=107 => self.foreground = Self::parse_color(p, &mut iter), + _ => { + // Unsupported SGR sequence. + // Be compatible and pretend one just wasn't was provided. + } + } + } + + true + } + + fn update_with_csi(&mut self, finalizer: char, sequence: &str) -> bool { + if finalizer == 'm' { + self.update_with_sgr(sequence) + } else { + false + } + } + + fn update_with_unsupported(&mut self, sequence: &str) -> bool { + self.unknown_buffer.push_str(sequence); + false + } + + fn update_with_charset(&mut self, kind: char, set: impl Iterator) -> bool { + self.charset = format!("\x1B{}{}", kind, set.take(1).collect::()); + true + } + + fn parse_color(color: u16, parameters: &mut dyn Iterator) -> String { + match color % 10 { + 8 => match parameters.next() { + Some(5) /* 256-color */ => format!("\x1B[{};5;{}m", color, join(";", 1, parameters)), + Some(2) /* 24-bit color */ => format!("\x1B[{};2;{}m", color, join(";", 3, parameters)), + Some(c) => format!("\x1B[{};{}m", color, c), + _ => "".to_owned(), + }, + 9 => "".to_owned(), + _ => format!("\x1B[{}m", color), + } + } +} + +impl Display for Attributes { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!( + f, + "{}{}{}{}{}{}{}{}{}", + self.foreground, + self.background, + self.underlined, + self.charset, + self.bold, + self.dim, + self.underline, + self.italic, + self.strike, + ) + } +} + +fn join( + delimiter: &str, + limit: usize, + iterator: &mut dyn Iterator, +) -> String { + iterator + .take(limit) + .map(|i| i.to_string()) + .collect::>() + .join(delimiter) +} diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 02e60a75..9352c372 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1442,6 +1442,26 @@ fn ansi_highlight_underline() { .stderr(""); } +// Ensure that ANSI passthrough is emitted properly for both wrapping and non-wrapping printer. +// See https://github.com/sharkdp/bat/issues/2307 for what common use case this test tests. +#[test] +fn ansi_passthrough_emit() { + for wrapping in &["never", "character"] { + bat() + .arg("--paging=never") + .arg("--color=never") + .arg("--terminal-width=80") + .arg(format!("--wrap={}", wrapping)) + .arg("--decorations=always") + .arg("--style=plain") + .write_stdin("\x1B[33mColor\nColor \x1B[m\nPlain\n") + .assert() + .success() + .stdout("\x1B[33m\x1B[33mColor\n\x1B[33mColor \x1B[m\nPlain\n") + .stderr(""); + } +} + #[test] fn ignored_suffix_arg() { bat() From e5d95796141a719e208208182a5d3c2090a009c6 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Fri, 9 Sep 2022 20:26:55 +0200 Subject: [PATCH 02/18] Bump version to v0.22.1 --- CHANGELOG.md | 12 +----------- Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 3 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8460faf..a8245e0f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,19 +1,9 @@ -# unreleased - -## Features +# v0.22.1 ## Bugfixes - Bring back pre-processing of ANSI escape characters to so that some common `bat` use cases starts working again. See #2308 (@Enselic) -## Other - -## Syntaxes - -## Themes - -## `bat` as a library - # v0.22.0 diff --git a/Cargo.lock b/Cargo.lock index 6793cc53..4aa42a7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -74,7 +74,7 @@ checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" [[package]] name = "bat" -version = "0.22.0" +version = "0.22.1" dependencies = [ "ansi_colours", "ansi_term", diff --git a/Cargo.toml b/Cargo.toml index 7420dd7c..b51d5e4b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ homepage = "https://github.com/sharkdp/bat" license = "MIT/Apache-2.0" name = "bat" repository = "https://github.com/sharkdp/bat" -version = "0.22.0" +version = "0.22.1" exclude = ["assets/syntaxes/*", "assets/themes/*"] build = "build.rs" edition = '2018' From 8bd5a88f07f1e919edba1b93c4e8c2feb80eac85 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sat, 10 Sep 2022 20:39:33 +0200 Subject: [PATCH 03/18] Prepare a new "unreleased" section at the top of CHANGELOG.md --- CHANGELOG.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a8245e0f..986e8a09 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,18 @@ +# unreleased + +## Features + +## Bugfixes + +## Other + +## Syntaxes + +## Themes + +## `bat` as a library + + # v0.22.1 ## Bugfixes From e96cdc3b9505229fb00833cef9096b19fd148d6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 10 Sep 2022 10:08:54 +0300 Subject: [PATCH 04/18] Split bash completion option lists over multiple lines, sync sort with --help For maintainability/diffability. --- assets/completions/bat.bash.in | 62 +++++++++++++++++++++++++++------- 1 file changed, 50 insertions(+), 12 deletions(-) diff --git a/assets/completions/bat.bash.in b/assets/completions/bat.bash.in index 97e32a0a..9f54c966 100644 --- a/assets/completions/bat.bash.in +++ b/assets/completions/bat.bash.in @@ -27,7 +27,12 @@ _bat() { ;; esac COMPREPLY=($(compgen -W " - --build --clear --source --target --blank --help + --build + --clear + --source + --target + --blank + --help " -- "$cur")) return 0 fi @@ -43,10 +48,20 @@ _bat() { compopt -o filenames # for escaping return 0 ;; - -H | --highlight-line | --diff-context | --tabs | --terminal-width | \ - -m | --map-syntax | --style | --line-range | -h | --help | -V | \ - --version | --diagnostic | --config-file | --config-dir | \ - --cache-dir | --generate-config-file) + -H | --highlight-line | \ + --diff-context | \ + --tabs | \ + --terminal-width | \ + -m | --map-syntax | \ + --style | \ + --line-range | \ + --diagnostic | \ + -h | --help | \ + -V | --version | \ + --cache-dir | \ + --config-dir | \ + --config-file | \ + --generate-config-file) # argument required but no completion available, or option # causes an exit return 0 @@ -83,13 +98,36 @@ _bat() { if [[ $cur == -* ]]; then COMPREPLY=($(compgen -W " - --show-all --plain --language --highlight-line - --file-name --diff --diff-context --tabs --wrap - --terminal-width --number --color --italic-text - --decorations --paging --pager --map-syntax --theme - --list-themes --style --line-range --list-languages - --help --version --force-colorization --unbuffered - --diagnostic --config-file --config-dir --cache-dir + --show-all + --plain + --language + --highlight-line + --file-name + --diff + --diff-context + --tabs + --wrap + --terminal-width + --number + --color + --italic-text + --decorations + --force-colorization + --paging + --pager + --map-syntax + --theme + --list-themes + --style + --line-range + --list-languages + --unbuffered + --diagnostic + --help + --version + --cache-dir + --config-dir + --config-file --generate-config-file " -- "$cur")) return 0 From 066701d671e04a07446e6b42b95601417ec2cbbe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 10 Sep 2022 10:19:27 +0300 Subject: [PATCH 05/18] Add --acknowledgements and --ignored-suffix to bash completion --- assets/completions/bat.bash.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/assets/completions/bat.bash.in b/assets/completions/bat.bash.in index 9f54c966..22c29fab 100644 --- a/assets/completions/bat.bash.in +++ b/assets/completions/bat.bash.in @@ -53,9 +53,11 @@ _bat() { --tabs | \ --terminal-width | \ -m | --map-syntax | \ + --ignored-suffix | \ --style | \ --line-range | \ --diagnostic | \ + --acknowledgements | \ -h | --help | \ -V | --version | \ --cache-dir | \ @@ -116,6 +118,7 @@ _bat() { --paging --pager --map-syntax + --ignored-suffix --theme --list-themes --style @@ -123,6 +126,7 @@ _bat() { --list-languages --unbuffered --diagnostic + --acknowledgements --help --version --cache-dir From 46bf3c1e9a984a8e850bfca5bc1d6b4d7afe0835 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 10 Sep 2022 10:21:54 +0300 Subject: [PATCH 06/18] Do not offer bash filename completions with --list-languages/-themes --- assets/completions/bat.bash.in | 2 ++ 1 file changed, 2 insertions(+) diff --git a/assets/completions/bat.bash.in b/assets/completions/bat.bash.in index 22c29fab..f3b31d36 100644 --- a/assets/completions/bat.bash.in +++ b/assets/completions/bat.bash.in @@ -55,7 +55,9 @@ _bat() { -m | --map-syntax | \ --ignored-suffix | \ --style | \ + --list-themes | \ --line-range | \ + -L | --list-languages | \ --diagnostic | \ --acknowledgements | \ -h | --help | \ From c816188f9758c550c961a3e0d8e3594d4ac47c4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 10 Sep 2022 10:33:13 +0300 Subject: [PATCH 07/18] Add --style argument bash completion --- assets/completions/bat.bash.in | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/assets/completions/bat.bash.in b/assets/completions/bat.bash.in index f3b31d36..eea5b6a3 100644 --- a/assets/completions/bat.bash.in +++ b/assets/completions/bat.bash.in @@ -54,7 +54,6 @@ _bat() { --terminal-width | \ -m | --map-syntax | \ --ignored-suffix | \ - --style | \ --list-themes | \ --line-range | \ -L | --list-languages | \ @@ -96,6 +95,30 @@ _bat() { compopt -o filenames # for escaping return 0 ;; + --style) + # shellcheck disable=SC2034 + local -a styles=( + default + full + auto + plain + changes + header + header-filename + header-filesize + grid + rule + numbers + snip + ) + # shellcheck disable=SC2016 + if declare -F _comp_delimited >/dev/null 2>&1; then + # bash-completion > 2.11 + _comp_delimited , -W '"${styles[@]}"' + else + COMPREPLY=($(compgen -W '${styles[@]}' -- "$cur")) + fi + return 0 esac $split && return 0 From 66edfe5dff6eb9c5d9e61a575859cd2a6a3b24be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 10 Sep 2022 10:37:43 +0300 Subject: [PATCH 08/18] Exclude --unbuffered from bash completions It's a no-op, so there's little reason to suggest it. --- assets/completions/bat.bash.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/assets/completions/bat.bash.in b/assets/completions/bat.bash.in index eea5b6a3..7969442d 100644 --- a/assets/completions/bat.bash.in +++ b/assets/completions/bat.bash.in @@ -124,6 +124,7 @@ _bat() { $split && return 0 if [[ $cur == -* ]]; then + # --unbuffered excluded intentionally (no-op) COMPREPLY=($(compgen -W " --show-all --plain @@ -149,7 +150,6 @@ _bat() { --style --line-range --list-languages - --unbuffered --diagnostic --acknowledgements --help From 2dbc88d3afdacf6449f299c70f29e5456904779b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Skytt=C3=A4?= Date: Sat, 10 Sep 2022 11:31:14 +0300 Subject: [PATCH 09/18] Improve bash completion escaping `compopt -o filenames` is a cheap way to accomplish mostly wanted behavior. However it is semantically incorrect when we are not actually completing filenames, and has side effects -- for example adds a trailing slash to candidates matching present dirs. bash >= 4.1 can `printf -v` to an array index, use it instead where available. --- assets/completions/bat.bash.in | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/assets/completions/bat.bash.in b/assets/completions/bat.bash.in index 7969442d..40481b48 100644 --- a/assets/completions/bat.bash.in +++ b/assets/completions/bat.bash.in @@ -10,6 +10,27 @@ __bat_init_completion() _get_comp_words_by_ref "$@" cur prev words cword } +__bat_escape_completions() +{ + # Do not escape if completing a quoted value. + [[ $cur == [\"\']* ]] && return 0 + # printf -v to an array index is available in bash >= 4.1. + # Use it if available, as -o filenames is semantically incorrect if + # we are not actually completing filenames, and it has side effects + # (e.g. adds trailing slash to candidates matching present dirs). + if (( + BASH_VERSINFO[0] > 4 || \ + BASH_VERSINFO[0] == 4 && BASH_VERSINFO[1] > 0 + )); then + local i + for i in ${!COMPREPLY[*]}; do + printf -v "COMPREPLY[i]" %q "${COMPREPLY[i]}" + done + else + compopt -o filenames + fi +} + _bat() { local cur prev words cword split=false if declare -F _init_completion >/dev/null 2>&1; then @@ -45,7 +66,7 @@ _bat() { printf "%s\n" "$lang" done )" -- "$cur")) - compopt -o filenames # for escaping + __bat_escape_completions return 0 ;; -H | --highlight-line | \ @@ -92,7 +113,7 @@ _bat() { --theme) local IFS=$'\n' COMPREPLY=($(compgen -W "$("$1" --list-themes)" -- "$cur")) - compopt -o filenames # for escaping + __bat_escape_completions return 0 ;; --style) From c662801ad8d9d074c8ae0160e2ae08eb1d4f0f9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Oct 2022 02:02:08 +0000 Subject: [PATCH 10/18] Bump console from 0.15.1 to 0.15.2 Bumps [console](https://github.com/console-rs/console) from 0.15.1 to 0.15.2. - [Release notes](https://github.com/console-rs/console/releases) - [Changelog](https://github.com/console-rs/console/blob/master/CHANGELOG.md) - [Commits](https://github.com/console-rs/console/compare/0.15.1...0.15.2) --- updated-dependencies: - dependency-name: console dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 6 +++--- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4aa42a7c..b786eb96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -231,13 +231,13 @@ dependencies = [ [[package]] name = "console" -version = "0.15.1" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89eab4d20ce20cea182308bca13088fecea9c05f6776cf287205d41a0ed3c847" +checksum = "c050367d967ced717c04b65d8c619d863ef9292ce0c5760028655a2fb298718c" dependencies = [ "encode_unicode", + "lazy_static", "libc", - "once_cell", "terminal_size", "unicode-width", "winapi", diff --git a/Cargo.toml b/Cargo.toml index b51d5e4b..586adab8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ atty = { version = "0.2.14", optional = true } ansi_term = "^0.12.1" ansi_colours = "^1.1" bincode = "1.0" -console = "0.15.1" +console = "0.15.2" flate2 = "1.0" once_cell = "1.13" thiserror = "1.0" From 9d39054e184756b61d620a319842343f7e0b9acc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Oct 2022 02:02:06 +0000 Subject: [PATCH 11/18] Bump thiserror from 1.0.33 to 1.0.37 Bumps [thiserror](https://github.com/dtolnay/thiserror) from 1.0.33 to 1.0.37. - [Release notes](https://github.com/dtolnay/thiserror/releases) - [Commits](https://github.com/dtolnay/thiserror/compare/1.0.33...1.0.37) --- updated-dependencies: - dependency-name: thiserror dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index b786eb96..877f1ead 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,18 +1160,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d0a539a918745651435ac7db7a18761589a94cd7e94cd56999f828bf73c8a57" +checksum = "10deb33631e3c9018b9baf9dcbbc4f737320d2b576bac10f6aefa048fa407e3e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c251e90f708e16c49a16f4917dc2131e75222b72edfa9cb7f7c58ae56aae0c09" +checksum = "982d17546b47146b28f7c22e3d08465f6b8903d0ea13c1660d9d84a6e7adcdbb" dependencies = [ "proc-macro2", "quote", From 10ab72f8ae4279c1e58943fcb470f0d0a083a075 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Oct 2022 02:01:58 +0000 Subject: [PATCH 12/18] Bump unicode-width from 0.1.9 to 0.1.10 Bumps [unicode-width](https://github.com/unicode-rs/unicode-width) from 0.1.9 to 0.1.10. - [Release notes](https://github.com/unicode-rs/unicode-width/releases) - [Commits](https://github.com/unicode-rs/unicode-width/compare/v0.1.9...v0.1.10) --- updated-dependencies: - dependency-name: unicode-width dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 877f1ead..3bdacfac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1226,9 +1226,9 @@ dependencies = [ [[package]] name = "unicode-width" -version = "0.1.9" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973" +checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" [[package]] name = "url" diff --git a/Cargo.toml b/Cargo.toml index 586adab8..cf50f169 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,7 +52,7 @@ wild = { version = "2.1", optional = true } content_inspector = "0.2.4" encoding = "0.2" shell-words = { version = "1.1.0", optional = true } -unicode-width = "0.1.9" +unicode-width = "0.1.10" globset = "0.4" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" From b9d5f3878d0a58268b73bd843bededdc566418af Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Oct 2022 02:01:53 +0000 Subject: [PATCH 13/18] Bump semver from 1.0.13 to 1.0.14 Bumps [semver](https://github.com/dtolnay/semver) from 1.0.13 to 1.0.14. - [Release notes](https://github.com/dtolnay/semver/releases) - [Commits](https://github.com/dtolnay/semver/compare/1.0.13...1.0.14) --- updated-dependencies: - dependency-name: semver dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3bdacfac..0ae2b331 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -964,9 +964,9 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" [[package]] name = "semver" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711" +checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "serde" From 42a3ef28e818523c23e1b608935365783fdb9785 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sat, 1 Oct 2022 07:06:40 +0000 Subject: [PATCH 14/18] Bump once_cell from 1.13.1 to 1.15.0 Bumps [once_cell](https://github.com/matklad/once_cell) from 1.13.1 to 1.15.0. - [Release notes](https://github.com/matklad/once_cell/releases) - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.13.1...v1.15.0) --- updated-dependencies: - dependency-name: once_cell dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0ae2b331..4b063d4c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -699,9 +699,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.13.1" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e" +checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1" [[package]] name = "onig" diff --git a/Cargo.toml b/Cargo.toml index cf50f169..a282c424 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -46,7 +46,7 @@ ansi_colours = "^1.1" bincode = "1.0" console = "0.15.2" flate2 = "1.0" -once_cell = "1.13" +once_cell = "1.15" thiserror = "1.0" wild = { version = "2.1", optional = true } content_inspector = "0.2.4" From 16d181a7559fad2e06ae8a8ec535381095e38f90 Mon Sep 17 00:00:00 2001 From: Masanori Kakura Date: Sat, 1 Oct 2022 16:23:20 +0900 Subject: [PATCH 15/18] ja: Update description about Debian/Ubuntu packages --- doc/README-ja.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/README-ja.md b/doc/README-ja.md index 7badf2b9..f23ad098 100644 --- a/doc/README-ja.md +++ b/doc/README-ja.md @@ -186,7 +186,7 @@ man 2 select ### On Ubuntu (`apt` を使用) *... や他のDebianベースのLinuxディストリビューション* -Ubuntu Eoan 19.10 または Debian 不安定版 sid 以降の [the Ubuntu `bat` package](https://packages.ubuntu.com/eoan/bat) または [the Debian `bat` package](https://packages.debian.org/sid/bat) からインストールできます: +[20.04 ("Focal") 以降の Ubuntu](https://packages.ubuntu.com/search?keywords=bat&exact=1) または [2021 年 8 月以降の Debian (Debian 11 - "Bullseye")](https://packages.debian.org/bullseye/bat) では `bat` パッケージが利用できます。 ```bash apt install bat From 9051fc5465f2ad54d8e5de0491a70193e0ecc438 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?G=C3=A1bor=20Lipt=C3=A1k?= Date: Fri, 30 Sep 2022 20:08:50 -0400 Subject: [PATCH 16/18] Add github-actions to Dependabot MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Gábor Lipták --- .github/dependabot.yml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index b4987cae..20b7953c 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -16,3 +16,9 @@ updates: interval: monthly time: "04:00" timezone: Europe/Berlin +- package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: monthly + time: "04:00" + timezone: Europe/Berlin From 0cc4e98560077a937c288e37988f676644e6e147 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 19:42:28 +0000 Subject: [PATCH 17/18] Bump actions/checkout from 2 to 3 Bumps [actions/checkout](https://github.com/actions/checkout) from 2 to 3. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v2...v3) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/CICD.yml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/CICD.yml b/.github/workflows/CICD.yml index 2ccb2f32..268e65c0 100644 --- a/.github/workflows/CICD.yml +++ b/.github/workflows/CICD.yml @@ -24,14 +24,14 @@ jobs: default: true profile: minimal components: rustfmt - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 - run: cargo fmt -- --check license_checks: name: License checks runs-on: ubuntu-20.04 steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v3 with: submodules: true # we especially want to perform license checks on submodules - run: tests/scripts/license-checks.sh @@ -43,7 +43,7 @@ jobs: MSRV_FEATURES: --no-default-features --features minimal-application,bugreport,build-assets steps: - name: Checkout source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install rust toolchain (v${{ env.MIN_SUPPORTED_RUST_VERSION }}) uses: actions-rs/toolchain@v1 @@ -68,7 +68,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Git checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 with: submodules: true # we need all syntax and theme submodules - name: Install Rust toolchain @@ -113,7 +113,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Git checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Prepare environment variables run: | echo "BAT_SYSTEM_CONFIG_PREFIX=$GITHUB_WORKSPACE/tests/examples/system_config" >> $GITHUB_ENV @@ -139,7 +139,7 @@ jobs: runs-on: ubuntu-20.04 steps: - name: Git checkout - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install Rust toolchain uses: actions-rs/toolchain@v1 with: @@ -186,7 +186,7 @@ jobs: - { target: x86_64-unknown-linux-musl , os: ubuntu-20.04, use-cross: true } steps: - name: Checkout source code - uses: actions/checkout@v2 + uses: actions/checkout@v3 - name: Install prerequisites shell: bash From 5fce1389e55ea1c4050393f850747194e3909785 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 3 Oct 2022 19:43:21 +0000 Subject: [PATCH 18/18] Bump serde from 1.0.144 to 1.0.145 Bumps [serde](https://github.com/serde-rs/serde) from 1.0.144 to 1.0.145. - [Release notes](https://github.com/serde-rs/serde/releases) - [Commits](https://github.com/serde-rs/serde/compare/v1.0.144...v1.0.145) --- updated-dependencies: - dependency-name: serde dependency-type: direct:production update-type: version-update:semver-patch ... Signed-off-by: dependabot[bot] --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4b063d4c..c85f77b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -970,18 +970,18 @@ checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" [[package]] name = "serde" -version = "1.0.144" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" +checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.144" +version = "1.0.145" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" +checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c" dependencies = [ "proc-macro2", "quote",