mirror of
https://github.com/ilyakooo0/helix.git
synced 2024-08-17 20:10:26 +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]]
|
[[package]]
|
||||||
name = "fastrand"
|
name = "fastrand"
|
||||||
version = "2.0.0"
|
version = "2.0.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6999dc1837253364c2ebb0704ba97994bd874e8f195d665c50b7548f6ea92764"
|
checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "fern"
|
name = "fern"
|
||||||
@ -1240,6 +1240,7 @@ dependencies = [
|
|||||||
"dunce",
|
"dunce",
|
||||||
"encoding_rs",
|
"encoding_rs",
|
||||||
"etcetera",
|
"etcetera",
|
||||||
|
"globset",
|
||||||
"hashbrown 0.14.3",
|
"hashbrown 0.14.3",
|
||||||
"helix-loader",
|
"helix-loader",
|
||||||
"helix-stdx",
|
"helix-stdx",
|
||||||
@ -1386,6 +1387,7 @@ dependencies = [
|
|||||||
"signal-hook-tokio",
|
"signal-hook-tokio",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"tempfile",
|
"tempfile",
|
||||||
|
"termini",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"toml",
|
"toml",
|
||||||
@ -1971,9 +1973,9 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.30"
|
version = "0.38.31"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "322394588aaf33c24007e8bb3238ee3e4c5c09c084ab32bc73890b99ff326bca"
|
checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags 2.4.2",
|
"bitflags 2.4.2",
|
||||||
"errno",
|
"errno",
|
||||||
@ -2201,13 +2203,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.9.0"
|
version = "3.10.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "01ce4141aa927a6d1bd34a041795abd0db1cccba5d5f24b009f694bdf3a1f3fa"
|
checksum = "a365e8cd18e44762ef95d87f284f4b5cd04107fec2ff3052bd6a3e6069669e67"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"fastrand",
|
"fastrand",
|
||||||
"redox_syscall 0.4.1",
|
|
||||||
"rustix",
|
"rustix",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
@ -2316,9 +2317,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.35.1"
|
version = "1.36.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c89b4efa943be685f629b149f53829423f8f5531ea21249408e8e2f8671ec104"
|
checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
| cabal | | | | `haskell-language-server-wrapper` |
|
| cabal | | | | `haskell-language-server-wrapper` |
|
||||||
| cairo | ✓ | ✓ | ✓ | `cairo-language-server` |
|
| cairo | ✓ | ✓ | ✓ | `cairo-language-server` |
|
||||||
| capnp | ✓ | | ✓ | |
|
| capnp | ✓ | | ✓ | |
|
||||||
|
| cel | ✓ | | | |
|
||||||
| clojure | ✓ | | | `clojure-lsp` |
|
| clojure | ✓ | | | `clojure-lsp` |
|
||||||
| cmake | ✓ | ✓ | ✓ | `cmake-language-server` |
|
| cmake | ✓ | ✓ | ✓ | `cmake-language-server` |
|
||||||
| comment | ✓ | | | |
|
| comment | ✓ | | | |
|
||||||
@ -68,8 +69,8 @@
|
|||||||
| haskell-persistent | ✓ | | | |
|
| haskell-persistent | ✓ | | | |
|
||||||
| hcl | ✓ | | ✓ | `terraform-ls` |
|
| hcl | ✓ | | ✓ | `terraform-ls` |
|
||||||
| heex | ✓ | ✓ | | `elixir-ls` |
|
| heex | ✓ | ✓ | | `elixir-ls` |
|
||||||
| hoon | ✓ | | | |
|
|
||||||
| hocon | ✓ | | ✓ | |
|
| hocon | ✓ | | ✓ | |
|
||||||
|
| hoon | ✓ | | | |
|
||||||
| hosts | ✓ | | | |
|
| hosts | ✓ | | | |
|
||||||
| html | ✓ | | | `vscode-html-language-server` |
|
| html | ✓ | | | `vscode-html-language-server` |
|
||||||
| hurl | ✓ | | ✓ | |
|
| hurl | ✓ | | ✓ | |
|
||||||
@ -155,6 +156,7 @@
|
|||||||
| smithy | ✓ | | | `cs` |
|
| smithy | ✓ | | | `cs` |
|
||||||
| sml | ✓ | | | |
|
| sml | ✓ | | | |
|
||||||
| solidity | ✓ | | | `solc` |
|
| solidity | ✓ | | | `solc` |
|
||||||
|
| spicedb | ✓ | | | |
|
||||||
| sql | ✓ | | | |
|
| sql | ✓ | | | |
|
||||||
| sshclientconfig | ✓ | | | |
|
| sshclientconfig | ✓ | | | |
|
||||||
| starlark | ✓ | ✓ | | |
|
| starlark | ✓ | ✓ | | |
|
||||||
|
@ -78,24 +78,26 @@ ### File-type detection and the `file-types` key
|
|||||||
example:
|
example:
|
||||||
|
|
||||||
```toml
|
```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
|
When determining a language configuration to use, Helix searches the file-types
|
||||||
with the following priorities:
|
with the following priorities:
|
||||||
|
|
||||||
1. Exact match: if the filename of a file is an exact match of a string in a
|
1. Glob: values in `glob` tables are checked against the full path of the given
|
||||||
`file-types` list, that language wins. In the example above, `"Makefile"`
|
file. Globs are standard Unix-style path globs (e.g. the kind you use in Shell)
|
||||||
will match against `Makefile` files.
|
and can be used to match paths for a specific prefix, suffix, directory, etc.
|
||||||
2. Extension: if there are no exact matches, any `file-types` string that
|
In the above example, the `{ glob = "Makefile" }` config would match files
|
||||||
matches the file extension of a given file wins. In the example above, the
|
with the name `Makefile`, the `{ glob = ".git/config" }` config would match
|
||||||
`"toml"` matches files like `Cargo.toml` or `languages.toml`.
|
`config` files in `.git` directories, and the `{ glob = ".github/workflows/*.yaml" }`
|
||||||
3. Suffix: if there are still no matches, any values in `suffix` tables
|
config would match any `yaml` files in `.github/workflow` directories. Note
|
||||||
are checked against the full path of the given file. In the example above,
|
that globs should always use the Unix path separator `/` even on Windows systems;
|
||||||
the `{ suffix = ".git/config" }` would match against any `config` files
|
the matcher will automatically take the machine-specific separators into account.
|
||||||
in `.git` directories. Note: `/` is used as the directory separator but is
|
If the glob isn't an absolute path or doesn't already start with a glob prefix,
|
||||||
replaced at runtime with the appropriate path separator for the operating
|
`*/` will automatically be added to ensure it matches for any subdirectory.
|
||||||
system, so this rule would match against `.git\config` files on Windows.
|
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
|
## Language Server configuration
|
||||||
|
|
||||||
@ -127,6 +129,7 @@ ## Language Server configuration
|
|||||||
| `config` | LSP initialization options |
|
| `config` | LSP initialization options |
|
||||||
| `timeout` | The maximum time a request to the language server may take, in seconds. Defaults to `20` |
|
| `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" }` |
|
| `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
|
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).
|
[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
|
nucleo.workspace = true
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
|
globset = "0.4.14"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
quickcheck = { version = "1", default-features = false }
|
quickcheck = { version = "1", default-features = false }
|
||||||
|
@ -1,10 +1,45 @@
|
|||||||
/// Syntax configuration loader based on built-in languages.toml.
|
use crate::syntax::{Configuration, Loader, LoaderError};
|
||||||
pub fn default_syntax_loader() -> crate::syntax::Configuration {
|
|
||||||
|
/// Language configuration based on built-in languages.toml.
|
||||||
|
pub fn default_lang_config() -> Configuration {
|
||||||
helix_loader::config::default_lang_config()
|
helix_loader::config::default_lang_config()
|
||||||
.try_into()
|
.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()
|
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 ahash::RandomState;
|
||||||
use arc_swap::{ArcSwap, Guard};
|
use arc_swap::{ArcSwap, Guard};
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
|
use globset::GlobSet;
|
||||||
use hashbrown::raw::RawTable;
|
use hashbrown::raw::RawTable;
|
||||||
use slotmap::{DefaultKey as LayerId, HopSlotMap};
|
use slotmap::{DefaultKey as LayerId, HopSlotMap};
|
||||||
|
|
||||||
@ -82,12 +83,6 @@ pub struct Configuration {
|
|||||||
pub language_server: HashMap<String, LanguageServerConfiguration>,
|
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
|
// largely based on tree-sitter/cli/src/loader.rs
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
#[serde(rename_all = "kebab-case", deny_unknown_fields)]
|
||||||
@ -164,9 +159,11 @@ pub enum FileType {
|
|||||||
/// The extension of the file, either the `Path::extension` or the full
|
/// The extension of the file, either the `Path::extension` or the full
|
||||||
/// filename if the file does not have an extension.
|
/// filename if the file does not have an extension.
|
||||||
Extension(String),
|
Extension(String),
|
||||||
/// The suffix of a file. This is compared to a given file's absolute
|
/// A Unix-style path glob. This is compared to the file's absolute path, so
|
||||||
/// path, so it can be used to detect files based on their directories.
|
/// it can be used to detect files based on their directories. If the glob
|
||||||
Suffix(String),
|
/// 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 {
|
impl Serialize for FileType {
|
||||||
@ -178,9 +175,9 @@ fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
|
|||||||
|
|
||||||
match self {
|
match self {
|
||||||
FileType::Extension(extension) => serializer.serialize_str(extension),
|
FileType::Extension(extension) => serializer.serialize_str(extension),
|
||||||
FileType::Suffix(suffix) => {
|
FileType::Glob(glob) => {
|
||||||
let mut map = serializer.serialize_map(Some(1))?;
|
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()
|
map.end()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -213,9 +210,20 @@ fn visit_map<M>(self, mut map: M) -> Result<Self::Value, M::Error>
|
|||||||
M: serde::de::MapAccess<'de>,
|
M: serde::de::MapAccess<'de>,
|
||||||
{
|
{
|
||||||
match map.next_entry::<String, String>()? {
|
match map.next_entry::<String, String>()? {
|
||||||
Some((key, suffix)) if key == "suffix" => Ok(FileType::Suffix({
|
Some((key, mut glob)) if key == "glob" => {
|
||||||
suffix.replace('/', std::path::MAIN_SEPARATOR_STR)
|
// 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!(
|
Some((key, _value)) => Err(serde::de::Error::custom(format!(
|
||||||
"unknown key in `file-types` list: {}",
|
"unknown key in `file-types` list: {}",
|
||||||
key
|
key
|
||||||
@ -358,6 +366,22 @@ fn serialize_lang_features<S>(
|
|||||||
serializer.end()
|
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)]
|
#[derive(Debug, Serialize, Deserialize)]
|
||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct LanguageServerConfiguration {
|
pub struct LanguageServerConfiguration {
|
||||||
@ -371,6 +395,12 @@ pub struct LanguageServerConfiguration {
|
|||||||
pub config: Option<serde_json::Value>,
|
pub config: Option<serde_json::Value>,
|
||||||
#[serde(default = "default_timeout")]
|
#[serde(default = "default_timeout")]
|
||||||
pub timeout: u64,
|
pub timeout: u64,
|
||||||
|
#[serde(
|
||||||
|
default,
|
||||||
|
skip_serializing,
|
||||||
|
deserialize_with = "deserialize_required_root_patterns"
|
||||||
|
)]
|
||||||
|
pub required_root_patterns: Option<GlobSet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
@ -752,6 +782,47 @@ pub struct SoftWrap {
|
|||||||
pub wrap_at_text_width: Option<bool>,
|
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?
|
// Expose loader as Lazy<> global since it's always static?
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -759,7 +830,7 @@ pub struct Loader {
|
|||||||
// highlight_names ?
|
// highlight_names ?
|
||||||
language_configs: Vec<Arc<LanguageConfiguration>>,
|
language_configs: Vec<Arc<LanguageConfiguration>>,
|
||||||
language_config_ids_by_extension: HashMap<String, usize>, // Vec<usize>
|
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_config_ids_by_shebang: HashMap<String, usize>,
|
||||||
|
|
||||||
language_server_configs: HashMap<String, LanguageServerConfiguration>,
|
language_server_configs: HashMap<String, LanguageServerConfiguration>,
|
||||||
@ -767,66 +838,57 @@ pub struct Loader {
|
|||||||
scopes: ArcSwap<Vec<String>>,
|
scopes: ArcSwap<Vec<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub type LoaderError = globset::Error;
|
||||||
|
|
||||||
impl Loader {
|
impl Loader {
|
||||||
pub fn new(config: Configuration) -> Self {
|
pub fn new(config: Configuration) -> Result<Self, LoaderError> {
|
||||||
let mut loader = Self {
|
let mut language_configs = Vec::new();
|
||||||
language_configs: Vec::new(),
|
let mut language_config_ids_by_extension = HashMap::new();
|
||||||
language_server_configs: config.language_server,
|
let mut language_config_ids_by_shebang = HashMap::new();
|
||||||
language_config_ids_by_extension: HashMap::new(),
|
let mut file_type_globs = Vec::new();
|
||||||
language_config_ids_by_suffix: HashMap::new(),
|
|
||||||
language_config_ids_by_shebang: HashMap::new(),
|
|
||||||
scopes: ArcSwap::from_pointee(Vec::new()),
|
|
||||||
};
|
|
||||||
|
|
||||||
for config in config.language {
|
for config in config.language {
|
||||||
// get the next id
|
// get the next id
|
||||||
let language_id = loader.language_configs.len();
|
let language_id = language_configs.len();
|
||||||
|
|
||||||
for file_type in &config.file_types {
|
for file_type in &config.file_types {
|
||||||
// entry().or_insert(Vec::new).push(language_id);
|
// entry().or_insert(Vec::new).push(language_id);
|
||||||
match file_type {
|
match file_type {
|
||||||
FileType::Extension(extension) => loader
|
FileType::Extension(extension) => {
|
||||||
.language_config_ids_by_extension
|
language_config_ids_by_extension.insert(extension.clone(), language_id);
|
||||||
.insert(extension.clone(), language_id),
|
}
|
||||||
FileType::Suffix(suffix) => loader
|
FileType::Glob(glob) => {
|
||||||
.language_config_ids_by_suffix
|
file_type_globs.push(FileTypeGlob::new(glob.to_owned(), language_id));
|
||||||
.insert(suffix.clone(), language_id),
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
for shebang in &config.shebangs {
|
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>> {
|
pub fn language_config_for_file_name(&self, path: &Path) -> Option<Arc<LanguageConfiguration>> {
|
||||||
// Find all the language configurations that match this file name
|
// Find all the language configurations that match this file name
|
||||||
// or a suffix of the file name.
|
// or a suffix of the file name.
|
||||||
let configuration_id = path
|
let configuration_id = self
|
||||||
.file_name()
|
.language_config_ids_glob_matcher
|
||||||
.and_then(|n| n.to_str())
|
.language_id_for_path(path)
|
||||||
.and_then(|file_name| self.language_config_ids_by_extension.get(file_name))
|
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
path.extension()
|
path.extension()
|
||||||
.and_then(|extension| extension.to_str())
|
.and_then(|extension| extension.to_str())
|
||||||
.and_then(|extension| self.language_config_ids_by_extension.get(extension))
|
.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())
|
configuration_id.and_then(|&id| self.language_configs.get(id).cloned())
|
||||||
@ -2592,7 +2654,8 @@ fn test_textobject_queries() {
|
|||||||
let loader = Loader::new(Configuration {
|
let loader = Loader::new(Configuration {
|
||||||
language: vec![],
|
language: vec![],
|
||||||
language_server: HashMap::new(),
|
language_server: HashMap::new(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
let language = get_language("rust").unwrap();
|
let language = get_language("rust").unwrap();
|
||||||
|
|
||||||
let query = Query::new(language, query_str).unwrap();
|
let query = Query::new(language, query_str).unwrap();
|
||||||
@ -2654,7 +2717,8 @@ fn test_parser() {
|
|||||||
let loader = Loader::new(Configuration {
|
let loader = Loader::new(Configuration {
|
||||||
language: vec![],
|
language: vec![],
|
||||||
language_server: HashMap::new(),
|
language_server: HashMap::new(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let language = get_language("rust").unwrap();
|
let language = get_language("rust").unwrap();
|
||||||
let config = HighlightConfiguration::new(
|
let config = HighlightConfiguration::new(
|
||||||
@ -2760,7 +2824,8 @@ fn assert_pretty_print(
|
|||||||
let loader = Loader::new(Configuration {
|
let loader = Loader::new(Configuration {
|
||||||
language: vec![],
|
language: vec![],
|
||||||
language_server: HashMap::new(),
|
language_server: HashMap::new(),
|
||||||
});
|
})
|
||||||
|
.unwrap();
|
||||||
let language = get_language(language_name).unwrap();
|
let language = get_language(language_name).unwrap();
|
||||||
|
|
||||||
let config = HighlightConfiguration::new(language, "", "", "").unwrap();
|
let config = HighlightConfiguration::new(language, "", "", "").unwrap();
|
||||||
|
@ -186,7 +186,7 @@ fn test_treesitter_indent(
|
|||||||
lang_scope: &str,
|
lang_scope: &str,
|
||||||
ignored_lines: Vec<std::ops::Range<usize>>,
|
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
|
// set runtime path so we can find the queries
|
||||||
let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
let mut runtime = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||||
|
@ -30,7 +30,7 @@ log = "0.4"
|
|||||||
# cloning/compiling tree-sitter grammars
|
# cloning/compiling tree-sitter grammars
|
||||||
cc = { version = "1" }
|
cc = { version = "1" }
|
||||||
threadpool = { version = "1.0" }
|
threadpool = { version = "1.0" }
|
||||||
tempfile = "3.9.0"
|
tempfile = "3.10.0"
|
||||||
dunce = "1.0.4"
|
dunce = "1.0.4"
|
||||||
|
|
||||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||||
|
@ -27,6 +27,6 @@ lsp-types = { version = "0.95" }
|
|||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
thiserror = "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"
|
tokio-stream = "0.1.14"
|
||||||
parking_lot = "0.12.1"
|
parking_lot = "0.12.1"
|
||||||
|
@ -177,12 +177,11 @@ pub fn start(
|
|||||||
args: &[String],
|
args: &[String],
|
||||||
config: Option<Value>,
|
config: Option<Value>,
|
||||||
server_environment: HashMap<String, String>,
|
server_environment: HashMap<String, String>,
|
||||||
root_markers: &[String],
|
root_path: PathBuf,
|
||||||
manual_roots: &[PathBuf],
|
root_uri: Option<lsp::Url>,
|
||||||
id: usize,
|
id: usize,
|
||||||
name: String,
|
name: String,
|
||||||
req_timeout: u64,
|
req_timeout: u64,
|
||||||
doc_path: Option<&std::path::PathBuf>,
|
|
||||||
) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
|
) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
|
||||||
// Resolve path to the binary
|
// Resolve path to the binary
|
||||||
let cmd = helix_stdx::env::which(cmd)?;
|
let cmd = helix_stdx::env::which(cmd)?;
|
||||||
@ -206,22 +205,6 @@ pub fn start(
|
|||||||
|
|
||||||
let (server_rx, server_tx, initialize_notify) =
|
let (server_rx, server_tx, initialize_notify) =
|
||||||
Transport::start(reader, writer, stderr, id, name.clone());
|
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
|
let workspace_folders = root_uri
|
||||||
.clone()
|
.clone()
|
||||||
|
@ -680,7 +680,7 @@ fn start_client(
|
|||||||
doc_path: Option<&std::path::PathBuf>,
|
doc_path: Option<&std::path::PathBuf>,
|
||||||
root_dirs: &[PathBuf],
|
root_dirs: &[PathBuf],
|
||||||
enable_snippets: bool,
|
enable_snippets: bool,
|
||||||
) -> Result<Arc<Client>> {
|
) -> Result<Option<Arc<Client>>> {
|
||||||
let config = self
|
let config = self
|
||||||
.syn_loader
|
.syn_loader
|
||||||
.language_server_configs()
|
.language_server_configs()
|
||||||
@ -688,7 +688,7 @@ fn start_client(
|
|||||||
.ok_or_else(|| anyhow::anyhow!("Language server '{name}' not defined"))?;
|
.ok_or_else(|| anyhow::anyhow!("Language server '{name}' not defined"))?;
|
||||||
let id = self.counter;
|
let id = self.counter;
|
||||||
self.counter += 1;
|
self.counter += 1;
|
||||||
let NewClient(client, incoming) = start_client(
|
if let Some(NewClient(client, incoming)) = start_client(
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
ls_config,
|
ls_config,
|
||||||
@ -696,9 +696,12 @@ fn start_client(
|
|||||||
doc_path,
|
doc_path,
|
||||||
root_dirs,
|
root_dirs,
|
||||||
enable_snippets,
|
enable_snippets,
|
||||||
)?;
|
)? {
|
||||||
self.incoming.push(UnboundedReceiverStream::new(incoming));
|
self.incoming.push(UnboundedReceiverStream::new(incoming));
|
||||||
Ok(client)
|
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,
|
/// 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,
|
root_dirs,
|
||||||
enable_snippets,
|
enable_snippets,
|
||||||
) {
|
) {
|
||||||
Ok(client) => client,
|
Ok(client) => client?,
|
||||||
error => return Some(error),
|
Err(error) => return Some(Err(error)),
|
||||||
};
|
};
|
||||||
let old_clients = self
|
let old_clients = self
|
||||||
.inner
|
.inner
|
||||||
@ -764,13 +767,13 @@ pub fn get<'a>(
|
|||||||
root_dirs: &'a [PathBuf],
|
root_dirs: &'a [PathBuf],
|
||||||
enable_snippets: bool,
|
enable_snippets: bool,
|
||||||
) -> impl Iterator<Item = (LanguageServerName, Result<Arc<Client>>)> + 'a {
|
) -> impl Iterator<Item = (LanguageServerName, Result<Arc<Client>>)> + 'a {
|
||||||
language_config.language_servers.iter().map(
|
language_config.language_servers.iter().filter_map(
|
||||||
move |LanguageServerFeatures { name, .. }| {
|
move |LanguageServerFeatures { name, .. }| {
|
||||||
if let Some(clients) = self.inner.get(name) {
|
if let Some(clients) = self.inner.get(name) {
|
||||||
if let Some((_, client)) = clients.iter().enumerate().find(|(i, client)| {
|
if let Some((_, client)) = clients.iter().enumerate().find(|(i, client)| {
|
||||||
client.try_add_doc(&language_config.roots, root_dirs, doc_path, *i == 0)
|
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(
|
match self.start_client(
|
||||||
@ -781,13 +784,14 @@ pub fn get<'a>(
|
|||||||
enable_snippets,
|
enable_snippets,
|
||||||
) {
|
) {
|
||||||
Ok(client) => {
|
Ok(client) => {
|
||||||
|
let client = client?;
|
||||||
self.inner
|
self.inner
|
||||||
.entry(name.to_owned())
|
.entry(name.to_owned())
|
||||||
.or_default()
|
.or_default()
|
||||||
.push(client.clone());
|
.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>,
|
doc_path: Option<&std::path::PathBuf>,
|
||||||
root_dirs: &[PathBuf],
|
root_dirs: &[PathBuf],
|
||||||
enable_snippets: bool,
|
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(
|
let (client, incoming, initialize_notify) = Client::start(
|
||||||
&ls_config.command,
|
&ls_config.command,
|
||||||
&ls_config.args,
|
&ls_config.args,
|
||||||
ls_config.config.clone(),
|
ls_config.config.clone(),
|
||||||
ls_config.environment.clone(),
|
ls_config.environment.clone(),
|
||||||
&config.roots,
|
root_path,
|
||||||
config.workspace_lsp_roots.as_deref().unwrap_or(root_dirs),
|
root_uri,
|
||||||
id,
|
id,
|
||||||
name,
|
name,
|
||||||
ls_config.timeout,
|
ls_config.timeout,
|
||||||
doc_path,
|
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
let client = Arc::new(client);
|
let client = Arc::new(client);
|
||||||
@ -938,7 +969,7 @@ fn start_client(
|
|||||||
initialize_notify.notify_one();
|
initialize_notify.notify_one();
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(NewClient(client, incoming))
|
Ok(Some(NewClient(client, incoming)))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find an LSP workspace of a file using the following mechanism:
|
/// 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"
|
which = "6.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3.9"
|
tempfile = "3.10"
|
||||||
|
@ -42,6 +42,7 @@ signal-hook = "0.3"
|
|||||||
tokio-stream = "0.1"
|
tokio-stream = "0.1"
|
||||||
futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
|
futures-util = { version = "0.3", features = ["std", "async-await"], default-features = false }
|
||||||
arc-swap = { version = "1.6.0" }
|
arc-swap = { version = "1.6.0" }
|
||||||
|
termini = "1"
|
||||||
|
|
||||||
# Logging
|
# Logging
|
||||||
fern = "0.6"
|
fern = "0.6"
|
||||||
@ -83,4 +84,4 @@ helix-loader = { path = "../helix-loader" }
|
|||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
smallvec = "1.13"
|
smallvec = "1.13"
|
||||||
indoc = "2.0.4"
|
indoc = "2.0.4"
|
||||||
tempfile = "3.9.0"
|
tempfile = "3.10.0"
|
||||||
|
@ -96,11 +96,7 @@ fn setup_integration_logging() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Application {
|
impl Application {
|
||||||
pub fn new(
|
pub fn new(args: Args, config: Config, lang_loader: syntax::Loader) -> Result<Self, Error> {
|
||||||
args: Args,
|
|
||||||
config: Config,
|
|
||||||
syn_loader_conf: syntax::Configuration,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
#[cfg(feature = "integration")]
|
#[cfg(feature = "integration")]
|
||||||
setup_integration_logging();
|
setup_integration_logging();
|
||||||
|
|
||||||
@ -126,7 +122,7 @@ pub fn new(
|
|||||||
})
|
})
|
||||||
.unwrap_or_else(|| theme_loader.default_theme(true_color));
|
.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"))]
|
#[cfg(not(feature = "integration"))]
|
||||||
let backend = CrosstermBackend::new(stdout(), &config.editor);
|
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
|
/// refresh language config after config change
|
||||||
fn refresh_language_config(&mut self) -> Result<(), Error> {
|
fn refresh_language_config(&mut self) -> Result<(), Error> {
|
||||||
let syntax_config = helix_core::config::user_syntax_loader()
|
let lang_loader = helix_core::config::user_lang_loader()?;
|
||||||
.map_err(|err| anyhow::anyhow!("Failed to load language config: {}", err))?;
|
self.syn_loader = std::sync::Arc::new(lang_loader);
|
||||||
|
|
||||||
self.syn_loader = std::sync::Arc::new(syntax::Loader::new(syntax_config));
|
|
||||||
self.editor.syn_loader = self.syn_loader.clone();
|
self.editor.syn_loader = self.syn_loader.clone();
|
||||||
for document in self.editor.documents.values_mut() {
|
for document in self.editor.documents.values_mut() {
|
||||||
document.detect_language(self.syn_loader.clone());
|
document.detect_language(self.syn_loader.clone());
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
style::{Color, Print, Stylize},
|
style::{Color, Print, Stylize},
|
||||||
tty::IsTty,
|
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_loader::grammar::load_runtime_file;
|
||||||
use helix_view::clipboard::get_clipboard_provider;
|
use helix_view::clipboard::get_clipboard_provider;
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
@ -128,7 +128,7 @@ pub fn languages_all() -> std::io::Result<()> {
|
|||||||
let stdout = std::io::stdout();
|
let stdout = std::io::stdout();
|
||||||
let mut stdout = stdout.lock();
|
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,
|
Ok(conf) => conf,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let stderr = std::io::stderr();
|
let stderr = std::io::stderr();
|
||||||
@ -141,7 +141,7 @@ pub fn languages_all() -> std::io::Result<()> {
|
|||||||
err
|
err
|
||||||
)?;
|
)?;
|
||||||
writeln!(stderr, "{}", "Using default language config".yellow())?;
|
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 stdout = std::io::stdout();
|
||||||
let mut stdout = stdout.lock();
|
let mut stdout = stdout.lock();
|
||||||
|
|
||||||
let syn_loader_conf = match user_syntax_loader() {
|
let syn_loader_conf = match user_lang_config() {
|
||||||
Ok(conf) => conf,
|
Ok(conf) => conf,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
let stderr = std::io::stderr();
|
let stderr = std::io::stderr();
|
||||||
@ -247,7 +247,7 @@ pub fn language(lang_str: String) -> std::io::Result<()> {
|
|||||||
err
|
err
|
||||||
)?;
|
)?;
|
||||||
writeln!(stderr, "{}", "Using default language config".yellow())?;
|
writeln!(stderr, "{}", "Using default language config".yellow())?;
|
||||||
default_syntax_loader()
|
default_lang_config()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,17 +22,30 @@
|
|||||||
|
|
||||||
pub use keymap::macros::*;
|
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)]
|
#[cfg(windows)]
|
||||||
fn true_color() -> bool {
|
fn true_color() -> bool {
|
||||||
true
|
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.
|
/// Function used for filtering dir entries in the various file pickers.
|
||||||
fn filter_picker_entry(entry: &DirEntry, root: &Path, dedup_symlinks: bool) -> bool {
|
fn filter_picker_entry(entry: &DirEntry, root: &Path, dedup_symlinks: bool) -> bool {
|
||||||
// We always want to ignore the .git directory, otherwise if
|
// 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| {
|
let lang_loader = helix_core::config::user_lang_loader().unwrap_or_else(|err| {
|
||||||
eprintln!("Bad language config: {}", err);
|
eprintln!("{}", err);
|
||||||
eprintln!("Press <ENTER> to continue with default language config");
|
eprintln!("Press <ENTER> to continue with default language config");
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
// This waits for an enter press.
|
// This waits for an enter press.
|
||||||
let _ = std::io::stdin().read(&mut []);
|
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
|
// 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)
|
let mut app =
|
||||||
.context("unable to create new application")?;
|
Application::new(args, config, lang_loader).context("unable to create new application")?;
|
||||||
|
|
||||||
let exit_code = app.run(&mut EventStream::new()).await?;
|
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()
|
let mut app = helpers::AppBuilder::new()
|
||||||
.with_file(file.path(), None)
|
.with_file(file.path(), None)
|
||||||
.with_input_text("#[l|]#et foo = 0;\n")
|
.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()?;
|
.build()?;
|
||||||
|
|
||||||
test_key_sequences(&mut app, vec![(Some(":w<ret>"), None)], false).await?;
|
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 test_case = test_case.into();
|
||||||
let mut app = match app {
|
let mut app = match app {
|
||||||
Some(app) => 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);
|
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
|
.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.
|
/// 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();
|
let mut lang = helix_loader::config::default_lang_config();
|
||||||
|
|
||||||
if let Some(overrides) = overrides {
|
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 = 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
|
/// 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 {
|
pub struct AppBuilder {
|
||||||
args: Args,
|
args: Args,
|
||||||
config: Config,
|
config: Config,
|
||||||
syn_conf: helix_core::syntax::Configuration,
|
syn_loader: helix_core::syntax::Loader,
|
||||||
input: Option<(String, Selection)>,
|
input: Option<(String, Selection)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,7 +280,7 @@ fn default() -> Self {
|
|||||||
Self {
|
Self {
|
||||||
args: Args::default(),
|
args: Args::default(),
|
||||||
config: test_config(),
|
config: test_config(),
|
||||||
syn_conf: test_syntax_conf(None),
|
syn_loader: test_syntax_loader(None),
|
||||||
input: None,
|
input: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -314,8 +314,8 @@ pub fn with_input_text<S: Into<String>>(mut self, input_text: S) -> Self {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn with_lang_config(mut self, syn_conf: helix_core::syntax::Configuration) -> Self {
|
pub fn with_lang_loader(mut self, syn_loader: helix_core::syntax::Loader) -> Self {
|
||||||
self.syn_conf = syn_conf;
|
self.syn_loader = syn_loader;
|
||||||
self
|
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");
|
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 {
|
if let Some((text, selection)) = self.input {
|
||||||
let (view, doc) = helix_view::current!(app.editor);
|
let (view, doc) = helix_view::current!(app.editor);
|
||||||
|
@ -29,4 +29,4 @@ log = "0.4"
|
|||||||
git = ["gix"]
|
git = ["gix"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[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"
|
name = "toml"
|
||||||
scope = "source.toml"
|
scope = "source.toml"
|
||||||
injection-regex = "toml"
|
injection-regex = "toml"
|
||||||
file-types = ["toml", "poetry.lock", "Cargo.lock"]
|
file-types = ["toml", { glob = "poetry.lock" }, { glob = "Cargo.lock" }]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
language-servers = [ "taplo" ]
|
language-servers = [ "taplo" ]
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
@ -292,7 +292,7 @@ source = { git = "https://github.com/yusdacra/tree-sitter-protobuf", rev = "19c2
|
|||||||
name = "elixir"
|
name = "elixir"
|
||||||
scope = "source.elixir"
|
scope = "source.elixir"
|
||||||
injection-regex = "(elixir|ex)"
|
injection-regex = "(elixir|ex)"
|
||||||
file-types = ["ex", "exs", "mix.lock"]
|
file-types = ["ex", "exs", { glob = "mix.lock" }]
|
||||||
shebangs = ["elixir"]
|
shebangs = ["elixir"]
|
||||||
roots = ["mix.exs", "mix.lock"]
|
roots = ["mix.exs", "mix.lock"]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
@ -361,20 +361,20 @@ file-types = [
|
|||||||
"geojson",
|
"geojson",
|
||||||
"gltf",
|
"gltf",
|
||||||
"webmanifest",
|
"webmanifest",
|
||||||
"flake.lock",
|
{ glob = "flake.lock" },
|
||||||
".babelrc",
|
{ glob = ".babelrc" },
|
||||||
".bowerrc",
|
{ glob = ".bowerrc" },
|
||||||
".jscrc",
|
{ glob = ".jscrc" },
|
||||||
"js.map",
|
"js.map",
|
||||||
"ts.map",
|
"ts.map",
|
||||||
"css.map",
|
"css.map",
|
||||||
".jslintrc",
|
{ glob = ".jslintrc" },
|
||||||
"jsonld",
|
"jsonld",
|
||||||
".vuerc",
|
{ glob = ".vuerc" },
|
||||||
"composer.lock",
|
{ glob = "composer.lock" },
|
||||||
".watchmanconfig",
|
{ glob = ".watchmanconfig" },
|
||||||
"avsc",
|
"avsc",
|
||||||
".prettierrc"
|
{ glob = ".prettierrc" },
|
||||||
]
|
]
|
||||||
language-servers = [ "vscode-json-language-server" ]
|
language-servers = [ "vscode-json-language-server" ]
|
||||||
auto-format = true
|
auto-format = true
|
||||||
@ -439,7 +439,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-c", rev = "7175a6dd
|
|||||||
name = "cpp"
|
name = "cpp"
|
||||||
scope = "source.cpp"
|
scope = "source.cpp"
|
||||||
injection-regex = "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 = "//"
|
comment-token = "//"
|
||||||
language-servers = [ "clangd" ]
|
language-servers = [ "clangd" ]
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
@ -514,6 +514,30 @@ args = { processId = "{0}" }
|
|||||||
name = "c-sharp"
|
name = "c-sharp"
|
||||||
source = { git = "https://github.com/tree-sitter/tree-sitter-c-sharp", rev = "5b60f99545fea00a33bbfae5be956f684c4c69e2" }
|
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]]
|
[[language]]
|
||||||
name = "go"
|
name = "go"
|
||||||
scope = "source.go"
|
scope = "source.go"
|
||||||
@ -571,7 +595,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-go", rev = "64457ea
|
|||||||
name = "gomod"
|
name = "gomod"
|
||||||
scope = "source.gomod"
|
scope = "source.gomod"
|
||||||
injection-regex = "gomod"
|
injection-regex = "gomod"
|
||||||
file-types = ["go.mod"]
|
file-types = [{ glob = "go.mod" }]
|
||||||
auto-format = true
|
auto-format = true
|
||||||
comment-token = "//"
|
comment-token = "//"
|
||||||
language-servers = [ "gopls" ]
|
language-servers = [ "gopls" ]
|
||||||
@ -598,7 +622,7 @@ source = { git = "https://github.com/dannylongeuay/tree-sitter-go-template", rev
|
|||||||
name = "gowork"
|
name = "gowork"
|
||||||
scope = "source.gowork"
|
scope = "source.gowork"
|
||||||
injection-regex = "gowork"
|
injection-regex = "gowork"
|
||||||
file-types = ["go.work"]
|
file-types = [{ glob = "go.work" }]
|
||||||
auto-format = true
|
auto-format = true
|
||||||
comment-token = "//"
|
comment-token = "//"
|
||||||
language-servers = [ "gopls" ]
|
language-servers = [ "gopls" ]
|
||||||
@ -613,7 +637,7 @@ name = "javascript"
|
|||||||
scope = "source.js"
|
scope = "source.js"
|
||||||
injection-regex = "(js|javascript)"
|
injection-regex = "(js|javascript)"
|
||||||
language-id = "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"]
|
shebangs = ["node"]
|
||||||
comment-token = "//"
|
comment-token = "//"
|
||||||
language-servers = [ "typescript-language-server" ]
|
language-servers = [ "typescript-language-server" ]
|
||||||
@ -716,7 +740,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-html", rev = "29f53
|
|||||||
name = "python"
|
name = "python"
|
||||||
scope = "source.python"
|
scope = "source.python"
|
||||||
injection-regex = "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"]
|
shebangs = ["python"]
|
||||||
roots = ["pyproject.toml", "setup.py", "poetry.lock", "pyrightconfig.json"]
|
roots = ["pyproject.toml", "setup.py", "poetry.lock", "pyrightconfig.json"]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
@ -769,38 +793,38 @@ injection-regex = "ruby"
|
|||||||
file-types = [
|
file-types = [
|
||||||
"rb",
|
"rb",
|
||||||
"rake",
|
"rake",
|
||||||
"rakefile",
|
|
||||||
"irb",
|
"irb",
|
||||||
"gemfile",
|
|
||||||
"gemspec",
|
"gemspec",
|
||||||
"Rakefile",
|
|
||||||
"Gemfile",
|
|
||||||
"rabl",
|
"rabl",
|
||||||
"jbuilder",
|
"jbuilder",
|
||||||
"jb",
|
"jb",
|
||||||
"Podfile",
|
|
||||||
"podspec",
|
"podspec",
|
||||||
"Vagrantfile",
|
|
||||||
"Brewfile",
|
|
||||||
"rjs",
|
"rjs",
|
||||||
"rbi",
|
"rbi",
|
||||||
"Guardfile",
|
{ glob = "rakefile" },
|
||||||
"Capfile",
|
{ glob = "gemfile" },
|
||||||
"Cheffile",
|
{ glob = "Rakefile" },
|
||||||
"Hobofile",
|
{ glob = "Gemfile" },
|
||||||
"Appraisals",
|
{ glob = "Podfile" },
|
||||||
"Rantfile",
|
{ glob = "Vagrantfile" },
|
||||||
"Berksfile",
|
{ glob = "Brewfile" },
|
||||||
"Berksfile.lock",
|
{ glob = "Guardfile" },
|
||||||
"Thorfile",
|
{ glob = "Capfile" },
|
||||||
"Puppetfile",
|
{ glob = "Cheffile" },
|
||||||
"Fastfile",
|
{ glob = "Hobofile" },
|
||||||
"Appfile",
|
{ glob = "Appraisals" },
|
||||||
"Deliverfile",
|
{ glob = "Rantfile" },
|
||||||
"Matchfile",
|
{ glob = "Berksfile" },
|
||||||
"Scanfile",
|
{ glob = "Berksfile.lock" },
|
||||||
"Snapfile",
|
{ glob = "Thorfile" },
|
||||||
"Gymfile"
|
{ glob = "Puppetfile" },
|
||||||
|
{ glob = "Fastfile" },
|
||||||
|
{ glob = "Appfile" },
|
||||||
|
{ glob = "Deliverfile" },
|
||||||
|
{ glob = "Matchfile" },
|
||||||
|
{ glob = "Scanfile" },
|
||||||
|
{ glob = "Snapfile" },
|
||||||
|
{ glob = "Gymfile" },
|
||||||
]
|
]
|
||||||
shebangs = ["ruby"]
|
shebangs = ["ruby"]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
@ -819,43 +843,43 @@ file-types = [
|
|||||||
"sh",
|
"sh",
|
||||||
"bash",
|
"bash",
|
||||||
"zsh",
|
"zsh",
|
||||||
".bash_history",
|
|
||||||
".bash_login",
|
|
||||||
".bash_logout",
|
|
||||||
".bash_profile",
|
|
||||||
".bashrc",
|
|
||||||
".profile",
|
|
||||||
".zshenv",
|
|
||||||
"zshenv",
|
"zshenv",
|
||||||
".zlogin",
|
|
||||||
"zlogin",
|
"zlogin",
|
||||||
".zlogout",
|
|
||||||
"zlogout",
|
"zlogout",
|
||||||
".zprofile",
|
|
||||||
"zprofile",
|
"zprofile",
|
||||||
".zshrc",
|
|
||||||
"zshrc",
|
"zshrc",
|
||||||
".zimrc",
|
|
||||||
"APKBUILD",
|
|
||||||
"PKGBUILD",
|
|
||||||
"eclass",
|
"eclass",
|
||||||
"ebuild",
|
"ebuild",
|
||||||
"bazelrc",
|
"bazelrc",
|
||||||
".bash_aliases",
|
|
||||||
"Renviron",
|
"Renviron",
|
||||||
".Renviron",
|
|
||||||
".xprofile",
|
|
||||||
".xsession",
|
|
||||||
".xsessionrc",
|
|
||||||
"zsh-theme",
|
"zsh-theme",
|
||||||
"ksh",
|
"ksh",
|
||||||
"cshrc",
|
"cshrc",
|
||||||
"tcshrc",
|
"tcshrc",
|
||||||
".yashrc",
|
|
||||||
".yash_profile",
|
|
||||||
".hushlogin",
|
|
||||||
"bashrc_Apple_Terminal",
|
"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"]
|
shebangs = ["sh", "bash", "dash", "zsh"]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
@ -1216,7 +1240,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-tsq", rev = "48b5
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "cmake"
|
name = "cmake"
|
||||||
scope = "source.cmake"
|
scope = "source.cmake"
|
||||||
file-types = ["cmake", "CMakeLists.txt"]
|
file-types = ["cmake", { glob = "CMakeLists.txt" }]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
language-servers = [ "cmake-language-server" ]
|
language-servers = [ "cmake-language-server" ]
|
||||||
@ -1229,7 +1253,7 @@ source = { git = "https://github.com/uyha/tree-sitter-cmake", rev = "6e51463ef30
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "make"
|
name = "make"
|
||||||
scope = "source.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"]
|
shebangs = ["make", "gmake"]
|
||||||
injection-regex = "(make|makefile|Makefile|mk)"
|
injection-regex = "(make|makefile|Makefile|mk)"
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
@ -1372,7 +1396,7 @@ source = { git = "https://github.com/Flakebi/tree-sitter-tablegen", rev = "568dd
|
|||||||
name = "markdown"
|
name = "markdown"
|
||||||
scope = "source.md"
|
scope = "source.md"
|
||||||
injection-regex = "md|markdown"
|
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"]
|
roots = [".marksman.toml"]
|
||||||
language-servers = [ "marksman" ]
|
language-servers = [ "marksman" ]
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
@ -1424,7 +1448,7 @@ name = "dockerfile"
|
|||||||
scope = "source.dockerfile"
|
scope = "source.dockerfile"
|
||||||
injection-regex = "docker|dockerfile"
|
injection-regex = "docker|dockerfile"
|
||||||
roots = ["Dockerfile", "Containerfile"]
|
roots = ["Dockerfile", "Containerfile"]
|
||||||
file-types = ["Dockerfile", "dockerfile", "Containerfile", "containerfile"]
|
file-types = [{ glob = "Dockerfile*" }, { glob = "dockerfile*" }, { glob = "Containerfile*" }, { glob = "containerfile*" }]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
language-servers = [ "docker-langserver" ]
|
language-servers = [ "docker-langserver" ]
|
||||||
@ -1436,7 +1460,7 @@ source = { git = "https://github.com/camdencheek/tree-sitter-dockerfile", rev =
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "git-commit"
|
name = "git-commit"
|
||||||
scope = "git.commitmsg"
|
scope = "git.commitmsg"
|
||||||
file-types = ["COMMIT_EDITMSG"]
|
file-types = [{ glob = "COMMIT_EDITMSG" }]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
rulers = [51, 73]
|
rulers = [51, 73]
|
||||||
@ -1461,7 +1485,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-diff", rev = "fd7
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "git-rebase"
|
name = "git-rebase"
|
||||||
scope = "source.gitrebase"
|
scope = "source.gitrebase"
|
||||||
file-types = ["git-rebase-todo"]
|
file-types = [{ glob = "git-rebase-todo" }]
|
||||||
injection-regex = "git-rebase"
|
injection-regex = "git-rebase"
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 2, unit = "y" }
|
indent = { tab-width = 2, unit = "y" }
|
||||||
@ -1474,7 +1498,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-git-rebase", rev
|
|||||||
name = "regex"
|
name = "regex"
|
||||||
scope = "source.regex"
|
scope = "source.regex"
|
||||||
injection-regex = "regex"
|
injection-regex = "regex"
|
||||||
file-types = ["regex", ".Rbuildignore"]
|
file-types = ["regex", { glob = ".Rbuildignore" }]
|
||||||
|
|
||||||
[[grammar]]
|
[[grammar]]
|
||||||
name = "regex"
|
name = "regex"
|
||||||
@ -1483,7 +1507,7 @@ source = { git = "https://github.com/tree-sitter/tree-sitter-regex", rev = "e1cf
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "git-config"
|
name = "git-config"
|
||||||
scope = "source.gitconfig"
|
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"
|
injection-regex = "git-config"
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 4, unit = "\t" }
|
indent = { tab-width = 4, unit = "\t" }
|
||||||
@ -1495,7 +1519,7 @@ source = { git = "https://github.com/the-mikedavis/tree-sitter-git-config", rev
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "git-attributes"
|
name = "git-attributes"
|
||||||
scope = "source.gitattributes"
|
scope = "source.gitattributes"
|
||||||
file-types = [".gitattributes"]
|
file-types = [{ glob = ".gitattributes" }]
|
||||||
injection-regex = "git-attributes"
|
injection-regex = "git-attributes"
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
grammar = "gitattributes"
|
grammar = "gitattributes"
|
||||||
@ -1507,7 +1531,7 @@ source = { git = "https://github.com/mtoohey31/tree-sitter-gitattributes", rev =
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "git-ignore"
|
name = "git-ignore"
|
||||||
scope = "source.gitignore"
|
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"
|
injection-regex = "git-ignore"
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
grammar = "gitignore"
|
grammar = "gitignore"
|
||||||
@ -1572,7 +1596,7 @@ source = { git = "https://github.com/jaredramirez/tree-sitter-rescript", rev = "
|
|||||||
name = "erlang"
|
name = "erlang"
|
||||||
scope = "source.erlang"
|
scope = "source.erlang"
|
||||||
injection-regex = "erl(ang)?"
|
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"]
|
roots = ["rebar.config"]
|
||||||
shebangs = ["escript"]
|
shebangs = ["escript"]
|
||||||
comment-token = "%%"
|
comment-token = "%%"
|
||||||
@ -1698,7 +1722,7 @@ source = { git = "https://github.com/Hubro/tree-sitter-robot", rev = "322e4cc657
|
|||||||
name = "r"
|
name = "r"
|
||||||
scope = "source.r"
|
scope = "source.r"
|
||||||
injection-regex = "(r|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"]
|
shebangs = ["r", "R"]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
@ -1730,7 +1754,7 @@ language-servers = [ "sourcekit-lsp" ]
|
|||||||
|
|
||||||
[[grammar]]
|
[[grammar]]
|
||||||
name = "swift"
|
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]]
|
[[language]]
|
||||||
name = "erb"
|
name = "erb"
|
||||||
@ -1913,7 +1937,7 @@ source = { git = "https://github.com/ap29600/tree-sitter-odin", rev = "b219207e4
|
|||||||
name = "meson"
|
name = "meson"
|
||||||
scope = "source.meson"
|
scope = "source.meson"
|
||||||
injection-regex = "meson"
|
injection-regex = "meson"
|
||||||
file-types = ["meson.build", "meson_options.txt"]
|
file-types = [{ glob = "meson.build" }, { glob = "meson_options.txt" }]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 2, unit = " " }
|
indent = { tab-width = 2, unit = " " }
|
||||||
|
|
||||||
@ -1924,7 +1948,7 @@ source = { git = "https://github.com/staysail/tree-sitter-meson", rev = "32a83e8
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "sshclientconfig"
|
name = "sshclientconfig"
|
||||||
scope = "source.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 = "#"
|
comment-token = "#"
|
||||||
|
|
||||||
[[grammar]]
|
[[grammar]]
|
||||||
@ -2045,7 +2069,7 @@ source = { git = "https://github.com/sogaiu/tree-sitter-clojure", rev = "e57c569
|
|||||||
name = "starlark"
|
name = "starlark"
|
||||||
scope = "source.starlark"
|
scope = "source.starlark"
|
||||||
injection-regex = "(starlark|bzl|bazel)"
|
injection-regex = "(starlark|bzl|bazel)"
|
||||||
file-types = ["bzl", "bazel", "BUILD", "star"]
|
file-types = ["bzl", "bazel", "star", { glob = "BUILD" }, { glob = "BUILD.*" }]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 4, unit = " " }
|
indent = { tab-width = 4, unit = " " }
|
||||||
grammar = "python"
|
grammar = "python"
|
||||||
@ -2413,7 +2437,7 @@ source = { git = "https://github.com/hh9527/tree-sitter-wit", rev = "c917790ab9a
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "env"
|
name = "env"
|
||||||
scope = "source.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"
|
injection-regex = "env"
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 4, unit = "\t" }
|
indent = { tab-width = 4, unit = "\t" }
|
||||||
@ -2441,7 +2465,7 @@ file-types = [
|
|||||||
"volume",
|
"volume",
|
||||||
"kube",
|
"kube",
|
||||||
"network",
|
"network",
|
||||||
".editorconfig",
|
{ glob = ".editorconfig" },
|
||||||
"properties",
|
"properties",
|
||||||
"cfg",
|
"cfg",
|
||||||
"directory"
|
"directory"
|
||||||
@ -2569,7 +2593,7 @@ source = { git = "https://github.com/mtoohey31/tree-sitter-pem", rev = "be67a433
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "passwd"
|
name = "passwd"
|
||||||
scope = "source.passwd"
|
scope = "source.passwd"
|
||||||
file-types = ["passwd"]
|
file-types = [{ glob = "passwd" }]
|
||||||
|
|
||||||
[[grammar]]
|
[[grammar]]
|
||||||
name = "passwd"
|
name = "passwd"
|
||||||
@ -2578,7 +2602,7 @@ source = { git = "https://github.com/ath3/tree-sitter-passwd", rev = "20239395ea
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "hosts"
|
name = "hosts"
|
||||||
scope = "source.hosts"
|
scope = "source.hosts"
|
||||||
file-types = ["hosts"]
|
file-types = [{ glob = "hosts" }]
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
|
|
||||||
[[grammar]]
|
[[grammar]]
|
||||||
@ -2786,7 +2810,7 @@ source = { git = "https://github.com/lefp/tree-sitter-opencl", rev = "8e1d24a570
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "just"
|
name = "just"
|
||||||
scope = "source.just"
|
scope = "source.just"
|
||||||
file-types = ["justfile", "Justfile", ".justfile", ".Justfile"]
|
file-types = [{ glob = "justfile" }, { glob = "Justfile" }, { glob = ".justfile" }, { glob = ".Justfile" }]
|
||||||
injection-regex = "just"
|
injection-regex = "just"
|
||||||
comment-token = "#"
|
comment-token = "#"
|
||||||
indent = { tab-width = 4, unit = "\t" }
|
indent = { tab-width = 4, unit = "\t" }
|
||||||
@ -2945,7 +2969,7 @@ source = { git = "https://github.com/kylegoetz/tree-sitter-unison", rev = "1f505
|
|||||||
[[language]]
|
[[language]]
|
||||||
name = "todotxt"
|
name = "todotxt"
|
||||||
scope = "text.todotxt"
|
scope = "text.todotxt"
|
||||||
file-types = [{ suffix = ".todo.txt" }, "todotxt"]
|
file-types = [{ glob = "todo.txt" }, { glob = "*.todo.txt" }, "todotxt"]
|
||||||
formatter = { command = "sort" }
|
formatter = { command = "sort" }
|
||||||
auto-format = true
|
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
|
(line_string_literal
|
||||||
["\\(" ")"] @punctuation.special)
|
["\\(" ")"] @punctuation.special)
|
||||||
|
|
||||||
["." ";" ":" "," ] @punctuation.delimiter
|
["." ";" ":" "," ] @punctuation.delimiter
|
||||||
["(" ")" "[" "]" "{" "}"] @punctuation.bracket ; TODO: "\\(" ")" in interpolations should be @punctuation.special
|
["(" ")" "[" "]" "{" "}"] @punctuation.bracket
|
||||||
|
|
||||||
; Identifiers
|
; Identifiers
|
||||||
(attribute) @variable
|
(attribute) @variable
|
||||||
@ -26,6 +26,7 @@
|
|||||||
(function_declaration "init" @constructor)
|
(function_declaration "init" @constructor)
|
||||||
(throws) @keyword
|
(throws) @keyword
|
||||||
"async" @keyword
|
"async" @keyword
|
||||||
|
"await" @keyword
|
||||||
(where_keyword) @keyword
|
(where_keyword) @keyword
|
||||||
(parameter external_name: (simple_identifier) @variable.parameter)
|
(parameter external_name: (simple_identifier) @variable.parameter)
|
||||||
(parameter name: (simple_identifier) @variable.parameter)
|
(parameter name: (simple_identifier) @variable.parameter)
|
||||||
@ -48,6 +49,7 @@
|
|||||||
"convenience"
|
"convenience"
|
||||||
"required"
|
"required"
|
||||||
"some"
|
"some"
|
||||||
|
"any"
|
||||||
] @keyword
|
] @keyword
|
||||||
|
|
||||||
[
|
[
|
||||||
|
@ -63,6 +63,9 @@
|
|||||||
"ui.cursorline.primary" = { bg = "bg1" }
|
"ui.cursorline.primary" = { bg = "bg1" }
|
||||||
"ui.statusline" = { fg = "fg", bg = "bg3" }
|
"ui.statusline" = { fg = "fg", bg = "bg3" }
|
||||||
"ui.statusline.inactive" = { fg = "grey", bg = "bg1" }
|
"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.popup" = { fg = "grey", bg = "bg2" }
|
||||||
"ui.window" = { fg = "grey", bg = "bg0" }
|
"ui.window" = { fg = "grey", bg = "bg0" }
|
||||||
"ui.help" = { fg = "fg", bg = "bg1" }
|
"ui.help" = { fg = "fg", bg = "bg1" }
|
||||||
@ -71,7 +74,7 @@
|
|||||||
"ui.menu" = { fg = "fg", bg = "bg2" }
|
"ui.menu" = { fg = "fg", bg = "bg2" }
|
||||||
"ui.menu.selected" = { fg = "bg0", bg = "green" }
|
"ui.menu.selected" = { fg = "bg0", bg = "green" }
|
||||||
"ui.virtual.whitespace" = { fg = "grey_dim" }
|
"ui.virtual.whitespace" = { fg = "grey_dim" }
|
||||||
"ui.virtual.ruler" = { bg = "grey_dim" }
|
"ui.virtual.ruler" = { bg = "bg3" }
|
||||||
"ui.virtual.inlay-hint" = { fg = "grey_dim" }
|
"ui.virtual.inlay-hint" = { fg = "grey_dim" }
|
||||||
|
|
||||||
info = { fg = 'green', bg = 'bg2' }
|
info = { fg = 'green', bg = 'bg2' }
|
||||||
|
Loading…
Reference in New Issue
Block a user