Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@

## `bat` as a library

- Deprecate `HighlightingAssets::syntaxes()` and `HighlightingAssets::syntax_for_file_name()`. Use `HighlightingAssets::get_syntaxes()` and `HighlightingAssets::get_syntax_for_file_name()` instead. They return a `Result` which is needed for upcoming lazy-loading work to improve startup performance. See #1747 and #1755 (@Enselic)
- Deprecate `HighlightingAssets::syntaxes()` and `HighlightingAssets::syntax_for_file_name()`. Use `HighlightingAssets::get_syntaxes()` and `HighlightingAssets::get_syntax_for_file_name()` instead. They return a `Result` which is needed for upcoming lazy-loading work to improve startup performance. They also return what `SyntaxSet` the returned `SyntaxReference` belongs to. See #1747, #1755 and #1776 (@Enselic)



Expand Down
84 changes: 52 additions & 32 deletions src/assets.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,12 @@ pub struct HighlightingAssets {
fallback_theme: Option<&'static str>,
}

#[derive(Debug)]
pub struct SyntaxReferenceInSet<'a> {
pub syntax: &'a SyntaxReference,
pub syntax_set: &'a SyntaxSet,
}

const IGNORED_SUFFIXES: [&str; 10] = [
// Editor etc backups
"~",
Expand Down Expand Up @@ -120,11 +126,7 @@ impl HighlightingAssets {
}
}

Ok(HighlightingAssets::new(
Some(syntax_set),
None,
theme_set,
))
Ok(HighlightingAssets::new(Some(syntax_set), None, theme_set))
}

pub fn from_cache(cache_path: &Path) -> Result<Self> {
Expand Down Expand Up @@ -215,21 +217,26 @@ impl HighlightingAssets {
file_name: impl AsRef<Path>,
mapping: &SyntaxMapping,
) -> Option<&SyntaxReference> {
self.get_syntax_for_file_name(file_name, mapping).expect(
".syntax_for_file_name() is deprecated, use .get_syntax_for_file_name() instead",
)
self.get_syntax_for_file_name(file_name, mapping)
.expect(
".syntax_for_file_name() is deprecated, use .get_syntax_for_file_name() instead",
)
.map(|syntax_in_set| syntax_in_set.syntax)
}

pub fn get_syntax_for_file_name(
&self,
file_name: impl AsRef<Path>,
mapping: &SyntaxMapping,
) -> Result<Option<&SyntaxReference>> {
) -> Result<Option<SyntaxReferenceInSet>> {
let file_name = file_name.as_ref();
Ok(match mapping.get_syntax_for(file_name) {
Some(MappingTarget::MapToUnknown) => None,
Some(MappingTarget::MapTo(syntax_name)) => {
self.get_syntax_set()?.find_syntax_by_name(syntax_name)
let syntax_set = self.get_syntax_set()?;
syntax_set
.find_syntax_by_name(syntax_name)
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })
}
None => self.get_extension_syntax(file_name.as_os_str())?,
})
Expand Down Expand Up @@ -257,10 +264,12 @@ impl HighlightingAssets {
language: Option<&str>,
input: &mut OpenedInput,
mapping: &SyntaxMapping,
) -> Result<&SyntaxReference> {
) -> Result<SyntaxReferenceInSet> {
if let Some(language) = language {
self.get_syntax_set()?
let syntax_set = self.get_syntax_set()?;
syntax_set
.find_syntax_by_token(language)
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })
.ok_or_else(|| ErrorKind::UnknownSyntax(language.to_owned()).into())
} else {
let line_syntax = self.get_first_line_syntax(&mut input.reader)?;
Expand Down Expand Up @@ -291,10 +300,13 @@ impl HighlightingAssets {
ErrorKind::UndetectedSyntax(path.to_string_lossy().into()).into()
}),

Some(MappingTarget::MapTo(syntax_name)) => self
.get_syntax_set()?
.find_syntax_by_name(syntax_name)
.ok_or_else(|| ErrorKind::UnknownSyntax(syntax_name.to_owned()).into()),
Some(MappingTarget::MapTo(syntax_name)) => {
let syntax_set = self.get_syntax_set()?;
syntax_set
.find_syntax_by_name(syntax_name)
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })
.ok_or_else(|| ErrorKind::UnknownSyntax(syntax_name.to_owned()).into())
}

None => {
let file_name = path.file_name().unwrap_or_default();
Expand All @@ -312,7 +324,7 @@ impl HighlightingAssets {
}
}

fn get_extension_syntax(&self, file_name: &OsStr) -> Result<Option<&SyntaxReference>> {
fn get_extension_syntax(&self, file_name: &OsStr) -> Result<Option<SyntaxReferenceInSet>> {
let mut syntax = self.find_syntax_by_file_name(file_name)?;
if syntax.is_none() {
syntax = self.find_syntax_by_file_name_extension(file_name)?;
Expand All @@ -323,31 +335,35 @@ impl HighlightingAssets {
Ok(syntax)
}

fn find_syntax_by_file_name(&self, file_name: &OsStr) -> Result<Option<&SyntaxReference>> {
Ok(self
.get_syntax_set()?
.find_syntax_by_extension(file_name.to_str().unwrap_or_default()))
fn find_syntax_by_file_name(&self, file_name: &OsStr) -> Result<Option<SyntaxReferenceInSet>> {
let syntax_set = self.get_syntax_set()?;
Ok(syntax_set
.find_syntax_by_extension(file_name.to_str().unwrap_or_default())
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
}

fn find_syntax_by_file_name_extension(
&self,
file_name: &OsStr,
) -> Result<Option<&SyntaxReference>> {
) -> Result<Option<SyntaxReferenceInSet>> {
let file_path = Path::new(file_name);
Ok(self.get_syntax_set()?.find_syntax_by_extension(
file_path
.extension()
.and_then(|x| x.to_str())
.unwrap_or_default(),
))
let syntax_set = self.get_syntax_set()?;
Ok(syntax_set
.find_syntax_by_extension(
file_path
.extension()
.and_then(|x| x.to_str())
.unwrap_or_default(),
)
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
}

/// If we find an ignored suffix on the file name, e.g. '~', we strip it and
/// then try again to find a syntax without it. Note that we do this recursively.
fn get_extension_syntax_with_stripped_suffix(
&self,
file_name: &OsStr,
) -> Result<Option<&SyntaxReference>> {
) -> Result<Option<SyntaxReferenceInSet>> {
let file_path = Path::new(file_name);
let mut syntax = None;
if let Some(file_str) = file_path.to_str() {
Expand All @@ -361,11 +377,15 @@ impl HighlightingAssets {
Ok(syntax)
}

fn get_first_line_syntax(&self, reader: &mut InputReader) -> Result<Option<&SyntaxReference>> {
fn get_first_line_syntax(
&self,
reader: &mut InputReader,
) -> Result<Option<SyntaxReferenceInSet>> {
let syntax_set = self.get_syntax_set()?;
Ok(String::from_utf8(reader.first_line.clone())
.ok()
.and_then(|l| syntax_set.find_syntax_by_first_line(&l)))
.and_then(|l| syntax_set.find_syntax_by_first_line(&l))
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
}
}

Expand Down Expand Up @@ -460,7 +480,7 @@ mod tests {
) -> String {
self.assets
.get_syntax(language, input, mapping)
.map(|syntax| syntax.name.clone())
.map(|syntax_in_set| syntax_in_set.syntax.name.clone())
.unwrap_or_else(|_| "!no syntax!".to_owned())
}

Expand Down
6 changes: 3 additions & 3 deletions src/bin/bat/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,11 +101,11 @@ pub fn get_languages(config: &Config) -> Result<String> {
true
} else {
let test_file = Path::new("test").with_extension(extension);
let syntax = assets
let syntax_in_set = assets
.get_syntax_for_file_name(test_file, &config.syntax_mapping)
.unwrap(); // safe since .get_syntaxes() above worked
match syntax {
Some(syntax) => syntax.name == lang_name,
match syntax_in_set {
Some(syntax_in_set) => syntax_in_set.syntax.name == lang_name,
None => false,
}
}
Expand Down
30 changes: 18 additions & 12 deletions src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ use encoding::{DecoderTrap, Encoding};

use unicode_width::UnicodeWidthChar;

use crate::assets::HighlightingAssets;
use crate::assets::{HighlightingAssets, SyntaxReferenceInSet};
use crate::config::Config;
#[cfg(feature = "git")]
use crate::decorations::LineChangesDecoration;
Expand Down Expand Up @@ -163,23 +163,29 @@ impl<'a> InteractivePrinter<'a> {
panel_width = 0;
}

let highlighter = if input
let (highlighter, syntax_set) = if input
.reader
.content_type
.map_or(false, |c| c.is_binary() && !config.show_nonprintable)
{
None
(None, assets.get_syntax_set()?)
} else {
// Determine the type of syntax for highlighting
let syntax = match assets.get_syntax(config.language, input, &config.syntax_mapping) {
Ok(syntax) => syntax,
Err(Error(ErrorKind::UndetectedSyntax(_), _)) => {
assets.get_syntax_set()?.find_syntax_plain_text()
}
Err(e) => return Err(e),
};
let syntax_in_set =
match assets.get_syntax(config.language, input, &config.syntax_mapping) {
Ok(syntax_in_set) => syntax_in_set,
Err(Error(ErrorKind::UndetectedSyntax(_), _)) => {
let syntax_set = assets.get_syntax_set()?;
let syntax = syntax_set.find_syntax_plain_text();
SyntaxReferenceInSet { syntax, syntax_set }
}
Err(e) => return Err(e),
};

Some(HighlightLines::new(syntax, theme))
(
Some(HighlightLines::new(syntax_in_set.syntax, theme)),
syntax_in_set.syntax_set,
)
};

Ok(InteractivePrinter {
Expand All @@ -192,7 +198,7 @@ impl<'a> InteractivePrinter<'a> {
#[cfg(feature = "git")]
line_changes,
highlighter,
syntax_set: assets.get_syntax_set()?,
syntax_set,
background_color_highlight,
})
}
Expand Down