Add a setting for custom associations between languages and files (#9290)
Closes #5178 Release Notes: - Added a `file_types` setting that can be used to associate languages with file names and file extensions. For example, to interpret all `.c` files as C++, and files called `MyLockFile` as TOML, add the following to `settings.json`: ```json { "file_types": { "C++": ["c"], "TOML": ["MyLockFile"] } } ``` As with most zed settings, this can be configured on a per-directory basis by including a local `.zed/settings.json` file in that directory. --------- Co-authored-by: Marshall <marshall@zed.dev>
This commit is contained in:
parent
77de5689a3
commit
724c19a223
30 changed files with 640 additions and 415 deletions
|
@ -69,8 +69,10 @@ fn test_line_endings(cx: &mut gpui::AppContext) {
|
|||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_select_language() {
|
||||
let registry = Arc::new(LanguageRegistry::test());
|
||||
fn test_select_language(cx: &mut AppContext) {
|
||||
init_settings(cx, |_| {});
|
||||
|
||||
let registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
|
||||
registry.add(Arc::new(Language::new(
|
||||
LanguageConfig {
|
||||
name: "Rust".into(),
|
||||
|
@ -97,14 +99,14 @@ fn test_select_language() {
|
|||
// matching file extension
|
||||
assert_eq!(
|
||||
registry
|
||||
.language_for_file("zed/lib.rs".as_ref(), None)
|
||||
.language_for_file(&file("src/lib.rs"), None, cx)
|
||||
.now_or_never()
|
||||
.and_then(|l| Some(l.ok()?.name())),
|
||||
Some("Rust".into())
|
||||
);
|
||||
assert_eq!(
|
||||
registry
|
||||
.language_for_file("zed/lib.mk".as_ref(), None)
|
||||
.language_for_file(&file("src/lib.mk"), None, cx)
|
||||
.now_or_never()
|
||||
.and_then(|l| Some(l.ok()?.name())),
|
||||
Some("Make".into())
|
||||
|
@ -113,7 +115,7 @@ fn test_select_language() {
|
|||
// matching filename
|
||||
assert_eq!(
|
||||
registry
|
||||
.language_for_file("zed/Makefile".as_ref(), None)
|
||||
.language_for_file(&file("src/Makefile"), None, cx)
|
||||
.now_or_never()
|
||||
.and_then(|l| Some(l.ok()?.name())),
|
||||
Some("Make".into())
|
||||
|
@ -122,27 +124,132 @@ fn test_select_language() {
|
|||
// matching suffix that is not the full file extension or filename
|
||||
assert_eq!(
|
||||
registry
|
||||
.language_for_file("zed/cars".as_ref(), None)
|
||||
.language_for_file(&file("zed/cars"), None, cx)
|
||||
.now_or_never()
|
||||
.and_then(|l| Some(l.ok()?.name())),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
registry
|
||||
.language_for_file("zed/a.cars".as_ref(), None)
|
||||
.language_for_file(&file("zed/a.cars"), None, cx)
|
||||
.now_or_never()
|
||||
.and_then(|l| Some(l.ok()?.name())),
|
||||
None
|
||||
);
|
||||
assert_eq!(
|
||||
registry
|
||||
.language_for_file("zed/sumk".as_ref(), None)
|
||||
.language_for_file(&file("zed/sumk"), None, cx)
|
||||
.now_or_never()
|
||||
.and_then(|l| Some(l.ok()?.name())),
|
||||
None
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test(iterations = 10)]
|
||||
async fn test_first_line_pattern(cx: &mut TestAppContext) {
|
||||
cx.update(|cx| init_settings(cx, |_| {}));
|
||||
|
||||
let languages = LanguageRegistry::test(cx.executor());
|
||||
let languages = Arc::new(languages);
|
||||
|
||||
languages.register_test_language(LanguageConfig {
|
||||
name: "JavaScript".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["js".into()],
|
||||
first_line_pattern: Some(Regex::new(r"\bnode\b").unwrap()),
|
||||
},
|
||||
..Default::default()
|
||||
});
|
||||
|
||||
cx.read(|cx| languages.language_for_file(&file("the/script"), None, cx))
|
||||
.await
|
||||
.unwrap_err();
|
||||
cx.read(|cx| languages.language_for_file(&file("the/script"), Some(&"nothing".into()), cx))
|
||||
.await
|
||||
.unwrap_err();
|
||||
assert_eq!(
|
||||
cx.read(|cx| languages.language_for_file(
|
||||
&file("the/script"),
|
||||
Some(&"#!/bin/env node".into()),
|
||||
cx
|
||||
))
|
||||
.await
|
||||
.unwrap()
|
||||
.name()
|
||||
.as_ref(),
|
||||
"JavaScript"
|
||||
);
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
async fn test_language_for_file_with_custom_file_types(cx: &mut TestAppContext) {
|
||||
cx.update(|cx| {
|
||||
init_settings(cx, |settings| {
|
||||
settings.file_types.extend([
|
||||
("TypeScript".into(), vec!["js".into()]),
|
||||
("C++".into(), vec!["c".into()]),
|
||||
]);
|
||||
})
|
||||
});
|
||||
|
||||
let languages = Arc::new(LanguageRegistry::test(cx.executor()));
|
||||
|
||||
for config in [
|
||||
LanguageConfig {
|
||||
name: "JavaScript".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["js".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
LanguageConfig {
|
||||
name: "TypeScript".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["js".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
LanguageConfig {
|
||||
name: "C++".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["cpp".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
LanguageConfig {
|
||||
name: "C".into(),
|
||||
matcher: LanguageMatcher {
|
||||
path_suffixes: vec!["c".to_string()],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
},
|
||||
] {
|
||||
languages.add(Arc::new(Language::new(config, None)));
|
||||
}
|
||||
|
||||
let language = cx
|
||||
.read(|cx| languages.language_for_file(&file("foo.js"), None, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(language.name().as_ref(), "TypeScript");
|
||||
let language = cx
|
||||
.read(|cx| languages.language_for_file(&file("foo.c"), None, cx))
|
||||
.await
|
||||
.unwrap();
|
||||
assert_eq!(language.name().as_ref(), "C++");
|
||||
}
|
||||
|
||||
fn file(path: &str) -> Arc<dyn File> {
|
||||
Arc::new(TestFile {
|
||||
path: Path::new(path).into(),
|
||||
root_name: "zed".into(),
|
||||
})
|
||||
}
|
||||
|
||||
#[gpui::test]
|
||||
fn test_edit_events(cx: &mut gpui::AppContext) {
|
||||
let mut now = Instant::now();
|
||||
|
@ -1575,7 +1682,7 @@ fn test_autoindent_with_injected_languages(cx: &mut AppContext) {
|
|||
|
||||
let javascript_language = Arc::new(javascript_lang());
|
||||
|
||||
let language_registry = Arc::new(LanguageRegistry::test());
|
||||
let language_registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
|
||||
language_registry.add(html_language.clone());
|
||||
language_registry.add(javascript_language.clone());
|
||||
|
||||
|
@ -1895,7 +2002,7 @@ fn test_language_scope_at_with_combined_injections(cx: &mut AppContext) {
|
|||
"#
|
||||
.unindent();
|
||||
|
||||
let language_registry = Arc::new(LanguageRegistry::test());
|
||||
let language_registry = Arc::new(LanguageRegistry::test(cx.background_executor().clone()));
|
||||
language_registry.add(Arc::new(ruby_lang()));
|
||||
language_registry.add(Arc::new(html_lang()));
|
||||
language_registry.add(Arc::new(erb_lang()));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue