Mercurial > forks > helix
view xtask/src/main.rs @ 6770:7b5782139252
xtask: Allow passing languages and themes to check
This is for convenience when testing a few languages or themes, for
example while updating a language's parser and queries. query-check in
particular can take a while since parser initialization and query
analysis can each take some time and there are now many many languages.
Specifying the exact language makes the feedback loop much faster.
author | Michael Davis <mcarsondavis@gmail.com> |
---|---|
date | Thu, 08 May 2025 09:04:18 -0400 |
parents | 732e735bc929 |
children | 6a72d595f89b |
line wrap: on
line source
mod docgen; mod helpers; mod path; use std::{env, error::Error}; type DynError = Box<dyn Error>; pub mod tasks { use crate::DynError; use std::collections::HashSet; pub fn docgen() -> Result<(), DynError> { use crate::docgen::*; write(TYPABLE_COMMANDS_MD_OUTPUT, &typable_commands()?); write(STATIC_COMMANDS_MD_OUTPUT, &static_commands()?); write(LANG_SUPPORT_MD_OUTPUT, &lang_features()?); Ok(()) } pub fn querycheck(languages: impl Iterator<Item = String>) -> Result<(), DynError> { use crate::helpers::lang_config; use helix_core::{syntax::read_query, tree_sitter::Query}; use helix_loader::grammar::get_language; let query_files = [ "highlights.scm", "locals.scm", "injections.scm", "textobjects.scm", "indents.scm", ]; let languages_to_check: HashSet<_> = languages.collect(); for language in lang_config().language { if !languages_to_check.is_empty() && !languages_to_check.contains(&language.language_id) { continue; } let language_name = &language.language_id; let grammar_name = language.grammar.as_ref().unwrap_or(language_name); for query_file in query_files { let language = get_language(grammar_name); let query_text = read_query(language_name, query_file); if let Ok(lang) = language { if !query_text.is_empty() { if let Err(reason) = Query::new(&lang, &query_text) { return Err(format!( "Failed to parse {} queries for {}: {}", query_file, language_name, reason ) .into()); } } } } } println!("Query check succeeded"); Ok(()) } pub fn themecheck(themes: impl Iterator<Item = String>) -> Result<(), DynError> { use helix_view::theme::Loader; let themes_to_check: HashSet<_> = themes.collect(); let theme_names = [ vec!["default".to_string(), "base16_default".to_string()], Loader::read_names(&crate::path::themes()), ] .concat(); let loader = Loader::new(&[crate::path::runtime()]); let mut errors_present = false; for name in theme_names { if !themes_to_check.is_empty() && !themes_to_check.contains(&name) { continue; } let (_, warnings) = loader.load_with_warnings(&name).unwrap(); if !warnings.is_empty() { errors_present = true; println!("Theme '{name}' loaded with errors:"); for warning in warnings { println!("\t* {}", warning); } } } match errors_present { true => Err("Errors found when loading bundled themes".into()), false => { println!("Theme check successful!"); Ok(()) } } } pub fn print_help() { println!( " Usage: Run with `cargo xtask <task>`, eg. `cargo xtask docgen`. Tasks: docgen Generate files to be included in the mdbook output. query-check [languages] Check that tree-sitter queries are valid for the given languages, or all languages if none are specified. theme-check [themes] Check that the theme files in runtime/themes/ are valid for the given themes, or all themes if none are specified. " ); } } fn main() -> Result<(), DynError> { let mut args = env::args().skip(1); let task = args.next(); match task { None => tasks::print_help(), Some(t) => match t.as_str() { "docgen" => tasks::docgen()?, "query-check" => tasks::querycheck(args)?, "theme-check" => tasks::themecheck(args)?, invalid => return Err(format!("Invalid task name: {}", invalid).into()), }, }; Ok(()) }