mirror of
https://github.com/sharkdp/bat
synced 2024-11-15 08:37:12 +00:00
When returning a SyntaxReference, also return the SyntaxSet that contains it (#1776)
To improve startup performance, we will later load smaller `SyntaxSet`s instead of one giant one. However, the current API assumes only one `SyntaxSet` is ever used, and that that implicitly is the `SyntaxSet` from which returned `SyntaxReference`s comes. This change changes the API to reflect that `SyntaxSet` and `SyntaxReference` are tightly coupled, and enables the use of several `SyntaxSet`.
This commit is contained in:
parent
5236ed135e
commit
d8b813c0bf
4 changed files with 73 additions and 43 deletions
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
## `bat` as a library
|
## `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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,6 +25,12 @@ pub struct HighlightingAssets {
|
||||||
fallback_theme: Option<&'static str>,
|
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] = [
|
const IGNORED_SUFFIXES: [&str; 10] = [
|
||||||
// Editor etc backups
|
// Editor etc backups
|
||||||
"~",
|
"~",
|
||||||
|
@ -217,21 +223,26 @@ impl HighlightingAssets {
|
||||||
file_name: impl AsRef<Path>,
|
file_name: impl AsRef<Path>,
|
||||||
mapping: &SyntaxMapping,
|
mapping: &SyntaxMapping,
|
||||||
) -> Option<&SyntaxReference> {
|
) -> Option<&SyntaxReference> {
|
||||||
self.get_syntax_for_file_name(file_name, mapping).expect(
|
self.get_syntax_for_file_name(file_name, mapping)
|
||||||
|
.expect(
|
||||||
".syntax_for_file_name() is deprecated, use .get_syntax_for_file_name() instead",
|
".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(
|
pub fn get_syntax_for_file_name(
|
||||||
&self,
|
&self,
|
||||||
file_name: impl AsRef<Path>,
|
file_name: impl AsRef<Path>,
|
||||||
mapping: &SyntaxMapping,
|
mapping: &SyntaxMapping,
|
||||||
) -> Result<Option<&SyntaxReference>> {
|
) -> Result<Option<SyntaxReferenceInSet>> {
|
||||||
let file_name = file_name.as_ref();
|
let file_name = file_name.as_ref();
|
||||||
Ok(match mapping.get_syntax_for(file_name) {
|
Ok(match mapping.get_syntax_for(file_name) {
|
||||||
Some(MappingTarget::MapToUnknown) => None,
|
Some(MappingTarget::MapToUnknown) => None,
|
||||||
Some(MappingTarget::MapTo(syntax_name)) => {
|
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())?,
|
None => self.get_extension_syntax(file_name.as_os_str())?,
|
||||||
})
|
})
|
||||||
|
@ -259,10 +270,12 @@ impl HighlightingAssets {
|
||||||
language: Option<&str>,
|
language: Option<&str>,
|
||||||
input: &mut OpenedInput,
|
input: &mut OpenedInput,
|
||||||
mapping: &SyntaxMapping,
|
mapping: &SyntaxMapping,
|
||||||
) -> Result<&SyntaxReference> {
|
) -> Result<SyntaxReferenceInSet> {
|
||||||
if let Some(language) = language {
|
if let Some(language) = language {
|
||||||
self.get_syntax_set()?
|
let syntax_set = self.get_syntax_set()?;
|
||||||
|
syntax_set
|
||||||
.find_syntax_by_token(language)
|
.find_syntax_by_token(language)
|
||||||
|
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })
|
||||||
.ok_or_else(|| ErrorKind::UnknownSyntax(language.to_owned()).into())
|
.ok_or_else(|| ErrorKind::UnknownSyntax(language.to_owned()).into())
|
||||||
} else {
|
} else {
|
||||||
let line_syntax = self.get_first_line_syntax(&mut input.reader)?;
|
let line_syntax = self.get_first_line_syntax(&mut input.reader)?;
|
||||||
|
@ -293,10 +306,13 @@ impl HighlightingAssets {
|
||||||
ErrorKind::UndetectedSyntax(path.to_string_lossy().into()).into()
|
ErrorKind::UndetectedSyntax(path.to_string_lossy().into()).into()
|
||||||
}),
|
}),
|
||||||
|
|
||||||
Some(MappingTarget::MapTo(syntax_name)) => self
|
Some(MappingTarget::MapTo(syntax_name)) => {
|
||||||
.get_syntax_set()?
|
let syntax_set = self.get_syntax_set()?;
|
||||||
|
syntax_set
|
||||||
.find_syntax_by_name(syntax_name)
|
.find_syntax_by_name(syntax_name)
|
||||||
.ok_or_else(|| ErrorKind::UnknownSyntax(syntax_name.to_owned()).into()),
|
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set })
|
||||||
|
.ok_or_else(|| ErrorKind::UnknownSyntax(syntax_name.to_owned()).into())
|
||||||
|
}
|
||||||
|
|
||||||
None => {
|
None => {
|
||||||
let file_name = path.file_name().unwrap_or_default();
|
let file_name = path.file_name().unwrap_or_default();
|
||||||
|
@ -314,7 +330,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)?;
|
let mut syntax = self.find_syntax_by_file_name(file_name)?;
|
||||||
if syntax.is_none() {
|
if syntax.is_none() {
|
||||||
syntax = self.find_syntax_by_file_name_extension(file_name)?;
|
syntax = self.find_syntax_by_file_name_extension(file_name)?;
|
||||||
|
@ -325,23 +341,27 @@ impl HighlightingAssets {
|
||||||
Ok(syntax)
|
Ok(syntax)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_syntax_by_file_name(&self, file_name: &OsStr) -> Result<Option<&SyntaxReference>> {
|
fn find_syntax_by_file_name(&self, file_name: &OsStr) -> Result<Option<SyntaxReferenceInSet>> {
|
||||||
Ok(self
|
let syntax_set = self.get_syntax_set()?;
|
||||||
.get_syntax_set()?
|
Ok(syntax_set
|
||||||
.find_syntax_by_extension(file_name.to_str().unwrap_or_default()))
|
.find_syntax_by_extension(file_name.to_str().unwrap_or_default())
|
||||||
|
.map(|syntax| SyntaxReferenceInSet { syntax, syntax_set }))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn find_syntax_by_file_name_extension(
|
fn find_syntax_by_file_name_extension(
|
||||||
&self,
|
&self,
|
||||||
file_name: &OsStr,
|
file_name: &OsStr,
|
||||||
) -> Result<Option<&SyntaxReference>> {
|
) -> Result<Option<SyntaxReferenceInSet>> {
|
||||||
let file_path = Path::new(file_name);
|
let file_path = Path::new(file_name);
|
||||||
Ok(self.get_syntax_set()?.find_syntax_by_extension(
|
let syntax_set = self.get_syntax_set()?;
|
||||||
|
Ok(syntax_set
|
||||||
|
.find_syntax_by_extension(
|
||||||
file_path
|
file_path
|
||||||
.extension()
|
.extension()
|
||||||
.and_then(|x| x.to_str())
|
.and_then(|x| x.to_str())
|
||||||
.unwrap_or_default(),
|
.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
|
/// If we find an ignored suffix on the file name, e.g. '~', we strip it and
|
||||||
|
@ -349,7 +369,7 @@ impl HighlightingAssets {
|
||||||
fn get_extension_syntax_with_stripped_suffix(
|
fn get_extension_syntax_with_stripped_suffix(
|
||||||
&self,
|
&self,
|
||||||
file_name: &OsStr,
|
file_name: &OsStr,
|
||||||
) -> Result<Option<&SyntaxReference>> {
|
) -> Result<Option<SyntaxReferenceInSet>> {
|
||||||
let file_path = Path::new(file_name);
|
let file_path = Path::new(file_name);
|
||||||
let mut syntax = None;
|
let mut syntax = None;
|
||||||
if let Some(file_str) = file_path.to_str() {
|
if let Some(file_str) = file_path.to_str() {
|
||||||
|
@ -363,11 +383,15 @@ impl HighlightingAssets {
|
||||||
Ok(syntax)
|
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()?;
|
let syntax_set = self.get_syntax_set()?;
|
||||||
Ok(String::from_utf8(reader.first_line.clone())
|
Ok(String::from_utf8(reader.first_line.clone())
|
||||||
.ok()
|
.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 }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,7 +486,7 @@ mod tests {
|
||||||
) -> String {
|
) -> String {
|
||||||
self.assets
|
self.assets
|
||||||
.get_syntax(language, input, mapping)
|
.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())
|
.unwrap_or_else(|_| "!no syntax!".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,11 +101,11 @@ pub fn get_languages(config: &Config) -> Result<String> {
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
let test_file = Path::new("test").with_extension(extension);
|
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)
|
.get_syntax_for_file_name(test_file, &config.syntax_mapping)
|
||||||
.unwrap(); // safe since .get_syntaxes() above worked
|
.unwrap(); // safe since .get_syntaxes() above worked
|
||||||
match syntax {
|
match syntax_in_set {
|
||||||
Some(syntax) => syntax.name == lang_name,
|
Some(syntax_in_set) => syntax_in_set.syntax.name == lang_name,
|
||||||
None => false,
|
None => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ use encoding::{DecoderTrap, Encoding};
|
||||||
|
|
||||||
use unicode_width::UnicodeWidthChar;
|
use unicode_width::UnicodeWidthChar;
|
||||||
|
|
||||||
use crate::assets::HighlightingAssets;
|
use crate::assets::{HighlightingAssets, SyntaxReferenceInSet};
|
||||||
use crate::config::Config;
|
use crate::config::Config;
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
use crate::decorations::LineChangesDecoration;
|
use crate::decorations::LineChangesDecoration;
|
||||||
|
@ -163,23 +163,29 @@ impl<'a> InteractivePrinter<'a> {
|
||||||
panel_width = 0;
|
panel_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let highlighter = if input
|
let (highlighter, syntax_set) = if input
|
||||||
.reader
|
.reader
|
||||||
.content_type
|
.content_type
|
||||||
.map_or(false, |c| c.is_binary() && !config.show_nonprintable)
|
.map_or(false, |c| c.is_binary() && !config.show_nonprintable)
|
||||||
{
|
{
|
||||||
None
|
(None, assets.get_syntax_set()?)
|
||||||
} else {
|
} else {
|
||||||
// Determine the type of syntax for highlighting
|
// Determine the type of syntax for highlighting
|
||||||
let syntax = match assets.get_syntax(config.language, input, &config.syntax_mapping) {
|
let syntax_in_set =
|
||||||
Ok(syntax) => syntax,
|
match assets.get_syntax(config.language, input, &config.syntax_mapping) {
|
||||||
|
Ok(syntax_in_set) => syntax_in_set,
|
||||||
Err(Error(ErrorKind::UndetectedSyntax(_), _)) => {
|
Err(Error(ErrorKind::UndetectedSyntax(_), _)) => {
|
||||||
assets.get_syntax_set()?.find_syntax_plain_text()
|
let syntax_set = assets.get_syntax_set()?;
|
||||||
|
let syntax = syntax_set.find_syntax_plain_text();
|
||||||
|
SyntaxReferenceInSet { syntax, syntax_set }
|
||||||
}
|
}
|
||||||
Err(e) => return Err(e),
|
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 {
|
Ok(InteractivePrinter {
|
||||||
|
@ -192,7 +198,7 @@ impl<'a> InteractivePrinter<'a> {
|
||||||
#[cfg(feature = "git")]
|
#[cfg(feature = "git")]
|
||||||
line_changes,
|
line_changes,
|
||||||
highlighter,
|
highlighter,
|
||||||
syntax_set: assets.get_syntax_set()?,
|
syntax_set,
|
||||||
background_color_highlight,
|
background_color_highlight,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue