mirror of
https://github.com/ilyakooo0/helix.git
synced 2024-10-05 20:07:21 +03:00
Compare commits
10 Commits
9b5182e6f0
...
bef7c2ac6c
Author | SHA1 | Date | |
---|---|---|---|
|
bef7c2ac6c | ||
|
ad7b7bc804 | ||
|
6a90166d0a | ||
|
ac8d1f62a1 | ||
|
d9f7aaacaf | ||
|
7d8ce1a400 | ||
|
204c3707b0 | ||
|
13b9885084 | ||
|
786b5c533e | ||
|
581a1ebf5d |
19
Cargo.lock
generated
19
Cargo.lock
generated
@ -424,9 +424,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "fastrand"
|
||||
version = "2.0.0"
|
||||
version = "2.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
||||
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||
|
||||
[[package]]
|
||||
name = "fern"
|
||||
@ -1240,6 +1240,7 @@ dependencies = [
|
||||
"dunce",
|
||||
"encoding_rs",
|
||||
"etcetera",
|
||||
"globset",
|
||||
"hashbrown 0.14.3",
|
||||
"helix-loader",
|
||||
"helix-stdx",
|
||||
@ -1386,6 +1387,7 @@ dependencies = [
|
||||
"signal-hook-tokio",
|
||||
"smallvec",
|
||||
"tempfile",
|
||||
"termini",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"toml",
|
||||
@ -1971,9 +1973,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
||||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.30"
|
||||
version = "0.38.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
|
||||
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
|
||||
dependencies = [
|
||||
"bitflags 2.4.2",
|
||||
"errno",
|
||||
@ -2201,13 +2203,12 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
version = "3.9.0"
|
||||
version = "3.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
|
||||
checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"redox_syscall 0.4.1",
|
||||
"rustix",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
@ -2316,9 +2317,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.35.1"
|
||||
version = "1.36.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
|
||||
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
|
@ -14,6 +14,7 @@
|
||||
| cabal | | | | `haskell-language-server-wrapper` |
|
||||
| cairo | ✓ | ✓ | ✓ | `cairo-language-server` |
|
||||
| capnp | ✓ | | ✓ | |
|
||||
| cel | ✓ | | | |
|
||||
| clojure | ✓ | | | `clojure-lsp` |
|
||||
| cmake | ✓ | ✓ | ✓ | `cmake-language-server` |
|
||||
| comment | ✓ | | | |
|
||||
@ -68,8 +69,8 @@
|
||||
| haskell-persistent | ✓ | | | |
|
||||
| hcl | ✓ | | ✓ | `terraform-ls` |
|
||||
| heex | ✓ | ✓ | | `elixir-ls` |
|
||||
| hoon | ✓ | | | |
|
||||
| hocon | ✓ | | ✓ | |
|
||||
| hoon | ✓ | | | |
|
||||
| hosts | ✓ | | | |
|
||||
| html | ✓ | | | `vscode-html-language-server` |
|
||||
| hurl | ✓ | | ✓ | |
|
||||
@ -155,6 +156,7 @@
|
||||
| smithy | ✓ | | | `cs` |
|
||||
| sml | ✓ | | | |
|
||||
| solidity | ✓ | | | `solc` |
|
||||
| spicedb | ✓ | | | |
|
||||
| sql | ✓ | | | |
|
||||
| sshclientconfig | ✓ | | | |
|
||||
| starlark | ✓ | ✓ | | |
|
||||
|
@ -78,24 +78,26 @@ ### File-type detection and the `file-types` key
|
||||
example:
|
||||
|
||||
```toml
|
||||
file-types = ["Makefile", "toml", { suffix = ".git/config" }]
|
||||
file-types = ["toml", { glob = "Makefile" }, { glob = ".git/config" }, { glob = ".github/workflows/*.yaml" } ]
|
||||
```
|
||||
|
||||
When determining a language configuration to use, Helix searches the file-types
|
||||
with the following priorities:
|
||||
|
||||
1. Exact match: if the filename of a file is an exact match of a string in a
|
||||
`file-types` list, that language wins. In the example above, `"Makefile"`
|
||||
will match against `Makefile` files.
|
||||
2. Extension: if there are no exact matches, any `file-types` string that
|
||||
matches the file extension of a given file wins. In the example above, the
|
||||
`"toml"` matches files like `Cargo.toml` or `languages.toml`.
|
||||
3. Suffix: if there are still no matches, any values in `suffix` tables
|
||||
are checked against the full path of the given file. In the example above,
|
||||
the `{ suffix = ".git/config" }` would match against any `config` files
|
||||
in `.git` directories. Note: `/` is used as the directory separator but is
|
||||
replaced at runtime with the appropriate path separator for the operating
|
||||
system, so this rule would match against `.git\config` files on Windows.
|
||||
1. Glob: values in `glob` tables are checked against the full path of the given
|
||||
file. Globs are standard Unix-style path globs (e.g. the kind you use in Shell)
|
||||
and can be used to match paths for a specific prefix, suffix, directory, etc.
|
||||
In the above example, the `{ glob = "Makefile" }` config would match files
|
||||
with the name `Makefile`, the `{ glob = ".git/config" }` config would match
|
||||
`config` files in `.git` directories, and the `{ glob = ".github/workflows/*.yaml" }`
|
||||
config would match any `yaml` files in `.github/workflow` directories. Note
|
||||
that globs should always use the Unix path separator `/` even on Windows systems;
|
||||
the matcher will automatically take the machine-specific separators into account.
|
||||
If the glob isn't an absolute path or doesn't already start with a glob prefix,
|
||||
`*/` will automatically be added to ensure it matches for any subdirectory.
|
||||
2. Extension: if there are no glob matches, any `file-types` string that matches
|
||||
the file extension of a given file wins. In the example above, the `"toml"`
|
||||
config matches files like `Cargo.toml` or `languages.toml`.
|
||||
|
||||
## Language Server configuration
|
||||
|
||||
@ -120,13 +122,14 @@ ## Language Server configuration
|
||||
|
||||
These are the available options for a language server.
|
||||
|
||||
| Key | Description |
|
||||
| ---- | ----------- |
|
||||
| `command` | The name or path of the language server binary to execute. Binaries must be in `$PATH` |
|
||||
| `args` | A list of arguments to pass to the language server binary |
|
||||
| `config` | LSP initialization options |
|
||||
| `timeout` | The maximum time a request to the language server may take, in seconds. Defaults to `20` |
|
||||
| `environment` | Any environment variables that will be used when starting the language server `{ "KEY1" = "Value1", "KEY2" = "Value2" }` |
|
||||
| Key | Description |
|
||||
| ---- | ----------- |
|
||||
| `command` | The name or path of the language server binary to execute. Binaries must be in `$PATH` |
|
||||
| `args` | A list of arguments to pass to the language server binary |
|
||||
| `config` | LSP initialization options |
|
||||
| `timeout` | The maximum time a request to the language server may take, in seconds. Defaults to `20` |
|
||||
| `environment` | Any environment variables that will be used when starting the language server `{ "KEY1" = "Value1", "KEY2" = "Value2" }` |
|
||||
| `required-root-patterns` | A list of `glob` patterns to look for in the working directory. The language server is started if at least one of them is found. |
|
||||
|
||||
A `format` sub-table within `config` can be used to pass extra formatting options to
|
||||
[Document Formatting Requests](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_formatting).
|
||||
|
@ -52,6 +52,7 @@ textwrap = "0.16.0"
|
||||
|
||||
nucleo.workspace = true
|
||||
parking_lot = "0.12"
|
||||
globset = "0.4.14"
|
||||
|
||||
[dev-dependencies]
|
||||
quickcheck = { version = "1", default-features = false }
|
||||
|
@ -1,10 +1,45 @@
|
||||
/// Syntax configuration loader based on built-in languages.toml.
|
||||
pub fn default_syntax_loader() -> crate::syntax::Configuration {
|
||||
use crate::syntax::{Configuration, Loader, LoaderError};
|
||||
|
||||
/// Language configuration based on built-in languages.toml.
|
||||
pub fn default_lang_config() -> Configuration {
|
||||
helix_loader::config::default_lang_config()
|
||||
.try_into()
|
||||
.expect("Could not serialize built-in languages.toml")
|
||||
.expect("Could not deserialize built-in languages.toml")
|
||||
}
|
||||
/// Syntax configuration loader based on user configured languages.toml.
|
||||
pub fn user_syntax_loader() -> Result<crate::syntax::Configuration, toml::de::Error> {
|
||||
|
||||
/// Language configuration loader based on built-in languages.toml.
|
||||
pub fn default_lang_loader() -> Loader {
|
||||
Loader::new(default_lang_config()).expect("Could not compile loader for default config")
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LanguageLoaderError {
|
||||
DeserializeError(toml::de::Error),
|
||||
LoaderError(LoaderError),
|
||||
}
|
||||
|
||||
impl std::fmt::Display for LanguageLoaderError {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::DeserializeError(err) => write!(f, "Failed to parse language config: {err}"),
|
||||
Self::LoaderError(err) => write!(f, "Failed to compile language config: {err}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::error::Error for LanguageLoaderError {}
|
||||
|
||||
/// Language configuration based on user configured languages.toml.
|
||||
pub fn user_lang_config() -> Result<Configuration, toml::de::Error> {
|
||||
helix_loader::config::user_lang_config()?.try_into()
|
||||
}
|
||||
|
||||
/// Language configuration loader based on user configured languages.toml.
|
||||
pub fn user_lang_loader() -> Result<Loader, LanguageLoaderError> {
|
||||
let config: Configuration = helix_loader::config::user_lang_config()
|
||||
.map_err(LanguageLoaderError::DeserializeError)?
|
||||
.try_into()
|
||||
.map_err(LanguageLoaderError::DeserializeError)?;
|
||||
|
||||
Loader::new(config).map_err(LanguageLoaderError::LoaderError)
|
||||
}
|
||||
|
@ -10,6 +10,7 @@
|
||||
use ahash::RandomState;
|
||||
use arc_swap::{ArcSwap, Guard};
|
||||
use bitflags::bitflags;
|
||||
use globset::GlobSet;
|
||||
use hashbrown::raw::RawTable;
|
||||
use slotmap::{DefaultKey as LayerId, HopSlotMap};
|
||||
|
||||
@ -82,12 +83,6 @@ pub struct Configuration {
|
||||
pub language_server: HashMap<String, LanguageServerConfiguration>,
|
||||
}
|
||||
|
||||
impl Default for Configuration {
|
||||
fn default() -> Self {
|
||||
crate::config::default_syntax_loader()
|
||||
}
|
||||
}
|
||||
|
||||
// largely based on tree-sitter/cli/src/loader.rs
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
||||
@ -164,9 +159,11 @@ pub enum FileType {
|
||||
/// The extension of the file, either the `Path::extension` or the full
|
||||
/// filename if the file does not have an extension.
|
||||
Extension(String),
|
||||
/// The suffix of a file. This is compared to a given file's absolute
|
||||
/// path, so it can be used to detect files based on their directories.
|
||||
Suffix(String),
|
||||
/// A Unix-style path glob. This is compared to the file's absolute path, so
|
||||
/// it can be used to detect files based on their directories. If the glob
|
||||
/// is not an absolute path and does not already start with a glob pattern,
|
||||
/// a glob pattern will be prepended to it.
|
||||
Glob(globset::Glob),
|
||||
}
|
||||
|
||||
impl Serialize for FileType {
|
||||
@ -178,9 +175,9 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
||||
|
||||
match self {
|
||||
FileType::Extension(extension) => serializer.serialize_str(extension),
|
||||
FileType::Suffix(suffix) => {
|
||||
FileType::Glob(glob) => {
|
||||
let mut map = serializer.serialize_map(Some(1))?;
|
||||
map.serialize_entry("suffix", &suffix.replace(std::path::MAIN_SEPARATOR, "/"))?;
|
||||
map.serialize_entry("glob", glob.glob())?;
|
||||
map.end()
|
||||
}
|
||||
}
|
||||
@ -213,9 +210,20 @@ fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
|
||||
M: serde::de::MapAccess<'de>,
|
||||
{
|
||||
match map.next_entry::<String, String>()? {
|
||||
Some((key, suffix)) if key == "suffix" => Ok(FileType::Suffix({
|
||||
suffix.replace('/', std::path::MAIN_SEPARATOR_STR)
|
||||
})),
|
||||
Some((key, mut glob)) if key == "glob" => {
|
||||
// If the glob isn't an absolute path or already starts
|
||||
// with a glob pattern, add a leading glob so we
|
||||
// properly match relative paths.
|
||||
if !glob.starts_with('/') && !glob.starts_with("*/") {
|
||||
glob.insert_str(0, "*/");
|
||||
}
|
||||
|
||||
globset::Glob::new(glob.as_str())
|
||||
.map(FileType::Glob)
|
||||
.map_err(|err| {
|
||||
serde::de::Error::custom(format!("invalid `glob` pattern: {}", err))
|
||||
})
|
||||
}
|
||||
Some((key, _value)) => Err(serde::de::Error::custom(format!(
|
||||
"unknown key in `file-types` list: {}",
|
||||
key
|
||||
@ -358,6 +366,22 @@ fn serialize_lang_features<S>(
|
||||
serializer.end()
|
||||
}
|
||||
|
||||
fn deserialize_required_root_patterns<'de, D>(deserializer: D) -> Result<Option<GlobSet>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let patterns = Vec::<String>::deserialize(deserializer)?;
|
||||
if patterns.is_empty() {
|
||||
return Ok(None);
|
||||
}
|
||||
let mut builder = globset::GlobSetBuilder::new();
|
||||
for pattern in patterns {
|
||||
let glob = globset::Glob::new(&pattern).map_err(serde::de::Error::custom)?;
|
||||
builder.add(glob);
|
||||
}
|
||||
builder.build().map(Some).map_err(serde::de::Error::custom)
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct LanguageServerConfiguration {
|
||||
@ -371,6 +395,12 @@ pub struct LanguageServerConfiguration {
|
||||
pub config: Option<serde_json::Value>,
|
||||
#[serde(default = "default_timeout")]
|
||||
pub timeout: u64,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing,
|
||||
deserialize_with = "deserialize_required_root_patterns"
|
||||
)]
|
||||
pub required_root_patterns: Option<GlobSet>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
@ -752,6 +782,47 @@ pub struct SoftWrap {
|
||||
pub wrap_at_text_width: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FileTypeGlob {
|
||||
glob: globset::Glob,
|
||||
language_id: usize,
|
||||
}
|
||||
|
||||
impl FileTypeGlob {
|
||||
fn new(glob: globset::Glob, language_id: usize) -> Self {
|
||||
Self { glob, language_id }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct FileTypeGlobMatcher {
|
||||
matcher: globset::GlobSet,
|
||||
file_types: Vec<FileTypeGlob>,
|
||||
}
|
||||
|
||||
impl FileTypeGlobMatcher {
|
||||
fn new(file_types: Vec<FileTypeGlob>) -> Result<Self, globset::Error> {
|
||||
let mut builder = globset::GlobSetBuilder::new();
|
||||
for file_type in &file_types {
|
||||
builder.add(file_type.glob.clone());
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
matcher: builder.build()?,
|
||||
file_types,
|
||||
})
|
||||
}
|
||||
|
||||
fn language_id_for_path(&self, path: &Path) -> Option<&usize> {
|
||||
self.matcher
|
||||
.matches(path)
|
||||
.iter()
|
||||
.filter_map(|idx| self.file_types.get(*idx))
|
||||
.max_by_key(|file_type| file_type.glob.glob().len())
|
||||
.map(|file_type| &file_type.language_id)
|
||||
}
|
||||
}
|
||||
|
||||
// Expose loader as Lazy<> global since it's always static?
|
||||
|
||||
#[derive(Debug)]
|
||||
@ -759,7 +830,7 @@ pub struct Loader {
|
||||
// highlight_names ?
|
||||
language_configs: Vec<Arc<LanguageConfiguration>>,
|
||||
language_config_ids_by_extension: HashMap<String, usize>, // Vec<usize>
|
||||
language_config_ids_by_suffix: HashMap<String, usize>,
|
||||
language_config_ids_glob_matcher: FileTypeGlobMatcher,
|
||||
language_config_ids_by_shebang: HashMap<String, usize>,
|
||||
|
||||
language_server_configs: HashMap<String, LanguageServerConfiguration>,
|
||||
@ -767,66 +838,57 @@ pub struct Loader {
|
||||
scopes: ArcSwap<Vec<String>>,
|
||||
}
|
||||
|
||||
pub type LoaderError = globset::Error;
|
||||
|
||||
impl Loader {
|
||||
pub fn new(config: Configuration) -> Self {
|
||||
let mut loader = Self {
|
||||
language_configs: Vec::new(),
|
||||
language_server_configs: config.language_server,
|
||||
language_config_ids_by_extension: HashMap::new(),
|
||||
language_config_ids_by_suffix: HashMap::new(),
|
||||
language_config_ids_by_shebang: HashMap::new(),
|
||||
scopes: ArcSwap::from_pointee(Vec::new()),
|
||||
};
|
||||
pub fn new(config: Configuration) -> Result<Self, LoaderError> {
|
||||
let mut language_configs = Vec::new();
|
||||
let mut language_config_ids_by_extension = HashMap::new();
|
||||
let mut language_config_ids_by_shebang = HashMap::new();
|
||||
let mut file_type_globs = Vec::new();
|
||||
|
||||
for config in config.language {
|
||||
// get the next id
|
||||
let language_id = loader.language_configs.len();
|
||||
let language_id = language_configs.len();
|
||||
|
||||
for file_type in &config.file_types {
|
||||
// entry().or_insert(Vec::new).push(language_id);
|
||||
match file_type {
|
||||
FileType::Extension(extension) => loader
|
||||
.language_config_ids_by_extension
|
||||
.insert(extension.clone(), language_id),
|
||||
FileType::Suffix(suffix) => loader
|
||||
.language_config_ids_by_suffix
|
||||
.insert(suffix.clone(), language_id),
|
||||
FileType::Extension(extension) => {
|
||||
language_config_ids_by_extension.insert(extension.clone(), language_id);
|
||||
}
|
||||
FileType::Glob(glob) => {
|
||||
file_type_globs.push(FileTypeGlob::new(glob.to_owned(), language_id));
|
||||
}
|
||||
};
|
||||
}
|
||||
for shebang in &config.shebangs {
|
||||
loader
|
||||
.language_config_ids_by_shebang
|
||||
.insert(shebang.clone(), language_id);
|
||||
language_config_ids_by_shebang.insert(shebang.clone(), language_id);
|
||||
}
|
||||
|
||||
loader.language_configs.push(Arc::new(config));
|
||||
language_configs.push(Arc::new(config));
|
||||
}
|
||||
|
||||
loader
|
||||
Ok(Self {
|
||||
language_configs,
|
||||
language_config_ids_by_extension,
|
||||
language_config_ids_glob_matcher: FileTypeGlobMatcher::new(file_type_globs)?,
|
||||
language_config_ids_by_shebang,
|
||||
language_server_configs: config.language_server,
|
||||
scopes: ArcSwap::from_pointee(Vec::new()),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn language_config_for_file_name(&self, path: &Path) -> Option<Arc<LanguageConfiguration>> {
|
||||
// Find all the language configurations that match this file name
|
||||
// or a suffix of the file name.
|
||||
let configuration_id = path
|
||||
.file_name()
|
||||
.and_then(|n| n.to_str())
|
||||
.and_then(|file_name| self.language_config_ids_by_extension.get(file_name))
|
||||
let configuration_id = self
|
||||
.language_config_ids_glob_matcher
|
||||
.language_id_for_path(path)
|
||||
.or_else(|| {
|
||||
path.extension()
|
||||
.and_then(|extension| extension.to_str())
|
||||
.and_then(|extension| self.language_config_ids_by_extension.get(extension))
|
||||
})
|
||||
.or_else(|| {
|
||||
self.language_config_ids_by_suffix
|
||||
.iter()
|
||||
.find_map(|(file_type, id)| {
|
||||
if path.to_str()?.ends_with(file_type) {
|
||||
Some(id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
configuration_id.and_then(|&id| self.language_configs.get(id).cloned())
|
||||
@ -2592,7 +2654,8 @@ fn test_textobject_queries() {
|
||||
let loader = Loader::new(Configuration {
|
||||
language: vec![],
|
||||
language_server: HashMap::new(),
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
let language = get_language("rust").unwrap();
|
||||
|
||||
let query = Query::new(language, query_str).unwrap();
|
||||
@ -2654,7 +2717,8 @@ fn test_parser() {
|
||||
let loader = Loader::new(Configuration {
|
||||
language: vec![],
|
||||
language_server: HashMap::new(),
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let language = get_language("rust").unwrap();
|
||||
let config = HighlightConfiguration::new(
|
||||
@ -2760,7 +2824,8 @@ fn assert_pretty_print(
|
||||
let loader = Loader::new(Configuration {
|
||||
language: vec![],
|
||||
language_server: HashMap::new(),
|
||||
});
|
||||
})
|
||||
.unwrap();
|
||||
let language = get_language(language_name).unwrap();
|
||||
|
||||
let config = HighlightConfiguration::new(language, "", "", "").unwrap();
|
||||
|
@ -186,7 +186,7 @@ fn test_treesitter_indent(
|
||||
lang_scope: &str,
|
||||
ignored_lines: Vec<std::ops::Range<usize>>,
|
||||
) {
|
||||
let loader = Loader::new(indent_tests_config());
|
||||
let loader = Loader::new(indent_tests_config()).unwrap();
|
||||
|
||||
// set runtime path so we can find the queries
|
||||
let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
|
@ -30,7 +30,7 @@ log = "0.4"
|
||||
# cloning/compiling tree-sitter grammars
|
||||
cc = { version = "1" }
|
||||
threadpool = { version = "1.0" }
|
||||
tempfile = "3.9.0"
|
||||
tempfile = "3.10.0"
|
||||
dunce = "1.0.4"
|
||||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
|
@ -27,6 +27,6 @@ lsp-types = { version = "0.95" }
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
thiserror = "1.0"
|
||||
tokio = { version = "1.35", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"] }
|
||||
tokio = { version = "1.36", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot", "sync"] }
|
||||
tokio-stream = "0.1.14"
|
||||
parking_lot = "0.12.1"
|
||||
|
@ -177,12 +177,11 @@ pub fn start(
|
||||
args: &[String],
|
||||
config: Option<Value>,
|
||||
server_environment: HashMap<String, String>,
|
||||
root_markers: &[String],
|
||||
manual_roots: &[PathBuf],
|
||||
root_path: PathBuf,
|
||||
root_uri: Option<lsp::Url>,
|
||||
id: usize,
|
||||
name: String,
|
||||
req_timeout: u64,
|
||||
doc_path: Option<&std::path::PathBuf>,
|
||||
) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
|
||||
// Resolve path to the binary
|
||||
let cmd = helix_stdx::env::which(cmd)?;
|
||||
@ -206,22 +205,6 @@ pub fn start(
|
||||
|
||||
let (server_rx, server_tx, initialize_notify) =
|
||||
Transport::start(reader, writer, stderr, id, name.clone());
|
||||
let (workspace, workspace_is_cwd) = find_workspace();
|
||||
let workspace = path::normalize(workspace);
|
||||
let root = find_lsp_workspace(
|
||||
doc_path
|
||||
.and_then(|x| x.parent().and_then(|x| x.to_str()))
|
||||
.unwrap_or("."),
|
||||
root_markers,
|
||||
manual_roots,
|
||||
&workspace,
|
||||
workspace_is_cwd,
|
||||
);
|
||||
|
||||
// `root_uri` and `workspace_folder` can be empty in case there is no workspace
|
||||
// `root_url` can not, use `workspace` as a fallback
|
||||
let root_path = root.clone().unwrap_or_else(|| workspace.clone());
|
||||
let root_uri = root.and_then(|root| lsp::Url::from_file_path(root).ok());
|
||||
|
||||
let workspace_folders = root_uri
|
||||
.clone()
|
||||
|
@ -680,7 +680,7 @@ fn start_client(
|
||||
doc_path: Option<&std::path::PathBuf>,
|
||||
root_dirs: &[PathBuf],
|
||||
enable_snippets: bool,
|
||||
) -> Result<Arc<Client>> {
|
||||
) -> Result<Option<Arc<Client>>> {
|
||||
let config = self
|
||||
.syn_loader
|
||||
.language_server_configs()
|
||||
@ -688,7 +688,7 @@ fn start_client(
|
||||
.ok_or_else(|| anyhow::anyhow!("Language server '{name}' not defined"))?;
|
||||
let id = self.counter;
|
||||
self.counter += 1;
|
||||
let NewClient(client, incoming) = start_client(
|
||||
if let Some(NewClient(client, incoming)) = start_client(
|
||||
id,
|
||||
name,
|
||||
ls_config,
|
||||
@ -696,9 +696,12 @@ fn start_client(
|
||||
doc_path,
|
||||
root_dirs,
|
||||
enable_snippets,
|
||||
)?;
|
||||
self.incoming.push(UnboundedReceiverStream::new(incoming));
|
||||
Ok(client)
|
||||
)? {
|
||||
self.incoming.push(UnboundedReceiverStream::new(incoming));
|
||||
Ok(Some(client))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
/// If this method is called, all documents that have a reference to language servers used by the language config have to refresh their language servers,
|
||||
@ -723,8 +726,8 @@ pub fn restart(
|
||||
root_dirs,
|
||||
enable_snippets,
|
||||
) {
|
||||
Ok(client) => client,
|
||||
error => return Some(error),
|
||||
Ok(client) => client?,
|
||||
Err(error) => return Some(Err(error)),
|
||||
};
|
||||
let old_clients = self
|
||||
.inner
|
||||
@ -764,13 +767,13 @@ pub fn get<'a>(
|
||||
root_dirs: &'a [PathBuf],
|
||||
enable_snippets: bool,
|
||||
) -> impl Iterator<Item = (LanguageServerName, Result<Arc<Client>>)> + 'a {
|
||||
language_config.language_servers.iter().map(
|
||||
language_config.language_servers.iter().filter_map(
|
||||
move |LanguageServerFeatures { name, .. }| {
|
||||
if let Some(clients) = self.inner.get(name) {
|
||||
if let Some((_, client)) = clients.iter().enumerate().find(|(i, client)| {
|
||||
client.try_add_doc(&language_config.roots, root_dirs, doc_path, *i == 0)
|
||||
}) {
|
||||
return (name.to_owned(), Ok(client.clone()));
|
||||
return Some((name.to_owned(), Ok(client.clone())));
|
||||
}
|
||||
}
|
||||
match self.start_client(
|
||||
@ -781,13 +784,14 @@ pub fn get<'a>(
|
||||
enable_snippets,
|
||||
) {
|
||||
Ok(client) => {
|
||||
let client = client?;
|
||||
self.inner
|
||||
.entry(name.to_owned())
|
||||
.or_default()
|
||||
.push(client.clone());
|
||||
(name.clone(), Ok(client))
|
||||
Some((name.clone(), Ok(client)))
|
||||
}
|
||||
Err(err) => (name.to_owned(), Err(err)),
|
||||
Err(err) => Some((name.to_owned(), Err(err))),
|
||||
}
|
||||
},
|
||||
)
|
||||
@ -888,18 +892,45 @@ fn start_client(
|
||||
doc_path: Option<&std::path::PathBuf>,
|
||||
root_dirs: &[PathBuf],
|
||||
enable_snippets: bool,
|
||||
) -> Result<NewClient> {
|
||||
) -> Result<Option<NewClient>> {
|
||||
let (workspace, workspace_is_cwd) = helix_loader::find_workspace();
|
||||
let workspace = path::normalize(workspace);
|
||||
let root = find_lsp_workspace(
|
||||
doc_path
|
||||
.and_then(|x| x.parent().and_then(|x| x.to_str()))
|
||||
.unwrap_or("."),
|
||||
&config.roots,
|
||||
config.workspace_lsp_roots.as_deref().unwrap_or(root_dirs),
|
||||
&workspace,
|
||||
workspace_is_cwd,
|
||||
);
|
||||
|
||||
// `root_uri` and `workspace_folder` can be empty in case there is no workspace
|
||||
// `root_url` can not, use `workspace` as a fallback
|
||||
let root_path = root.clone().unwrap_or_else(|| workspace.clone());
|
||||
let root_uri = root.and_then(|root| lsp::Url::from_file_path(root).ok());
|
||||
|
||||
if let Some(globset) = &ls_config.required_root_patterns {
|
||||
if !root_path
|
||||
.read_dir()?
|
||||
.flatten()
|
||||
.map(|entry| entry.file_name())
|
||||
.any(|entry| globset.is_match(entry))
|
||||
{
|
||||
return Ok(None);
|
||||
}
|
||||
}
|
||||
|
||||
let (client, incoming, initialize_notify) = Client::start(
|
||||
&ls_config.command,
|
||||
&ls_config.args,
|
||||
ls_config.config.clone(),
|
||||
ls_config.environment.clone(),
|
||||
&config.roots,
|
||||
config.workspace_lsp_roots.as_deref().unwrap_or(root_dirs),
|
||||
root_path,
|
||||
root_uri,
|
||||
id,
|
||||
name,
|
||||
ls_config.timeout,
|
||||
doc_path,
|
||||
)?;
|
||||
|
||||
let client = Arc::new(client);
|
||||
@ -938,7 +969,7 @@ fn start_client(
|
||||
initialize_notify.notify_one();
|
||||
});
|
||||
|
||||
Ok(NewClient(client, incoming))
|
||||
Ok(Some(NewClient(client, incoming)))
|
||||
}
|
||||
|
||||
/// Find an LSP workspace of a file using the following mechanism:
|
||||
|
@ -18,4 +18,4 @@ ropey = { version = "1.6.1", default-features = false }
|
||||
which = "6.0"
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.9"
|
||||
tempfile = "3.10"
|
||||
|
@ -42,6 +42,7 @@ signal-hook = "0.3"
|
||||
tokio-stream = "0.1"
|
||||
futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
|
||||
arc-swap = { version = "1.6.0" }
|
||||
termini = "1"
|
||||
|
||||
# Logging
|
||||
fern = "0.6"
|
||||
@ -83,4 +84,4 @@ helix-loader = { path = "../helix-loader" }
|
||||
[dev-dependencies]
|
||||
smallvec = "1.13"
|
||||
indoc = "2.0.4"
|
||||
tempfile = "3.9.0"
|
||||
tempfile = "3.10.0"
|
||||
|
@ -96,11 +96,7 @@ fn setup_integration_logging() {
|
||||
}
|
||||
|
||||
impl Application {
|
||||
pub fn new(
|
||||
args: Args,
|
||||
config: Config,
|
||||
syn_loader_conf: syntax::Configuration,
|
||||
) -> Result<Self, Error> {
|
||||
pub fn new(args: Args, config: Config, lang_loader: syntax::Loader) -> Result<Self, Error> {
|
||||
#[cfg(feature = "integration")]
|
||||
setup_integration_logging();
|
||||
|
||||
@ -126,7 +122,7 @@ pub fn new(
|
||||
})
|
||||
.unwrap_or_else(|| theme_loader.default_theme(true_color));
|
||||
|
||||
let syn_loader = std::sync::Arc::new(syntax::Loader::new(syn_loader_conf));
|
||||
let syn_loader = std::sync::Arc::new(lang_loader);
|
||||
|
||||
#[cfg(not(feature = "integration"))]
|
||||
let backend = CrosstermBackend::new(stdout(), &config.editor);
|
||||
@ -394,10 +390,8 @@ pub fn handle_config_events(&mut self, config_event: ConfigEvent) {
|
||||
|
||||
/// refresh language config after config change
|
||||
fn refresh_language_config(&mut self) -> Result<(), Error> {
|
||||
let syntax_config = helix_core::config::user_syntax_loader()
|
||||
.map_err(|err| anyhow::anyhow!("Failed to load language config: {}", err))?;
|
||||
|
||||
self.syn_loader = std::sync::Arc::new(syntax::Loader::new(syntax_config));
|
||||
let lang_loader = helix_core::config::user_lang_loader()?;
|
||||
self.syn_loader = std::sync::Arc::new(lang_loader);
|
||||
self.editor.syn_loader = self.syn_loader.clone();
|
||||
for document in self.editor.documents.values_mut() {
|
||||
document.detect_language(self.syn_loader.clone());
|
||||
|
@ -2,7 +2,7 @@
|
||||
style::{Color, Print, Stylize},
|
||||
tty::IsTty,
|
||||
};
|
||||
use helix_core::config::{default_syntax_loader, user_syntax_loader};
|
||||
use helix_core::config::{default_lang_config, user_lang_config};
|
||||
use helix_loader::grammar::load_runtime_file;
|
||||
use helix_view::clipboard::get_clipboard_provider;
|
||||
use std::io::Write;
|
||||
@ -128,7 +128,7 @@ pub fn languages_all() -> std::io::Result<()> {
|
||||
let stdout = std::io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
|
||||
let mut syn_loader_conf = match user_syntax_loader() {
|
||||
let mut syn_loader_conf = match user_lang_config() {
|
||||
Ok(conf) => conf,
|
||||
Err(err) => {
|
||||
let stderr = std::io::stderr();
|
||||
@ -141,7 +141,7 @@ pub fn languages_all() -> std::io::Result<()> {
|
||||
err
|
||||
)?;
|
||||
writeln!(stderr, "{}", "Using default language config".yellow())?;
|
||||
default_syntax_loader()
|
||||
default_lang_config()
|
||||
}
|
||||
};
|
||||
|
||||
@ -234,7 +234,7 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
|
||||
let stdout = std::io::stdout();
|
||||
let mut stdout = stdout.lock();
|
||||
|
||||
let syn_loader_conf = match user_syntax_loader() {
|
||||
let syn_loader_conf = match user_lang_config() {
|
||||
Ok(conf) => conf,
|
||||
Err(err) => {
|
||||
let stderr = std::io::stderr();
|
||||
@ -247,7 +247,7 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
|
||||
err
|
||||
)?;
|
||||
writeln!(stderr, "{}", "Using default language config".yellow())?;
|
||||
default_syntax_loader()
|
||||
default_lang_config()
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -22,17 +22,30 @@
|
||||
|
||||
pub use keymap::macros::*;
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn true_color() -> bool {
|
||||
std::env::var("COLORTERM")
|
||||
.map(|v| matches!(v.as_str(), "truecolor" | "24bit"))
|
||||
.unwrap_or(false)
|
||||
}
|
||||
#[cfg(windows)]
|
||||
fn true_color() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn true_color() -> bool {
|
||||
if matches!(
|
||||
std::env::var("COLORTERM").map(|v| matches!(v.as_str(), "truecolor" | "24bit")),
|
||||
Ok(true)
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
match termini::TermInfo::from_env() {
|
||||
Ok(t) => {
|
||||
t.extended_cap("RGB").is_some()
|
||||
|| t.extended_cap("Tc").is_some()
|
||||
|| (t.extended_cap("setrgbf").is_some() && t.extended_cap("setrgbb").is_some())
|
||||
}
|
||||
Err(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Function used for filtering dir entries in the various file pickers.
|
||||
fn filter_picker_entry(entry: &DirEntry, root: &Path, dedup_symlinks: bool) -> bool {
|
||||
// We always want to ignore the .git directory, otherwise if
|
||||
|
@ -145,18 +145,18 @@ async fn main_impl() -> Result<i32> {
|
||||
}
|
||||
};
|
||||
|
||||
let syn_loader_conf = helix_core::config::user_syntax_loader().unwrap_or_else(|err| {
|
||||
eprintln!("Bad language config: {}", err);
|
||||
let lang_loader = helix_core::config::user_lang_loader().unwrap_or_else(|err| {
|
||||
eprintln!("{}", err);
|
||||
eprintln!("Press <ENTER> to continue with default language config");
|
||||
use std::io::Read;
|
||||
// This waits for an enter press.
|
||||
let _ = std::io::stdin().read(&mut []);
|
||||
helix_core::config::default_syntax_loader()
|
||||
helix_core::config::default_lang_loader()
|
||||
});
|
||||
|
||||
// TODO: use the thread local executor to spawn the application task separately from the work pool
|
||||
let mut app = Application::new(args, config, syn_loader_conf)
|
||||
.context("unable to create new application")?;
|
||||
let mut app =
|
||||
Application::new(args, config, lang_loader).context("unable to create new application")?;
|
||||
|
||||
let exit_code = app.run(&mut EventStream::new()).await?;
|
||||
|
||||
|
@ -315,7 +315,7 @@ async fn test_write_auto_format_fails_still_writes() -> anyhow::Result<()> {
|
||||
let mut app = helpers::AppBuilder::new()
|
||||
.with_file(file.path(), None)
|
||||
.with_input_text("#[l|]#et foo = 0;\n")
|
||||
.with_lang_config(helpers::test_syntax_conf(Some(lang_conf.into())))
|
||||
.with_lang_loader(helpers::test_syntax_loader(Some(lang_conf.into())))
|
||||
.build()?;
|
||||
|
||||
test_key_sequences(&mut app, vec![(Some(":w<ret>"), None)], false).await?;
|
||||
|
@ -139,7 +139,7 @@ pub async fn test_key_sequence_with_input_text<T: Into<TestCase>>(
|
||||
let test_case = test_case.into();
|
||||
let mut app = match app {
|
||||
Some(app) => app,
|
||||
None => Application::new(Args::default(), test_config(), test_syntax_conf(None))?,
|
||||
None => Application::new(Args::default(), test_config(), test_syntax_loader(None))?,
|
||||
};
|
||||
|
||||
let (view, doc) = helix_view::current!(app.editor);
|
||||
@ -162,9 +162,9 @@ pub async fn test_key_sequence_with_input_text<T: Into<TestCase>>(
|
||||
.await
|
||||
}
|
||||
|
||||
/// Generates language configs that merge in overrides, like a user language
|
||||
/// Generates language config loader that merge in overrides, like a user language
|
||||
/// config. The argument string must be a raw TOML document.
|
||||
pub fn test_syntax_conf(overrides: Option<String>) -> helix_core::syntax::Configuration {
|
||||
pub fn test_syntax_loader(overrides: Option<String>) -> helix_core::syntax::Loader {
|
||||
let mut lang = helix_loader::config::default_lang_config();
|
||||
|
||||
if let Some(overrides) = overrides {
|
||||
@ -172,7 +172,7 @@ pub fn test_syntax_conf(overrides: Option<String>) -> helix_core::syntax::Config
|
||||
lang = helix_loader::merge_toml_values(lang, override_toml, 3);
|
||||
}
|
||||
|
||||
lang.try_into().unwrap()
|
||||
helix_core::syntax::Loader::new(lang.try_into().unwrap()).unwrap()
|
||||
}
|
||||
|
||||
/// Use this for very simple test cases where there is one input
|
||||
@ -271,7 +271,7 @@ pub fn new_readonly_tempfile() -> anyhow::Result<NamedTempFile> {
|
||||
pub struct AppBuilder {
|
||||
args: Args,
|
||||
config: Config,
|
||||
syn_conf: helix_core::syntax::Configuration,
|
||||
syn_loader: helix_core::syntax::Loader,
|
||||
input: Option<(String, Selection)>,
|
||||
}
|
||||
|
||||
@ -280,7 +280,7 @@ fn default() -> Self {
|
||||
Self {
|
||||
args: Args::default(),
|
||||
config: test_config(),
|
||||
syn_conf: test_syntax_conf(None),
|
||||
syn_loader: test_syntax_loader(None),
|
||||
input: None,
|
||||
}
|
||||
}
|
||||
@ -314,8 +314,8 @@ pub fn with_input_text<S: Into<String>>(mut self, input_text: S) -> Self {
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_lang_config(mut self, syn_conf: helix_core::syntax::Configuration) -> Self {
|
||||
self.syn_conf = syn_conf;
|
||||
pub fn with_lang_loader(mut self, syn_loader: helix_core::syntax::Loader) -> Self {
|
||||
self.syn_loader = syn_loader;
|
||||
self
|
||||
}
|
||||
|
||||
@ -328,7 +328,7 @@ pub fn build(self) -> anyhow::Result<Application> {
|
||||
bail!("Having the directory {path:?} in args.files[0] is not yet supported for integration tests");
|
||||
}
|
||||
|
||||
let mut app = Application::new(self.args, self.config, self.syn_conf)?;
|
||||
let mut app = Application::new(self.args, self.config, self.syn_loader)?;
|
||||
|
||||
if let Some((text, selection)) = self.input {
|
||||
let (view, doc) = helix_view::current!(app.editor);
|
||||
|
@ -29,4 +29,4 @@ log = "0.4"
|
||||
git = ["gix"]
|
||||
|
||||
[dev-dependencies]
|
||||
tempfile = "3.9"
|
||||
tempfile = "3.10"
|
||||
|
194
languages.toml
194
languages.toml
@ -253,7 +253,7 @@ source = { git = "https://github.com/FuelLabs/tree-sitter-sway", rev = "e491a005
|
||||
name = "toml"
|
||||
scope = "source.toml"
|
||||
injection-regex = "toml"
|
||||
file-types = ["toml", "poetry.lock", "Cargo.lock"]
|
||||
file-types = ["toml", { glob = "poetry.lock" }, { glob = "Cargo.lock" }]
|
||||
comment-token = "#"
|
||||
language-servers = [ "taplo" ]
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
@ -292,7 +292,7 @@ source = { git = "https://github.com/yusdacra/tree-sitter-protobuf", rev = "19c2
|
||||
name = "elixir"
|
||||
scope = "source.elixir"
|
||||
injection-regex = "(elixir|ex)"
|
||||
file-types = ["ex", "exs", "mix.lock"]
|
||||
file-types = ["ex", "exs", { glob = "mix.lock" }]
|
||||
shebangs = ["elixir"]
|
||||
roots = ["mix.exs", "mix.lock"]
|
||||
comment-token = "#"
|
||||
@ -361,20 +361,20 @@ file-types = [
|
||||
"geojson",
|
||||
"gltf",
|
||||
"webmanifest",
|
||||
"flake.lock",
|
||||
".babelrc",
|
||||
".bowerrc",
|
||||
".jscrc",
|
||||
{ glob = "flake.lock" },
|
||||
{ glob = ".babelrc" },
|
||||
{ glob = ".bowerrc" },
|
||||
{ glob = ".jscrc" },
|
||||
"js.map",
|
||||
"ts.map",
|
||||
"css.map",
|
||||
".jslintrc",
|
||||
{ glob = ".jslintrc" },
|
||||
"jsonld",
|
||||
".vuerc",
|
||||
"composer.lock",
|
||||
".watchmanconfig",
|
||||
{ glob = ".vuerc" },
|
||||
{ glob = "composer.lock" },
|
||||
{ glob = ".watchmanconfig" },
|
||||
"avsc",
|
||||
".prettierrc"
|
||||
{ glob = ".prettierrc" },
|
||||
]
|
||||
language-servers = [ "vscode-json-language-server" ]
|
||||
auto-format = true
|
||||
@ -439,7 +439,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-c", rev = "7175a6dd
|
||||
name = "cpp"
|
||||
scope = "source.cpp"
|
||||
injection-regex = "cpp"
|
||||
file-types = ["cc", "hh", "c++", "cpp", "hpp", "h", "ipp", "tpp", "cxx", "hxx", "ixx", "txx", "ino", "C", "H", "cu", "cuh", "cppm", "h++", "ii", "inl", { suffix = ".hpp.in" }, { suffix = ".h.in" }]
|
||||
file-types = ["cc", "hh", "c++", "cpp", "hpp", "h", "ipp", "tpp", "cxx", "hxx", "ixx", "txx", "ino", "C", "H", "cu", "cuh", "cppm", "h++", "ii", "inl", { glob = ".hpp.in" }, { glob = ".h.in" }]
|
||||
comment-token = "//"
|
||||
language-servers = [ "clangd" ]
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
@ -514,6 +514,30 @@ args = { processId = "{0}" }
|
||||
name = "c-sharp"
|
||||
source = { git = "https://github.com/tree-sitter/tree-sitter-c-sharp", rev = "5b60f99545fea00a33bbfae5be956f684c4c69e2" }
|
||||
|
||||
[[language]]
|
||||
name = "cel"
|
||||
scope = "source.cel"
|
||||
injection-regex = "cel"
|
||||
file-types = ["cel"]
|
||||
comment-token = "//"
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
|
||||
[[grammar]]
|
||||
name = "cel"
|
||||
source = { git = "https://github.com/bufbuild/tree-sitter-cel", rev = "9f2b65da14c216df53933748e489db0f11121464" }
|
||||
|
||||
[[language]]
|
||||
name = "spicedb"
|
||||
scope = "source.zed"
|
||||
injection-regex = "spicedb"
|
||||
file-types = ["zed"]
|
||||
comment-token = "//"
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
|
||||
[[grammar]]
|
||||
name = "spicedb"
|
||||
source = { git = "https://github.com/jzelinskie/tree-sitter-spicedb", rev = "a4e4645651f86d6684c15dfa9931b7841dc52a66" }
|
||||
|
||||
[[language]]
|
||||
name = "go"
|
||||
scope = "source.go"
|
||||
@ -571,7 +595,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "64457ea
|
||||
name = "gomod"
|
||||
scope = "source.gomod"
|
||||
injection-regex = "gomod"
|
||||
file-types = ["go.mod"]
|
||||
file-types = [{ glob = "go.mod" }]
|
||||
auto-format = true
|
||||
comment-token = "//"
|
||||
language-servers = [ "gopls" ]
|
||||
@ -598,7 +622,7 @@ source = { git = "https://github.com/dannylongeuay/tree-sitter-go-template", rev
|
||||
name = "gowork"
|
||||
scope = "source.gowork"
|
||||
injection-regex = "gowork"
|
||||
file-types = ["go.work"]
|
||||
file-types = [{ glob = "go.work" }]
|
||||
auto-format = true
|
||||
comment-token = "//"
|
||||
language-servers = [ "gopls" ]
|
||||
@ -613,7 +637,7 @@ name = "javascript"
|
||||
scope = "source.js"
|
||||
injection-regex = "(js|javascript)"
|
||||
language-id = "javascript"
|
||||
file-types = ["js", "mjs", "cjs", "rules", "es6", "pac", "jakefile"]
|
||||
file-types = ["js", "mjs", "cjs", "rules", "es6", "pac", { glob = "jakefile" }]
|
||||
shebangs = ["node"]
|
||||
comment-token = "//"
|
||||
language-servers = [ "typescript-language-server" ]
|
||||
@ -716,7 +740,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-html", rev = "29f53
|
||||
name = "python"
|
||||
scope = "source.python"
|
||||
injection-regex = "python"
|
||||
file-types = ["py","pyi","py3","pyw","ptl",".pythonstartup",".pythonrc","SConstruct", "rpy", "cpy", "ipy", "pyt", "SConscript"]
|
||||
file-types = ["py", "pyi", "py3", "pyw", "ptl", "rpy", "cpy", "ipy", "pyt", { glob = ".pythonstartup" }, { glob = ".pythonrc" }, { glob = "SConstruct" }, { glob = "SConscript" }]
|
||||
shebangs = ["python"]
|
||||
roots = ["pyproject.toml", "setup.py", "poetry.lock", "pyrightconfig.json"]
|
||||
comment-token = "#"
|
||||
@ -769,38 +793,38 @@ injection-regex = "ruby"
|
||||
file-types = [
|
||||
"rb",
|
||||
"rake",
|
||||
"rakefile",
|
||||
"irb",
|
||||
"gemfile",
|
||||
"gemspec",
|
||||
"Rakefile",
|
||||
"Gemfile",
|
||||
"rabl",
|
||||
"jbuilder",
|
||||
"jb",
|
||||
"Podfile",
|
||||
"podspec",
|
||||
"Vagrantfile",
|
||||
"Brewfile",
|
||||
"rjs",
|
||||
"rbi",
|
||||
"Guardfile",
|
||||
"Capfile",
|
||||
"Cheffile",
|
||||
"Hobofile",
|
||||
"Appraisals",
|
||||
"Rantfile",
|
||||
"Berksfile",
|
||||
"Berksfile.lock",
|
||||
"Thorfile",
|
||||
"Puppetfile",
|
||||
"Fastfile",
|
||||
"Appfile",
|
||||
"Deliverfile",
|
||||
"Matchfile",
|
||||
"Scanfile",
|
||||
"Snapfile",
|
||||
"Gymfile"
|
||||
{ glob = "rakefile" },
|
||||
{ glob = "gemfile" },
|
||||
{ glob = "Rakefile" },
|
||||
{ glob = "Gemfile" },
|
||||
{ glob = "Podfile" },
|
||||
{ glob = "Vagrantfile" },
|
||||
{ glob = "Brewfile" },
|
||||
{ glob = "Guardfile" },
|
||||
{ glob = "Capfile" },
|
||||
{ glob = "Cheffile" },
|
||||
{ glob = "Hobofile" },
|
||||
{ glob = "Appraisals" },
|
||||
{ glob = "Rantfile" },
|
||||
{ glob = "Berksfile" },
|
||||
{ glob = "Berksfile.lock" },
|
||||
{ glob = "Thorfile" },
|
||||
{ glob = "Puppetfile" },
|
||||
{ glob = "Fastfile" },
|
||||
{ glob = "Appfile" },
|
||||
{ glob = "Deliverfile" },
|
||||
{ glob = "Matchfile" },
|
||||
{ glob = "Scanfile" },
|
||||
{ glob = "Snapfile" },
|
||||
{ glob = "Gymfile" },
|
||||
]
|
||||
shebangs = ["ruby"]
|
||||
comment-token = "#"
|
||||
@ -819,43 +843,43 @@ file-types = [
|
||||
"sh",
|
||||
"bash",
|
||||
"zsh",
|
||||
".bash_history",
|
||||
".bash_login",
|
||||
".bash_logout",
|
||||
".bash_profile",
|
||||
".bashrc",
|
||||
".profile",
|
||||
".zshenv",
|
||||
"zshenv",
|
||||
".zlogin",
|
||||
"zlogin",
|
||||
".zlogout",
|
||||
"zlogout",
|
||||
".zprofile",
|
||||
"zprofile",
|
||||
".zshrc",
|
||||
"zshrc",
|
||||
".zimrc",
|
||||
"APKBUILD",
|
||||
"PKGBUILD",
|
||||
"eclass",
|
||||
"ebuild",
|
||||
"bazelrc",
|
||||
".bash_aliases",
|
||||
"Renviron",
|
||||
".Renviron",
|
||||
".xprofile",
|
||||
".xsession",
|
||||
".xsessionrc",
|
||||
"zsh-theme",
|
||||
"ksh",
|
||||
"cshrc",
|
||||
"tcshrc",
|
||||
".yashrc",
|
||||
".yash_profile",
|
||||
".hushlogin",
|
||||
"bashrc_Apple_Terminal",
|
||||
"zshrc_Apple_Terminal"
|
||||
"zshrc_Apple_Terminal",
|
||||
{ glob = ".bash_history" },
|
||||
{ glob = ".bash_login" },
|
||||
{ glob = ".bash_logout" },
|
||||
{ glob = ".bash_profile" },
|
||||
{ glob = ".bashrc" },
|
||||
{ glob = ".profile" },
|
||||
{ glob = ".zshenv" },
|
||||
{ glob = ".zlogin" },
|
||||
{ glob = ".zlogout" },
|
||||
{ glob = ".zprofile" },
|
||||
{ glob = ".zshrc" },
|
||||
{ glob = ".zimrc" },
|
||||
{ glob = "APKBUILD" },
|
||||
{ glob = "PKGBUILD" },
|
||||
{ glob = ".bash_aliases" },
|
||||
{ glob = ".Renviron" },
|
||||
{ glob = ".xprofile" },
|
||||
{ glob = ".xsession" },
|
||||
{ glob = ".xsessionrc" },
|
||||
{ glob = ".yashrc" },
|
||||
{ glob = ".yash_profile" },
|
||||
{ glob = ".hushlogin" },
|
||||
]
|
||||
shebangs = ["sh", "bash", "dash", "zsh"]
|
||||
comment-token = "#"
|
||||
@ -1216,7 +1240,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-tsq", rev = "48b5
|
||||
[[language]]
|
||||
name = "cmake"
|
||||
scope = "source.cmake"
|
||||
file-types = ["cmake", "CMakeLists.txt"]
|
||||
file-types = ["cmake", { glob = "CMakeLists.txt" }]
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
language-servers = [ "cmake-language-server" ]
|
||||
@ -1229,7 +1253,7 @@ source = { git = "https://github.com/uyha/tree-sitter-cmake", rev = "6e51463ef30
|
||||
[[language]]
|
||||
name = "make"
|
||||
scope = "source.make"
|
||||
file-types = ["Makefile", "makefile", "make", "mk", "mak", "GNUmakefile", "OCamlMakefile"]
|
||||
file-types = [{ glob = "Makefile" }, { glob = "makefile" }, "make", "mk", "mak", {glob = "GNUmakefile" }, { glob = "OCamlMakefile" }]
|
||||
shebangs = ["make", "gmake"]
|
||||
injection-regex = "(make|makefile|Makefile|mk)"
|
||||
comment-token = "#"
|
||||
@ -1372,7 +1396,7 @@ source = { git = "https://github.com/Flakebi/tree-sitter-tablegen", rev = "568dd
|
||||
name = "markdown"
|
||||
scope = "source.md"
|
||||
injection-regex = "md|markdown"
|
||||
file-types = ["md", "markdown", "PULLREQ_EDITMSG", "mkd", "mdwn", "mdown", "markdn", "mdtxt", "mdtext", "workbook"]
|
||||
file-types = ["md", "markdown", "mkd", "mdwn", "mdown", "markdn", "mdtxt", "mdtext", "workbook", { glob = "PULLREQ_EDITMSG" }]
|
||||
roots = [".marksman.toml"]
|
||||
language-servers = [ "marksman" ]
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
@ -1424,7 +1448,7 @@ name = "dockerfile"
|
||||
scope = "source.dockerfile"
|
||||
injection-regex = "docker|dockerfile"
|
||||
roots = ["Dockerfile", "Containerfile"]
|
||||
file-types = ["Dockerfile", "dockerfile", "Containerfile", "containerfile"]
|
||||
file-types = [{ glob = "Dockerfile*" }, { glob = "dockerfile*" }, { glob = "Containerfile*" }, { glob = "containerfile*" }]
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
language-servers = [ "docker-langserver" ]
|
||||
@ -1436,7 +1460,7 @@ source = { git = "https://github.com/camdencheek/tree-sitter-dockerfile", rev =
|
||||
[[language]]
|
||||
name = "git-commit"
|
||||
scope = "git.commitmsg"
|
||||
file-types = ["COMMIT_EDITMSG"]
|
||||
file-types = [{ glob = "COMMIT_EDITMSG" }]
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
rulers = [51, 73]
|
||||
@ -1461,7 +1485,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-diff", rev = "fd7
|
||||
[[language]]
|
||||
name = "git-rebase"
|
||||
scope = "source.gitrebase"
|
||||
file-types = ["git-rebase-todo"]
|
||||
file-types = [{ glob = "git-rebase-todo" }]
|
||||
injection-regex = "git-rebase"
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 2, unit = "y" }
|
||||
@ -1474,7 +1498,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-git-rebase", rev
|
||||
name = "regex"
|
||||
scope = "source.regex"
|
||||
injection-regex = "regex"
|
||||
file-types = ["regex", ".Rbuildignore"]
|
||||
file-types = ["regex", { glob = ".Rbuildignore" }]
|
||||
|
||||
[[grammar]]
|
||||
name = "regex"
|
||||
@ -1483,7 +1507,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-regex", rev = "e1cf
|
||||
[[language]]
|
||||
name = "git-config"
|
||||
scope = "source.gitconfig"
|
||||
file-types = [".gitmodules", ".gitconfig", { suffix = ".git/config" }, { suffix = ".config/git/config" }]
|
||||
file-types = [{ glob = ".gitmodules" }, { glob = ".gitconfig" }, { glob = ".git/config" }, { glob = ".config/git/config" }]
|
||||
injection-regex = "git-config"
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 4, unit = "\t" }
|
||||
@ -1495,7 +1519,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-git-config", rev
|
||||
[[language]]
|
||||
name = "git-attributes"
|
||||
scope = "source.gitattributes"
|
||||
file-types = [".gitattributes"]
|
||||
file-types = [{ glob = ".gitattributes" }]
|
||||
injection-regex = "git-attributes"
|
||||
comment-token = "#"
|
||||
grammar = "gitattributes"
|
||||
@ -1507,7 +1531,7 @@ source = { git = "https://github.com/mtoohey31/tree-sitter-gitattributes", rev =
|
||||
[[language]]
|
||||
name = "git-ignore"
|
||||
scope = "source.gitignore"
|
||||
file-types = [".gitignore", ".gitignore_global", ".ignore", ".prettierignore", ".eslintignore", ".npmignore", "CODEOWNERS", { suffix = ".config/helix/ignore" }, { suffix = ".helix/ignore" }]
|
||||
file-types = [{ glob = ".gitignore" }, { glob = ".gitignore_global" }, { glob = ".ignore" }, { glob = ".prettierignore" }, { glob = ".eslintignore" }, { glob = ".npmignore"}, { glob = "CODEOWNERS" }, { glob = ".config/helix/ignore" }, { glob = ".helix/ignore" }]
|
||||
injection-regex = "git-ignore"
|
||||
comment-token = "#"
|
||||
grammar = "gitignore"
|
||||
@ -1572,7 +1596,7 @@ source = { git = "https://github.com/jaredramirez/tree-sitter-rescript", rev = "
|
||||
name = "erlang"
|
||||
scope = "source.erlang"
|
||||
injection-regex = "erl(ang)?"
|
||||
file-types = ["erl", "hrl", "app", "rebar.config", "rebar.lock"]
|
||||
file-types = ["erl", "hrl", "app", { glob = "rebar.config" }, { glob = "rebar.lock" }]
|
||||
roots = ["rebar.config"]
|
||||
shebangs = ["escript"]
|
||||
comment-token = "%%"
|
||||
@ -1698,7 +1722,7 @@ source = { git = "https://github.com/Hubro/tree-sitter-robot", rev = "322e4cc657
|
||||
name = "r"
|
||||
scope = "source.r"
|
||||
injection-regex = "(r|R)"
|
||||
file-types = ["r", "R", ".Rprofile", "Rprofile.site", ".RHistory"]
|
||||
file-types = ["r", "R", { glob = ".Rprofile" }, { glob = "Rprofile.site" }, { glob = ".RHistory" }]
|
||||
shebangs = ["r", "R"]
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
@ -1730,7 +1754,7 @@ language-servers = [ "sourcekit-lsp" ]
|
||||
|
||||
[[grammar]]
|
||||
name = "swift"
|
||||
source = { git = "https://github.com/alex-pinkus/tree-sitter-swift", rev = "77c6312c8438f4dbaa0350cec92b3d6dd3d74a66" }
|
||||
source = { git = "https://github.com/alex-pinkus/tree-sitter-swift", rev = "b1b66955d420d5cf5ff268ae552f0d6e43ff66e1" }
|
||||
|
||||
[[language]]
|
||||
name = "erb"
|
||||
@ -1913,7 +1937,7 @@ source = { git = "https://github.com/ap29600/tree-sitter-odin", rev = "b219207e4
|
||||
name = "meson"
|
||||
scope = "source.meson"
|
||||
injection-regex = "meson"
|
||||
file-types = ["meson.build", "meson_options.txt"]
|
||||
file-types = [{ glob = "meson.build" }, { glob = "meson_options.txt" }]
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
|
||||
@ -1924,7 +1948,7 @@ source = { git = "https://github.com/staysail/tree-sitter-meson", rev = "32a83e8
|
||||
[[language]]
|
||||
name = "sshclientconfig"
|
||||
scope = "source.sshclientconfig"
|
||||
file-types = [{ suffix = ".ssh/config" }, { suffix = "/etc/ssh/ssh_config" }]
|
||||
file-types = [{ glob = ".ssh/config" }, { glob = "/etc/ssh/ssh_config" }]
|
||||
comment-token = "#"
|
||||
|
||||
[[grammar]]
|
||||
@ -2045,7 +2069,7 @@ source = { git = "https://github.com/sogaiu/tree-sitter-clojure", rev = "e57c569
|
||||
name = "starlark"
|
||||
scope = "source.starlark"
|
||||
injection-regex = "(starlark|bzl|bazel)"
|
||||
file-types = ["bzl", "bazel", "BUILD", "star"]
|
||||
file-types = ["bzl", "bazel", "star", { glob = "BUILD" }, { glob = "BUILD.*" }]
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 4, unit = " " }
|
||||
grammar = "python"
|
||||
@ -2413,7 +2437,7 @@ source = { git = "https://github.com/hh9527/tree-sitter-wit", rev = "c917790ab9a
|
||||
[[language]]
|
||||
name = "env"
|
||||
scope = "source.env"
|
||||
file-types = [".env", ".env.local", ".env.development", ".env.production", ".env.dist", ".envrc", ".envrc.local", ".envrc.private"]
|
||||
file-types = [{ glob = ".env" }, { glob = ".env.*" }, { glob = ".envrc" }, { glob = ".envrc.*" }]
|
||||
injection-regex = "env"
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 4, unit = "\t" }
|
||||
@ -2441,7 +2465,7 @@ file-types = [
|
||||
"volume",
|
||||
"kube",
|
||||
"network",
|
||||
".editorconfig",
|
||||
{ glob = ".editorconfig" },
|
||||
"properties",
|
||||
"cfg",
|
||||
"directory"
|
||||
@ -2569,7 +2593,7 @@ source = { git = "https://github.com/mtoohey31/tree-sitter-pem", rev = "be67a433
|
||||
[[language]]
|
||||
name = "passwd"
|
||||
scope = "source.passwd"
|
||||
file-types = ["passwd"]
|
||||
file-types = [{ glob = "passwd" }]
|
||||
|
||||
[[grammar]]
|
||||
name = "passwd"
|
||||
@ -2578,7 +2602,7 @@ source = { git = "https://github.com/ath3/tree-sitter-passwd", rev = "20239395ea
|
||||
[[language]]
|
||||
name = "hosts"
|
||||
scope = "source.hosts"
|
||||
file-types = ["hosts"]
|
||||
file-types = [{ glob = "hosts" }]
|
||||
comment-token = "#"
|
||||
|
||||
[[grammar]]
|
||||
@ -2786,7 +2810,7 @@ source = { git = "https://github.com/lefp/tree-sitter-opencl", rev = "8e1d24a570
|
||||
[[language]]
|
||||
name = "just"
|
||||
scope = "source.just"
|
||||
file-types = ["justfile", "Justfile", ".justfile", ".Justfile"]
|
||||
file-types = [{ glob = "justfile" }, { glob = "Justfile" }, { glob = ".justfile" }, { glob = ".Justfile" }]
|
||||
injection-regex = "just"
|
||||
comment-token = "#"
|
||||
indent = { tab-width = 4, unit = "\t" }
|
||||
@ -2945,7 +2969,7 @@ source = { git = "https://github.com/kylegoetz/tree-sitter-unison", rev = "1f505
|
||||
[[language]]
|
||||
name = "todotxt"
|
||||
scope = "text.todotxt"
|
||||
file-types = [{ suffix = ".todo.txt" }, "todotxt"]
|
||||
file-types = [{ glob = "todo.txt" }, { glob = "*.todo.txt" }, "todotxt"]
|
||||
formatter = { command = "sort" }
|
||||
auto-format = true
|
||||
|
||||
|
66
runtime/queries/cel/highlights.scm
Normal file
66
runtime/queries/cel/highlights.scm
Normal file
@ -0,0 +1,66 @@
|
||||
; Operators
|
||||
|
||||
[
|
||||
"-"
|
||||
"!"
|
||||
"*"
|
||||
"/"
|
||||
"&&"
|
||||
"%"
|
||||
"+"
|
||||
"<"
|
||||
"<="
|
||||
"=="
|
||||
">"
|
||||
">="
|
||||
"||"
|
||||
] @operator
|
||||
|
||||
; Keywords
|
||||
|
||||
[
|
||||
"in"
|
||||
] @keyword
|
||||
|
||||
; Function calls
|
||||
|
||||
(call_expression
|
||||
function: (identifier) @function)
|
||||
|
||||
(member_call_expression
|
||||
function: (identifier) @function)
|
||||
|
||||
; Identifiers
|
||||
|
||||
(select_expression
|
||||
operand: (identifier) @type)
|
||||
|
||||
(select_expression
|
||||
operand: (select_expression
|
||||
member: (identifier) @type))
|
||||
|
||||
(identifier) @variable.other.member
|
||||
|
||||
; Literals
|
||||
|
||||
[
|
||||
(double_quote_string_literal)
|
||||
(single_quoted_string_literal)
|
||||
(triple_double_quote_string_literal)
|
||||
(triple_single_quoted_string_literal)
|
||||
] @string
|
||||
|
||||
[
|
||||
(int_literal)
|
||||
(uint_literal)
|
||||
] @constant.numeric.integer
|
||||
(float_literal) @constant.numeric.float
|
||||
|
||||
[
|
||||
(true)
|
||||
(false)
|
||||
] @constant.builtin.boolean
|
||||
|
||||
(null) @constant.builtin
|
||||
|
||||
(comment) @comment
|
47
runtime/queries/spicedb/highlights.scm
Normal file
47
runtime/queries/spicedb/highlights.scm
Normal file
@ -0,0 +1,47 @@
|
||||
; highlights.scm
|
||||
|
||||
[
|
||||
"definition"
|
||||
"caveat"
|
||||
"permission"
|
||||
"relation"
|
||||
"nil"
|
||||
] @keyword
|
||||
|
||||
[
|
||||
","
|
||||
":"
|
||||
] @punctuation.delimiter
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"{"
|
||||
"}"
|
||||
] @punctuation.bracket
|
||||
|
||||
[
|
||||
"|"
|
||||
"+"
|
||||
"-"
|
||||
"&"
|
||||
"#"
|
||||
"->"
|
||||
"="
|
||||
] @operator
|
||||
("with") @keyword.operator
|
||||
|
||||
[
|
||||
"nil"
|
||||
"*"
|
||||
] @constant.builtin
|
||||
|
||||
(comment) @comment
|
||||
(type_identifier) @type
|
||||
(cel_type_identifier) @type
|
||||
(cel_variable_identifier) @variable.parameter
|
||||
(field_identifier) @variable.other.member
|
||||
[
|
||||
(func_identifier)
|
||||
(method_identifier)
|
||||
] @function.method
|
5
runtime/queries/spicedb/injections.scm
Normal file
5
runtime/queries/spicedb/injections.scm
Normal file
@ -0,0 +1,5 @@
|
||||
((comment) @injection.content
|
||||
(#set! injection.language "comment"))
|
||||
|
||||
((caveat_expr) @injection.content
|
||||
(#set! injection.language "cel"))
|
4
runtime/queries/spicedb/tags.scm
Normal file
4
runtime/queries/spicedb/tags.scm
Normal file
@ -0,0 +1,4 @@
|
||||
(object_definition
|
||||
name: (type_identifier) @name) @definition.type
|
||||
|
||||
(type_identifier) @name @reference.type
|
@ -1,10 +1,10 @@
|
||||
; Upstream: https://github.com/alex-pinkus/tree-sitter-swift/blob/8d2fd80e3322df51e3f70952e60d57f5d4077eb8/queries/highlights.scm
|
||||
; Upstream: https://github.com/alex-pinkus/tree-sitter-swift/blob/1c586339fb00014b23d6933f2cc32b588a226f3b/queries/highlights.scm
|
||||
|
||||
(line_string_literal
|
||||
["\\(" ")"] @punctuation.special)
|
||||
|
||||
["." ";" ":" "," ] @punctuation.delimiter
|
||||
["(" ")" "[" "]" "{" "}"] @punctuation.bracket ; TODO: "\\(" ")" in interpolations should be @punctuation.special
|
||||
["(" ")" "[" "]" "{" "}"] @punctuation.bracket
|
||||
|
||||
; Identifiers
|
||||
(attribute) @variable
|
||||
@ -26,6 +26,7 @@
|
||||
(function_declaration "init" @constructor)
|
||||
(throws) @keyword
|
||||
"async" @keyword
|
||||
"await" @keyword
|
||||
(where_keyword) @keyword
|
||||
(parameter external_name: (simple_identifier) @variable.parameter)
|
||||
(parameter name: (simple_identifier) @variable.parameter)
|
||||
@ -48,6 +49,7 @@
|
||||
"convenience"
|
||||
"required"
|
||||
"some"
|
||||
"any"
|
||||
] @keyword
|
||||
|
||||
[
|
||||
|
@ -63,6 +63,9 @@
|
||||
"ui.cursorline.primary" = { bg = "bg1" }
|
||||
"ui.statusline" = { fg = "fg", bg = "bg3" }
|
||||
"ui.statusline.inactive" = { fg = "grey", bg = "bg1" }
|
||||
"ui.statusline.normal" = { fg = "bg0", bg = "blue", modifiers = ["bold"] }
|
||||
"ui.statusline.insert" = { fg = "bg0", bg = "green", modifiers = ["bold"] }
|
||||
"ui.statusline.select" = { fg = "bg0", bg = "purple", modifiers = ["bold"] }
|
||||
"ui.popup" = { fg = "grey", bg = "bg2" }
|
||||
"ui.window" = { fg = "grey", bg = "bg0" }
|
||||
"ui.help" = { fg = "fg", bg = "bg1" }
|
||||
@ -71,7 +74,7 @@
|
||||
"ui.menu" = { fg = "fg", bg = "bg2" }
|
||||
"ui.menu.selected" = { fg = "bg0", bg = "green" }
|
||||
"ui.virtual.whitespace" = { fg = "grey_dim" }
|
||||
"ui.virtual.ruler" = { bg = "grey_dim" }
|
||||
"ui.virtual.ruler" = { bg = "bg3" }
|
||||
"ui.virtual.inlay-hint" = { fg = "grey_dim" }
|
||||
|
||||
info = { fg = 'green', bg = 'bg2' }
|
||||
|
Loading…
Reference in New Issue
Block a user