add 'use-grammars' to languages.toml

The vision with 'use-grammars' is to allow the long-requested feature
of being able to declare your own set of grammars that you would like.
A simple schema with only/except grammar names controls the list
of grammars that is fetched and built. It does not (yet) control which
grammars may be loaded at runtime if they already exist.
This commit is contained in:
Michael Davis 2022-02-14 23:23:01 -06:00 committed by Blaž Hrastnik
parent db3470d973
commit 08ee949dcb
4 changed files with 36 additions and 4 deletions

View file

@ -28,4 +28,13 @@ name = "c"
source = { path = "/path/to/tree-sitter-c" } source = { path = "/path/to/tree-sitter-c" }
``` ```
If a user has a `languages.toml`, only the grammars in that `languages.toml` are evaluated when running `hx --fetch-grammars` and `hx --build-grammars`. Otherwise the [default `languages.toml`](https://github.com/helix-editor/helix/blob/master/languages.toml) is used. You may use a top-level `use-grammars` key to control which grammars are fetched and built.
```toml
# Note: this key must come **before** the [[language]] and [[grammar]] sections
use-grammars = { only = [ "rust", "c", "cpp" ] }
# or
use-grammars = { except = [ "yaml", "json" ] }
```
When omitted, all grammars are fetched and built.

View file

@ -445,6 +445,7 @@ where
auto_pairs: None, auto_pairs: None,
}], }],
grammar: vec![], grammar: vec![],
grammar_selection: None,
}); });
// set runtime path so we can find the queries // set runtime path so we can find the queries

View file

@ -81,12 +81,21 @@ where
} }
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(deny_unknown_fields)] #[serde(rename_all = "kebab-case", deny_unknown_fields)]
pub struct Configuration { pub struct Configuration {
#[serde(rename = "use-grammars")]
pub grammar_selection: Option<GrammarSelection>,
pub language: Vec<LanguageConfiguration>, pub language: Vec<LanguageConfiguration>,
pub grammar: Vec<GrammarConfiguration>, pub grammar: Vec<GrammarConfiguration>,
} }
#[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "lowercase", untagged)]
pub enum GrammarSelection {
Only(HashSet<String>),
Except(HashSet<String>),
}
// largely based on tree-sitter/cli/src/loader.rs // largely based on tree-sitter/cli/src/loader.rs
#[derive(Debug, Serialize, Deserialize)] #[derive(Debug, Serialize, Deserialize)]
#[serde(rename_all = "kebab-case", deny_unknown_fields)] #[serde(rename_all = "kebab-case", deny_unknown_fields)]
@ -2110,6 +2119,7 @@ mod test {
let loader = Loader::new(Configuration { let loader = Loader::new(Configuration {
language: vec![], language: vec![],
grammar: vec![], grammar: vec![],
grammar_selection: None,
}); });
let language = get_language(&crate::RUNTIME_DIR, "Rust").unwrap(); let language = get_language(&crate::RUNTIME_DIR, "Rust").unwrap();

View file

@ -7,7 +7,7 @@ use std::{
sync::mpsc::channel, sync::mpsc::channel,
}; };
use helix_core::syntax::{GrammarConfiguration, GrammarSource, DYLIB_EXTENSION}; use helix_core::syntax::{GrammarConfiguration, GrammarSelection, GrammarSource, DYLIB_EXTENSION};
const BUILD_TARGET: &str = env!("BUILD_TARGET"); const BUILD_TARGET: &str = env!("BUILD_TARGET");
const REMOTE_NAME: &str = "origin"; const REMOTE_NAME: &str = "origin";
@ -163,7 +163,19 @@ fn build_grammar(grammar: GrammarConfiguration) -> Result<()> {
fn get_grammar_configs() -> Vec<GrammarConfiguration> { fn get_grammar_configs() -> Vec<GrammarConfiguration> {
let config = helix_core::config::user_syntax_loader().expect("Could not parse languages.toml"); let config = helix_core::config::user_syntax_loader().expect("Could not parse languages.toml");
config.grammar match config.grammar_selection {
Some(GrammarSelection::Only(selections)) => config
.grammar
.into_iter()
.filter(|grammar| selections.contains(&grammar.grammar_id))
.collect(),
Some(GrammarSelection::Except(rejections)) => config
.grammar
.into_iter()
.filter(|grammar| !rejections.contains(&grammar.grammar_id))
.collect(),
None => config.grammar,
}
} }
fn build_tree_sitter_library(src_path: &Path, grammar: GrammarConfiguration) -> Result<()> { fn build_tree_sitter_library(src_path: &Path, grammar: GrammarConfiguration) -> Result<()> {