diff --git a/assets/default_newlines.packdump b/assets/default_newlines.packdump index 49ca9f4e..87f57798 100644 Binary files a/assets/default_newlines.packdump and b/assets/default_newlines.packdump differ diff --git a/assets/default_nonewlines.packdump b/assets/default_nonewlines.packdump index 830bec67..bf832e42 100644 Binary files a/assets/default_nonewlines.packdump and b/assets/default_nonewlines.packdump differ diff --git a/examples/syntest.rs b/examples/syntest.rs index 881b7298..93523e05 100644 --- a/examples/syntest.rs +++ b/examples/syntest.rs @@ -132,10 +132,9 @@ fn test_file(ss: &SyntaxSet, path: &Path, parse_test_lines: bool) -> Result syntax, None => return Err(SyntaxTestHeaderError::SyntaxDefinitionNotFound) }; diff --git a/src/parsing/syntax_set.rs b/src/parsing/syntax_set.rs index d45ee3a3..defe814d 100644 --- a/src/parsing/syntax_set.rs +++ b/src/parsing/syntax_set.rs @@ -11,6 +11,7 @@ use std::mem; use std::rc::Rc; use std::ascii::AsciiExt; use std::sync::Mutex; +use std::collections::HashMap; use onig::Regex; use rustc_serialize::{Encodable, Encoder, Decodable, Decoder}; @@ -26,6 +27,7 @@ pub struct SyntaxSet { syntaxes: Vec, pub is_linked: bool, first_line_cache: Mutex, + path_scope_map: HashMap, } fn load_syntax_file(p: &Path, @@ -44,6 +46,7 @@ impl Default for SyntaxSet { syntaxes: Vec::new(), is_linked: true, first_line_cache: Mutex::new(FirstLineCache::new()), + path_scope_map: HashMap::new(), } } } @@ -85,7 +88,9 @@ impl SyntaxSet { let entry = try!(entry.map_err(LoadingError::WalkDir)); if entry.path().extension().map_or(false, |e| e == "sublime-syntax") { // println!("{}", entry.path().display()); - self.syntaxes.push(try!(load_syntax_file(entry.path(), lines_include_newline))); + let syntax = try!(load_syntax_file(entry.path(), lines_include_newline)); + self.path_scope_map.insert(entry.path().to_str().unwrap().to_string(), syntax.scope); + self.syntaxes.push(syntax); } } Ok(()) @@ -156,6 +161,15 @@ impl SyntaxSet { None } + /// Searches for a syntax by it's original file path when it was first loaded from disk + /// primarily useful for syntax tests + /// some may specify a Packages/PackageName/SyntaxName.sublime-syntax path + /// others may just have SyntaxName.sublime-syntax + /// this caters for these by matching the end of the path of the loaded syntax definition files + pub fn find_syntax_by_path<'a>(&'a self, path: &str) -> Option<&'a SyntaxDefinition> { + return self.path_scope_map.keys().find(|p| p.ends_with(path)).and_then(|p| self.syntaxes.iter().find(|&s| &s.scope == self.path_scope_map.get(p).unwrap())); + } + /// Convenience method that tries to find the syntax for a file path, /// first by extension and then by first line of the file if that doesn't work. /// May IO Error because it sometimes tries to read the first line of the file. @@ -372,9 +386,10 @@ impl FirstLineCache { impl Encodable for SyntaxSet { fn encode(&self, s: &mut S) -> Result<(), S::Error> { - s.emit_struct("SyntaxSet", 2, |s| { + s.emit_struct("SyntaxSet", 3, |s| { try!(s.emit_struct_field("syntaxes", 0, |s| self.syntaxes.encode(s))); try!(s.emit_struct_field("is_linked", 1, |s| self.is_linked.encode(s))); + try!(s.emit_struct_field("path_scope_map", 2, |s| self.path_scope_map.encode(s))); Ok(()) }) } @@ -382,11 +397,12 @@ impl Encodable for SyntaxSet { impl Decodable for SyntaxSet { fn decode(d: &mut D) -> Result { - d.read_struct("SyntaxSet", 2, |d| { + d.read_struct("SyntaxSet", 3, |d| { let ss = SyntaxSet { syntaxes: try!(d.read_struct_field("syntaxes", 0, Decodable::decode)), is_linked: try!(d.read_struct_field("is_linked", 1, Decodable::decode)), first_line_cache: Mutex::new(FirstLineCache::new()), + path_scope_map: try!(d.read_struct_field("path_scope_map", 2, Decodable::decode)), }; Ok(ss)