aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--book/src/languages.md28
-rw-r--r--helix-core/Cargo.toml1
-rw-r--r--helix-core/src/config.rs45
-rw-r--r--helix-core/src/syntax.rs150
-rw-r--r--helix-core/tests/indent.rs2
-rw-r--r--helix-term/src/application.rs14
-rw-r--r--helix-term/src/health.rs10
-rw-r--r--helix-term/src/main.rs10
-rw-r--r--helix-term/tests/test/commands/write.rs2
-rw-r--r--helix-term/tests/test/helpers.rs18
-rw-r--r--languages.toml168
12 files changed, 262 insertions, 187 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 73e548ae..a7ef8eb0 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1240,6 +1240,7 @@ dependencies = [
"dunce",
"encoding_rs",
"etcetera",
+ "globset",
"hashbrown 0.14.3",
"helix-loader",
"helix-stdx",
diff --git a/book/src/languages.md b/book/src/languages.md
index 944ebf09..7e49a603 100644
--- a/book/src/languages.md
+++ b/book/src/languages.md
@@ -78,24 +78,26 @@ from the above section. `file-types` is a list of strings or tables, for
example:
```toml
-file-types = ["Makefile", "toml", { suffix = ".git/config" }]
+file-types = ["toml", { glob = "Makefile" }, { glob = ".git/config" }, { glob = ".github/workflows/*.yaml" } ]
```
When determining a language configuration to use, Helix searches the file-types
with the following priorities:
-1. Exact match: if the filename of a file is an exact match of a string in a
- `file-types` list, that language wins. In the example above, `"Makefile"`
- will match against `Makefile` files.
-2. Extension: if there are no exact matches, any `file-types` string that
- matches the file extension of a given file wins. In the example above, the
- `"toml"` matches files like `Cargo.toml` or `languages.toml`.
-3. Suffix: if there are still no matches, any values in `suffix` tables
- are checked against the full path of the given file. In the example above,
- the `{ suffix = ".git/config" }` would match against any `config` files
- in `.git` directories. Note: `/` is used as the directory separator but is
- replaced at runtime with the appropriate path separator for the operating
- system, so this rule would match against `.git\config` files on Windows.
+1. Glob: values in `glob` tables are checked against the full path of the given
+ file. Globs are standard Unix-style path globs (e.g. the kind you use in Shell)
+ and can be used to match paths for a specific prefix, suffix, directory, etc.
+ In the above example, the `{ glob = "Makefile" }` config would match files
+ with the name `Makefile`, the `{ glob = ".git/config" }` config would match
+ `config` files in `.git` directories, and the `{ glob = ".github/workflows/*.yaml" }`
+ config would match any `yaml` files in `.github/workflow` directories. Note
+ that globs should always use the Unix path separator `/` even on Windows systems;
+ the matcher will automatically take the machine-specific separators into account.
+ If the glob isn't an absolute path or doesn't already start with a glob prefix,
+ `*/` will automatically be added to ensure it matches for any subdirectory.
+2. Extension: if there are no glob matches, any `file-types` string that matches
+ the file extension of a given file wins. In the example above, the `"toml"`
+ config matches files like `Cargo.toml` or `languages.toml`.
## Language Server configuration
diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml
index 8c63af8e..bdc879ca 100644
--- a/helix-core/Cargo.toml
+++ b/helix-core/Cargo.toml
@@ -49,6 +49,7 @@ chrono = { version = "0.4", default-features = false, features = ["alloc", "std"
etcetera = "0.8"
textwrap = "0.16.0"
+globset = "0.4.14"
nucleo.workspace = true
parking_lot = "0.12"
diff --git a/helix-core/src/config.rs b/helix-core/src/config.rs
index 2076fc22..27cd4e29 100644
--- a/helix-core/src/config.rs
+++ b/helix-core/src/config.rs
@@ -1,10 +1,45 @@
-/// Syntax configuration loader based on built-in languages.toml.
-pub fn default_syntax_loader() -> crate::syntax::Configuration {
+use crate::syntax::{Configuration, Loader, LoaderError};
+
+/// Language configuration based on built-in languages.toml.
+pub fn default_lang_config() -> Configuration {
helix_loader::config::default_lang_config()
.try_into()
- .expect("Could not serialize built-in languages.toml")
+ .expect("Could not deserialize built-in languages.toml")
}
-/// Syntax configuration loader based on user configured languages.toml.
-pub fn user_syntax_loader() -> Result<crate::syntax::Configuration, toml::de::Error> {
+
+/// Language configuration loader based on built-in languages.toml.
+pub fn default_lang_loader() -> Loader {
+ Loader::new(default_lang_config()).expect("Could not compile loader for default config")
+}
+
+#[derive(Debug)]
+pub enum LanguageLoaderError {
+ DeserializeError(toml::de::Error),
+ LoaderError(LoaderError),
+}
+
+impl std::fmt::Display for LanguageLoaderError {
+ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+ match self {
+ Self::DeserializeError(err) => write!(f, "Failed to parse language config: {err}"),
+ Self::LoaderError(err) => write!(f, "Failed to compile language config: {err}"),
+ }
+ }
+}
+
+impl std::error::Error for LanguageLoaderError {}
+
+/// Language configuration based on user configured languages.toml.
+pub fn user_lang_config() -> Result<Configuration, toml::de::Error> {
helix_loader::config::user_lang_config()?.try_into()
}
+
+/// Language configuration loader based on user configured languages.toml.
+pub fn user_lang_loader() -> Result<Loader, LanguageLoaderError> {
+ let config: Configuration = helix_loader::config::user_lang_config()
+ .map_err(LanguageLoaderError::DeserializeError)?
+ .try_into()
+ .map_err(LanguageLoaderError::DeserializeError)?;
+
+ Loader::new(config).map_err(LanguageLoaderError::LoaderError)
+}
diff --git a/helix-core/src/syntax.rs b/helix-core/src/syntax.rs
index 24de1a33..99b5a3d1 100644
--- a/helix-core/src/syntax.rs
+++ b/helix-core/src/syntax.rs
@@ -82,12 +82,6 @@ pub struct Configuration {
pub language_server: HashMap<String, LanguageServerConfiguration>,
}
-impl Default for Configuration {
- fn default() -> Self {
- crate::config::default_syntax_loader()
- }
-}
-
// largely based on tree-sitter/cli/src/loader.rs
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
@@ -164,9 +158,11 @@ pub enum FileType {
/// The extension of the file, either the `Path::extension` or the full
/// filename if the file does not have an extension.
Extension(String),
- /// The suffix of a file. This is compared to a given file's absolute
- /// path, so it can be used to detect files based on their directories.
- Suffix(String),
+ /// A Unix-style path glob. This is compared to the file's absolute path, so
+ /// it can be used to detect files based on their directories. If the glob
+ /// is not an absolute path and does not already start with a glob pattern,
+ /// a glob pattern will be prepended to it.
+ Glob(globset::Glob),
}
impl Serialize for FileType {
@@ -178,9 +174,9 @@ impl Serialize for FileType {
match self {
FileType::Extension(extension) => serializer.serialize_str(extension),
- FileType::Suffix(suffix) => {
+ FileType::Glob(glob) => {
let mut map = serializer.serialize_map(Some(1))?;
- map.serialize_entry("suffix", &suffix.replace(std::path::MAIN_SEPARATOR, "/"))?;
+ map.serialize_entry("glob", glob.glob())?;
map.end()
}
}
@@ -213,9 +209,20 @@ impl<'de> Deserialize<'de> for FileType {
M: serde::de::MapAccess<'de>,
{
match map.next_entry::<String, String>()? {
- Some((key, suffix)) if key == "suffix" => Ok(FileType::Suffix({
- suffix.replace('/', std::path::MAIN_SEPARATOR_STR)
- })),
+ Some((key, mut glob)) if key == "glob" => {
+ // If the glob isn't an absolute path or already starts
+ // with a glob pattern, add a leading glob so we
+ // properly match relative paths.
+ if !glob.starts_with('/') && !glob.starts_with("*/") {
+ glob.insert_str(0, "*/");
+ }
+
+ globset::Glob::new(glob.as_str())
+ .map(FileType::Glob)
+ .map_err(|err| {
+ serde::de::Error::custom(format!("invalid `glob` pattern: {}", err))
+ })
+ }
Some((key, _value)) => Err(serde::de::Error::custom(format!(
"unknown key in `file-types` list: {}",
key
@@ -752,6 +759,47 @@ pub struct SoftWrap {
pub wrap_at_text_width: Option<bool>,
}
+#[derive(Debug)]
+struct FileTypeGlob {
+ glob: globset::Glob,
+ language_id: usize,
+}
+
+impl FileTypeGlob {
+ fn new(glob: globset::Glob, language_id: usize) -> Self {
+ Self { glob, language_id }
+ }
+}
+
+#[derive(Debug)]
+struct FileTypeGlobMatcher {
+ matcher: globset::GlobSet,
+ file_types: Vec<FileTypeGlob>,
+}
+
+impl FileTypeGlobMatcher {
+ fn new(file_types: Vec<FileTypeGlob>) -> Result<Self, globset::Error> {
+ let mut builder = globset::GlobSetBuilder::new();
+ for file_type in &file_types {
+ builder.add(file_type.glob.clone());
+ }
+
+ Ok(Self {
+ matcher: builder.build()?,
+ file_types,
+ })
+ }
+
+ fn language_id_for_path(&self, path: &Path) -> Option<&usize> {
+ self.matcher
+ .matches(path)
+ .iter()
+ .filter_map(|idx| self.file_types.get(*idx))
+ .max_by_key(|file_type| file_type.glob.glob().len())
+ .map(|file_type| &file_type.language_id)
+ }
+}
+
// Expose loader as Lazy<> global since it's always static?
#[derive(Debug)]
@@ -759,7 +807,7 @@ pub struct Loader {
// highlight_names ?
language_configs: Vec<Arc<LanguageConfiguration>>,
language_config_ids_by_extension: HashMap<String, usize>, // Vec<usize>
- language_config_ids_by_suffix: HashMap<String, usize>,
+ language_config_ids_glob_matcher: FileTypeGlobMatcher,
language_config_ids_by_shebang: HashMap<String, usize>,
language_server_configs: HashMap<String, LanguageServerConfiguration>,
@@ -767,66 +815,57 @@ pub struct Loader {
scopes: ArcSwap<Vec<String>>,
}
+pub type LoaderError = globset::Error;
+
impl Loader {
- pub fn new(config: Configuration) -> Self {
- let mut loader = Self {
- language_configs: Vec::new(),
- language_server_configs: config.language_server,
- language_config_ids_by_extension: HashMap::new(),
- language_config_ids_by_suffix: HashMap::new(),
- language_config_ids_by_shebang: HashMap::new(),
- scopes: ArcSwap::from_pointee(Vec::new()),
- };
+ pub fn new(config: Configuration) -> Result<Self, LoaderError> {
+ let mut language_configs = Vec::new();
+ let mut language_config_ids_by_extension = HashMap::new();
+ let mut language_config_ids_by_shebang = HashMap::new();
+ let mut file_type_globs = Vec::new();
for config in config.language {
// get the next id
- let language_id = loader.language_configs.len();
+ let language_id = language_configs.len();
for file_type in &config.file_types {
// entry().or_insert(Vec::new).push(language_id);
match file_type {
- FileType::Extension(extension) => loader
- .language_config_ids_by_extension
- .insert(extension.clone(), language_id),
- FileType::Suffix(suffix) => loader
- .language_config_ids_by_suffix
- .insert(suffix.clone(), language_id),
+ FileType::Extension(extension) => {
+ language_config_ids_by_extension.insert(extension.clone(), language_id);
+ }
+ FileType::Glob(glob) => {
+ file_type_globs.push(FileTypeGlob::new(glob.to_owned(), language_id));
+ }
};
}
for shebang in &config.shebangs {
- loader
- .language_config_ids_by_shebang
- .insert(shebang.clone(), language_id);
+ language_config_ids_by_shebang.insert(shebang.clone(), language_id);
}
- loader.language_configs.push(Arc::new(config));
+ language_configs.push(Arc::new(config));
}
- loader
+ Ok(Self {
+ language_configs,
+ language_config_ids_by_extension,
+ language_config_ids_glob_matcher: FileTypeGlobMatcher::new(file_type_globs)?,
+ language_config_ids_by_shebang,
+ language_server_configs: config.language_server,
+ scopes: ArcSwap::from_pointee(Vec::new()),
+ })
}
pub fn language_config_for_file_name(&self, path: &Path) -> Option<Arc<LanguageConfiguration>> {
// Find all the language configurations that match this file name
// or a suffix of the file name.
- let configuration_id = path
- .file_name()
- .and_then(|n| n.to_str())
- .and_then(|file_name| self.language_config_ids_by_extension.get(file_name))
+ let configuration_id = self
+ .language_config_ids_glob_matcher
+ .language_id_for_path(path)
.or_else(|| {
path.extension()
.and_then(|extension| extension.to_str())
.and_then(|extension| self.language_config_ids_by_extension.get(extension))
- })
- .or_else(|| {
- self.language_config_ids_by_suffix
- .iter()
- .find_map(|(file_type, id)| {
- if path.to_str()?.ends_with(file_type) {
- Some(id)
- } else {
- None
- }
- })
});
configuration_id.and_then(|&id| self.language_configs.get(id).cloned())
@@ -2592,7 +2631,8 @@ mod test {
let loader = Loader::new(Configuration {
language: vec![],
language_server: HashMap::new(),
- });
+ })
+ .unwrap();
let language = get_language("rust").unwrap();
let query = Query::new(language, query_str).unwrap();
@@ -2654,7 +2694,8 @@ mod test {
let loader = Loader::new(Configuration {
language: vec![],
language_server: HashMap::new(),
- });
+ })
+ .unwrap();
let language = get_language("rust").unwrap();
let config = HighlightConfiguration::new(
@@ -2760,7 +2801,8 @@ mod test {
let loader = Loader::new(Configuration {
language: vec![],
language_server: HashMap::new(),
- });
+ })
+ .unwrap();
let language = get_language(language_name).unwrap();
let config = HighlightConfiguration::new(language, "", "", "").unwrap();
diff --git a/helix-core/tests/indent.rs b/helix-core/tests/indent.rs
index faf845c0..de1434f7 100644
--- a/helix-core/tests/indent.rs
+++ b/helix-core/tests/indent.rs
@@ -186,7 +186,7 @@ fn test_treesitter_indent(
lang_scope: &str,
ignored_lines: Vec<std::ops::Range<usize>>,
) {
- let loader = Loader::new(indent_tests_config());
+ let loader = Loader::new(indent_tests_config()).unwrap();
// set runtime path so we can find the queries
let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
diff --git a/helix-term/src/application.rs b/helix-term/src/application.rs
index b5150a13..b844b5f0 100644
--- a/helix-term/src/application.rs
+++ b/helix-term/src/application.rs
@@ -96,11 +96,7 @@ fn setup_integration_logging() {
}
impl Application {
- pub fn new(
- args: Args,
- config: Config,
- syn_loader_conf: syntax::Configuration,
- ) -> Result<Self, Error> {
+ pub fn new(args: Args, config: Config, lang_loader: syntax::Loader) -> Result<Self, Error> {
#[cfg(feature = "integration")]
setup_integration_logging();
@@ -126,7 +122,7 @@ impl Application {
})
.unwrap_or_else(|| theme_loader.default_theme(true_color));
- let syn_loader = std::sync::Arc::new(syntax::Loader::new(syn_loader_conf));
+ let syn_loader = std::sync::Arc::new(lang_loader);
#[cfg(not(feature = "integration"))]
let backend = CrosstermBackend::new(stdout(), &config.editor);
@@ -394,10 +390,8 @@ impl Application {
/// refresh language config after config change
fn refresh_language_config(&mut self) -> Result<(), Error> {
- let syntax_config = helix_core::config::user_syntax_loader()
- .map_err(|err| anyhow::anyhow!("Failed to load language config: {}", err))?;
-
- self.syn_loader = std::sync::Arc::new(syntax::Loader::new(syntax_config));
+ let lang_loader = helix_core::config::user_lang_loader()?;
+ self.syn_loader = std::sync::Arc::new(lang_loader);
self.editor.syn_loader = self.syn_loader.clone();
for document in self.editor.documents.values_mut() {
document.detect_language(self.syn_loader.clone());
diff --git a/helix-term/src/health.rs b/helix-term/src/health.rs
index 5f201926..0bbb5735 100644
--- a/helix-term/src/health.rs
+++ b/helix-term/src/health.rs
@@ -2,7 +2,7 @@ use crossterm::{
style::{Color, Print, Stylize},
tty::IsTty,
};
-use helix_core::config::{default_syntax_loader, user_syntax_loader};
+use helix_core::config::{default_lang_config, user_lang_config};
use helix_loader::grammar::load_runtime_file;
use helix_view::clipboard::get_clipboard_provider;
use std::io::Write;
@@ -128,7 +128,7 @@ pub fn languages_all() -> std::io::Result<()> {
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
- let mut syn_loader_conf = match user_syntax_loader() {
+ let mut syn_loader_conf = match user_lang_config() {
Ok(conf) => conf,
Err(err) => {
let stderr = std::io::stderr();
@@ -141,7 +141,7 @@ pub fn languages_all() -> std::io::Result<()> {
err
)?;
writeln!(stderr, "{}", "Using default language config".yellow())?;
- default_syntax_loader()
+ default_lang_config()
}
};
@@ -234,7 +234,7 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
let stdout = std::io::stdout();
let mut stdout = stdout.lock();
- let syn_loader_conf = match user_syntax_loader() {
+ let syn_loader_conf = match user_lang_config() {
Ok(conf) => conf,
Err(err) => {
let stderr = std::io::stderr();
@@ -247,7 +247,7 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
err
)?;
writeln!(stderr, "{}", "Using default language config".yellow())?;
- default_syntax_loader()
+ default_lang_config()
}
};
diff --git a/helix-term/src/main.rs b/helix-term/src/main.rs
index 132ee796..fbe1a846 100644
--- a/helix-term/src/main.rs
+++ b/helix-term/src/main.rs
@@ -145,18 +145,18 @@ FLAGS:
}
};
- let syn_loader_conf = helix_core::config::user_syntax_loader().unwrap_or_else(|err| {
- eprintln!("Bad language config: {}", err);
+ let lang_loader = helix_core::config::user_lang_loader().unwrap_or_else(|err| {
+ eprintln!("{}", err);
eprintln!("Press <ENTER> to continue with default language config");
use std::io::Read;
// This waits for an enter press.
let _ = std::io::stdin().read(&mut []);
- helix_core::config::default_syntax_loader()
+ helix_core::config::default_lang_loader()
});
// TODO: use the thread local executor to spawn the application task separately from the work pool
- let mut app = Application::new(args, config, syn_loader_conf)
- .context("unable to create new application")?;
+ let mut app =
+ Application::new(args, config, lang_loader).context("unable to create new application")?;
let exit_code = app.run(&mut EventStream::new()).await?;
diff --git a/helix-term/tests/test/commands/write.rs b/helix-term/tests/test/commands/write.rs
index adc721c5..f65352c7 100644
--- a/helix-term/tests/test/commands/write.rs
+++ b/helix-term/tests/test/commands/write.rs
@@ -315,7 +315,7 @@ async fn test_write_auto_format_fails_still_writes() -> anyhow::Result<()> {
let mut app = helpers::AppBuilder::new()
.with_file(file.path(), None)
.with_input_text("#[l|]#et foo = 0;\n")
- .with_lang_config(helpers::test_syntax_conf(Some(lang_conf.into())))
+ .with_lang_loader(helpers::test_syntax_loader(Some(lang_conf.into())))
.build()?;
test_key_sequences(&mut app, vec![(Some(":w<ret>"), None)], false).await?;
diff --git a/helix-term/tests/test/helpers.rs b/helix-term/tests/test/helpers.rs
index 112b5e35..a978f386 100644
--- a/helix-term/tests/test/helpers.rs
+++ b/helix-term/tests/test/helpers.rs
@@ -139,7 +139,7 @@ pub async fn test_key_sequence_with_input_text<T: Into<TestCase>>(
let test_case = test_case.into();
let mut app = match app {
Some(app) => app,
- None => Application::new(Args::default(), test_config(), test_syntax_conf(None))?,
+ None => Application::new(Args::default(), test_config(), test_syntax_loader(None))?,
};
let (view, doc) = helix_view::current!(app.editor);
@@ -162,9 +162,9 @@ pub async fn test_key_sequence_with_input_text<T: Into<TestCase>>(
.await
}
-/// Generates language configs that merge in overrides, like a user language
+/// Generates language config loader that merge in overrides, like a user language
/// config. The argument string must be a raw TOML document.
-pub fn test_syntax_conf(overrides: Option<String>) -> helix_core::syntax::Configuration {
+pub fn test_syntax_loader(overrides: Option<String>) -> helix_core::syntax::Loader {
let mut lang = helix_loader::config::default_lang_config();
if let Some(overrides) = overrides {
@@ -172,7 +172,7 @@ pub fn test_syntax_conf(overrides: Option<String>) -> helix_core::syntax::Config
lang = helix_loader::merge_toml_values(lang, override_toml, 3);
}
- lang.try_into().unwrap()
+ helix_core::syntax::Loader::new(lang.try_into().unwrap()).unwrap()
}
/// Use this for very simple test cases where there is one input
@@ -271,7 +271,7 @@ pub fn new_readonly_tempfile() -> anyhow::Result<NamedTempFile> {
pub struct AppBuilder {
args: Args,
config: Config,
- syn_conf: helix_core::syntax::Configuration,
+ syn_loader: helix_core::syntax::Loader,
input: Option<(String, Selection)>,
}
@@ -280,7 +280,7 @@ impl Default for AppBuilder {
Self {
args: Args::default(),
config: test_config(),
- syn_conf: test_syntax_conf(None),
+ syn_loader: test_syntax_loader(None),
input: None,
}
}
@@ -314,8 +314,8 @@ impl AppBuilder {
self
}
- pub fn with_lang_config(mut self, syn_conf: helix_core::syntax::Configuration) -> Self {
- self.syn_conf = syn_conf;
+ pub fn with_lang_loader(mut self, syn_loader: helix_core::syntax::Loader) -> Self {
+ self.syn_loader = syn_loader;
self
}
@@ -328,7 +328,7 @@ impl AppBuilder {
bail!("Having the directory {path:?} in args.files[0] is not yet supported for integration tests");
}
- let mut app = Application::new(self.args, self.config, self.syn_conf)?;
+ let mut app = Application::new(self.args, self.config, self.syn_loader)?;
if let Some((text, selection)) = self.input {
let (view, doc) = helix_view::current!(app.editor);
diff --git a/languages.toml b/languages.toml
index 30b41157..084d4932 100644
--- a/languages.toml
+++ b/languages.toml
@@ -253,7 +253,7 @@ source = { git = "https://github.com/FuelLabs/tree-sitter-sway", rev = "e491a005
name = "toml"
scope = "source.toml"
injection-regex = "toml"
-file-types = ["toml", "poetry.lock", "Cargo.lock"]
+file-types = ["toml", { glob = "poetry.lock" }, { glob = "Cargo.lock" }]
comment-token = "#"
language-servers = [ "taplo" ]
indent = { tab-width = 2, unit = " " }
@@ -292,7 +292,7 @@ source = { git = "https://github.com/yusdacra/tree-sitter-protobuf", rev = "19c2
name = "elixir"
scope = "source.elixir"
injection-regex = "(elixir|ex)"
-file-types = ["ex", "exs", "mix.lock"]
+file-types = ["ex", "exs", { glob = "mix.lock" }]
shebangs = ["elixir"]
roots = ["mix.exs", "mix.lock"]
comment-token = "#"
@@ -361,20 +361,20 @@ file-types = [
"geojson",
"gltf",
"webmanifest",
- "flake.lock",
- ".babelrc",
- ".bowerrc",
- ".jscrc",
+ { glob = "flake.lock" },
+ { glob = ".babelrc" },
+ { glob = ".bowerrc" },
+ { glob = ".jscrc" },
"js.map",
"ts.map",
"css.map",
- ".jslintrc",
+ { glob = ".jslintrc" },
"jsonld",
- ".vuerc",
- "composer.lock",
- ".watchmanconfig",
+ { glob = ".vuerc" },
+ { glob = "composer.lock" },
+ { glob = ".watchmanconfig" },
"avsc",
- ".prettierrc"
+ { glob = ".prettierrc" },
]
language-servers = [ "vscode-json-language-server" ]
auto-format = true
@@ -439,7 +439,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-c", rev = "7175a6dd
name = "cpp"
scope = "source.cpp"
injection-regex = "cpp"
-file-types = ["cc", "hh", "c++", "cpp", "hpp", "h", "ipp", "tpp", "cxx", "hxx", "ixx", "txx", "ino", "C", "H", "cu", "cuh", "cppm", "h++", "ii", "inl", { suffix = ".hpp.in" }, { suffix = ".h.in" }]
+file-types = ["cc", "hh", "c++", "cpp", "hpp", "h", "ipp", "tpp", "cxx", "hxx", "ixx", "txx", "ino", "C", "H", "cu", "cuh", "cppm", "h++", "ii", "inl", { glob = ".hpp.in" }, { glob = ".h.in" }]
comment-token = "//"
language-servers = [ "clangd" ]
indent = { tab-width = 2, unit = " " }
@@ -571,7 +571,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "64457ea
name = "gomod"
scope = "source.gomod"
injection-regex = "gomod"
-file-types = ["go.mod"]
+file-types = [{ glob = "go.mod" }]
auto-format = true
comment-token = "//"
language-servers = [ "gopls" ]
@@ -598,7 +598,7 @@ source = { git = "https://github.com/dannylongeuay/tree-sitter-go-template", rev
name = "gowork"
scope = "source.gowork"
injection-regex = "gowork"
-file-types = ["go.work"]
+file-types = [{ glob = "go.work" }]
auto-format = true
comment-token = "//"
language-servers = [ "gopls" ]
@@ -613,7 +613,7 @@ name = "javascript"
scope = "source.js"
injection-regex = "(js|javascript)"
language-id = "javascript"
-file-types = ["js", "mjs", "cjs", "rules", "es6", "pac", "jakefile"]
+file-types = ["js", "mjs", "cjs", "rules", "es6", "pac", { glob = "jakefile" }]
shebangs = ["node"]
comment-token = "//"
language-servers = [ "typescript-language-server" ]
@@ -716,7 +716,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-html", rev = "29f53
name = "python"
scope = "source.python"
injection-regex = "python"
-file-types = ["py","pyi","py3","pyw","ptl",".pythonstartup",".pythonrc","SConstruct", "rpy", "cpy", "ipy", "pyt", "SConscript"]
+file-types = ["py", "pyi", "py3", "pyw", "ptl", "rpy", "cpy", "ipy", "pyt", { glob = ".pythonstartup" }, { glob = ".pythonrc" }, { glob = "SConstruct" }, { glob = "SConscript" }]
shebangs = ["python"]
roots = ["pyproject.toml", "setup.py", "poetry.lock", "pyrightconfig.json"]
comment-token = "#"
@@ -769,38 +769,38 @@ injection-regex = "ruby"
file-types = [
"rb",
"rake",
- "rakefile",
"irb",
- "gemfile",
"gemspec",
- "Rakefile",
- "Gemfile",
"rabl",
"jbuilder",
"jb",
- "Podfile",
"podspec",
- "Vagrantfile",
- "Brewfile",
"rjs",
"rbi",
- "Guardfile",
- "Capfile",
- "Cheffile",
- "Hobofile",
- "Appraisals",
- "Rantfile",
- "Berksfile",
- "Berksfile.lock",
- "Thorfile",
- "Puppetfile",
- "Fastfile",
- "Appfile",
- "Deliverfile",
- "Matchfile",
- "Scanfile",
- "Snapfile",
- "Gymfile"
+ { glob = "rakefile" },
+ { glob = "gemfile" },
+ { glob = "Rakefile" },
+ { glob = "Gemfile" },
+ { glob = "Podfile" },
+ { glob = "Vagrantfile" },
+ { glob = "Brewfile" },
+ { glob = "Guardfile" },
+ { glob = "Capfile" },
+ { glob = "Cheffile" },
+ { glob = "Hobofile" },
+ { glob = "Appraisals" },
+ { glob = "Rantfile" },
+ { glob = "Berksfile" },
+ { glob = "Berksfile.lock" },
+ { glob = "Thorfile" },
+ { glob = "Puppetfile" },
+ { glob = "Fastfile" },
+ { glob = "Appfile" },
+ { glob = "Deliverfile" },
+ { glob = "Matchfile" },
+ { glob = "Scanfile" },
+ { glob = "Snapfile" },
+ { glob = "Gymfile" },
]
shebangs = ["ruby"]
comment-token = "#"
@@ -819,43 +819,43 @@ file-types = [
"sh",
"bash",
"zsh",
- ".bash_history",
- ".bash_login",
- ".bash_logout",
- ".bash_profile",
- ".bashrc",
- ".profile",
- ".zshenv",
"zshenv",
- ".zlogin",
"zlogin",
- ".zlogout",
"zlogout",
- ".zprofile",
"zprofile",
- ".zshrc",
"zshrc",
- ".zimrc",
- "APKBUILD",
- "PKGBUILD",
"eclass",
"ebuild",
"bazelrc",
- ".bash_aliases",
"Renviron",
- ".Renviron",
- ".xprofile",
- ".xsession",
- ".xsessionrc",
"zsh-theme",
"ksh",
"cshrc",
"tcshrc",
- ".yashrc",
- ".yash_profile",
- ".hushlogin",
"bashrc_Apple_Terminal",
- "zshrc_Apple_Terminal"
+ "zshrc_Apple_Terminal",
+ { glob = ".bash_history" },
+ { glob = ".bash_login" },
+ { glob = ".bash_logout" },
+ { glob = ".bash_profile" },
+ { glob = ".bashrc" },
+ { glob = ".profile" },
+ { glob = ".zshenv" },
+ { glob = ".zlogin" },
+ { glob = ".zlogout" },
+ { glob = ".zprofile" },
+ { glob = ".zshrc" },
+ { glob = ".zimrc" },
+ { glob = "APKBUILD" },
+ { glob = "PKGBUILD" },
+ { glob = ".bash_aliases" },
+ { glob = ".Renviron" },
+ { glob = ".xprofile" },
+ { glob = ".xsession" },
+ { glob = ".xsessionrc" },
+ { glob = ".yashrc" },
+ { glob = ".yash_profile" },
+ { glob = ".hushlogin" },
]
shebangs = ["sh", "bash", "dash", "zsh"]
comment-token = "#"
@@ -1216,7 +1216,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-tsq", rev = "48b5
[[language]]
name = "cmake"
scope = "source.cmake"
-file-types = ["cmake", "CMakeLists.txt"]
+file-types = ["cmake", { glob = "CMakeLists.txt" }]
comment-token = "#"
indent = { tab-width = 2, unit = " " }
language-servers = [ "cmake-language-server" ]
@@ -1229,7 +1229,7 @@ source = { git = "https://github.com/uyha/tree-sitter-cmake", rev = "6e51463ef30
[[language]]
name = "make"
scope = "source.make"
-file-types = ["Makefile", "makefile", "make", "mk", "mak", "GNUmakefile", "OCamlMakefile"]
+file-types = [{ glob = "Makefile" }, { glob = "makefile" }, "make", "mk", "mak", {glob = "GNUmakefile" }, { glob = "OCamlMakefile" }]
shebangs = ["make", "gmake"]
injection-regex = "(make|makefile|Makefile|mk)"
comment-token = "#"
@@ -1372,7 +1372,7 @@ source = { git = "https://github.com/Flakebi/tree-sitter-tablegen", rev = "568dd
name = "markdown"
scope = "source.md"
injection-regex = "md|markdown"
-file-types = ["md", "markdown", "PULLREQ_EDITMSG", "mkd", "mdwn", "mdown", "markdn", "mdtxt", "mdtext", "workbook"]
+file-types = ["md", "markdown", "mkd", "mdwn", "mdown", "markdn", "mdtxt", "mdtext", "workbook", { glob = "PULLREQ_EDITMSG" }]
roots = [".marksman.toml"]
language-servers = [ "marksman" ]
indent = { tab-width = 2, unit = " " }
@@ -1424,7 +1424,7 @@ name = "dockerfile"
scope = "source.dockerfile"
injection-regex = "docker|dockerfile"
roots = ["Dockerfile", "Containerfile"]
-file-types = ["Dockerfile", "dockerfile", "Containerfile", "containerfile"]
+file-types = [{ glob = "Dockerfile*" }, { glob = "dockerfile*" }, { glob = "Containerfile*" }, { glob = "containerfile*" }]
comment-token = "#"
indent = { tab-width = 2, unit = " " }
language-servers = [ "docker-langserver" ]
@@ -1436,7 +1436,7 @@ source = { git = "https://github.com/camdencheek/tree-sitter-dockerfile", rev =
[[language]]
name = "git-commit"
scope = "git.commitmsg"
-file-types = ["COMMIT_EDITMSG"]
+file-types = [{ glob = "COMMIT_EDITMSG" }]
comment-token = "#"
indent = { tab-width = 2, unit = " " }
rulers = [51, 73]
@@ -1461,7 +1461,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-diff", rev = "fd7
[[language]]
name = "git-rebase"
scope = "source.gitrebase"
-file-types = ["git-rebase-todo"]
+file-types = [{ glob = "git-rebase-todo" }]
injection-regex = "git-rebase"
comment-token = "#"
indent = { tab-width = 2, unit = "y" }
@@ -1474,7 +1474,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-git-rebase", rev
name = "regex"
scope = "source.regex"
injection-regex = "regex"
-file-types = ["regex", ".Rbuildignore"]
+file-types = ["regex", { glob = ".Rbuildignore" }]
[[grammar]]
name = "regex"
@@ -1483,7 +1483,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-regex", rev = "e1cf
[[language]]
name = "git-config"
scope = "source.gitconfig"
-file-types = [".gitmodules", ".gitconfig", { suffix = ".git/config" }, { suffix = ".config/git/config" }]
+file-types = [{ glob = ".gitmodules" }, { glob = ".gitconfig" }, { glob = ".git/config" }, { glob = ".config/git/config" }]
injection-regex = "git-config"
comment-token = "#"
indent = { tab-width = 4, unit = "\t" }
@@ -1495,7 +1495,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-git-config", rev
[[language]]
name = "git-attributes"
scope = "source.gitattributes"
-file-types = [".gitattributes"]
+file-types = [{ glob = ".gitattributes" }]
injection-regex = "git-attributes"
comment-token = "#"
grammar = "gitattributes"
@@ -1507,7 +1507,7 @@ source = { git = "https://github.com/mtoohey31/tree-sitter-gitattributes", rev =
[[language]]
name = "git-ignore"
scope = "source.gitignore"
-file-types = [".gitignore", ".gitignore_global", ".ignore", ".prettierignore", ".eslintignore", ".npmignore", "CODEOWNERS", { suffix = ".config/helix/ignore" }, { suffix = ".helix/ignore" }]
+file-types = [{ glob = ".gitignore" }, { glob = ".gitignore_global" }, { glob = ".ignore" }, { glob = ".prettierignore" }, { glob = ".eslintignore" }, { glob = ".npmignore"}, { glob = "CODEOWNERS" }, { glob = ".config/helix/ignore" }, { glob = ".helix/ignore" }]
injection-regex = "git-ignore"
comment-token = "#"
grammar = "gitignore"
@@ -1572,7 +1572,7 @@ source = { git = "https://github.com/jaredramirez/tree-sitter-rescript", rev = "
name = "erlang"
scope = "source.erlang"
injection-regex = "erl(ang)?"
-file-types = ["erl", "hrl", "app", "rebar.config", "rebar.lock"]
+file-types = ["erl", "hrl", "app", { glob = "rebar.config" }, { glob = "rebar.lock" }]
roots = ["rebar.config"]
shebangs = ["escript"]
comment-token = "%%"
@@ -1698,7 +1698,7 @@ source = { git = "https://github.com/Hubro/tree-sitter-robot", rev = "322e4cc657
name = "r"
scope = "source.r"
injection-regex = "(r|R)"
-file-types = ["r", "R", ".Rprofile", "Rprofile.site", ".RHistory"]
+file-types = ["r", "R", { glob = ".Rprofile" }, { glob = "Rprofile.site" }, { glob = ".RHistory" }]
shebangs = ["r", "R"]
comment-token = "#"
indent = { tab-width = 2, unit = " " }
@@ -1913,7 +1913,7 @@ source = { git = "https://github.com/ap29600/tree-sitter-odin", rev = "b219207e4
name = "meson"
scope = "source.meson"
injection-regex = "meson"
-file-types = ["meson.build", "meson_options.txt"]
+file-types = [{ glob = "meson.build" }, { glob = "meson_options.txt" }]
comment-token = "#"
indent = { tab-width = 2, unit = " " }
@@ -1924,7 +1924,7 @@ source = { git = "https://github.com/staysail/tree-sitter-meson", rev = "32a83e8
[[language]]
name = "sshclientconfig"
scope = "source.sshclientconfig"
-file-types = [{ suffix = ".ssh/config" }, { suffix = "/etc/ssh/ssh_config" }]
+file-types = [{ glob = ".ssh/config" }, { glob = "/etc/ssh/ssh_config" }]
comment-token = "#"
[[grammar]]
@@ -2045,7 +2045,7 @@ source = { git = "https://github.com/sogaiu/tree-sitter-clojure", rev = "e57c569
name = "starlark"
scope = "source.starlark"
injection-regex = "(starlark|bzl|bazel)"
-file-types = ["bzl", "bazel", "BUILD", "star"]
+file-types = ["bzl", "bazel", "star", { glob = "BUILD" }, { glob = "BUILD.*" }]
comment-token = "#"
indent = { tab-width = 4, unit = " " }
grammar = "python"
@@ -2413,7 +2413,7 @@ source = { git = "https://github.com/hh9527/tree-sitter-wit", rev = "c917790ab9a
[[language]]
name = "env"
scope = "source.env"
-file-types = [".env", ".env.local", ".env.development", ".env.production", ".env.dist", ".envrc", ".envrc.local", ".envrc.private"]
+file-types = [{ glob = ".env" }, { glob = ".env.*" }, { glob = ".envrc" }, { glob = ".envrc.*" }]
injection-regex = "env"
comment-token = "#"
indent = { tab-width = 4, unit = "\t" }
@@ -2441,7 +2441,7 @@ file-types = [
"volume",
"kube",
"network",
- ".editorconfig",
+ { glob = ".editorconfig" },
"properties",
"cfg",
"directory"
@@ -2569,7 +2569,7 @@ source = { git = "https://github.com/mtoohey31/tree-sitter-pem", rev = "be67a433
[[language]]
name = "passwd"
scope = "source.passwd"
-file-types = ["passwd"]
+file-types = [{ glob = "passwd" }]
[[grammar]]
name = "passwd"
@@ -2578,7 +2578,7 @@ source = { git = "https://github.com/ath3/tree-sitter-passwd", rev = "20239395ea
[[language]]
name = "hosts"
scope = "source.hosts"
-file-types = ["hosts"]
+file-types = [{ glob = "hosts" }]
comment-token = "#"
[[grammar]]
@@ -2786,7 +2786,7 @@ source = { git = "https://github.com/lefp/tree-sitter-opencl", rev = "8e1d24a570
[[language]]
name = "just"
scope = "source.just"
-file-types = ["justfile", "Justfile", ".justfile", ".Justfile"]
+file-types = [{ glob = "justfile" }, { glob = "Justfile" }, { glob = ".justfile" }, { glob = ".Justfile" }]
injection-regex = "just"
comment-token = "#"
indent = { tab-width = 4, unit = "\t" }
@@ -2945,7 +2945,7 @@ source = { git = "https://github.com/kylegoetz/tree-sitter-unison", rev = "1f505
[[language]]
name = "todotxt"
scope = "text.todotxt"
-file-types = [{ suffix = ".todo.txt" }, "todotxt"]
+file-types = [{ glob = "todo.txt" }, { glob = "*.todo.txt" }, "todotxt"]
formatter = { command = "sort" }
auto-format = true