From 324c11a9cb933bfbdc3686d013adfe8250087553 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Thu, 28 Jul 2022 22:46:50 +0200 Subject: [PATCH 01/33] feat: cargo xtask themelint --- Cargo.lock | 1 + xtask/Cargo.toml | 1 + xtask/src/docgen.rs | 117 ++++++++++++++++++++++ xtask/src/helpers.rs | 58 +++++++++++ xtask/src/main.rs | 222 +++-------------------------------------- xtask/src/paths.rs | 24 +++++ xtask/src/themelint.rs | 71 +++++++++++++ 7 files changed, 288 insertions(+), 206 deletions(-) create mode 100644 xtask/src/docgen.rs create mode 100644 xtask/src/helpers.rs create mode 100644 xtask/src/paths.rs create mode 100644 xtask/src/themelint.rs diff --git a/Cargo.lock b/Cargo.lock index 802bf8ba2dab..d930b3928341 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1422,5 +1422,6 @@ version = "0.6.0" dependencies = [ "helix-core", "helix-term", + "helix-view", "toml", ] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 717530d0a45a..651e37aea1de 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -8,4 +8,5 @@ edition = "2021" [dependencies] helix-term = { version = "0.6", path = "../helix-term" } helix-core = { version = "0.6", path = "../helix-core" } +helix-view = { version = "0.6", path = "../helix-view" } toml = "0.5" diff --git a/xtask/src/docgen.rs b/xtask/src/docgen.rs new file mode 100644 index 000000000000..7fc0235726d7 --- /dev/null +++ b/xtask/src/docgen.rs @@ -0,0 +1,117 @@ +use crate::helpers; +use crate::paths; +use crate::DynError; + +use helix_term::commands::TYPABLE_COMMAND_LIST; +use helix_term::health::TsFeature; +use std::fs; + +pub const TYPABLE_COMMANDS_MD_OUTPUT: &str = "typable-cmd.md"; +pub const LANG_SUPPORT_MD_OUTPUT: &str = "lang-support.md"; + +fn md_table_heading(cols: &[String]) -> String { + let mut header = String::new(); + header += &md_table_row(cols); + header += &md_table_row(&vec!["---".to_string(); cols.len()]); + header +} + +fn md_table_row(cols: &[String]) -> String { + format!("| {} |\n", cols.join(" | ")) +} + +fn md_mono(s: &str) -> String { + format!("`{}`", s) +} + +pub fn typable_commands() -> Result { + let mut md = String::new(); + md.push_str(&md_table_heading(&[ + "Name".to_owned(), + "Description".to_owned(), + ])); + + let cmdify = |s: &str| format!("`:{}`", s); + + for cmd in TYPABLE_COMMAND_LIST { + let names = std::iter::once(&cmd.name) + .chain(cmd.aliases.iter()) + .map(|a| cmdify(a)) + .collect::>() + .join(", "); + + let doc = cmd.doc.replace('\n', "
"); + + md.push_str(&md_table_row(&[names.to_owned(), doc.to_owned()])); + } + + Ok(md) +} + +pub fn lang_features() -> Result { + let mut md = String::new(); + let ts_features = TsFeature::all(); + + let mut cols = vec!["Language".to_owned()]; + cols.append( + &mut ts_features + .iter() + .map(|t| t.long_title().to_string()) + .collect::>(), + ); + cols.push("Default LSP".to_owned()); + + md.push_str(&md_table_heading(&cols)); + let config = helpers::lang_config(); + + let mut langs = config + .language + .iter() + .map(|l| l.language_id.clone()) + .collect::>(); + langs.sort_unstable(); + + let mut ts_features_to_langs = Vec::new(); + for &feat in ts_features { + ts_features_to_langs.push((feat, helpers::ts_lang_support(feat))); + } + + let mut row = Vec::new(); + for lang in langs { + let lc = config + .language + .iter() + .find(|l| l.language_id == lang) + .unwrap(); // lang comes from config + row.push(lc.language_id.clone()); + + for (_feat, support_list) in &ts_features_to_langs { + row.push( + if support_list.contains(&lang) { + "✓" + } else { + "" + } + .to_owned(), + ); + } + row.push( + lc.language_server + .as_ref() + .map(|s| s.command.clone()) + .map(|c| md_mono(&c)) + .unwrap_or_default(), + ); + + md.push_str(&md_table_row(&row)); + row.clear(); + } + + Ok(md) +} + +pub fn write(filename: &str, data: &str) { + let error = format!("Could not write to {}", filename); + let path = paths::book_gen().join(filename); + fs::write(path, data).expect(&error); +} diff --git a/xtask/src/helpers.rs b/xtask/src/helpers.rs new file mode 100644 index 000000000000..345f50bfd133 --- /dev/null +++ b/xtask/src/helpers.rs @@ -0,0 +1,58 @@ +use std::path::{Path, PathBuf}; + +use crate::paths; +use helix_core::syntax::Configuration as LangConfig; +use helix_term::health::TsFeature; + +/// Get the list of languages that support a particular tree-sitter +/// based feature. +pub fn ts_lang_support(feat: TsFeature) -> Vec { + let queries_dir = paths::ts_queries(); + + find_files(&queries_dir, feat.runtime_filename()) + .iter() + .map(|f| { + // .../helix/runtime/queries/python/highlights.scm + let tail = f.strip_prefix(&queries_dir).unwrap(); // python/highlights.scm + let lang = tail.components().next().unwrap(); // python + lang.as_os_str().to_string_lossy().to_string() + }) + .collect() +} + +/// Get the list of languages that have any form of tree-sitter +/// queries defined in the runtime directory. +pub fn langs_with_ts_queries() -> Vec { + std::fs::read_dir(paths::ts_queries()) + .unwrap() + .filter_map(|entry| { + let entry = entry.ok()?; + entry + .file_type() + .ok()? + .is_dir() + .then(|| entry.file_name().to_string_lossy().to_string()) + }) + .collect() +} + +// naive implementation, but suffices for our needs +pub fn find_files(dir: &Path, filename: &str) -> Vec { + std::fs::read_dir(dir) + .unwrap() + .filter_map(|entry| { + let path = entry.ok()?.path(); + if path.is_dir() { + Some(find_files(&path, filename)) + } else { + (path.file_name()?.to_string_lossy() == filename).then(|| vec![path]) + } + }) + .flatten() + .collect() +} + +pub fn lang_config() -> LangConfig { + let bytes = std::fs::read(paths::lang_config()).unwrap(); + toml::from_slice(&bytes).unwrap() +} diff --git a/xtask/src/main.rs b/xtask/src/main.rs index f66fb4f4237a..b4596c8aa645 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,222 +1,30 @@ +mod docgen; +mod helpers; +mod paths; +mod themelint; + use std::{env, error::Error}; type DynError = Box; -pub mod helpers { - use std::path::{Path, PathBuf}; - - use crate::path; - use helix_core::syntax::Configuration as LangConfig; - use helix_term::health::TsFeature; - - /// Get the list of languages that support a particular tree-sitter - /// based feature. - pub fn ts_lang_support(feat: TsFeature) -> Vec { - let queries_dir = path::ts_queries(); - - find_files(&queries_dir, feat.runtime_filename()) - .iter() - .map(|f| { - // .../helix/runtime/queries/python/highlights.scm - let tail = f.strip_prefix(&queries_dir).unwrap(); // python/highlights.scm - let lang = tail.components().next().unwrap(); // python - lang.as_os_str().to_string_lossy().to_string() - }) - .collect() - } - - /// Get the list of languages that have any form of tree-sitter - /// queries defined in the runtime directory. - pub fn langs_with_ts_queries() -> Vec { - std::fs::read_dir(path::ts_queries()) - .unwrap() - .filter_map(|entry| { - let entry = entry.ok()?; - entry - .file_type() - .ok()? - .is_dir() - .then(|| entry.file_name().to_string_lossy().to_string()) - }) - .collect() - } - - // naive implementation, but suffices for our needs - pub fn find_files(dir: &Path, filename: &str) -> Vec { - std::fs::read_dir(dir) - .unwrap() - .filter_map(|entry| { - let path = entry.ok()?.path(); - if path.is_dir() { - Some(find_files(&path, filename)) - } else { - (path.file_name()?.to_string_lossy() == filename).then(|| vec![path]) - } - }) - .flatten() - .collect() - } - - pub fn lang_config() -> LangConfig { - let bytes = std::fs::read(path::lang_config()).unwrap(); - toml::from_slice(&bytes).unwrap() - } -} - -pub mod md_gen { - use crate::DynError; - - use crate::helpers; - use crate::path; - use helix_term::commands::TYPABLE_COMMAND_LIST; - use helix_term::health::TsFeature; - use std::fs; - - pub const TYPABLE_COMMANDS_MD_OUTPUT: &str = "typable-cmd.md"; - pub const LANG_SUPPORT_MD_OUTPUT: &str = "lang-support.md"; - - fn md_table_heading(cols: &[String]) -> String { - let mut header = String::new(); - header += &md_table_row(cols); - header += &md_table_row(&vec!["---".to_string(); cols.len()]); - header - } - - fn md_table_row(cols: &[String]) -> String { - format!("| {} |\n", cols.join(" | ")) - } - - fn md_mono(s: &str) -> String { - format!("`{}`", s) - } - - pub fn typable_commands() -> Result { - let mut md = String::new(); - md.push_str(&md_table_heading(&[ - "Name".to_owned(), - "Description".to_owned(), - ])); - - let cmdify = |s: &str| format!("`:{}`", s); - - for cmd in TYPABLE_COMMAND_LIST { - let names = std::iter::once(&cmd.name) - .chain(cmd.aliases.iter()) - .map(|a| cmdify(a)) - .collect::>() - .join(", "); - - let doc = cmd.doc.replace('\n', "
"); - - md.push_str(&md_table_row(&[names.to_owned(), doc.to_owned()])); - } - - Ok(md) - } - - pub fn lang_features() -> Result { - let mut md = String::new(); - let ts_features = TsFeature::all(); - - let mut cols = vec!["Language".to_owned()]; - cols.append( - &mut ts_features - .iter() - .map(|t| t.long_title().to_string()) - .collect::>(), - ); - cols.push("Default LSP".to_owned()); - - md.push_str(&md_table_heading(&cols)); - let config = helpers::lang_config(); - - let mut langs = config - .language - .iter() - .map(|l| l.language_id.clone()) - .collect::>(); - langs.sort_unstable(); - - let mut ts_features_to_langs = Vec::new(); - for &feat in ts_features { - ts_features_to_langs.push((feat, helpers::ts_lang_support(feat))); - } - - let mut row = Vec::new(); - for lang in langs { - let lc = config - .language - .iter() - .find(|l| l.language_id == lang) - .unwrap(); // lang comes from config - row.push(lc.language_id.clone()); - - for (_feat, support_list) in &ts_features_to_langs { - row.push( - if support_list.contains(&lang) { - "✓" - } else { - "" - } - .to_owned(), - ); - } - row.push( - lc.language_server - .as_ref() - .map(|s| s.command.clone()) - .map(|c| md_mono(&c)) - .unwrap_or_default(), - ); - - md.push_str(&md_table_row(&row)); - row.clear(); - } - - Ok(md) - } - - pub fn write(filename: &str, data: &str) { - let error = format!("Could not write to {}", filename); - let path = path::book_gen().join(filename); - fs::write(path, data).expect(&error); - } -} - -pub mod path { - use std::path::{Path, PathBuf}; - - pub fn project_root() -> PathBuf { - Path::new(env!("CARGO_MANIFEST_DIR")) - .parent() - .unwrap() - .to_path_buf() - } - - pub fn book_gen() -> PathBuf { - project_root().join("book/src/generated/") - } - - pub fn ts_queries() -> PathBuf { - project_root().join("runtime/queries") - } - - pub fn lang_config() -> PathBuf { - project_root().join("languages.toml") - } -} - pub mod tasks { - use crate::md_gen; + use crate::docgen::*; + use crate::themelint::*; use crate::DynError; pub fn docgen() -> Result<(), DynError> { - use md_gen::*; write(TYPABLE_COMMANDS_MD_OUTPUT, &typable_commands()?); write(LANG_SUPPORT_MD_OUTPUT, &lang_features()?); Ok(()) } + pub fn themelint(file: Option) -> Result<(), DynError> { + match file { + Some(file) => lint(file), + None => lint_all(), + } + } + pub fn print_help() { println!( " @@ -224,6 +32,7 @@ Usage: Run with `cargo xtask `, eg. `cargo xtask docgen`. Tasks: docgen: Generate files to be included in the mdbook output. + themelint : Report errors for , or all themes if no theme is specified. " ); } @@ -235,6 +44,7 @@ fn main() -> Result<(), DynError> { None => tasks::print_help(), Some(t) => match t.as_str() { "docgen" => tasks::docgen()?, + "themelint" => tasks::themelint(env::args().nth(2))?, invalid => return Err(format!("Invalid task name: {}", invalid).into()), }, }; diff --git a/xtask/src/paths.rs b/xtask/src/paths.rs new file mode 100644 index 000000000000..6f4545c274aa --- /dev/null +++ b/xtask/src/paths.rs @@ -0,0 +1,24 @@ +use std::path::{Path, PathBuf}; + +pub fn project_root() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .to_path_buf() +} + +pub fn book_gen() -> PathBuf { + project_root().join("book/src/generated/") +} + +pub fn ts_queries() -> PathBuf { + project_root().join("runtime/queries") +} + +pub fn lang_config() -> PathBuf { + project_root().join("languages.toml") +} + +pub fn themes() -> PathBuf { + project_root().join("runtime/themes") +} diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs new file mode 100644 index 000000000000..3a26b9db4913 --- /dev/null +++ b/xtask/src/themelint.rs @@ -0,0 +1,71 @@ +use crate::paths; +use crate::DynError; +use helix_view::theme::Style; +use helix_view::Theme; + +pub fn lint_all() -> Result<(), DynError> { + let files = std::fs::read_dir(paths::themes()) + .unwrap() + .filter_map(|entry| { + let path = entry.ok()?.path(); + if path.is_dir() { + None + } else { + Some(path.file_name()?.to_string_lossy().to_string()) + } + }) + .collect::>(); + let mut errors = vec![]; + files + .into_iter() + .for_each(|path| match lint(path.replace(".toml", "")) { + Err(err) => { + let errs: String = err.to_string(); + errors.push(errs) + } + _ => return, + }); + if errors.len() > 0 { + Err(errors.join(" ").into()) + } else { + Ok(()) + } +} + +pub fn lint(file: String) -> Result<(), DynError> { + let path = paths::themes().join(file + ".toml"); + let theme = std::fs::read(&path).unwrap(); + let theme: Theme = toml::from_slice(&theme).expect("Failed to parse theme"); + let check = vec![ + "ui.background", + "ui.virtual", + "ui.cursor", + "ui.selection", + "ui.linenr", + "ui.text", + "ui.popup", + "ui.window", + "ui.menu", + "ui.statusline", + "ui.cursorline.primary", + ]; + + let lint_errors: Vec = check + .into_iter() + .filter_map(|path| { + let style = theme.get(path); + if style.eq(&Style::default()) { + Some(path.split(".").take(2).collect::>().join(".")) + } else { + None + } + }) + .collect(); + + if lint_errors.len() > 0 { + println!("{:?}", path); + println!("{:?}", lint_errors); + } + + Ok(()) +} From 5a09b77c404c7a7c3f6df14a24d5182ac861b570 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Fri, 29 Jul 2022 00:12:31 +0200 Subject: [PATCH 02/33] fix: add docs and print json error status --- book/src/themes.md | 12 +++++++ xtask/src/themelint.rs | 75 +++++++++++++++++++++++++++++++++++------- 2 files changed, 75 insertions(+), 12 deletions(-) diff --git a/book/src/themes.md b/book/src/themes.md index e03782db3795..f852a05655ce 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -252,4 +252,16 @@ These scopes are used for theming the editor interface. | `diagnostic.warning` | Diagnostics warning (editing area) | | `diagnostic.error` | Diagnostics error (editing area) | +You can check compliance to spec with + +```shell +cargo xtask themelint onedark # replace onedark with +``` + +Find all themes with issues with + +```shell +cargo xtask themelint 2> /dev/null | jq 'keys' +``` + [editor-section]: ./configuration.md#editor-section diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 3a26b9db4913..4b63c61d10e0 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -8,14 +8,17 @@ pub fn lint_all() -> Result<(), DynError> { .unwrap() .filter_map(|entry| { let path = entry.ok()?.path(); - if path.is_dir() { + let name = path.file_name()?.to_string_lossy().to_string(); + if path.is_dir() || name.contains("README") { None } else { - Some(path.file_name()?.to_string_lossy().to_string()) + Some(name) } }) .collect::>(); let mut errors = vec![]; + let files_count = files.len(); + println!("{{"); files .into_iter() .for_each(|path| match lint(path.replace(".toml", "")) { @@ -25,6 +28,11 @@ pub fn lint_all() -> Result<(), DynError> { } _ => return, }); + println!( + "\"status\":\"{} of {} themes had issues\"}}", + errors.len(), + files_count + ); if errors.len() > 0 { Err(errors.join(" ").into()) } else { @@ -33,21 +41,53 @@ pub fn lint_all() -> Result<(), DynError> { } pub fn lint(file: String) -> Result<(), DynError> { - let path = paths::themes().join(file + ".toml"); + let path = paths::themes().join(file.clone() + ".toml"); let theme = std::fs::read(&path).unwrap(); let theme: Theme = toml::from_slice(&theme).expect("Failed to parse theme"); let check = vec![ "ui.background", - "ui.virtual", + "ui.background.separator", "ui.cursor", - "ui.selection", + "ui.cursor.insert", + "ui.cursor.select", + "ui.cursor.match", + "ui.cursor.primary", "ui.linenr", - "ui.text", + "ui.linenr.selected", + "ui.statusline", + "ui.statusline.inactive", + "ui.statusline.normal", + "ui.statusline.insert", + "ui.statusline.select", + "ui.statusline.separator", "ui.popup", + "ui.popup.info", "ui.window", + "ui.help", + "ui.text", + "ui.text.focus", + "ui.text.info", + "ui.virtual.ruler", + "ui.virtual.whitespace", + "ui.virtual.indent-guide", "ui.menu", - "ui.statusline", + "ui.menu.selected", + "ui.menu.scroll", + "ui.selection", + "ui.selection.primary", "ui.cursorline.primary", + //"ui.cursorline.secondary", + "warning", + "error", + "info", + "hint", + "diagnostic", + "diagnostic.hint", + "diagnostic.info", + "diagnostic.warning", + "diagnostic.error", + "markup.raw.inline", + "markup.heading", ]; let lint_errors: Vec = check @@ -55,7 +95,7 @@ pub fn lint(file: String) -> Result<(), DynError> { .filter_map(|path| { let style = theme.get(path); if style.eq(&Style::default()) { - Some(path.split(".").take(2).collect::>().join(".")) + Some(path.to_string()) } else { None } @@ -63,9 +103,20 @@ pub fn lint(file: String) -> Result<(), DynError> { .collect(); if lint_errors.len() > 0 { - println!("{:?}", path); - println!("{:?}", lint_errors); + print!("{:?}:", file); + print_json_arr(lint_errors); + println!(","); + Err(path.to_string_lossy().to_string().into()) + } else { + Ok(()) } - - Ok(()) +} +fn print_json_arr(arr: Vec) { + println!("["); + let mut first = true; + for err in arr { + println!("\t{}\"{}\"", if first { "" } else { "," }, err); + first = false; + } + println!("]"); } From a931e6150764a575ea18184472dd9d9c97aa763d Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Fri, 29 Jul 2022 10:53:56 +0200 Subject: [PATCH 03/33] fix: refactor paths -> path --- xtask/src/docgen.rs | 4 ++-- xtask/src/helpers.rs | 8 ++++---- xtask/src/main.rs | 2 +- xtask/src/{paths.rs => path.rs} | 0 xtask/src/themelint.rs | 6 +++--- 5 files changed, 10 insertions(+), 10 deletions(-) rename xtask/src/{paths.rs => path.rs} (100%) diff --git a/xtask/src/docgen.rs b/xtask/src/docgen.rs index 7fc0235726d7..473882f3ee65 100644 --- a/xtask/src/docgen.rs +++ b/xtask/src/docgen.rs @@ -1,5 +1,5 @@ use crate::helpers; -use crate::paths; +use crate::path; use crate::DynError; use helix_term::commands::TYPABLE_COMMAND_LIST; @@ -112,6 +112,6 @@ pub fn lang_features() -> Result { pub fn write(filename: &str, data: &str) { let error = format!("Could not write to {}", filename); - let path = paths::book_gen().join(filename); + let path = path::book_gen().join(filename); fs::write(path, data).expect(&error); } diff --git a/xtask/src/helpers.rs b/xtask/src/helpers.rs index 345f50bfd133..742039e0a710 100644 --- a/xtask/src/helpers.rs +++ b/xtask/src/helpers.rs @@ -1,13 +1,13 @@ use std::path::{Path, PathBuf}; -use crate::paths; +use crate::path; use helix_core::syntax::Configuration as LangConfig; use helix_term::health::TsFeature; /// Get the list of languages that support a particular tree-sitter /// based feature. pub fn ts_lang_support(feat: TsFeature) -> Vec { - let queries_dir = paths::ts_queries(); + let queries_dir = path::ts_queries(); find_files(&queries_dir, feat.runtime_filename()) .iter() @@ -23,7 +23,7 @@ pub fn ts_lang_support(feat: TsFeature) -> Vec { /// Get the list of languages that have any form of tree-sitter /// queries defined in the runtime directory. pub fn langs_with_ts_queries() -> Vec { - std::fs::read_dir(paths::ts_queries()) + std::fs::read_dir(path::ts_queries()) .unwrap() .filter_map(|entry| { let entry = entry.ok()?; @@ -53,6 +53,6 @@ pub fn find_files(dir: &Path, filename: &str) -> Vec { } pub fn lang_config() -> LangConfig { - let bytes = std::fs::read(paths::lang_config()).unwrap(); + let bytes = std::fs::read(path::lang_config()).unwrap(); toml::from_slice(&bytes).unwrap() } diff --git a/xtask/src/main.rs b/xtask/src/main.rs index b4596c8aa645..403a493a8060 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,6 +1,6 @@ mod docgen; mod helpers; -mod paths; +mod path; mod themelint; use std::{env, error::Error}; diff --git a/xtask/src/paths.rs b/xtask/src/path.rs similarity index 100% rename from xtask/src/paths.rs rename to xtask/src/path.rs diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 4b63c61d10e0..b29da281f995 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -1,10 +1,10 @@ -use crate::paths; +use crate::path; use crate::DynError; use helix_view::theme::Style; use helix_view::Theme; pub fn lint_all() -> Result<(), DynError> { - let files = std::fs::read_dir(paths::themes()) + let files = std::fs::read_dir(path::themes()) .unwrap() .filter_map(|entry| { let path = entry.ok()?.path(); @@ -41,7 +41,7 @@ pub fn lint_all() -> Result<(), DynError> { } pub fn lint(file: String) -> Result<(), DynError> { - let path = paths::themes().join(file.clone() + ".toml"); + let path = path::themes().join(file.clone() + ".toml"); let theme = std::fs::read(&path).unwrap(); let theme: Theme = toml::from_slice(&theme).expect("Failed to parse theme"); let check = vec![ From b90f318d84331c7de846c7e0cd5e8fc5dc6395ef Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Sun, 31 Jul 2022 00:46:43 +0200 Subject: [PATCH 04/33] fix: remove unused function --- xtask/src/helpers.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/xtask/src/helpers.rs b/xtask/src/helpers.rs index 742039e0a710..07970507ffff 100644 --- a/xtask/src/helpers.rs +++ b/xtask/src/helpers.rs @@ -20,22 +20,6 @@ pub fn ts_lang_support(feat: TsFeature) -> Vec { .collect() } -/// Get the list of languages that have any form of tree-sitter -/// queries defined in the runtime directory. -pub fn langs_with_ts_queries() -> Vec { - std::fs::read_dir(path::ts_queries()) - .unwrap() - .filter_map(|entry| { - let entry = entry.ok()?; - entry - .file_type() - .ok()? - .is_dir() - .then(|| entry.file_name().to_string_lossy().to_string()) - }) - .collect() -} - // naive implementation, but suffices for our needs pub fn find_files(dir: &Path, filename: &str) -> Vec { std::fs::read_dir(dir) From a11bc22871ae77d7832a64b40b7a985f57d2ac44 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Sun, 31 Jul 2022 14:29:16 +0200 Subject: [PATCH 05/33] fix: only report one err per scope (ui.statusline is reported if none of ui.statusline.* is recognized) --- xtask/src/themelint.rs | 118 ++++++++++++++++++++++++----------------- 1 file changed, 68 insertions(+), 50 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index b29da281f995..24547f0b6c06 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -45,61 +45,79 @@ pub fn lint(file: String) -> Result<(), DynError> { let theme = std::fs::read(&path).unwrap(); let theme: Theme = toml::from_slice(&theme).expect("Failed to parse theme"); let check = vec![ - "ui.background", - "ui.background.separator", - "ui.cursor", - "ui.cursor.insert", - "ui.cursor.select", - "ui.cursor.match", - "ui.cursor.primary", - "ui.linenr", - "ui.linenr.selected", - "ui.statusline", - "ui.statusline.inactive", - "ui.statusline.normal", - "ui.statusline.insert", - "ui.statusline.select", - "ui.statusline.separator", - "ui.popup", - "ui.popup.info", - "ui.window", - "ui.help", - "ui.text", - "ui.text.focus", - "ui.text.info", - "ui.virtual.ruler", - "ui.virtual.whitespace", - "ui.virtual.indent-guide", - "ui.menu", - "ui.menu.selected", - "ui.menu.scroll", - "ui.selection", - "ui.selection.primary", - "ui.cursorline.primary", - //"ui.cursorline.secondary", - "warning", - "error", - "info", - "hint", - "diagnostic", - "diagnostic.hint", - "diagnostic.info", - "diagnostic.warning", - "diagnostic.error", - "markup.raw.inline", - "markup.heading", + vec!["ui.background", "ui.background.separator"], + vec![ + "ui.cursor", + "ui.cursor.insert", + "ui.cursor.select", + "ui.cursor.match", + "ui.cursor.primary", + ], + vec!["ui.linenr", "ui.linenr.selected"], + vec![ + "ui.statusline", + "ui.statusline.inactive", + "ui.statusline.normal", + "ui.statusline.insert", + "ui.statusline.select", + "ui.statusline.separator", + ], + vec!["ui.popup", "ui.popup.info"], + vec!["ui.window"], + vec!["ui.help"], + vec!["ui.text"], + vec!["ui.text.focus", "ui.text.info"], + vec![ + "ui.virtual", + "ui.virtual.ruler", + "ui.virtual.whitespace", + "ui.virtual.indent-guide", + ], + vec!["ui.menu", "ui.menu.selected", "ui.menu.scroll"], + vec!["ui.selection", "ui.selection.primary"], + vec![ + "ui.cursorline", + "ui.cursorline.primary", + "ui.cursorline.secondary", + ], + vec!["warning"], + vec!["error"], + vec!["info"], + vec!["hint"], + vec![ + "diagnostic", + "diagnostic.hint", + "diagnostic.info", + "diagnostic.warning", + "diagnostic.error", + ], + vec!["markup.raw.inline", "markup.heading"], ]; + struct ScopeWithError { + error: bool, + scope: String, + } let lint_errors: Vec = check .into_iter() - .filter_map(|path| { - let style = theme.get(path); - if style.eq(&Style::default()) { - Some(path.to_string()) - } else { - None - } + .map(|oneof| { + oneof.into_iter().fold( + ScopeWithError { + error: false, + scope: String::new(), + }, + |mut acc, path| { + let style = theme.get(path); + if !style.eq(&Style::default()) { + acc.error = true; + } else if acc.scope.len() == 0 { + acc.scope = path.to_string(); + } + acc + }, + ) }) + .filter_map(|s| if !s.error { Some(s.scope) } else { None }) .collect(); if lint_errors.len() > 0 { From b4edea4bf13415cdb4fd38033c991393e0d450fa Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Thu, 4 Aug 2022 08:26:03 +0200 Subject: [PATCH 06/33] fix: save work for later --- xtask/src/themelint.rs | 63 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 3 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 24547f0b6c06..b9ace0817116 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -1,8 +1,11 @@ use crate::path; use crate::DynError; +use helix_view::theme::Color; use helix_view::theme::Style; use helix_view::Theme; +const CONTRAST_REQUIRED: f64 = 2.; + pub fn lint_all() -> Result<(), DynError> { let files = std::fs::read_dir(path::themes()) .unwrap() @@ -93,9 +96,59 @@ pub fn lint(file: String) -> Result<(), DynError> { ], vec!["markup.raw.inline", "markup.heading"], ]; + + let lumin_color = |c: Color| -> i64 { + println!("{:?}", c); + match c { + Color::Black => 1, + _ => 1000, + } + }; + let lumin = |r: u8, g: u8, b: u8| -> f64 { + (0.2126 * r as f64) + (0.7152 * g as f64) + (0.0722 * b as f64) * 1000. + 1. + }; + let get_fg = |s: Style| -> Color { s.fg.expect("Must have fg") }; + let get_bg = |s: Style| -> Color { s.bg.expect("Must have bg") }; + let lint_rules = vec![ + (("ui.text", get_fg), ("ui.background", get_bg)), + (("ui.statusline", get_fg), ("ui.statusline", get_bg)), + ]; + + let mut lint_warnings = vec![]; + lint_rules.into_iter().for_each(|rule| { + let from_rule = rule.0; + let from_color = from_rule.1(theme.get(from_rule.0)); + let to_rule = rule.1; + let to_color = to_rule.1(theme.get(to_rule.0)); + let from_lumin = if let Color::Rgb(r, g, b) = from_color { + lumin(r, g, b) as i64 + } else { + lumin_color(from_color) + }; + let to_lumin = if let Color::Rgb(r, g, b) = to_color { + lumin(r, g, b) as i64 + } else { + lumin_color(from_color) + }; + let contrast = std::cmp::max(from_lumin, to_lumin) as f64 + / (std::cmp::min(from_lumin, to_lumin) as f64 + 0.000001); + let mut message = String::from(contrast.to_string()); + if from_lumin == 0 { + message.push_str("from0"); + } + if to_lumin == 0 { + message.push_str("to0"); + } + if from_lumin != 0 && to_lumin != 0 && contrast < CONTRAST_REQUIRED { + message.push_str("LOW") + } + lint_warnings.push(message); + }); + println!("{:?}", lint_warnings); struct ScopeWithError { error: bool, scope: String, + messages: Vec, } let lint_errors: Vec = check @@ -105,19 +158,22 @@ pub fn lint(file: String) -> Result<(), DynError> { ScopeWithError { error: false, scope: String::new(), + messages: Vec::new(), }, |mut acc, path| { let style = theme.get(path); - if !style.eq(&Style::default()) { + if style.eq(&Style::default()) { acc.error = true; - } else if acc.scope.len() == 0 { + } + if acc.scope.len() == 0 { acc.scope = path.to_string(); } + acc }, ) }) - .filter_map(|s| if !s.error { Some(s.scope) } else { None }) + .filter_map(|s| if s.error { Some(s.scope) } else { None }) .collect(); if lint_errors.len() > 0 { @@ -129,6 +185,7 @@ pub fn lint(file: String) -> Result<(), DynError> { Ok(()) } } + fn print_json_arr(arr: Vec) { println!("["); let mut first = true; From 7ccb8169848746df71ee4e1108e437e0be8c3348 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Thu, 25 Aug 2022 21:53:39 +0200 Subject: [PATCH 07/33] fix: finally decided on a design --- xtask/src/themelint.rs | 230 +++++++++++++---------------------------- 1 file changed, 73 insertions(+), 157 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index b9ace0817116..a0195bedb3f2 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -1,10 +1,80 @@ use crate::path; use crate::DynError; -use helix_view::theme::Color; -use helix_view::theme::Style; use helix_view::Theme; -const CONTRAST_REQUIRED: f64 = 2.; +struct Rule { + fg: Option, + bg: Option, +} + +// Placed in an fn here, so it's the first thing you see +fn get_rules() -> Vec { + vec![ + Rule::has_fg_bg("ui.text".into(), "ui.background".into()), + Rule::has_both("ui.statusline".into()), + Rule::has_bg("ui.virtual.ruler".into()), + ] +} + +impl Rule { + fn has_fg_bg(fg: String, bg: String) -> Rule { + Rule { + fg: Some(fg), + bg: Some(bg), + } + } + fn has_bg(bg: String) -> Rule { + Rule { + fg: None, + bg: Some(bg), + } + } + fn has_both(item: String) -> Rule { + Rule { + fg: Some(item.clone()), + bg: Some(item), + } + } + fn validate(&self, theme: &Theme, messages: &mut Vec) { + if let Some(fg) = &self.fg { + if theme.get(fg).fg.is_none() { + messages.push(format!("{}.fg", fg.clone())); + } + } + if let Some(bg) = &self.bg { + if theme.get(bg).bg.is_none() { + messages.push(format!("{}.bg", bg.clone())); + } + } + } +} + +pub fn lint(file: String) -> Result<(), DynError> { + let path = path::themes().join(file.clone() + ".toml"); + let theme = std::fs::read(&path).unwrap(); + let theme: Theme = toml::from_slice(&theme).expect("Failed to parse theme"); + + let mut messages: Vec = vec![]; + get_rules() + .iter() + .for_each(|rule| rule.validate(&theme, &mut messages)); + + if messages.len() > 0 { + Err(messages + .iter() + .map(|m| { + let mut msg = file.clone(); + msg.push_str("."); + msg.push_str(m); + msg + }) + .collect::>() + .join(" ") + .into()) + } else { + Ok(()) + } +} pub fn lint_all() -> Result<(), DynError> { let files = std::fs::read_dir(path::themes()) @@ -21,7 +91,6 @@ pub fn lint_all() -> Result<(), DynError> { .collect::>(); let mut errors = vec![]; let files_count = files.len(); - println!("{{"); files .into_iter() .for_each(|path| match lint(path.replace(".toml", "")) { @@ -42,156 +111,3 @@ pub fn lint_all() -> Result<(), DynError> { Ok(()) } } - -pub fn lint(file: String) -> Result<(), DynError> { - let path = path::themes().join(file.clone() + ".toml"); - let theme = std::fs::read(&path).unwrap(); - let theme: Theme = toml::from_slice(&theme).expect("Failed to parse theme"); - let check = vec![ - vec!["ui.background", "ui.background.separator"], - vec![ - "ui.cursor", - "ui.cursor.insert", - "ui.cursor.select", - "ui.cursor.match", - "ui.cursor.primary", - ], - vec!["ui.linenr", "ui.linenr.selected"], - vec![ - "ui.statusline", - "ui.statusline.inactive", - "ui.statusline.normal", - "ui.statusline.insert", - "ui.statusline.select", - "ui.statusline.separator", - ], - vec!["ui.popup", "ui.popup.info"], - vec!["ui.window"], - vec!["ui.help"], - vec!["ui.text"], - vec!["ui.text.focus", "ui.text.info"], - vec![ - "ui.virtual", - "ui.virtual.ruler", - "ui.virtual.whitespace", - "ui.virtual.indent-guide", - ], - vec!["ui.menu", "ui.menu.selected", "ui.menu.scroll"], - vec!["ui.selection", "ui.selection.primary"], - vec![ - "ui.cursorline", - "ui.cursorline.primary", - "ui.cursorline.secondary", - ], - vec!["warning"], - vec!["error"], - vec!["info"], - vec!["hint"], - vec![ - "diagnostic", - "diagnostic.hint", - "diagnostic.info", - "diagnostic.warning", - "diagnostic.error", - ], - vec!["markup.raw.inline", "markup.heading"], - ]; - - let lumin_color = |c: Color| -> i64 { - println!("{:?}", c); - match c { - Color::Black => 1, - _ => 1000, - } - }; - let lumin = |r: u8, g: u8, b: u8| -> f64 { - (0.2126 * r as f64) + (0.7152 * g as f64) + (0.0722 * b as f64) * 1000. + 1. - }; - let get_fg = |s: Style| -> Color { s.fg.expect("Must have fg") }; - let get_bg = |s: Style| -> Color { s.bg.expect("Must have bg") }; - let lint_rules = vec![ - (("ui.text", get_fg), ("ui.background", get_bg)), - (("ui.statusline", get_fg), ("ui.statusline", get_bg)), - ]; - - let mut lint_warnings = vec![]; - lint_rules.into_iter().for_each(|rule| { - let from_rule = rule.0; - let from_color = from_rule.1(theme.get(from_rule.0)); - let to_rule = rule.1; - let to_color = to_rule.1(theme.get(to_rule.0)); - let from_lumin = if let Color::Rgb(r, g, b) = from_color { - lumin(r, g, b) as i64 - } else { - lumin_color(from_color) - }; - let to_lumin = if let Color::Rgb(r, g, b) = to_color { - lumin(r, g, b) as i64 - } else { - lumin_color(from_color) - }; - let contrast = std::cmp::max(from_lumin, to_lumin) as f64 - / (std::cmp::min(from_lumin, to_lumin) as f64 + 0.000001); - let mut message = String::from(contrast.to_string()); - if from_lumin == 0 { - message.push_str("from0"); - } - if to_lumin == 0 { - message.push_str("to0"); - } - if from_lumin != 0 && to_lumin != 0 && contrast < CONTRAST_REQUIRED { - message.push_str("LOW") - } - lint_warnings.push(message); - }); - println!("{:?}", lint_warnings); - struct ScopeWithError { - error: bool, - scope: String, - messages: Vec, - } - - let lint_errors: Vec = check - .into_iter() - .map(|oneof| { - oneof.into_iter().fold( - ScopeWithError { - error: false, - scope: String::new(), - messages: Vec::new(), - }, - |mut acc, path| { - let style = theme.get(path); - if style.eq(&Style::default()) { - acc.error = true; - } - if acc.scope.len() == 0 { - acc.scope = path.to_string(); - } - - acc - }, - ) - }) - .filter_map(|s| if s.error { Some(s.scope) } else { None }) - .collect(); - - if lint_errors.len() > 0 { - print!("{:?}:", file); - print_json_arr(lint_errors); - println!(","); - Err(path.to_string_lossy().to_string().into()) - } else { - Ok(()) - } -} - -fn print_json_arr(arr: Vec) { - println!("["); - let mut first = true; - for err in arr { - println!("\t{}\"{}\"", if first { "" } else { "," }, err); - first = false; - } - println!("]"); -} From 10cda9877120e64d435216ff794911dbfff53376 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Thu, 25 Aug 2022 23:22:52 +0200 Subject: [PATCH 08/33] fix: ready for discussion --- book/src/themes.md | 6 ---- xtask/src/themelint.rs | 77 +++++++++++++++++++++++++++++++++++------- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/book/src/themes.md b/book/src/themes.md index 8047c404252e..048796fba811 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -260,10 +260,4 @@ You can check compliance to spec with cargo xtask themelint onedark # replace onedark with ``` -Find all themes with issues with - -```shell -cargo xtask themelint 2> /dev/null | jq 'keys' -``` - [editor-section]: ./configuration.md#editor-section diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index a0195bedb3f2..c6cd0ef9ff24 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -1,18 +1,36 @@ use crate::path; use crate::DynError; +use helix_view::theme::Modifier; use helix_view::Theme; struct Rule { fg: Option, bg: Option, + check_both: bool, } // Placed in an fn here, so it's the first thing you see fn get_rules() -> Vec { vec![ + // Check for ui.selection, which is required + Rule::has_either("ui.selection".into()), + // Check for planned readable text Rule::has_fg_bg("ui.text".into(), "ui.background".into()), + // Check for complete editor.statusline bare minimum Rule::has_both("ui.statusline".into()), + // Check for editor.color-modes + Rule::has_either("ui.statusline.insert".into()), + Rule::has_either("ui.statusline.normal".into()), + Rule::has_either("ui.statusline.select".into()), + // Check for editor.cursorline + Rule::has_bg("ui.cursorline".into()), + // Check for editor.rulers Rule::has_bg("ui.virtual.ruler".into()), + // Check for menus and prompts + Rule::has_both("ui.menu".into()), + // Check for visible cursor + Rule::has_bg("ui.cursor.primary".into()), + Rule::has_bg("ui.cursor.match".into()), ] } @@ -21,29 +39,64 @@ impl Rule { Rule { fg: Some(fg), bg: Some(bg), + check_both: true, } } fn has_bg(bg: String) -> Rule { Rule { fg: None, bg: Some(bg), + check_both: true, + } + } + fn has_fg(fg: String) -> Rule { + Rule { + fg: Some(fg), + bg: None, + check_both: true, + } + } + fn has_either(item: String) -> Rule { + Rule { + fg: Some(item.clone()), + bg: Some(item), + check_both: false, } } fn has_both(item: String) -> Rule { Rule { fg: Some(item.clone()), bg: Some(item), + check_both: true, } } fn validate(&self, theme: &Theme, messages: &mut Vec) { + let mut found_fg = true; + let mut found_bg = true; + let mut fg_name = ""; + let mut bg_name = ""; if let Some(fg) = &self.fg { - if theme.get(fg).fg.is_none() { - messages.push(format!("{}.fg", fg.clone())); + fg_name = fg; + if theme.get(fg).fg.is_none() && theme.get(fg).add_modifier == Modifier::empty() { + found_fg = false; } } if let Some(bg) = &self.bg { - if theme.get(bg).bg.is_none() { - messages.push(format!("{}.bg", bg.clone())); + bg_name = bg; + if theme.get(bg).bg.is_none() && theme.get(bg).add_modifier == Modifier::empty() { + found_bg = false; + } + } + if self.check_both { + if !found_fg { + messages.push(format!("{}.fg", fg_name.clone())); + } + if !found_bg { + messages.push(format!("{}.bg", bg_name.clone())); + } + } else { + if !found_fg && !found_bg { + messages.push(format!("{}", fg_name)) } } } @@ -60,7 +113,7 @@ pub fn lint(file: String) -> Result<(), DynError> { .for_each(|rule| rule.validate(&theme, &mut messages)); if messages.len() > 0 { - Err(messages + let message: String = messages .iter() .map(|m| { let mut msg = file.clone(); @@ -70,7 +123,9 @@ pub fn lint(file: String) -> Result<(), DynError> { }) .collect::>() .join(" ") - .into()) + .into(); + println!("{}", message.replace(" ", "\n")); + Err(messages.len().to_string().into()) } else { Ok(()) } @@ -95,18 +150,14 @@ pub fn lint_all() -> Result<(), DynError> { .into_iter() .for_each(|path| match lint(path.replace(".toml", "")) { Err(err) => { - let errs: String = err.to_string(); + let errs: i32 = err.to_string().parse().expect("Errors must be integral"); errors.push(errs) } _ => return, }); - println!( - "\"status\":\"{} of {} themes had issues\"}}", - errors.len(), - files_count - ); + println!("{} of {} themes had issues", errors.len(), files_count); if errors.len() > 0 { - Err(errors.join(" ").into()) + Err(errors.iter().sum::().to_string().into()) } else { Ok(()) } From 943c4217289020967287d12b17a74aa66e9e48cc Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Sun, 28 Aug 2022 00:20:06 +0200 Subject: [PATCH 09/33] fix: better rules --- xtask/src/themelint.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index c6cd0ef9ff24..f3138990685a 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -18,19 +18,23 @@ fn get_rules() -> Vec { Rule::has_fg_bg("ui.text".into(), "ui.background".into()), // Check for complete editor.statusline bare minimum Rule::has_both("ui.statusline".into()), + Rule::has_both("ui.statusline.inactive".into()), // Check for editor.color-modes Rule::has_either("ui.statusline.insert".into()), Rule::has_either("ui.statusline.normal".into()), Rule::has_either("ui.statusline.select".into()), // Check for editor.cursorline - Rule::has_bg("ui.cursorline".into()), + Rule::has_bg("ui.cursorline.primary".into()), // Check for editor.rulers - Rule::has_bg("ui.virtual.ruler".into()), + Rule::has_either("ui.virtual.ruler".into()), // Check for menus and prompts Rule::has_both("ui.menu".into()), + Rule::has_bg("ui.help".into()), + Rule::has_bg("ui.popup".into()), + Rule::has_either("ui.window".into()), // Check for visible cursor Rule::has_bg("ui.cursor.primary".into()), - Rule::has_bg("ui.cursor.match".into()), + Rule::has_either("ui.cursor.match".into()), ] } @@ -103,6 +107,10 @@ impl Rule { } pub fn lint(file: String) -> Result<(), DynError> { + if file.contains("base16") { + println!("Skipping base16: {}", file); + return Ok(()); + } let path = path::themes().join(file.clone() + ".toml"); let theme = std::fs::read(&path).unwrap(); let theme: Theme = toml::from_slice(&theme).expect("Failed to parse theme"); From 16a5f87be30d9f72e3a0943e8d691e2fd37f8f85 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Mon, 29 Aug 2022 08:12:24 +0200 Subject: [PATCH 10/33] fix: lint precision --- xtask/src/themelint.rs | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index f3138990685a..8d86d81be615 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -15,7 +15,8 @@ fn get_rules() -> Vec { // Check for ui.selection, which is required Rule::has_either("ui.selection".into()), // Check for planned readable text - Rule::has_fg_bg("ui.text".into(), "ui.background".into()), + Rule::has_fg("ui.text".into()), + Rule::has_bg("ui.background".into()), // Check for complete editor.statusline bare minimum Rule::has_both("ui.statusline".into()), Rule::has_both("ui.statusline.inactive".into()), @@ -29,7 +30,7 @@ fn get_rules() -> Vec { Rule::has_either("ui.virtual.ruler".into()), // Check for menus and prompts Rule::has_both("ui.menu".into()), - Rule::has_bg("ui.help".into()), + Rule::has_both("ui.help".into()), Rule::has_bg("ui.popup".into()), Rule::has_either("ui.window".into()), // Check for visible cursor @@ -39,13 +40,6 @@ fn get_rules() -> Vec { } impl Rule { - fn has_fg_bg(fg: String, bg: String) -> Rule { - Rule { - fg: Some(fg), - bg: Some(bg), - check_both: true, - } - } fn has_bg(bg: String) -> Rule { Rule { fg: None, From 336e9018076c4616a52affa526662347f2fe1dc2 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Mon, 29 Aug 2022 16:06:54 +0200 Subject: [PATCH 11/33] fix: String -> &'static str --- xtask/src/themelint.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 8d86d81be615..ab879f071665 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -4,8 +4,8 @@ use helix_view::theme::Modifier; use helix_view::Theme; struct Rule { - fg: Option, - bg: Option, + fg: Option<&'static str>, + bg: Option<&'static str>, check_both: bool, } @@ -40,28 +40,28 @@ fn get_rules() -> Vec { } impl Rule { - fn has_bg(bg: String) -> Rule { + fn has_bg(bg: &'static str) -> Rule { Rule { fg: None, bg: Some(bg), check_both: true, } } - fn has_fg(fg: String) -> Rule { + fn has_fg(fg: &'static str) -> Rule { Rule { fg: Some(fg), bg: None, check_both: true, } } - fn has_either(item: String) -> Rule { + fn has_either(item: &'static str) -> Rule { Rule { fg: Some(item.clone()), bg: Some(item), check_both: false, } } - fn has_both(item: String) -> Rule { + fn has_both(item: &'static str) -> Rule { Rule { fg: Some(item.clone()), bg: Some(item), From 90ca345d0e1f165f74f5bc0c865e96d05d4c5c82 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Mon, 29 Aug 2022 16:10:31 +0200 Subject: [PATCH 12/33] fix: allowlist not denylist for file type --- xtask/src/themelint.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index ab879f071665..6f7d0d10959d 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -139,10 +139,10 @@ pub fn lint_all() -> Result<(), DynError> { .filter_map(|entry| { let path = entry.ok()?.path(); let name = path.file_name()?.to_string_lossy().to_string(); - if path.is_dir() || name.contains("README") { - None - } else { + if path.extension().unwrap() == "toml" { Some(name) + } else { + None } }) .collect::>(); From d160366947b2acccd44f1b6b1f9ac1b4d77b9aeb Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Mon, 29 Aug 2022 16:16:12 +0200 Subject: [PATCH 13/33] fix: add missing and indication of what's needed --- xtask/src/themelint.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 6f7d0d10959d..1a0cf35f87f5 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -87,14 +87,14 @@ impl Rule { } if self.check_both { if !found_fg { - messages.push(format!("{}.fg", fg_name.clone())); + messages.push(format!("{}={{\"fg\"=\"missing\"}}", fg_name.clone())); } if !found_bg { - messages.push(format!("{}.bg", bg_name.clone())); + messages.push(format!("{}={{\"bg\"=\"missing\"}}", bg_name.clone())); } } else { if !found_fg && !found_bg { - messages.push(format!("{}", fg_name)) + messages.push(format!("{}=\"missing\"", fg_name)) } } } From 6ffba6bfd2696fb8412c4b3fc26df43948fe4491 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Mon, 29 Aug 2022 16:20:26 +0200 Subject: [PATCH 14/33] fix: copy pasteable errors --- xtask/src/themelint.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 1a0cf35f87f5..8c0045577bc5 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -87,14 +87,14 @@ impl Rule { } if self.check_both { if !found_fg { - messages.push(format!("{}={{\"fg\"=\"missing\"}}", fg_name.clone())); + messages.push(format!("\"{}\"={{\"fg\"=\"missing\"}}", fg_name.clone())); } if !found_bg { - messages.push(format!("{}={{\"bg\"=\"missing\"}}", bg_name.clone())); + messages.push(format!("\"{}\"={{\"bg\"=\"missing\"}}", bg_name.clone())); } } else { if !found_fg && !found_bg { - messages.push(format!("{}=\"missing\"", fg_name)) + messages.push(format!("\"{}\"=\"missing\"", fg_name)) } } } @@ -119,7 +119,7 @@ pub fn lint(file: String) -> Result<(), DynError> { .iter() .map(|m| { let mut msg = file.clone(); - msg.push_str("."); + msg.push_str(":"); msg.push_str(m); msg }) From 237f706edade94a7ba8c8bfd5cccd62892473160 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Mon, 29 Aug 2022 16:24:59 +0200 Subject: [PATCH 15/33] fix: use Loader:read_names --- xtask/src/themelint.rs | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 8c0045577bc5..f57ed9bca142 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -1,5 +1,6 @@ use crate::path; use crate::DynError; +use helix_view::theme::Loader; use helix_view::theme::Modifier; use helix_view::Theme; @@ -134,18 +135,7 @@ pub fn lint(file: String) -> Result<(), DynError> { } pub fn lint_all() -> Result<(), DynError> { - let files = std::fs::read_dir(path::themes()) - .unwrap() - .filter_map(|entry| { - let path = entry.ok()?.path(); - let name = path.file_name()?.to_string_lossy().to_string(); - if path.extension().unwrap() == "toml" { - Some(name) - } else { - None - } - }) - .collect::>(); + let files = Loader::read_names(path::themes().as_path()); let mut errors = vec![]; let files_count = files.len(); files From 50662cf5647ca64857a8f8793b5b538a837af897 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Mon, 29 Aug 2022 16:26:33 +0200 Subject: [PATCH 16/33] Update xtask/src/helpers.rs Co-authored-by: Ivan Tham --- xtask/src/helpers.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/xtask/src/helpers.rs b/xtask/src/helpers.rs index 07970507ffff..4f759e74f725 100644 --- a/xtask/src/helpers.rs +++ b/xtask/src/helpers.rs @@ -28,8 +28,10 @@ pub fn find_files(dir: &Path, filename: &str) -> Vec { let path = entry.ok()?.path(); if path.is_dir() { Some(find_files(&path, filename)) + } else if path.file_name()?.to_string_lossy() == filename { + Some(vec![path]) } else { - (path.file_name()?.to_string_lossy() == filename).then(|| vec![path]) + None } }) .flatten() From af2011d88cd25f5467705db4dbbbf93b66c89228 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Wed, 31 Aug 2022 08:13:35 +0200 Subject: [PATCH 17/33] fix: remove into and clone for str --- xtask/src/themelint.rs | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index f57ed9bca142..df88723f0394 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -14,29 +14,29 @@ struct Rule { fn get_rules() -> Vec { vec![ // Check for ui.selection, which is required - Rule::has_either("ui.selection".into()), + Rule::has_either("ui.selection"), // Check for planned readable text - Rule::has_fg("ui.text".into()), - Rule::has_bg("ui.background".into()), + Rule::has_fg("ui.text"), + Rule::has_bg("ui.background"), // Check for complete editor.statusline bare minimum - Rule::has_both("ui.statusline".into()), - Rule::has_both("ui.statusline.inactive".into()), + Rule::has_both("ui.statusline"), + Rule::has_both("ui.statusline.inactive"), // Check for editor.color-modes - Rule::has_either("ui.statusline.insert".into()), - Rule::has_either("ui.statusline.normal".into()), - Rule::has_either("ui.statusline.select".into()), + Rule::has_either("ui.statusline.insert"), + Rule::has_either("ui.statusline.normal"), + Rule::has_either("ui.statusline.select"), // Check for editor.cursorline - Rule::has_bg("ui.cursorline.primary".into()), + Rule::has_bg("ui.cursorline.primary"), // Check for editor.rulers - Rule::has_either("ui.virtual.ruler".into()), + Rule::has_either("ui.virtual.ruler"), // Check for menus and prompts - Rule::has_both("ui.menu".into()), - Rule::has_both("ui.help".into()), - Rule::has_bg("ui.popup".into()), - Rule::has_either("ui.window".into()), + Rule::has_both("ui.menu"), + Rule::has_both("ui.help"), + Rule::has_bg("ui.popup"), + Rule::has_either("ui.window"), // Check for visible cursor - Rule::has_bg("ui.cursor.primary".into()), - Rule::has_either("ui.cursor.match".into()), + Rule::has_bg("ui.cursor.primary"), + Rule::has_either("ui.cursor.match"), ] } @@ -57,14 +57,14 @@ impl Rule { } fn has_either(item: &'static str) -> Rule { Rule { - fg: Some(item.clone()), + fg: Some(item), bg: Some(item), check_both: false, } } fn has_both(item: &'static str) -> Rule { Rule { - fg: Some(item.clone()), + fg: Some(item), bg: Some(item), check_both: true, } @@ -88,10 +88,10 @@ impl Rule { } if self.check_both { if !found_fg { - messages.push(format!("\"{}\"={{\"fg\"=\"missing\"}}", fg_name.clone())); + messages.push(format!("\"{}\"={{\"fg\"=\"missing\"}}", fg_name)); } if !found_bg { - messages.push(format!("\"{}\"={{\"bg\"=\"missing\"}}", bg_name.clone())); + messages.push(format!("\"{}\"={{\"bg\"=\"missing\"}}", bg_name)); } } else { if !found_fg && !found_bg { From 0632c3f1d408175dc105a70d4356b698014884e9 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Wed, 31 Aug 2022 16:19:11 +0200 Subject: [PATCH 18/33] Update book/src/themes.md Co-authored-by: Ivan Tham --- book/src/themes.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/themes.md b/book/src/themes.md index 048796fba811..9908456fca38 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -257,7 +257,7 @@ These scopes are used for theming the editor interface. You can check compliance to spec with ```shell -cargo xtask themelint onedark # replace onedark with +cargo xtask themelint onedark # replace onedark with ``` [editor-section]: ./configuration.md#editor-section From b2f6540f3231efad8f406b6b5579aef0c7c756b5 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Thu, 1 Sep 2022 21:17:21 +0200 Subject: [PATCH 19/33] fix: better lint output --- xtask/src/themelint.rs | 72 ++++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 28 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index df88723f0394..42803a10dfa3 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -69,33 +69,56 @@ impl Rule { check_both: true, } } - fn validate(&self, theme: &Theme, messages: &mut Vec) { - let mut found_fg = true; - let mut found_bg = true; - let mut fg_name = ""; - let mut bg_name = ""; - if let Some(fg) = &self.fg { - fg_name = fg; + fn found_impl(theme: &Theme, find: Option<&'static str>) -> bool { + if let Some(fg) = &find { if theme.get(fg).fg.is_none() && theme.get(fg).add_modifier == Modifier::empty() { - found_fg = false; + return false; } } - if let Some(bg) = &self.bg { - bg_name = bg; - if theme.get(bg).bg.is_none() && theme.get(bg).add_modifier == Modifier::empty() { - found_bg = false; - } + return true; + } + fn found_fg(&self, theme: &Theme) -> bool { + return Rule::found_impl(theme, self.fg); + } + fn found_bg(&self, theme: &Theme) -> bool { + return Rule::found_impl(theme, self.bg); + } + fn rule_name(&self) -> &'static str { + if self.fg.is_some() { + self.fg.unwrap() + } else if self.bg.is_some() { + self.bg.unwrap() + } else { + "LINTER_ERROR_NO_RULE" } + } + + fn validate(&self, theme: &Theme, messages: &mut Vec) { + let mut missing = vec![]; + + let found_fg = self.found_fg(theme); + let found_bg = self.found_bg(theme); if self.check_both { if !found_fg { - messages.push(format!("\"{}\"={{\"fg\"=\"missing\"}}", fg_name)); + missing.push("`fg`"); } if !found_bg { - messages.push(format!("\"{}\"={{\"bg\"=\"missing\"}}", bg_name)); + missing.push("`bg`"); + } + if !found_fg || !found_bg { + messages.push(format!( + "$THEME: missing {} for `{}`", + missing.join(" and "), + self.rule_name() + )); } } else { if !found_fg && !found_bg { - messages.push(format!("\"{}\"=\"missing\"", fg_name)) + messages.push(format!( + "$THEME: missing {} for `{}`", + "entry", + self.rule_name() + )) } } } @@ -116,18 +139,11 @@ pub fn lint(file: String) -> Result<(), DynError> { .for_each(|rule| rule.validate(&theme, &mut messages)); if messages.len() > 0 { - let message: String = messages - .iter() - .map(|m| { - let mut msg = file.clone(); - msg.push_str(":"); - msg.push_str(m); - msg - }) - .collect::>() - .join(" ") - .into(); - println!("{}", message.replace(" ", "\n")); + messages.iter().for_each(|m| { + let theme = file.clone(); + let message = m.replace("$THEME", theme.as_str()); + println!("{}", message); + }); Err(messages.len().to_string().into()) } else { Ok(()) From 1a8d812f5c95201a6ec0f7e53e78cb3ff66dcfce Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Thu, 1 Sep 2022 21:28:21 +0200 Subject: [PATCH 20/33] fix: cleaner logic for lint reporting --- xtask/src/themelint.rs | 31 +++++++++++++------------------ 1 file changed, 13 insertions(+), 18 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 42803a10dfa3..9c23a11b159f 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -94,32 +94,27 @@ impl Rule { } fn validate(&self, theme: &Theme, messages: &mut Vec) { - let mut missing = vec![]; - let found_fg = self.found_fg(theme); let found_bg = self.found_bg(theme); - if self.check_both { + + if !found_fg || !found_bg { + let mut missing = vec![]; if !found_fg { missing.push("`fg`"); } if !found_bg { missing.push("`bg`"); } - if !found_fg || !found_bg { - messages.push(format!( - "$THEME: missing {} for `{}`", - missing.join(" and "), - self.rule_name() - )); - } - } else { - if !found_fg && !found_bg { - messages.push(format!( - "$THEME: missing {} for `{}`", - "entry", - self.rule_name() - )) - } + let entry = if !self.check_both && !found_fg && !found_bg { + missing.join(" or ") + } else { + missing.join(" and ") + }; + messages.push(format!( + "$THEME: missing {} for `{}`", + entry, + self.rule_name() + )) } } } From 1cf35e7f19be9636663fc90cd176efb07848f8e2 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Thu, 1 Sep 2022 21:33:03 +0200 Subject: [PATCH 21/33] style: use explicit imports --- xtask/src/main.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 403a493a8060..22300948e02b 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -8,8 +8,9 @@ use std::{env, error::Error}; type DynError = Box; pub mod tasks { - use crate::docgen::*; - use crate::themelint::*; + use crate::docgen::{lang_features, typable_commands, write}; + use crate::docgen::{LANG_SUPPORT_MD_OUTPUT, TYPABLE_COMMANDS_MD_OUTPUT}; + use crate::themelint::{lint, lint_all}; use crate::DynError; pub fn docgen() -> Result<(), DynError> { From 917aec4716258fe9a044f0652de419e756e2c4bb Mon Sep 17 00:00:00 2001 From: ath3 <45574139+ath3@users.noreply.github.com> Date: Fri, 26 Aug 2022 00:59:02 +0200 Subject: [PATCH 22/33] Pascal support (#3542) --- book/src/generated/lang-support.md | 1 + languages.toml | 14 + runtime/queries/pascal/highlights.scm | 382 +++++++++++++++++++++++++ runtime/queries/pascal/injections.scm | 2 + runtime/queries/pascal/textobjects.scm | 10 + 5 files changed, 409 insertions(+) create mode 100644 runtime/queries/pascal/highlights.scm create mode 100644 runtime/queries/pascal/injections.scm create mode 100644 runtime/queries/pascal/textobjects.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 8c1d820897f9..8d8275ab6383 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -76,6 +76,7 @@ | odin | ✓ | | | `ols` | | openscad | ✓ | | | `openscad-language-server` | | org | ✓ | | | | +| pascal | ✓ | ✓ | | `pasls` | | perl | ✓ | ✓ | ✓ | | | php | ✓ | ✓ | ✓ | `intelephense` | | prisma | ✓ | | | `prisma-language-server` | diff --git a/languages.toml b/languages.toml index 0bcc6ef21b6c..986b927e3a1e 100644 --- a/languages.toml +++ b/languages.toml @@ -1691,3 +1691,17 @@ roots = ["edgedb.toml"] [[grammar]] name ="esdl" source = { git = "https://github.com/greym0uth/tree-sitter-esdl", rev = "b840c8a8028127e0a7c6e6c45141adade2bd75cf" } + +[[language]] +name = "pascal" +scope = "source.pascal" +injection-regex = "pascal" +file-types = ["pas", "pp", "inc", "lpr", "lfm"] +roots = [] +comment-token = "//" +indent = { tab-width = 2, unit = " " } +language-server = { command = "pasls", args = [] } + +[[grammar]] +name = "pascal" +source = { git = "https://github.com/Isopod/tree-sitter-pascal", rev = "2fd40f477d3e2794af152618ccfac8d92eb72a66" } diff --git a/runtime/queries/pascal/highlights.scm b/runtime/queries/pascal/highlights.scm new file mode 100644 index 000000000000..5368a22b87cd --- /dev/null +++ b/runtime/queries/pascal/highlights.scm @@ -0,0 +1,382 @@ +; -- Identifier type inferrence + +; VERY QUESTIONABLE: Highlighting of identifiers based on spelling +(exprBinary ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprUnary ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(assignment rhs: ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprBrackets ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprParens ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprDot rhs: ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprTpl args: ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(exprArgs ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(declEnumValue ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) +(defaultValue ((identifier) @constant + (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) + +; -- Break, Continue & Exit +; (Not ideal: ideally, there would be a way to check if these special +; identifiers are shadowed by a local variable) +(statement ((identifier) @keyword.control.return + (#match? @keyword.control.return "^[eE][xX][iI][tT]$"))) +(statement (exprCall entity: ((identifier) @keyword.control.return + (#match? @keyword.control.return "^[eE][xX][iI][tT]$")))) +(statement ((identifier) @keyword.control.repeat + (#match? @keyword.control.repeat "^[bB][rR][eE][aA][kK]$"))) +(statement ((identifier) @keyword.control.repeat + (#match? @keyword.control.repeat "^[cC][oO][nN][tT][iI][nN][uU][eE]$"))) + +; -- Heuristic for procedure/function calls without parentheses +; (If a statement consists only of an identifier, assume it's a procedure) +; (This will still not match all procedure calls, and also may produce false +; positives in rare cases, but only for nonsensical code) + +(statement (exprDot rhs: (exprTpl entity: (identifier) @function))) +(statement (exprTpl entity: (identifier) @function)) +(statement (exprDot rhs: (identifier) @function)) +(statement (identifier) @function) + +; -- Procedure name in calls with parentheses +; (Pascal doesn't require parentheses for procedure calls, so this will not +; detect all calls) + +(inherited) @function + +; foo.bar +(exprCall entity: (exprDot rhs: (exprTpl entity: (identifier) @function))) +; foo.bar +(exprCall entity: (exprDot rhs: (identifier) @function)) +; foobar +(exprCall entity: (exprTpl entity: (identifier) @function)) +; foobar +(exprCall entity: (identifier) @function) + +; -- Fields + +(declSection (declVars (declVar name:(identifier) @variable.other.member))) +(declSection (declField name:(identifier) @variable.other.member)) +(declClass (declField name:(identifier) @variable.other.member)) +(exprDot rhs: (exprDot) @variable.other.member) +(exprDot rhs: (identifier) @variable.other.member) + +(recInitializerField name:(identifier) @variable.other.member) + +; -- Variable & constant declarations +; (This is only questionable because we cannot detect types of identifiers +; declared in other units, so the results will be inconsistent) + +(declVar name: (identifier) @variable) +(declConst name: (identifier) @constant) +(declEnumValue name: (identifier) @constant) + +; -- Constant usage + +[ + (caseLabel) + (label) +] @constant + +(procAttribute (identifier) @constant) +(procExternal (identifier) @constant) + +; -- Type usage + +(typeref) @type + +; -- Exception parameters + +(exceptionHandler variable: (identifier) @variable.parameter) + +; -- Template parameters + +(genericArg type: (typeref) @type) +(genericArg name: (identifier) @variable.parameter) + +(declProc name: (genericDot lhs: (identifier) @type)) +(declType (genericDot (identifier) @type)) + +(genericDot (genericTpl (identifier) @type)) +(genericDot (genericDot (identifier) @type)) + +(genericTpl entity: (genericDot (identifier) @type)) +(genericTpl entity: (identifier) @type) + +; -- Function parameters + +(declArg name: (identifier) @variable.parameter) + +; Treat property declarations like functions + +(declProp name: (identifier) @function) +(declProp getter: (identifier) @variable.other.member) +(declProp setter: (identifier) @variable.other.member) + +; -- Procedure & function declarations + +; foo.bar +(declProc name: (genericDot rhs: (genericTpl entity: (identifier) @function))) +; foo.bar +(declProc name: (genericDot rhs: (identifier) @function)) +; foobar +(declProc name: (genericTpl entity: (identifier) @function)) +; foobar +(declProc name: (identifier) @function) + +; -- Type declaration + +(declType name: (genericTpl entity: (identifier) @type)) +(declType name: (identifier) @type) + +; -- Comments + +(comment) @comment +(pp) @function.macro + +; -- Variables + +(exprBinary (identifier) @variable) +(exprUnary (identifier) @variable) +(assignment (identifier) @variable) +(exprBrackets (identifier) @variable) +(exprParens (identifier) @variable) +(exprDot (identifier) @variable) +(exprTpl (identifier) @variable) +(exprArgs (identifier) @variable) +(defaultValue (identifier) @variable) + +; -- Literals + +(literalNumber) @constant.builtin.numeric +(literalString) @string + +; -- Builtin constants + +[ + (kTrue) + (kFalse) +] @constant.builtin.boolean + +[ + (kNil) +] @constant.builtin + +; -- Punctuation & operators + +[ + (kOr) + (kXor) + (kDiv) + (kMod) + (kAnd) + (kShl) + (kShr) + (kNot) + (kIs) + (kAs) + (kIn) +] @keyword.operator + +[ + (kDot) + (kAdd) + (kSub) + (kMul) + (kFdiv) + (kAssign) + (kAssignAdd) + (kAssignSub) + (kAssignMul) + (kAssignDiv) + (kEq) + (kLt) + (kLte) + (kGt) + (kGte) + (kNeq) + (kAt) + (kHat) +] @operator + +[ + ".." +] @punctuation.special + +[ + ";" + "," + ":" + (kEndDot) +] @punctuation.delimiter + +[ + "(" + ")" + "[" + "]" +] @punctuation.bracket + +; -- Attributes + +(procAttribute (kPublic) @attribute) + +[ + (kDefault) + (kIndex) + (kNodefault) + (kStored) + + (kStatic) + (kVirtual) + (kAbstract) + (kSealed) + (kDynamic) + (kOverride) + (kOverload) + (kReintroduce) + (kInline) + + (kForward) + + (kStdcall) + (kCdecl) + (kCppdecl) + (kPascal) + (kRegister) + (kMwpascal) + (kExternal) + (kName) + (kMessage) + (kDeprecated) + (kExperimental) + (kPlatform) + (kUnimplemented) + (kCvar) + (kExport) + (kFar) + (kNear) + (kSafecall) + (kAssembler) + (kNostackframe) + (kInterrupt) + (kNoreturn) + (kIocheck) + (kLocal) + (kHardfloat) + (kSoftfloat) + (kMs_abi_default) + (kMs_abi_cdecl) + (kSaveregisters) + (kSysv_abi_default) + (kSysv_abi_cdecl) + (kVectorcall) + (kVarargs) + (kWinapi) + (kAlias) + (kDelayed) + + (rttiAttributes) + (procAttribute) + +] @attribute + +; -- Keywords +[ + (kProgram) + (kLibrary) + (kUnit) + (kUses) + + (kBegin) + (kEnd) + (kAsm) + + (kVar) + (kThreadvar) + (kConst) + (kResourcestring) + (kConstref) + (kOut) + (kType) + (kLabel) + (kExports) + + (kAbsolute) + + (kProperty) + (kRead) + (kWrite) + (kImplements) + + (kClass) + (kInterface) + (kObject) + (kRecord) + (kObjcclass) + (kObjccategory) + (kObjcprotocol) + (kArray) + (kFile) + (kString) + (kSet) + (kOf) + (kHelper) + (kPacked) + + (kInherited) + + (kGeneric) + (kSpecialize) + + (kFunction) + (kProcedure) + (kConstructor) + (kDestructor) + (kOperator) + (kReference) + + (kInterface) + (kImplementation) + (kInitialization) + (kFinalization) + + (kPublished) + (kPublic) + (kProtected) + (kPrivate) + (kStrict) + (kRequired) + (kOptional) + + (kTry) + (kExcept) + (kFinally) + (kRaise) + (kOn) + (kCase) + (kWith) + (kGoto) +] @keyword + +[ + (kFor) + (kTo) + (kDownto) + (kDo) + (kWhile) + (kRepeat) + (kUntil) +] @keyword.control.repeat + +[ + (kIf) + (kThen) + (kElse) +] @keyword.control.conditional diff --git a/runtime/queries/pascal/injections.scm b/runtime/queries/pascal/injections.scm new file mode 100644 index 000000000000..321c90add371 --- /dev/null +++ b/runtime/queries/pascal/injections.scm @@ -0,0 +1,2 @@ +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/pascal/textobjects.scm b/runtime/queries/pascal/textobjects.scm new file mode 100644 index 000000000000..56dbe54032e7 --- /dev/null +++ b/runtime/queries/pascal/textobjects.scm @@ -0,0 +1,10 @@ + +(declType (declClass (declSection) @class.inside)) @class.around + +(defProc body: (_) @function.inside) @function.around + +(declArgs (_) @parameter.inside) @parameter.around +(exprArgs (_) @parameter.inside) @parameter.around + +(comment) @comment.inside +(comment)+ @comment.around From 464d7c541823cda2cc3016e9f3edfa84c3a5dca2 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Mon, 5 Sep 2022 12:38:50 +0200 Subject: [PATCH 23/33] fix: add difference check for statusline normal,insert,select --- xtask/src/themelint.rs | 72 +++++++++++++++++++++++++++--------------- 1 file changed, 46 insertions(+), 26 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 9c23a11b159f..3e5e2887ed53 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -10,33 +10,44 @@ struct Rule { check_both: bool, } +enum Require { + Existence(Rule), + Difference(&'static str, &'static str), +} + // Placed in an fn here, so it's the first thing you see -fn get_rules() -> Vec { +fn get_rules() -> Vec { vec![ // Check for ui.selection, which is required - Rule::has_either("ui.selection"), + Require::Existence(Rule::has_either("ui.selection")), // Check for planned readable text - Rule::has_fg("ui.text"), - Rule::has_bg("ui.background"), + Require::Existence(Rule::has_fg("ui.text")), + Require::Existence(Rule::has_bg("ui.background")), // Check for complete editor.statusline bare minimum - Rule::has_both("ui.statusline"), - Rule::has_both("ui.statusline.inactive"), + Require::Existence(Rule::has_both("ui.statusline")), + Require::Existence(Rule::has_both("ui.statusline.inactive")), // Check for editor.color-modes - Rule::has_either("ui.statusline.insert"), - Rule::has_either("ui.statusline.normal"), - Rule::has_either("ui.statusline.select"), + Require::Existence(Rule::has_either("ui.statusline.normal")), + Require::Existence(Rule::has_either("ui.statusline.insert")), + Require::Existence(Rule::has_either("ui.statusline.select")), + Require::Difference("ui.statusline.normal", "ui.statusline.insert"), + Require::Difference("ui.statusline.normal", "ui.statusline.select"), // Check for editor.cursorline - Rule::has_bg("ui.cursorline.primary"), + Require::Existence(Rule::has_bg("ui.cursorline.primary")), + // Check for editor.whitespace + Require::Existence(Rule::has_both("ui.virtual.whitespace")), + // Check fir rulers + Require::Existence(Rule::has_either("ui.virtual.indent-guide")), // Check for editor.rulers - Rule::has_either("ui.virtual.ruler"), + Require::Existence(Rule::has_either("ui.virtual.ruler")), // Check for menus and prompts - Rule::has_both("ui.menu"), - Rule::has_both("ui.help"), - Rule::has_bg("ui.popup"), - Rule::has_either("ui.window"), + Require::Existence(Rule::has_both("ui.menu")), + Require::Existence(Rule::has_both("ui.help")), + Require::Existence(Rule::has_bg("ui.popup")), + Require::Existence(Rule::has_either("ui.window")), // Check for visible cursor - Rule::has_bg("ui.cursor.primary"), - Rule::has_either("ui.cursor.match"), + Require::Existence(Rule::has_bg("ui.cursor.primary")), + Require::Existence(Rule::has_either("ui.cursor.match")), ] } @@ -69,19 +80,21 @@ impl Rule { check_both: true, } } - fn found_impl(theme: &Theme, find: Option<&'static str>) -> bool { - if let Some(fg) = &find { + fn found_fg(&self, theme: &Theme) -> bool { + if let Some(fg) = &self.fg { if theme.get(fg).fg.is_none() && theme.get(fg).add_modifier == Modifier::empty() { return false; } } return true; } - fn found_fg(&self, theme: &Theme) -> bool { - return Rule::found_impl(theme, self.fg); - } fn found_bg(&self, theme: &Theme) -> bool { - return Rule::found_impl(theme, self.bg); + if let Some(bg) = &self.bg { + if theme.get(bg).bg.is_none() && theme.get(bg).add_modifier == Modifier::empty() { + return false; + } + } + return true; } fn rule_name(&self) -> &'static str { if self.fg.is_some() { @@ -129,9 +142,16 @@ pub fn lint(file: String) -> Result<(), DynError> { let theme: Theme = toml::from_slice(&theme).expect("Failed to parse theme"); let mut messages: Vec = vec![]; - get_rules() - .iter() - .for_each(|rule| rule.validate(&theme, &mut messages)); + get_rules().iter().for_each(|lint| match lint { + Require::Existence(rule) => rule.validate(&theme, &mut messages), + Require::Difference(a, b) => { + let theme_a = theme.get(a); + let theme_b = theme.get(b); + if theme_a == theme_b { + messages.push(format!("$THEME: `{}` and `{}` cannot be equal", a, b)); + } + } + }); if messages.len() > 0 { messages.iter().for_each(|m| { From f64c587e84415a1d9ed06cf70b61f001c1f5203e Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Mon, 5 Sep 2022 13:17:39 +0200 Subject: [PATCH 24/33] fix: fg for whitespace and early exit if and one is ok --- xtask/src/themelint.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 3e5e2887ed53..daaf18ef82db 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -35,7 +35,7 @@ fn get_rules() -> Vec { // Check for editor.cursorline Require::Existence(Rule::has_bg("ui.cursorline.primary")), // Check for editor.whitespace - Require::Existence(Rule::has_both("ui.virtual.whitespace")), + Require::Existence(Rule::has_fg("ui.virtual.whitespace")), // Check fir rulers Require::Existence(Rule::has_either("ui.virtual.indent-guide")), // Check for editor.rulers @@ -110,6 +110,9 @@ impl Rule { let found_fg = self.found_fg(theme); let found_bg = self.found_bg(theme); + if !self.check_both && (found_fg || found_bg) { + return; + } if !found_fg || !found_bg { let mut missing = vec![]; if !found_fg { From 726f85b7fc41f4f38b8983f2ba651ebae42f8eae Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Fri, 9 Sep 2022 20:23:45 +0200 Subject: [PATCH 25/33] chore: cleaning up, no idea how these got here or how this will look --- book/src/generated/lang-support.md | 18 +- languages.toml | 66 +++-- runtime/queries/pascal/highlights.scm | 382 ------------------------- runtime/queries/pascal/injections.scm | 2 - runtime/queries/pascal/textobjects.scm | 10 - 5 files changed, 60 insertions(+), 418 deletions(-) delete mode 100644 runtime/queries/pascal/highlights.scm delete mode 100644 runtime/queries/pascal/injections.scm delete mode 100644 runtime/queries/pascal/textobjects.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 8d8275ab6383..ca7c12481b4a 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -4,7 +4,7 @@ | bash | ✓ | | | `bash-language-server` | | beancount | ✓ | | | | | c | ✓ | ✓ | ✓ | `clangd` | -| c-sharp | ✓ | | | `OmniSharp` | +| c-sharp | ✓ | ✓ | | `OmniSharp` | | cairo | ✓ | | | | | clojure | ✓ | | | `clojure-lsp` | | cmake | ✓ | ✓ | ✓ | `cmake-language-server` | @@ -14,7 +14,8 @@ | css | ✓ | | | `vscode-css-language-server` | | cue | ✓ | | | `cuelsp` | | dart | ✓ | | ✓ | `dart` | -| devicetree | ✓ | | ✓ | | +| devicetree | ✓ | | | | +| diff | ✓ | | | | | dockerfile | ✓ | | | `docker-langserver` | | dot | ✓ | | | `dot-language-server` | | edoc | ✓ | | | | @@ -28,11 +29,10 @@ | esdl | ✓ | | | | | fish | ✓ | ✓ | ✓ | | | fortran | ✓ | | ✓ | `fortls` | -| gdscript | ✓ | | ✓ | | +| gdscript | ✓ | | | | | git-attributes | ✓ | | | | | git-commit | ✓ | | | | | git-config | ✓ | | | | -| git-diff | ✓ | | | | | git-ignore | ✓ | | | | | git-rebase | ✓ | | | | | gleam | ✓ | ✓ | | `gleam` | @@ -42,7 +42,7 @@ | gotmpl | ✓ | | | `gopls` | | gowork | ✓ | | | `gopls` | | graphql | ✓ | | | | -| hare | ✓ | | ✓ | | +| hare | ✓ | | | | | haskell | ✓ | | | `haskell-language-server-wrapper` | | hcl | ✓ | | ✓ | `terraform-ls` | | heex | ✓ | ✓ | | | @@ -53,6 +53,7 @@ | javascript | ✓ | ✓ | ✓ | `typescript-language-server` | | jsdoc | ✓ | | | | | json | ✓ | | ✓ | `vscode-json-language-server` | +| jsonnet | ✓ | | | `jsonnet-language-server` | | jsx | ✓ | ✓ | ✓ | `typescript-language-server` | | julia | ✓ | | | `julia` | | kotlin | ✓ | | | `kotlin-language-server` | @@ -69,12 +70,12 @@ | meson | ✓ | | ✓ | | | mint | | | | `mint` | | nickel | ✓ | | ✓ | `nls` | -| nix | ✓ | | ✓ | `rnix-lsp` | +| nix | ✓ | | | `rnix-lsp` | | nu | ✓ | | | | | ocaml | ✓ | | ✓ | `ocamllsp` | | ocaml-interface | ✓ | | | `ocamllsp` | | odin | ✓ | | | `ols` | -| openscad | ✓ | | | `openscad-language-server` | +| openscad | ✓ | | | `openscad-lsp` | | org | ✓ | | | | | pascal | ✓ | ✓ | | `pasls` | | perl | ✓ | ✓ | ✓ | | @@ -95,11 +96,12 @@ | scheme | ✓ | | | | | scss | ✓ | | | `vscode-css-language-server` | | slint | ✓ | | ✓ | `slint-lsp` | +| sml | ✓ | | | | | solidity | ✓ | | | `solc` | | sql | ✓ | | | | | sshclientconfig | ✓ | | | | | starlark | ✓ | ✓ | | | -| svelte | ✓ | | ✓ | `svelteserver` | +| svelte | ✓ | | | `svelteserver` | | swift | ✓ | | | `sourcekit-lsp` | | tablegen | ✓ | ✓ | ✓ | | | task | ✓ | | | | diff --git a/languages.toml b/languages.toml index 986b927e3a1e..15fbe7fb15ed 100644 --- a/languages.toml +++ b/languages.toml @@ -50,7 +50,7 @@ args = { attachCommands = [ "platform select remote-gdb-server", "platform conne [[grammar]] name = "rust" -source = { git = "https://github.com/tree-sitter/tree-sitter-rust", rev = "a360da0a29a19c281d08295a35ecd0544d2da211" } +source = { git = "https://github.com/tree-sitter/tree-sitter-rust", rev = "41e23b454f503e6fe63ec4b6d9f7f2cf7788ab8e" } [[language]] name = "toml" @@ -121,7 +121,7 @@ indent = { tab-width = 4, unit = " " } [[grammar]] name = "fish" -source = { git = "https://github.com/ram02z/tree-sitter-fish", rev = "04e54ab6585dfd4fee6ddfe5849af56f101b6d4f" } +source = { git = "https://github.com/ram02z/tree-sitter-fish", rev = "84436cf24c2b3176bfbb220922a0fdbd0141e406" } [[language]] name = "mint" @@ -235,7 +235,7 @@ language-server = { command = "OmniSharp", args = [ "--languageserver" ] } [[grammar]] name = "c-sharp" -source = { git = "https://github.com/tree-sitter/tree-sitter-c-sharp", rev = "53a65a908167d6556e1fcdb67f1ee62aac101dda" } +source = { git = "https://github.com/tree-sitter/tree-sitter-c-sharp", rev = "9c494a503c8e2044bfffce57f70b480c01a82f03" } [[language]] name = "go" @@ -331,7 +331,7 @@ source = { git = "https://github.com/omertuc/tree-sitter-go-work", rev = "6dd9dd [[language]] name = "javascript" scope = "source.js" -injection-regex = "^(js|javascript)$" +injection-regex = "(js|javascript)" file-types = ["js", "jsx", "mjs", "cjs"] shebangs = ["node"] roots = [] @@ -370,7 +370,7 @@ grammar = "javascript" [[language]] name = "typescript" scope = "source.ts" -injection-regex = "^(ts|typescript)$" +injection-regex = "(ts|typescript)" file-types = ["ts"] shebangs = [] roots = [] @@ -385,7 +385,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-typescript", rev = [[language]] name = "tsx" scope = "source.tsx" -injection-regex = "^(tsx)$" # |typescript +injection-regex = "(tsx)" # |typescript file-types = ["tsx"] roots = [] # TODO: highlights-params @@ -735,10 +735,9 @@ language-server = { command = "zls" } indent = { tab-width = 4, unit = " " } formatter = { command = "zig" , args = ["fmt", "--stdin"] } - [[grammar]] name = "zig" -source = { git = "https://github.com/maxxnino/tree-sitter-zig", rev = "93331b8bd8b4ebee2b575490b2758f16ad4e9f30" } +source = { git = "https://github.com/maxxnino/tree-sitter-zig", rev = "8d3224c3bd0890fe08358886ebf54fca2ed448a6" } [[language]] name = "prolog" @@ -905,7 +904,7 @@ source = { git = "https://github.com/Flakebi/tree-sitter-tablegen", rev = "568dd name = "markdown" scope = "source.md" injection-regex = "md|markdown" -file-types = ["md"] +file-types = ["md", "markdown"] roots = [] indent = { tab-width = 2, unit = " " } @@ -973,13 +972,15 @@ roots = [] file-types = ["COMMIT_EDITMSG"] comment-token = "#" indent = { tab-width = 2, unit = " " } +rulers = [50, 72] +max-line-length = 72 [[grammar]] name = "git-commit" source = { git = "https://github.com/the-mikedavis/tree-sitter-git-commit", rev = "318dd72abfaa7b8044c1d1fbeabcd06deaaf038f" } [[language]] -name = "git-diff" +name = "diff" scope = "source.diff" roots = [] file-types = ["diff"] @@ -988,8 +989,8 @@ comment-token = "#" indent = { tab-width = 2, unit = " " } [[grammar]] -name = "git-diff" -source = { git = "https://github.com/the-mikedavis/tree-sitter-git-diff", rev = "c12e6ecb54485f764250556ffd7ccb18f8e2942b" } +name = "diff" +source = { git = "https://github.com/the-mikedavis/tree-sitter-diff", rev = "fd74c78fa88a20085dbc7bbeaba066f4d1692b63" } [[language]] name = "git-rebase" @@ -1118,6 +1119,14 @@ comment-token = "%%" indent = { tab-width = 4, unit = " " } language-server = { command = "erlang_ls" } +[language.auto-pairs] +'(' = ')' +'{' = '}' +'[' = ']' +'"' = '"' +"'" = "'" +'`' = "'" + [[grammar]] name = "erlang" source = { git = "https://github.com/the-mikedavis/tree-sitter-erlang", rev = "0e7d677d11a7379686c53c616825714ccb728059" } @@ -1176,7 +1185,7 @@ source = { git = "https://github.com/milisims/tree-sitter-org", rev = "698bb1a34 [[language]] name = "solidity" scope = "source.sol" -injection-regex = "^(sol|solidity)$" +injection-regex = "(sol|solidity)" file-types = ["sol"] roots = [] comment-token = "//" @@ -1185,7 +1194,7 @@ language-server = { command = "solc", args = ["--lsp"] } [[grammar]] name = "solidity" -source = { git = "https://github.com/slinlee/tree-sitter-solidity", rev = "f3a002274744e859bf64cf3524985f8c31ea84fd" } +source = { git = "https://github.com/JoranHonig/tree-sitter-solidity", rev = "9004b86531cb424bd379424cf7266a4585f2af7d" } [[language]] name = "gleam" @@ -1393,7 +1402,7 @@ source = { git = "https://github.com/archseer/tree-sitter-cairo", rev = "5155c6e [[language]] name = "cpon" scope = "scope.cpon" -injection-regex = "^cpon$" +injection-regex = "cpon" file-types = ["cpon", "cp"] roots = [] auto-format = true @@ -1514,7 +1523,7 @@ injection-regex = "openscad" file-types = ["scad"] roots = [] comment-token = "//" -language-server = { command = "openscad-language-server" } +language-server = { command = "openscad-lsp", args = ["--stdio"] } indent = { tab-width = 2, unit = "\t" } [[grammar]] @@ -1705,3 +1714,28 @@ language-server = { command = "pasls", args = [] } [[grammar]] name = "pascal" source = { git = "https://github.com/Isopod/tree-sitter-pascal", rev = "2fd40f477d3e2794af152618ccfac8d92eb72a66" } + +[[language]] +name = "sml" +scope = "source.sml" +injection-regex = "sml" +file-types = ["sml"] +comment-token = "(*" +roots = [] + +[[grammar]] +name = "sml" +source = { git = "https://github.com/Giorbo/tree-sitter-sml", rev = "bd4055d5554614520d4a0706b34dc0c317c6b608" } + +[[language]] +name = "jsonnet" +scope = "source.jsonnet" +file-types = ["libsonnet", "jsonnet"] +roots = ["jsonnetfile.json"] +comment-token = "//" +indent = { tab-width = 2, unit = " " } +language-server = { command = "jsonnet-language-server", args= ["-t", "--lint"] } + +[[grammar]] +name = "jsonnet" +source = { git = "https://github.com/sourcegraph/tree-sitter-jsonnet", rev = "0475a5017ad7dc84845d1d33187f2321abcb261d" } diff --git a/runtime/queries/pascal/highlights.scm b/runtime/queries/pascal/highlights.scm deleted file mode 100644 index 5368a22b87cd..000000000000 --- a/runtime/queries/pascal/highlights.scm +++ /dev/null @@ -1,382 +0,0 @@ -; -- Identifier type inferrence - -; VERY QUESTIONABLE: Highlighting of identifiers based on spelling -(exprBinary ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) -(exprUnary ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) -(assignment rhs: ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) -(exprBrackets ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) -(exprParens ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) -(exprDot rhs: ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) -(exprTpl args: ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) -(exprArgs ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) -(declEnumValue ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) -(defaultValue ((identifier) @constant - (#match? @constant "^[A-Z][A-Z0-9_]+$|^[a-z]{2,3}[A-Z].+$"))) - -; -- Break, Continue & Exit -; (Not ideal: ideally, there would be a way to check if these special -; identifiers are shadowed by a local variable) -(statement ((identifier) @keyword.control.return - (#match? @keyword.control.return "^[eE][xX][iI][tT]$"))) -(statement (exprCall entity: ((identifier) @keyword.control.return - (#match? @keyword.control.return "^[eE][xX][iI][tT]$")))) -(statement ((identifier) @keyword.control.repeat - (#match? @keyword.control.repeat "^[bB][rR][eE][aA][kK]$"))) -(statement ((identifier) @keyword.control.repeat - (#match? @keyword.control.repeat "^[cC][oO][nN][tT][iI][nN][uU][eE]$"))) - -; -- Heuristic for procedure/function calls without parentheses -; (If a statement consists only of an identifier, assume it's a procedure) -; (This will still not match all procedure calls, and also may produce false -; positives in rare cases, but only for nonsensical code) - -(statement (exprDot rhs: (exprTpl entity: (identifier) @function))) -(statement (exprTpl entity: (identifier) @function)) -(statement (exprDot rhs: (identifier) @function)) -(statement (identifier) @function) - -; -- Procedure name in calls with parentheses -; (Pascal doesn't require parentheses for procedure calls, so this will not -; detect all calls) - -(inherited) @function - -; foo.bar -(exprCall entity: (exprDot rhs: (exprTpl entity: (identifier) @function))) -; foo.bar -(exprCall entity: (exprDot rhs: (identifier) @function)) -; foobar -(exprCall entity: (exprTpl entity: (identifier) @function)) -; foobar -(exprCall entity: (identifier) @function) - -; -- Fields - -(declSection (declVars (declVar name:(identifier) @variable.other.member))) -(declSection (declField name:(identifier) @variable.other.member)) -(declClass (declField name:(identifier) @variable.other.member)) -(exprDot rhs: (exprDot) @variable.other.member) -(exprDot rhs: (identifier) @variable.other.member) - -(recInitializerField name:(identifier) @variable.other.member) - -; -- Variable & constant declarations -; (This is only questionable because we cannot detect types of identifiers -; declared in other units, so the results will be inconsistent) - -(declVar name: (identifier) @variable) -(declConst name: (identifier) @constant) -(declEnumValue name: (identifier) @constant) - -; -- Constant usage - -[ - (caseLabel) - (label) -] @constant - -(procAttribute (identifier) @constant) -(procExternal (identifier) @constant) - -; -- Type usage - -(typeref) @type - -; -- Exception parameters - -(exceptionHandler variable: (identifier) @variable.parameter) - -; -- Template parameters - -(genericArg type: (typeref) @type) -(genericArg name: (identifier) @variable.parameter) - -(declProc name: (genericDot lhs: (identifier) @type)) -(declType (genericDot (identifier) @type)) - -(genericDot (genericTpl (identifier) @type)) -(genericDot (genericDot (identifier) @type)) - -(genericTpl entity: (genericDot (identifier) @type)) -(genericTpl entity: (identifier) @type) - -; -- Function parameters - -(declArg name: (identifier) @variable.parameter) - -; Treat property declarations like functions - -(declProp name: (identifier) @function) -(declProp getter: (identifier) @variable.other.member) -(declProp setter: (identifier) @variable.other.member) - -; -- Procedure & function declarations - -; foo.bar -(declProc name: (genericDot rhs: (genericTpl entity: (identifier) @function))) -; foo.bar -(declProc name: (genericDot rhs: (identifier) @function)) -; foobar -(declProc name: (genericTpl entity: (identifier) @function)) -; foobar -(declProc name: (identifier) @function) - -; -- Type declaration - -(declType name: (genericTpl entity: (identifier) @type)) -(declType name: (identifier) @type) - -; -- Comments - -(comment) @comment -(pp) @function.macro - -; -- Variables - -(exprBinary (identifier) @variable) -(exprUnary (identifier) @variable) -(assignment (identifier) @variable) -(exprBrackets (identifier) @variable) -(exprParens (identifier) @variable) -(exprDot (identifier) @variable) -(exprTpl (identifier) @variable) -(exprArgs (identifier) @variable) -(defaultValue (identifier) @variable) - -; -- Literals - -(literalNumber) @constant.builtin.numeric -(literalString) @string - -; -- Builtin constants - -[ - (kTrue) - (kFalse) -] @constant.builtin.boolean - -[ - (kNil) -] @constant.builtin - -; -- Punctuation & operators - -[ - (kOr) - (kXor) - (kDiv) - (kMod) - (kAnd) - (kShl) - (kShr) - (kNot) - (kIs) - (kAs) - (kIn) -] @keyword.operator - -[ - (kDot) - (kAdd) - (kSub) - (kMul) - (kFdiv) - (kAssign) - (kAssignAdd) - (kAssignSub) - (kAssignMul) - (kAssignDiv) - (kEq) - (kLt) - (kLte) - (kGt) - (kGte) - (kNeq) - (kAt) - (kHat) -] @operator - -[ - ".." -] @punctuation.special - -[ - ";" - "," - ":" - (kEndDot) -] @punctuation.delimiter - -[ - "(" - ")" - "[" - "]" -] @punctuation.bracket - -; -- Attributes - -(procAttribute (kPublic) @attribute) - -[ - (kDefault) - (kIndex) - (kNodefault) - (kStored) - - (kStatic) - (kVirtual) - (kAbstract) - (kSealed) - (kDynamic) - (kOverride) - (kOverload) - (kReintroduce) - (kInline) - - (kForward) - - (kStdcall) - (kCdecl) - (kCppdecl) - (kPascal) - (kRegister) - (kMwpascal) - (kExternal) - (kName) - (kMessage) - (kDeprecated) - (kExperimental) - (kPlatform) - (kUnimplemented) - (kCvar) - (kExport) - (kFar) - (kNear) - (kSafecall) - (kAssembler) - (kNostackframe) - (kInterrupt) - (kNoreturn) - (kIocheck) - (kLocal) - (kHardfloat) - (kSoftfloat) - (kMs_abi_default) - (kMs_abi_cdecl) - (kSaveregisters) - (kSysv_abi_default) - (kSysv_abi_cdecl) - (kVectorcall) - (kVarargs) - (kWinapi) - (kAlias) - (kDelayed) - - (rttiAttributes) - (procAttribute) - -] @attribute - -; -- Keywords -[ - (kProgram) - (kLibrary) - (kUnit) - (kUses) - - (kBegin) - (kEnd) - (kAsm) - - (kVar) - (kThreadvar) - (kConst) - (kResourcestring) - (kConstref) - (kOut) - (kType) - (kLabel) - (kExports) - - (kAbsolute) - - (kProperty) - (kRead) - (kWrite) - (kImplements) - - (kClass) - (kInterface) - (kObject) - (kRecord) - (kObjcclass) - (kObjccategory) - (kObjcprotocol) - (kArray) - (kFile) - (kString) - (kSet) - (kOf) - (kHelper) - (kPacked) - - (kInherited) - - (kGeneric) - (kSpecialize) - - (kFunction) - (kProcedure) - (kConstructor) - (kDestructor) - (kOperator) - (kReference) - - (kInterface) - (kImplementation) - (kInitialization) - (kFinalization) - - (kPublished) - (kPublic) - (kProtected) - (kPrivate) - (kStrict) - (kRequired) - (kOptional) - - (kTry) - (kExcept) - (kFinally) - (kRaise) - (kOn) - (kCase) - (kWith) - (kGoto) -] @keyword - -[ - (kFor) - (kTo) - (kDownto) - (kDo) - (kWhile) - (kRepeat) - (kUntil) -] @keyword.control.repeat - -[ - (kIf) - (kThen) - (kElse) -] @keyword.control.conditional diff --git a/runtime/queries/pascal/injections.scm b/runtime/queries/pascal/injections.scm deleted file mode 100644 index 321c90add371..000000000000 --- a/runtime/queries/pascal/injections.scm +++ /dev/null @@ -1,2 +0,0 @@ -((comment) @injection.content - (#set! injection.language "comment")) diff --git a/runtime/queries/pascal/textobjects.scm b/runtime/queries/pascal/textobjects.scm deleted file mode 100644 index 56dbe54032e7..000000000000 --- a/runtime/queries/pascal/textobjects.scm +++ /dev/null @@ -1,10 +0,0 @@ - -(declType (declClass (declSection) @class.inside)) @class.around - -(defProc body: (_) @function.inside) @function.around - -(declArgs (_) @parameter.inside) @parameter.around -(exprArgs (_) @parameter.inside) @parameter.around - -(comment) @comment.inside -(comment)+ @comment.around From 91bb2f52c29b071638c575dc8dfe67a200edddbb Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Fri, 9 Sep 2022 20:25:48 +0200 Subject: [PATCH 26/33] chore: revert from older commit? --- book/src/generated/lang-support.md | 19 +++---- languages.toml | 80 ++++++------------------------ 2 files changed, 24 insertions(+), 75 deletions(-) diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index ca7c12481b4a..8c1d820897f9 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -4,7 +4,7 @@ | bash | ✓ | | | `bash-language-server` | | beancount | ✓ | | | | | c | ✓ | ✓ | ✓ | `clangd` | -| c-sharp | ✓ | ✓ | | `OmniSharp` | +| c-sharp | ✓ | | | `OmniSharp` | | cairo | ✓ | | | | | clojure | ✓ | | | `clojure-lsp` | | cmake | ✓ | ✓ | ✓ | `cmake-language-server` | @@ -14,8 +14,7 @@ | css | ✓ | | | `vscode-css-language-server` | | cue | ✓ | | | `cuelsp` | | dart | ✓ | | ✓ | `dart` | -| devicetree | ✓ | | | | -| diff | ✓ | | | | +| devicetree | ✓ | | ✓ | | | dockerfile | ✓ | | | `docker-langserver` | | dot | ✓ | | | `dot-language-server` | | edoc | ✓ | | | | @@ -29,10 +28,11 @@ | esdl | ✓ | | | | | fish | ✓ | ✓ | ✓ | | | fortran | ✓ | | ✓ | `fortls` | -| gdscript | ✓ | | | | +| gdscript | ✓ | | ✓ | | | git-attributes | ✓ | | | | | git-commit | ✓ | | | | | git-config | ✓ | | | | +| git-diff | ✓ | | | | | git-ignore | ✓ | | | | | git-rebase | ✓ | | | | | gleam | ✓ | ✓ | | `gleam` | @@ -42,7 +42,7 @@ | gotmpl | ✓ | | | `gopls` | | gowork | ✓ | | | `gopls` | | graphql | ✓ | | | | -| hare | ✓ | | | | +| hare | ✓ | | ✓ | | | haskell | ✓ | | | `haskell-language-server-wrapper` | | hcl | ✓ | | ✓ | `terraform-ls` | | heex | ✓ | ✓ | | | @@ -53,7 +53,6 @@ | javascript | ✓ | ✓ | ✓ | `typescript-language-server` | | jsdoc | ✓ | | | | | json | ✓ | | ✓ | `vscode-json-language-server` | -| jsonnet | ✓ | | | `jsonnet-language-server` | | jsx | ✓ | ✓ | ✓ | `typescript-language-server` | | julia | ✓ | | | `julia` | | kotlin | ✓ | | | `kotlin-language-server` | @@ -70,14 +69,13 @@ | meson | ✓ | | ✓ | | | mint | | | | `mint` | | nickel | ✓ | | ✓ | `nls` | -| nix | ✓ | | | `rnix-lsp` | +| nix | ✓ | | ✓ | `rnix-lsp` | | nu | ✓ | | | | | ocaml | ✓ | | ✓ | `ocamllsp` | | ocaml-interface | ✓ | | | `ocamllsp` | | odin | ✓ | | | `ols` | -| openscad | ✓ | | | `openscad-lsp` | +| openscad | ✓ | | | `openscad-language-server` | | org | ✓ | | | | -| pascal | ✓ | ✓ | | `pasls` | | perl | ✓ | ✓ | ✓ | | | php | ✓ | ✓ | ✓ | `intelephense` | | prisma | ✓ | | | `prisma-language-server` | @@ -96,12 +94,11 @@ | scheme | ✓ | | | | | scss | ✓ | | | `vscode-css-language-server` | | slint | ✓ | | ✓ | `slint-lsp` | -| sml | ✓ | | | | | solidity | ✓ | | | `solc` | | sql | ✓ | | | | | sshclientconfig | ✓ | | | | | starlark | ✓ | ✓ | | | -| svelte | ✓ | | | `svelteserver` | +| svelte | ✓ | | ✓ | `svelteserver` | | swift | ✓ | | | `sourcekit-lsp` | | tablegen | ✓ | ✓ | ✓ | | | task | ✓ | | | | diff --git a/languages.toml b/languages.toml index 15fbe7fb15ed..0bcc6ef21b6c 100644 --- a/languages.toml +++ b/languages.toml @@ -50,7 +50,7 @@ args = { attachCommands = [ "platform select remote-gdb-server", "platform conne [[grammar]] name = "rust" -source = { git = "https://github.com/tree-sitter/tree-sitter-rust", rev = "41e23b454f503e6fe63ec4b6d9f7f2cf7788ab8e" } +source = { git = "https://github.com/tree-sitter/tree-sitter-rust", rev = "a360da0a29a19c281d08295a35ecd0544d2da211" } [[language]] name = "toml" @@ -121,7 +121,7 @@ indent = { tab-width = 4, unit = " " } [[grammar]] name = "fish" -source = { git = "https://github.com/ram02z/tree-sitter-fish", rev = "84436cf24c2b3176bfbb220922a0fdbd0141e406" } +source = { git = "https://github.com/ram02z/tree-sitter-fish", rev = "04e54ab6585dfd4fee6ddfe5849af56f101b6d4f" } [[language]] name = "mint" @@ -235,7 +235,7 @@ language-server = { command = "OmniSharp", args = [ "--languageserver" ] } [[grammar]] name = "c-sharp" -source = { git = "https://github.com/tree-sitter/tree-sitter-c-sharp", rev = "9c494a503c8e2044bfffce57f70b480c01a82f03" } +source = { git = "https://github.com/tree-sitter/tree-sitter-c-sharp", rev = "53a65a908167d6556e1fcdb67f1ee62aac101dda" } [[language]] name = "go" @@ -331,7 +331,7 @@ source = { git = "https://github.com/omertuc/tree-sitter-go-work", rev = "6dd9dd [[language]] name = "javascript" scope = "source.js" -injection-regex = "(js|javascript)" +injection-regex = "^(js|javascript)$" file-types = ["js", "jsx", "mjs", "cjs"] shebangs = ["node"] roots = [] @@ -370,7 +370,7 @@ grammar = "javascript" [[language]] name = "typescript" scope = "source.ts" -injection-regex = "(ts|typescript)" +injection-regex = "^(ts|typescript)$" file-types = ["ts"] shebangs = [] roots = [] @@ -385,7 +385,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-typescript", rev = [[language]] name = "tsx" scope = "source.tsx" -injection-regex = "(tsx)" # |typescript +injection-regex = "^(tsx)$" # |typescript file-types = ["tsx"] roots = [] # TODO: highlights-params @@ -735,9 +735,10 @@ language-server = { command = "zls" } indent = { tab-width = 4, unit = " " } formatter = { command = "zig" , args = ["fmt", "--stdin"] } + [[grammar]] name = "zig" -source = { git = "https://github.com/maxxnino/tree-sitter-zig", rev = "8d3224c3bd0890fe08358886ebf54fca2ed448a6" } +source = { git = "https://github.com/maxxnino/tree-sitter-zig", rev = "93331b8bd8b4ebee2b575490b2758f16ad4e9f30" } [[language]] name = "prolog" @@ -904,7 +905,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"] +file-types = ["md"] roots = [] indent = { tab-width = 2, unit = " " } @@ -972,15 +973,13 @@ roots = [] file-types = ["COMMIT_EDITMSG"] comment-token = "#" indent = { tab-width = 2, unit = " " } -rulers = [50, 72] -max-line-length = 72 [[grammar]] name = "git-commit" source = { git = "https://github.com/the-mikedavis/tree-sitter-git-commit", rev = "318dd72abfaa7b8044c1d1fbeabcd06deaaf038f" } [[language]] -name = "diff" +name = "git-diff" scope = "source.diff" roots = [] file-types = ["diff"] @@ -989,8 +988,8 @@ comment-token = "#" indent = { tab-width = 2, unit = " " } [[grammar]] -name = "diff" -source = { git = "https://github.com/the-mikedavis/tree-sitter-diff", rev = "fd74c78fa88a20085dbc7bbeaba066f4d1692b63" } +name = "git-diff" +source = { git = "https://github.com/the-mikedavis/tree-sitter-git-diff", rev = "c12e6ecb54485f764250556ffd7ccb18f8e2942b" } [[language]] name = "git-rebase" @@ -1119,14 +1118,6 @@ comment-token = "%%" indent = { tab-width = 4, unit = " " } language-server = { command = "erlang_ls" } -[language.auto-pairs] -'(' = ')' -'{' = '}' -'[' = ']' -'"' = '"' -"'" = "'" -'`' = "'" - [[grammar]] name = "erlang" source = { git = "https://github.com/the-mikedavis/tree-sitter-erlang", rev = "0e7d677d11a7379686c53c616825714ccb728059" } @@ -1185,7 +1176,7 @@ source = { git = "https://github.com/milisims/tree-sitter-org", rev = "698bb1a34 [[language]] name = "solidity" scope = "source.sol" -injection-regex = "(sol|solidity)" +injection-regex = "^(sol|solidity)$" file-types = ["sol"] roots = [] comment-token = "//" @@ -1194,7 +1185,7 @@ language-server = { command = "solc", args = ["--lsp"] } [[grammar]] name = "solidity" -source = { git = "https://github.com/JoranHonig/tree-sitter-solidity", rev = "9004b86531cb424bd379424cf7266a4585f2af7d" } +source = { git = "https://github.com/slinlee/tree-sitter-solidity", rev = "f3a002274744e859bf64cf3524985f8c31ea84fd" } [[language]] name = "gleam" @@ -1402,7 +1393,7 @@ source = { git = "https://github.com/archseer/tree-sitter-cairo", rev = "5155c6e [[language]] name = "cpon" scope = "scope.cpon" -injection-regex = "cpon" +injection-regex = "^cpon$" file-types = ["cpon", "cp"] roots = [] auto-format = true @@ -1523,7 +1514,7 @@ injection-regex = "openscad" file-types = ["scad"] roots = [] comment-token = "//" -language-server = { command = "openscad-lsp", args = ["--stdio"] } +language-server = { command = "openscad-language-server" } indent = { tab-width = 2, unit = "\t" } [[grammar]] @@ -1700,42 +1691,3 @@ roots = ["edgedb.toml"] [[grammar]] name ="esdl" source = { git = "https://github.com/greym0uth/tree-sitter-esdl", rev = "b840c8a8028127e0a7c6e6c45141adade2bd75cf" } - -[[language]] -name = "pascal" -scope = "source.pascal" -injection-regex = "pascal" -file-types = ["pas", "pp", "inc", "lpr", "lfm"] -roots = [] -comment-token = "//" -indent = { tab-width = 2, unit = " " } -language-server = { command = "pasls", args = [] } - -[[grammar]] -name = "pascal" -source = { git = "https://github.com/Isopod/tree-sitter-pascal", rev = "2fd40f477d3e2794af152618ccfac8d92eb72a66" } - -[[language]] -name = "sml" -scope = "source.sml" -injection-regex = "sml" -file-types = ["sml"] -comment-token = "(*" -roots = [] - -[[grammar]] -name = "sml" -source = { git = "https://github.com/Giorbo/tree-sitter-sml", rev = "bd4055d5554614520d4a0706b34dc0c317c6b608" } - -[[language]] -name = "jsonnet" -scope = "source.jsonnet" -file-types = ["libsonnet", "jsonnet"] -roots = ["jsonnetfile.json"] -comment-token = "//" -indent = { tab-width = 2, unit = " " } -language-server = { command = "jsonnet-language-server", args= ["-t", "--lint"] } - -[[grammar]] -name = "jsonnet" -source = { git = "https://github.com/sourcegraph/tree-sitter-jsonnet", rev = "0475a5017ad7dc84845d1d33187f2321abcb261d" } From 4ce09f7b500163b86ae14a9256acdcf81a81b8e8 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Fri, 9 Sep 2022 20:39:40 +0200 Subject: [PATCH 27/33] refactor: use static fn to equalize api between difference and existance --- xtask/src/themelint.rs | 35 +++++++++++++++++++++-------------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index daaf18ef82db..2255a01adc13 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -106,11 +106,24 @@ impl Rule { } } - fn validate(&self, theme: &Theme, messages: &mut Vec) { - let found_fg = self.found_fg(theme); - let found_bg = self.found_bg(theme); + fn check_difference( + theme: &Theme, + a: &'static str, + b: &'static str, + messages: &mut Vec, + ) { + let theme_a = theme.get(a); + let theme_b = theme.get(b); + if theme_a == theme_b { + messages.push(format!("$THEME: `{}` and `{}` cannot be equal", a, b)); + } + } + + fn check_existence(rule: &Rule, theme: &Theme, messages: &mut Vec) { + let found_fg = rule.found_fg(theme); + let found_bg = rule.found_bg(theme); - if !self.check_both && (found_fg || found_bg) { + if !rule.check_both && (found_fg || found_bg) { return; } if !found_fg || !found_bg { @@ -121,7 +134,7 @@ impl Rule { if !found_bg { missing.push("`bg`"); } - let entry = if !self.check_both && !found_fg && !found_bg { + let entry = if !rule.check_both && !found_fg && !found_bg { missing.join(" or ") } else { missing.join(" and ") @@ -129,7 +142,7 @@ impl Rule { messages.push(format!( "$THEME: missing {} for `{}`", entry, - self.rule_name() + rule.rule_name() )) } } @@ -146,14 +159,8 @@ pub fn lint(file: String) -> Result<(), DynError> { let mut messages: Vec = vec![]; get_rules().iter().for_each(|lint| match lint { - Require::Existence(rule) => rule.validate(&theme, &mut messages), - Require::Difference(a, b) => { - let theme_a = theme.get(a); - let theme_b = theme.get(b); - if theme_a == theme_b { - messages.push(format!("$THEME: `{}` and `{}` cannot be equal", a, b)); - } - } + Require::Existence(rule) => Rule::check_existence(&rule, &theme, &mut messages), + Require::Difference(a, b) => Rule::check_difference(&theme, a, b, &mut messages), }); if messages.len() > 0 { From a264aefb6282c9966849bb6d6ae6a80120a6234f Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Fri, 9 Sep 2022 21:47:59 +0200 Subject: [PATCH 28/33] refactor: querycheck and clippy --- xtask/src/main.rs | 40 +++++---------------------------------- xtask/src/querycheck.rs | 42 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 35 deletions(-) create mode 100644 xtask/src/querycheck.rs diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 26459fd4dc82..1421fd1a1de6 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -1,6 +1,7 @@ mod docgen; mod helpers; mod path; +mod querycheck; mod themelint; use std::{env, error::Error}; @@ -10,6 +11,7 @@ type DynError = Box; pub mod tasks { use crate::docgen::{lang_features, typable_commands, write}; use crate::docgen::{LANG_SUPPORT_MD_OUTPUT, TYPABLE_COMMANDS_MD_OUTPUT}; + use crate::querycheck::query_check; use crate::themelint::{lint, lint_all}; use crate::DynError; @@ -19,47 +21,15 @@ pub mod tasks { Ok(()) } - pub fn themelint(file: Option) -> Result<(), DynError> { match file { Some(file) => lint(file), None => lint_all(), } } - - pub fn query_check() -> Result<(), String> { - 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", - ]; - - for language in lang_config().language { - let language_name = language.language_id.to_ascii_lowercase(); - let grammar_name = language.grammar.unwrap_or(language.language_id); - for query_file in query_files { - let language = get_language(&grammar_name); - let query_text = read_query(&language_name, query_file); - if !query_text.is_empty() && language.is_ok() { - if let Err(reason) = Query::new(language.unwrap(), &query_text) { - return Err(format!( - "Failed to parse {} queries for {}: {}", - query_file, language_name, reason - )); - } - } - } - } - - println!("Query check succeeded"); - Ok(()) + pub fn querycheck() -> Result<(), DynError> { + query_check() } pub fn print_help() { @@ -83,7 +53,7 @@ fn main() -> Result<(), DynError> { Some(t) => match t.as_str() { "docgen" => tasks::docgen()?, "themelint" => tasks::themelint(env::args().nth(2))?, - "query-check" => tasks::query_check()?, + "query-check" => tasks::querycheck()?, invalid => return Err(format!("Invalid task name: {}", invalid).into()), }, }; diff --git a/xtask/src/querycheck.rs b/xtask/src/querycheck.rs new file mode 100644 index 000000000000..81c08d06f8b7 --- /dev/null +++ b/xtask/src/querycheck.rs @@ -0,0 +1,42 @@ +use crate::DynError; + +pub fn query_check() -> 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", + ]; + + for language in lang_config().language { + let language_name = language.language_id.to_ascii_lowercase(); + let grammar_name = language.grammar.unwrap_or(language.language_id); + for query_file in query_files { + let language = get_language(&grammar_name); + let query_text = read_query(&language_name, query_file); + match language { + Ok(lang) => { + 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()); + } + } + } + Err(e) => return Err(e.into()), + } + } + } + + println!("Query check succeeded"); + + Ok(()) +} From 434c35da0b06e00e5396e48e1ce18d42a94cbf6b Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Fri, 9 Sep 2022 21:48:13 +0200 Subject: [PATCH 29/33] refactor: clippy fixes --- xtask/src/themelint.rs | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index 2255a01adc13..c76f648591e6 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -86,7 +86,7 @@ impl Rule { return false; } } - return true; + true } fn found_bg(&self, theme: &Theme) -> bool { if let Some(bg) = &self.bg { @@ -94,7 +94,7 @@ impl Rule { return false; } } - return true; + true } fn rule_name(&self) -> &'static str { if self.fg.is_some() { @@ -159,11 +159,11 @@ pub fn lint(file: String) -> Result<(), DynError> { let mut messages: Vec = vec![]; get_rules().iter().for_each(|lint| match lint { - Require::Existence(rule) => Rule::check_existence(&rule, &theme, &mut messages), + Require::Existence(rule) => Rule::check_existence(rule, &theme, &mut messages), Require::Difference(a, b) => Rule::check_difference(&theme, a, b, &mut messages), }); - if messages.len() > 0 { + if !messages.is_empty() { messages.iter().for_each(|m| { let theme = file.clone(); let message = m.replace("$THEME", theme.as_str()); @@ -179,17 +179,14 @@ pub fn lint_all() -> Result<(), DynError> { let files = Loader::read_names(path::themes().as_path()); let mut errors = vec![]; let files_count = files.len(); - files - .into_iter() - .for_each(|path| match lint(path.replace(".toml", "")) { - Err(err) => { - let errs: i32 = err.to_string().parse().expect("Errors must be integral"); - errors.push(errs) - } - _ => return, - }); + files.into_iter().for_each(|path| { + if let Err(err) = lint(path.replace(".toml", "")) { + let errs: i32 = err.to_string().parse().expect("Errors must be integral"); + errors.push(errs) + } + }); println!("{} of {} themes had issues", errors.len(), files_count); - if errors.len() > 0 { + if !errors.is_empty() { Err(errors.iter().sum::().to_string().into()) } else { Ok(()) From 11840be7328adf08b60195e52e41c9a16dc09ad8 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Fri, 9 Sep 2022 21:55:21 +0200 Subject: [PATCH 30/33] fix: query-check behaves as before --- xtask/src/querycheck.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/xtask/src/querycheck.rs b/xtask/src/querycheck.rs index 81c08d06f8b7..5595b8ec88fb 100644 --- a/xtask/src/querycheck.rs +++ b/xtask/src/querycheck.rs @@ -19,19 +19,16 @@ pub fn query_check() -> Result<(), DynError> { for query_file in query_files { let language = get_language(&grammar_name); let query_text = read_query(&language_name, query_file); - match language { - Ok(lang) => { - 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()); - } + 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()); } } - Err(e) => return Err(e.into()), } } } From 6e2b7b395f118a149f00e66bd725e30131505089 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Sun, 11 Sep 2022 20:49:30 +0200 Subject: [PATCH 31/33] fix: error with x of y message, not total count --- xtask/src/themelint.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index c76f648591e6..d3ce6d523bc6 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -185,9 +185,9 @@ pub fn lint_all() -> Result<(), DynError> { errors.push(errs) } }); - println!("{} of {} themes had issues", errors.len(), files_count); + if !errors.is_empty() { - Err(errors.iter().sum::().to_string().into()) + Err(format!("{} of {} themes had issues", errors.len(), files_count).into()) } else { Ok(()) } From 886206f21c021b206bb707e19eedc6f1b8f38f85 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Thu, 15 Sep 2022 01:00:54 +0200 Subject: [PATCH 32/33] fix: consistent reporting and less mutable state --- xtask/src/themelint.rs | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index d3ce6d523bc6..d8a47c5f9f4a 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -169,7 +169,7 @@ pub fn lint(file: String) -> Result<(), DynError> { let message = m.replace("$THEME", theme.as_str()); println!("{}", message); }); - Err(messages.len().to_string().into()) + Err(format!("{} has issues", file.clone().as_str()).into()) } else { Ok(()) } @@ -177,17 +177,20 @@ pub fn lint(file: String) -> Result<(), DynError> { pub fn lint_all() -> Result<(), DynError> { let files = Loader::read_names(path::themes().as_path()); - let mut errors = vec![]; let files_count = files.len(); - files.into_iter().for_each(|path| { - if let Err(err) = lint(path.replace(".toml", "")) { - let errs: i32 = err.to_string().parse().expect("Errors must be integral"); - errors.push(errs) - } - }); + let ok_files_count = files + .into_iter() + .filter_map(|path| lint(path.replace(".toml", "")).ok()) + .collect::>() + .len(); - if !errors.is_empty() { - Err(format!("{} of {} themes had issues", errors.len(), files_count).into()) + if files_count != ok_files_count { + Err(format!( + "{} of {} themes had issues", + files_count - ok_files_count, + files_count + ) + .into()) } else { Ok(()) } From 0f0282faabf876515cacf175eeb6da4fd588b5e0 Mon Sep 17 00:00:00 2001 From: Alexander Brevig Date: Thu, 15 Sep 2022 01:26:16 +0200 Subject: [PATCH 33/33] fix: selection difference ref #3942 ref #1833 --- xtask/src/themelint.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/xtask/src/themelint.rs b/xtask/src/themelint.rs index d8a47c5f9f4a..26d1cb04e199 100644 --- a/xtask/src/themelint.rs +++ b/xtask/src/themelint.rs @@ -20,6 +20,8 @@ fn get_rules() -> Vec { vec![ // Check for ui.selection, which is required Require::Existence(Rule::has_either("ui.selection")), + Require::Existence(Rule::has_either("ui.selection.primary")), + Require::Difference("ui.selection", "ui.selection.primary"), // Check for planned readable text Require::Existence(Rule::has_fg("ui.text")), Require::Existence(Rule::has_bg("ui.background")),