Merge branch 'master' into debug
This commit is contained in:
commit
0a6b60085a
31 changed files with 846 additions and 117 deletions
8
.gitmodules
vendored
8
.gitmodules
vendored
|
@ -122,3 +122,11 @@
|
|||
path = helix-syntax/languages/tree-sitter-svelte
|
||||
url = https://github.com/Himujjal/tree-sitter-svelte
|
||||
shallow = true
|
||||
[submodule "helix-syntax/languages/tree-sitter-vue"]
|
||||
path = helix-syntax/languages/tree-sitter-vue
|
||||
url = https://github.com/ikatyang/tree-sitter-vue
|
||||
shallow = true
|
||||
[submodule "helix-syntax/languages/tree-sitter-tsq"]
|
||||
path = helix-syntax/languages/tree-sitter-tsq
|
||||
url = https://github.com/tree-sitter/tree-sitter-tsq
|
||||
shallow = true
|
||||
|
|
69
Cargo.lock
generated
69
Cargo.lock
generated
|
@ -37,9 +37,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
|||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.16"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90682c8d613ad3373e66de8c6411e0ae2ab2571e879d2efbf73558cc66f21279"
|
||||
checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
|
@ -54,9 +54,9 @@ checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"
|
|||
|
||||
[[package]]
|
||||
name = "bytes"
|
||||
version = "1.0.1"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b700ce4376041dcd0a327fd0097c41095743c4c8af8887265942faf1100bd040"
|
||||
checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8"
|
||||
|
||||
[[package]]
|
||||
name = "cassowary"
|
||||
|
@ -66,9 +66,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.70"
|
||||
version = "1.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0"
|
||||
checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
|
@ -369,6 +369,7 @@ dependencies = [
|
|||
"regex",
|
||||
"ropey",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"similar",
|
||||
"smallvec",
|
||||
"tendril",
|
||||
|
@ -531,18 +532,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "instant"
|
||||
version = "0.1.10"
|
||||
version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d"
|
||||
checksum = "716d3d89f35ac6a34fd0eed635395f4c3b76fa889338a4632e5231a8684216bd"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "0.4.7"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||
checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4"
|
||||
|
||||
[[package]]
|
||||
name = "jsonrpc-core"
|
||||
|
@ -565,15 +566,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.99"
|
||||
version = "0.2.103"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7f823d141fe0a24df1e23b4af4e3c7ba9e5966ec514ea068c93024aa7deb765"
|
||||
checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a"
|
||||
checksum = "c0cf036d15402bea3c5d4de17b3fce76b3e4a56ebc1f577be0e7a72f7c607cf0"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
|
@ -581,9 +582,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.4"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb"
|
||||
checksum = "712a4d093c9976e24e7dbca41db895dabcbac38eb5f4045393d17a95bdfb1109"
|
||||
dependencies = [
|
||||
"scopeguard",
|
||||
]
|
||||
|
@ -599,9 +600,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "lsp-types"
|
||||
version = "0.90.0"
|
||||
version = "0.90.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7404037aab080771c90b0a499836d9d8a10336ecd07badf969567b65c6d51a1"
|
||||
checksum = "6f3734ab1d7d157fc0c45110e06b587c31cd82bea2ccfd6b563cbff0aaeeb1d3"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"serde",
|
||||
|
@ -711,9 +712,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
|||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.11.1"
|
||||
version = "0.11.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
|
||||
checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99"
|
||||
dependencies = [
|
||||
"instant",
|
||||
"lock_api",
|
||||
|
@ -722,9 +723,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "parking_lot_core"
|
||||
version = "0.8.3"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
|
||||
checksum = "d76e8e1493bcac0d2766c42737f34458f1c8c50c0d23bcb24ea953affb273216"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"instant",
|
||||
|
@ -754,9 +755,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
|||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.28"
|
||||
version = "1.0.29"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612"
|
||||
checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d"
|
||||
dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
@ -999,9 +1000,9 @@ checksum = "d44a3643b4ff9caf57abcee9c2c621d6c03d9135e0d8b589bd9afb5992cb176a"
|
|||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "1.0.74"
|
||||
version = "1.0.78"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1873d832550d4588c3dbc20f01361ab00bfe741048f71e3fecf145a7cc18b29c"
|
||||
checksum = "a4eac2e6c19f5c3abc0c229bea31ff0b9b091c7b14990e8924b92902a303a0c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1021,18 +1022,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.29"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "602eca064b2d83369e2b2f34b09c70b605402801927c65c11071ac911d299b88"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.29"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bad553cc2c78e8de258400763a647e80e6d1b31ee237275d756f6836d204494c"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1059,9 +1060,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.3.1"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "848a1e1181b9f6753b5e96a092749e29b11d19ede67dfbbd6c7dc7e0f49b5338"
|
||||
checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7"
|
||||
dependencies = [
|
||||
"tinyvec_macros",
|
||||
]
|
||||
|
@ -1094,9 +1095,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "1.3.0"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54473be61f4ebe4efd09cec9bd5d16fa51d70ea0192213d754d2d500457db110"
|
||||
checksum = "154794c8f499c2619acd19e839294703e9e32e7630ef5f46ea80d4ef0fbee5eb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -83,4 +83,6 @@ a good overview of the internals.
|
|||
|
||||
# Getting help
|
||||
|
||||
Your question might already be answered on the [FAQ](https://github.com/helix-editor/helix/wiki/FAQ).
|
||||
|
||||
Discuss the project on the community [Matrix Space](https://matrix.to/#/#helix-community:matrix.org) (make sure to join `#helix-editor:matrix.org` if you're on a client that doesn't support Matrix Spaces yet).
|
||||
|
|
|
@ -19,6 +19,8 @@ To override global configuration parameters, create a `config.toml` file located
|
|||
| `line-number` | Line number display (`absolute`, `relative`) | `absolute` |
|
||||
| `smart-case` | Enable smart case regex searching (case insensitive unless pattern contains upper case characters) | `true` |
|
||||
| `auto-pairs` | Enable automatic insertion of pairs to parenthese, brackets, etc. | `true` |
|
||||
| `auto-completion` | Enable automatic pop up of auto-completion. | `true` |
|
||||
| `idle-timeout` | Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. | `400` |
|
||||
|
||||
## LSP
|
||||
|
||||
|
|
|
@ -196,7 +196,7 @@ a > .hljs {
|
|||
border-radius: 3px;
|
||||
}
|
||||
|
||||
:not(pre):not(a) > .hljs {
|
||||
:not(pre):not(a):not(td):not(p) > .hljs {
|
||||
color: var(--inline-code-color);
|
||||
overflow-x: initial;
|
||||
}
|
||||
|
|
|
@ -162,7 +162,6 @@ table thead td {
|
|||
table thead th {
|
||||
padding: .75rem;
|
||||
text-align: left;
|
||||
color: var(--table-border-color);
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
width: auto;
|
||||
|
@ -228,3 +227,7 @@ blockquote *:last-child {
|
|||
margin: 5px 0px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.result-no-output {
|
||||
font-style: italic;
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
.ayu {
|
||||
--bg: hsl(210, 25%, 8%);
|
||||
--fg: #c5c5c5;
|
||||
--heading-fg: #c5c5c5;
|
||||
|
||||
--sidebar-bg: #14191f;
|
||||
--sidebar-fg: #c8c9db;
|
||||
|
@ -54,7 +53,6 @@
|
|||
.coal {
|
||||
--bg: hsl(200, 7%, 8%);
|
||||
--fg: #98a3ad;
|
||||
--heading-fg: #98a3ad;
|
||||
|
||||
--sidebar-bg: #292c2f;
|
||||
--sidebar-fg: #a1adb8;
|
||||
|
@ -95,7 +93,6 @@
|
|||
.light {
|
||||
--bg: hsl(0, 0%, 100%);
|
||||
--fg: hsl(0, 0%, 0%);
|
||||
--heading-fg: hsl(0, 0%, 0%);
|
||||
|
||||
--sidebar-bg: #fafafa;
|
||||
--sidebar-fg: hsl(0, 0%, 0%);
|
||||
|
@ -110,7 +107,7 @@
|
|||
|
||||
--links: #20609f;
|
||||
|
||||
--inline-code-color: #a39e9b;
|
||||
--inline-code-color: #301900;
|
||||
|
||||
--theme-popup-bg: #fafafa;
|
||||
--theme-popup-border: #cccccc;
|
||||
|
@ -136,7 +133,6 @@
|
|||
.navy {
|
||||
--bg: hsl(226, 23%, 11%);
|
||||
--fg: #bcbdd0;
|
||||
--heading-fg: #bcbdd0;
|
||||
|
||||
--sidebar-bg: #282d3f;
|
||||
--sidebar-fg: #c8c9db;
|
||||
|
@ -177,7 +173,6 @@
|
|||
.rust {
|
||||
--bg: hsl(60, 9%, 87%);
|
||||
--fg: #262625;
|
||||
--heading-fg: #262625;
|
||||
|
||||
--sidebar-bg: #3b2e2a;
|
||||
--sidebar-fg: #c8c9db;
|
||||
|
@ -192,7 +187,7 @@
|
|||
|
||||
--links: #2b79a2;
|
||||
|
||||
--inline-code-color: #c5c8c6;
|
||||
--inline-code-color: #6e6b5e;
|
||||
|
||||
--theme-popup-bg: #e1e1db;
|
||||
--theme-popup-border: #b38f6b;
|
||||
|
@ -218,8 +213,7 @@
|
|||
@media (prefers-color-scheme: dark) {
|
||||
.light.no-js {
|
||||
--bg: hsl(200, 7%, 8%);
|
||||
--fg: #ebeafa;
|
||||
--heading-fg: #ebeafa;
|
||||
--fg: #98a3ad;
|
||||
|
||||
--sidebar-bg: #292c2f;
|
||||
--sidebar-fg: #a1adb8;
|
||||
|
@ -234,7 +228,7 @@
|
|||
|
||||
--links: #2b79a2;
|
||||
|
||||
--inline-code-color: #6e6b5e;
|
||||
--inline-code-color: #c5c8c6;
|
||||
|
||||
--theme-popup-bg: #141617;
|
||||
--theme-popup-border: #43484d;
|
||||
|
|
|
@ -29,6 +29,7 @@ arc-swap = "1"
|
|||
regex = "1"
|
||||
|
||||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
toml = "0.5"
|
||||
|
||||
similar = "2.1"
|
||||
|
|
|
@ -29,10 +29,10 @@ use std::borrow::Cow;
|
|||
/// "(anchor, head)", followed by example text with "[" and "]"
|
||||
/// inserted to represent the anchor and head positions:
|
||||
///
|
||||
/// - (0, 3): [Som]e text.
|
||||
/// - (3, 0): ]Som[e text.
|
||||
/// - (2, 7): So[me te]xt.
|
||||
/// - (1, 1): S[]ome text.
|
||||
/// - (0, 3): `[Som]e text`.
|
||||
/// - (3, 0): `]Som[e text`.
|
||||
/// - (2, 7): `So[me te]xt`.
|
||||
/// - (1, 1): `S[]ome text`.
|
||||
///
|
||||
/// Ranges are considered to be inclusive on the left and
|
||||
/// exclusive on the right, regardless of anchor-head ordering.
|
||||
|
|
|
@ -31,6 +31,15 @@ where
|
|||
.transpose()
|
||||
}
|
||||
|
||||
fn deserialize_lsp_config<'de, D>(deserializer: D) -> Result<Option<serde_json::Value>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
Option::<toml::Value>::deserialize(deserializer)?
|
||||
.map(|toml| toml.try_into().map_err(serde::de::Error::custom))
|
||||
.transpose()
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Configuration {
|
||||
pub language: Vec<LanguageConfiguration>,
|
||||
|
@ -46,7 +55,9 @@ pub struct LanguageConfiguration {
|
|||
pub file_types: Vec<String>, // filename ends_with? <Gemfile, rb, etc>
|
||||
pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
|
||||
pub comment_token: Option<String>,
|
||||
pub config: Option<String>,
|
||||
|
||||
#[serde(default, skip_serializing, deserialize_with = "deserialize_lsp_config")]
|
||||
pub config: Option<serde_json::Value>,
|
||||
|
||||
#[serde(default)]
|
||||
pub auto_format: bool,
|
||||
|
|
|
@ -318,15 +318,7 @@ impl Registry {
|
|||
let (client, incoming, initialize_notify) = Client::start(
|
||||
&config.command,
|
||||
&config.args,
|
||||
serde_json::from_str(language_config.config.as_deref().unwrap_or(""))
|
||||
.map_err(|e| {
|
||||
log::error!(
|
||||
"LSP Config, {}, in `languages.toml` for `{}`",
|
||||
e,
|
||||
language_config.scope()
|
||||
)
|
||||
})
|
||||
.ok(),
|
||||
language_config.config.clone(),
|
||||
id,
|
||||
)?;
|
||||
self.incoming.push(UnboundedReceiverStream::new(incoming));
|
||||
|
|
1
helix-syntax/languages/tree-sitter-tsq
Submodule
1
helix-syntax/languages/tree-sitter-tsq
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit b665659d3238e6036e22ed0e24935e60efb39415
|
1
helix-syntax/languages/tree-sitter-vue
Submodule
1
helix-syntax/languages/tree-sitter-vue
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 91fe2754796cd8fba5f229505a23fa08f3546c06
|
|
@ -102,6 +102,7 @@ impl Application {
|
|||
if !args.files.is_empty() {
|
||||
let first = &args.files[0]; // we know it's not empty
|
||||
if first.is_dir() {
|
||||
std::env::set_current_dir(&first)?;
|
||||
editor.new_file(Action::VerticalSplit);
|
||||
compositor.push(Box::new(ui::file_picker(first.clone())));
|
||||
} else {
|
||||
|
@ -204,6 +205,11 @@ impl Application {
|
|||
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
|
||||
self.render();
|
||||
}
|
||||
_ = &mut self.editor.idle_timer => {
|
||||
// idle timeout
|
||||
self.editor.clear_idle_timer();
|
||||
self.handle_idle_timeout();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -233,6 +239,38 @@ impl Application {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn handle_idle_timeout(&mut self) {
|
||||
use crate::commands::{completion, Context};
|
||||
use helix_view::document::Mode;
|
||||
|
||||
if doc_mut!(self.editor).mode != Mode::Insert || !self.config.editor.auto_completion {
|
||||
return;
|
||||
}
|
||||
let editor_view = self
|
||||
.compositor
|
||||
.find(std::any::type_name::<ui::EditorView>())
|
||||
.expect("expected at least one EditorView");
|
||||
let editor_view = editor_view
|
||||
.as_any_mut()
|
||||
.downcast_mut::<ui::EditorView>()
|
||||
.unwrap();
|
||||
|
||||
if editor_view.completion.is_some() {
|
||||
return;
|
||||
}
|
||||
|
||||
let mut cx = Context {
|
||||
register: None,
|
||||
editor: &mut self.editor,
|
||||
jobs: &mut self.jobs,
|
||||
count: None,
|
||||
callback: None,
|
||||
on_next_key_callback: None,
|
||||
};
|
||||
completion(&mut cx);
|
||||
self.render();
|
||||
}
|
||||
|
||||
pub fn handle_terminal_events(&mut self, event: Option<Result<Event, crossterm::ErrorKind>>) {
|
||||
let mut cx = crate::compositor::Context {
|
||||
editor: &mut self.editor,
|
||||
|
@ -417,14 +455,6 @@ impl Application {
|
|||
server_id: usize,
|
||||
) {
|
||||
use helix_lsp::{Call, MethodCall, Notification};
|
||||
let editor_view = self
|
||||
.compositor
|
||||
.find(std::any::type_name::<ui::EditorView>())
|
||||
.expect("expected at least one EditorView");
|
||||
let editor_view = editor_view
|
||||
.as_any_mut()
|
||||
.downcast_mut::<ui::EditorView>()
|
||||
.unwrap();
|
||||
|
||||
match call {
|
||||
Call::Notification(helix_lsp::jsonrpc::Notification { method, params, .. }) => {
|
||||
|
@ -534,7 +564,19 @@ impl Application {
|
|||
Notification::LogMessage(params) => {
|
||||
log::info!("window/logMessage: {:?}", params);
|
||||
}
|
||||
Notification::ProgressMessage(params) => {
|
||||
Notification::ProgressMessage(params)
|
||||
if !self
|
||||
.compositor
|
||||
.has_component(std::any::type_name::<ui::Prompt>()) =>
|
||||
{
|
||||
let editor_view = self
|
||||
.compositor
|
||||
.find(std::any::type_name::<ui::EditorView>())
|
||||
.expect("expected at least one EditorView");
|
||||
let editor_view = editor_view
|
||||
.as_any_mut()
|
||||
.downcast_mut::<ui::EditorView>()
|
||||
.unwrap();
|
||||
let lsp::ProgressParams { token, value } = params;
|
||||
|
||||
let lsp::ProgressParamsValue::WorkDone(work) = value;
|
||||
|
@ -609,6 +651,9 @@ impl Application {
|
|||
self.editor.set_status(status);
|
||||
}
|
||||
}
|
||||
Notification::ProgressMessage(_params) => {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
Call::MethodCall(helix_lsp::jsonrpc::MethodCall {
|
||||
|
@ -643,6 +688,14 @@ impl Application {
|
|||
MethodCall::WorkDoneProgressCreate(params) => {
|
||||
self.lsp_progress.create(server_id, params.token);
|
||||
|
||||
let editor_view = self
|
||||
.compositor
|
||||
.find(std::any::type_name::<ui::EditorView>())
|
||||
.expect("expected at least one EditorView");
|
||||
let editor_view = editor_view
|
||||
.as_any_mut()
|
||||
.downcast_mut::<ui::EditorView>()
|
||||
.unwrap();
|
||||
let spinner = editor_view.spinners_mut().get_or_create(server_id);
|
||||
if spinner.is_stopped() {
|
||||
spinner.start();
|
||||
|
|
|
@ -1310,7 +1310,8 @@ fn global_search(cx: &mut Context) {
|
|||
|
||||
cx.push_layer(Box::new(prompt));
|
||||
|
||||
let root = find_root(None).unwrap_or_else(|| PathBuf::from("./"));
|
||||
let current_path = doc_mut!(cx.editor).path().cloned();
|
||||
|
||||
let show_picker = async move {
|
||||
let all_matches: Vec<(usize, PathBuf)> =
|
||||
UnboundedReceiverStream::new(all_matches_rx).collect().await;
|
||||
|
@ -1320,14 +1321,19 @@ fn global_search(cx: &mut Context) {
|
|||
editor.set_status("No matches found".to_string());
|
||||
return;
|
||||
}
|
||||
|
||||
let picker = FilePicker::new(
|
||||
all_matches,
|
||||
move |(_line_num, path)| {
|
||||
path.strip_prefix(&root)
|
||||
.unwrap_or(path)
|
||||
let relative_path = helix_core::path::get_relative_path(path)
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.into()
|
||||
.to_owned();
|
||||
if current_path.as_ref().map(|p| p == path).unwrap_or(false) {
|
||||
format!("{} (*)", relative_path).into()
|
||||
} else {
|
||||
relative_path.into()
|
||||
}
|
||||
},
|
||||
move |editor: &mut Editor, (line_num, path), action| {
|
||||
match editor.open(path.into(), action) {
|
||||
|
@ -4160,7 +4166,7 @@ fn remove_primary_selection(cx: &mut Context) {
|
|||
doc.set_selection(view.id, selection);
|
||||
}
|
||||
|
||||
fn completion(cx: &mut Context) {
|
||||
pub fn completion(cx: &mut Context) {
|
||||
// trigger on trigger char, or if user calls it
|
||||
// (or on word char typing??)
|
||||
// after it's triggered, if response marked is_incomplete, update on every subsequent keypress
|
||||
|
@ -4205,10 +4211,8 @@ fn completion(cx: &mut Context) {
|
|||
};
|
||||
|
||||
let offset_encoding = language_server.offset_encoding();
|
||||
let cursor = doc
|
||||
.selection(view.id)
|
||||
.primary()
|
||||
.cursor(doc.text().slice(..));
|
||||
let text = doc.text().slice(..);
|
||||
let cursor = doc.selection(view.id).primary().cursor(text);
|
||||
|
||||
let pos = pos_to_lsp_pos(doc.text(), cursor, offset_encoding);
|
||||
|
||||
|
@ -4216,6 +4220,15 @@ fn completion(cx: &mut Context) {
|
|||
|
||||
let trigger_offset = cursor;
|
||||
|
||||
// TODO: trigger_offset should be the cursor offset but we also need a starting offset from where we want to apply
|
||||
// completion filtering. For example logger.te| should filter the initial suggestion list with "te".
|
||||
|
||||
use helix_core::chars;
|
||||
let mut iter = text.chars_at(cursor);
|
||||
iter.reverse();
|
||||
let offset = iter.take_while(|ch| chars::char_is_word(*ch)).count();
|
||||
let start_offset = cursor.saturating_sub(offset);
|
||||
|
||||
cx.callback(
|
||||
future,
|
||||
move |editor: &mut Editor,
|
||||
|
@ -4238,7 +4251,7 @@ fn completion(cx: &mut Context) {
|
|||
};
|
||||
|
||||
if items.is_empty() {
|
||||
editor.set_error("No completion available".to_string());
|
||||
// editor.set_error("No completion available".to_string());
|
||||
return;
|
||||
}
|
||||
let size = compositor.size();
|
||||
|
@ -4246,7 +4259,14 @@ fn completion(cx: &mut Context) {
|
|||
.find(std::any::type_name::<ui::EditorView>())
|
||||
.unwrap();
|
||||
if let Some(ui) = ui.as_any_mut().downcast_mut::<ui::EditorView>() {
|
||||
ui.set_completion(items, offset_encoding, trigger_offset, size);
|
||||
ui.set_completion(
|
||||
editor,
|
||||
items,
|
||||
offset_encoding,
|
||||
start_offset,
|
||||
trigger_offset,
|
||||
size,
|
||||
);
|
||||
};
|
||||
},
|
||||
);
|
||||
|
|
|
@ -171,6 +171,12 @@ impl Compositor {
|
|||
(None, CursorKind::Hidden)
|
||||
}
|
||||
|
||||
pub fn has_component(&self, type_name: &str) -> bool {
|
||||
self.layers
|
||||
.iter()
|
||||
.any(|component| component.type_name() == type_name)
|
||||
}
|
||||
|
||||
pub fn find(&mut self, type_name: &str) -> Option<&mut dyn Component> {
|
||||
self.layers
|
||||
.iter_mut()
|
||||
|
|
|
@ -69,14 +69,18 @@ impl menu::Item for CompletionItem {
|
|||
/// Wraps a Menu.
|
||||
pub struct Completion {
|
||||
popup: Popup<Menu<CompletionItem>>,
|
||||
start_offset: usize,
|
||||
#[allow(dead_code)]
|
||||
trigger_offset: usize,
|
||||
// TODO: maintain a completioncontext with trigger kind & trigger char
|
||||
}
|
||||
|
||||
impl Completion {
|
||||
pub fn new(
|
||||
editor: &Editor,
|
||||
items: Vec<CompletionItem>,
|
||||
offset_encoding: helix_lsp::OffsetEncoding,
|
||||
start_offset: usize,
|
||||
trigger_offset: usize,
|
||||
) -> Self {
|
||||
// let items: Vec<CompletionItem> = Vec::new();
|
||||
|
@ -175,16 +179,22 @@ impl Completion {
|
|||
};
|
||||
});
|
||||
let popup = Popup::new(menu);
|
||||
Self {
|
||||
let mut completion = Self {
|
||||
popup,
|
||||
start_offset,
|
||||
trigger_offset,
|
||||
}
|
||||
};
|
||||
|
||||
// need to recompute immediately in case start_offset != trigger_offset
|
||||
completion.recompute_filter(editor);
|
||||
|
||||
completion
|
||||
}
|
||||
|
||||
pub fn update(&mut self, cx: &mut commands::Context) {
|
||||
pub fn recompute_filter(&mut self, editor: &Editor) {
|
||||
// recompute menu based on matches
|
||||
let menu = self.popup.contents_mut();
|
||||
let (view, doc) = current!(cx.editor);
|
||||
let (view, doc) = current_ref!(editor);
|
||||
|
||||
// cx.hooks()
|
||||
// cx.add_hook(enum type, ||)
|
||||
|
@ -200,14 +210,22 @@ impl Completion {
|
|||
.selection(view.id)
|
||||
.primary()
|
||||
.cursor(doc.text().slice(..));
|
||||
if self.trigger_offset <= cursor {
|
||||
let fragment = doc.text().slice(self.trigger_offset..cursor);
|
||||
if self.start_offset <= cursor {
|
||||
let fragment = doc.text().slice(self.start_offset..cursor);
|
||||
let text = Cow::from(fragment);
|
||||
// TODO: logic is same as ui/picker
|
||||
menu.score(&text);
|
||||
} else {
|
||||
// we backspaced before the start offset, clear the menu
|
||||
// this will cause the editor to remove the completion popup
|
||||
menu.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn update(&mut self, cx: &mut commands::Context) {
|
||||
self.recompute_filter(cx.editor)
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.popup.contents().is_empty()
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ pub struct EditorView {
|
|||
keymaps: Keymaps,
|
||||
on_next_key: Option<Box<dyn FnOnce(&mut commands::Context, KeyEvent)>>,
|
||||
last_insert: (commands::Command, Vec<KeyEvent>),
|
||||
completion: Option<Completion>,
|
||||
pub(crate) completion: Option<Completion>,
|
||||
spinners: ProgressSpinners,
|
||||
autoinfo: Option<Info>,
|
||||
}
|
||||
|
@ -984,12 +984,21 @@ impl EditorView {
|
|||
|
||||
pub fn set_completion(
|
||||
&mut self,
|
||||
editor: &Editor,
|
||||
items: Vec<helix_lsp::lsp::CompletionItem>,
|
||||
offset_encoding: helix_lsp::OffsetEncoding,
|
||||
start_offset: usize,
|
||||
trigger_offset: usize,
|
||||
size: Rect,
|
||||
) {
|
||||
let mut completion = Completion::new(items, offset_encoding, trigger_offset);
|
||||
let mut completion =
|
||||
Completion::new(editor, items, offset_encoding, start_offset, trigger_offset);
|
||||
|
||||
if completion.is_empty() {
|
||||
// skip if we got no completion results
|
||||
return;
|
||||
}
|
||||
|
||||
// TODO : propagate required size on resize to completion too
|
||||
completion.required_size((size.width, size.height));
|
||||
self.completion = Some(completion);
|
||||
|
@ -1211,6 +1220,7 @@ impl Component for EditorView {
|
|||
EventResult::Consumed(None)
|
||||
}
|
||||
Event::Key(key) => {
|
||||
cxt.editor.reset_idle_timer();
|
||||
let mut key = KeyEvent::from(key);
|
||||
canonicalize_key(&mut key);
|
||||
// clear status
|
||||
|
@ -1245,6 +1255,7 @@ impl Component for EditorView {
|
|||
if callback.is_some() {
|
||||
// assume close_fn
|
||||
self.completion = None;
|
||||
cxt.editor.clear_idle_timer(); // don't retrigger
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1258,6 +1269,7 @@ impl Component for EditorView {
|
|||
completion.update(&mut cxt);
|
||||
if completion.is_empty() {
|
||||
self.completion = None;
|
||||
cxt.editor.clear_idle_timer(); // don't retrigger
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,14 @@ impl<T: Item> Menu<T> {
|
|||
self.recalculate = true;
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.matches.clear();
|
||||
|
||||
// reset cursor position
|
||||
self.cursor = None;
|
||||
self.scroll = 0;
|
||||
}
|
||||
|
||||
pub fn move_up(&mut self) {
|
||||
let len = self.matches.len();
|
||||
let pos = self.cursor.map_or(0, |i| (i + len.saturating_sub(1)) % len) % len;
|
||||
|
|
|
@ -271,12 +271,18 @@ impl<T> Picker<T> {
|
|||
}
|
||||
|
||||
pub fn move_up(&mut self) {
|
||||
if self.matches.is_empty() {
|
||||
return;
|
||||
}
|
||||
let len = self.matches.len();
|
||||
let pos = ((self.cursor + len.saturating_sub(1)) % len) % len;
|
||||
self.cursor = pos;
|
||||
}
|
||||
|
||||
pub fn move_down(&mut self) {
|
||||
if self.matches.is_empty() {
|
||||
return;
|
||||
}
|
||||
let len = self.matches.len();
|
||||
let pos = (self.cursor + 1) % len;
|
||||
self.cursor = pos;
|
||||
|
|
|
@ -13,10 +13,12 @@ use tokio_stream::wrappers::UnboundedReceiverStream;
|
|||
use std::{
|
||||
collections::HashMap,
|
||||
path::{Path, PathBuf},
|
||||
pin::Pin,
|
||||
sync::Arc,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use tokio::time::{sleep, Duration, Instant, Sleep};
|
||||
|
||||
use slotmap::SlotMap;
|
||||
|
||||
use anyhow::Error;
|
||||
|
@ -29,6 +31,14 @@ use helix_dap as dap;
|
|||
|
||||
use serde::Deserialize;
|
||||
|
||||
fn deserialize_duration_millis<'de, D>(deserializer: D) -> Result<Duration, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let millis = u64::deserialize(deserializer)?;
|
||||
Ok(Duration::from_millis(millis))
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Deserialize)]
|
||||
#[serde(rename_all = "kebab-case", default)]
|
||||
pub struct Config {
|
||||
|
@ -42,12 +52,17 @@ pub struct Config {
|
|||
pub shell: Vec<String>,
|
||||
/// Line number mode.
|
||||
pub line_number: LineNumber,
|
||||
/// Middle click paste support. Defaults to true
|
||||
/// Middle click paste support. Defaults to true.
|
||||
pub middle_click_paste: bool,
|
||||
/// Smart case: Case insensitive searching unless pattern contains upper case characters. Defaults to true.
|
||||
pub smart_case: bool,
|
||||
/// Automatic insertion of pairs to parentheses, brackets, etc. Defaults to true.
|
||||
pub auto_pairs: bool,
|
||||
/// Automatic auto-completion, automatically pop up without user trigger. Defaults to true.
|
||||
pub auto_completion: bool,
|
||||
/// Time in milliseconds since last keypress before idle timers trigger. Used for autocompletion, set to 0 for instant. Defaults to 400ms.
|
||||
#[serde(skip_serializing, deserialize_with = "deserialize_duration_millis")]
|
||||
pub idle_timeout: Duration,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Deserialize)]
|
||||
|
@ -75,6 +90,8 @@ impl Default for Config {
|
|||
middle_click_paste: true,
|
||||
smart_case: true,
|
||||
auto_pairs: true,
|
||||
auto_completion: true,
|
||||
idle_timeout: Duration::from_millis(400),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -105,6 +122,8 @@ pub struct Editor {
|
|||
pub status_msg: Option<(String, Severity)>,
|
||||
|
||||
pub config: Config,
|
||||
|
||||
pub idle_timer: Pin<Box<Sleep>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
|
@ -146,10 +165,24 @@ impl Editor {
|
|||
registers: Registers::default(),
|
||||
clipboard_provider: get_clipboard_provider(),
|
||||
status_msg: None,
|
||||
idle_timer: Box::pin(sleep(config.idle_timeout)),
|
||||
config,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_idle_timer(&mut self) {
|
||||
// equivalent to internal Instant::far_future() (30 years)
|
||||
self.idle_timer
|
||||
.as_mut()
|
||||
.reset(Instant::now() + Duration::from_secs(86400 * 365 * 30));
|
||||
}
|
||||
|
||||
pub fn reset_idle_timer(&mut self) {
|
||||
self.idle_timer
|
||||
.as_mut()
|
||||
.reset(Instant::now() + self.config.idle_timeout);
|
||||
}
|
||||
|
||||
pub fn clear_status(&mut self) {
|
||||
self.status_msg = None;
|
||||
}
|
||||
|
|
|
@ -44,3 +44,19 @@ macro_rules! view {
|
|||
$( $editor ).+ .tree.get($( $editor ).+ .tree.focus)
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! doc {
|
||||
( $( $editor:ident ).+ ) => {{
|
||||
$crate::current_ref!( $( $editor ).+ ).1
|
||||
}};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! current_ref {
|
||||
( $( $editor:ident ).+ ) => {{
|
||||
let view = $( $editor ).+ .tree.get($( $editor ).+ .tree.focus);
|
||||
let doc = &$( $editor ).+ .documents[view.doc];
|
||||
(view, doc)
|
||||
}};
|
||||
}
|
||||
|
|
|
@ -6,19 +6,11 @@ file-types = ["rs"]
|
|||
roots = []
|
||||
auto-format = true
|
||||
comment-token = "//"
|
||||
config = """
|
||||
{
|
||||
"cargo": {
|
||||
"loadOutDirsFromCheck": true
|
||||
},
|
||||
"procMacro": {
|
||||
"enable": false
|
||||
}
|
||||
}
|
||||
"""
|
||||
|
||||
language-server = { command = "rust-analyzer" }
|
||||
indent = { tab-width = 4, unit = " " }
|
||||
[language.config]
|
||||
cargo = { loadOutDirsFromCheck = true }
|
||||
procMacro = { enable = false }
|
||||
|
||||
[language.debugger]
|
||||
name = "lldb-vscode"
|
||||
|
@ -133,6 +125,16 @@ request = "attach"
|
|||
completion = [ "pid" ]
|
||||
args = { console = "internalConsole", pid = "{0}" }
|
||||
|
||||
[[language]]
|
||||
name = "c-sharp"
|
||||
scope = "source.csharp"
|
||||
injection-regex = "c-?sharp"
|
||||
file-types = ["cs"]
|
||||
roots = []
|
||||
comment-token = "//"
|
||||
|
||||
indent = { tab-width = 4, unit = "\t" }
|
||||
|
||||
[[language]]
|
||||
name = "go"
|
||||
scope = "source.go"
|
||||
|
@ -248,7 +250,7 @@ file-types = ["py"]
|
|||
roots = []
|
||||
comment-token = "#"
|
||||
|
||||
language-server = { command = "pyls" }
|
||||
language-server = { command = "pylsp" }
|
||||
# TODO: pyls needs utf-8 offsets
|
||||
indent = { tab-width = 4, unit = " " }
|
||||
|
||||
|
@ -380,6 +382,15 @@ roots = []
|
|||
indent = { tab-width = 2, unit = " " }
|
||||
language-server = { command = "svelteserver", args = ["--stdio"] }
|
||||
|
||||
|
||||
[[language]]
|
||||
name = "vue"
|
||||
scope = "source.vue"
|
||||
injection-regex = "vue"
|
||||
file-types = ["vue"]
|
||||
roots = []
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
|
||||
[[language]]
|
||||
name = "yaml"
|
||||
scope = "source.yaml"
|
||||
|
@ -409,3 +420,23 @@ comment-token = "//"
|
|||
|
||||
language-server = { command = "zls" }
|
||||
indent = { tab-width = 4, unit = " " }
|
||||
|
||||
[[language]]
|
||||
name = "prolog"
|
||||
scope = "source.prolog"
|
||||
roots = []
|
||||
file-types = ["pl", "prolog"]
|
||||
comment-token = "%"
|
||||
|
||||
language-server = { command = "swipl", args = [
|
||||
"-g", "use_module(library(lsp_server))",
|
||||
"-g", "lsp_server:main",
|
||||
"-t", "halt", "--", "stdio"] }
|
||||
|
||||
[[language]]
|
||||
name = "tsq"
|
||||
scope = "source.tsq"
|
||||
file-types = ["scm"]
|
||||
roots = []
|
||||
comment-token = ";"
|
||||
indent = { tab-width = 2, unit = " " }
|
||||
|
|
238
runtime/queries/c-sharp/highlights.scm
Normal file
238
runtime/queries/c-sharp/highlights.scm
Normal file
|
@ -0,0 +1,238 @@
|
|||
;; Methods
|
||||
(method_declaration (identifier) @type (identifier) @function)
|
||||
|
||||
;; Types
|
||||
(interface_declaration name: (identifier) @type)
|
||||
(class_declaration name: (identifier) @type)
|
||||
(enum_declaration name: (identifier) @type)
|
||||
(struct_declaration (identifier) @type)
|
||||
(record_declaration (identifier) @type)
|
||||
(namespace_declaration name: (identifier) @type)
|
||||
|
||||
(constructor_declaration name: (identifier) @type)
|
||||
|
||||
[
|
||||
(implicit_type)
|
||||
(nullable_type)
|
||||
(pointer_type)
|
||||
(function_pointer_type)
|
||||
(predefined_type)
|
||||
] @type.builtin
|
||||
|
||||
;; Enum
|
||||
(enum_member_declaration (identifier) @variable.property)
|
||||
|
||||
;; Literals
|
||||
[
|
||||
(real_literal)
|
||||
(integer_literal)
|
||||
] @number
|
||||
|
||||
[
|
||||
(character_literal)
|
||||
(string_literal)
|
||||
(verbatim_string_literal)
|
||||
(interpolated_string_text)
|
||||
(interpolated_verbatim_string_text)
|
||||
"\""
|
||||
"$\""
|
||||
"@$\""
|
||||
"$@\""
|
||||
] @string
|
||||
|
||||
[
|
||||
(boolean_literal)
|
||||
(null_literal)
|
||||
(void_keyword)
|
||||
] @constant.builtin
|
||||
|
||||
;; Comments
|
||||
(comment) @comment
|
||||
|
||||
;; Tokens
|
||||
[
|
||||
";"
|
||||
"."
|
||||
","
|
||||
] @punctuation.delimiter
|
||||
|
||||
[
|
||||
"--"
|
||||
"-"
|
||||
"-="
|
||||
"&"
|
||||
"&&"
|
||||
"+"
|
||||
"++"
|
||||
"+="
|
||||
"<"
|
||||
"<<"
|
||||
"="
|
||||
"=="
|
||||
"!"
|
||||
"!="
|
||||
"=>"
|
||||
">"
|
||||
">>"
|
||||
"|"
|
||||
"||"
|
||||
"?"
|
||||
"??"
|
||||
"^"
|
||||
"~"
|
||||
"*"
|
||||
"/"
|
||||
"%"
|
||||
":"
|
||||
] @operator
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
"{"
|
||||
"}"
|
||||
] @punctuation.bracket
|
||||
|
||||
;; Keywords
|
||||
(modifier) @keyword
|
||||
(this_expression) @keyword
|
||||
(escape_sequence) @keyword
|
||||
|
||||
[
|
||||
"as"
|
||||
"base"
|
||||
"break"
|
||||
"case"
|
||||
"catch"
|
||||
"checked"
|
||||
"class"
|
||||
"continue"
|
||||
"default"
|
||||
"delegate"
|
||||
"do"
|
||||
"else"
|
||||
"enum"
|
||||
"event"
|
||||
"explicit"
|
||||
"finally"
|
||||
"for"
|
||||
"foreach"
|
||||
"goto"
|
||||
"if"
|
||||
"implicit"
|
||||
"interface"
|
||||
"is"
|
||||
"lock"
|
||||
"namespace"
|
||||
"operator"
|
||||
"params"
|
||||
"return"
|
||||
"sizeof"
|
||||
"stackalloc"
|
||||
"struct"
|
||||
"switch"
|
||||
"throw"
|
||||
"try"
|
||||
"typeof"
|
||||
"unchecked"
|
||||
"using"
|
||||
"while"
|
||||
"new"
|
||||
"await"
|
||||
"in"
|
||||
"yield"
|
||||
"get"
|
||||
"set"
|
||||
"when"
|
||||
"out"
|
||||
"ref"
|
||||
"from"
|
||||
"where"
|
||||
"select"
|
||||
"record"
|
||||
"init"
|
||||
"with"
|
||||
"let"
|
||||
] @keyword
|
||||
|
||||
|
||||
;; Linq
|
||||
(from_clause (identifier) @variable)
|
||||
(group_clause)
|
||||
(order_by_clause)
|
||||
(select_clause (identifier) @variable)
|
||||
(query_continuation (identifier) @variable) @keyword
|
||||
|
||||
;; Record
|
||||
(with_expression
|
||||
(with_initializer_expression
|
||||
(simple_assignment_expression
|
||||
(identifier) @variable)))
|
||||
|
||||
;; Exprs
|
||||
(binary_expression (identifier) @variable (identifier) @variable)
|
||||
(binary_expression (identifier)* @variable)
|
||||
(conditional_expression (identifier) @variable)
|
||||
(prefix_unary_expression (identifier) @variable)
|
||||
(postfix_unary_expression (identifier)* @variable)
|
||||
(assignment_expression (identifier) @variable)
|
||||
(cast_expression (identifier) @type (identifier) @variable)
|
||||
|
||||
;; Class
|
||||
(base_list (identifier) @type)
|
||||
(property_declaration (generic_name))
|
||||
(property_declaration
|
||||
type: (nullable_type) @type
|
||||
name: (identifier) @variable)
|
||||
(property_declaration
|
||||
type: (predefined_type) @type
|
||||
name: (identifier) @variable)
|
||||
(property_declaration
|
||||
type: (identifier) @type
|
||||
name: (identifier) @variable)
|
||||
|
||||
;; Lambda
|
||||
(lambda_expression) @variable
|
||||
|
||||
;; Attribute
|
||||
(attribute) @type
|
||||
|
||||
;; Parameter
|
||||
(parameter
|
||||
type: (identifier) @type
|
||||
name: (identifier) @variable.parameter)
|
||||
(parameter (identifier) @variable.parameter)
|
||||
(parameter_modifier) @keyword
|
||||
|
||||
;; Typeof
|
||||
(type_of_expression (identifier) @type)
|
||||
|
||||
;; Variable
|
||||
(variable_declaration (identifier) @type)
|
||||
(variable_declarator (identifier) @variable)
|
||||
|
||||
;; Return
|
||||
(return_statement (identifier) @variable)
|
||||
(yield_statement (identifier) @variable)
|
||||
|
||||
;; Type
|
||||
(generic_name (identifier) @type)
|
||||
(type_parameter (identifier) @variable.parameter)
|
||||
(type_argument_list (identifier) @type)
|
||||
|
||||
;; Type constraints
|
||||
(type_parameter_constraints_clause (identifier) @variable.parameter)
|
||||
(type_constraint (identifier) @type)
|
||||
|
||||
;; Exception
|
||||
(catch_declaration (identifier) @type (identifier) @variable)
|
||||
(catch_declaration (identifier) @type)
|
||||
|
||||
;; Switch
|
||||
(switch_statement (identifier) @variable)
|
||||
(switch_expression (identifier) @variable)
|
||||
|
||||
;; Lock statement
|
||||
(lock_statement (identifier) @variable)
|
|
@ -47,7 +47,7 @@
|
|||
; Variables
|
||||
|
||||
((identifier) @constant
|
||||
(#match? @constant "^_*[A-Z][A-Z\d_]+"))
|
||||
(#match? @constant "^_*[A-Z][A-Z\\d_]+$"))
|
||||
|
||||
(identifier) @variable
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
(relative_scope) @variable.builtin
|
||||
|
||||
((name) @constant
|
||||
(#match? @constant "^_?[A-Z][A-Z\d_]+$"))
|
||||
(#match? @constant "^_?[A-Z][A-Z\\d_]+$"))
|
||||
|
||||
((name) @constructor
|
||||
(#match? @constructor "^[A-Z]"))
|
||||
|
|
46
runtime/queries/tsq/highlights.scm
Normal file
46
runtime/queries/tsq/highlights.scm
Normal file
|
@ -0,0 +1,46 @@
|
|||
; mark the string passed #match? as a regex
|
||||
(((predicate_name) @function
|
||||
(capture)
|
||||
(string) @string.regexp)
|
||||
(#eq? @function "#match?"))
|
||||
|
||||
; highlight inheritance comments
|
||||
((query . (comment) @keyword.directive)
|
||||
(#match? @keyword.directive "^;\ +inherits *:"))
|
||||
|
||||
[
|
||||
"("
|
||||
")"
|
||||
"["
|
||||
"]"
|
||||
] @punctuation.bracket
|
||||
|
||||
":" @punctuation.delimiter
|
||||
|
||||
[
|
||||
(one_or_more)
|
||||
(zero_or_one)
|
||||
(zero_or_more)
|
||||
] @operator
|
||||
|
||||
[
|
||||
(wildcard_node)
|
||||
(anchor)
|
||||
] @constant.builtin
|
||||
|
||||
[
|
||||
(anonymous_leaf)
|
||||
(string)
|
||||
] @string
|
||||
|
||||
(comment) @comment
|
||||
|
||||
(field_name) @property
|
||||
|
||||
(capture) @label
|
||||
|
||||
(predicate_name) @function
|
||||
|
||||
(escape_sequence) @escape
|
||||
|
||||
(node_name) @variable
|
21
runtime/queries/vue/highlights.scm
Normal file
21
runtime/queries/vue/highlights.scm
Normal file
|
@ -0,0 +1,21 @@
|
|||
(tag_name) @tag
|
||||
(end_tag) @tag
|
||||
|
||||
(directive_name) @keyword
|
||||
(directive_argument) @constant
|
||||
|
||||
(attribute
|
||||
(attribute_name) @attribute
|
||||
(quoted_attribute_value
|
||||
(attribute_value) @string)
|
||||
)
|
||||
|
||||
(comment) @comment
|
||||
|
||||
[
|
||||
"<"
|
||||
">"
|
||||
"</"
|
||||
"{{"
|
||||
"}}"
|
||||
] @punctuation.bracket
|
17
runtime/queries/vue/injections.scm
Normal file
17
runtime/queries/vue/injections.scm
Normal file
|
@ -0,0 +1,17 @@
|
|||
(directive_attribute
|
||||
(directive_name) @keyword
|
||||
(quoted_attribute_value
|
||||
(attribute_value) @injection.content)
|
||||
(#set! injection.language "javascript"))
|
||||
|
||||
((interpolation
|
||||
(raw_text) @injection.content)
|
||||
(#set! injection.language "javascript"))
|
||||
|
||||
((script_element
|
||||
(raw_text) @injection.content)
|
||||
(#set! injection.language "javascript"))
|
||||
|
||||
((style_element
|
||||
(raw_text) @injection.content)
|
||||
(#set! injection.language "css"))
|
|
@ -1,7 +1,7 @@
|
|||
# Author : RayGervais<raygervais@hotmail.ca>
|
||||
|
||||
# "ui.linenr.selected" = { fg = "#d8dee9" }
|
||||
# "ui.text.focus" = { fg = "#e5ded6", modifiers= ["bold"] }
|
||||
"ui.text.focus" = { fg = "#88c0d0", modifiers= ["bold"] }
|
||||
# "ui.menu.selected" = { fg = "#e5ded6", bg = "#313f4e" }
|
||||
|
||||
# "info" = "#b48ead"
|
||||
|
@ -24,8 +24,8 @@
|
|||
"ui.cursor.match" = { bg = "434c5e" }
|
||||
|
||||
# nord3 - comments
|
||||
"comment" = "#4c566a"
|
||||
"ui.linenr" = { fg = "#4c566a" }
|
||||
"comment" = "#616E88"
|
||||
"ui.linenr" = { fg = "#616E88" }
|
||||
|
||||
# Snow Storm
|
||||
# nord4 - cursor, variables, constants, attributes, fields
|
||||
|
|
|
@ -20,7 +20,6 @@ _________________________________________________________________
|
|||
the first lesson.
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= BASIC CURSOR MOVEMENT =
|
||||
=================================================================
|
||||
|
@ -43,7 +42,6 @@ _________________________________________________________________
|
|||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= EXITING HELIX =
|
||||
=================================================================
|
||||
|
@ -66,7 +64,6 @@ _________________________________________________________________
|
|||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= DELETION =
|
||||
=================================================================
|
||||
|
@ -89,7 +86,6 @@ _________________________________________________________________
|
|||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= INSERT MODE =
|
||||
=================================================================
|
||||
|
@ -112,7 +108,6 @@ _________________________________________________________________
|
|||
Note: The status bar will display your current mode.
|
||||
Notice that when you press i, 'NOR' changes to 'INS'.
|
||||
|
||||
|
||||
=================================================================
|
||||
= MORE ON INSERT MODE =
|
||||
=================================================================
|
||||
|
@ -123,7 +118,7 @@ _________________________________________________________________
|
|||
|
||||
Common examples of insertion commands include:
|
||||
i - Insert before the selection.
|
||||
a - Insert after the selection. (a means "append")
|
||||
a - Insert after the selection. (a means 'append')
|
||||
I - Insert at the start of the line.
|
||||
A - Insert at the end of the line.
|
||||
|
||||
|
@ -135,7 +130,6 @@ _________________________________________________________________
|
|||
--> This sentence is miss
|
||||
This sentence is missing some text.
|
||||
|
||||
|
||||
=================================================================
|
||||
= SAVING A FILE =
|
||||
=================================================================
|
||||
|
@ -158,7 +152,6 @@ _________________________________________________________________
|
|||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= RECAP =
|
||||
=================================================================
|
||||
|
@ -181,7 +174,6 @@ _________________________________________________________________
|
|||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= MOTIONS AND SELECTIONS =
|
||||
=================================================================
|
||||
|
@ -204,7 +196,6 @@ _________________________________________________________________
|
|||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= MORE ON MOTIONS =
|
||||
=================================================================
|
||||
|
@ -227,6 +218,203 @@ _________________________________________________________________
|
|||
|
||||
|
||||
|
||||
=================================================================
|
||||
= THE CHANGE COMMAND =
|
||||
=================================================================
|
||||
|
||||
Press c to change the current selection.
|
||||
|
||||
The change command deletes the current selection and enters
|
||||
Insert mode, so it is a very common shorthand for di.
|
||||
|
||||
1. Move the cursor to the line below marked -->.
|
||||
2. Move to the start of an incorrect word and press w to
|
||||
select it.
|
||||
3. Press c to delete the word and enter Insert mode.
|
||||
4. Type the correct word.
|
||||
5. Repeat until the line matches the line below it.
|
||||
|
||||
--> This paper has heavy words behind it.
|
||||
This sentence has incorrect words in it.
|
||||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= COUNTS WITH MOTIONS =
|
||||
=================================================================
|
||||
|
||||
Type a number before a motion to repeat it that many times.
|
||||
|
||||
1. Move the cursor to the line below marked -->.
|
||||
|
||||
2. Type 2w to move 2 words forward.
|
||||
|
||||
3. Type 3e to move to the end of the third word forward.
|
||||
|
||||
4. Type 2b to move 2 words backwards
|
||||
|
||||
5. Try the above with different numbers.
|
||||
|
||||
--> This is just a line with words you can move around in.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= SELECTING LINES =
|
||||
=================================================================
|
||||
|
||||
Press x to select a whole line. Press again to select the next.
|
||||
|
||||
1. Move the cursor to the second line below marked -->.
|
||||
2. Press x to select the line, and d to delete it.
|
||||
3. Move to the fourth line.
|
||||
4. Press x twice or type 2x to select 2 lines, and d to delete.
|
||||
|
||||
--> 1) Roses are red,
|
||||
--> 2) Mud is fun,
|
||||
--> 3) Violets are blue,
|
||||
--> 4) I have a car,
|
||||
--> 5) Clocks tell time,
|
||||
--> 6) Sugar is sweet,
|
||||
--> 7) And so are you.
|
||||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= UNDOING =
|
||||
=================================================================
|
||||
|
||||
Type u to undo. Type U to redo.
|
||||
|
||||
1. Move the cursor to the line below marked -->.
|
||||
2. Move to the first error, and press d to delete it.
|
||||
3. Type u to undo your deletion.
|
||||
4. Fix all the errors on the line.
|
||||
5. Type u several times to undo your fixes.
|
||||
6. Type U (<SHIFT> + u) several times to redo your fixes.
|
||||
|
||||
--> Fiix the errors on thhis line and reeplace them witth undo.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= RECAP =
|
||||
=================================================================
|
||||
|
||||
* Type w to select forward until the next word.
|
||||
* Type e to select to the end of the current word.
|
||||
* Type b to select backward to the start of the current word.
|
||||
* Use uppercase counterparts, W,E,B, to traverse WORDS.
|
||||
|
||||
* Typing d deletes the entire selection, so you can delete a
|
||||
word forward by typing wd.
|
||||
|
||||
* Type c to delete the selection and enter Insert mode.
|
||||
|
||||
* Type a number before a motion to repeat it that many times.
|
||||
|
||||
* Type x to select the entire current line. Type x again to
|
||||
select the next line.
|
||||
|
||||
* Type u to undo. Type U to redo.
|
||||
|
||||
|
||||
=================================================================
|
||||
= MULTIPLE CURSORS =
|
||||
=================================================================
|
||||
|
||||
Type C to duplicate the cursor to the next line.
|
||||
|
||||
1. Move the cursor to the first line below marked -->.
|
||||
2. Type C to duplicate the cursor to the next line. Keys you
|
||||
press will now affect both cursors.
|
||||
3. Use Insert mode to correct the lines. The two cursors will
|
||||
fix both lines simultaneously.
|
||||
4. Type , to remove the second cursor.
|
||||
|
||||
--> Fix th two nes at same ime.
|
||||
--> Fix th two nes at same ime.
|
||||
|
||||
Fix these two lines at the same time.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= THE SELECT COMMAND =
|
||||
=================================================================
|
||||
|
||||
Type s to select matches in the selection.
|
||||
|
||||
1. Move the cursor to the line below marked -->.
|
||||
2. Press x to select the line.
|
||||
3. Press s. A prompt will appear.
|
||||
4. Type 'apples' and press <ENTER>. Both occurrences of
|
||||
'apples' in the line will be selected.
|
||||
5. You can now press c and change 'apples' to something else,
|
||||
like 'oranges'.
|
||||
6. Type , to remove the second cursor.
|
||||
|
||||
--> I like to eat apples since my favorite fruit is apples.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= SELECTING VIA REGEX =
|
||||
=================================================================
|
||||
|
||||
The select command selects regular expressions, not just exact
|
||||
matches, allowing you to target more complex patterns.
|
||||
|
||||
1. Move the cursor to the line below marked -->.
|
||||
2. Select the line with x and then press s.
|
||||
3. Enter ' +' to select any amount of consecutive spaces >1.
|
||||
4. Press c and change the matches to single spaces.
|
||||
|
||||
--> This sentence has some extra spaces.
|
||||
|
||||
Note: If you want to perform find-and-replace, the select
|
||||
command is the way to do it. Select the text you want
|
||||
to replace in — type % to select the whole file — and
|
||||
then perform the steps explained above.
|
||||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
= COLLAPSING SELECTIONS =
|
||||
=================================================================
|
||||
|
||||
Type ; to collapse selections to single cursors.
|
||||
|
||||
Sometimes, you want to deselect without having to move the
|
||||
cursor(s). This can be done using the ; key.
|
||||
|
||||
1. Move the cursor to the line below marked -->.
|
||||
|
||||
2. Use the motions you have learned to move around the line,
|
||||
and try using ; to deselect the text after it is selected
|
||||
by the motions.
|
||||
|
||||
--> This is an error-free line with words to move around in.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
=================================================================
|
||||
This tutorial is still a work-in-progress.
|
||||
|
|
Loading…
Reference in a new issue