mirror of
https://github.com/helix-editor/helix.git
synced 2025-01-19 13:37:06 +04:00
Merge branch 'master' into great_line_ending_and_cursor_range_cleanup
This commit is contained in:
commit
a77274e8bb
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
@ -99,6 +99,7 @@ jobs:
|
|||||||
else
|
else
|
||||||
cp "target/${{ matrix.target }}/release/hx" "dist/"
|
cp "target/${{ matrix.target }}/release/hx" "dist/"
|
||||||
fi
|
fi
|
||||||
|
cp -r runtime dist
|
||||||
|
|
||||||
- uses: actions/upload-artifact@v2.2.4
|
- uses: actions/upload-artifact@v2.2.4
|
||||||
with:
|
with:
|
||||||
@ -148,7 +149,7 @@ jobs:
|
|||||||
pkgname=helix-$TAG-$platform
|
pkgname=helix-$TAG-$platform
|
||||||
mkdir tmp/$pkgname
|
mkdir tmp/$pkgname
|
||||||
cp LICENSE README.md tmp/$pkgname
|
cp LICENSE README.md tmp/$pkgname
|
||||||
cp -r runtime tmp/$pkgname/
|
mv bins-$platform/runtime tmp/$pkgname/
|
||||||
mv bins-$platform/hx$exe tmp/$pkgname
|
mv bins-$platform/hx$exe tmp/$pkgname
|
||||||
chmod +x tmp/$pkgname/hx$exe
|
chmod +x tmp/$pkgname/hx$exe
|
||||||
|
|
||||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ target
|
|||||||
helix-term/rustfmt.toml
|
helix-term/rustfmt.toml
|
||||||
helix-syntax/languages/
|
helix-syntax/languages/
|
||||||
result
|
result
|
||||||
|
runtime/grammars
|
||||||
|
57
Cargo.lock
generated
57
Cargo.lock
generated
@ -13,9 +13,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anyhow"
|
name = "anyhow"
|
||||||
version = "1.0.41"
|
version = "1.0.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "15af2628f6890fe2609a3b91bef4c83450512802e59489f9c1cb1fa5df064a61"
|
checksum = "595d3cfa7a60d4555cb5067b99f07142a08ea778de5cf993f7b75c7d8fabc486"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "arc-swap"
|
name = "arc-swap"
|
||||||
@ -58,12 +58,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.0.68"
|
version = "1.0.69"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
|
checksum = "e70cc2f62c6ce1868963827bd677764c62d07c3d9a3e1fb1177ee1a9ab199eb2"
|
||||||
dependencies = [
|
|
||||||
"jobserver",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cfg-if"
|
name = "cfg-if"
|
||||||
@ -354,8 +351,9 @@ dependencies = [
|
|||||||
name = "helix-syntax"
|
name = "helix-syntax"
|
||||||
version = "0.3.0"
|
version = "0.3.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"cc",
|
"cc",
|
||||||
"serde",
|
"libloading",
|
||||||
"threadpool",
|
"threadpool",
|
||||||
"tree-sitter",
|
"tree-sitter",
|
||||||
]
|
]
|
||||||
@ -475,15 +473,6 @@ version = "0.4.7"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "jobserver"
|
|
||||||
version = "0.1.22"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "972f5ae5d1cb9c6ae417789196c803205313edde988685da5e3aae0827b9e7fd"
|
|
||||||
dependencies = [
|
|
||||||
"libc",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "jsonrpc-core"
|
name = "jsonrpc-core"
|
||||||
version = "17.1.0"
|
version = "17.1.0"
|
||||||
@ -509,6 +498,16 @@ version = "0.2.97"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
|
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libloading"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6f84d96438c15fcd6c3f244c8fce01d1e2b9c6b5623e9c711dc9286d8fc92d6a"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 1.0.0",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
version = "0.4.4"
|
version = "0.4.4"
|
||||||
@ -914,9 +913,9 @@ checksum = "f173ac3d1a7e3b28003f40de0b5ce7fe2710f9b9dc3fc38664cebee46b3b6527"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "slotmap"
|
name = "slotmap"
|
||||||
version = "1.0.3"
|
version = "1.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "585cd5dffe4e9e06f6dfdf66708b70aca3f781bed561f4f667b2d9c0d4559e36"
|
checksum = "a952280edbecfb1d4bd3cf2dbc309dc6ab523e53487c438ae21a6df09fe84bc4"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
@ -957,18 +956,18 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror"
|
name = "thiserror"
|
||||||
version = "1.0.25"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fa6f76457f59514c7eeb4e59d891395fab0b2fd1d40723ae737d64153392e9c6"
|
checksum = "93119e4feac1cbe6c798c34d3a53ea0026b0b1de6a120deef895137c0529bfe2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"thiserror-impl",
|
"thiserror-impl",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "thiserror-impl"
|
name = "thiserror-impl"
|
||||||
version = "1.0.25"
|
version = "1.0.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8a36768c0fbf1bb15eca10defa29526bda730a2376c2ab4393ccfa16fb1a318d"
|
checksum = "060d69a0afe7796bf42e9e2ff91f5ee691fb15c53d38b4b62a9a53eb23164745"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1010,9 +1009,9 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.7.1"
|
version = "1.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5fb2ed024293bb19f7a5dc54fe83bf86532a44c12a2bb8ba40d64a4509395ca2"
|
checksum = "98c8b05dc14c75ea83d63dd391100353789f5f24b8b3866542a5e85c8be8e985"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
"autocfg",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -1041,9 +1040,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-stream"
|
name = "tokio-stream"
|
||||||
version = "0.1.6"
|
version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f8864d706fdb3cc0843a49647ac892720dac98a6eeb818b77190592cf4994066"
|
checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
@ -1104,9 +1103,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-segmentation"
|
name = "unicode-segmentation"
|
||||||
version = "1.7.1"
|
version = "1.8.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-width"
|
name = "unicode-width"
|
||||||
|
11
README.md
11
README.md
@ -41,14 +41,17 @@ # Installation
|
|||||||
|
|
||||||
This will install the `hx` binary to `$HOME/.cargo/bin`.
|
This will install the `hx` binary to `$HOME/.cargo/bin`.
|
||||||
|
|
||||||
Now copy the `runtime/` directory somewhere. Helix will by default look for the runtime
|
Helix also needs it's runtime files so make sure to copy/symlink the `runtime/` directory into the
|
||||||
inside the config directory or the same directory as executable, but that can be overriden
|
config directory (for example `~/.config/helix/runtime` on Linux/macOS). This location can be overriden
|
||||||
via the `HELIX_RUNTIME` environment variable.
|
via the `HELIX_RUNTIME` environment variable.
|
||||||
|
|
||||||
> NOTE: running via cargo doesn't require setting explicit `HELIX_RUNTIME` path, it will automatically
|
Packages already solve this for you by wrapping the `hx` binary with a wrapper
|
||||||
|
that sets the variable to the install dir.
|
||||||
|
|
||||||
|
> NOTE: running via cargo also doesn't require setting explicit `HELIX_RUNTIME` path, it will automatically
|
||||||
> detect the `runtime` directory in the project root.
|
> detect the `runtime` directory in the project root.
|
||||||
|
|
||||||
If you want to embed the `runtime/` directory into the Helix binary you can build
|
Alternatively, if you want to embed the `runtime/` directory into the Helix binary you can build
|
||||||
it with:
|
it with:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -45,6 +45,9 @@ ### Changes
|
|||||||
| ----- | ----------- |
|
| ----- | ----------- |
|
||||||
| `r` | Replace with a character |
|
| `r` | Replace with a character |
|
||||||
| `R` | Replace with yanked text |
|
| `R` | Replace with yanked text |
|
||||||
|
| `~` | Switch case of the selected text |
|
||||||
|
| `\`` | Set the selected text to upper case |
|
||||||
|
| `Alt-\`` | Set the selected text to lower case |
|
||||||
| `i` | Insert before selection |
|
| `i` | Insert before selection |
|
||||||
| `a` | Insert after selection (append) |
|
| `a` | Insert after selection (append) |
|
||||||
| `I` | Insert at the start of the line |
|
| `I` | Insert at the start of the line |
|
||||||
|
@ -51,6 +51,7 @@ ## Creating a theme
|
|||||||
| `attribute` | |
|
| `attribute` | |
|
||||||
| `keyword` | |
|
| `keyword` | |
|
||||||
| `keyword.directive` | Preprocessor directives (\#if in C) |
|
| `keyword.directive` | Preprocessor directives (\#if in C) |
|
||||||
|
| `keyword.control` | Control flow |
|
||||||
| `namespace` | |
|
| `namespace` | |
|
||||||
| `punctuation` | |
|
| `punctuation` | |
|
||||||
| `punctuation.delimiter` | |
|
| `punctuation.delimiter` | |
|
||||||
@ -61,6 +62,7 @@ ## Creating a theme
|
|||||||
| `variable.parameter` | |
|
| `variable.parameter` | |
|
||||||
| `type` | |
|
| `type` | |
|
||||||
| `type.builtin` | |
|
| `type.builtin` | |
|
||||||
|
| `type.enum.variant` | Enum variants |
|
||||||
| `constructor` | |
|
| `constructor` | |
|
||||||
| `function` | |
|
| `function` | |
|
||||||
| `function.macro` | |
|
| `function.macro` | |
|
||||||
|
@ -19,7 +19,7 @@ helix-syntax = { version = "0.3", path = "../helix-syntax" }
|
|||||||
ropey = "1.3"
|
ropey = "1.3"
|
||||||
smallvec = "1.4"
|
smallvec = "1.4"
|
||||||
tendril = "0.4.2"
|
tendril = "0.4.2"
|
||||||
unicode-segmentation = "1.7"
|
unicode-segmentation = "1.8"
|
||||||
unicode-width = "0.1"
|
unicode-width = "0.1"
|
||||||
unicode-general-category = "0.4"
|
unicode-general-category = "0.4"
|
||||||
# slab = "0.4.2"
|
# slab = "0.4.2"
|
||||||
|
@ -253,14 +253,14 @@ pub fn change<I>(document: &Document, changes: I) -> Self
|
|||||||
|
|
||||||
let doc = Rope::from(doc);
|
let doc = Rope::from(doc);
|
||||||
use crate::syntax::{
|
use crate::syntax::{
|
||||||
Configuration, IndentationConfiguration, Lang, LanguageConfiguration, Loader,
|
Configuration, IndentationConfiguration, LanguageConfiguration, Loader,
|
||||||
};
|
};
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
let loader = Loader::new(Configuration {
|
let loader = Loader::new(Configuration {
|
||||||
language: vec![LanguageConfiguration {
|
language: vec![LanguageConfiguration {
|
||||||
scope: "source.rust".to_string(),
|
scope: "source.rust".to_string(),
|
||||||
file_types: vec!["rs".to_string()],
|
file_types: vec!["rs".to_string()],
|
||||||
language_id: Lang::Rust,
|
language_id: "Rust".to_string(),
|
||||||
highlight_config: OnceCell::new(),
|
highlight_config: OnceCell::new(),
|
||||||
//
|
//
|
||||||
roots: vec![],
|
roots: vec![],
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
Rope, RopeSlice, Tendril,
|
Rope, RopeSlice, Tendril,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use helix_syntax::{get_language, get_language_name, Lang};
|
pub use helix_syntax::get_language;
|
||||||
|
|
||||||
use arc_swap::ArcSwap;
|
use arc_swap::ArcSwap;
|
||||||
|
|
||||||
@ -31,7 +31,7 @@ pub struct Configuration {
|
|||||||
#[serde(rename_all = "kebab-case")]
|
#[serde(rename_all = "kebab-case")]
|
||||||
pub struct LanguageConfiguration {
|
pub struct LanguageConfiguration {
|
||||||
#[serde(rename = "name")]
|
#[serde(rename = "name")]
|
||||||
pub(crate) language_id: Lang,
|
pub(crate) language_id: String,
|
||||||
pub scope: String, // source.rust
|
pub scope: String, // source.rust
|
||||||
pub file_types: Vec<String>, // filename ends_with? <Gemfile, rb, etc>
|
pub file_types: Vec<String>, // filename ends_with? <Gemfile, rb, etc>
|
||||||
pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
|
pub roots: Vec<String>, // these indicate project roots <.git, Cargo.toml>
|
||||||
@ -153,7 +153,7 @@ fn read_query(language: &str, filename: &str) -> String {
|
|||||||
|
|
||||||
impl LanguageConfiguration {
|
impl LanguageConfiguration {
|
||||||
fn initialize_highlight(&self, scopes: &[String]) -> Option<Arc<HighlightConfiguration>> {
|
fn initialize_highlight(&self, scopes: &[String]) -> Option<Arc<HighlightConfiguration>> {
|
||||||
let language = get_language_name(self.language_id).to_ascii_lowercase();
|
let language = self.language_id.to_ascii_lowercase();
|
||||||
|
|
||||||
let highlights_query = read_query(&language, "highlights.scm");
|
let highlights_query = read_query(&language, "highlights.scm");
|
||||||
// always highlight syntax errors
|
// always highlight syntax errors
|
||||||
@ -161,17 +161,17 @@ fn initialize_highlight(&self, scopes: &[String]) -> Option<Arc<HighlightConfigu
|
|||||||
|
|
||||||
let injections_query = read_query(&language, "injections.scm");
|
let injections_query = read_query(&language, "injections.scm");
|
||||||
|
|
||||||
let locals_query = "";
|
let locals_query = read_query(&language, "locals.scm");
|
||||||
|
|
||||||
if highlights_query.is_empty() {
|
if highlights_query.is_empty() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let language = get_language(self.language_id);
|
let language = get_language(&crate::RUNTIME_DIR, &self.language_id).ok()?;
|
||||||
let config = HighlightConfiguration::new(
|
let config = HighlightConfiguration::new(
|
||||||
language,
|
language,
|
||||||
&highlights_query,
|
&highlights_query,
|
||||||
&injections_query,
|
&injections_query,
|
||||||
locals_query,
|
&locals_query,
|
||||||
)
|
)
|
||||||
.unwrap(); // TODO: no unwrap
|
.unwrap(); // TODO: no unwrap
|
||||||
config.configure(scopes);
|
config.configure(scopes);
|
||||||
@ -198,7 +198,7 @@ pub fn is_highlight_initialized(&self) -> bool {
|
|||||||
pub fn indent_query(&self) -> Option<&IndentQuery> {
|
pub fn indent_query(&self) -> Option<&IndentQuery> {
|
||||||
self.indent_query
|
self.indent_query
|
||||||
.get_or_init(|| {
|
.get_or_init(|| {
|
||||||
let language = get_language_name(self.language_id).to_ascii_lowercase();
|
let language = self.language_id.to_ascii_lowercase();
|
||||||
|
|
||||||
let toml = load_runtime_file(&language, "indents.toml").ok()?;
|
let toml = load_runtime_file(&language, "indents.toml").ok()?;
|
||||||
toml::from_slice(toml.as_bytes()).ok()
|
toml::from_slice(toml.as_bytes()).ok()
|
||||||
@ -1812,7 +1812,7 @@ fn test_parser() {
|
|||||||
.map(String::from)
|
.map(String::from)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let language = get_language(Lang::Rust);
|
let language = get_language(&crate::RUNTIME_DIR, "Rust").unwrap();
|
||||||
let config = HighlightConfiguration::new(
|
let config = HighlightConfiguration::new(
|
||||||
language,
|
language,
|
||||||
&std::fs::read_to_string(
|
&std::fs::read_to_string(
|
||||||
|
@ -23,5 +23,5 @@ lsp-types = { version = "0.89", features = ["proposed"] }
|
|||||||
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.7", features = ["full"] }
|
tokio = { version = "1.8", features = ["full"] }
|
||||||
tokio-stream = "0.1.6"
|
tokio-stream = "0.1.7"
|
||||||
|
@ -12,8 +12,10 @@ include = ["src/**/*", "languages/**/*", "build.rs", "!**/docs/**/*", "!**/test/
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
tree-sitter = "0.19"
|
tree-sitter = "0.19"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
libloading = "0.7"
|
||||||
|
anyhow = "1"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = { version = "1", features = ["parallel"] }
|
cc = { version = "1" }
|
||||||
threadpool = { version = "1.0" }
|
threadpool = { version = "1.0" }
|
||||||
|
anyhow = "1"
|
||||||
|
@ -1,79 +1,147 @@
|
|||||||
|
use anyhow::{anyhow, Context, Result};
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::PathBuf;
|
use std::time::SystemTime;
|
||||||
|
use std::{
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
process::Command,
|
||||||
|
};
|
||||||
|
|
||||||
use std::sync::mpsc::channel;
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
fn collect_tree_sitter_dirs(ignore: &[String]) -> Vec<String> {
|
fn collect_tree_sitter_dirs(ignore: &[String]) -> Result<Vec<String>> {
|
||||||
let mut dirs = Vec::new();
|
let mut dirs = Vec::new();
|
||||||
for entry in fs::read_dir("languages").unwrap().flatten() {
|
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("languages");
|
||||||
let path = entry.path();
|
|
||||||
let dir = path.file_name().unwrap().to_str().unwrap().to_string();
|
|
||||||
if !ignore.contains(&dir) {
|
|
||||||
dirs.push(dir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dirs
|
|
||||||
}
|
|
||||||
|
|
||||||
fn collect_src_files(dir: &str) -> (Vec<String>, Vec<String>) {
|
for entry in fs::read_dir(path)? {
|
||||||
eprintln!("Collect files for {}", dir);
|
let entry = entry?;
|
||||||
|
|
||||||
let mut c_files = Vec::new();
|
|
||||||
let mut cpp_files = Vec::new();
|
|
||||||
let path = PathBuf::from("languages").join(&dir).join("src");
|
|
||||||
for entry in fs::read_dir(path).unwrap().flatten() {
|
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path
|
|
||||||
.file_stem()
|
if !entry.file_type()?.is_dir() {
|
||||||
.unwrap()
|
|
||||||
.to_str()
|
|
||||||
.unwrap()
|
|
||||||
.starts_with("binding")
|
|
||||||
{
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if let Some(ext) = path.extension() {
|
|
||||||
if ext == "c" {
|
let dir = path.file_name().unwrap().to_str().unwrap().to_string();
|
||||||
c_files.push(path.to_str().unwrap().to_string());
|
|
||||||
} else if ext == "cc" || ext == "cpp" || ext == "cxx" {
|
// filter ignores
|
||||||
cpp_files.push(path.to_str().unwrap().to_string());
|
if ignore.contains(&dir) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
dirs.push(dir)
|
||||||
}
|
|
||||||
(c_files, cpp_files)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_c(files: Vec<String>, language: &str) {
|
Ok(dirs)
|
||||||
let mut build = cc::Build::new();
|
|
||||||
for file in files {
|
|
||||||
build
|
|
||||||
.file(&file)
|
|
||||||
.include(PathBuf::from(file).parent().unwrap())
|
|
||||||
.pic(true)
|
|
||||||
.warnings(false);
|
|
||||||
}
|
|
||||||
build.compile(&format!("tree-sitter-{}-c", language));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_cpp(files: Vec<String>, language: &str) {
|
#[cfg(unix)]
|
||||||
let mut build = cc::Build::new();
|
const DYLIB_EXTENSION: &str = "so";
|
||||||
|
|
||||||
let flag = if build.get_compiler().is_like_msvc() {
|
#[cfg(windows)]
|
||||||
"/std:c++17"
|
const DYLIB_EXTENSION: &str = "dll";
|
||||||
|
|
||||||
|
fn build_library(src_path: &Path, language: &str) -> Result<()> {
|
||||||
|
let header_path = src_path;
|
||||||
|
// let grammar_path = src_path.join("grammar.json");
|
||||||
|
let parser_path = src_path.join("parser.c");
|
||||||
|
let mut scanner_path = src_path.join("scanner.c");
|
||||||
|
|
||||||
|
let scanner_path = if scanner_path.exists() {
|
||||||
|
Some(scanner_path)
|
||||||
} else {
|
} else {
|
||||||
"-std=c++14"
|
scanner_path.set_extension("cc");
|
||||||
};
|
if scanner_path.exists() {
|
||||||
|
Some(scanner_path)
|
||||||
for file in files {
|
} else {
|
||||||
build
|
None
|
||||||
.file(&file)
|
|
||||||
.include(PathBuf::from(file).parent().unwrap())
|
|
||||||
.pic(true)
|
|
||||||
.warnings(false)
|
|
||||||
.cpp(true)
|
|
||||||
.flag_if_supported(flag);
|
|
||||||
}
|
}
|
||||||
build.compile(&format!("tree-sitter-{}-cpp", language));
|
};
|
||||||
|
let parser_lib_path = PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("../runtime/grammars");
|
||||||
|
let mut library_path = parser_lib_path.join(language);
|
||||||
|
library_path.set_extension(DYLIB_EXTENSION);
|
||||||
|
|
||||||
|
let recompile = needs_recompile(&library_path, &parser_path, &scanner_path)
|
||||||
|
.with_context(|| "Failed to compare source and binary timestamps")?;
|
||||||
|
|
||||||
|
if !recompile {
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
let mut config = cc::Build::new();
|
||||||
|
config.cpp(true).opt_level(2).cargo_metadata(false);
|
||||||
|
let compiler = config.get_compiler();
|
||||||
|
let mut command = Command::new(compiler.path());
|
||||||
|
command.current_dir(src_path);
|
||||||
|
for (key, value) in compiler.env() {
|
||||||
|
command.env(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if cfg!(windows) {
|
||||||
|
command
|
||||||
|
.args(&["/nologo", "/LD", "/I"])
|
||||||
|
.arg(header_path)
|
||||||
|
.arg("/Od");
|
||||||
|
if let Some(scanner_path) = scanner_path.as_ref() {
|
||||||
|
command.arg(scanner_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
command
|
||||||
|
.arg(parser_path)
|
||||||
|
.arg("/link")
|
||||||
|
.arg(format!("/out:{}", library_path.to_str().unwrap()));
|
||||||
|
} else {
|
||||||
|
command
|
||||||
|
.arg("-shared")
|
||||||
|
.arg("-fPIC")
|
||||||
|
.arg("-fno-exceptions")
|
||||||
|
.arg("-g")
|
||||||
|
.arg("-I")
|
||||||
|
.arg(header_path)
|
||||||
|
.arg("-o")
|
||||||
|
.arg(&library_path)
|
||||||
|
.arg("-O2");
|
||||||
|
if let Some(scanner_path) = scanner_path.as_ref() {
|
||||||
|
if scanner_path.extension() == Some("c".as_ref()) {
|
||||||
|
command.arg("-xc").arg("-std=c99").arg(scanner_path);
|
||||||
|
} else {
|
||||||
|
command.arg(scanner_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
command.arg("-xc").arg(parser_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = command
|
||||||
|
.output()
|
||||||
|
.with_context(|| "Failed to execute C compiler")?;
|
||||||
|
if !output.status.success() {
|
||||||
|
return Err(anyhow!(
|
||||||
|
"Parser compilation failed.\nStdout: {}\nStderr: {}",
|
||||||
|
String::from_utf8_lossy(&output.stdout),
|
||||||
|
String::from_utf8_lossy(&output.stderr)
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
fn needs_recompile(
|
||||||
|
lib_path: &Path,
|
||||||
|
parser_c_path: &Path,
|
||||||
|
scanner_path: &Option<PathBuf>,
|
||||||
|
) -> Result<bool> {
|
||||||
|
if !lib_path.exists() {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
let lib_mtime = mtime(lib_path)?;
|
||||||
|
if mtime(parser_c_path)? > lib_mtime {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
if let Some(scanner_path) = scanner_path {
|
||||||
|
if mtime(scanner_path)? > lib_mtime {
|
||||||
|
return Ok(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mtime(path: &Path) -> Result<SystemTime> {
|
||||||
|
Ok(fs::metadata(path)?.modified()?)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_dir(dir: &str, language: &str) {
|
fn build_dir(dir: &str, language: &str) {
|
||||||
@ -92,22 +160,21 @@ fn build_dir(dir: &str, language: &str) {
|
|||||||
eprintln!("You can fix in using 'git submodule init && git submodule update --recursive'.");
|
eprintln!("You can fix in using 'git submodule init && git submodule update --recursive'.");
|
||||||
std::process::exit(1);
|
std::process::exit(1);
|
||||||
}
|
}
|
||||||
let (c, cpp) = collect_src_files(dir);
|
|
||||||
if !c.is_empty() {
|
let path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
|
||||||
build_c(c, language);
|
.join("languages")
|
||||||
}
|
.join(dir)
|
||||||
if !cpp.is_empty() {
|
.join("src");
|
||||||
build_cpp(cpp, language);
|
|
||||||
}
|
build_library(&path, language).unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let ignore = vec![
|
let ignore = vec![
|
||||||
"tree-sitter-typescript".to_string(),
|
"tree-sitter-typescript".to_string(),
|
||||||
"tree-sitter-haskell".to_string(), // aarch64 failures: https://github.com/tree-sitter/tree-sitter-haskell/issues/34
|
"tree-sitter-haskell".to_string(), // aarch64 failures: https://github.com/tree-sitter/tree-sitter-haskell/issues/34
|
||||||
".DS_Store".to_string(),
|
|
||||||
];
|
];
|
||||||
let dirs = collect_tree_sitter_dirs(&ignore);
|
let dirs = collect_tree_sitter_dirs(&ignore).unwrap();
|
||||||
|
|
||||||
let mut n_jobs = 0;
|
let mut n_jobs = 0;
|
||||||
let pool = threadpool::Builder::new().build(); // by going through the builder, it'll use num_cpus
|
let pool = threadpool::Builder::new().build(); // by going through the builder, it'll use num_cpus
|
||||||
@ -118,7 +185,7 @@ fn main() {
|
|||||||
n_jobs += 1;
|
n_jobs += 1;
|
||||||
|
|
||||||
pool.execute(move || {
|
pool.execute(move || {
|
||||||
let language = &dir[12..]; // skip tree-sitter- prefix
|
let language = &dir.strip_prefix("tree-sitter-").unwrap();
|
||||||
build_dir(&dir, language);
|
build_dir(&dir, language);
|
||||||
|
|
||||||
// report progress
|
// report progress
|
||||||
|
@ -1,94 +1,39 @@
|
|||||||
use serde::{Deserialize, Serialize};
|
use anyhow::{Context, Result};
|
||||||
|
use libloading::{Library, Symbol};
|
||||||
use tree_sitter::Language;
|
use tree_sitter::Language;
|
||||||
|
|
||||||
#[macro_export]
|
fn replace_dashes_with_underscores(name: &str) -> String {
|
||||||
macro_rules! mk_extern {
|
let mut result = String::with_capacity(name.len());
|
||||||
( $( $name:ident ),* ) => {
|
for c in name.chars() {
|
||||||
$(
|
if c == '-' {
|
||||||
extern "C" { pub fn $name() -> Language; }
|
result.push('_');
|
||||||
)*
|
} else {
|
||||||
};
|
result.push(c);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
#[cfg(unix)]
|
||||||
|
const DYLIB_EXTENSION: &str = "so";
|
||||||
|
|
||||||
#[macro_export]
|
#[cfg(windows)]
|
||||||
macro_rules! mk_enum {
|
const DYLIB_EXTENSION: &str = "dll";
|
||||||
( $( $camel:ident ),* ) => {
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "lowercase")]
|
|
||||||
pub enum Lang {
|
|
||||||
$(
|
|
||||||
$camel,
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
pub fn get_language(runtime_path: &std::path::Path, name: &str) -> Result<Language> {
|
||||||
macro_rules! mk_get_language {
|
let name = name.to_ascii_lowercase();
|
||||||
( $( ($camel:ident, $name:ident) ),* ) => {
|
let mut library_path = runtime_path.join("grammars").join(&name);
|
||||||
#[must_use]
|
// TODO: duplicated under build
|
||||||
pub fn get_language(lang: Lang) -> Language {
|
library_path.set_extension(DYLIB_EXTENSION);
|
||||||
unsafe {
|
|
||||||
match lang {
|
|
||||||
$(
|
|
||||||
Lang::$camel => $name(),
|
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[macro_export]
|
let library = unsafe { Library::new(&library_path) }
|
||||||
macro_rules! mk_get_language_name {
|
.with_context(|| format!("Error opening dynamic library {:?}", &library_path))?;
|
||||||
( $( $camel:ident ),* ) => {
|
let language_fn_name = format!("tree_sitter_{}", replace_dashes_with_underscores(&name));
|
||||||
#[must_use]
|
let language = unsafe {
|
||||||
pub const fn get_language_name(lang: Lang) -> &'static str {
|
let language_fn: Symbol<unsafe extern "C" fn() -> Language> = library
|
||||||
match lang {
|
.get(language_fn_name.as_bytes())
|
||||||
$(
|
.with_context(|| format!("Failed to load symbol {}", language_fn_name))?;
|
||||||
Lang::$camel => stringify!($camel),
|
language_fn()
|
||||||
)*
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
std::mem::forget(library);
|
||||||
|
Ok(language)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[macro_export]
|
|
||||||
macro_rules! mk_langs {
|
|
||||||
( $( ($camel:ident, $name:ident) ),* ) => {
|
|
||||||
mk_extern!($( $name ),*);
|
|
||||||
mk_enum!($( $camel ),*);
|
|
||||||
mk_get_language!($( ($camel, $name) ),*);
|
|
||||||
mk_get_language_name!($( $camel ),*);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
mk_langs!(
|
|
||||||
// 1) Name for enum
|
|
||||||
// 2) tree-sitter function to call to get a Language
|
|
||||||
(Agda, tree_sitter_agda),
|
|
||||||
(Bash, tree_sitter_bash),
|
|
||||||
(Cpp, tree_sitter_cpp),
|
|
||||||
(CSharp, tree_sitter_c_sharp),
|
|
||||||
(Css, tree_sitter_css),
|
|
||||||
(C, tree_sitter_c),
|
|
||||||
(Elixir, tree_sitter_elixir),
|
|
||||||
(Go, tree_sitter_go),
|
|
||||||
// (Haskell, tree_sitter_haskell),
|
|
||||||
(Html, tree_sitter_html),
|
|
||||||
(Javascript, tree_sitter_javascript),
|
|
||||||
(Java, tree_sitter_java),
|
|
||||||
(Json, tree_sitter_json),
|
|
||||||
(Julia, tree_sitter_julia),
|
|
||||||
(Latex, tree_sitter_latex),
|
|
||||||
(Nix, tree_sitter_nix),
|
|
||||||
(Php, tree_sitter_php),
|
|
||||||
(Python, tree_sitter_python),
|
|
||||||
(Ruby, tree_sitter_ruby),
|
|
||||||
(Rust, tree_sitter_rust),
|
|
||||||
(Scala, tree_sitter_scala),
|
|
||||||
(Swift, tree_sitter_swift),
|
|
||||||
(Toml, tree_sitter_toml),
|
|
||||||
(Tsx, tree_sitter_tsx),
|
|
||||||
(Typescript, tree_sitter_typescript)
|
|
||||||
);
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
use std::{
|
use std::{
|
||||||
io::{stdout, Write},
|
io::{stdout, Write},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
use anyhow::Error;
|
use anyhow::Error;
|
||||||
@ -82,15 +83,18 @@ pub fn new(args: Args, mut config: Config) -> Result<Self, Error> {
|
|||||||
editor.new_file(Action::VerticalSplit);
|
editor.new_file(Action::VerticalSplit);
|
||||||
compositor.push(Box::new(ui::file_picker(first.clone())));
|
compositor.push(Box::new(ui::file_picker(first.clone())));
|
||||||
} else {
|
} else {
|
||||||
|
let nr_of_files = args.files.len();
|
||||||
|
editor.open(first.to_path_buf(), Action::VerticalSplit)?;
|
||||||
for file in args.files {
|
for file in args.files {
|
||||||
if file.is_dir() {
|
if file.is_dir() {
|
||||||
return Err(anyhow::anyhow!(
|
return Err(anyhow::anyhow!(
|
||||||
"expected a path to file, found a directory. (to open a directory pass it as first argument)"
|
"expected a path to file, found a directory. (to open a directory pass it as first argument)"
|
||||||
));
|
));
|
||||||
} else {
|
} else {
|
||||||
editor.open(file, Action::VerticalSplit)?;
|
editor.open(file.to_path_buf(), Action::Load)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
editor.set_status(format!("Loaded {} files.", nr_of_files));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
editor.new_file(Action::VerticalSplit);
|
editor.new_file(Action::VerticalSplit);
|
||||||
@ -130,6 +134,8 @@ fn render(&mut self) {
|
|||||||
|
|
||||||
pub async fn event_loop(&mut self) {
|
pub async fn event_loop(&mut self) {
|
||||||
let mut reader = EventStream::new();
|
let mut reader = EventStream::new();
|
||||||
|
let mut last_render = Instant::now();
|
||||||
|
let deadline = Duration::from_secs(1) / 60;
|
||||||
|
|
||||||
self.render();
|
self.render();
|
||||||
|
|
||||||
@ -139,26 +145,22 @@ pub async fn event_loop(&mut self) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
use futures_util::{FutureExt, StreamExt};
|
use futures_util::StreamExt;
|
||||||
|
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
|
biased;
|
||||||
|
|
||||||
event = reader.next() => {
|
event = reader.next() => {
|
||||||
self.handle_terminal_events(event)
|
self.handle_terminal_events(event)
|
||||||
}
|
}
|
||||||
Some((id, call)) = self.editor.language_servers.incoming.next() => {
|
Some((id, call)) = self.editor.language_servers.incoming.next() => {
|
||||||
self.handle_language_server_message(call, id).await;
|
self.handle_language_server_message(call, id).await;
|
||||||
|
// limit render calls for fast language server messages
|
||||||
// eagerly process any other available notifications/calls
|
let last = self.editor.language_servers.incoming.is_empty();
|
||||||
let now = std::time::Instant::now();
|
if last || last_render.elapsed() > deadline {
|
||||||
let deadline = std::time::Duration::from_millis(10);
|
|
||||||
while let Some(Some((id, call))) = self.editor.language_servers.incoming.next().now_or_never() {
|
|
||||||
self.handle_language_server_message(call, id).await;
|
|
||||||
|
|
||||||
if now.elapsed() > deadline { // use a deadline so we don't block too long
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.render();
|
self.render();
|
||||||
|
last_render = Instant::now();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Some(callback) = self.jobs.futures.next() => {
|
Some(callback) = self.jobs.futures.next() => {
|
||||||
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
|
self.jobs.handle_callback(&mut self.editor, &mut self.compositor, callback);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -82,6 +82,10 @@ fn default() -> Keymaps {
|
|||||||
key!('r') => Command::replace,
|
key!('r') => Command::replace,
|
||||||
key!('R') => Command::replace_with_yanked,
|
key!('R') => Command::replace_with_yanked,
|
||||||
|
|
||||||
|
key!('~') => Command::switch_case,
|
||||||
|
alt!('`') => Command::switch_to_uppercase,
|
||||||
|
key!('`') => Command::switch_to_lowercase,
|
||||||
|
|
||||||
key!(Home) => Command::goto_line_start,
|
key!(Home) => Command::goto_line_start,
|
||||||
key!(End) => Command::goto_line_end,
|
key!(End) => Command::goto_line_end,
|
||||||
|
|
||||||
@ -120,7 +124,6 @@ fn default() -> Keymaps {
|
|||||||
alt!(';') => Command::flip_selections,
|
alt!(';') => Command::flip_selections,
|
||||||
key!('%') => Command::select_all,
|
key!('%') => Command::select_all,
|
||||||
key!('x') => Command::extend_line,
|
key!('x') => Command::extend_line,
|
||||||
key!('x') => Command::extend_line,
|
|
||||||
key!('X') => Command::extend_to_line_bounds,
|
key!('X') => Command::extend_to_line_bounds,
|
||||||
// crop_to_whole_line
|
// crop_to_whole_line
|
||||||
|
|
||||||
|
@ -64,6 +64,7 @@ pub fn render_view(
|
|||||||
surface: &mut Surface,
|
surface: &mut Surface,
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
is_focused: bool,
|
is_focused: bool,
|
||||||
|
loader: &syntax::Loader,
|
||||||
) {
|
) {
|
||||||
let area = Rect::new(
|
let area = Rect::new(
|
||||||
view.area.x + OFFSET,
|
view.area.x + OFFSET,
|
||||||
@ -72,7 +73,7 @@ pub fn render_view(
|
|||||||
view.area.height.saturating_sub(1),
|
view.area.height.saturating_sub(1),
|
||||||
); // - 1 for statusline
|
); // - 1 for statusline
|
||||||
|
|
||||||
self.render_buffer(doc, view, area, surface, theme, is_focused);
|
self.render_buffer(doc, view, area, surface, theme, is_focused, loader);
|
||||||
|
|
||||||
// if we're not at the edge of the screen, draw a right border
|
// if we're not at the edge of the screen, draw a right border
|
||||||
if viewport.right() != view.area.right() {
|
if viewport.right() != view.area.right() {
|
||||||
@ -98,6 +99,7 @@ pub fn render_view(
|
|||||||
self.render_statusline(doc, view, area, surface, theme, is_focused);
|
self.render_statusline(doc, view, area, surface, theme, is_focused);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn render_buffer(
|
pub fn render_buffer(
|
||||||
&self,
|
&self,
|
||||||
doc: &Document,
|
doc: &Document,
|
||||||
@ -106,6 +108,7 @@ pub fn render_buffer(
|
|||||||
surface: &mut Surface,
|
surface: &mut Surface,
|
||||||
theme: &Theme,
|
theme: &Theme,
|
||||||
is_focused: bool,
|
is_focused: bool,
|
||||||
|
loader: &syntax::Loader,
|
||||||
) {
|
) {
|
||||||
let text = doc.text().slice(..);
|
let text = doc.text().slice(..);
|
||||||
|
|
||||||
@ -122,8 +125,26 @@ pub fn render_buffer(
|
|||||||
// TODO: range doesn't actually restrict source, just highlight range
|
// TODO: range doesn't actually restrict source, just highlight range
|
||||||
let highlights: Vec<_> = match doc.syntax() {
|
let highlights: Vec<_> = match doc.syntax() {
|
||||||
Some(syntax) => {
|
Some(syntax) => {
|
||||||
|
let scopes = theme.scopes();
|
||||||
syntax
|
syntax
|
||||||
.highlight_iter(text.slice(..), Some(range), None, |_| None)
|
.highlight_iter(text.slice(..), Some(range), None, |language| {
|
||||||
|
loader
|
||||||
|
.language_config_for_scope(&format!("source.{}", language))
|
||||||
|
.and_then(|language_config| {
|
||||||
|
let config = language_config.highlight_config(scopes)?;
|
||||||
|
let config_ref = config.as_ref();
|
||||||
|
// SAFETY: the referenced `HighlightConfiguration` behind
|
||||||
|
// the `Arc` is guaranteed to remain valid throughout the
|
||||||
|
// duration of the highlight.
|
||||||
|
let config_ref = unsafe {
|
||||||
|
std::mem::transmute::<
|
||||||
|
_,
|
||||||
|
&'static syntax::HighlightConfiguration,
|
||||||
|
>(config_ref)
|
||||||
|
};
|
||||||
|
Some(config_ref)
|
||||||
|
})
|
||||||
|
})
|
||||||
.collect() // TODO: we collect here to avoid holding the lock, fix later
|
.collect() // TODO: we collect here to avoid holding the lock, fix later
|
||||||
}
|
}
|
||||||
None => vec![Ok(HighlightEvent::Source {
|
None => vec![Ok(HighlightEvent::Source {
|
||||||
@ -735,7 +756,16 @@ fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
|||||||
|
|
||||||
for (view, is_focused) in cx.editor.tree.views() {
|
for (view, is_focused) in cx.editor.tree.views() {
|
||||||
let doc = cx.editor.document(view.doc).unwrap();
|
let doc = cx.editor.document(view.doc).unwrap();
|
||||||
self.render_view(doc, view, area, surface, &cx.editor.theme, is_focused);
|
let loader = &cx.editor.syn_loader;
|
||||||
|
self.render_view(
|
||||||
|
doc,
|
||||||
|
view,
|
||||||
|
area,
|
||||||
|
surface,
|
||||||
|
&cx.editor.theme,
|
||||||
|
is_focused,
|
||||||
|
loader,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(info) = std::mem::take(&mut cx.editor.autoinfo) {
|
if let Some(info) = std::mem::take(&mut cx.editor.autoinfo) {
|
||||||
|
@ -18,7 +18,7 @@ default = ["crossterm"]
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
cassowary = "0.3"
|
cassowary = "0.3"
|
||||||
unicode-segmentation = "1.2"
|
unicode-segmentation = "1.8"
|
||||||
crossterm = { version = "0.20", optional = true }
|
crossterm = { version = "0.20", optional = true }
|
||||||
serde = { version = "1", "optional" = true, features = ["derive"]}
|
serde = { version = "1", "optional" = true, features = ["derive"]}
|
||||||
helix-view = { version = "0.3", path = "../helix-view", features = ["term"] }
|
helix-view = { version = "0.3", path = "../helix-view", features = ["term"] }
|
||||||
|
@ -456,14 +456,16 @@ pub fn open(
|
|||||||
theme: Option<&Theme>,
|
theme: Option<&Theme>,
|
||||||
config_loader: Option<&syntax::Loader>,
|
config_loader: Option<&syntax::Loader>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
if !path.exists() {
|
let (mut rope, encoding) = if path.exists() {
|
||||||
return Ok(Self::default());
|
let mut file =
|
||||||
}
|
std::fs::File::open(&path).context(format!("unable to open {:?}", path))?;
|
||||||
|
from_reader(&mut file, encoding)?
|
||||||
|
} else {
|
||||||
|
let encoding = encoding.unwrap_or(encoding_rs::UTF_8);
|
||||||
|
(Rope::from(DEFAULT_LINE_ENDING.as_str()), encoding)
|
||||||
|
};
|
||||||
|
|
||||||
let mut file = std::fs::File::open(&path).context(format!("unable to open {:?}", path))?;
|
|
||||||
let (mut rope, encoding) = from_reader(&mut file, encoding)?;
|
|
||||||
let line_ending = with_line_ending(&mut rope);
|
let line_ending = with_line_ending(&mut rope);
|
||||||
|
|
||||||
let mut doc = Self::from(rope, Some(encoding));
|
let mut doc = Self::from(rope, Some(encoding));
|
||||||
|
|
||||||
// set the path and try detecting the language
|
// set the path and try detecting the language
|
||||||
|
@ -39,6 +39,7 @@ pub struct Editor {
|
|||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
pub enum Action {
|
pub enum Action {
|
||||||
|
Load,
|
||||||
Replace,
|
Replace,
|
||||||
HorizontalSplit,
|
HorizontalSplit,
|
||||||
VerticalSplit,
|
VerticalSplit,
|
||||||
@ -97,16 +98,14 @@ pub fn set_theme(&mut self, theme: Theme) {
|
|||||||
self._refresh();
|
self._refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_theme_from_name(&mut self, theme: &str) {
|
pub fn set_theme_from_name(&mut self, theme: &str) -> anyhow::Result<()> {
|
||||||
let theme = match self.theme_loader.load(theme.as_ref()) {
|
use anyhow::Context;
|
||||||
Ok(theme) => theme,
|
let theme = self
|
||||||
Err(e) => {
|
.theme_loader
|
||||||
log::warn!("failed setting theme `{}` - {}", theme, e);
|
.load(theme.as_ref())
|
||||||
return;
|
.with_context(|| format!("failed setting theme `{}`", theme))?;
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
self.set_theme(theme);
|
self.set_theme(theme);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn _refresh(&mut self) {
|
fn _refresh(&mut self) {
|
||||||
@ -153,6 +152,9 @@ pub fn switch(&mut self, id: DocumentId, action: Action) {
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
Action::Load => {
|
||||||
|
return;
|
||||||
|
}
|
||||||
Action::HorizontalSplit => {
|
Action::HorizontalSplit => {
|
||||||
let view = View::new(id);
|
let view = View::new(id);
|
||||||
let view_id = self.tree.split(view, Layout::Horizontal);
|
let view_id = self.tree.split(view, Layout::Horizontal);
|
||||||
|
0
runtime/grammars/.gitkeep
Normal file
0
runtime/grammars/.gitkeep
Normal file
@ -54,6 +54,8 @@
|
|||||||
"." @punctuation.delimiter
|
"." @punctuation.delimiter
|
||||||
";" @punctuation.delimiter
|
";" @punctuation.delimiter
|
||||||
|
|
||||||
|
(enumerator) @type.enum.variant
|
||||||
|
|
||||||
(string_literal) @string
|
(string_literal) @string
|
||||||
(system_lib_string) @string
|
(system_lib_string) @string
|
||||||
|
|
||||||
|
@ -1,175 +1,256 @@
|
|||||||
; Identifier conventions
|
; -------
|
||||||
|
; Tree-Sitter doesn't allow overrides in regards to captures,
|
||||||
|
; though it is possible to affect the child node of a captured
|
||||||
|
; node. Thus, the approach here is to flip the order so that
|
||||||
|
; overrides are unnecessary.
|
||||||
|
; -------
|
||||||
|
|
||||||
|
|
||||||
; Assume all-caps names are constants
|
|
||||||
((identifier) @constant
|
|
||||||
(#match? @constant "^[A-Z][A-Z\\d_]+$'"))
|
|
||||||
|
|
||||||
; Assume other uppercase names are enum constructors
|
; -------
|
||||||
((identifier) @constructor
|
; Types
|
||||||
(#match? @constructor "^[A-Z]"))
|
; -------
|
||||||
|
|
||||||
; Assume that uppercase names in paths are types
|
; ---
|
||||||
(mod_item
|
; Primitives
|
||||||
name: (identifier) @namespace)
|
; ---
|
||||||
(scoped_identifier
|
|
||||||
path: (identifier) @namespace)
|
|
||||||
(scoped_identifier
|
|
||||||
(scoped_identifier
|
|
||||||
name: (identifier) @namespace))
|
|
||||||
(scoped_type_identifier
|
|
||||||
path: (identifier) @namespace)
|
|
||||||
(scoped_type_identifier
|
|
||||||
(scoped_identifier
|
|
||||||
name: (identifier) @namespace))
|
|
||||||
|
|
||||||
((scoped_identifier
|
(escape_sequence) @escape
|
||||||
path: (identifier) @type)
|
|
||||||
(#match? @type "^[A-Z]"))
|
|
||||||
((scoped_identifier
|
|
||||||
path: (scoped_identifier
|
|
||||||
name: (identifier) @type))
|
|
||||||
(#match? @type "^[A-Z]"))
|
|
||||||
|
|
||||||
; Namespaces
|
|
||||||
|
|
||||||
(crate) @namespace
|
|
||||||
(extern_crate_declaration
|
|
||||||
(crate)
|
|
||||||
name: (identifier) @namespace)
|
|
||||||
(scoped_use_list
|
|
||||||
path: (identifier) @namespace)
|
|
||||||
(scoped_use_list
|
|
||||||
path: (scoped_identifier
|
|
||||||
(identifier) @namespace))
|
|
||||||
(use_list (scoped_identifier (identifier) @namespace . (_)))
|
|
||||||
|
|
||||||
; Function calls
|
|
||||||
|
|
||||||
(call_expression
|
|
||||||
function: (identifier) @function)
|
|
||||||
(call_expression
|
|
||||||
function: (field_expression
|
|
||||||
field: (field_identifier) @function.method))
|
|
||||||
(call_expression
|
|
||||||
function: (scoped_identifier
|
|
||||||
"::"
|
|
||||||
name: (identifier) @function))
|
|
||||||
|
|
||||||
(generic_function
|
|
||||||
function: (identifier) @function)
|
|
||||||
(generic_function
|
|
||||||
function: (scoped_identifier
|
|
||||||
name: (identifier) @function))
|
|
||||||
(generic_function
|
|
||||||
function: (field_expression
|
|
||||||
field: (field_identifier) @function.method))
|
|
||||||
|
|
||||||
(macro_invocation
|
|
||||||
macro: (identifier) @function.macro
|
|
||||||
"!" @function.macro)
|
|
||||||
(macro_invocation
|
|
||||||
macro: (scoped_identifier
|
|
||||||
(identifier) @function.macro .))
|
|
||||||
|
|
||||||
; (metavariable) @variable
|
|
||||||
(metavariable) @function.macro
|
|
||||||
|
|
||||||
"$" @function.macro
|
|
||||||
|
|
||||||
; Function definitions
|
|
||||||
|
|
||||||
(function_item (identifier) @function)
|
|
||||||
(function_signature_item (identifier) @function)
|
|
||||||
|
|
||||||
; Other identifiers
|
|
||||||
|
|
||||||
(type_identifier) @type
|
|
||||||
(primitive_type) @type.builtin
|
(primitive_type) @type.builtin
|
||||||
(field_identifier) @property
|
(boolean_literal) @constant.builtin
|
||||||
|
[
|
||||||
(line_comment) @comment
|
(integer_literal)
|
||||||
(block_comment) @comment
|
(float_literal)
|
||||||
|
] @number
|
||||||
"(" @punctuation.bracket
|
|
||||||
")" @punctuation.bracket
|
|
||||||
"[" @punctuation.bracket
|
|
||||||
"]" @punctuation.bracket
|
|
||||||
|
|
||||||
(type_arguments
|
|
||||||
"<" @punctuation.bracket
|
|
||||||
">" @punctuation.bracket)
|
|
||||||
(type_parameters
|
|
||||||
"<" @punctuation.bracket
|
|
||||||
">" @punctuation.bracket)
|
|
||||||
|
|
||||||
"::" @punctuation.delimiter
|
|
||||||
"." @punctuation.delimiter
|
|
||||||
";" @punctuation.delimiter
|
|
||||||
|
|
||||||
(parameter (identifier) @variable.parameter)
|
|
||||||
(closure_parameters (_) @variable.parameter)
|
|
||||||
|
|
||||||
(lifetime (identifier) @label)
|
|
||||||
|
|
||||||
"async" @keyword
|
|
||||||
"break" @keyword
|
|
||||||
"const" @keyword
|
|
||||||
"continue" @keyword
|
|
||||||
(crate) @keyword
|
|
||||||
"default" @keyword
|
|
||||||
"dyn" @keyword
|
|
||||||
"else" @keyword
|
|
||||||
"enum" @keyword
|
|
||||||
"extern" @keyword
|
|
||||||
"fn" @keyword
|
|
||||||
"for" @keyword
|
|
||||||
"if" @keyword
|
|
||||||
"impl" @keyword
|
|
||||||
"in" @keyword
|
|
||||||
"let" @keyword
|
|
||||||
"let" @keyword
|
|
||||||
"loop" @keyword
|
|
||||||
"macro_rules!" @keyword
|
|
||||||
"match" @keyword
|
|
||||||
"mod" @keyword
|
|
||||||
"move" @keyword
|
|
||||||
"pub" @keyword
|
|
||||||
"ref" @keyword
|
|
||||||
"return" @keyword
|
|
||||||
"static" @keyword
|
|
||||||
"struct" @keyword
|
|
||||||
"trait" @keyword
|
|
||||||
"type" @keyword
|
|
||||||
"union" @keyword
|
|
||||||
"unsafe" @keyword
|
|
||||||
"use" @keyword
|
|
||||||
"where" @keyword
|
|
||||||
"while" @keyword
|
|
||||||
(mutable_specifier) @keyword.mut
|
|
||||||
(use_list (self) @keyword)
|
|
||||||
(scoped_use_list (self) @keyword)
|
|
||||||
(scoped_identifier (self) @keyword)
|
|
||||||
(super) @keyword
|
|
||||||
"as" @keyword
|
|
||||||
|
|
||||||
(self) @variable.builtin
|
|
||||||
|
|
||||||
[
|
[
|
||||||
(char_literal)
|
(char_literal)
|
||||||
(string_literal)
|
(string_literal)
|
||||||
(raw_string_literal)
|
(raw_string_literal)
|
||||||
] @string
|
] @string
|
||||||
|
[
|
||||||
|
(line_comment)
|
||||||
|
(block_comment)
|
||||||
|
] @comment
|
||||||
|
|
||||||
(boolean_literal) @constant.builtin
|
; ---
|
||||||
(integer_literal) @number
|
; Extraneous
|
||||||
(float_literal) @number
|
; ---
|
||||||
|
|
||||||
(escape_sequence) @escape
|
(self) @variable.builtin
|
||||||
|
(enum_variant (identifier) @type.enum.variant)
|
||||||
|
|
||||||
|
(field_initializer
|
||||||
|
(field_identifier) @property)
|
||||||
|
(shorthand_field_initializer) @variable
|
||||||
|
(shorthand_field_identifier) @variable
|
||||||
|
|
||||||
|
(lifetime
|
||||||
|
"'" @label
|
||||||
|
(identifier) @label)
|
||||||
|
(loop_label
|
||||||
|
(identifier) @type)
|
||||||
|
|
||||||
|
; ---
|
||||||
|
; Punctuation
|
||||||
|
; ---
|
||||||
|
|
||||||
|
[
|
||||||
|
"::"
|
||||||
|
"."
|
||||||
|
";"
|
||||||
|
] @punctuation.delimiter
|
||||||
|
|
||||||
|
[
|
||||||
|
"("
|
||||||
|
")"
|
||||||
|
"["
|
||||||
|
"]"
|
||||||
|
] @punctuation.bracket
|
||||||
|
(type_arguments
|
||||||
|
[
|
||||||
|
"<"
|
||||||
|
">"
|
||||||
|
] @punctuation.bracket)
|
||||||
|
(type_parameters
|
||||||
|
[
|
||||||
|
"<"
|
||||||
|
">"
|
||||||
|
] @punctuation.bracket)
|
||||||
|
|
||||||
|
; ---
|
||||||
|
; Parameters
|
||||||
|
; ---
|
||||||
|
|
||||||
|
(parameter
|
||||||
|
pattern: (identifier) @variable.parameter)
|
||||||
|
(closure_parameters
|
||||||
|
(identifier) @variable.parameter)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; -------
|
||||||
|
; Keywords
|
||||||
|
; -------
|
||||||
|
|
||||||
|
(for_expression
|
||||||
|
"for" @keyword.control)
|
||||||
|
((identifier) @keyword.control
|
||||||
|
(#match? @keyword.control "^yield$"))
|
||||||
|
[
|
||||||
|
"while"
|
||||||
|
"loop"
|
||||||
|
"in"
|
||||||
|
"break"
|
||||||
|
"continue"
|
||||||
|
|
||||||
|
"match"
|
||||||
|
"if"
|
||||||
|
"else"
|
||||||
|
"return"
|
||||||
|
|
||||||
|
"await"
|
||||||
|
] @keyword.control
|
||||||
|
|
||||||
|
[
|
||||||
|
(crate)
|
||||||
|
(super)
|
||||||
|
"as"
|
||||||
|
"use"
|
||||||
|
"pub"
|
||||||
|
"mod"
|
||||||
|
"extern"
|
||||||
|
|
||||||
|
"fn"
|
||||||
|
"struct"
|
||||||
|
"enum"
|
||||||
|
"impl"
|
||||||
|
"where"
|
||||||
|
"trait"
|
||||||
|
"for"
|
||||||
|
|
||||||
|
"type"
|
||||||
|
"union"
|
||||||
|
"unsafe"
|
||||||
|
"default"
|
||||||
|
"macro_rules!"
|
||||||
|
|
||||||
|
"let"
|
||||||
|
"ref"
|
||||||
|
"move"
|
||||||
|
|
||||||
|
"dyn"
|
||||||
|
"static"
|
||||||
|
"const"
|
||||||
|
"async"
|
||||||
|
] @keyword
|
||||||
|
|
||||||
|
(mutable_specifier) @keyword.mut
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; -------
|
||||||
|
; Guess Other Types
|
||||||
|
; -------
|
||||||
|
|
||||||
|
((identifier) @constant
|
||||||
|
(#match? @constant "^[A-Z][A-Z\\d_]+$"))
|
||||||
|
|
||||||
|
; ---
|
||||||
|
; PascalCase identifiers in call_expressions (e.g. `Ok()`)
|
||||||
|
; are assumed to be enum constructors.
|
||||||
|
; ---
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: [
|
||||||
|
((identifier) @type.variant
|
||||||
|
(#match? @type.variant "^[A-Z]"))
|
||||||
|
(scoped_identifier
|
||||||
|
name: ((identifier) @type.variant
|
||||||
|
(#match? @type.variant "^[A-Z]")))
|
||||||
|
])
|
||||||
|
|
||||||
|
; ---
|
||||||
|
; Assume that types in match arms are enums and not
|
||||||
|
; tuple structs. Same for `if let` expressions.
|
||||||
|
; ---
|
||||||
|
|
||||||
|
(match_pattern
|
||||||
|
(scoped_identifier
|
||||||
|
name: (identifier) @constructor))
|
||||||
|
(tuple_struct_pattern
|
||||||
|
type: [
|
||||||
|
((identifier) @constructor)
|
||||||
|
(scoped_identifier
|
||||||
|
name: (identifier) @constructor)
|
||||||
|
])
|
||||||
|
(struct_pattern
|
||||||
|
type: [
|
||||||
|
((type_identifier) @constructor)
|
||||||
|
(scoped_type_identifier
|
||||||
|
name: (type_identifier) @constructor)
|
||||||
|
])
|
||||||
|
|
||||||
|
; ---
|
||||||
|
; Other PascalCase identifiers are assumed to be structs.
|
||||||
|
; ---
|
||||||
|
|
||||||
|
((identifier) @type
|
||||||
|
(#match? @type "^[A-Z]"))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; -------
|
||||||
|
; Functions
|
||||||
|
; -------
|
||||||
|
|
||||||
|
(call_expression
|
||||||
|
function: [
|
||||||
|
((identifier) @function)
|
||||||
|
(scoped_identifier
|
||||||
|
name: (identifier) @function)
|
||||||
|
(field_expression
|
||||||
|
field: (field_identifier) @function)
|
||||||
|
])
|
||||||
|
(generic_function
|
||||||
|
function: [
|
||||||
|
((identifier) @function)
|
||||||
|
(scoped_identifier
|
||||||
|
name: (identifier) @function)
|
||||||
|
(field_expression
|
||||||
|
field: (field_identifier) @function.method)
|
||||||
|
])
|
||||||
|
|
||||||
|
(function_item
|
||||||
|
name: (identifier) @function)
|
||||||
|
|
||||||
|
; ---
|
||||||
|
; Macros
|
||||||
|
; ---
|
||||||
|
|
||||||
|
(meta_item
|
||||||
|
(identifier) @attribute)
|
||||||
(attribute_item) @attribute
|
(attribute_item) @attribute
|
||||||
(inner_attribute_item) @attribute
|
(inner_attribute_item) @attribute
|
||||||
|
|
||||||
|
(macro_definition
|
||||||
|
name: (identifier) @function.macro)
|
||||||
|
(macro_invocation
|
||||||
|
macro: [
|
||||||
|
((identifier) @function.macro)
|
||||||
|
(scoped_identifier
|
||||||
|
name: (identifier) @function.macro)
|
||||||
|
]
|
||||||
|
"!" @function.macro)
|
||||||
|
|
||||||
|
(metavariable) @variable.parameter
|
||||||
|
(fragment_specifier) @variable.parameter
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; -------
|
||||||
|
; Operators
|
||||||
|
; -------
|
||||||
|
|
||||||
[
|
[
|
||||||
"*"
|
"*"
|
||||||
"'"
|
"'"
|
||||||
@ -210,4 +291,46 @@
|
|||||||
"'"
|
"'"
|
||||||
] @operator
|
] @operator
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; -------
|
||||||
|
; Paths
|
||||||
|
; -------
|
||||||
|
|
||||||
|
(use_declaration
|
||||||
|
argument: (identifier) @namespace)
|
||||||
|
(use_wildcard
|
||||||
|
(identifier) @namespace)
|
||||||
|
(extern_crate_declaration
|
||||||
|
name: (identifier) @namespace)
|
||||||
|
(mod_item
|
||||||
|
name: (identifier) @namespace)
|
||||||
|
(scoped_use_list
|
||||||
|
path: (identifier)? @namespace)
|
||||||
|
(use_list
|
||||||
|
(identifier) @namespace)
|
||||||
|
(use_as_clause
|
||||||
|
path: (identifier)? @namespace
|
||||||
|
alias: (identifier) @namespace)
|
||||||
|
|
||||||
|
; ---
|
||||||
|
; Remaining Paths
|
||||||
|
; ---
|
||||||
|
|
||||||
|
(scoped_identifier
|
||||||
|
path: (identifier)? @namespace
|
||||||
|
name: (identifier) @namespace)
|
||||||
|
(scoped_type_identifier
|
||||||
|
path: (identifier) @namespace)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; -------
|
||||||
|
; Remaining Identifiers
|
||||||
|
; -------
|
||||||
|
|
||||||
"?" @special
|
"?" @special
|
||||||
|
|
||||||
|
(type_identifier) @type
|
||||||
|
(identifier) @variable
|
||||||
|
(field_identifier) @variable
|
||||||
|
80
runtime/themes/dark_plus.toml
Normal file
80
runtime/themes/dark_plus.toml
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
# Author: Shafkath Shuhan <shafkathshuhannyc@gmail.com>
|
||||||
|
|
||||||
|
"namespace" = { fg = "type" }
|
||||||
|
"module" = { fg = "type" }
|
||||||
|
"type" = { fg = "type" }
|
||||||
|
"type.builtin" = { fg = "type" }
|
||||||
|
|
||||||
|
"keyword" = { fg = "keyword" }
|
||||||
|
"keyword.directive" = { fg = "keyword" }
|
||||||
|
"function.macro" = { fg = "keyword" }
|
||||||
|
"variable.builtin" = { fg = "keyword" }
|
||||||
|
"label" = { fg = "keyword" }
|
||||||
|
"constant.builtin" = { fg = "keyword" }
|
||||||
|
|
||||||
|
"punctuation" = { fg = "text" }
|
||||||
|
"punctuation.delimiter" = { fg = "text" }
|
||||||
|
|
||||||
|
"keyword.control" = { fg = "special" }
|
||||||
|
"special" = { fg = "text" }
|
||||||
|
"operator" = { fg = "text" }
|
||||||
|
|
||||||
|
"variable" = { fg = "variable" }
|
||||||
|
"variable.parameter" = { fg = "variable" }
|
||||||
|
"property" = { fg = "variable" }
|
||||||
|
|
||||||
|
"attribute" = { fg = "fn_declaration" }
|
||||||
|
"function" = { fg = "fn_declaration" }
|
||||||
|
"function.builtin" = { fg = "fn_declaration" }
|
||||||
|
|
||||||
|
"comment" = { fg = "#6A9955" }
|
||||||
|
|
||||||
|
"constant" = { fg = "constant" }
|
||||||
|
"type.enum.variant" = { fg = "constant" }
|
||||||
|
"constructor" = { fg = "constant" }
|
||||||
|
|
||||||
|
"string" = { fg = "#ce9178" }
|
||||||
|
"number" = { fg = "#b5cea8" }
|
||||||
|
"escape" = { fg = "#d7ba7d" }
|
||||||
|
|
||||||
|
"ui.background" = { fg = "#d4d4d4", bg = "#1e1e1e" }
|
||||||
|
|
||||||
|
"ui.help" = { bg = "widget" }
|
||||||
|
"ui.popup" = { bg = "widget" }
|
||||||
|
"ui.window" = { bg = "widget" }
|
||||||
|
"ui.menu.selected" = { bg = "widget" }
|
||||||
|
|
||||||
|
"ui.cursor" = { fg = "cursor", modifiers = ["reversed"] }
|
||||||
|
"ui.cursor.primary" = { fg = "cursor", modifiers = ["reversed"] }
|
||||||
|
"ui.cursor.match" = { fg = "cursor", modifiers = ['underlined'] }
|
||||||
|
|
||||||
|
"ui.selection" = { bg = "#3a3d41" }
|
||||||
|
"ui.selection.primary" = { bg = "#add6ff26" }
|
||||||
|
|
||||||
|
"ui.linenr" = { fg = "#858585" }
|
||||||
|
"ui.linenr.selected" = { fg = "#c6c6c6" }
|
||||||
|
|
||||||
|
"ui.statusline" = { fg = "#ffffff", bg = "#007acc" }
|
||||||
|
"ui.statusline.inactive" = { fg = "#ffffff", bg = "#007acc" }
|
||||||
|
|
||||||
|
"ui.text" = { fg = "text", bg = "background" }
|
||||||
|
"ui.text.focus" = { fg = "#ffffff" }
|
||||||
|
|
||||||
|
"warning" = { fg = "#cca700" }
|
||||||
|
"error" = { fg = "#f48771" }
|
||||||
|
"info" = { fg = "#75beff" }
|
||||||
|
"hint" = { fg = "#eeeeeeb3" }
|
||||||
|
|
||||||
|
[palette]
|
||||||
|
type = "#4EC9B0"
|
||||||
|
keyword = "#569CD6"
|
||||||
|
regex = "#CE9178"
|
||||||
|
special = "#C586C0"
|
||||||
|
variable = "#9CDCFE"
|
||||||
|
fn_declaration = "#DCDCAA"
|
||||||
|
constant = "#4FC1FF"
|
||||||
|
|
||||||
|
background = "#1e1e1e"
|
||||||
|
text = "#d4d4d4"
|
||||||
|
cursor = "#a6a6a6"
|
||||||
|
widget = "#252526"
|
115
theme.toml
115
theme.toml
@ -1,68 +1,81 @@
|
|||||||
"attribute" = "#dbbfef" # lilac
|
attribute = "lilac"
|
||||||
"keyword" = "#eccdba" # almond
|
keyword = "almond"
|
||||||
"keyword.directive" = "#dbbfef" # lilac -- preprocessor comments (#if in C)
|
"keyword.directive" = "lilac" # -- preprocessor comments (#if in C)
|
||||||
"namespace" = "#dbbfef" # lilac
|
namespace = "lilac"
|
||||||
"punctuation" = "#a4a0e8" # lavender
|
punctuation = "lavender"
|
||||||
"punctuation.delimiter" = "#a4a0e8" # lavender
|
"punctuation.delimiter" = "lavender"
|
||||||
"operator" = "#dbbfef" # lilac
|
operator = "lilac"
|
||||||
"special" = "#efba5d" # honey
|
special = "honey"
|
||||||
# "property" = "#a4a0e8" # lavender
|
property = "white"
|
||||||
"property" = "#ffffff" # white
|
variable = "lavender"
|
||||||
"variable" = "#a4a0e8" # lavender
|
# variable = "almond" # TODO: metavariables only
|
||||||
# "variable" = "#eccdba" # almond TODO: metavariables only
|
"variable.parameter" = "lavender"
|
||||||
"variable.parameter" = "#a4a0e8" # lavender
|
"variable.builtin" = "mint"
|
||||||
# TODO distinguish type from type.builtin?
|
type = "white"
|
||||||
"type" = "#ffffff" # white
|
"type.builtin" = "white" # TODO: distinguish?
|
||||||
"type.builtin" = "#ffffff" # white
|
constructor = "lilac"
|
||||||
"constructor" = "#dbbfef" # lilac
|
function = "white"
|
||||||
"function" = "#ffffff" # white
|
"function.macro" = "lilac"
|
||||||
"function.macro" = "#dbbfef" # lilac
|
"function.builtin" = "white"
|
||||||
"function.builtin" = "#ffffff" # white
|
comment = "sirocco"
|
||||||
"comment" = "#697C81" # sirocco
|
constant = "white"
|
||||||
"variable.builtin" = "#9ff28f" # mint
|
"constant.builtin" = "white"
|
||||||
"constant" = "#ffffff" # white
|
string = "silver"
|
||||||
"constant.builtin" = "#ffffff" # white
|
number = "chamois"
|
||||||
"string" = "#cccccc" # silver
|
escape = "honey"
|
||||||
"number" = "#e8dca0" # chamois
|
|
||||||
"escape" = "#efba5d" # honey
|
|
||||||
# used for lifetimes
|
# used for lifetimes
|
||||||
"label" = "#efba5d" # honey
|
label = "honey"
|
||||||
|
|
||||||
# TODO: diferentiate number builtin
|
|
||||||
# TODO: diferentiate doc comment
|
# TODO: diferentiate doc comment
|
||||||
# TODO: variable as lilac
|
|
||||||
# TODO: mod/use statements as white
|
|
||||||
# TODO: mod stuff as chamois
|
|
||||||
#
|
|
||||||
# concat (ERROR) @syntax-error and "MISSING ;" selectors for errors
|
# concat (ERROR) @syntax-error and "MISSING ;" selectors for errors
|
||||||
|
|
||||||
"module" = "#ff0000"
|
module = "#ff0000"
|
||||||
|
|
||||||
"ui.background" = { bg = "#3b224c" } # midnight
|
"ui.background" = { bg = "midnight" }
|
||||||
"ui.linenr" = { fg = "#5a5977" } # comet
|
"ui.linenr" = { fg = "comet" }
|
||||||
"ui.linenr.selected" = { fg = "#dbbfef" } # lilac
|
"ui.linenr.selected" = { fg = "lilac" }
|
||||||
"ui.statusline" = { fg = "#dbbfef", bg = "#281733" } # revolver
|
"ui.statusline" = { fg = "lilac", bg = "revolver" }
|
||||||
"ui.statusline.inactive" = { fg = "#a4a0e8", bg = "#281733" } # revolver
|
"ui.statusline.inactive" = { fg = "lavender", bg = "revolver" }
|
||||||
"ui.popup" = { bg = "#281733" } # revolver
|
"ui.popup" = { bg = "revolver" }
|
||||||
"ui.window" = { fg = "#452859" } # bossa nova
|
"ui.window" = { fg = "bossanova" }
|
||||||
"ui.help" = { bg = "#7958DC", fg = "#171452" }
|
"ui.help" = { bg = "#7958DC", fg = "#171452" }
|
||||||
|
|
||||||
"ui.text" = { fg = "#a4a0e8" } # lavender
|
"ui.text" = { fg = "lavender" }
|
||||||
"ui.text.focus" = { fg = "#dbbfef" } # lilac
|
"ui.text.focus" = { fg = "lilac" }
|
||||||
|
|
||||||
"ui.selection" = { bg = "#540099" }
|
"ui.selection" = { bg = "#540099" }
|
||||||
"ui.selection.primary" = { bg = "#540099" }
|
"ui.selection.primary" = { bg = "#540099" }
|
||||||
# TODO: namespace ui.cursor as ui.selection.cursor?
|
# TODO: namespace ui.cursor as ui.selection.cursor?
|
||||||
"ui.cursor.select" = { bg = "#6F44F0" }
|
"ui.cursor.select" = { bg = "delta" }
|
||||||
"ui.cursor.insert" = { bg = "#ffffff" }
|
"ui.cursor.insert" = { bg = "white" }
|
||||||
"ui.cursor.match" = { fg = "#212121", bg = "#6C6999" }
|
"ui.cursor.match" = { fg = "#212121", bg = "#6C6999" }
|
||||||
"ui.cursor" = { modifiers = ["reversed"] }
|
"ui.cursor" = { modifiers = ["reversed"] }
|
||||||
|
|
||||||
"ui.menu.selected" = { fg = "#281733", bg = "#ffffff" } # revolver
|
"ui.menu.selected" = { fg = "revolver", bg = "white" }
|
||||||
|
|
||||||
"diagnostic" = { modifiers = ["underlined"] }
|
diagnostic = { modifiers = ["underlined"] }
|
||||||
|
|
||||||
"warning" = "#ffcd1c"
|
warning = "lightning"
|
||||||
"error" = "#f47868"
|
error = "apricot"
|
||||||
"info" = "#6F44F0"
|
info = "delta"
|
||||||
"hint" = "#cccccc"
|
hint = "silver"
|
||||||
|
|
||||||
|
[palette]
|
||||||
|
white = "#ffffff"
|
||||||
|
lilac = "#dbbfef"
|
||||||
|
lavender = "#a4a0e8"
|
||||||
|
comet = "#5a5977"
|
||||||
|
bossanova = "#452859"
|
||||||
|
midnight = "#3b224c"
|
||||||
|
revolver = "#281733"
|
||||||
|
|
||||||
|
silver = "#cccccc"
|
||||||
|
sirocco = "#697C81"
|
||||||
|
mint = "#9ff28f"
|
||||||
|
almond = "#eccdba"
|
||||||
|
chamois = "#E8DCA0"
|
||||||
|
honey = "#efba5d"
|
||||||
|
|
||||||
|
apricot = "#f47868"
|
||||||
|
lightning = "#ffcd1c"
|
||||||
|
delta = "#6F44F0"
|
||||||
|
Loading…
Reference in New Issue
Block a user