Allow file paths ending in a language-specific-extension to be used as the language name for injections (#12368)
Nathan Sobo
created 1 year ago
This allows us to detect the language from the extension if we use paths
in fenced code blocks.
Release Notes:
- You can now use file paths ending in a language-specific file
extension at the start of markdown code blocks.
Change summary
crates/language/src/syntax_map.rs | 34 +++++++++------
crates/language/src/syntax_map/syntax_map_tests.rs | 6 +-
2 files changed, 24 insertions(+), 16 deletions(-)
Detailed changes
@@ -1252,20 +1252,28 @@ fn get_injections(
prev_match = Some((mat.pattern_index, content_range.clone()));
let combined = config.patterns[mat.pattern_index].combined;
- let mut language_name = None;
let mut step_range = content_range.clone();
- if let Some(name) = config.patterns[mat.pattern_index].language.as_ref() {
- language_name = Some(Cow::Borrowed(name.as_ref()))
- } else if let Some(language_node) = config
- .language_capture_ix
- .and_then(|ix| mat.nodes_for_capture_index(ix).next())
- {
- step_range.start = cmp::min(content_range.start, language_node.start_byte());
- step_range.end = cmp::max(content_range.end, language_node.end_byte());
- language_name = Some(Cow::Owned(
- text.text_for_range(language_node.byte_range()).collect(),
- ))
- };
+ let language_name =
+ if let Some(name) = config.patterns[mat.pattern_index].language.as_ref() {
+ Some(Cow::Borrowed(name.as_ref()))
+ } else if let Some(language_node) = config
+ .language_capture_ix
+ .and_then(|ix| mat.nodes_for_capture_index(ix).next())
+ {
+ step_range.start = cmp::min(content_range.start, language_node.start_byte());
+ step_range.end = cmp::max(content_range.end, language_node.end_byte());
+ let language_name: String =
+ text.text_for_range(language_node.byte_range()).collect();
+
+ // Enable paths ending in a language extension to represent a language name: e.g. "foo/bar/baz.rs"
+ if let Some(last_dot_pos) = language_name.rfind('.') {
+ Some(Cow::Owned(language_name[last_dot_pos + 1..].to_string()))
+ } else {
+ Some(Cow::Owned(language_name))
+ }
+ } else {
+ None
+ };
if let Some(language_name) = language_name {
let language = language_registry
@@ -214,9 +214,9 @@ fn test_dynamic_language_injection(cx: &mut AppContext) {
],
);
- // Replace Rust with Ruby in code block.
+ // Replace `rs` with a path to ending in `.rb` in code block.
let macro_name_range = range_for_text(&buffer, "rs");
- buffer.edit([(macro_name_range, "ruby")]);
+ buffer.edit([(macro_name_range, "foo/bar/baz.rb")]);
syntax_map.interpolate(&buffer);
syntax_map.reparse(markdown.clone(), &buffer);
syntax_map.reparse(markdown_inline.clone(), &buffer);
@@ -232,7 +232,7 @@ fn test_dynamic_language_injection(cx: &mut AppContext) {
);
// Replace Ruby with a language that hasn't been loaded yet.
- let macro_name_range = range_for_text(&buffer, "ruby");
+ let macro_name_range = range_for_text(&buffer, "foo/bar/baz.rb");
buffer.edit([(macro_name_range, "html")]);
syntax_map.interpolate(&buffer);
syntax_map.reparse(markdown.clone(), &buffer);