Replace LanguageRegistry trait with a simple callback
This commit is contained in:
parent
e89b6b2402
commit
a46515b80f
4 changed files with 96 additions and 87 deletions
|
|
@ -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, "<table>\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, "</table>\n")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn language_for_injection_string<'a>(
|
||||
loader: &'a Loader,
|
||||
string: &str,
|
||||
) -> Option<(Language, &'a PropertySheet<Properties>)> {
|
||||
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)),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Properties>)> {
|
||||
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,
|
||||
|
|
|
|||
|
|
@ -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<Properties> =
|
||||
|
|
@ -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<Properties>)> {
|
||||
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<Properties>)> {
|
||||
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<Properties>,
|
||||
) -> Result<Vec<String>, 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),
|
||||
|
|
|
|||
|
|
@ -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<Properties>)>;
|
||||
}
|
||||
|
||||
#[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<Properties>)>,
|
||||
{
|
||||
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<Properties>)>,
|
||||
{
|
||||
fn new(
|
||||
language_registry: &'a T,
|
||||
source: &'a [u8],
|
||||
language: Language,
|
||||
property_sheet: &'a PropertySheet<Properties>,
|
||||
injection_callback: &'a F,
|
||||
) -> Result<Self, String> {
|
||||
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<String> {
|
||||
match language {
|
||||
|
|
@ -556,10 +555,7 @@ impl<'a, T: LanguageRegistry> Highlighter<'a, T> {
|
|||
}
|
||||
|
||||
fn add_layer(&mut self, language_string: &str, ranges: Vec<Range>) {
|
||||
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<Properties>)>> Iterator
|
||||
for Highlighter<'a, T>
|
||||
{
|
||||
type Item = HighlightEvent<'a>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
|
|
@ -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<Properties>,
|
||||
) -> Result<impl Iterator<Item = HighlightEvent<'a>> + 'a, String> {
|
||||
Highlighter::new(language_registry, source, language, property_sheet)
|
||||
injection_callback: &'a F,
|
||||
) -> Result<impl Iterator<Item = HighlightEvent<'a>> + 'a, String>
|
||||
where
|
||||
F: Fn(&str) -> Option<(Language, &'a PropertySheet<Properties>)>,
|
||||
{
|
||||
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<Properties>,
|
||||
attribute_callback: F,
|
||||
) -> Result<Vec<String>, String> {
|
||||
let highlighter = Highlighter::new(language_registry, source, language, property_sheet)?;
|
||||
injection_callback: &'a F1,
|
||||
attribute_callback: &'a F2,
|
||||
) -> Result<Vec<String>, String>
|
||||
where
|
||||
F1: Fn(&str) -> Option<(Language, &'a PropertySheet<Properties>)>,
|
||||
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(),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue