summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Nordholts <enselic@gmail.com>2021-08-08 08:26:17 +0200
committerGitHub <noreply@github.com>2021-08-08 08:26:17 +0200
commitd8b813c0bf1c88a11f1f49ffbd4b7328a02807a6 (patch)
tree3b0d4366542294499af26948bce86e12e62ca828
parent5236ed135e56bff956162bedf442c480521e6b54 (diff)
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`.
-rw-r--r--CHANGELOG.md2
-rw-r--r--src/assets.rs78
-rw-r--r--src/bin/bat/main.rs6
-rw-r--r--src/printer.rs30
4 files changed, 73 insertions, 43 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b15745c8..e78f8147 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,7 +26,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)
diff --git a/src/assets.rs b/src/assets.rs
index 7c8273fb..ba60274d 100644
--- a/src/assets.rs
+++ b/src/assets.rs
@@ -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
"~",
@@ -217,21 +223,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())?,
})
@@ -259,10 +270,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)?;
@@ -293,10 +306,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();
@@ -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)?;
if syntax.is_none() {
syntax = self.find_syntax_by_file_name_extension(file_name)?;
@@ -325,23 +341,27 @@ 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
@@ -349,7 +369,7 @@ impl HighlightingAssets {
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() {
@@ -363,11 +383,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 }))
}
}
@@ -462,7 +486,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())
}
diff --git a/src/bin/bat/main.rs b/src/bin/bat/main.rs
index 7369dc03..173ac551 100644
--- a/src/bin/bat/main.rs
+++ b/src/bin/bat/main.rs
@@ -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,
}
}
diff --git a/src/printer.rs b/src/printer.rs
index 22d7c22d..f07d2db1 100644
--- a/src/printer.rs
+++ b/src/printer.rs
@@ -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;
@@ -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 {
@@ -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,
})
}