mirror of
https://github.com/sharkdp/bat
synced 2026-08-04 19:01:44 +00:00
Merge branch 'master' into fix/lessclose-nonzero-warning
This commit is contained in:
@@ -240,6 +240,7 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
.arg(
|
||||
Arg::new("terminal-width")
|
||||
.long("terminal-width")
|
||||
.overrides_with("terminal-width")
|
||||
.value_name("width")
|
||||
.hide_short_help(true)
|
||||
.allow_hyphen_values(true)
|
||||
@@ -255,10 +256,13 @@ pub fn build_app(interactive_output: bool) -> Command {
|
||||
})
|
||||
.map_err(|e| e.to_string())
|
||||
})
|
||||
.help(
|
||||
.help("Explicitly set the width of the terminal instead of determining it automatically.")
|
||||
.long_help(
|
||||
"Explicitly set the width of the terminal instead of determining it \
|
||||
automatically. If prefixed with '+' or '-', the value will be treated \
|
||||
as an offset to the actual terminal width. See also: '--wrap'.",
|
||||
as an offset to the actual terminal width. This can also be configured \
|
||||
via the BAT_WIDTH environment variable (e.g. export BAT_WIDTH=\"100\"). \
|
||||
See also: '--wrap'.",
|
||||
),
|
||||
)
|
||||
.arg(
|
||||
|
||||
@@ -153,6 +153,7 @@ fn get_args_from_str(content: &str) -> Result<Vec<OsString>, shell_words::ParseE
|
||||
pub fn get_args_from_env_vars() -> Vec<OsString> {
|
||||
[
|
||||
("--tabs", "BAT_TABS"),
|
||||
("--terminal-width", "BAT_WIDTH"),
|
||||
("--theme", bat::theme::env::BAT_THEME),
|
||||
("--theme-dark", bat::theme::env::BAT_THEME_DARK),
|
||||
("--theme-light", bat::theme::env::BAT_THEME_LIGHT),
|
||||
|
||||
+26
-1
@@ -285,7 +285,28 @@ fn run_controller(inputs: Vec<Input>, config: &Config, cache_dir: &Path) -> Resu
|
||||
|
||||
#[cfg(feature = "bugreport")]
|
||||
fn invoke_bugreport(app: &App, cache_dir: &Path) {
|
||||
use bugreport::{bugreport, collector::*, format::Markdown};
|
||||
use bugreport::{bugreport, collector::*, format::Markdown, report::ReportEntry};
|
||||
|
||||
struct ColorSchemeCollector;
|
||||
|
||||
impl Collector for ColorSchemeCollector {
|
||||
fn description(&self) -> &str {
|
||||
"Detected terminal color scheme"
|
||||
}
|
||||
|
||||
fn collect(
|
||||
&mut self,
|
||||
_: &bugreport::CrateInfo,
|
||||
) -> std::result::Result<ReportEntry, CollectionError> {
|
||||
let color_scheme = bat::theme::color_scheme(bat::theme::DetectColorScheme::Always);
|
||||
let text = match color_scheme {
|
||||
Some(bat::theme::ColorScheme::Dark) => "dark",
|
||||
Some(bat::theme::ColorScheme::Light) => "light",
|
||||
None => "not detected",
|
||||
};
|
||||
Ok(ReportEntry::Text(text.to_string()))
|
||||
}
|
||||
}
|
||||
let pager = bat::config::get_pager_executable(
|
||||
app.matches.get_one::<String>("pager").map(|s| s.as_str()),
|
||||
)
|
||||
@@ -307,6 +328,9 @@ fn invoke_bugreport(app: &App, cache_dir: &Path) {
|
||||
"BAT_STYLE",
|
||||
"BAT_TABS",
|
||||
"BAT_THEME",
|
||||
"BAT_WIDTH",
|
||||
bat::theme::env::BAT_THEME_DARK,
|
||||
bat::theme::env::BAT_THEME_LIGHT,
|
||||
"COLORTERM",
|
||||
"LANG",
|
||||
"LC_ALL",
|
||||
@@ -326,6 +350,7 @@ fn invoke_bugreport(app: &App, cache_dir: &Path) {
|
||||
custom_assets_metadata,
|
||||
))
|
||||
.info(DirectoryEntries::new("Custom assets", cache_dir))
|
||||
.info(ColorSchemeCollector)
|
||||
.info(CompileTimeInformation::default());
|
||||
|
||||
#[cfg(feature = "paging")]
|
||||
|
||||
+72
-15
@@ -207,7 +207,7 @@ impl<'a> Input<'a> {
|
||||
kind: OpenedInputKind::StdIn,
|
||||
description,
|
||||
metadata: self.metadata,
|
||||
reader: InputReader::new(stdin),
|
||||
reader: InputReader::try_new(stdin)?,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -236,14 +236,14 @@ impl<'a> Input<'a> {
|
||||
file = input_identifier.into_inner().expect("The file was lost in the clircle::Identifier, this should not have happened...");
|
||||
}
|
||||
|
||||
InputReader::new(BufReader::new(file))
|
||||
InputReader::try_new(BufReader::new(file))?
|
||||
},
|
||||
}),
|
||||
InputKind::CustomReader(reader) => Ok(OpenedInput {
|
||||
description,
|
||||
kind: OpenedInputKind::CustomReader,
|
||||
metadata: self.metadata,
|
||||
reader: InputReader::new(BufReader::new(reader)),
|
||||
reader: InputReader::try_new(BufReader::new(reader))?,
|
||||
}),
|
||||
}
|
||||
}
|
||||
@@ -257,28 +257,29 @@ pub(crate) struct InputReader<'a> {
|
||||
}
|
||||
|
||||
impl<'a> InputReader<'a> {
|
||||
pub(crate) fn new<R: BufRead + 'a>(mut reader: R) -> InputReader<'a> {
|
||||
let mut first_line = vec![];
|
||||
reader.read_until(b'\n', &mut first_line).ok();
|
||||
#[cfg(test)]
|
||||
pub(crate) fn new<R: BufRead + 'a>(reader: R) -> InputReader<'a> {
|
||||
Self::try_new(reader).expect("reading the first line failed")
|
||||
}
|
||||
|
||||
let content_type = if first_line.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(content_inspector::inspect(&first_line[..]))
|
||||
};
|
||||
pub(crate) fn try_new<R: BufRead + 'a>(mut reader: R) -> io::Result<InputReader<'a>> {
|
||||
let mut first_line = vec![];
|
||||
reader.read_until(b'\n', &mut first_line)?;
|
||||
|
||||
let content_type = inspect_content_type(&first_line);
|
||||
|
||||
if content_type == Some(ContentType::UTF_16LE) {
|
||||
read_utf16_line(&mut reader, &mut first_line, 0x00, 0x0A).ok();
|
||||
read_utf16_line(&mut reader, &mut first_line, 0x00, 0x0A)?;
|
||||
} else if content_type == Some(ContentType::UTF_16BE) {
|
||||
read_utf16_line(&mut reader, &mut first_line, 0x0A, 0x00).ok();
|
||||
read_utf16_line(&mut reader, &mut first_line, 0x0A, 0x00)?;
|
||||
}
|
||||
|
||||
InputReader {
|
||||
Ok(InputReader {
|
||||
inner: Box::new(reader),
|
||||
first_line,
|
||||
content_type,
|
||||
unbuffered: false,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn read_line(&mut self, buf: &mut Vec<u8>) -> io::Result<bool> {
|
||||
@@ -319,6 +320,25 @@ impl<'a> InputReader<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn inspect_content_type(first_line: &[u8]) -> Option<ContentType> {
|
||||
if first_line.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
||||
let content_type = content_inspector::inspect(first_line);
|
||||
if content_type == ContentType::UTF_8 && has_zip_signature(first_line) {
|
||||
Some(ContentType::BINARY)
|
||||
} else {
|
||||
Some(content_type)
|
||||
}
|
||||
}
|
||||
|
||||
fn has_zip_signature(bytes: &[u8]) -> bool {
|
||||
[b"PK\x03\x04", b"PK\x05\x06", b"PK\x07\x08"]
|
||||
.into_iter()
|
||||
.any(|signature| bytes.starts_with(signature))
|
||||
}
|
||||
|
||||
fn read_utf16_line<R: BufRead>(
|
||||
reader: &mut R,
|
||||
buf: &mut Vec<u8>,
|
||||
@@ -374,6 +394,43 @@ fn basic() {
|
||||
assert!(buffer.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn zip_magic_headers_are_treated_as_binary() {
|
||||
for content in [b"PK\x03\x04hello", b"PK\x05\x06hello", b"PK\x07\x08hello"] {
|
||||
let reader = InputReader::new(&content[..]);
|
||||
assert_eq!(Some(ContentType::BINARY), reader.content_type);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn non_zip_pk_prefix_is_not_treated_as_binary() {
|
||||
assert_eq!(
|
||||
Some(ContentType::UTF_8),
|
||||
inspect_content_type(b"PK\x03\x03hello")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn input_open_returns_initial_read_errors() {
|
||||
struct FailingRead;
|
||||
|
||||
impl Read for FailingRead {
|
||||
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
|
||||
Err(io::Error::other("initial read failed"))
|
||||
}
|
||||
}
|
||||
|
||||
let input = Input::from_reader(Box::new(FailingRead));
|
||||
let result = input.open(io::empty(), None);
|
||||
|
||||
assert!(result.is_err());
|
||||
assert!(result
|
||||
.err()
|
||||
.unwrap()
|
||||
.to_string()
|
||||
.contains("initial read failed"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn utf16le() {
|
||||
let content = b"\xFF\xFE\x73\x00\x0A\x00\x64\x00";
|
||||
|
||||
+2
-2
@@ -155,7 +155,7 @@ impl LessOpenPreprocessor {
|
||||
|
||||
Ok(OpenedInput {
|
||||
kind,
|
||||
reader: InputReader::new(BufReader::new(
|
||||
reader: InputReader::try_new(BufReader::new(
|
||||
if matches!(self.kind, LessOpenKind::TempFile) {
|
||||
let lessopen_string = match String::from_utf8(lessopen_stdout) {
|
||||
Ok(string) => string,
|
||||
@@ -192,7 +192,7 @@ impl LessOpenPreprocessor {
|
||||
.map(|s| s.replacen("%s", &path_str, 1).replacen("%s", "-", 1)),
|
||||
}
|
||||
},
|
||||
)),
|
||||
))?,
|
||||
metadata: input.metadata,
|
||||
description: input.description,
|
||||
})
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
[mappings]
|
||||
"XML" = ["*.csproj", "*.vbproj", "*.props", "*.targets"]
|
||||
"XML" = ["*.csproj", "*.vbproj", "*.props", "*.targets", "*.slnx"]
|
||||
|
||||
Reference in New Issue
Block a user