diff --git a/cli/src/highlight.rs b/cli/src/highlight.rs
index 1651b98d..0f88149a 100644
--- a/cli/src/highlight.rs
+++ b/cli/src/highlight.rs
@@ -4,7 +4,7 @@ use ansi_term::{Color, Style};
use lazy_static::lazy_static;
use serde_json::Value;
use std::collections::HashMap;
-use std::{fmt, fs, io, mem, path};
+use std::{fmt, fs, io, path};
use tree_sitter::{Language, PropertySheet};
use tree_sitter_highlight::{highlight, highlight_html, HighlightEvent, Properties, Scope};
@@ -195,7 +195,9 @@ pub fn ansi(
let stdout = io::stdout();
let mut stdout = stdout.lock();
let mut scope_stack = Vec::new();
- for event in highlight(loader, source, language, property_sheet)? {
+ for event in highlight(source, language, property_sheet, &|s| {
+ language_for_injection_string(loader, s)
+ })? {
match event {
HighlightEvent::Source(s) => {
if let Some(style) = scope_stack.last().and_then(|s| theme.ansi_style(*s)) {
@@ -252,13 +254,19 @@ pub fn html(
let stdout = io::stdout();
let mut stdout = stdout.lock();
write!(&mut stdout, "
\n")?;
- let lines = highlight_html(loader, source, language, property_sheet, |scope| {
- if let Some(css_style) = theme.css_style(scope) {
- css_style
- } else {
- ""
- }
- })?;
+ let lines = highlight_html(
+ source,
+ language,
+ property_sheet,
+ &|s| language_for_injection_string(loader, s),
+ &|scope| {
+ if let Some(css_style) = theme.css_style(scope) {
+ css_style
+ } else {
+ ""
+ }
+ },
+ )?;
for (i, line) in lines.into_iter().enumerate() {
write!(
&mut stdout,
@@ -270,3 +278,32 @@ pub fn html(
write!(&mut stdout, "
\n")?;
Ok(())
}
+
+fn language_for_injection_string<'a>(
+ loader: &'a Loader,
+ string: &str,
+) -> Option<(Language, &'a PropertySheet)> {
+ match loader.language_configuration_for_injection_string(string) {
+ Err(message) => {
+ eprintln!(
+ "Failed to load language for injection string '{}': {}",
+ string, message.0
+ );
+ None
+ }
+ Ok(None) => None,
+ Ok(Some((language, configuration))) => {
+ match configuration.highlight_property_sheet(language) {
+ Err(message) => {
+ eprintln!(
+ "Failed to load property sheet for injection string '{}': {}",
+ string, message.0
+ );
+ None
+ }
+ Ok(None) => None,
+ Ok(Some(sheet)) => Some((language, sheet)),
+ }
+ }
+ }
+}
diff --git a/cli/src/loader.rs b/cli/src/loader.rs
index d19acf46..49bab4b4 100644
--- a/cli/src/loader.rs
+++ b/cli/src/loader.rs
@@ -10,7 +10,7 @@ use std::process::Command;
use std::time::SystemTime;
use std::{fs, mem};
use tree_sitter::{Language, PropertySheet};
-use tree_sitter_highlight::{load_property_sheet, LanguageRegistry, Properties};
+use tree_sitter_highlight::{load_property_sheet, Properties};
#[cfg(unix)]
const DYLIB_EXTENSION: &'static str = "so";
@@ -320,37 +320,6 @@ impl Loader {
}
}
-impl LanguageRegistry for Loader {
- fn language_for_injection_string<'a>(
- &'a self,
- string: &str,
- ) -> Option<(Language, &'a PropertySheet)> {
- match self.language_configuration_for_injection_string(string) {
- Err(message) => {
- eprintln!(
- "Failed to load language for injection string '{}': {}",
- string, message.0
- );
- None
- }
- Ok(None) => None,
- Ok(Some((language, configuration))) => {
- match configuration.highlight_property_sheet(language) {
- Err(message) => {
- eprintln!(
- "Failed to load property sheet for injection string '{}': {}",
- string, message.0
- );
- None
- }
- Ok(None) => None,
- Ok(Some(sheet)) => Some((language, sheet)),
- }
- }
- }
- }
-}
-
impl LanguageConfiguration {
pub fn highlight_property_sheet(
&self,
diff --git a/cli/src/tests/highlight_test.rs b/cli/src/tests/highlight_test.rs
index ea14a1c2..6e07ab4a 100644
--- a/cli/src/tests/highlight_test.rs
+++ b/cli/src/tests/highlight_test.rs
@@ -1,9 +1,7 @@
use super::helpers::fixtures::{get_language, get_property_sheet};
use lazy_static::lazy_static;
use tree_sitter::{Language, PropertySheet};
-use tree_sitter_highlight::{
- highlight, highlight_html, HighlightEvent, LanguageRegistry, Properties, Scope,
-};
+use tree_sitter_highlight::{highlight, highlight_html, HighlightEvent, Properties, Scope};
lazy_static! {
static ref JS_SHEET: PropertySheet =
@@ -124,18 +122,13 @@ fn test_highlighting_multiline_scopes_to_html() {
);
}
-struct TestLanguageRegistry;
-
-impl LanguageRegistry for TestLanguageRegistry {
- fn language_for_injection_string(
- &self,
- string: &str,
- ) -> Option<(Language, &PropertySheet)> {
- match string {
- "javascript" => Some((get_language("javascript"), &JS_SHEET)),
- "html" => Some((get_language("html"), &HTML_SHEET)),
- _ => None,
- }
+fn test_language_for_injection_string<'a>(
+ string: &str,
+) -> Option<(Language, &'a PropertySheet)> {
+ match string {
+ "javascript" => Some((get_language("javascript"), &JS_SHEET)),
+ "html" => Some((get_language("html"), &HTML_SHEET)),
+ _ => None,
}
}
@@ -145,11 +138,11 @@ fn to_html<'a>(
property_sheet: &'a PropertySheet,
) -> Result, String> {
highlight_html(
- &TestLanguageRegistry,
src.as_bytes(),
language,
property_sheet,
- |scope| SCOPE_CLASS_STRINGS[scope as usize].as_str(),
+ &test_language_for_injection_string,
+ &|scope| SCOPE_CLASS_STRINGS[scope as usize].as_str(),
)
}
@@ -162,10 +155,10 @@ fn to_token_vector<'a>(
let mut scopes = Vec::new();
let mut line = Vec::new();
for event in highlight(
- &TestLanguageRegistry,
src.as_bytes(),
language,
property_sheet,
+ &test_language_for_injection_string,
)? {
match event {
HighlightEvent::ScopeStart(s) => scopes.push(s),
diff --git a/highlight/src/lib.rs b/highlight/src/lib.rs
index bdf35b9f..453685f4 100644
--- a/highlight/src/lib.rs
+++ b/highlight/src/lib.rs
@@ -9,13 +9,6 @@ use std::str;
use std::usize;
use tree_sitter::{Language, Node, Parser, Point, PropertySheet, Range, Tree, TreePropertyCursor};
-pub trait LanguageRegistry {
- fn language_for_injection_string<'a>(
- &'a self,
- s: &str,
- ) -> Option<(Language, &'a PropertySheet)>;
-}
-
#[derive(Debug)]
enum TreeStep {
Child {
@@ -87,8 +80,11 @@ struct Layer<'a> {
at_node_end: bool,
}
-struct Highlighter<'a, T: LanguageRegistry> {
- language_registry: &'a T,
+struct Highlighter<'a, T>
+where
+ T: Fn(&str) -> Option<(Language, &'a PropertySheet)>,
+{
+ injection_callback: &'a T,
source: &'a [u8],
source_offset: usize,
parser: Parser,
@@ -349,12 +345,15 @@ impl Properties {
}
}
-impl<'a, T: LanguageRegistry> Highlighter<'a, T> {
+impl<'a, F> Highlighter<'a, F>
+where
+ F: Fn(&str) -> Option<(Language, &'a PropertySheet)>,
+{
fn new(
- language_registry: &'a T,
source: &'a [u8],
language: Language,
property_sheet: &'a PropertySheet,
+ injection_callback: &'a F,
) -> Result {
let mut parser = Parser::new();
parser.set_language(language)?;
@@ -362,7 +361,7 @@ impl<'a, T: LanguageRegistry> Highlighter<'a, T> {
.parse(source, None)
.ok_or_else(|| format!("Tree-sitter: failed to parse"))?;
Ok(Self {
- language_registry,
+ injection_callback,
source,
source_offset: 0,
parser,
@@ -457,7 +456,7 @@ impl<'a, T: LanguageRegistry> Highlighter<'a, T> {
// on the text of some node in the syntax tree.
fn injection_language_string(
&self,
- node: &Node,
+ node: &Node<'a>,
language: &InjectionLanguage,
) -> Option {
match language {
@@ -556,10 +555,7 @@ impl<'a, T: LanguageRegistry> Highlighter<'a, T> {
}
fn add_layer(&mut self, language_string: &str, ranges: Vec) {
- if let Some((language, property_sheet)) = self
- .language_registry
- .language_for_injection_string(language_string)
- {
+ if let Some((language, property_sheet)) = (self.injection_callback)(language_string) {
self.parser
.set_language(language)
.expect("Failed to set language");
@@ -579,7 +575,9 @@ impl<'a, T: LanguageRegistry> Highlighter<'a, T> {
}
}
-impl<'a, T: LanguageRegistry> Iterator for Highlighter<'a, T> {
+impl<'a, T: Fn(&str) -> Option<(Language, &'a PropertySheet)>> Iterator
+ for Highlighter<'a, T>
+{
type Item = HighlightEvent<'a>;
fn next(&mut self) -> Option {
@@ -738,23 +736,32 @@ impl<'de> Deserialize<'de> for Scope {
}
}
-pub fn highlight<'a, T: LanguageRegistry>(
- language_registry: &'a T,
+pub trait HTMLAttributeCallback<'a>: Fn(Scope) -> &'a str {}
+
+pub fn highlight<'a, F>(
source: &'a [u8],
language: Language,
property_sheet: &'a PropertySheet,
-) -> Result> + 'a, String> {
- Highlighter::new(language_registry, source, language, property_sheet)
+ injection_callback: &'a F,
+) -> Result> + 'a, String>
+where
+ F: Fn(&str) -> Option<(Language, &'a PropertySheet)>,
+{
+ Highlighter::new(source, language, property_sheet, injection_callback)
}
-pub fn highlight_html<'a, T: LanguageRegistry, F: Fn(Scope) -> &'a str>(
- language_registry: &'a T,
+pub fn highlight_html<'a, F1, F2>(
source: &'a [u8],
language: Language,
property_sheet: &'a PropertySheet,
- attribute_callback: F,
-) -> Result, String> {
- let highlighter = Highlighter::new(language_registry, source, language, property_sheet)?;
+ injection_callback: &'a F1,
+ attribute_callback: &'a F2,
+) -> Result, String>
+where
+ F1: Fn(&str) -> Option<(Language, &'a PropertySheet)>,
+ F2: Fn(Scope) -> &'a str,
+{
+ let highlighter = Highlighter::new(source, language, property_sheet, injection_callback)?;
let mut renderer = HtmlRenderer::new(attribute_callback);
let mut scopes = Vec::new();
for event in highlighter {
@@ -782,7 +789,10 @@ struct HtmlRenderer<'a, F: Fn(Scope) -> &'a str> {
attribute_callback: F,
}
-impl<'a, F: Fn(Scope) -> &'a str> HtmlRenderer<'a, F> {
+impl<'a, F> HtmlRenderer<'a, F>
+where
+ F: Fn(Scope) -> &'a str,
+{
fn new(attribute_callback: F) -> Self {
HtmlRenderer {
result: Vec::new(),