mirror of https://github.com/helix-editor/helix
Merge branch 'helix-editor:master' into pull-diagnostics
commit
c27dc062d4
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,12 @@
|
|||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
|
use crate::Transaction;
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct CompletionItem {
|
||||||
|
pub transaction: Transaction,
|
||||||
|
pub label: Cow<'static, str>,
|
||||||
|
pub kind: Cow<'static, str>,
|
||||||
|
/// Containing Markdown
|
||||||
|
pub documentation: String,
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
use helix_lsp::{lsp, LanguageServerId};
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub struct LspCompletionItem {
|
||||||
|
pub item: lsp::CompletionItem,
|
||||||
|
pub provider: LanguageServerId,
|
||||||
|
pub resolved: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
|
pub enum CompletionItem {
|
||||||
|
Lsp(LspCompletionItem),
|
||||||
|
Other(helix_core::CompletionItem),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<CompletionItem> for LspCompletionItem {
|
||||||
|
fn eq(&self, other: &CompletionItem) -> bool {
|
||||||
|
match other {
|
||||||
|
CompletionItem::Lsp(other) => self == other,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialEq<CompletionItem> for helix_core::CompletionItem {
|
||||||
|
fn eq(&self, other: &CompletionItem) -> bool {
|
||||||
|
match other {
|
||||||
|
CompletionItem::Other(other) => self == other,
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl CompletionItem {
|
||||||
|
pub fn preselect(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
CompletionItem::Lsp(LspCompletionItem { item, .. }) => item.preselect.unwrap_or(false),
|
||||||
|
CompletionItem::Other(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,189 @@
|
|||||||
|
use std::{
|
||||||
|
borrow::Cow,
|
||||||
|
fs,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
str::FromStr as _,
|
||||||
|
};
|
||||||
|
|
||||||
|
use futures_util::{future::BoxFuture, FutureExt as _};
|
||||||
|
use helix_core as core;
|
||||||
|
use helix_core::Transaction;
|
||||||
|
use helix_event::TaskHandle;
|
||||||
|
use helix_stdx::path::{self, canonicalize, fold_home_dir, get_path_suffix};
|
||||||
|
use helix_view::Document;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
|
use super::item::CompletionItem;
|
||||||
|
|
||||||
|
pub(crate) fn path_completion(
|
||||||
|
cursor: usize,
|
||||||
|
text: core::Rope,
|
||||||
|
doc: &Document,
|
||||||
|
handle: TaskHandle,
|
||||||
|
) -> Option<BoxFuture<'static, anyhow::Result<Vec<CompletionItem>>>> {
|
||||||
|
if !doc.path_completion_enabled() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let cur_line = text.char_to_line(cursor);
|
||||||
|
let start = text.line_to_char(cur_line).max(cursor.saturating_sub(1000));
|
||||||
|
let line_until_cursor = text.slice(start..cursor);
|
||||||
|
|
||||||
|
let (dir_path, typed_file_name) =
|
||||||
|
get_path_suffix(line_until_cursor, false).and_then(|matched_path| {
|
||||||
|
let matched_path = Cow::from(matched_path);
|
||||||
|
let path: Cow<_> = if matched_path.starts_with("file://") {
|
||||||
|
Url::from_str(&matched_path)
|
||||||
|
.ok()
|
||||||
|
.and_then(|url| url.to_file_path().ok())?
|
||||||
|
.into()
|
||||||
|
} else {
|
||||||
|
Path::new(&*matched_path).into()
|
||||||
|
};
|
||||||
|
let path = path::expand(&path);
|
||||||
|
let parent_dir = doc.path().and_then(|dp| dp.parent());
|
||||||
|
let path = match parent_dir {
|
||||||
|
Some(parent_dir) if path.is_relative() => parent_dir.join(&path),
|
||||||
|
_ => path.into_owned(),
|
||||||
|
};
|
||||||
|
#[cfg(windows)]
|
||||||
|
let ends_with_slash = matches!(matched_path.as_bytes().last(), Some(b'/' | b'\\'));
|
||||||
|
#[cfg(not(windows))]
|
||||||
|
let ends_with_slash = matches!(matched_path.as_bytes().last(), Some(b'/'));
|
||||||
|
|
||||||
|
if ends_with_slash {
|
||||||
|
Some((PathBuf::from(path.as_path()), None))
|
||||||
|
} else {
|
||||||
|
path.parent().map(|parent_path| {
|
||||||
|
(
|
||||||
|
PathBuf::from(parent_path),
|
||||||
|
path.file_name().and_then(|f| f.to_str().map(String::from)),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
if handle.is_canceled() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let future = tokio::task::spawn_blocking(move || {
|
||||||
|
let Ok(read_dir) = std::fs::read_dir(&dir_path) else {
|
||||||
|
return Vec::new();
|
||||||
|
};
|
||||||
|
|
||||||
|
read_dir
|
||||||
|
.filter_map(Result::ok)
|
||||||
|
.filter_map(|dir_entry| {
|
||||||
|
dir_entry
|
||||||
|
.metadata()
|
||||||
|
.ok()
|
||||||
|
.and_then(|md| Some((dir_entry.file_name().into_string().ok()?, md)))
|
||||||
|
})
|
||||||
|
.map_while(|(file_name, md)| {
|
||||||
|
if handle.is_canceled() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let kind = path_kind(&md);
|
||||||
|
let documentation = path_documentation(&md, &dir_path.join(&file_name), kind);
|
||||||
|
|
||||||
|
let edit_diff = typed_file_name
|
||||||
|
.as_ref()
|
||||||
|
.map(|f| f.len())
|
||||||
|
.unwrap_or_default();
|
||||||
|
|
||||||
|
let transaction = Transaction::change(
|
||||||
|
&text,
|
||||||
|
std::iter::once((cursor - edit_diff, cursor, Some((&file_name).into()))),
|
||||||
|
);
|
||||||
|
|
||||||
|
Some(CompletionItem::Other(core::CompletionItem {
|
||||||
|
kind: Cow::Borrowed(kind),
|
||||||
|
label: file_name.into(),
|
||||||
|
transaction,
|
||||||
|
documentation,
|
||||||
|
}))
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
});
|
||||||
|
|
||||||
|
Some(async move { Ok(future.await?) }.boxed())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn path_documentation(md: &fs::Metadata, full_path: &Path, kind: &str) -> String {
|
||||||
|
let full_path = fold_home_dir(canonicalize(full_path));
|
||||||
|
let full_path_name = full_path.to_string_lossy();
|
||||||
|
|
||||||
|
use std::os::unix::prelude::PermissionsExt;
|
||||||
|
let mode = md.permissions().mode();
|
||||||
|
|
||||||
|
let perms = [
|
||||||
|
(libc::S_IRUSR, 'r'),
|
||||||
|
(libc::S_IWUSR, 'w'),
|
||||||
|
(libc::S_IXUSR, 'x'),
|
||||||
|
(libc::S_IRGRP, 'r'),
|
||||||
|
(libc::S_IWGRP, 'w'),
|
||||||
|
(libc::S_IXGRP, 'x'),
|
||||||
|
(libc::S_IROTH, 'r'),
|
||||||
|
(libc::S_IWOTH, 'w'),
|
||||||
|
(libc::S_IXOTH, 'x'),
|
||||||
|
]
|
||||||
|
.into_iter()
|
||||||
|
.fold(String::with_capacity(9), |mut acc, (p, s)| {
|
||||||
|
// This cast is necessary on some platforms such as macos as `mode_t` is u16 there
|
||||||
|
#[allow(clippy::unnecessary_cast)]
|
||||||
|
acc.push(if mode & (p as u32) > 0 { s } else { '-' });
|
||||||
|
acc
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO it would be great to be able to individually color the documentation,
|
||||||
|
// but this will likely require a custom doc implementation (i.e. not `lsp::Documentation`)
|
||||||
|
// and/or different rendering in completion.rs
|
||||||
|
format!(
|
||||||
|
"type: `{kind}`\n\
|
||||||
|
permissions: `[{perms}]`\n\
|
||||||
|
full path: `{full_path_name}`",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
fn path_documentation(md: &fs::Metadata, full_path: &Path, kind: &str) -> String {
|
||||||
|
let full_path = fold_home_dir(canonicalize(full_path));
|
||||||
|
let full_path_name = full_path.to_string_lossy();
|
||||||
|
format!("type: `{kind}`\nfull path: `{full_path_name}`",)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
fn path_kind(md: &fs::Metadata) -> &'static str {
|
||||||
|
if md.is_symlink() {
|
||||||
|
"link"
|
||||||
|
} else if md.is_dir() {
|
||||||
|
"folder"
|
||||||
|
} else {
|
||||||
|
use std::os::unix::fs::FileTypeExt;
|
||||||
|
if md.file_type().is_block_device() {
|
||||||
|
"block"
|
||||||
|
} else if md.file_type().is_socket() {
|
||||||
|
"socket"
|
||||||
|
} else if md.file_type().is_char_device() {
|
||||||
|
"char_device"
|
||||||
|
} else if md.file_type().is_fifo() {
|
||||||
|
"fifo"
|
||||||
|
} else {
|
||||||
|
"file"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(not(unix))]
|
||||||
|
fn path_kind(md: &fs::Metadata) -> &'static str {
|
||||||
|
if md.is_symlink() {
|
||||||
|
"link"
|
||||||
|
} else if md.is_dir() {
|
||||||
|
"folder"
|
||||||
|
} else {
|
||||||
|
"file"
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
Copyright © WHATWG (Apple, Google, Mozilla, Microsoft).
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
3. Neither the name of the copyright holder nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived from
|
||||||
|
this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||||
|
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||||
|
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||||
|
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||||
|
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||||
|
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -0,0 +1,24 @@
|
|||||||
|
Syntax symbol pickers
|
||||||
|
==
|
||||||
|
|
||||||
|
This adds two new symbol picker commands that use tree-sitter rather than LSP. We run a new `symbols.scm` query across the file and extract tagged things like function definitions, types, classes, etc. For languages with unambiguous syntax this behaves roughly the same as the LSP symbol picker (`<space>s`). It's less precise though since we don't have semantic info about the language. For example it can easily produce false positives for C/C++ because of preprocessor magic.
|
||||||
|
|
||||||
|
The hope is to start introducing LSP-like features for navigation that can work without installing or running a language server. I made these two pickers in particular because I don't like LSP equivalents in ErlangLS - the document symbol picker can take a long time to show up during boot and the workspace symbol picker only searches for module names. The other motivation is to have some navigation features in cases when running a language server is too cumbersome - either to set up or because of resource constraints. For example `clangd` needs a fair amount of setup (`compile_commands.json`) that you might not want to do when quickly reading through a codebase.
|
||||||
|
|
||||||
|
GitHub already uses tree-sitter like this to provide [imprecise code navigation](https://docs.github.com/en/repositories/working-with-files/using-files/navigating-code-on-github#about-navigating-code-on-github). It should be possible to find definitions and references as well like `gd` and `gr` - this is left as a follow-up.
|
||||||
|
|
||||||
|
This PR also adds commands that either open the LSP symbol picker or the syntax one if a language server is not available. This way you can customize a language to not use the LSP symbol pickers, for example:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[[language]]
|
||||||
|
name = "erlang"
|
||||||
|
language-servers = [{ name = "erlang-ls", except-features = ["document-symbols", "workspace-symbols"] }]
|
||||||
|
```
|
||||||
|
|
||||||
|
and `<space>s` will use the syntax symbol picker, while `<space>s` on a Rust file will still prefer the language server.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Outstanding question - how closely should we try to match LSP symbol kind? Not at all? Should we have markup specific symbol kinds? (For example see markdown's `symbols.scm`).
|
||||||
|
|
||||||
|
Also this PR needs docs on writing `symbols.scm` queries.
|
@ -0,0 +1,60 @@
|
|||||||
|
(comment) @comment
|
||||||
|
|
||||||
|
[
|
||||||
|
"if"
|
||||||
|
"loop"
|
||||||
|
"for"
|
||||||
|
"return"
|
||||||
|
"fun"
|
||||||
|
"else"
|
||||||
|
"then"
|
||||||
|
"break"
|
||||||
|
"continue"
|
||||||
|
"and"
|
||||||
|
"or"
|
||||||
|
"not"
|
||||||
|
"let"
|
||||||
|
"pub"
|
||||||
|
"main"
|
||||||
|
"echo"
|
||||||
|
"exit"
|
||||||
|
"fun"
|
||||||
|
"import"
|
||||||
|
"from"
|
||||||
|
"as"
|
||||||
|
"in"
|
||||||
|
"fail"
|
||||||
|
"failed"
|
||||||
|
"silent"
|
||||||
|
"nameof"
|
||||||
|
"is"
|
||||||
|
"unsafe"
|
||||||
|
"trust"
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
; Literals
|
||||||
|
(boolean) @constant.builtin.boolean
|
||||||
|
(number) @constant.numeric
|
||||||
|
(null) @constant.numeric
|
||||||
|
(string) @string
|
||||||
|
(status) @keyword
|
||||||
|
(command) @string
|
||||||
|
(handler) @keyword
|
||||||
|
(block) @punctuation.delimiter
|
||||||
|
(variable_init) @keyword
|
||||||
|
(variable_assignment) @punctuation.delimiter
|
||||||
|
(variable) @variable
|
||||||
|
(escape_sequence) @constant.character.escape
|
||||||
|
(type_name_symbol) @type
|
||||||
|
(interpolation) @punctuation.delimiter
|
||||||
|
(reference) @keyword
|
||||||
|
(preprocessor_directive) @comment
|
||||||
|
(shebang) @comment
|
||||||
|
(function_definition
|
||||||
|
name: (variable) @function.method)
|
||||||
|
(function_call
|
||||||
|
name: (variable) @function.method)
|
||||||
|
(import_statement
|
||||||
|
"pub" @keyword
|
||||||
|
"import" @keyword
|
||||||
|
"from" @keyword)
|
@ -1,73 +1,232 @@
|
|||||||
; Keywords
|
; Includes
|
||||||
|
[
|
||||||
|
"import"
|
||||||
|
"provider"
|
||||||
|
"with"
|
||||||
|
"as"
|
||||||
|
"from"
|
||||||
|
] @keyword.control.import
|
||||||
|
|
||||||
|
; Namespaces
|
||||||
|
(module_declaration
|
||||||
|
(identifier) @namespace)
|
||||||
|
|
||||||
|
; Builtins
|
||||||
|
(primitive_type) @type.builtin
|
||||||
|
|
||||||
|
((member_expression
|
||||||
|
object: (identifier) @type.builtin)
|
||||||
|
(#eq? @type.builtin "sys"))
|
||||||
|
|
||||||
|
; Functions
|
||||||
|
(call_expression
|
||||||
|
function: (identifier) @function)
|
||||||
|
|
||||||
|
(user_defined_function
|
||||||
|
name: (identifier) @function)
|
||||||
|
|
||||||
|
; Properties
|
||||||
|
(object_property
|
||||||
|
(identifier) @function.method
|
||||||
|
":" @punctuation.delimiter
|
||||||
|
(_))
|
||||||
|
|
||||||
|
(object_property
|
||||||
|
(compatible_identifier) @function.method
|
||||||
|
":" @punctuation.delimiter
|
||||||
|
(_))
|
||||||
|
|
||||||
|
(property_identifier) @function.method
|
||||||
|
|
||||||
|
; Attributes
|
||||||
|
(decorator
|
||||||
|
"@" @attribute)
|
||||||
|
|
||||||
|
(decorator
|
||||||
|
(call_expression
|
||||||
|
(identifier) @attribute))
|
||||||
|
|
||||||
|
(decorator
|
||||||
|
(call_expression
|
||||||
|
(member_expression
|
||||||
|
object: (identifier) @attribute
|
||||||
|
property: (property_identifier) @attribute)))
|
||||||
|
|
||||||
|
; Types
|
||||||
|
(type_declaration
|
||||||
|
(identifier) @type)
|
||||||
|
|
||||||
|
(type_declaration
|
||||||
|
(identifier)
|
||||||
|
"="
|
||||||
|
(identifier) @type)
|
||||||
|
|
||||||
|
(type
|
||||||
|
(identifier) @type)
|
||||||
|
|
||||||
|
(resource_declaration
|
||||||
|
(identifier) @type)
|
||||||
|
|
||||||
|
(resource_expression
|
||||||
|
(identifier) @type)
|
||||||
|
|
||||||
|
; Parameters
|
||||||
|
(parameter_declaration
|
||||||
|
(identifier) @variable.parameter
|
||||||
|
(_))
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: (_)
|
||||||
|
(arguments
|
||||||
|
(identifier) @variable.parameter))
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: (_)
|
||||||
|
(arguments
|
||||||
|
(member_expression
|
||||||
|
object: (identifier) @variable.parameter)))
|
||||||
|
|
||||||
|
(parameter
|
||||||
|
.
|
||||||
|
(identifier) @variable.parameter)
|
||||||
|
|
||||||
|
; Variables
|
||||||
|
(variable_declaration
|
||||||
|
(identifier) @variable
|
||||||
|
(_))
|
||||||
|
|
||||||
|
(metadata_declaration
|
||||||
|
(identifier) @variable
|
||||||
|
(_))
|
||||||
|
|
||||||
|
(output_declaration
|
||||||
|
(identifier) @variable
|
||||||
|
(_))
|
||||||
|
|
||||||
|
(object_property
|
||||||
|
(_)
|
||||||
|
":"
|
||||||
|
(identifier) @variable)
|
||||||
|
|
||||||
|
(for_statement
|
||||||
|
"for"
|
||||||
|
(for_loop_parameters
|
||||||
|
(loop_variable) @variable
|
||||||
|
(loop_enumerator) @variable))
|
||||||
|
|
||||||
|
; Conditionals
|
||||||
|
"if" @keyword.conditional
|
||||||
|
|
||||||
|
(ternary_expression
|
||||||
|
"?" @keyword.control.conditional
|
||||||
|
":" @keyword.control.conditional)
|
||||||
|
|
||||||
|
; Loops
|
||||||
|
(for_statement
|
||||||
|
"for" @keyword.control.repeat
|
||||||
|
"in"
|
||||||
|
":" @punctuation.delimiter)
|
||||||
|
|
||||||
|
; Keywords
|
||||||
[
|
[
|
||||||
"module"
|
"module"
|
||||||
"var"
|
"metadata"
|
||||||
|
"output"
|
||||||
"param"
|
"param"
|
||||||
"import"
|
|
||||||
"resource"
|
"resource"
|
||||||
"existing"
|
"existing"
|
||||||
"if"
|
|
||||||
"targetScope"
|
"targetScope"
|
||||||
"output"
|
"type"
|
||||||
|
"var"
|
||||||
|
"using"
|
||||||
|
"test"
|
||||||
] @keyword
|
] @keyword
|
||||||
|
|
||||||
; Functions
|
"func" @keyword.function
|
||||||
|
|
||||||
(decorator) @function.builtin
|
"assert" @keyword.control.exception
|
||||||
|
|
||||||
(functionCall) @function
|
; Operators
|
||||||
|
[
|
||||||
|
"+"
|
||||||
|
"-"
|
||||||
|
"*"
|
||||||
|
"/"
|
||||||
|
"%"
|
||||||
|
"||"
|
||||||
|
"&&"
|
||||||
|
"|"
|
||||||
|
"=="
|
||||||
|
"!="
|
||||||
|
"=~"
|
||||||
|
"!~"
|
||||||
|
">"
|
||||||
|
">="
|
||||||
|
"<="
|
||||||
|
"<"
|
||||||
|
"??"
|
||||||
|
"="
|
||||||
|
"!"
|
||||||
|
".?"
|
||||||
|
] @operator
|
||||||
|
|
||||||
(functionCall
|
(subscript_expression
|
||||||
(functionArgument
|
"?" @operator)
|
||||||
(variableAccess) @variable))
|
|
||||||
|
|
||||||
; Literals/Types
|
(nullable_type
|
||||||
|
"?" @operator)
|
||||||
|
|
||||||
[
|
"in" @keyword.operator
|
||||||
"("
|
|
||||||
")"
|
|
||||||
"["
|
|
||||||
"]"
|
|
||||||
"{"
|
|
||||||
"}"
|
|
||||||
] @punctuation.bracket
|
|
||||||
|
|
||||||
(resourceDeclaration
|
; Literals
|
||||||
(string
|
(string) @string
|
||||||
(stringLiteral) @string.special))
|
|
||||||
|
|
||||||
(moduleDeclaration
|
(escape_sequence) @constant.character
|
||||||
(string
|
|
||||||
(stringLiteral) @string.special))
|
|
||||||
|
|
||||||
[
|
(number) @constant.number
|
||||||
(string)
|
|
||||||
(stringLiteral)
|
|
||||||
] @string
|
|
||||||
|
|
||||||
(nullLiteral) @keyword
|
(boolean) @constant.builtin.boolean
|
||||||
(booleanLiteral) @constant.builtin.boolean
|
|
||||||
(integerLiteral) @constant.numeric.integer
|
|
||||||
(comment) @comment
|
|
||||||
|
|
||||||
(string
|
(null) @constant.builtin
|
||||||
(variableAccess
|
|
||||||
(identifier) @variable))
|
|
||||||
|
|
||||||
(type) @type
|
; Misc
|
||||||
|
(compatible_identifier
|
||||||
|
"?" @punctuation.special)
|
||||||
|
|
||||||
; Variables
|
(nullable_return_type) @punctuation.special
|
||||||
|
|
||||||
|
[
|
||||||
|
"{"
|
||||||
|
"}"
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
(localVariable) @variable
|
[
|
||||||
|
"["
|
||||||
|
"]"
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
; Statements
|
[
|
||||||
|
"("
|
||||||
|
")"
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
(object
|
[
|
||||||
(objectProperty
|
"."
|
||||||
(identifier) @identifier))
|
":"
|
||||||
|
"::"
|
||||||
|
"=>"
|
||||||
|
] @punctuation.delimiter
|
||||||
|
|
||||||
|
; Interpolation
|
||||||
|
(interpolation
|
||||||
|
"${" @punctuation.special
|
||||||
|
"}" @punctuation.special)
|
||||||
|
|
||||||
(propertyAccess
|
(interpolation
|
||||||
(identifier) @identifier)
|
(identifier) @variable)
|
||||||
|
|
||||||
(ifCondition) @keyword.control.conditional
|
; Comments
|
||||||
|
[
|
||||||
|
(comment)
|
||||||
|
(diagnostic_comment)
|
||||||
|
] @comment
|
||||||
|
@ -0,0 +1 @@
|
|||||||
|
; inherits: yaml
|
@ -0,0 +1 @@
|
|||||||
|
; inherits: yaml
|
@ -0,0 +1 @@
|
|||||||
|
; inherits: yaml
|
@ -0,0 +1 @@
|
|||||||
|
; inherits: yaml
|
@ -0,0 +1,94 @@
|
|||||||
|
[
|
||||||
|
"module"
|
||||||
|
"type"
|
||||||
|
"assume"
|
||||||
|
"const"
|
||||||
|
"var"
|
||||||
|
"val"
|
||||||
|
"nondet"
|
||||||
|
"def"
|
||||||
|
"pure"
|
||||||
|
"action"
|
||||||
|
"temporal"
|
||||||
|
"run"
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
(match_expr "match" @keyword.control.conditional)
|
||||||
|
|
||||||
|
(if_else_condition
|
||||||
|
"if" @keyword.control.conditional
|
||||||
|
"else" @keyword.control.conditional)
|
||||||
|
|
||||||
|
(import "import" @keyword.control.import)
|
||||||
|
(import "as" @keyword.control.import)
|
||||||
|
(import "from" @keyword.control.import)
|
||||||
|
(export "export" @keyword.control.import)
|
||||||
|
(export "as" @keyword.control.import)
|
||||||
|
|
||||||
|
[
|
||||||
|
"true"
|
||||||
|
"false"
|
||||||
|
"Int"
|
||||||
|
"Nat"
|
||||||
|
"Bool"
|
||||||
|
] @constant.builtin
|
||||||
|
|
||||||
|
[
|
||||||
|
";"
|
||||||
|
"."
|
||||||
|
","
|
||||||
|
] @punctuation.delimiter
|
||||||
|
|
||||||
|
[
|
||||||
|
"-"
|
||||||
|
"+"
|
||||||
|
"*"
|
||||||
|
"/"
|
||||||
|
"%"
|
||||||
|
"<"
|
||||||
|
"<="
|
||||||
|
"="
|
||||||
|
"=="
|
||||||
|
"!="
|
||||||
|
"=>"
|
||||||
|
">"
|
||||||
|
">="
|
||||||
|
"^"
|
||||||
|
"->"
|
||||||
|
] @operator
|
||||||
|
|
||||||
|
(infix_and "and" @operator)
|
||||||
|
(infix_or "or" @operator)
|
||||||
|
(infix_iff "iff" @operator)
|
||||||
|
(infix_implies "implies" @operator)
|
||||||
|
|
||||||
|
(braced_and "and" @keyword)
|
||||||
|
(braced_or "or" @keyword)
|
||||||
|
(braced_all "all" @keyword)
|
||||||
|
(braced_any "any" @keyword)
|
||||||
|
|
||||||
|
[
|
||||||
|
"("
|
||||||
|
")"
|
||||||
|
"["
|
||||||
|
"]"
|
||||||
|
"{"
|
||||||
|
"}"
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
|
(polymorphic_type
|
||||||
|
(type) @type.parameter)
|
||||||
|
|
||||||
|
(variant_constructor) @type.enum.variant
|
||||||
|
|
||||||
|
(type) @type
|
||||||
|
(int_literal) @constant.numeric.integer
|
||||||
|
(comment) @comment
|
||||||
|
(string) @string
|
||||||
|
|
||||||
|
(operator_application
|
||||||
|
operator: (qualified_identifier) @function)
|
||||||
|
|
||||||
|
(operator_definition
|
||||||
|
name: (qualified_identifier) @function
|
||||||
|
arguments: (typed_argument_list))
|
@ -1,8 +1,29 @@
|
|||||||
((comment) @injection.content
|
((comment) @injection.content (#set! injection.language "comment"))
|
||||||
(#set! injection.language "comment"))
|
|
||||||
|
|
||||||
((raw_js) @injection.content
|
; %re
|
||||||
(#set! injection.language "javascript"))
|
(extension_expression
|
||||||
|
(extension_identifier) @_name
|
||||||
|
(#eq? @_name "re")
|
||||||
|
(expression_statement (_) @injection.content (#set! injection.language "regex")))
|
||||||
|
|
||||||
|
; %raw
|
||||||
|
(extension_expression
|
||||||
|
(extension_identifier) @_name
|
||||||
|
(#eq? @_name "raw")
|
||||||
|
(expression_statement
|
||||||
|
(_ (_) @injection.content (#set! injection.language "javascript"))))
|
||||||
|
|
||||||
|
; %graphql
|
||||||
|
(extension_expression
|
||||||
|
(extension_identifier) @_name
|
||||||
|
(#eq? @_name "graphql")
|
||||||
|
(expression_statement
|
||||||
|
(_ (_) @injection.content (#set! injection.language "graphql"))))
|
||||||
|
|
||||||
|
; %relay
|
||||||
|
(extension_expression
|
||||||
|
(extension_identifier) @_name
|
||||||
|
(#eq? @_name "relay")
|
||||||
|
(expression_statement
|
||||||
|
(_ (_) @injection.content (#set! injection.language "graphql") )))
|
||||||
|
|
||||||
((raw_gql) @injection.content
|
|
||||||
(#set! injection.language "graphql"))
|
|
@ -1,7 +1,7 @@
|
|||||||
(switch_expression) @local.scope
|
(switch_expression) @local.scope
|
||||||
(if_expression) @local.scope
|
|
||||||
|
|
||||||
; Definitions
|
; Definitions
|
||||||
;------------
|
;------------
|
||||||
(type_declaration) @local.defintion
|
(type_declaration) @local.definition
|
||||||
(let_binding) @local.defintion
|
(let_binding) @local.definition
|
||||||
|
(module_declaration) @local.definition
|
||||||
|
@ -0,0 +1,130 @@
|
|||||||
|
(self) @variable.builtin
|
||||||
|
|
||||||
|
(unit_definition (identifier) @function)
|
||||||
|
|
||||||
|
(parameter (identifier) @variable.parameter)
|
||||||
|
|
||||||
|
((pipeline_reg_marker) @keyword)
|
||||||
|
|
||||||
|
(scoped_identifier
|
||||||
|
path: (identifier) @namespace)
|
||||||
|
(scoped_identifier
|
||||||
|
(scoped_identifier
|
||||||
|
name: (identifier) @namespace))
|
||||||
|
|
||||||
|
((builtin_type) @type.builtin)
|
||||||
|
|
||||||
|
((identifier) @type.builtin
|
||||||
|
(#any-of?
|
||||||
|
@type.builtin
|
||||||
|
"uint"
|
||||||
|
"Option"
|
||||||
|
"Memory"))
|
||||||
|
|
||||||
|
((identifier) @type.enum.variant.builtin
|
||||||
|
(#any-of? @type.enum.variant.builtin "Some" "None"))
|
||||||
|
|
||||||
|
((pipeline_stage_name) @label)
|
||||||
|
|
||||||
|
((stage_reference
|
||||||
|
stage: (identifier) @label))
|
||||||
|
|
||||||
|
[
|
||||||
|
"pipeline"
|
||||||
|
"let"
|
||||||
|
"set"
|
||||||
|
"entity"
|
||||||
|
"fn"
|
||||||
|
"reg"
|
||||||
|
"reset"
|
||||||
|
"initial"
|
||||||
|
"inst"
|
||||||
|
"assert"
|
||||||
|
"struct"
|
||||||
|
"enum"
|
||||||
|
"stage"
|
||||||
|
"impl"
|
||||||
|
"port"
|
||||||
|
"decl"
|
||||||
|
"mod"
|
||||||
|
"where"
|
||||||
|
"trait"
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
[
|
||||||
|
"use"
|
||||||
|
] @keyword.import
|
||||||
|
|
||||||
|
[
|
||||||
|
"$if"
|
||||||
|
"$else"
|
||||||
|
"$config"
|
||||||
|
] @keyword.directive
|
||||||
|
|
||||||
|
((comptime_if ["{" "}"] @keyword.directive))
|
||||||
|
((comptime_else ["{" "}"] @keyword.directive))
|
||||||
|
|
||||||
|
((attribute) ["#" "[" "]"] @punctuation.delimiter)
|
||||||
|
|
||||||
|
[
|
||||||
|
"else"
|
||||||
|
"if"
|
||||||
|
"match"
|
||||||
|
] @keyword.control.conditional
|
||||||
|
|
||||||
|
(bool_literal) @constant.builtin.boolean
|
||||||
|
(int_literal) @constant.numeric.integer
|
||||||
|
|
||||||
|
[
|
||||||
|
"&"
|
||||||
|
"inv"
|
||||||
|
"-"
|
||||||
|
"=>"
|
||||||
|
">"
|
||||||
|
"<"
|
||||||
|
"::<"
|
||||||
|
"::$<"
|
||||||
|
"="
|
||||||
|
"->"
|
||||||
|
"~"
|
||||||
|
"!"
|
||||||
|
] @operator
|
||||||
|
|
||||||
|
|
||||||
|
((op_add) @operator)
|
||||||
|
((op_sub) @operator)
|
||||||
|
((op_mul) @operator)
|
||||||
|
((op_equals) @operator)
|
||||||
|
((op_lt) @operator)
|
||||||
|
((op_gt) @operator)
|
||||||
|
((op_le) @operator)
|
||||||
|
((op_ge) @operator)
|
||||||
|
((op_lshift) @operator)
|
||||||
|
((op_rshift) @operator)
|
||||||
|
((op_bitwise_and) @operator)
|
||||||
|
((op_bitwise_xor) @operator)
|
||||||
|
((op_bitwise_or) @operator)
|
||||||
|
((op_logical_and) @operator)
|
||||||
|
((op_logical_or) @operator)
|
||||||
|
|
||||||
|
|
||||||
|
[
|
||||||
|
(line_comment)
|
||||||
|
(block_comment)
|
||||||
|
] @comment
|
||||||
|
|
||||||
|
[
|
||||||
|
(doc_comment)
|
||||||
|
] @comment.block.documentation
|
||||||
|
|
||||||
|
|
||||||
|
((identifier) @type
|
||||||
|
(#match? @type "[A-Z]"))
|
||||||
|
|
||||||
|
((scoped_identifier
|
||||||
|
name: (identifier) @type)
|
||||||
|
(#match? @type "^[A-Z]"))
|
||||||
|
|
||||||
|
((identifier) @constant
|
||||||
|
(#match? @constant "^[A-Z][A-Z\\d_]*$"))
|
||||||
|
|
@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
[
|
||||||
|
(unit_definition)
|
||||||
|
(struct_definition)
|
||||||
|
(enum_definition)
|
||||||
|
(enum_member)
|
||||||
|
(impl)
|
||||||
|
(mod)
|
||||||
|
(argument_list)
|
||||||
|
(let_binding)
|
||||||
|
(block)
|
||||||
|
(tuple_literal)
|
||||||
|
(array_literal)
|
||||||
|
(paren_expression)
|
||||||
|
(turbofish)
|
||||||
|
(generic_parameters)
|
||||||
|
(named_unpack)
|
||||||
|
(positional_unpack)
|
||||||
|
(tuple_pattern)
|
||||||
|
] @indent
|
||||||
|
|
||||||
|
[
|
||||||
|
"}"
|
||||||
|
"]"
|
||||||
|
")"
|
||||||
|
] @outdent
|
||||||
|
|
@ -0,0 +1,22 @@
|
|||||||
|
(string) @string
|
||||||
|
|
||||||
|
(field_name) @variable.other.member
|
||||||
|
|
||||||
|
(comment) @comment
|
||||||
|
|
||||||
|
(number) @constant.numeric
|
||||||
|
; covers e.g. booleans and "inf"
|
||||||
|
(scalar_value (identifier)) @constant
|
||||||
|
; Covers "-inf"
|
||||||
|
(scalar_value (signed_identifier)) @constant.numeric
|
||||||
|
|
||||||
|
[
|
||||||
|
(open_squiggly)
|
||||||
|
(close_squiggly)
|
||||||
|
(open_square)
|
||||||
|
(close_square)
|
||||||
|
(open_arrow)
|
||||||
|
(close_arrow)
|
||||||
|
] @punctuation.bracket
|
||||||
|
|
||||||
|
"," @punctuation.delimiter
|
@ -0,0 +1,11 @@
|
|||||||
|
[
|
||||||
|
(message_value)
|
||||||
|
(message_list)
|
||||||
|
(scalar_list)
|
||||||
|
] @indent
|
||||||
|
|
||||||
|
[
|
||||||
|
(close_arrow)
|
||||||
|
(close_square)
|
||||||
|
(close_squiggly)
|
||||||
|
] @outdent
|
@ -0,0 +1,12 @@
|
|||||||
|
(message_field
|
||||||
|
(_) @entry.inside) @entry.around
|
||||||
|
|
||||||
|
(scalar_field
|
||||||
|
(_) @entry.inside) @entry.around
|
||||||
|
|
||||||
|
(message_list
|
||||||
|
(_) @entry.around)
|
||||||
|
|
||||||
|
(scalar_list
|
||||||
|
(_) @entry.around)
|
||||||
|
|
@ -0,0 +1,15 @@
|
|||||||
|
(term_declaration) @function.around
|
||||||
|
|
||||||
|
(type_declaration) @class.inside
|
||||||
|
(record) @class.inside
|
||||||
|
|
||||||
|
(comment) @comment.inside
|
||||||
|
(comment)+ @comment.around
|
||||||
|
|
||||||
|
(doc_block) @comment.around
|
||||||
|
|
||||||
|
(literal_list) @entry.around
|
||||||
|
|
||||||
|
(parenthesized_or_tuple_pattern) @entry.around
|
||||||
|
|
||||||
|
(pattern) @entry.around
|
@ -0,0 +1,110 @@
|
|||||||
|
inherits="adwaita-dark"
|
||||||
|
"attribute" = "orange_5"
|
||||||
|
|
||||||
|
"type" = "teal_4"
|
||||||
|
"type.builtin" = "teal_4"
|
||||||
|
|
||||||
|
"constructor" = "blue_4"
|
||||||
|
|
||||||
|
"constant" = "violet_4"
|
||||||
|
"constant.builtin" = { fg = "violet_4", modifiers = ["bold"] }
|
||||||
|
"constant.character" = "teal_5"
|
||||||
|
"constant.numeric" = { fg = "teal_5", modifiers = ["bold"] }
|
||||||
|
"constant.character.escape" = "violet_4"
|
||||||
|
|
||||||
|
"string" = "teal_3"
|
||||||
|
"string.regexp" = "purple_4"
|
||||||
|
"string.special" = "blue_4"
|
||||||
|
|
||||||
|
"comment" = "light_6"
|
||||||
|
|
||||||
|
"variable" = "dark_5"
|
||||||
|
"variable.parameter" = "orange_4"
|
||||||
|
"variable.builtin" = "orange_4"
|
||||||
|
"variable.other" = "teal_4"
|
||||||
|
"variable.other.member" = "teal_5"
|
||||||
|
|
||||||
|
"label" = "purple_4"
|
||||||
|
|
||||||
|
"punctuation" = "dark_4"
|
||||||
|
"punctuation.delimiter" = "dark_4"
|
||||||
|
"punctuation.bracket" = "dark_4"
|
||||||
|
"punctuation.special" = "red_5"
|
||||||
|
|
||||||
|
"keyword" = { fg = "orange_4", modifiers = ["bold"] }
|
||||||
|
"keyword.control" = { fg = "orange_4", modifiers = ["bold"] }
|
||||||
|
"keyword.operator" = "purple_4"
|
||||||
|
"keyword.directive" = { fg = "orange_4", modifiers = ["bold"] }
|
||||||
|
"keyword.function" = "orange_4"
|
||||||
|
"keyword.storage" = { fg = "orange_4", modifiers = ["bold"] }
|
||||||
|
|
||||||
|
"operator" = "purple_4"
|
||||||
|
|
||||||
|
"function" = "blue_4"
|
||||||
|
"function.builtin" = "blue_4"
|
||||||
|
"function.macro" = { fg = "blue_4", modifiers = ["bold"] }
|
||||||
|
"function.special" = { fg = "blue_4", modifiers = ["bold"] }
|
||||||
|
|
||||||
|
"tag" = "teal_4"
|
||||||
|
|
||||||
|
"namespace" = "orange_4"
|
||||||
|
|
||||||
|
"markup" = "dark_4"
|
||||||
|
"markup.heading" = { fg = "teal_4", modifiers = ["bold"] }
|
||||||
|
"markup.list" = { fg = "orange_4", modifiers = ["bold"] }
|
||||||
|
"markup.bold" = { fg = "dark_4", modifiers = ["bold"] }
|
||||||
|
"markup.italic" = { fg = "dark_4", modifiers = ["italic"] }
|
||||||
|
"markup.link" = { fg = "blue_5", modifiers = ["underlined"] }
|
||||||
|
"markup.quote" = { fg = "dark_3", modifiers = ["italic"] }
|
||||||
|
"diff.plus" = "teal_5"
|
||||||
|
"diff.minus" = "red_3"
|
||||||
|
"diff.delta" = "orange_5"
|
||||||
|
"diff.delta.moved" = "orange_4"
|
||||||
|
|
||||||
|
"ui.background" = { fg = "dark_4", bg = "light_1" }
|
||||||
|
"ui.background.separator" = { fg = "split_and_borders", bg = "light_2" }
|
||||||
|
"ui.cursor" = { fg = "light_2", bg = "dark_5" }
|
||||||
|
"ui.cursor.insert" = { fg = "light_2", bg = "dark_4" }
|
||||||
|
"ui.cursor.primary.insert" = { fg = "light_2", bg = "yellow_5" }
|
||||||
|
"ui.cursor.select" = { fg = "light_2", bg = "dark_5" }
|
||||||
|
"ui.cursor.match" = { fg = "light_2", bg = "blue_1" }
|
||||||
|
"ui.cursor.primary" = { fg = "light_2", bg = "dark_6" }
|
||||||
|
"ui.linenr" = "light_5"
|
||||||
|
"ui.linenr.selected" = { fg = "dark_2", bg = "light_3", modifiers = [
|
||||||
|
"bold",
|
||||||
|
] }
|
||||||
|
"ui.statusline" = { fg = "dark_4", bg = "light_4" }
|
||||||
|
"ui.statusline.inactive" = { fg = "dark_3", bg = "light_3" }
|
||||||
|
"ui.statusline.insert" = { fg = "light_5", bg = "teal_3" }
|
||||||
|
"ui.statusline.select" = { fg = "light_4", bg = "blue_3" }
|
||||||
|
"ui.popup" = { bg = "light_3" }
|
||||||
|
"ui.window" = "split_and_borders"
|
||||||
|
"ui.help" = { bg = "light_3" }
|
||||||
|
"ui.text" = "dark_4"
|
||||||
|
"ui.virtual" = "light_1"
|
||||||
|
"ui.virtual.ruler" = { bg = "light_5"}
|
||||||
|
"ui.menu" = { fg = "dark_4", bg = "light_3" }
|
||||||
|
"ui.menu.selected" = { fg = "dark_4", bg = "blue_1" }
|
||||||
|
"ui.menu.scroll" = { fg = "dark_6", bg = "light_3" }
|
||||||
|
"ui.selection" = { bg = "blue_0" }
|
||||||
|
"ui.selection.primary" = { bg = "blue_0" }
|
||||||
|
"ui.cursorline.primary" = { bg = "light_3" }
|
||||||
|
"ui.virtual.whitespace" = "light_7"
|
||||||
|
|
||||||
|
"warning" = "yellow_4"
|
||||||
|
"error" = "red_5"
|
||||||
|
"info" = "purple_3"
|
||||||
|
"hint" = "blue_3"
|
||||||
|
|
||||||
|
"diagnostic.hint" = { fg = "blue_4", modifiers = ["dim"] }
|
||||||
|
"diagnostic.info" = { fg = "purple_4", modifiers = ["dim"] }
|
||||||
|
"diagnostic.error" = { fg = "red_5", modifiers = ["underlined"] }
|
||||||
|
"diagnostic.warning" = { fg = "yellow_4", modifiers = ["underlined"] }
|
||||||
|
"diagnostic.unnecessary" = { modifiers = ["dim"] }
|
||||||
|
"diagnostic.deprecated" = { modifiers = ["crossed_out"] }
|
||||||
|
|
||||||
|
"ui.bufferline" = { fg = "light_7", bg = "light_2" }
|
||||||
|
"ui.bufferline.active" = { fg = "dark_4", bg = "light_4", modifiers = ["bold"]}
|
||||||
|
|
||||||
|
[palette]
|
||||||
|
blue_0 = "#d3e4f9"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue