mirror of
https://github.com/sharkdp/bat.git
synced 2025-09-29 00:22:26 +01:00
Merge branch 'master' into master
This commit is contained in:
@@ -152,7 +152,7 @@ impl HighlightingAssets {
|
||||
&self,
|
||||
path: impl AsRef<Path>,
|
||||
mapping: &SyntaxMapping,
|
||||
) -> Result<SyntaxReferenceInSet> {
|
||||
) -> Result<SyntaxReferenceInSet<'_>> {
|
||||
let path = path.as_ref();
|
||||
|
||||
let syntax_match = mapping.get_syntax_for(path);
|
||||
@@ -191,11 +191,11 @@ impl HighlightingAssets {
|
||||
Some(theme) => theme,
|
||||
None => {
|
||||
if theme == "ansi-light" || theme == "ansi-dark" {
|
||||
bat_warning!("Theme '{}' is deprecated, using 'ansi' instead.", theme);
|
||||
bat_warning!("Theme '{theme}' is deprecated, using 'ansi' instead.");
|
||||
return self.get_theme("ansi");
|
||||
}
|
||||
if !theme.is_empty() {
|
||||
bat_warning!("Unknown theme '{}', using default.", theme)
|
||||
bat_warning!("Unknown theme '{theme}', using default.")
|
||||
}
|
||||
self.get_theme_set()
|
||||
.get(
|
||||
@@ -212,7 +212,7 @@ impl HighlightingAssets {
|
||||
language: Option<&str>,
|
||||
input: &mut OpenedInput,
|
||||
mapping: &SyntaxMapping,
|
||||
) -> Result<SyntaxReferenceInSet> {
|
||||
) -> Result<SyntaxReferenceInSet<'_>> {
|
||||
if let Some(language) = language {
|
||||
let syntax_set = self.get_syntax_set()?;
|
||||
return syntax_set
|
||||
@@ -244,14 +244,17 @@ impl HighlightingAssets {
|
||||
pub(crate) fn find_syntax_by_name(
|
||||
&self,
|
||||
syntax_name: &str,
|
||||
) -> Result<Option<SyntaxReferenceInSet>> {
|
||||
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||
let syntax_set = self.get_syntax_set()?;
|
||||
Ok(syntax_set
|
||||
.find_syntax_by_name(syntax_name)
|
||||
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
||||
}
|
||||
|
||||
fn find_syntax_by_extension(&self, e: Option<&OsStr>) -> Result<Option<SyntaxReferenceInSet>> {
|
||||
fn find_syntax_by_extension(
|
||||
&self,
|
||||
e: Option<&OsStr>,
|
||||
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||
let syntax_set = self.get_syntax_set()?;
|
||||
let extension = e.and_then(|x| x.to_str()).unwrap_or_default();
|
||||
Ok(syntax_set
|
||||
@@ -259,7 +262,7 @@ impl HighlightingAssets {
|
||||
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
||||
}
|
||||
|
||||
fn find_syntax_by_token(&self, token: &str) -> Result<Option<SyntaxReferenceInSet>> {
|
||||
fn find_syntax_by_token(&self, token: &str) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||
let syntax_set = self.get_syntax_set()?;
|
||||
Ok(syntax_set
|
||||
.find_syntax_by_token(token)
|
||||
@@ -270,7 +273,7 @@ impl HighlightingAssets {
|
||||
&self,
|
||||
file_name: &OsStr,
|
||||
ignored_suffixes: &IgnoredSuffixes,
|
||||
) -> Result<Option<SyntaxReferenceInSet>> {
|
||||
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||
let mut syntax = self.find_syntax_by_extension(Some(file_name))?;
|
||||
if syntax.is_none() {
|
||||
syntax =
|
||||
@@ -286,7 +289,7 @@ impl HighlightingAssets {
|
||||
&self,
|
||||
file_name: &OsStr,
|
||||
ignored_suffixes: &IgnoredSuffixes,
|
||||
) -> Result<Option<SyntaxReferenceInSet>> {
|
||||
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||
let mut syntax = self.find_syntax_by_extension(Path::new(file_name).extension())?;
|
||||
if syntax.is_none() {
|
||||
syntax =
|
||||
@@ -301,7 +304,7 @@ impl HighlightingAssets {
|
||||
fn get_first_line_syntax(
|
||||
&self,
|
||||
reader: &mut InputReader,
|
||||
) -> Result<Option<SyntaxReferenceInSet>> {
|
||||
) -> Result<Option<SyntaxReferenceInSet<'_>>> {
|
||||
let syntax_set = self.get_syntax_set()?;
|
||||
Ok(String::from_utf8(reader.first_line.clone())
|
||||
.ok()
|
||||
@@ -354,8 +357,7 @@ fn asset_from_cache<T: serde::de::DeserializeOwned>(
|
||||
) -> Result<T> {
|
||||
let contents = fs::read(path).map_err(|_| {
|
||||
format!(
|
||||
"Could not load cached {} '{}'",
|
||||
description,
|
||||
"Could not load cached {description} '{}'",
|
||||
path.to_string_lossy()
|
||||
)
|
||||
})?;
|
||||
|
@@ -40,15 +40,15 @@ impl AssetsMetadata {
|
||||
/// Load metadata about the stored cache file from the given folder.
|
||||
///
|
||||
/// There are several possibilities:
|
||||
/// - We find a metadata.yaml file and are able to parse it
|
||||
/// => return the contained information
|
||||
/// - We find a metadata.yaml file and but are not able to parse it
|
||||
/// => return a SerdeYamlError
|
||||
/// - We do not find a metadata.yaml file but a syntaxes.bin or themes.bin file
|
||||
/// => assume that these were created by an old version of bat and return
|
||||
/// AssetsMetadata::default() without version information
|
||||
/// - We do not find a metadata.yaml file and no cached assets
|
||||
/// => no user provided assets are available, return None
|
||||
/// - We find a `metadata.yaml` file and are able to parse it
|
||||
/// - return the contained information
|
||||
/// - We find a `metadata.yaml` file, but are not able to parse it
|
||||
/// - return a [`Error::SerdeYamlError`]
|
||||
/// - We do not find a `metadata.yaml` file but a `syntaxes.bin` or `themes.bin` file
|
||||
/// - assume that these were created by an old version of bat and return
|
||||
/// [`AssetsMetadata::default()`] without version information
|
||||
/// - We do not find a `metadata.yaml` file and no cached assets
|
||||
/// - no user provided assets are available, return `None`
|
||||
pub fn load_from_folder(path: &Path) -> Result<Option<Self>> {
|
||||
match Self::try_load_from_folder(path) {
|
||||
Ok(metadata) => Ok(Some(metadata)),
|
||||
|
@@ -47,9 +47,8 @@ fn build_theme_set(source_dir: &Path, include_integrated_assets: bool) -> Result
|
||||
let res = theme_set.add_from_folder(&theme_dir);
|
||||
if let Err(err) = res {
|
||||
println!(
|
||||
"Failed to load one or more themes from '{}' (reason: '{}')",
|
||||
"Failed to load one or more themes from '{}' (reason: '{err}')",
|
||||
theme_dir.to_string_lossy(),
|
||||
err,
|
||||
);
|
||||
}
|
||||
} else {
|
||||
@@ -162,15 +161,10 @@ fn asset_to_cache<T: serde::Serialize>(
|
||||
description: &str,
|
||||
compressed: bool,
|
||||
) -> Result<()> {
|
||||
print!("Writing {} to {} ... ", description, path.to_string_lossy());
|
||||
print!("Writing {description} to {} ... ", path.to_string_lossy());
|
||||
let contents = asset_to_contents(asset, description, compressed)?;
|
||||
std::fs::write(path, &contents[..]).map_err(|_| {
|
||||
format!(
|
||||
"Could not save {} to {}",
|
||||
description,
|
||||
path.to_string_lossy()
|
||||
)
|
||||
})?;
|
||||
std::fs::write(path, &contents[..])
|
||||
.map_err(|_| format!("Could not save {description} to {}", path.to_string_lossy()))?;
|
||||
println!("okay");
|
||||
Ok(())
|
||||
}
|
||||
|
@@ -96,7 +96,7 @@ impl App {
|
||||
Ok(clap_app::build_app(interactive_output).get_matches_from(args))
|
||||
}
|
||||
|
||||
pub fn config(&self, inputs: &[Input]) -> Result<Config> {
|
||||
pub fn config(&self, inputs: &[Input]) -> Result<Config<'_>> {
|
||||
let style_components = self.style_components()?;
|
||||
|
||||
let extra_plain = self.matches.get_count("plain") > 1;
|
||||
@@ -338,7 +338,7 @@ impl App {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn inputs(&self) -> Result<Vec<Input>> {
|
||||
pub fn inputs(&self) -> Result<Vec<Input<'_>>> {
|
||||
let filenames: Option<Vec<&Path>> = self
|
||||
.matches
|
||||
.get_many::<PathBuf>("file-name")
|
||||
|
@@ -50,7 +50,7 @@ fn clear_asset(path: PathBuf, description: &str) {
|
||||
println!("skipped (not present)");
|
||||
}
|
||||
Err(err) => {
|
||||
println!("could not remove the cache file {:?}: {}", &path, err);
|
||||
println!("could not remove the cache file {path:?}: {err}");
|
||||
}
|
||||
Ok(_) => println!("okay"),
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ static VERSION: Lazy<String> = Lazy::new(|| {
|
||||
if git_version.is_empty() {
|
||||
crate_version!().to_string()
|
||||
} else {
|
||||
format!("{} ({})", crate_version!(), git_version)
|
||||
format!("{} ({git_version})", crate_version!())
|
||||
}
|
||||
});
|
||||
|
||||
|
@@ -88,9 +88,8 @@ pub fn generate_config_file() -> bat::error::Result<()> {
|
||||
|
||||
fs::write(&config_file, default_config).map_err(|e| {
|
||||
format!(
|
||||
"Failed to create config file at '{}': {}",
|
||||
"Failed to create config file at '{}': {e}",
|
||||
config_file.to_string_lossy(),
|
||||
e
|
||||
)
|
||||
})?;
|
||||
|
||||
|
@@ -5,7 +5,7 @@ pub fn new_file_input<'a>(file: &'a Path, name: Option<&'a Path>) -> Input<'a> {
|
||||
named(Input::ordinary_file(file), name.or(Some(file)))
|
||||
}
|
||||
|
||||
pub fn new_stdin_input(name: Option<&Path>) -> Input {
|
||||
pub fn new_stdin_input(name: Option<&Path>) -> Input<'_> {
|
||||
named(Input::stdin(), name)
|
||||
}
|
||||
|
||||
|
@@ -162,7 +162,7 @@ pub fn get_languages(config: &Config, cache_dir: &Path) -> Result<String> {
|
||||
};
|
||||
|
||||
for lang in languages {
|
||||
write!(result, "{:width$}{}", lang.name, separator, width = longest).ok();
|
||||
write!(result, "{:width$}{separator}", lang.name, width = longest).ok();
|
||||
|
||||
// Number of characters on this line so far, wrap before `desired_width`
|
||||
let mut num_chars = 0;
|
||||
@@ -173,7 +173,7 @@ pub fn get_languages(config: &Config, cache_dir: &Path) -> Result<String> {
|
||||
let new_chars = word.len() + comma_separator.len();
|
||||
if num_chars + new_chars >= desired_width {
|
||||
num_chars = 0;
|
||||
write!(result, "\n{:width$}{}", "", separator, width = longest).ok();
|
||||
write!(result, "\n{:width$}{separator}", "", width = longest).ok();
|
||||
}
|
||||
|
||||
num_chars += new_chars;
|
||||
@@ -224,9 +224,8 @@ pub fn list_themes(
|
||||
if config.colored_output {
|
||||
writeln!(
|
||||
writer,
|
||||
"Theme: {}{}\n",
|
||||
"Theme: {}{default_theme_info}\n",
|
||||
Style::new().bold().paint(theme.to_string()),
|
||||
default_theme_info
|
||||
)?;
|
||||
config.theme = theme.to_string();
|
||||
Controller::new(&config, &assets)
|
||||
@@ -363,7 +362,7 @@ fn run() -> Result<bool> {
|
||||
"fish" => println!("{}", completions::FISH_COMPLETION),
|
||||
"ps1" => println!("{}", completions::PS1_COMPLETION),
|
||||
"zsh" => println!("{}", completions::ZSH_COMPLETION),
|
||||
_ => unreachable!("No completion for shell '{}' available.", shell),
|
||||
_ => unreachable!("No completion for shell '{shell}' available."),
|
||||
}
|
||||
return Ok(true);
|
||||
}
|
||||
|
@@ -60,18 +60,16 @@ pub fn default_error_handler(error: &Error, output: &mut dyn Write) {
|
||||
Error::SerdeYamlError(_) => {
|
||||
writeln!(
|
||||
output,
|
||||
"{}: Error while parsing metadata.yaml file: {}",
|
||||
"{}: Error while parsing metadata.yaml file: {error}",
|
||||
Red.paint("[bat error]"),
|
||||
error
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
_ => {
|
||||
writeln!(
|
||||
&mut std::io::stderr().lock(),
|
||||
"{}: {}",
|
||||
"{}: {error}",
|
||||
Red.paint("[bat error]"),
|
||||
error
|
||||
)
|
||||
.ok();
|
||||
}
|
||||
|
92
src/input.rs
92
src/input.rs
@@ -217,14 +217,14 @@ impl<'a> Input<'a> {
|
||||
metadata: self.metadata,
|
||||
reader: {
|
||||
let mut file = File::open(&path)
|
||||
.map_err(|e| format!("'{}': {}", path.to_string_lossy(), e))?;
|
||||
.map_err(|e| format!("'{}': {e}", path.to_string_lossy()))?;
|
||||
if file.metadata()?.is_dir() {
|
||||
return Err(format!("'{}' is a directory.", path.to_string_lossy()).into());
|
||||
}
|
||||
|
||||
if let Some(stdout) = stdout_identifier {
|
||||
let input_identifier = Identifier::try_from(file).map_err(|e| {
|
||||
format!("{}: Error identifying file: {}", path.to_string_lossy(), e)
|
||||
format!("{}: Error identifying file: {e}", path.to_string_lossy())
|
||||
})?;
|
||||
if stdout.surely_conflicts_with(&input_identifier) {
|
||||
return Err(format!(
|
||||
@@ -267,7 +267,9 @@ impl<'a> InputReader<'a> {
|
||||
};
|
||||
|
||||
if content_type == Some(ContentType::UTF_16LE) {
|
||||
reader.read_until(0x00, &mut first_line).ok();
|
||||
read_utf16_line(&mut reader, &mut first_line, 0x00, 0x0A).ok();
|
||||
} else if content_type == Some(ContentType::UTF_16BE) {
|
||||
read_utf16_line(&mut reader, &mut first_line, 0x0A, 0x00).ok();
|
||||
}
|
||||
|
||||
InputReader {
|
||||
@@ -283,16 +285,44 @@ impl<'a> InputReader<'a> {
|
||||
return Ok(true);
|
||||
}
|
||||
|
||||
let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
|
||||
|
||||
if self.content_type == Some(ContentType::UTF_16LE) {
|
||||
let _ = self.inner.read_until(0x00, buf);
|
||||
return read_utf16_line(&mut self.inner, buf, 0x00, 0x0A);
|
||||
}
|
||||
if self.content_type == Some(ContentType::UTF_16BE) {
|
||||
return read_utf16_line(&mut self.inner, buf, 0x0A, 0x00);
|
||||
}
|
||||
|
||||
let res = self.inner.read_until(b'\n', buf).map(|size| size > 0)?;
|
||||
Ok(res)
|
||||
}
|
||||
}
|
||||
|
||||
fn read_utf16_line<R: BufRead>(
|
||||
reader: &mut R,
|
||||
buf: &mut Vec<u8>,
|
||||
read_until_char: u8,
|
||||
preceded_by_char: u8,
|
||||
) -> io::Result<bool> {
|
||||
loop {
|
||||
let mut temp = Vec::new();
|
||||
let n = reader.read_until(read_until_char, &mut temp)?;
|
||||
if n == 0 {
|
||||
// EOF reached
|
||||
break;
|
||||
}
|
||||
buf.extend_from_slice(&temp);
|
||||
if buf.len() >= 2
|
||||
&& buf[buf.len() - 2] == preceded_by_char
|
||||
&& buf[buf.len() - 1] == read_until_char
|
||||
{
|
||||
// end of line found
|
||||
break;
|
||||
}
|
||||
// end of line not found, keep going
|
||||
}
|
||||
Ok(!buf.is_empty())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn basic() {
|
||||
let content = b"#!/bin/bash\necho hello";
|
||||
@@ -350,3 +380,53 @@ fn utf16le() {
|
||||
assert!(!res.unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn utf16le_issue3367() {
|
||||
let content = b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00\
|
||||
\x6F\x00\x20\x00\x62\x00\x61\x00\x72\x00\x0A\x00\
|
||||
\x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00\x20\x00\x77\x00\x6F\x00\x72\x00\x6C\x00\x64\x00";
|
||||
let mut reader = InputReader::new(&content[..]);
|
||||
|
||||
assert_eq!(
|
||||
b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00",
|
||||
&reader.first_line[..]
|
||||
);
|
||||
|
||||
let mut buffer = vec![];
|
||||
|
||||
let res = reader.read_line(&mut buffer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap());
|
||||
assert_eq!(
|
||||
b"\xFF\xFE\x0A\x4E\x00\x4E\x0A\x4F\x00\x52\x0A\x00",
|
||||
&buffer[..]
|
||||
);
|
||||
|
||||
buffer.clear();
|
||||
|
||||
let res = reader.read_line(&mut buffer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap());
|
||||
assert_eq!(
|
||||
b"\x6F\x00\x20\x00\x62\x00\x61\x00\x72\x00\x0A\x00",
|
||||
&buffer[..]
|
||||
);
|
||||
|
||||
buffer.clear();
|
||||
|
||||
let res = reader.read_line(&mut buffer);
|
||||
assert!(res.is_ok());
|
||||
assert!(res.unwrap());
|
||||
assert_eq!(
|
||||
b"\x68\x00\x65\x00\x6C\x00\x6C\x00\x6F\x00\x20\x00\x77\x00\x6F\x00\x72\x00\x6C\x00\x64\x00",
|
||||
&buffer[..]
|
||||
);
|
||||
|
||||
buffer.clear();
|
||||
|
||||
let res = reader.read_line(&mut buffer);
|
||||
assert!(res.is_ok());
|
||||
assert!(!res.unwrap());
|
||||
assert!(buffer.is_empty());
|
||||
}
|
||||
|
@@ -39,7 +39,7 @@ impl LessOpenPreprocessor {
|
||||
// Note that $LESSCLOSE has no such requirement
|
||||
if lessopen.match_indices("%s").count() != 1 {
|
||||
let error_msg = "LESSOPEN ignored: must contain exactly one %s";
|
||||
bat_warning!("{}", error_msg);
|
||||
bat_warning!("{error_msg}");
|
||||
return Err(error_msg.into());
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ impl LessOpenPreprocessor {
|
||||
if self.preprocess_stdin {
|
||||
if let Some(stdout) = stdout_identifier {
|
||||
let input_identifier = Identifier::try_from(clircle::Stdio::Stdin)
|
||||
.map_err(|e| format!("Stdin: Error identifying file: {}", e))?;
|
||||
.map_err(|e| format!("Stdin: Error identifying file: {e}"))?;
|
||||
if stdout.surely_conflicts_with(&input_identifier) {
|
||||
return Err("IO circle detected. The input from stdin is also an output. Aborting to avoid infinite loop.".into());
|
||||
}
|
||||
|
@@ -329,7 +329,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
self.print_horizontal_line_term(handle, self.colors.grid)?;
|
||||
} else {
|
||||
let hline = "─".repeat(self.config.term_width - (self.panel_width + 1));
|
||||
let hline = format!("{}{}{}", "─".repeat(self.panel_width), grid_char, hline);
|
||||
let hline = format!("{}{grid_char}{hline}", "─".repeat(self.panel_width));
|
||||
writeln!(handle, "{}", self.colors.grid.paint(hline))?;
|
||||
}
|
||||
|
||||
@@ -343,8 +343,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
|
||||
let text_truncated: String = text.chars().take(self.panel_width - 1).collect();
|
||||
let text_filled: String = format!(
|
||||
"{}{}",
|
||||
text_truncated,
|
||||
"{text_truncated}{}",
|
||||
" ".repeat(self.panel_width - 1 - text_truncated.len())
|
||||
);
|
||||
if self.config.style_components.grid() {
|
||||
@@ -400,7 +399,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||
while content_graphemes.len() > content_width {
|
||||
let (content_line, remaining) = content_graphemes.split_at(content_width);
|
||||
self.print_header_component_with_indent(handle, content_line.join("").as_str())?;
|
||||
content_graphemes = remaining.iter().cloned().collect();
|
||||
content_graphemes = remaining.to_vec();
|
||||
}
|
||||
self.print_header_component_with_indent(handle, content_graphemes.join("").as_str())
|
||||
}
|
||||
@@ -513,13 +512,12 @@ impl Printer for InteractivePrinter<'_> {
|
||||
.try_for_each(|component| match component {
|
||||
StyleComponent::HeaderFilename => {
|
||||
let header_filename = format!(
|
||||
"{}{}{}",
|
||||
"{}{}{mode}",
|
||||
description
|
||||
.kind()
|
||||
.map(|kind| format!("{kind}: "))
|
||||
.unwrap_or_else(|| "".into()),
|
||||
self.colors.header_value.paint(description.title()),
|
||||
mode
|
||||
);
|
||||
self.print_header_multiline_component(handle, &header_filename)
|
||||
}
|
||||
@@ -701,7 +699,7 @@ impl Printer for InteractivePrinter<'_> {
|
||||
"{}{}",
|
||||
as_terminal_escaped(
|
||||
style,
|
||||
&format!("{}{}", self.ansi_style, text_trimmed),
|
||||
&format!("{}{text_trimmed}", self.ansi_style),
|
||||
true_color,
|
||||
colored_output,
|
||||
italics,
|
||||
@@ -791,7 +789,7 @@ impl Printer for InteractivePrinter<'_> {
|
||||
"{}{}\n{}",
|
||||
as_terminal_escaped(
|
||||
style,
|
||||
&format!("{}{}", self.ansi_style, line_buf),
|
||||
&format!("{}{line_buf}", self.ansi_style),
|
||||
self.config.true_color,
|
||||
self.config.colored_output,
|
||||
self.config.use_italic_text,
|
||||
@@ -818,7 +816,7 @@ impl Printer for InteractivePrinter<'_> {
|
||||
"{}",
|
||||
as_terminal_escaped(
|
||||
style,
|
||||
&format!("{}{}", self.ansi_style, line_buf),
|
||||
&format!("{}{line_buf}", self.ansi_style),
|
||||
self.config.true_color,
|
||||
self.config.colored_output,
|
||||
self.config.use_italic_text,
|
||||
|
@@ -212,15 +212,15 @@ impl Attributes {
|
||||
}
|
||||
|
||||
fn update_with_charset(&mut self, kind: char, set: impl Iterator<Item = char>) -> bool {
|
||||
self.charset = format!("\x1B{}{}", kind, set.take(1).collect::<String>());
|
||||
self.charset = format!("\x1B{kind}{}", set.take(1).collect::<String>());
|
||||
true
|
||||
}
|
||||
|
||||
fn parse_color(color: u16, parameters: &mut dyn Iterator<Item = u16>) -> 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(5) /* 256-color */ => format!("\x1B[{color};5;{}m", join(";", 1, parameters)),
|
||||
Some(2) /* 24-bit color */ => format!("\x1B[{color};2;{}m", join(";", 3, parameters)),
|
||||
Some(c) => format!("\x1B[{color};{c}m"),
|
||||
_ => "".to_owned(),
|
||||
},
|
||||
|
Reference in New Issue
Block a user