Merge branch 'helix-editor:master' into command-expansion

pull/11164/head
Théo Daron 5 months ago
commit 0d97406257

71
Cargo.lock generated

@ -136,9 +136,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53"
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.0.100" version = "1.0.106"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c891175c3fb232128f48de6590095e59198bbeb8620c310be349bfc3afd12c7b" checksum = "066fce287b1d4eafef758e89e09d724a24808a9196fe9756b8ca90e86d0719a2"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
@ -171,9 +171,9 @@ dependencies = [
[[package]] [[package]]
name = "clipboard-win" name = "clipboard-win"
version = "5.3.1" version = "5.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79f4473f5144e20d9aceaf2972478f06ddf687831eafeeb434fbaf0acc4144ad" checksum = "15efe7a882b08f34e38556b14f2fb3daa98769d06c7f0c1b076dfd0d983bc892"
dependencies = [ dependencies = [
"error-code", "error-code",
] ]
@ -351,6 +351,15 @@ dependencies = [
"parking_lot_core", "parking_lot_core",
] ]
[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
dependencies = [
"powerfmt",
]
[[package]] [[package]]
name = "dunce" name = "dunce"
version = "1.0.4" version = "1.0.4"
@ -1601,12 +1610,12 @@ dependencies = [
[[package]] [[package]]
name = "imara-diff" name = "imara-diff"
version = "0.1.5" version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e98c1d0ad70fc91b8b9654b1f33db55e59579d3b3de2bffdced0fdb810570cb8" checksum = "af13c8ceb376860ff0c6a66d83a8cdd4ecd9e464da24621bbffcd02b49619434"
dependencies = [ dependencies = [
"ahash", "ahash",
"hashbrown 0.12.3", "hashbrown 0.14.5",
] ]
[[package]] [[package]]
@ -1711,9 +1720,9 @@ dependencies = [
[[package]] [[package]]
name = "log" name = "log"
version = "0.4.21" version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
[[package]] [[package]]
name = "lsp-types" name = "lsp-types"
@ -1795,6 +1804,12 @@ dependencies = [
"unicode-segmentation", "unicode-segmentation",
] ]
[[package]]
name = "num-conv"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
[[package]] [[package]]
name = "num-traits" name = "num-traits"
version = "0.2.15" version = "0.2.15"
@ -1840,9 +1855,9 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
[[package]] [[package]]
name = "open" name = "open"
version = "5.1.4" version = "5.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5ca541f22b1c46d4bb9801014f234758ab4297e7870b904b6a8415b980a7388" checksum = "9d2c909a3fce3bd80efef4cd1c6c056bd9376a8fe06fcfdbebaf32cb485a7e37"
dependencies = [ dependencies = [
"is-wsl", "is-wsl",
"libc", "libc",
@ -1896,6 +1911,12 @@ version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "powerfmt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.76" version = "1.0.76"
@ -2098,18 +2119,18 @@ checksum = "1792db035ce95be60c3f8853017b3999209281c24e2ba5bc8e59bf97a0c590c1"
[[package]] [[package]]
name = "serde" name = "serde"
version = "1.0.203" version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.203" version = "1.0.204"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@ -2118,9 +2139,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.117" version = "1.0.120"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@ -2358,13 +2379,16 @@ dependencies = [
[[package]] [[package]]
name = "time" name = "time"
version = "0.3.23" version = "0.3.36"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59e399c068f43a5d116fedaf73b203fa4f9c519f17e2b34f63221d3792f81446" checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885"
dependencies = [ dependencies = [
"deranged",
"itoa", "itoa",
"libc", "libc",
"num-conv",
"num_threads", "num_threads",
"powerfmt",
"serde", "serde",
"time-core", "time-core",
"time-macros", "time-macros",
@ -2372,16 +2396,17 @@ dependencies = [
[[package]] [[package]]
name = "time-core" name = "time-core"
version = "0.1.1" version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3"
[[package]] [[package]]
name = "time-macros" name = "time-macros"
version = "0.2.10" version = "0.2.18"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "96ba15a897f3c86766b757e5ac7221554c6750054d74d5b28844fce5fb36a6c4" checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf"
dependencies = [ dependencies = [
"num-conv",
"time-core", "time-core",
] ]

@ -47,7 +47,7 @@ Note: Only certain languages have indentation definitions at the moment. Check
[Installation documentation](https://docs.helix-editor.com/install.html). [Installation documentation](https://docs.helix-editor.com/install.html).
[![Packaging status](https://repology.org/badge/vertical-allrepos/helix.svg)](https://repology.org/project/helix/versions) [![Packaging status](https://repology.org/badge/vertical-allrepos/helix.svg?exclude_unsupported=1)](https://repology.org/project/helix/versions)
# Contributing # Contributing

@ -148,6 +148,12 @@ provided `.desktop` and icon files to their correct folders:
cp contrib/Helix.desktop ~/.local/share/applications cp contrib/Helix.desktop ~/.local/share/applications
cp contrib/helix.png ~/.icons # or ~/.local/share/icons cp contrib/helix.png ~/.icons # or ~/.local/share/icons
``` ```
It is recommended to convert the links in the `.desktop` file to absolute paths to avoid potential problems:
```sh
sed -i -e "s|Exec=hx %F|Exec=$(readlink -f ~/.cargo/bin/hx) %F|g" \
-e "s|Icon=helix|Icon=$(readlink -f ~/.icons/helix.png)|g" ~/.local/share/applications/Helix.desktop
```
To use another terminal than the system default, you can modify the `.desktop` To use another terminal than the system default, you can modify the `.desktop`
file. For example, to use `kitty`: file. For example, to use `kitty`:

@ -1,15 +1,18 @@
#!/usr/bin/env fish #!/usr/bin/env fish
# Fish completion script for Helix editor # Fish completion script for Helix editor
set -l langs (hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g')
complete -c hx -s h -l help -d "Prints help information" complete -c hx -s h -l help -d "Prints help information"
complete -c hx -l tutor -d "Loads the tutorial" complete -c hx -l tutor -d "Loads the tutorial"
complete -c hx -l health -x -a "$langs" -d "Checks for errors in editor setup" complete -c hx -l health -xa "(__hx_langs_ops)" -d "Checks for errors"
complete -c hx -s g -l grammar -x -a "fetch build" -d "Fetches or builds tree-sitter grammars" complete -c hx -s g -l grammar -x -a "fetch build" -d "Fetch or build tree-sitter grammars"
complete -c hx -s v -o vv -o vvv -d "Increases logging verbosity" complete -c hx -s v -o vv -o vvv -d "Increases logging verbosity"
complete -c hx -s V -l version -d "Prints version information" complete -c hx -s V -l version -d "Prints version information"
complete -c hx -l vsplit -d "Splits all given files vertically into different windows" complete -c hx -l vsplit -d "Splits all given files vertically"
complete -c hx -l hsplit -d "Splits all given files horizontally into different windows" complete -c hx -l hsplit -d "Splits all given files horizontally"
complete -c hx -s c -l config -r -d "Specifies a file to use for completion" complete -c hx -s c -l config -r -d "Specifies a file to use for config"
complete -c hx -l log -r -d "Specifies a file to write log data into" complete -c hx -l log -r -d "Specifies a file to use for logging"
complete -c hx -s w -l working-dir -d "Specify initial working directory" -xa "(__fish_complete_directories)"
function __hx_langs_ops
hx --health languages | tail -n '+2' | string replace -fr '^(\S+) .*' '$1'
end

@ -14,16 +14,18 @@ _hx() {
"--health[Checks for errors in editor setup]:language:->health" \ "--health[Checks for errors in editor setup]:language:->health" \
"-g[Fetches or builds tree-sitter grammars]:action:->grammar" \ "-g[Fetches or builds tree-sitter grammars]:action:->grammar" \
"--grammar[Fetches or builds tree-sitter grammars]:action:->grammar" \ "--grammar[Fetches or builds tree-sitter grammars]:action:->grammar" \
"--vsplit[Splits all given files vertically into different windows]" \ "--vsplit[Splits all given files vertically]" \
"--hsplit[Splits all given files horizontally into different windows]" \ "--hsplit[Splits all given files horizontally]" \
"-c[Specifies a file to use for configuration]" \ "-c[Specifies a file to use for configuration]" \
"--config[Specifies a file to use for configuration]" \ "--config[Specifies a file to use for configuration]" \
"--log[Specifies a file to write log data into]" \ "-w[Specify initial working directory]" \
"--working-dir[Specify initial working directory]" \
"--log[Specifies a file to use for logging]" \
"*:file:_files" "*:file:_files"
case "$state" in case "$state" in
health) health)
local languages=($(hx --health |tail -n '+7' |awk '{print $1}' |sed 's/\x1b\[[0-9;]*m//g')) local languages=($(hx --health | tail -n '+11' | awk '{print $1}' | sed 's/\x1b\[[0-9;]*m//g;s/[✘✓]//g'))
_values 'language' $languages _values 'language' $languages
;; ;;
grammar) grammar)
@ -31,4 +33,3 @@ _hx() {
;; ;;
esac esac
} }

@ -40,7 +40,7 @@ serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
toml = "0.8" toml = "0.8"
imara-diff = "0.1.0" imara-diff = "0.1.6"
encoding_rs = "0.8" encoding_rs = "0.8"

@ -175,7 +175,7 @@ impl Range {
/// function runs in O(N) (N is number of changes) and can therefore /// function runs in O(N) (N is number of changes) and can therefore
/// cause performance problems if run for a large number of ranges as the /// cause performance problems if run for a large number of ranges as the
/// complexity is then O(MN) (for multicuror M=N usually). Instead use /// complexity is then O(MN) (for multicuror M=N usually). Instead use
/// [Selection::map] or [ChangeSet::update_positions] instead /// [Selection::map] or [ChangeSet::update_positions].
pub fn map(mut self, changes: &ChangeSet) -> Self { pub fn map(mut self, changes: &ChangeSet) -> Self {
use std::cmp::Ordering; use std::cmp::Ordering;
if changes.is_empty() { if changes.is_empty() {
@ -541,6 +541,8 @@ impl Selection {
} }
/// Normalizes a `Selection`. /// Normalizes a `Selection`.
///
/// Ranges are sorted by [Range::from], with overlapping ranges merged.
fn normalize(mut self) -> Self { fn normalize(mut self) -> Self {
if self.len() < 2 { if self.len() < 2 {
return self; return self;

@ -157,8 +157,8 @@ impl Client {
) )
} }
pub fn starting_request_args(&self) -> &Option<Value> { pub fn starting_request_args(&self) -> Option<&Value> {
&self.starting_request_args self.starting_request_args.as_ref()
} }
pub async fn tcp_process( pub async fn tcp_process(

@ -422,7 +422,7 @@ fn build_tree_sitter_library(
} }
} }
let recompile = needs_recompile(&library_path, &parser_path, &scanner_path) let recompile = needs_recompile(&library_path, &parser_path, scanner_path.as_ref())
.context("Failed to compare source and binary timestamps")?; .context("Failed to compare source and binary timestamps")?;
if !recompile { if !recompile {
@ -568,7 +568,7 @@ fn build_tree_sitter_library(
fn needs_recompile( fn needs_recompile(
lib_path: &Path, lib_path: &Path,
parser_c_path: &Path, parser_c_path: &Path,
scanner_path: &Option<PathBuf>, scanner_path: Option<&PathBuf>,
) -> Result<bool> { ) -> Result<bool> {
if !lib_path.exists() { if !lib_path.exists() {
return Ok(true); return Ok(true);

@ -123,7 +123,7 @@ impl Client {
{ {
client.add_workspace_folder( client.add_workspace_folder(
root_uri, root_uri,
&workspace_folders_caps.change_notifications, workspace_folders_caps.change_notifications.as_ref(),
); );
} }
}); });
@ -136,7 +136,10 @@ impl Client {
.and_then(|cap| cap.workspace_folders.as_ref()) .and_then(|cap| cap.workspace_folders.as_ref())
.filter(|cap| cap.supported.unwrap_or(false)) .filter(|cap| cap.supported.unwrap_or(false))
{ {
self.add_workspace_folder(root_uri, &workspace_folders_caps.change_notifications); self.add_workspace_folder(
root_uri,
workspace_folders_caps.change_notifications.as_ref(),
);
true true
} else { } else {
// the server doesn't support multi workspaces, we need a new client // the server doesn't support multi workspaces, we need a new client
@ -147,7 +150,7 @@ impl Client {
fn add_workspace_folder( fn add_workspace_folder(
&self, &self,
root_uri: Option<lsp::Url>, root_uri: Option<lsp::Url>,
change_notifications: &Option<OneOf<bool, String>>, change_notifications: Option<&OneOf<bool, String>>,
) { ) {
// root_uri is None just means that there isn't really any LSP workspace // root_uri is None just means that there isn't really any LSP workspace
// associated with this file. For servers that support multiple workspaces // associated with this file. For servers that support multiple workspaces
@ -162,7 +165,7 @@ impl Client {
self.workspace_folders self.workspace_folders
.lock() .lock()
.push(workspace_for_uri(root_uri.clone())); .push(workspace_for_uri(root_uri.clone()));
if &Some(OneOf::Left(false)) == change_notifications { if Some(&OneOf::Left(false)) == change_notifications {
// server specifically opted out of DidWorkspaceChange notifications // server specifically opted out of DidWorkspaceChange notifications
// let's assume the server will request the workspace folders itself // let's assume the server will request the workspace folders itself
// and that we can therefore reuse the client (but are done now) // and that we can therefore reuse the client (but are done now)
@ -616,6 +619,9 @@ impl Client {
prepare_support_default_behavior: None, prepare_support_default_behavior: None,
honors_change_annotations: Some(false), honors_change_annotations: Some(false),
}), }),
formatting: Some(lsp::DocumentFormattingClientCapabilities {
dynamic_registration: Some(false),
}),
code_action: Some(lsp::CodeActionClientCapabilities { code_action: Some(lsp::CodeActionClientCapabilities {
code_action_literal_support: Some(lsp::CodeActionLiteralSupport { code_action_literal_support: Some(lsp::CodeActionLiteralSupport {
code_action_kind: lsp::CodeActionKindLiteralSupport { code_action_kind: lsp::CodeActionKindLiteralSupport {

@ -58,7 +58,7 @@ pulldown-cmark = { version = "0.11", default-features = false }
content_inspector = "0.2.4" content_inspector = "0.2.4"
# opening URLs # opening URLs
open = "5.1.4" open = "5.2.0"
url = "2.5.2" url = "2.5.2"
# config # config

@ -1210,19 +1210,15 @@ fn goto_file_impl(cx: &mut Context, action: Action) {
let (view, doc) = current_ref!(cx.editor); let (view, doc) = current_ref!(cx.editor);
let text = doc.text(); let text = doc.text();
let selections = doc.selection(view.id); let selections = doc.selection(view.id);
let primary = selections.primary();
let rel_path = doc let rel_path = doc
.relative_path() .relative_path()
.map(|path| path.parent().unwrap().to_path_buf()) .map(|path| path.parent().unwrap().to_path_buf())
.unwrap_or_default(); .unwrap_or_default();
let mut paths: Vec<_> = selections
.iter()
.map(|r| text.slice(r.from()..r.to()).to_string())
.collect();
let primary = selections.primary();
// Checks whether there is only one selection with a width of 1
if selections.len() == 1 && primary.len() == 1 {
paths.clear();
let paths: Vec<_> = if selections.len() == 1 && primary.len() == 1 {
// Secial case: if there is only one one-width selection, try to detect the
// path under the cursor.
let is_valid_path_char = |c: &char| { let is_valid_path_char = |c: &char| {
#[cfg(target_os = "windows")] #[cfg(target_os = "windows")]
let valid_chars = &[ let valid_chars = &[
@ -1257,29 +1253,29 @@ fn goto_file_impl(cx: &mut Context, action: Action) {
.take_while(is_valid_path_char) .take_while(is_valid_path_char)
.count(); .count();
let path: Cow<str> = text let path: String = text
.slice((start_pos - prefix_len)..(start_pos + postfix_len)) .slice((start_pos - prefix_len)..(start_pos + postfix_len))
.into(); .into();
log::debug!("Goto file path: {}", path); log::debug!("goto_file auto-detected path: {}", path);
match expand_tilde(PathBuf::from(path.as_ref())).to_str() { vec![path]
Some(path) => paths.push(path.to_string()), } else {
None => cx.editor.set_error("Couldn't get string out of path."), // Otherwise use each selection, trimmed.
selections
.fragments(text.slice(..))
.map(|sel| sel.trim().to_string())
.filter(|sel| !sel.is_empty())
.collect()
}; };
}
for sel in paths { for sel in paths {
let p = sel.trim(); if let Ok(url) = Url::parse(&sel) {
if p.is_empty() {
continue;
}
if let Ok(url) = Url::parse(p) {
open_url(cx, url, action); open_url(cx, url, action);
continue; continue;
} }
let path = &rel_path.join(p); let path = expand_tilde(Cow::from(PathBuf::from(sel)));
let path = &rel_path.join(path);
if path.is_dir() { if path.is_dir() {
let picker = ui::file_picker(path.into(), &cx.editor.config()); let picker = ui::file_picker(path.into(), &cx.editor.config());
cx.push_layer(Box::new(overlaid(picker))); cx.push_layer(Box::new(overlaid(picker)));
@ -5768,6 +5764,7 @@ fn shell(cx: &mut compositor::Context, cmd: &str, behavior: &ShellBehavior) {
let fragment = range.slice(text); let fragment = range.slice(text);
match shell_impl(shell, cmd, pipe.then(|| fragment.into())) { match shell_impl(shell, cmd, pipe.then(|| fragment.into())) {
Ok(result) => { Ok(result) => {
let result = Tendril::from(result.trim_end());
if !pipe { if !pipe {
shell_output = Some(result.clone()); shell_output = Some(result.clone());
} }

@ -9,6 +9,7 @@ use super::*;
use helix_core::fuzzy::fuzzy_match; use helix_core::fuzzy::fuzzy_match;
use helix_core::indent::MAX_INDENT; use helix_core::indent::MAX_INDENT;
use helix_core::{line_ending, shellwords::Shellwords}; use helix_core::{line_ending, shellwords::Shellwords};
use helix_lsp::LanguageServerId;
use helix_view::document::{read_to_string, DEFAULT_LANGUAGE_NAME}; use helix_view::document::{read_to_string, DEFAULT_LANGUAGE_NAME};
use helix_view::editor::{CloseError, ConfigEvent}; use helix_view::editor::{CloseError, ConfigEvent};
use serde_json::Value; use serde_json::Value;
@ -339,9 +340,12 @@ fn write_impl(
let path = path.map(AsRef::as_ref); let path = path.map(AsRef::as_ref);
if config.insert_final_newline { if config.insert_final_newline {
insert_final_newline(doc, view); insert_final_newline(doc, view.id);
} }
// Save an undo checkpoint for any outstanding changes.
doc.append_changes_to_history(view);
let fmt = if config.auto_format { let fmt = if config.auto_format {
doc.auto_format().map(|fmt| { doc.auto_format().map(|fmt| {
let callback = make_format_callback( let callback = make_format_callback(
@ -366,13 +370,12 @@ fn write_impl(
Ok(()) Ok(())
} }
fn insert_final_newline(doc: &mut Document, view: &mut View) { fn insert_final_newline(doc: &mut Document, view_id: ViewId) {
let text = doc.text(); let text = doc.text();
if line_ending::get_line_ending(&text.slice(..)).is_none() { if line_ending::get_line_ending(&text.slice(..)).is_none() {
let eof = Selection::point(text.len_chars()); let eof = Selection::point(text.len_chars());
let insert = Transaction::insert(text, &eof, doc.line_ending.as_str().into()); let insert = Transaction::insert(text, &eof, doc.line_ending.as_str().into());
doc.apply(&insert, view.id); doc.apply(&insert, view_id);
doc.append_changes_to_history(view);
} }
} }
@ -703,11 +706,15 @@ pub fn write_all_impl(
for (doc_id, target_view) in saves { for (doc_id, target_view) in saves {
let doc = doc_mut!(cx.editor, &doc_id); let doc = doc_mut!(cx.editor, &doc_id);
let view = view_mut!(cx.editor, target_view);
if config.insert_final_newline { if config.insert_final_newline {
insert_final_newline(doc, view_mut!(cx.editor, target_view)); insert_final_newline(doc, target_view);
} }
// Save an undo checkpoint for any outstanding changes.
doc.append_changes_to_history(view);
let fmt = if config.auto_format { let fmt = if config.auto_format {
doc.auto_format().map(|fmt| { doc.auto_format().map(|fmt| {
let callback = make_format_callback( let callback = make_format_callback(
@ -1370,37 +1377,51 @@ fn lsp_workspace_command(
if event != PromptEvent::Validate { if event != PromptEvent::Validate {
return Ok(()); return Ok(());
} }
struct LsIdCommand(LanguageServerId, helix_lsp::lsp::Command);
impl ui::menu::Item for LsIdCommand {
type Data = ();
fn format(&self, _data: &Self::Data) -> Row {
self.1.title.as_str().into()
}
}
let doc = doc!(cx.editor); let doc = doc!(cx.editor);
let Some((language_server_id, options)) = doc let ls_id_commands = doc
.language_servers_with_feature(LanguageServerFeature::WorkspaceCommand) .language_servers_with_feature(LanguageServerFeature::WorkspaceCommand)
.find_map(|ls| { .flat_map(|ls| {
ls.capabilities() ls.capabilities()
.execute_command_provider .execute_command_provider
.as_ref() .iter()
.map(|options| (ls.id(), options)) .flat_map(|options| options.commands.iter())
}) .map(|command| (ls.id(), command))
else { });
cx.editor
.set_status("No active language servers for this document support workspace commands");
return Ok(());
};
if args.is_empty() { if args.is_empty() {
let commands = options let commands = ls_id_commands
.commands .map(|(ls_id, command)| {
.iter() LsIdCommand(
.map(|command| helix_lsp::lsp::Command { ls_id,
helix_lsp::lsp::Command {
title: command.clone(), title: command.clone(),
command: command.clone(), command: command.clone(),
arguments: None, arguments: None,
},
)
}) })
.collect::<Vec<_>>(); .collect::<Vec<_>>();
let callback = async move { let callback = async move {
let call: job::Callback = Callback::EditorCompositor(Box::new( let call: job::Callback = Callback::EditorCompositor(Box::new(
move |_editor: &mut Editor, compositor: &mut Compositor| { move |_editor: &mut Editor, compositor: &mut Compositor| {
let picker = ui::Picker::new(commands, (), move |cx, command, _action| { let picker = ui::Picker::new(
execute_lsp_command(cx.editor, language_server_id, command.clone()); commands,
}); (),
move |cx, LsIdCommand(ls_id, command), _action| {
execute_lsp_command(cx.editor, *ls_id, command.clone());
},
);
compositor.push(Box::new(overlaid(picker))) compositor.push(Box::new(overlaid(picker)))
}, },
)); ));
@ -1409,21 +1430,32 @@ fn lsp_workspace_command(
cx.jobs.callback(callback); cx.jobs.callback(callback);
} else { } else {
let command = args.join(" "); let command = args.join(" ");
if options.commands.iter().any(|c| c == &command) { let matches: Vec<_> = ls_id_commands
.filter(|(_ls_id, c)| *c == &command)
.collect();
match matches.as_slice() {
[(ls_id, _command)] => {
execute_lsp_command( execute_lsp_command(
cx.editor, cx.editor,
language_server_id, *ls_id,
helix_lsp::lsp::Command { helix_lsp::lsp::Command {
title: command.clone(), title: command.clone(),
arguments: None, arguments: None,
command, command,
}, },
); );
} else { }
[] => {
cx.editor.set_status(format!( cx.editor.set_status(format!(
"`{command}` is not supported for this language server" "`{command}` is not supported for any language server"
)); ));
return Ok(()); }
_ => {
cx.editor.set_status(format!(
"`{command}` supported by multiple language servers"
));
}
} }
} }
Ok(()) Ok(())

@ -364,14 +364,16 @@ pub mod completers {
} }
pub fn lsp_workspace_command(editor: &Editor, input: &str) -> Vec<Completion> { pub fn lsp_workspace_command(editor: &Editor, input: &str) -> Vec<Completion> {
let Some(options) = doc!(editor) let commands = doc!(editor)
.language_servers_with_feature(LanguageServerFeature::WorkspaceCommand) .language_servers_with_feature(LanguageServerFeature::WorkspaceCommand)
.find_map(|ls| ls.capabilities().execute_command_provider.as_ref()) .flat_map(|ls| {
else { ls.capabilities()
return vec![]; .execute_command_provider
}; .iter()
.flat_map(|options| options.commands.iter())
});
fuzzy_match(input, &options.commands, false) fuzzy_match(input, commands, false)
.into_iter() .into_iter()
.map(|(name, _)| ((0..), name.to_owned().into())) .map(|(name, _)| ((0..), name.to_owned().into()))
.collect() .collect()

@ -210,13 +210,10 @@ async fn test_multi_selection_shell_commands() -> anyhow::Result<()> {
"}, "},
"|echo foo<ret>", "|echo foo<ret>",
indoc! {"\ indoc! {"\
#[|foo\n]# #[|foo]#
#(|foo)#
#(|foo\n)# #(|foo)#"
},
#(|foo\n)#
"},
)) ))
.await?; .await?;
@ -229,12 +226,9 @@ async fn test_multi_selection_shell_commands() -> anyhow::Result<()> {
"}, "},
"!echo foo<ret>", "!echo foo<ret>",
indoc! {"\ indoc! {"\
#[|foo\n]# #[|foo]#lorem
lorem #(|foo)#ipsum
#(|foo\n)# #(|foo)#dolor
ipsum
#(|foo\n)#
dolor
"}, "},
)) ))
.await?; .await?;
@ -248,12 +242,9 @@ async fn test_multi_selection_shell_commands() -> anyhow::Result<()> {
"}, "},
"<A-!>echo foo<ret>", "<A-!>echo foo<ret>",
indoc! {"\ indoc! {"\
lorem#[|foo\n]# lorem#[|foo]#
ipsum#(|foo)#
ipsum#(|foo\n)# dolor#(|foo)#
dolor#(|foo\n)#
"}, "},
)) ))
.await?; .await?;

@ -20,7 +20,7 @@ parking_lot = "0.12"
arc-swap = { version = "1.7.1" } arc-swap = { version = "1.7.1" }
gix = { version = "0.63.0", features = ["attributes", "status"], default-features = false, optional = true } gix = { version = "0.63.0", features = ["attributes", "status"], default-features = false, optional = true }
imara-diff = "0.1.5" imara-diff = "0.1.6"
anyhow = "1" anyhow = "1"
log = "0.4" log = "0.4"

@ -53,7 +53,7 @@ parking_lot = "0.12.3"
thiserror.workspace = true thiserror.workspace = true
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
clipboard-win = { version = "5.3", features = ["std"] } clipboard-win = { version = "5.4", features = ["std"] }
[target.'cfg(unix)'.dependencies] [target.'cfg(unix)'.dependencies]
libc = "0.2" libc = "0.2"

@ -1410,6 +1410,11 @@ impl Document {
} }
fn undo_redo_impl(&mut self, view: &mut View, undo: bool) -> bool { fn undo_redo_impl(&mut self, view: &mut View, undo: bool) -> bool {
if undo {
self.append_changes_to_history(view);
} else if !self.changes.is_empty() {
return false;
}
let mut history = self.history.take(); let mut history = self.history.take();
let txn = if undo { history.undo() } else { history.redo() }; let txn = if undo { history.undo() } else { history.redo() };
let success = if let Some(txn) = txn { let success = if let Some(txn) = txn {
@ -1490,6 +1495,11 @@ impl Document {
} }
fn earlier_later_impl(&mut self, view: &mut View, uk: UndoKind, earlier: bool) -> bool { fn earlier_later_impl(&mut self, view: &mut View, uk: UndoKind, earlier: bool) -> bool {
if earlier {
self.append_changes_to_history(view);
} else if !self.changes.is_empty() {
return false;
}
let txns = if earlier { let txns = if earlier {
self.history.get_mut().earlier(uk) self.history.get_mut().earlier(uk)
} else { } else {

@ -73,6 +73,7 @@ prisma-language-server = { command = "prisma-language-server", args = ["--stdio"
purescript-language-server = { command = "purescript-language-server", args = ["--stdio"] } purescript-language-server = { command = "purescript-language-server", args = ["--stdio"] }
pylsp = { command = "pylsp" } pylsp = { command = "pylsp" }
pyright = { command = "pyright-langserver", args = ["--stdio"], config = {} } pyright = { command = "pyright-langserver", args = ["--stdio"], config = {} }
basedpyright = { command = "basedpyright-langserver", args = ["--stdio"], config = {} }
pylyzer = { command = "pylyzer", args = ["--server"] } pylyzer = { command = "pylyzer", args = ["--server"] }
qmlls = { command = "qmlls" } qmlls = { command = "qmlls" }
r = { command = "R", args = ["--no-echo", "-e", "languageserver::run()"] } r = { command = "R", args = ["--no-echo", "-e", "languageserver::run()"] }
@ -296,7 +297,7 @@ source = { git = "https://github.com/FuelLabs/tree-sitter-sway", rev = "e491a005
name = "toml" name = "toml"
scope = "source.toml" scope = "source.toml"
injection-regex = "toml" injection-regex = "toml"
file-types = ["toml", { glob = "poetry.lock" }, { glob = "Cargo.lock" }] file-types = ["toml", { glob = "pdm.lock" }, { glob = "poetry.lock" }, { glob = "Cargo.lock" }, { glob = "uv.lock" }]
comment-token = "#" comment-token = "#"
language-servers = [ "taplo" ] language-servers = [ "taplo" ]
indent = { tab-width = 2, unit = " " } indent = { tab-width = 2, unit = " " }
@ -1269,7 +1270,7 @@ source = { git = "https://github.com/ikatyang/tree-sitter-yaml", rev = "0e36bed1
name = "haskell" name = "haskell"
scope = "source.haskell" scope = "source.haskell"
injection-regex = "hs|haskell" injection-regex = "hs|haskell"
file-types = ["hs", "hs-boot"] file-types = ["hs", "hs-boot", "hsc"]
roots = ["Setup.hs", "stack.yaml", "cabal.project"] roots = ["Setup.hs", "stack.yaml", "cabal.project"]
comment-token = "--" comment-token = "--"
block-comment-tokens = { start = "{-", end = "-}" } block-comment-tokens = { start = "{-", end = "-}" }
@ -1693,7 +1694,7 @@ source = { git = "https://github.com/mtoohey31/tree-sitter-gitattributes", rev =
[[language]] [[language]]
name = "git-ignore" name = "git-ignore"
scope = "source.gitignore" scope = "source.gitignore"
file-types = [{ glob = ".gitignore_global" }, { glob = ".ignore" }, { glob = "CODEOWNERS" }, { glob = ".config/helix/ignore" }, { glob = ".helix/ignore" }, { glob = ".*ignore" }] file-types = [{ glob = ".gitignore_global" }, { glob = "git/ignore" }, { glob = ".ignore" }, { glob = "CODEOWNERS" }, { glob = ".config/helix/ignore" }, { glob = ".helix/ignore" }, { glob = ".*ignore" }]
injection-regex = "git-ignore" injection-regex = "git-ignore"
comment-token = "#" comment-token = "#"
grammar = "gitignore" grammar = "gitignore"
@ -2054,7 +2055,7 @@ indent = { tab-width = 8, unit = "\t" }
[[grammar]] [[grammar]]
name = "hare" name = "hare"
source = { git = "https://git.sr.ht/~ecmma/tree-sitter-hare", rev = "2495958aaf3f93581c87ec020164255e80655331" } source = { git = "https://git.sr.ht/~ecs/tree-sitter-hare", rev = "07035a248943575444aa0b893ffe306e1444c0ab" }
[[language]] [[language]]
name = "devicetree" name = "devicetree"
@ -2081,7 +2082,7 @@ language-servers = [ "cairo-language-server" ]
[[grammar]] [[grammar]]
name = "cairo" name = "cairo"
source = { git = "https://github.com/starkware-libs/tree-sitter-cairo", rev = "0596baab741ffacdc65c761d5d5ffbbeae97f033" } source = { git = "https://github.com/starkware-libs/tree-sitter-cairo", rev = "e3a0212261c125cb38248458cd856c0ffee2b398" }
[[language]] [[language]]
name = "cpon" name = "cpon"
@ -2702,6 +2703,8 @@ file-types = [
"kube", "kube",
"network", "network",
{ glob = ".editorconfig" }, { glob = ".editorconfig" },
{ glob = ".npmrc" },
{ glob = "npmrc" },
{ glob = "rclone.conf" }, { glob = "rclone.conf" },
"properties", "properties",
"cfg", "cfg",
@ -3242,7 +3245,7 @@ auto-format = true
[[grammar]] [[grammar]]
name = "todotxt" name = "todotxt"
source = { git = "https://github.com/arnarg/tree-sitter-todotxt", rev = "0207f6a4ab6aeafc4b091914d31d8235049a2578" } source = { git = "https://github.com/arnarg/tree-sitter-todotxt", rev = "3937c5cd105ec4127448651a21aef45f52d19609" }
[[language]] [[language]]
name = "strace" name = "strace"
@ -3513,7 +3516,7 @@ scope = "source.helm"
roots = ["Chart.yaml"] roots = ["Chart.yaml"]
comment-token = "#" comment-token = "#"
language-servers = ["helm_ls"] language-servers = ["helm_ls"]
file-types = [ { glob = "templates/*.yaml" }, { glob = "templates/_*.tpl"}, { glob = "templates/NOTES.txt" } ] file-types = [ { glob = "templates/*.yaml" }, { glob = "templates/*.yml" }, { glob = "templates/_*.tpl"}, { glob = "templates/NOTES.txt" } ]
[[language]] [[language]]
name = "glimmer" name = "glimmer"

@ -1,10 +1,15 @@
[ [
(string) (string)
(raw_string) (raw_string)
(ansi_c_string)
(heredoc_body) (heredoc_body)
(heredoc_start)
] @string ] @string
[
(heredoc_start)
(heredoc_end)
] @label
(command_name) @function (command_name) @function
(variable_name) @variable.other.member (variable_name) @variable.other.member

@ -6,3 +6,6 @@
argument: (raw_string) @injection.content argument: (raw_string) @injection.content
(#match? @_command "^[gnm]?awk$") (#match? @_command "^[gnm]?awk$")
(#set! injection.language "awk")) (#set! injection.language "awk"))
((regex) @injection.content
(#set! injection.language "regex"))

@ -95,6 +95,12 @@
; ------- ; -------
; Keywords ; Keywords
; ------- ; -------
(for_expression
"for" @keyword.control.repeat)
"in" @keyword.control
[ [
"match" "match"
"if" "if"

@ -115,4 +115,10 @@
(#not-same-line? @expr-start @pattern-guard) (#not-same-line? @expr-start @pattern-guard)
) @indent ) @indent
(for_expression
"in" @in
.
(_) @indent
(#not-same-line? @in @indent)
(#set! "scope" "all")
)

@ -1,22 +1,5 @@
[ (type) @type
"f32" (type "const" @type)
"f64"
"i16"
"i32"
"i64"
"i8"
"int"
"rune"
"str"
"u16"
"u32"
"u64"
"u8"
"uint"
"uintptr"
"void"
] @type
[ [
"else" "else"
@ -36,28 +19,23 @@
"break" "break"
] @keyword.control.repeat ] @keyword.control.repeat
[ "return" @keyword.control.return
"return"
"yield"
] @keyword.control.return
[ [
"abort" "abort"
"assert" "assert"
] @keyword.control.exception ] @keyword.control.exception
[ "fn" @keyword.function
"def"
"fn"
] @keyword.function
[ [
"alloc" "alloc"
"append" "append"
"as" "as"
"bool" "bool"
"char" "case"
"const" "const"
"def"
"defer" "defer"
"delete" "delete"
"enum" "enum"
@ -68,13 +46,14 @@
"match" "match"
"nullable" "nullable"
"offset" "offset"
"size"
"static"
"struct" "struct"
"type" "type"
"union" "union"
"yield"
] @keyword ] @keyword
"static" @keyword.storage.modifier
[ [
"." "."
"!" "!"
@ -137,15 +116,17 @@
"null" "null"
"true" "true"
] @constant.builtin ] @constant.builtin
(literal "void") @constant.builtin
(string_constant) @string (string_literal) @string
(escape_sequence) @constant.character.escape (escape_sequence) @constant.character.escape
(rune_constant) @string (rune_literal) @string
(integer_constant) @constant.numeric.integer (integer_literal) @constant.numeric.integer
(floating_constant) @constant.numeric.float (floating_literal) @constant.numeric.float
(call_expression (call_expression
(postfix_expression) @function) (postfix_expression) @function)
(size_expression "size" @function.builtin)
(function_declaration (function_declaration
name: (identifier) @function) name: (identifier) @function)
@ -158,4 +139,4 @@
(fndec_attrs) @special (fndec_attrs) @special
(identifier) @variable (identifier) @variable
(struct_union_field (name)) @variable

@ -1,20 +1,19 @@
(unit) @local.scope (sub_unit) @local.scope
(function_declaration) @local.scope (function_declaration) @local.scope
(compound_expression) @local.scope
(global_binding (global_binding
(identifier) @local.definition) (identifier) @local.definition)
(constant_binding (constant_binding
(identifier) @local.definition) (identifier) @local.definition)
(type_bindings (type_binding
(identifier) @local.definition) (identifier) @local.definition)
(function_declaration (function_declaration
(prototype (identifier) @local.definition)
(parameter_list (function_declaration
(parameters (parameter (name) @local.definition))
(parameter
(name) @local.definition)))))
(identifier) @local.reference (identifier) @local.reference

@ -24,6 +24,10 @@
"ui.cursor.match" = { fg = "light-yellow", underline = { color = "light-yellow", style = "line" } } "ui.cursor.match" = { fg = "light-yellow", underline = { color = "light-yellow", style = "line" } }
"ui.cursor.primary" = { modifiers = ["reversed", "slow_blink"] } "ui.cursor.primary" = { modifiers = ["reversed", "slow_blink"] }
"ui.cursor.secondary" = { modifiers = ["reversed"] } "ui.cursor.secondary" = { modifiers = ["reversed"] }
"ui.cursorline.primary" = { underline = { color = "light-gray", style = "line" } }
"ui.cursorline.secondary" = { underline = { color = "light-gray", style = "line" } }
"ui.cursorcolumn.primary" = { bg = "gray" }
"ui.cursorcolumn.secondary" = { bg = "gray" }
"ui.virtual.ruler" = { bg = "gray" } "ui.virtual.ruler" = { bg = "gray" }
"ui.virtual.whitespace" = "gray" "ui.virtual.whitespace" = "gray"
"ui.virtual.indent-guide" = "gray" "ui.virtual.indent-guide" = "gray"

@ -77,7 +77,7 @@
"ui.selection" = { bg = "Gray 50" } # .primary "ui.selection" = { bg = "Gray 50" } # .primary
"ui.selection.primary" = { bg = "Blue 40" } "ui.selection.primary" = { bg = "Blue 40" }
"ui.cursorline" = { bg = "Gray 20" } "ui.cursorline" = { bg = "Gray 15" }
"ui.linenr" = "Gray 70" "ui.linenr" = "Gray 70"
"ui.linenr.selected" = "Gray 110" "ui.linenr.selected" = "Gray 110"
@ -121,6 +121,7 @@
"Gray 40" = "#333333" "Gray 40" = "#333333"
"Gray 30" = "#2d2d2d" "Gray 30" = "#2d2d2d"
"Gray 20" = "#292929" "Gray 20" = "#292929"
"Gray 15" = "#1F1F1F"
"Gray 10" = "#181818" "Gray 10" = "#181818"
"Black" = "#000000" "Black" = "#000000"
"Blue 110" = "#6daaf7" "Blue 110" = "#6daaf7"

@ -6,6 +6,7 @@ inherits = "gruvbox"
"ui.cursor.primary" = { modifiers = ["reversed"] } "ui.cursor.primary" = { modifiers = ["reversed"] }
"ui.cursor.match" = { bg = "bg2" } "ui.cursor.match" = { bg = "bg2" }
"ui.cursorline" = { bg = "bg1" }
[palette] [palette]
bg0 = "#fbf1c7" # main background bg0 = "#fbf1c7" # main background

@ -0,0 +1,125 @@
# Kanagawa Dragon
# Author: EricHenry
# Adaptation of https://github.com/rebelot/kanagawa.nvim
# Original author: rebelot
# All credits to the original author, the palette is taken from the README
# because of some theming differences, it's not an exact copy of the original.
inherits = "kanagawa"
## User interface
"ui.selection" = { bg = "waveBlue2" }
"ui.selection.primary" = { bg = "waveBlue1" }
"ui.background" = { fg = "dragonWhite", bg = "dragonBlack3" }
"ui.gutter" = { fg = "dragonBlack6", bg = "dragonBlack4" }
"ui.linenr" = { fg = "dragonBlack6", bg = "dragonBlack4" }
"ui.linenr.selected" = { fg = "roninYellow", modifiers = ["bold"] }
"ui.virtual" = "dragonBlack4"
"ui.virtual.ruler" = { bg = "dragonBlack5" }
"ui.virtual.inlay-hint" = "dragonGray2"
"ui.virtual.inlay-hint.parameter" = { fg = "dragonYellow", modifiers = ["dim"] }
"ui.virtual.inlay-hint.type" = { fg = "dragonAqua", modifiers = ["dim"] }
"ui.virtual.jump-label" = { fg = "dragonRed", modifiers = ["bold"] }
"ui.statusline" = { fg = "oldWhite", bg = "dragonBlack0" }
"ui.bufferline" = { fg = "oldWhite", bg = "dragonBlack0" }
"ui.bufferline.active" = { fg = "oldWhite", bg = "dragonBlack0" }
"ui.bufferline.background" = { bg = "sumiInk0" }
"ui.popup" = { fg = "oldWhite", bg = "dragonBlack0" }
"ui.window" = { fg = "sumiInk0" }
"ui.help" = { fg = "fujiWhite", bg = "sumiInk0" }
"ui.text" = "dragonWhite"
"ui.text.focus" = { fg = "dragonWhite", bg = "waveBlue1", modifiers = ["bold"] }
"ui.cursor" = { fg = "waveBlue1", bg = "waveAqua2" }
"ui.cursor.primary" = { fg = "waveBlue1", bg = "fujiWhite" }
"ui.cursor.match" = { fg = "roninYellow", modifiers = ["bold"] }
"ui.highlight" = { fg = "fujiWhite", bg = "waveBlue2" }
"ui.cursorline.primary" = { bg = "dragonBlack5" }
"ui.cursorcolumn.primary" = { bg = "dragonBlack5" }
"diagnostic.info" = { underline = { color = "dragonBlue", style = "curl" } }
"diagnostic.hint" = { underline = { color = "waveAqua1", style = "curl" } }
"diagnostic.deprecated" = { fg= "katanaGray", modifiers = ["crossed_out"] }
## Syntax highlighting
"attribute" = "waveRed"
"type" = "dragonAqua"
"type.enum.variant" = "dragonOrange"
"constructor" = "dragonTeal"
"constant" = "dragonOrange"
"constant.numeric" = "dragonPink"
"constant.character.escape" = "dragonBlue2"
"string" = "dragonGreen2"
"string.regexp" = "dragonRed"
"string.special.url" = "dragonTeal"
"string.special.symbol" = "dragonTeal"
"comment" = "dragonAsh"
"variable" = "dragonWhite"
"variable.builtin" = "dragonRed"
"variable.parameter" = "dragonGray"
"variable.other.member" = "dragonYellow"
"label" = "dragonRed"
"punctuation" = "dragonWhite"
"keyword" = "dragonViolet"
"keyword.control.return" = "dragonRed"
"keyword.control.exception" = "dragonRed"
"keyword.directive" = "dragonRed"
"operator" = "dragonRed"
"function" = "dragonBlue2"
"function.builtin" = "dragonBlue2"
"function.macro" = "dragonRed"
"tag" = "dragonYellow"
"namespace" = "dragonWhite"
"special" = "dragonYellow"
## Markup modifiers
"markup.heading.marker" = "dragonViolet"
"markup.heading.1" = { fg = "dragonOrange", modifiers = ["bold"] }
"markup.heading.2" = { fg = "dragonYellow", modifiers = ["bold"] }
"markup.heading.3" = { fg = "dragonBlue2", modifiers = ["bold"] }
"markup.heading.4" = { fg = "dragonWhite", modifiers = ["bold"] }
"markup.heading.5" = { fg = "dragonRed", modifiers = ["bold"] }
"markup.heading.6" = { fg = "dragonPink", modifiers = ["bold"] }
"markup.list.numbered" = "dragonPink"
"markup.list.unnumbered" = "dragonRed"
"markup.bold" = { modifiers = ["bold"] }
"markup.italic" = { modifiers = ["italic"] }
"markup.strikethrough" = { modifiers = ["crossed_out"] }
"markup.link.text" = "dragonTeal"
"markup.link.url" = { fg = "dragonPink", underline.style = "line" }
"markup.link.label" = "dragonBlue2"
"markup.quote" = "springViolet1"
"markup.raw" = "dragonGreen2"
[palette]
dragonBlack0 = "#0d0c0c"
dragonBlack1 = "#12120f"
dragonBlack2 = "#1D1C19"
dragonBlack3 = "#181616"
dragonBlack4 = "#282727"
dragonBlack5 = "#393836"
dragonBlack6 = "#625e5a"
dragonWhite = "#c5c9c5"
dragonGreen = "#87a987"
dragonGreen2 = "#8a9a7b"
dragonPink = "#a292a3"
dragonOrange = "#b6927b"
dragonOrange2 = "#b98d7b"
dragonGray = "#a6a69c"
dragonGray2 = "#9e9b93"
dragonGray3 = "#7a8382"
dragonBlue2 = "#8ba4b0"
dragonViolet= "#8992a7"
dragonRed = "#c4746e"
dragonAqua = "#8ea4a2"
dragonAsh = "#737c73"
dragonTeal = "#949fb5"
dragonYellow = "#c4b28a"

@ -1,4 +1,5 @@
# Author : Eric Correia <correia.eh@gmail.com> # Zed OneDark
# Author : EricHenry
"attribute" = { fg = "yellow" } "attribute" = { fg = "yellow" }
"comment" = { fg = "light-gray", modifiers = ["italic"] } "comment" = { fg = "light-gray", modifiers = ["italic"] }

@ -1,4 +1,5 @@
# Author : Eric Correia <correia.eh@gmail.com> # Zed OneLight
# Author : EricHenry
inherits = "zed_onedark" inherits = "zed_onedark"

Loading…
Cancel
Save