From 606b95717211eab05ce9564cec8312b015220c3d Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 8 Aug 2024 11:03:29 -0400 Subject: [PATCH 01/27] Replace uses of lsp::Location with a custom Location type The lsp location type has the lsp's URI type and a range. We can replace that with a custom type private to the lsp commands module that uses the core URI type instead. We can't entirely replace the type with a new Location type in core. That type might look like: pub struct Location { uri: crate::Uri, range: crate::Range, } But we can't convert every `lsp::Location` to this type because for definitions, references and diagnostics language servers send documents which we haven't opened yet, so we don't have the information to convert an `lsp::Range` (line+col) to a `helix_core::Range` (char indexing). This cleans up the picker definitions in this file so that they can all use helpers like `jump_to_location` and `location_to_file_location` for the picker preview. It also removes the only use of the deprecated `PathOrId::from_path_buf` function, allowing us to drop the owned variant of that type in the child commit. --- helix-core/src/uri.rs | 24 +++- helix-term/src/commands/lsp.rs | 196 ++++++++++++++------------------- 2 files changed, 105 insertions(+), 115 deletions(-) diff --git a/helix-core/src/uri.rs b/helix-core/src/uri.rs index 4e03c58b1..ddb9fb7a8 100644 --- a/helix-core/src/uri.rs +++ b/helix-core/src/uri.rs @@ -1,4 +1,7 @@ -use std::path::{Path, PathBuf}; +use std::{ + fmt, + path::{Path, PathBuf}, +}; /// A generic pointer to a file location. /// @@ -47,6 +50,14 @@ impl TryFrom for PathBuf { } } +impl fmt::Display for Uri { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Self::File(path) => write!(f, "{}", path.display()), + } + } +} + #[derive(Debug)] pub struct UrlConversionError { source: url::Url, @@ -59,11 +70,16 @@ pub enum UrlConversionErrorKind { UnableToConvert, } -impl std::fmt::Display for UrlConversionError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { +impl fmt::Display for UrlConversionError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind { UrlConversionErrorKind::UnsupportedScheme => { - write!(f, "unsupported scheme in URL: {}", self.source.scheme()) + write!( + f, + "unsupported scheme '{}' in URL {}", + self.source.scheme(), + self.source + ) } UrlConversionErrorKind::UnableToConvert => { write!(f, "unable to convert URL to file path: {}", self.source) diff --git a/helix-term/src/commands/lsp.rs b/helix-term/src/commands/lsp.rs index 93ac2a849..fcc0333e8 100644 --- a/helix-term/src/commands/lsp.rs +++ b/helix-term/src/commands/lsp.rs @@ -34,7 +34,7 @@ use crate::{ use std::{ cmp::Ordering, collections::{BTreeMap, HashSet}, - fmt::{Display, Write}, + fmt::Display, future::Future, path::Path, }; @@ -61,10 +61,31 @@ macro_rules! language_server_with_feature { }}; } +/// A wrapper around `lsp::Location` that swaps out the LSP URI for `helix_core::Uri`. +#[derive(Debug, Clone, PartialEq, Eq)] +struct Location { + uri: Uri, + range: lsp::Range, +} + +fn lsp_location_to_location(location: lsp::Location) -> Option { + let uri = match location.uri.try_into() { + Ok(uri) => uri, + Err(err) => { + log::warn!("discarding invalid or unsupported URI: {err}"); + return None; + } + }; + Some(Location { + uri, + range: location.range, + }) +} + struct SymbolInformationItem { + location: Location, symbol: lsp::SymbolInformation, offset_encoding: OffsetEncoding, - uri: Uri, } struct DiagnosticStyles { @@ -75,35 +96,35 @@ struct DiagnosticStyles { } struct PickerDiagnostic { - uri: Uri, + location: Location, diag: lsp::Diagnostic, offset_encoding: OffsetEncoding, } -fn uri_to_file_location<'a>(uri: &'a Uri, range: &lsp::Range) -> Option> { - let path = uri.as_path()?; - let line = Some((range.start.line as usize, range.end.line as usize)); +fn location_to_file_location(location: &Location) -> Option { + let path = location.uri.as_path()?; + let line = Some(( + location.range.start.line as usize, + location.range.end.line as usize, + )); Some((path.into(), line)) } fn jump_to_location( editor: &mut Editor, - location: &lsp::Location, + location: &Location, offset_encoding: OffsetEncoding, action: Action, ) { let (view, doc) = current!(editor); push_jump(view, doc); - let path = match location.uri.to_file_path() { - Ok(path) => path, - Err(_) => { - let err = format!("unable to convert URI to filepath: {}", location.uri); - editor.set_error(err); - return; - } + let Some(path) = location.uri.as_path() else { + let err = format!("unable to convert URI to filepath: {:?}", location.uri); + editor.set_error(err); + return; }; - jump_to_position(editor, &path, location.range, offset_encoding, action); + jump_to_position(editor, path, location.range, offset_encoding, action); } fn jump_to_position( @@ -196,7 +217,10 @@ fn diag_picker( for (diag, ls) in diags { if let Some(ls) = cx.editor.language_server_by_id(ls) { flat_diag.push(PickerDiagnostic { - uri: uri.clone(), + location: Location { + uri: uri.clone(), + range: diag.range, + }, diag, offset_encoding: ls.offset_encoding(), }); @@ -243,7 +267,7 @@ fn diag_picker( // between message code and message 2, ui::PickerColumn::new("path", |item: &PickerDiagnostic, _| { - if let Some(path) = item.uri.as_path() { + if let Some(path) = item.location.uri.as_path() { path::get_truncated_path(path) .to_string_lossy() .to_string() @@ -261,26 +285,14 @@ fn diag_picker( primary_column, flat_diag, styles, - move |cx, - PickerDiagnostic { - uri, - diag, - offset_encoding, - }, - action| { - let Some(path) = uri.as_path() else { - return; - }; - jump_to_position(cx.editor, path, diag.range, *offset_encoding, action); + move |cx, diag, action| { + jump_to_location(cx.editor, &diag.location, diag.offset_encoding, action); let (view, doc) = current!(cx.editor); view.diagnostics_handler .immediately_show_diagnostic(doc, view.id); }, ) - .with_preview(move |_editor, PickerDiagnostic { uri, diag, .. }| { - let line = Some((diag.range.start.line as usize, diag.range.end.line as usize)); - Some((uri.as_path()?.into(), line)) - }) + .with_preview(move |_editor, diag| location_to_file_location(&diag.location)) .truncate_start(false) } @@ -303,7 +315,10 @@ pub fn symbol_picker(cx: &mut Context) { container_name: None, }, offset_encoding, - uri: uri.clone(), + location: Location { + uri: uri.clone(), + range: symbol.selection_range, + }, }); for child in symbol.children.into_iter().flatten() { nested_to_flat(list, file, uri, child, offset_encoding); @@ -337,7 +352,10 @@ pub fn symbol_picker(cx: &mut Context) { lsp::DocumentSymbolResponse::Flat(symbols) => symbols .into_iter() .map(|symbol| SymbolInformationItem { - uri: doc_uri.clone(), + location: Location { + uri: doc_uri.clone(), + range: symbol.location.range, + }, symbol, offset_encoding, }) @@ -392,17 +410,10 @@ pub fn symbol_picker(cx: &mut Context) { symbols, (), move |cx, item, action| { - jump_to_location( - cx.editor, - &item.symbol.location, - item.offset_encoding, - action, - ); + jump_to_location(cx.editor, &item.location, item.offset_encoding, action); }, ) - .with_preview(move |_editor, item| { - uri_to_file_location(&item.uri, &item.symbol.location.range) - }) + .with_preview(move |_editor, item| location_to_file_location(&item.location)) .truncate_start(false); compositor.push(Box::new(overlaid(picker))) @@ -453,8 +464,11 @@ pub fn workspace_symbol_picker(cx: &mut Context) { } }; Some(SymbolInformationItem { + location: Location { + uri, + range: symbol.location.range, + }, symbol, - uri, offset_encoding, }) }) @@ -490,7 +504,7 @@ pub fn workspace_symbol_picker(cx: &mut Context) { }) .without_filtering(), ui::PickerColumn::new("path", |item: &SymbolInformationItem, _| { - if let Some(path) = item.uri.as_path() { + if let Some(path) = item.location.uri.as_path() { path::get_relative_path(path) .to_string_lossy() .to_string() @@ -507,15 +521,10 @@ pub fn workspace_symbol_picker(cx: &mut Context) { [], (), move |cx, item, action| { - jump_to_location( - cx.editor, - &item.symbol.location, - item.offset_encoding, - action, - ); + jump_to_location(cx.editor, &item.location, item.offset_encoding, action); }, ) - .with_preview(|_editor, item| uri_to_file_location(&item.uri, &item.symbol.location.range)) + .with_preview(|_editor, item| location_to_file_location(&item.location)) .with_dynamic_query(get_symbols, None) .truncate_start(false); @@ -847,7 +856,7 @@ impl Display for ApplyEditErrorKind { fn goto_impl( editor: &mut Editor, compositor: &mut Compositor, - locations: Vec, + locations: Vec, offset_encoding: OffsetEncoding, ) { let cwdir = helix_stdx::env::current_working_dir(); @@ -860,80 +869,41 @@ fn goto_impl( _locations => { let columns = [ui::PickerColumn::new( "location", - |item: &lsp::Location, cwdir: &std::path::PathBuf| { - // The preallocation here will overallocate a few characters since it will account for the - // URL's scheme, which is not used most of the time since that scheme will be "file://". - // Those extra chars will be used to avoid allocating when writing the line number (in the - // common case where it has 5 digits or less, which should be enough for a cast majority - // of usages). - let mut res = String::with_capacity(item.uri.as_str().len()); - - if item.uri.scheme() == "file" { - // With the preallocation above and UTF-8 paths already, this closure will do one (1) - // allocation, for `to_file_path`, else there will be two (2), with `to_string_lossy`. - if let Ok(path) = item.uri.to_file_path() { - // We don't convert to a `helix_core::Uri` here because we've already checked the scheme. - // This path won't be normalized but it's only used for display. - res.push_str( - &path.strip_prefix(cwdir).unwrap_or(&path).to_string_lossy(), - ); - } + |item: &Location, cwdir: &std::path::PathBuf| { + let path = if let Some(path) = item.uri.as_path() { + path.strip_prefix(cwdir).unwrap_or(path).to_string_lossy() } else { - // Never allocates since we declared the string with this capacity already. - res.push_str(item.uri.as_str()); - } + item.uri.to_string().into() + }; - // Most commonly, this will not allocate, especially on Unix systems where the root prefix - // is a simple `/` and not `C:\` (with whatever drive letter) - write!(&mut res, ":{}", item.range.start.line + 1) - .expect("Will only failed if allocating fail"); - res.into() + format!("{path}:{}", item.range.start.line + 1).into() }, )]; let picker = Picker::new(columns, 0, locations, cwdir, move |cx, location, action| { jump_to_location(cx.editor, location, offset_encoding, action) }) - .with_preview(move |_editor, location| { - use crate::ui::picker::PathOrId; - - let lines = Some(( - location.range.start.line as usize, - location.range.end.line as usize, - )); - - // TODO: we should avoid allocating by doing the Uri conversion ahead of time. - // - // To do this, introduce a `Location` type in `helix-core` that reuses the core - // `Uri` type instead of the LSP `Url` type and replaces the LSP `Range` type. - // Refactor the callers of `goto_impl` to pass iterators that translate the - // LSP location type to the custom one in core, or have them collect and pass - // `Vec`s. Replace the `uri_to_file_location` function with - // `location_to_file_location` that takes only `&helix_core::Location` as - // parameters. - // - // By doing this we can also eliminate the duplicated URI info in the - // `SymbolInformationItem` type and introduce a custom Symbol type in `helix-core` - // which will be reused in the future for tree-sitter based symbol pickers. - let path = Uri::try_from(&location.uri).ok()?.as_path_buf()?; - #[allow(deprecated)] - Some((PathOrId::from_path_buf(path), lines)) - }); + .with_preview(move |_editor, location| location_to_file_location(location)); compositor.push(Box::new(overlaid(picker))); } } } -fn to_locations(definitions: Option) -> Vec { +fn to_locations(definitions: Option) -> Vec { match definitions { - Some(lsp::GotoDefinitionResponse::Scalar(location)) => vec![location], - Some(lsp::GotoDefinitionResponse::Array(locations)) => locations, + Some(lsp::GotoDefinitionResponse::Scalar(location)) => { + lsp_location_to_location(location).into_iter().collect() + } + Some(lsp::GotoDefinitionResponse::Array(locations)) => locations + .into_iter() + .flat_map(lsp_location_to_location) + .collect(), Some(lsp::GotoDefinitionResponse::Link(locations)) => locations .into_iter() - .map(|location_link| lsp::Location { - uri: location_link.target_uri, - range: location_link.target_range, + .map(|location_link| { + lsp::Location::new(location_link.target_uri, location_link.target_range) }) + .flat_map(lsp_location_to_location) .collect(), None => Vec::new(), } @@ -1018,7 +988,11 @@ pub fn goto_reference(cx: &mut Context) { cx.callback( future, move |editor, compositor, response: Option>| { - let items = response.unwrap_or_default(); + let items: Vec = response + .into_iter() + .flatten() + .flat_map(lsp_location_to_location) + .collect(); if items.is_empty() { editor.set_error("No references found."); } else { From 48e93577882e58de85d451225494efe48fe9b606 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 8 Aug 2024 11:05:12 -0400 Subject: [PATCH 02/27] picker: Removed owned variant of PathOrId The only caller of `from_path_buf` was removed in the parent commit allowing us to drop owned variant of path's `Cow`. With this change we never need to allocate in the picker preview callback. --- helix-term/src/ui/picker.rs | 21 +++------------------ 1 file changed, 3 insertions(+), 18 deletions(-) diff --git a/helix-term/src/ui/picker.rs b/helix-term/src/ui/picker.rs index 82fe96891..ecf8111ab 100644 --- a/helix-term/src/ui/picker.rs +++ b/helix-term/src/ui/picker.rs @@ -32,7 +32,7 @@ use std::{ borrow::Cow, collections::HashMap, io::Read, - path::{Path, PathBuf}, + path::Path, sync::{ atomic::{self, AtomicUsize}, Arc, @@ -63,26 +63,12 @@ pub const MAX_FILE_SIZE_FOR_PREVIEW: u64 = 10 * 1024 * 1024; #[derive(PartialEq, Eq, Hash)] pub enum PathOrId<'a> { Id(DocumentId), - // See [PathOrId::from_path_buf]: this will eventually become `Path(&Path)`. - Path(Cow<'a, Path>), -} - -impl<'a> PathOrId<'a> { - /// Creates a [PathOrId] from a PathBuf - /// - /// # Deprecated - /// The owned version of PathOrId will be removed in a future refactor - /// and replaced with `&'a Path`. See the caller of this function for - /// more details on its removal. - #[deprecated] - pub fn from_path_buf(path_buf: PathBuf) -> Self { - Self::Path(Cow::Owned(path_buf)) - } + Path(&'a Path), } impl<'a> From<&'a Path> for PathOrId<'a> { fn from(path: &'a Path) -> Self { - Self::Path(Cow::Borrowed(path)) + Self::Path(path) } } @@ -581,7 +567,6 @@ impl Picker { match path_or_id { PathOrId::Path(path) => { - let path = path.as_ref(); if let Some(doc) = editor.document_by_path(path) { return Some((Preview::EditorDocument(doc), range)); } From da2b0a74844f77ba233638c2b5a0ee2367a66871 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Thu, 8 Aug 2024 11:17:20 -0400 Subject: [PATCH 03/27] Make helix_core::Uri cheap to clone We clone this type very often in LSP pickers, for example diagnostics and symbols. We can use a single Arc in many cases to avoid the unnecessary clones. --- helix-core/src/uri.rs | 25 ++++++------------------- helix-view/src/handlers/lsp.rs | 18 +++++++++++------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/helix-core/src/uri.rs b/helix-core/src/uri.rs index ddb9fb7a8..cbe0fadda 100644 --- a/helix-core/src/uri.rs +++ b/helix-core/src/uri.rs @@ -1,15 +1,18 @@ use std::{ fmt, path::{Path, PathBuf}, + sync::Arc, }; /// A generic pointer to a file location. /// /// Currently this type only supports paths to local files. +/// +/// Cloning this type is cheap: the internal representation uses an Arc. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] #[non_exhaustive] pub enum Uri { - File(PathBuf), + File(Arc), } impl Uri { @@ -26,27 +29,11 @@ impl Uri { Self::File(path) => Some(path), } } - - pub fn as_path_buf(self) -> Option { - match self { - Self::File(path) => Some(path), - } - } } impl From for Uri { fn from(path: PathBuf) -> Self { - Self::File(path) - } -} - -impl TryFrom for PathBuf { - type Error = (); - - fn try_from(uri: Uri) -> Result { - match uri { - Uri::File(path) => Ok(path), - } + Self::File(path.into()) } } @@ -93,7 +80,7 @@ impl std::error::Error for UrlConversionError {} fn convert_url_to_uri(url: &url::Url) -> Result { if url.scheme() == "file" { url.to_file_path() - .map(|path| Uri::File(helix_stdx::path::normalize(path))) + .map(|path| Uri::File(helix_stdx::path::normalize(path).into())) .map_err(|_| UrlConversionErrorKind::UnableToConvert) } else { Err(UrlConversionErrorKind::UnsupportedScheme) diff --git a/helix-view/src/handlers/lsp.rs b/helix-view/src/handlers/lsp.rs index 6aff2e50c..1fd2289db 100644 --- a/helix-view/src/handlers/lsp.rs +++ b/helix-view/src/handlers/lsp.rs @@ -243,7 +243,7 @@ impl Editor { match op { ResourceOp::Create(op) => { let uri = Uri::try_from(&op.uri)?; - let path = uri.as_path_buf().expect("URIs are valid paths"); + let path = uri.as_path().expect("URIs are valid paths"); let ignore_if_exists = op.options.as_ref().map_or(false, |options| { !options.overwrite.unwrap_or(false) && options.ignore_if_exists.unwrap_or(false) }); @@ -255,13 +255,15 @@ impl Editor { } } - fs::write(&path, [])?; - self.language_servers.file_event_handler.file_changed(path); + fs::write(path, [])?; + self.language_servers + .file_event_handler + .file_changed(path.to_path_buf()); } } ResourceOp::Delete(op) => { let uri = Uri::try_from(&op.uri)?; - let path = uri.as_path_buf().expect("URIs are valid paths"); + let path = uri.as_path().expect("URIs are valid paths"); if path.is_dir() { let recursive = op .options @@ -270,11 +272,13 @@ impl Editor { .unwrap_or(false); if recursive { - fs::remove_dir_all(&path)? + fs::remove_dir_all(path)? } else { - fs::remove_dir(&path)? + fs::remove_dir(path)? } - self.language_servers.file_event_handler.file_changed(path); + self.language_servers + .file_event_handler + .file_changed(path.to_path_buf()); } else if path.is_file() { fs::remove_file(path)?; } From e28b0da1fb555d39d6a860211ad2e915872b6219 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:04:21 +0900 Subject: [PATCH 04/27] build(deps): bump cachix/install-nix-action from V28 to 29 (#11806) Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from V28 to 29. This release includes the previously tagged commit. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/V28...v29) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/cachix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cachix.yml b/.github/workflows/cachix.yml index 3685a7c61..5052622c5 100644 --- a/.github/workflows/cachix.yml +++ b/.github/workflows/cachix.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v4 - name: Install nix - uses: cachix/install-nix-action@V28 + uses: cachix/install-nix-action@v29 - name: Authenticate with Cachix uses: cachix/cachix-action@v15 From cb9307bb0327196b3d3d8a1b3b2c28f1791e0e76 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 1 Oct 2024 10:05:07 +0900 Subject: [PATCH 05/27] build(deps): bump the rust-dependencies group with 5 updates (#11805) Bumps the rust-dependencies group with 5 updates: | Package | From | To | | --- | --- | --- | | [once_cell](https://github.com/matklad/once_cell) | `1.19.0` | `1.20.1` | | [regex](https://github.com/rust-lang/regex) | `1.10.6` | `1.11.0` | | [tempfile](https://github.com/Stebalien/tempfile) | `3.12.0` | `3.13.0` | | [libc](https://github.com/rust-lang/libc) | `0.2.158` | `0.2.159` | | [cc](https://github.com/rust-lang/cc-rs) | `1.1.21` | `1.1.23` | Updates `once_cell` from 1.19.0 to 1.20.1 - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.19.0...v1.20.1) Updates `regex` from 1.10.6 to 1.11.0 - [Release notes](https://github.com/rust-lang/regex/releases) - [Changelog](https://github.com/rust-lang/regex/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/regex/compare/1.10.6...1.11.0) Updates `tempfile` from 3.12.0 to 3.13.0 - [Changelog](https://github.com/Stebalien/tempfile/blob/master/CHANGELOG.md) - [Commits](https://github.com/Stebalien/tempfile/compare/v3.12.0...v3.13.0) Updates `libc` from 0.2.158 to 0.2.159 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.159/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.158...0.2.159) Updates `cc` from 1.1.21 to 1.1.23 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.21...cc-v1.1.23) --- updated-dependencies: - dependency-name: once_cell dependency-type: direct:production update-type: version-update:semver-minor dependency-group: rust-dependencies - dependency-name: regex dependency-type: direct:production update-type: version-update:semver-minor dependency-group: rust-dependencies - dependency-name: tempfile dependency-type: direct:production update-type: version-update:semver-minor dependency-group: rust-dependencies - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies - dependency-name: cc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 31 +++++++++++++++++-------------- helix-core/Cargo.toml | 2 +- helix-event/Cargo.toml | 2 +- helix-loader/Cargo.toml | 4 ++-- helix-stdx/Cargo.toml | 2 +- helix-term/Cargo.toml | 6 +++--- helix-tui/Cargo.toml | 2 +- helix-vcs/Cargo.toml | 2 +- helix-view/Cargo.toml | 4 ++-- 9 files changed, 29 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5b8c87705..49a417890 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,9 +136,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "cc" -version = "1.1.21" +version = "1.1.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" +checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17" dependencies = [ "shlex", ] @@ -1609,9 +1609,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.158" +version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" +checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" [[package]] name = "libloading" @@ -1753,9 +1753,12 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" +dependencies = [ + "portable-atomic", +] [[package]] name = "open" @@ -1914,9 +1917,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.10.6" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4219d74c6b67a3654a9fbebc4b419e22126d13d2f3c4a07ee0cb61ff79a79619" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" dependencies = [ "aho-corasick", "memchr", @@ -1926,9 +1929,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -1950,9 +1953,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "ropey" @@ -2192,9 +2195,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", diff --git a/helix-core/Cargo.toml b/helix-core/Cargo.toml index bc890e007..4cd516268 100644 --- a/helix-core/Cargo.toml +++ b/helix-core/Cargo.toml @@ -32,7 +32,7 @@ unicode-width = "=0.1.12" unicode-general-category = "0.6" slotmap.workspace = true tree-sitter.workspace = true -once_cell = "1.19" +once_cell = "1.20" arc-swap = "1" regex = "1" bitflags = "2.6" diff --git a/helix-event/Cargo.toml b/helix-event/Cargo.toml index e7c877355..87e5019bd 100644 --- a/helix-event/Cargo.toml +++ b/helix-event/Cargo.toml @@ -19,7 +19,7 @@ tokio = { version = "1", features = ["rt", "rt-multi-thread", "time", "sync", "p # setup new events on initialization, hardware-lock-elision hugely benefits this case # as it essentially makes the lock entirely free as long as there is no writes parking_lot = { version = "0.12", features = ["hardware-lock-elision"] } -once_cell = "1.18" +once_cell = "1.20" anyhow = "1" log = "0.4" diff --git a/helix-loader/Cargo.toml b/helix-loader/Cargo.toml index f74829f30..26ab3f264 100644 --- a/helix-loader/Cargo.toml +++ b/helix-loader/Cargo.toml @@ -22,7 +22,7 @@ serde = { version = "1.0", features = ["derive"] } toml = "0.8" etcetera = "0.8" tree-sitter.workspace = true -once_cell = "1.19" +once_cell = "1.20" log = "0.4" # TODO: these two should be on !wasm32 only @@ -30,7 +30,7 @@ log = "0.4" # cloning/compiling tree-sitter grammars cc = { version = "1" } threadpool = { version = "1.0" } -tempfile = "3.12.0" +tempfile = "3.13.0" dunce = "1.0.5" [target.'cfg(not(target_arch = "wasm32"))'.dependencies] diff --git a/helix-stdx/Cargo.toml b/helix-stdx/Cargo.toml index 1c0d06ab1..25c0a164d 100644 --- a/helix-stdx/Cargo.toml +++ b/helix-stdx/Cargo.toml @@ -26,4 +26,4 @@ windows-sys = { version = "0.59", features = ["Win32_Foundation", "Win32_Securit rustix = { version = "0.38", features = ["fs"] } [dev-dependencies] -tempfile = "3.12" +tempfile = "3.13" diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml index c66aa0621..b14d3d3c5 100644 --- a/helix-term/Cargo.toml +++ b/helix-term/Cargo.toml @@ -33,7 +33,7 @@ helix-vcs = { path = "../helix-vcs" } helix-loader = { path = "../helix-loader" } anyhow = "1" -once_cell = "1.19" +once_cell = "1.20" tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std", "time", "process", "macros", "fs", "parking_lot"] } tui = { path = "../helix-tui", package = "helix-tui", default-features = false, features = ["crossterm"] } @@ -74,7 +74,7 @@ grep-searcher = "0.1.14" [target.'cfg(not(windows))'.dependencies] # https://github.com/vorner/signal-hook/issues/100 signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] } -libc = "0.2.158" +libc = "0.2.159" [target.'cfg(target_os = "macos")'.dependencies] crossterm = { version = "0.28", features = ["event-stream", "use-dev-tty", "libc"] } @@ -85,5 +85,5 @@ helix-loader = { path = "../helix-loader" } [dev-dependencies] smallvec = "1.13" indoc = "2.0.5" -tempfile = "3.12.0" +tempfile = "3.13.0" same-file = "1.0.1" diff --git a/helix-tui/Cargo.toml b/helix-tui/Cargo.toml index a349623b1..96f008a01 100644 --- a/helix-tui/Cargo.toml +++ b/helix-tui/Cargo.toml @@ -24,5 +24,5 @@ unicode-segmentation = "1.12" crossterm = { version = "0.28", optional = true } termini = "1.0" serde = { version = "1", "optional" = true, features = ["derive"]} -once_cell = "1.19" +once_cell = "1.20" log = "~0.4" diff --git a/helix-vcs/Cargo.toml b/helix-vcs/Cargo.toml index 245fdb8dc..43d5d619b 100644 --- a/helix-vcs/Cargo.toml +++ b/helix-vcs/Cargo.toml @@ -29,4 +29,4 @@ log = "0.4" git = ["gix"] [dev-dependencies] -tempfile = "3.12" +tempfile = "3.13" diff --git a/helix-view/Cargo.toml b/helix-view/Cargo.toml index ddfa9f7e4..725a77547 100644 --- a/helix-view/Cargo.toml +++ b/helix-view/Cargo.toml @@ -28,10 +28,10 @@ bitflags = "2.6" anyhow = "1" crossterm = { version = "0.28", optional = true } -tempfile = "3.12" +tempfile = "3.13" # Conversion traits -once_cell = "1.19" +once_cell = "1.20" url = "2.5.2" arc-swap = { version = "1.7.1" } From 083bb0118fd24bba897ac351534637196cafb40a Mon Sep 17 00:00:00 2001 From: Akseli Date: Tue, 1 Oct 2024 04:05:28 +0300 Subject: [PATCH 06/27] Fix some odin highlights (#11804) Some of the odin highlights seemed wrong or lacking, like the import names were not being matched: ```odin // color both "rl" here to same value import rl "vendor:raylib" ... rl.Vector3 ``` Import color was also not being used correctly --- runtime/queries/odin/highlights.scm | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/runtime/queries/odin/highlights.scm b/runtime/queries/odin/highlights.scm index bdc4c1290..ed302cdbf 100644 --- a/runtime/queries/odin/highlights.scm +++ b/runtime/queries/odin/highlights.scm @@ -4,10 +4,13 @@ ] @keyword.directive [ - "import" - "package" + "package" ] @namespace +[ + "import" +] @keyword.control.import + [ "foreign" "using" @@ -200,7 +203,7 @@ (struct . (identifier) @type) -(field_type . (identifier) "." (identifier) @type) +(field_type . (identifier) @keyword.storage.type "." (identifier) @type) (bit_set_type (identifier) @type ";") @@ -248,6 +251,8 @@ (using_statement (identifier) @namespace) +(import_declaration (identifier) @keyword.storage.type) + ; Parameters (parameter (identifier) @variable.parameter ":" "="? (identifier)? @constant) From 57ec3b7330de3f5a7b37e766a758f13fdf3c0da5 Mon Sep 17 00:00:00 2001 From: Ian Hobson Date: Tue, 1 Oct 2024 03:05:45 +0200 Subject: [PATCH 07/27] Add a highlight for the keyword.storage scope to the onedark theme (#11802) Rust highlight queries make use of keyword.storage for keywords like `struct`, `enum`, and also for modifiers like `mut` and `ref`. Using a color that's different to the one used for `"variable.parameter"` (red) improves differentiation for mutable function arguments. --- runtime/themes/onedark.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/runtime/themes/onedark.toml b/runtime/themes/onedark.toml index 7cdeac095..818b8c946 100644 --- a/runtime/themes/onedark.toml +++ b/runtime/themes/onedark.toml @@ -15,6 +15,7 @@ "keyword.control" = { fg = "purple" } "keyword.control.import" = { fg = "red" } "keyword.directive" = { fg = "purple" } +"keyword.storage" = { fg = "purple" } "label" = { fg = "purple" } "namespace" = { fg = "blue" } "operator" = { fg = "purple" } From 02b6f1488a4a1438b268f87d96c474a946ea3e5e Mon Sep 17 00:00:00 2001 From: Skyler Hawthorne Date: Thu, 3 Oct 2024 13:08:06 -0400 Subject: [PATCH 08/27] fix git repo detection on symlinks (#11732) --- helix-vcs/src/git.rs | 14 +++++++++--- helix-vcs/src/git/test.rs | 45 +++++++++++++++++++++++++++++++++------ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/helix-vcs/src/git.rs b/helix-vcs/src/git.rs index 78e582436..48220f4df 100644 --- a/helix-vcs/src/git.rs +++ b/helix-vcs/src/git.rs @@ -22,18 +22,24 @@ use crate::FileChange; #[cfg(test)] mod test; +#[inline] +fn get_repo_dir(file: &Path) -> Result<&Path> { + file.parent().context("file has no parent directory") +} + pub fn get_diff_base(file: &Path) -> Result> { debug_assert!(!file.exists() || file.is_file()); debug_assert!(file.is_absolute()); + let file = gix::path::realpath(file).context("resolve symlinks")?; // TODO cache repository lookup - let repo_dir = file.parent().context("file has no parent directory")?; + let repo_dir = get_repo_dir(&file)?; let repo = open_repo(repo_dir) .context("failed to open git repo")? .to_thread_local(); let head = repo.head_commit()?; - let file_oid = find_file_in_commit(&repo, &head, file)?; + let file_oid = find_file_in_commit(&repo, &head, &file)?; let file_object = repo.find_object(file_oid)?; let data = file_object.detach().data; @@ -56,7 +62,9 @@ pub fn get_diff_base(file: &Path) -> Result> { pub fn get_current_head_name(file: &Path) -> Result>>> { debug_assert!(!file.exists() || file.is_file()); debug_assert!(file.is_absolute()); - let repo_dir = file.parent().context("file has no parent directory")?; + let file = gix::path::realpath(file).context("resolve symlinks")?; + + let repo_dir = get_repo_dir(&file)?; let repo = open_repo(repo_dir) .context("failed to open git repo")? .to_thread_local(); diff --git a/helix-vcs/src/git/test.rs b/helix-vcs/src/git/test.rs index 95ff10b23..164040f50 100644 --- a/helix-vcs/src/git/test.rs +++ b/helix-vcs/src/git/test.rs @@ -98,9 +98,13 @@ fn directory() { assert!(git::get_diff_base(&dir).is_err()); } -/// Test that `get_file_head` does not return content for a symlink. -/// This is important to correctly cover cases where a symlink is removed and replaced by a file. -/// If the contents of the symlink object were returned a diff between a path and the actual file would be produced (bad ui). +/// Test that `get_diff_base` resolves symlinks so that the same diff base is +/// used as the target file. +/// +/// This is important to correctly cover cases where a symlink is removed and +/// replaced by a file. If the contents of the symlink object were returned +/// a diff between a literal file path and the actual file content would be +/// produced (bad ui). #[cfg(any(unix, windows))] #[test] fn symlink() { @@ -108,14 +112,41 @@ fn symlink() { use std::os::unix::fs::symlink; #[cfg(not(unix))] use std::os::windows::fs::symlink_file as symlink; + let temp_git = empty_git_repo(); let file = temp_git.path().join("file.txt"); - let contents = b"foo".as_slice(); - File::create(&file).unwrap().write_all(contents).unwrap(); + let contents = Vec::from(b"foo"); + File::create(&file).unwrap().write_all(&contents).unwrap(); let file_link = temp_git.path().join("file_link.txt"); + symlink("file.txt", &file_link).unwrap(); + create_commit(temp_git.path(), true); + + assert_eq!(git::get_diff_base(&file_link).unwrap(), contents); + assert_eq!(git::get_diff_base(&file).unwrap(), contents); +} + +/// Test that `get_diff_base` returns content when the file is a symlink to +/// another file that is in a git repo, but the symlink itself is not. +#[cfg(any(unix, windows))] +#[test] +fn symlink_to_git_repo() { + #[cfg(unix)] + use std::os::unix::fs::symlink; + #[cfg(not(unix))] + use std::os::windows::fs::symlink_file as symlink; + + let temp_dir = tempfile::tempdir().expect("create temp dir"); + let temp_git = empty_git_repo(); + let file = temp_git.path().join("file.txt"); + let contents = Vec::from(b"foo"); + File::create(&file).unwrap().write_all(&contents).unwrap(); create_commit(temp_git.path(), true); - assert!(git::get_diff_base(&file_link).is_err()); - assert_eq!(git::get_diff_base(&file).unwrap(), Vec::from(contents)); + + let file_link = temp_dir.path().join("file_link.txt"); + symlink(&file, &file_link).unwrap(); + + assert_eq!(git::get_diff_base(&file_link).unwrap(), contents); + assert_eq!(git::get_diff_base(&file).unwrap(), contents); } From f6d39cbc1d8945d69c550994498fa9498f862bc2 Mon Sep 17 00:00:00 2001 From: RoloEdits Date: Sun, 6 Oct 2024 06:54:17 -0700 Subject: [PATCH 09/27] refactor(lsp): handle out-of-range `active_signature` (#11825) --- helix-term/src/ui/lsp.rs | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/helix-term/src/ui/lsp.rs b/helix-term/src/ui/lsp.rs index b6491085b..488626305 100644 --- a/helix-term/src/ui/lsp.rs +++ b/helix-term/src/ui/lsp.rs @@ -96,7 +96,10 @@ impl Component for SignatureHelp { fn render(&mut self, area: Rect, surface: &mut Buffer, cx: &mut Context) { let margin = Margin::horizontal(1); - let signature = &self.signatures[self.active_signature]; + let signature = self + .signatures + .get(self.active_signature) + .unwrap_or_else(|| &self.signatures[0]); let active_param_span = signature.active_param_range.map(|(start, end)| { vec![( @@ -108,9 +111,13 @@ impl Component for SignatureHelp { )] }); - let sig = &self.signatures[self.active_signature]; + let signature = self + .signatures + .get(self.active_signature) + .unwrap_or_else(|| &self.signatures[0]); + let sig_text = crate::ui::markdown::highlighted_code_block( - sig.signature.as_str(), + signature.signature.as_str(), &self.language, Some(&cx.editor.theme), Arc::clone(&self.config_loader), @@ -130,7 +137,7 @@ impl Component for SignatureHelp { let sig_text_para = Paragraph::new(&sig_text).wrap(Wrap { trim: false }); sig_text_para.render(sig_text_area, surface); - if sig.signature_doc.is_none() { + if signature.signature_doc.is_none() { return; } @@ -142,7 +149,7 @@ impl Component for SignatureHelp { } } - let sig_doc = match &sig.signature_doc { + let sig_doc = match &signature.signature_doc { None => return, Some(doc) => Markdown::new(doc.clone(), Arc::clone(&self.config_loader)), }; @@ -160,12 +167,15 @@ impl Component for SignatureHelp { const PADDING: u16 = 2; const SEPARATOR_HEIGHT: u16 = 1; - let sig = &self.signatures[self.active_signature]; + let signature = self + .signatures + .get(self.active_signature) + .unwrap_or_else(|| &self.signatures[0]); let max_text_width = viewport.0.saturating_sub(PADDING).clamp(10, 120); let signature_text = crate::ui::markdown::highlighted_code_block( - sig.signature.as_str(), + signature.signature.as_str(), &self.language, None, Arc::clone(&self.config_loader), @@ -174,7 +184,7 @@ impl Component for SignatureHelp { let (sig_width, sig_height) = crate::ui::text::required_size(&signature_text, max_text_width); - let (width, height) = match sig.signature_doc { + let (width, height) = match signature.signature_doc { Some(ref doc) => { let doc_md = Markdown::new(doc.clone(), Arc::clone(&self.config_loader)); let doc_text = doc_md.parse(None); From 048973fc552fd8ccc7a8060d07b1078b7f090824 Mon Sep 17 00:00:00 2001 From: Christopher Kaster Date: Sun, 6 Oct 2024 21:53:12 +0200 Subject: [PATCH 10/27] Add support for dune project language (#11829) --- book/src/generated/lang-support.md | 1 + languages.toml | 17 +++++++++++++++++ runtime/queries/dune/highlights.scm | 1 + 3 files changed, 19 insertions(+) create mode 100644 runtime/queries/dune/highlights.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 79f3a6964..c5f79aa29 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -39,6 +39,7 @@ | dockerfile | ✓ | ✓ | | `docker-langserver` | | dot | ✓ | | | `dot-language-server` | | dtd | ✓ | | | | +| dune | ✓ | | | | | earthfile | ✓ | ✓ | ✓ | `earthlyls` | | edoc | ✓ | | | | | eex | ✓ | | | | diff --git a/languages.toml b/languages.toml index 806aa815e..9be8a0170 100644 --- a/languages.toml +++ b/languages.toml @@ -1243,6 +1243,23 @@ indent = { tab-width = 2, unit = " " } name = "ocaml-interface" source = { git = "https://github.com/tree-sitter/tree-sitter-ocaml", rev = "9965d208337d88bbf1a38ad0b0fe49e5f5ec9677", subpath = "interface" } +[[language]] +name = "dune" +scope = "source.dune" +roots = ["dune-project"] +file-types = [{ glob = "dune-project" }, { glob = "dune" }] +comment-token = ";" +indent = { tab-width = 1, unit = " " } +grammar = "scheme" +auto-format = true +formatter = { command = "dune", args = ["format-dune-file"] } + +[language.auto-pairs] +'(' = ')' +'{' = '}' +'[' = ']' +'"' = '"' + [[language]] name = "lua" injection-regex = "lua" diff --git a/runtime/queries/dune/highlights.scm b/runtime/queries/dune/highlights.scm new file mode 100644 index 000000000..e11eb7881 --- /dev/null +++ b/runtime/queries/dune/highlights.scm @@ -0,0 +1 @@ +; inherits: scheme From f55f1f8b439143309bff66a171fd8124d5df1c4d Mon Sep 17 00:00:00 2001 From: rhogenson <05huvhec@duck.com> Date: Sun, 6 Oct 2024 19:56:54 -0700 Subject: [PATCH 11/27] Remove auto-pair for single quote in SML. (#11838) Similar to OCaml and other ML languages, single quote is a normal character that can appear in identifiers and is also used in type parameters. It is not used for strings or character literals, which both use double quote. Co-authored-by: Rose Hogenson --- languages.toml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/languages.toml b/languages.toml index 9be8a0170..72b976dd0 100644 --- a/languages.toml +++ b/languages.toml @@ -2482,6 +2482,12 @@ injection-regex = "sml" file-types = ["sml"] block-comment-tokens = { start = "(*", end = "*)" } +[language.auto-pairs] +'(' = ')' +'{' = '}' +'[' = ']' +'"' = '"' + [[grammar]] name = "sml" source = { git = "https://github.com/Giorbo/tree-sitter-sml", rev = "bd4055d5554614520d4a0706b34dc0c317c6b608" } From 761f70d61179f38152e76c1f224589a53b62d00f Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:23:36 +0900 Subject: [PATCH 12/27] build(deps): bump cachix/install-nix-action from 29 to 30 (#11852) Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 29 to 30. - [Release notes](https://github.com/cachix/install-nix-action/releases) - [Commits](https://github.com/cachix/install-nix-action/compare/v29...v30) --- updated-dependencies: - dependency-name: cachix/install-nix-action dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/cachix.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/cachix.yml b/.github/workflows/cachix.yml index 5052622c5..9a25cbe45 100644 --- a/.github/workflows/cachix.yml +++ b/.github/workflows/cachix.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v4 - name: Install nix - uses: cachix/install-nix-action@v29 + uses: cachix/install-nix-action@v30 - name: Authenticate with Cachix uses: cachix/cachix-action@v15 From a7651f5bf027ec98645d571ab05a685d97e1b772 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 11 Oct 2024 16:38:21 +0900 Subject: [PATCH 13/27] build(deps): bump the rust-dependencies group with 4 updates (#11850) Bumps the rust-dependencies group with 4 updates: [once_cell](https://github.com/matklad/once_cell), [futures-util](https://github.com/rust-lang/futures-rs), [futures-executor](https://github.com/rust-lang/futures-rs) and [cc](https://github.com/rust-lang/cc-rs). Updates `once_cell` from 1.20.1 to 1.20.2 - [Changelog](https://github.com/matklad/once_cell/blob/master/CHANGELOG.md) - [Commits](https://github.com/matklad/once_cell/compare/v1.20.1...v1.20.2) Updates `futures-util` from 0.3.30 to 0.3.31 - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.30...0.3.31) Updates `futures-executor` from 0.3.30 to 0.3.31 - [Release notes](https://github.com/rust-lang/futures-rs/releases) - [Changelog](https://github.com/rust-lang/futures-rs/blob/master/CHANGELOG.md) - [Commits](https://github.com/rust-lang/futures-rs/compare/0.3.30...0.3.31) Updates `cc` from 1.1.23 to 1.1.28 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.23...cc-v1.1.28) --- updated-dependencies: - dependency-name: once_cell dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies - dependency-name: futures-util dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies - dependency-name: futures-executor dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies - dependency-name: cc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 27 ++++++++++++--------------- helix-event/Cargo.toml | 2 +- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 49a417890..e622fbe59 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,9 +136,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "cc" -version = "1.1.23" +version = "1.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3bbb537bb4a30b90362caddba8f360c0a56bc13d3a5570028e7197204cb54a17" +checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" dependencies = [ "shlex", ] @@ -412,15 +412,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -429,15 +429,15 @@ dependencies = [ [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-core", "futures-task", @@ -1753,12 +1753,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.20.1" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82881c4be219ab5faaf2ad5e5e5ecdff8c66bd7402ca3160975c93b24961afd1" -dependencies = [ - "portable-atomic", -] +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "open" diff --git a/helix-event/Cargo.toml b/helix-event/Cargo.toml index 87e5019bd..ee4038e69 100644 --- a/helix-event/Cargo.toml +++ b/helix-event/Cargo.toml @@ -23,7 +23,7 @@ once_cell = "1.20" anyhow = "1" log = "0.4" -futures-executor = "0.3.28" +futures-executor = "0.3.31" [features] integration_test = [] From e4f3483bd19b51ea7b80925b841f399d7eb411bb Mon Sep 17 00:00:00 2001 From: Dmitry Marakasov Date: Tue, 15 Oct 2024 19:52:50 +0300 Subject: [PATCH 14/27] Fix repology badge (#11895) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 90ebc9d16..11a909b26 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ Note: Only certain languages have indentation definitions at the moment. Check [Installation documentation](https://docs.helix-editor.com/install.html). -[![Packaging status](https://repology.org/badge/vertical-allrepos/helix.svg?exclude_unsupported=1)](https://repology.org/project/helix/versions) +[![Packaging status](https://repology.org/badge/vertical-allrepos/helix-editor.svg?exclude_unsupported=1)](https://repology.org/project/helix-editor/versions) # Contributing From f2d54db24f8582a302fc21e64ed82be5d99a9aaa Mon Sep 17 00:00:00 2001 From: David Else <12832280+David-Else@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:53:59 +0100 Subject: [PATCH 15/27] Update repology URL after change from helix to helix-editor (#11877) * Update repology URL after change from helix to helix-editor * Update book/src/package-managers.md Co-authored-by: Michael Davis --------- Co-authored-by: Michael Davis --- book/src/package-managers.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/book/src/package-managers.md b/book/src/package-managers.md index 3cfd31003..441de45e0 100644 --- a/book/src/package-managers.md +++ b/book/src/package-managers.md @@ -17,7 +17,7 @@ - [Chocolatey](#chocolatey) - [MSYS2](#msys2) -[![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-editor.svg)](https://repology.org/project/helix-editor/versions) ## Linux From d1b8129491124ce6068e95ccc58a7fefb1c9db45 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 16 Oct 2024 17:52:14 +0900 Subject: [PATCH 16/27] build(deps): bump cc in the rust-dependencies group (#11890) Bumps the rust-dependencies group with 1 update: [cc](https://github.com/rust-lang/cc-rs). Updates `cc` from 1.1.28 to 1.1.30 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.28...cc-v1.1.30) --- updated-dependencies: - dependency-name: cc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e622fbe59..92795e743 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -136,9 +136,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "cc" -version = "1.1.28" +version = "1.1.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e80e3b6a3ab07840e1cae9b0666a63970dc28e8ed5ffbcdacbfc760c281bfc1" +checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" dependencies = [ "shlex", ] From 1437ba1e5a9e3c89b03a608cd24177c56b9cba15 Mon Sep 17 00:00:00 2001 From: langurmonkey Date: Fri, 18 Oct 2024 04:17:25 +0200 Subject: [PATCH 17/27] Add glsl_analyzer as default language server for GLSL (#11891) * Add glsl_analyzer as default language server for GLSL * Generate docs --- book/src/generated/lang-support.md | 2 +- languages.toml | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index c5f79aa29..aac1e4746 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -69,7 +69,7 @@ | gjs | ✓ | ✓ | ✓ | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` | | gleam | ✓ | ✓ | | `gleam` | | glimmer | ✓ | | | `ember-language-server` | -| glsl | ✓ | ✓ | ✓ | | +| glsl | ✓ | ✓ | ✓ | `glsl_analyzer` | | gn | ✓ | | | | | go | ✓ | ✓ | ✓ | `gopls`, `golangci-lint-langserver` | | godot-resource | ✓ | ✓ | | | diff --git a/languages.toml b/languages.toml index 72b976dd0..898500ae6 100644 --- a/languages.toml +++ b/languages.toml @@ -41,6 +41,7 @@ forth-lsp = { command = "forth-lsp" } fortls = { command = "fortls", args = ["--lowercase_intrinsics"] } fsharp-ls = { command = "fsautocomplete", config = { AutomaticWorkspaceInit = true } } gleam = { command = "gleam", args = ["lsp"] } +glsl_analyzer = { command = "glsl_analyzer" } graphql-language-service = { command = "graphql-lsp", args = ["server", "-m", "stream"] } haskell-language-server = { command = "haskell-language-server-wrapper", args = ["--lsp"] } idris2-lsp = { command = "idris2-lsp" } @@ -1452,6 +1453,7 @@ file-types = ["glsl", "vert", "tesc", "tese", "geom", "frag", "comp" ] comment-token = "//" block-comment-tokens = { start = "/*", end = "*/" } indent = { tab-width = 4, unit = " " } +language-servers = [ "glsl_analyzer" ] injection-regex = "glsl" [[grammar]] From 5ab1f1eb5adb1abf7dfb899a49ad39aacab7edc5 Mon Sep 17 00:00:00 2001 From: "Ivan B." <6987136+bastaynav@users.noreply.github.com> Date: Fri, 18 Oct 2024 07:08:54 +0300 Subject: [PATCH 18/27] docs(themes): place `ui.highlight.frameline` and `ui.highlight` together (#11896) * docs(themes): place `ui.highlight.frameline` and `ui.highlight` together * docs(themes): small fix --- book/src/themes.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/themes.md b/book/src/themes.md index 1bc2627dd..4e0142ddd 100644 --- a/book/src/themes.md +++ b/book/src/themes.md @@ -283,7 +283,6 @@ These scopes are used for theming the editor interface: | `ui.debug.active` | Indicator for the line at which debugging execution is paused at, found in the gutter | | `ui.gutter` | Gutter | | `ui.gutter.selected` | Gutter for the line the cursor is on | -| `ui.highlight.frameline` | Line at which debugging execution is paused at | | `ui.linenr` | Line numbers | | `ui.linenr.selected` | Line number for the line the cursor is on | | `ui.statusline` | Statusline | @@ -297,7 +296,7 @@ These scopes are used for theming the editor interface: | `ui.bufferline.background` | Style for bufferline background | | `ui.popup` | Documentation popups (e.g. Space + k) | | `ui.popup.info` | Prompt for multiple key options | -| `ui.picker.header` | Header row area in pickers with multiple columns | +| `ui.picker.header` | Header row area in pickers with multiple columns | | `ui.picker.header.column` | Column names in pickers with multiple columns | | `ui.picker.header.column.active` | The column name in pickers with multiple columns where the cursor is entering into. | | `ui.window` | Borderlines separating splits | @@ -320,6 +319,7 @@ These scopes are used for theming the editor interface: | `ui.selection` | For selections in the editing area | | `ui.selection.primary` | | | `ui.highlight` | Highlighted lines in the picker preview | +| `ui.highlight.frameline` | Line at which debugging execution is paused at | | `ui.cursorline.primary` | The line of the primary cursor ([if cursorline is enabled][editor-section]) | | `ui.cursorline.secondary` | The lines of any other cursors ([if cursorline is enabled][editor-section]) | | `ui.cursorcolumn.primary` | The column of the primary cursor ([if cursorcolumn is enabled][editor-section]) | From 855a43a266bec808b2dd06ca5a2e84326890eaea Mon Sep 17 00:00:00 2001 From: karei Date: Fri, 18 Oct 2024 07:09:11 +0300 Subject: [PATCH 19/27] Bump `jjdescription` grammar revision (#11857) --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index 898500ae6..8ade3cf8b 100644 --- a/languages.toml +++ b/languages.toml @@ -3272,7 +3272,7 @@ text-width = 72 [[grammar]] name = "jjdescription" -source = { git = "https://github.com/kareigu/tree-sitter-jjdescription", rev = "2ddec6cad07b366aee276a608e1daa2c29d3caf2" } +source = { git = "https://github.com/kareigu/tree-sitter-jjdescription", rev = "23dd3dd18ee29bdd761642511aa314215801afd8" } [[language]] name = "jq" From a1453350df5ecf9cb9a8a6cb9293e56f85cf5e5a Mon Sep 17 00:00:00 2001 From: Sebastian Dall <80460441+SebastianDall@users.noreply.github.com> Date: Fri, 18 Oct 2024 23:12:36 +0200 Subject: [PATCH 20/27] Adding snakemake to language (#11858) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * feat: snakemake language * feat: snakemake syntax highlighting * doc: xtask docgen - snakemake * Addressed feedback: removed redundant grammar * fixed indentation * removed has-ancestor predicate --------- Co-authored-by: “SebastianDall” <“semoda@bio.auu.dk”> --- book/src/generated/lang-support.md | 1 + languages.toml | 14 +++++ runtime/queries/snakemake/LICENSE | 20 +++++++ runtime/queries/snakemake/folds.scm | 8 +++ runtime/queries/snakemake/highlights.scm | 76 ++++++++++++++++++++++++ runtime/queries/snakemake/indents.scm | 27 +++++++++ runtime/queries/snakemake/injections.scm | 5 ++ runtime/queries/snakemake/locals.scm | 1 + 8 files changed, 152 insertions(+) create mode 100755 runtime/queries/snakemake/LICENSE create mode 100755 runtime/queries/snakemake/folds.scm create mode 100755 runtime/queries/snakemake/highlights.scm create mode 100755 runtime/queries/snakemake/indents.scm create mode 100755 runtime/queries/snakemake/injections.scm create mode 100755 runtime/queries/snakemake/locals.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index aac1e4746..4f9b64de0 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -186,6 +186,7 @@ | smali | ✓ | | ✓ | | | smithy | ✓ | | | `cs` | | sml | ✓ | | | | +| snakemake | ✓ | | ✓ | `pylsp` | | solidity | ✓ | ✓ | | `solc` | | spicedb | ✓ | | | | | sql | ✓ | ✓ | | | diff --git a/languages.toml b/languages.toml index 8ade3cf8b..57d220b61 100644 --- a/languages.toml +++ b/languages.toml @@ -3835,3 +3835,17 @@ language-servers = ["circom-lsp"] [[grammar]] name = "circom" source = { git = "https://github.com/Decurity/tree-sitter-circom", rev = "02150524228b1e6afef96949f2d6b7cc0aaf999e" } + +[[language]] +name = "snakemake" +scope = "source.snakemake" +roots = ["Snakefile", "config.yaml", "environment.yaml", "workflow/"] +file-types = ["smk", "Snakefile"] +comment-tokens = ["#", "##"] +indent = { tab-width = 2, unit = " " } +language-servers = ["pylsp" ] + + +[[grammar]] +name = "snakemake" +source = { git = "https://github.com/osthomas/tree-sitter-snakemake", rev = "e909815acdbe37e69440261ebb1091ed52e1dec6" } diff --git a/runtime/queries/snakemake/LICENSE b/runtime/queries/snakemake/LICENSE new file mode 100755 index 000000000..3dea16274 --- /dev/null +++ b/runtime/queries/snakemake/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2016 Max Brunsfeld +Copyright (c) 2023 Oliver Thomas + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/runtime/queries/snakemake/folds.scm b/runtime/queries/snakemake/folds.scm new file mode 100755 index 000000000..d154f3cde --- /dev/null +++ b/runtime/queries/snakemake/folds.scm @@ -0,0 +1,8 @@ +; inherits: python + +[ + (rule_definition) + (rule_inheritance) + (module_definition) + (checkpoint_definition) +] @fold diff --git a/runtime/queries/snakemake/highlights.scm b/runtime/queries/snakemake/highlights.scm new file mode 100755 index 000000000..18d81811f --- /dev/null +++ b/runtime/queries/snakemake/highlights.scm @@ -0,0 +1,76 @@ +; inherits: python + +; Compound directives +[ + "rule" + "checkpoint" + "module" +] @keyword + +; Top level directives (eg. configfile, include) +(module + (directive + name: _ @keyword)) + +; Subordinate directives (eg. input, output) +((_) + body: (_ + (directive + name: _ @label))) + +; rule/module/checkpoint names +(rule_definition + name: (identifier) @type) + +(module_definition + name: (identifier) @type) + +(checkpoint_definition + name: (identifier) @type) + +; Rule imports +(rule_import + "use" @keyword.import + "rule" @keyword.import + "from" @keyword.import + "exclude"? @keyword.import + "as"? @keyword.import + "with"? @keyword.import) + +; Rule inheritance +(rule_inheritance + "use" @keyword + "rule" @keyword + "with" @keyword) + +; Wildcard names +(wildcard (identifier) @variable) +(wildcard (flag) @variable.parameter.builtin) + +; builtin variables +((identifier) @variable.builtin + (#any-of? @variable.builtin "checkpoints" "config" "gather" "rules" "scatter" "workflow")) + +; References to directive labels in wildcard interpolations +; the #any-of? queries are moved above the #has-ancestor? queries to +; short-circuit the potentially expensive tree traversal, if possible +; see: +; https://github.com/nvim-treesitter/nvim-treesitter/pull/4302#issuecomment-1685789790 +; directive labels in wildcard context +((wildcard + (identifier) @label) + (#any-of? @label "input" "log" "output" "params" "resources" "threads" "wildcards")) + +((wildcard + (attribute + object: (identifier) @label)) + (#any-of? @label "input" "log" "output" "params" "resources" "threads" "wildcards")) + +((wildcard + (subscript + value: (identifier) @label)) + (#any-of? @label "input" "log" "output" "params" "resources" "threads" "wildcards")) + +; directive labels in block context (eg. within 'run:') +((identifier) @label + (#any-of? @label "input" "log" "output" "params" "resources" "threads" "wildcards")) diff --git a/runtime/queries/snakemake/indents.scm b/runtime/queries/snakemake/indents.scm new file mode 100755 index 000000000..6685fccb1 --- /dev/null +++ b/runtime/queries/snakemake/indents.scm @@ -0,0 +1,27 @@ +; inherits: python + + +[ + (rule_definition) + (checkpoint_definition) + (rule_inheritance) + (module_definition) +] @indent + +[ + (rule_definition) + (checkpoint_definition) + (rule_inheritance) + (module_definition) +] @extend + + +(directive) @indent +(directive) @extend + +(rule_import + "with" + ":") @indent +(rule_import + "with" + ":") @extend diff --git a/runtime/queries/snakemake/injections.scm b/runtime/queries/snakemake/injections.scm new file mode 100755 index 000000000..fa56daabb --- /dev/null +++ b/runtime/queries/snakemake/injections.scm @@ -0,0 +1,5 @@ +; inherits: python + +(wildcard + (constraint) @injection.content + (#set! injection.language "regex")) diff --git a/runtime/queries/snakemake/locals.scm b/runtime/queries/snakemake/locals.scm new file mode 100755 index 000000000..0b920cbf9 --- /dev/null +++ b/runtime/queries/snakemake/locals.scm @@ -0,0 +1 @@ +; inherits: python From be2884d80061493ab1999d73ffa51dfb4f59639d Mon Sep 17 00:00:00 2001 From: TornaxO7 Date: Sat, 19 Oct 2024 11:48:07 +0200 Subject: [PATCH 21/27] Continue line comments (#10996) --- helix-core/src/comment.rs | 169 +++++++++++++++++++++++++++---------- helix-term/src/commands.rs | 97 +++++++++++++++------ 2 files changed, 192 insertions(+), 74 deletions(-) diff --git a/helix-core/src/comment.rs b/helix-core/src/comment.rs index 536b710ab..427021874 100644 --- a/helix-core/src/comment.rs +++ b/helix-core/src/comment.rs @@ -9,6 +9,24 @@ use crate::{ use helix_stdx::rope::RopeSliceExt; use std::borrow::Cow; +pub const DEFAULT_COMMENT_TOKEN: &str = "//"; + +/// Returns the longest matching comment token of the given line (if it exists). +pub fn get_comment_token<'a, S: AsRef>( + text: RopeSlice, + tokens: &'a [S], + line_num: usize, +) -> Option<&'a str> { + let line = text.line(line_num); + let start = line.first_non_whitespace_char()?; + + tokens + .iter() + .map(AsRef::as_ref) + .filter(|token| line.slice(start..).starts_with(token)) + .max_by_key(|token| token.len()) +} + /// Given text, a comment token, and a set of line indices, returns the following: /// - Whether the given lines should be considered commented /// - If any of the lines are uncommented, all lines are considered as such. @@ -28,21 +46,20 @@ fn find_line_comment( let mut min = usize::MAX; // minimum col for first_non_whitespace_char let mut margin = 1; let token_len = token.chars().count(); + for line in lines { let line_slice = text.line(line); if let Some(pos) = line_slice.first_non_whitespace_char() { let len = line_slice.len_chars(); - if pos < min { - min = pos; - } + min = std::cmp::min(min, pos); // line can be shorter than pos + token len let fragment = Cow::from(line_slice.slice(pos..std::cmp::min(pos + token.len(), len))); + // as soon as one of the non-blank lines doesn't have a comment, the whole block is + // considered uncommented. if fragment != token { - // as soon as one of the non-blank lines doesn't have a comment, the whole block is - // considered uncommented. commented = false; } @@ -56,6 +73,7 @@ fn find_line_comment( to_change.push(line); } } + (commented, to_change, min, margin) } @@ -63,7 +81,7 @@ fn find_line_comment( pub fn toggle_line_comments(doc: &Rope, selection: &Selection, token: Option<&str>) -> Transaction { let text = doc.slice(..); - let token = token.unwrap_or("//"); + let token = token.unwrap_or(DEFAULT_COMMENT_TOKEN); let comment = Tendril::from(format!("{} ", token)); let mut lines: Vec = Vec::with_capacity(selection.len()); @@ -317,56 +335,87 @@ pub fn split_lines_of_selection(text: RopeSlice, selection: &Selection) -> Selec mod test { use super::*; - #[test] - fn test_find_line_comment() { - // four lines, two space indented, except for line 1 which is blank. - let mut doc = Rope::from(" 1\n\n 2\n 3"); - // select whole document - let mut selection = Selection::single(0, doc.len_chars() - 1); + mod find_line_comment { + use super::*; - let text = doc.slice(..); + #[test] + fn not_commented() { + // four lines, two space indented, except for line 1 which is blank. + let doc = Rope::from(" 1\n\n 2\n 3"); - let res = find_line_comment("//", text, 0..3); - // (commented = true, to_change = [line 0, line 2], min = col 2, margin = 0) - assert_eq!(res, (false, vec![0, 2], 2, 0)); + let text = doc.slice(..); - // comment - let transaction = toggle_line_comments(&doc, &selection, None); - transaction.apply(&mut doc); - selection = selection.map(transaction.changes()); + let res = find_line_comment("//", text, 0..3); + // (commented = false, to_change = [line 0, line 2], min = col 2, margin = 0) + assert_eq!(res, (false, vec![0, 2], 2, 0)); + } - assert_eq!(doc, " // 1\n\n // 2\n // 3"); + #[test] + fn is_commented() { + // three lines where the second line is empty. + let doc = Rope::from("// hello\n\n// there"); - // uncomment - let transaction = toggle_line_comments(&doc, &selection, None); - transaction.apply(&mut doc); - selection = selection.map(transaction.changes()); - assert_eq!(doc, " 1\n\n 2\n 3"); - assert!(selection.len() == 1); // to ignore the selection unused warning + let res = find_line_comment("//", doc.slice(..), 0..3); - // 0 margin comments - doc = Rope::from(" //1\n\n //2\n //3"); - // reset the selection. - selection = Selection::single(0, doc.len_chars() - 1); + // (commented = true, to_change = [line 0, line 2], min = col 0, margin = 1) + assert_eq!(res, (true, vec![0, 2], 0, 1)); + } + } - let transaction = toggle_line_comments(&doc, &selection, None); - transaction.apply(&mut doc); - selection = selection.map(transaction.changes()); - assert_eq!(doc, " 1\n\n 2\n 3"); - assert!(selection.len() == 1); // to ignore the selection unused warning + // TODO: account for uncommenting with uneven comment indentation + mod toggle_line_comment { + use super::*; - // 0 margin comments, with no space - doc = Rope::from("//"); - // reset the selection. - selection = Selection::single(0, doc.len_chars() - 1); + #[test] + fn comment() { + // four lines, two space indented, except for line 1 which is blank. + let mut doc = Rope::from(" 1\n\n 2\n 3"); + // select whole document + let selection = Selection::single(0, doc.len_chars() - 1); - let transaction = toggle_line_comments(&doc, &selection, None); - transaction.apply(&mut doc); - selection = selection.map(transaction.changes()); - assert_eq!(doc, ""); - assert!(selection.len() == 1); // to ignore the selection unused warning + let transaction = toggle_line_comments(&doc, &selection, None); + transaction.apply(&mut doc); + + assert_eq!(doc, " // 1\n\n // 2\n // 3"); + } - // TODO: account for uncommenting with uneven comment indentation + #[test] + fn uncomment() { + let mut doc = Rope::from(" // 1\n\n // 2\n // 3"); + let mut selection = Selection::single(0, doc.len_chars() - 1); + + let transaction = toggle_line_comments(&doc, &selection, None); + transaction.apply(&mut doc); + selection = selection.map(transaction.changes()); + + assert_eq!(doc, " 1\n\n 2\n 3"); + assert!(selection.len() == 1); // to ignore the selection unused warning + } + + #[test] + fn uncomment_0_margin_comments() { + let mut doc = Rope::from(" //1\n\n //2\n //3"); + let mut selection = Selection::single(0, doc.len_chars() - 1); + + let transaction = toggle_line_comments(&doc, &selection, None); + transaction.apply(&mut doc); + selection = selection.map(transaction.changes()); + + assert_eq!(doc, " 1\n\n 2\n 3"); + assert!(selection.len() == 1); // to ignore the selection unused warning + } + + #[test] + fn uncomment_0_margin_comments_with_no_space() { + let mut doc = Rope::from("//"); + let mut selection = Selection::single(0, doc.len_chars() - 1); + + let transaction = toggle_line_comments(&doc, &selection, None); + transaction.apply(&mut doc); + selection = selection.map(transaction.changes()); + assert_eq!(doc, ""); + assert!(selection.len() == 1); // to ignore the selection unused warning + } } #[test] @@ -413,4 +462,32 @@ mod test { transaction.apply(&mut doc); assert_eq!(doc, ""); } + + /// Test, if `get_comment_tokens` works, even if the content of the file includes chars, whose + /// byte size unequal the amount of chars + #[test] + fn test_get_comment_with_char_boundaries() { + let rope = Rope::from("··"); + let tokens = ["//", "///"]; + + assert_eq!( + super::get_comment_token(rope.slice(..), tokens.as_slice(), 0), + None + ); + } + + /// Test for `get_comment_token`. + /// + /// Assuming the comment tokens are stored as `["///", "//"]`, `get_comment_token` should still + /// return `///` instead of `//` if the user is in a doc-comment section. + #[test] + fn test_use_longest_comment() { + let text = Rope::from(" /// amogus"); + let tokens = ["///", "//"]; + + assert_eq!( + super::get_comment_token(text.slice(..), tokens.as_slice(), 0), + Some("///") + ); + } } diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index b1c29378d..ee2949fa0 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -22,8 +22,8 @@ use helix_core::{ encoding, find_workspace, graphemes::{self, next_grapheme_boundary, RevRopeGraphemes}, history::UndoKind, - increment, indent, - indent::IndentStyle, + increment, + indent::{self, IndentStyle}, line_ending::{get_line_ending_of_str, line_end_char_index}, match_brackets, movement::{self, move_vertically_visual, Direction}, @@ -3467,31 +3467,51 @@ fn open(cx: &mut Context, open: Open) { ) }; - let indent = indent::indent_for_newline( - doc.language_config(), - doc.syntax(), - &doc.config.load().indent_heuristic, - &doc.indent_style, - doc.tab_width(), - text, - line_num, - line_end_index, - cursor_line, - ); + let continue_comment_token = doc + .language_config() + .and_then(|config| config.comment_tokens.as_ref()) + .and_then(|tokens| comment::get_comment_token(text, tokens, cursor_line)); + + let line = text.line(cursor_line); + let indent = match line.first_non_whitespace_char() { + Some(pos) if continue_comment_token.is_some() => line.slice(..pos).to_string(), + _ => indent::indent_for_newline( + doc.language_config(), + doc.syntax(), + &doc.config.load().indent_heuristic, + &doc.indent_style, + doc.tab_width(), + text, + line_num, + line_end_index, + cursor_line, + ), + }; let indent_len = indent.len(); let mut text = String::with_capacity(1 + indent_len); text.push_str(doc.line_ending.as_str()); text.push_str(&indent); + + if let Some(token) = continue_comment_token { + text.push_str(token); + text.push(' '); + } + let text = text.repeat(count); // calculate new selection ranges let pos = offs + line_end_index + line_end_offset_width; + let comment_len = continue_comment_token + .map(|token| token.len() + 1) // `+ 1` for the extra space added + .unwrap_or_default(); for i in 0..count { // pos -> beginning of reference line, - // + (i * (1+indent_len)) -> beginning of i'th line from pos - // + indent_len -> -> indent for i'th line - ranges.push(Range::point(pos + (i * (1 + indent_len)) + indent_len)); + // + (i * (1+indent_len + comment_len)) -> beginning of i'th line from pos (possibly including comment token) + // + indent_len + comment_len -> -> indent for i'th line + ranges.push(Range::point( + pos + (i * (1 + indent_len + comment_len)) + indent_len + comment_len, + )); } offs += text.chars().count(); @@ -3929,6 +3949,11 @@ pub mod insert { let mut new_text = String::new(); + let continue_comment_token = doc + .language_config() + .and_then(|config| config.comment_tokens.as_ref()) + .and_then(|tokens| comment::get_comment_token(text, tokens, current_line)); + // If the current line is all whitespace, insert a line ending at the beginning of // the current line. This makes the current line empty and the new line contain the // indentation of the old line. @@ -3938,17 +3963,22 @@ pub mod insert { (line_start, line_start, new_text.chars().count()) } else { - let indent = indent::indent_for_newline( - doc.language_config(), - doc.syntax(), - &doc.config.load().indent_heuristic, - &doc.indent_style, - doc.tab_width(), - text, - current_line, - pos, - current_line, - ); + let line = text.line(current_line); + + let indent = match line.first_non_whitespace_char() { + Some(pos) if continue_comment_token.is_some() => line.slice(..pos).to_string(), + _ => indent::indent_for_newline( + doc.language_config(), + doc.syntax(), + &doc.config.load().indent_heuristic, + &doc.indent_style, + doc.tab_width(), + text, + current_line, + pos, + current_line, + ), + }; // If we are between pairs (such as brackets), we want to // insert an additional line which is indented one level @@ -3958,19 +3988,30 @@ pub mod insert { .and_then(|pairs| pairs.get(prev)) .map_or(false, |pair| pair.open == prev && pair.close == curr); - let local_offs = if on_auto_pair { + let local_offs = if let Some(token) = continue_comment_token { + new_text.push_str(doc.line_ending.as_str()); + new_text.push_str(&indent); + new_text.push_str(token); + new_text.push(' '); + new_text.chars().count() + } else if on_auto_pair { + // line where the cursor will be let inner_indent = indent.clone() + doc.indent_style.as_str(); new_text.reserve_exact(2 + indent.len() + inner_indent.len()); new_text.push_str(doc.line_ending.as_str()); new_text.push_str(&inner_indent); + + // line where the matching pair will be let local_offs = new_text.chars().count(); new_text.push_str(doc.line_ending.as_str()); new_text.push_str(&indent); + local_offs } else { new_text.reserve_exact(1 + indent.len()); new_text.push_str(doc.line_ending.as_str()); new_text.push_str(&indent); + new_text.chars().count() }; From f371dcaa4e7e8769c66164006247016cf274dd67 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 7 Oct 2024 10:25:08 -0400 Subject: [PATCH 22/27] flake: Include --cfg tokio_unstable in Rust flags The flake sets `RUSTFLAGS` and that overwrites the setting in `.cargo/config.toml`. We need to add the `--cfg tokio_unstable` flag to enable integration tests to run when called from the devShell. --- flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/flake.nix b/flake.nix index c7e4fdce5..aabb6c70c 100644 --- a/flake.nix +++ b/flake.nix @@ -114,7 +114,7 @@ if pkgs.stdenv.isLinux then pkgs.stdenv else pkgs.clangStdenv; - rustFlagsEnv = pkgs.lib.optionalString stdenv.isLinux "-C link-arg=-fuse-ld=lld -C target-cpu=native -Clink-arg=-Wl,--no-rosegment"; + rustFlagsEnv = pkgs.lib.optionalString stdenv.isLinux "-C link-arg=-fuse-ld=lld -C target-cpu=native -Clink-arg=-Wl,--no-rosegment --cfg tokio_unstable"; rustToolchain = pkgs.pkgsBuildHost.rust-bin.fromRustupToolchainFile ./rust-toolchain.toml; craneLibMSRV = (crane.mkLib pkgs).overrideToolchain rustToolchain; craneLibStable = (crane.mkLib pkgs).overrideToolchain pkgs.pkgsBuildHost.rust-bin.stable.latest.default; From 6d64e6288add793caf1c841ea295518414c04ea0 Mon Sep 17 00:00:00 2001 From: Michael Davis Date: Mon, 7 Oct 2024 10:29:10 -0400 Subject: [PATCH 23/27] Bump flake dependencies `nix flake update` --- flake.lock | 32 ++++++++++++-------------------- flake.nix | 8 +------- 2 files changed, 13 insertions(+), 27 deletions(-) diff --git a/flake.lock b/flake.lock index 48fb4a59f..9d114d101 100644 --- a/flake.lock +++ b/flake.lock @@ -1,17 +1,12 @@ { "nodes": { "crane": { - "inputs": { - "nixpkgs": [ - "nixpkgs" - ] - }, "locked": { - "lastModified": 1709610799, - "narHash": "sha256-5jfLQx0U9hXbi2skYMGodDJkIgffrjIOgMRjZqms2QE=", + "lastModified": 1727974419, + "narHash": "sha256-WD0//20h+2/yPGkO88d2nYbb23WMWYvnRyDQ9Dx4UHg=", "owner": "ipetkov", "repo": "crane", - "rev": "81c393c776d5379c030607866afef6406ca1be57", + "rev": "37e4f9f0976cb9281cd3f0c70081e5e0ecaee93f", "type": "github" }, "original": { @@ -25,11 +20,11 @@ "systems": "systems" }, "locked": { - "lastModified": 1709126324, - "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "lastModified": 1726560853, + "narHash": "sha256-X6rJYSESBVr3hBoH0WbKE5KvhPU5bloyZ2L4K60/fPQ=", "owner": "numtide", "repo": "flake-utils", - "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "rev": "c1dfcf08411b08f6b8615f7d8971a2bfa81d5e8a", "type": "github" }, "original": { @@ -40,11 +35,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1709479366, - "narHash": "sha256-n6F0n8UV6lnTZbYPl1A9q1BS0p4hduAv1mGAP17CVd0=", + "lastModified": 1728018373, + "narHash": "sha256-NOiTvBbRLIOe5F6RbHaAh6++BNjsb149fGZd1T4+KBg=", "owner": "nixos", "repo": "nixpkgs", - "rev": "b8697e57f10292a6165a20f03d2f42920dfaf973", + "rev": "bc947f541ae55e999ffdb4013441347d83b00feb", "type": "github" }, "original": { @@ -64,19 +59,16 @@ }, "rust-overlay": { "inputs": { - "flake-utils": [ - "flake-utils" - ], "nixpkgs": [ "nixpkgs" ] }, "locked": { - "lastModified": 1709604635, - "narHash": "sha256-le4fwmWmjGRYWwkho0Gr7mnnZndOOe4XGbLw68OvF40=", + "lastModified": 1728268235, + "narHash": "sha256-lJMFnMO4maJuNO6PQ5fZesrTmglze3UFTTBuKGwR1Nw=", "owner": "oxalica", "repo": "rust-overlay", - "rev": "e86c0fb5d3a22a5f30d7f64ecad88643fe26449d", + "rev": "25685cc2c7054efc31351c172ae77b21814f2d42", "type": "github" }, "original": { diff --git a/flake.nix b/flake.nix index aabb6c70c..2f3be94ee 100644 --- a/flake.nix +++ b/flake.nix @@ -6,15 +6,9 @@ flake-utils.url = "github:numtide/flake-utils"; rust-overlay = { url = "github:oxalica/rust-overlay"; - inputs = { - nixpkgs.follows = "nixpkgs"; - flake-utils.follows = "flake-utils"; - }; - }; - crane = { - url = "github:ipetkov/crane"; inputs.nixpkgs.follows = "nixpkgs"; }; + crane.url = "github:ipetkov/crane"; }; outputs = { From 101a74bf6edbbfdf9b0628a0bdbbc307ebe10ff2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 23 Oct 2024 22:34:20 +0900 Subject: [PATCH 24/27] build(deps): bump the rust-dependencies group with 6 updates (#11924) Bumps the rust-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [serde_json](https://github.com/serde-rs/json) | `1.0.128` | `1.0.132` | | [anyhow](https://github.com/dtolnay/anyhow) | `1.0.89` | `1.0.90` | | [libc](https://github.com/rust-lang/libc) | `0.2.159` | `0.2.161` | | [fern](https://github.com/daboross/fern) | `0.6.2` | `0.7.0` | | [pulldown-cmark](https://github.com/raphlinus/pulldown-cmark) | `0.12.1` | `0.12.2` | | [cc](https://github.com/rust-lang/cc-rs) | `1.1.30` | `1.1.31` | Updates `serde_json` from 1.0.128 to 1.0.132 - [Release notes](https://github.com/serde-rs/json/releases) - [Commits](https://github.com/serde-rs/json/compare/1.0.128...1.0.132) Updates `anyhow` from 1.0.89 to 1.0.90 - [Release notes](https://github.com/dtolnay/anyhow/releases) - [Commits](https://github.com/dtolnay/anyhow/compare/1.0.89...1.0.90) Updates `libc` from 0.2.159 to 0.2.161 - [Release notes](https://github.com/rust-lang/libc/releases) - [Changelog](https://github.com/rust-lang/libc/blob/0.2.161/CHANGELOG.md) - [Commits](https://github.com/rust-lang/libc/compare/0.2.159...0.2.161) Updates `fern` from 0.6.2 to 0.7.0 - [Release notes](https://github.com/daboross/fern/releases) - [Changelog](https://github.com/daboross/fern/blob/main/CHANGELOG.md) - [Commits](https://github.com/daboross/fern/compare/fern-0.6.2...fern-0.7.0) Updates `pulldown-cmark` from 0.12.1 to 0.12.2 - [Release notes](https://github.com/raphlinus/pulldown-cmark/releases) - [Commits](https://github.com/raphlinus/pulldown-cmark/compare/v0.12.1...v0.12.2) Updates `cc` from 1.1.30 to 1.1.31 - [Release notes](https://github.com/rust-lang/cc-rs/releases) - [Changelog](https://github.com/rust-lang/cc-rs/blob/main/CHANGELOG.md) - [Commits](https://github.com/rust-lang/cc-rs/compare/cc-v1.1.30...cc-v1.1.31) --- updated-dependencies: - dependency-name: serde_json dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies - dependency-name: anyhow dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies - dependency-name: libc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies - dependency-name: fern dependency-type: direct:production update-type: version-update:semver-minor dependency-group: rust-dependencies - dependency-name: pulldown-cmark dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies - dependency-name: cc dependency-type: direct:production update-type: version-update:semver-patch dependency-group: rust-dependencies ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- Cargo.lock | 24 ++++++++++++------------ helix-dap/Cargo.toml | 2 +- helix-lsp-types/Cargo.toml | 2 +- helix-term/Cargo.toml | 4 ++-- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92795e743..f8662c41e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -68,9 +68,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.89" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86fdf8605db99b54d3cd748a44c6d04df638eb5dafb219b135d0149bd0db01f6" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" [[package]] name = "arc-swap" @@ -136,9 +136,9 @@ checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" [[package]] name = "cc" -version = "1.1.30" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "shlex", ] @@ -355,9 +355,9 @@ checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fern" -version = "0.6.2" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" +checksum = "69ff9c9d5fb3e6da8ac2f77ab76fe7e8087d512ce095200f8f29ac5b656cf6dc" dependencies = [ "log", ] @@ -1609,9 +1609,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libloading" @@ -1838,9 +1838,9 @@ checksum = "744a264d26b88a6a7e37cbad97953fa233b94d585236310bcbc88474b4092d79" [[package]] name = "pulldown-cmark" -version = "0.12.1" +version = "0.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666f0f59e259aea2d72e6012290c09877a780935cc3c18b1ceded41f3890d59c" +checksum = "f86ba2052aebccc42cbbb3ed234b8b13ce76f75c3551a303cb2bcffcff12bb14" dependencies = [ "bitflags", "memchr", @@ -2026,9 +2026,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", diff --git a/helix-dap/Cargo.toml b/helix-dap/Cargo.toml index c37340cc6..d67932afb 100644 --- a/helix-dap/Cargo.toml +++ b/helix-dap/Cargo.toml @@ -24,4 +24,4 @@ tokio = { version = "1", features = ["rt", "rt-multi-thread", "io-util", "io-std thiserror.workspace = true [dev-dependencies] -fern = "0.6" +fern = "0.7" diff --git a/helix-lsp-types/Cargo.toml b/helix-lsp-types/Cargo.toml index 1ecb3d810..bf2aeae12 100644 --- a/helix-lsp-types/Cargo.toml +++ b/helix-lsp-types/Cargo.toml @@ -23,7 +23,7 @@ license = "MIT" [dependencies] bitflags = "2.6.0" serde = { version = "1.0.209", features = ["derive"] } -serde_json = "1.0.127" +serde_json = "1.0.132" serde_repr = "0.1" url = {version = "2.0.0", features = ["serde"]} diff --git a/helix-term/Cargo.toml b/helix-term/Cargo.toml index b14d3d3c5..dc0e20b68 100644 --- a/helix-term/Cargo.toml +++ b/helix-term/Cargo.toml @@ -45,7 +45,7 @@ arc-swap = { version = "1.7.1" } termini = "1" # Logging -fern = "0.6" +fern = "0.7" chrono = { version = "0.4", default-features = false, features = ["clock"] } log = "0.4" @@ -74,7 +74,7 @@ grep-searcher = "0.1.14" [target.'cfg(not(windows))'.dependencies] # https://github.com/vorner/signal-hook/issues/100 signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"] } -libc = "0.2.159" +libc = "0.2.161" [target.'cfg(target_os = "macos")'.dependencies] crossterm = { version = "0.28", features = ["event-stream", "use-dev-tty", "libc"] } From 38faf74febf3332fb119302324bfd21229d39e14 Mon Sep 17 00:00:00 2001 From: Elliot Fontaine <92150839+elliotfontaine@users.noreply.github.com> Date: Wed, 30 Oct 2024 19:39:24 +0100 Subject: [PATCH 25/27] feat: Add support for cylc configuration files (#11830) Co-authored-by: Michael Davis --- book/src/generated/lang-support.md | 1 + languages.toml | 13 +++- runtime/queries/cylc/highlights.scm | 100 +++++++++++++++++++++++++++ runtime/queries/cylc/indents.scm | 19 +++++ runtime/queries/cylc/injections.scm | 20 ++++++ runtime/queries/cylc/textobjects.scm | 23 ++++++ 6 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 runtime/queries/cylc/highlights.scm create mode 100644 runtime/queries/cylc/indents.scm create mode 100644 runtime/queries/cylc/injections.scm create mode 100644 runtime/queries/cylc/textobjects.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 4f9b64de0..09f15b374 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -29,6 +29,7 @@ | crystal | ✓ | ✓ | | `crystalline` | | css | ✓ | | ✓ | `vscode-css-language-server` | | cue | ✓ | | | `cuelsp` | +| cylc | ✓ | ✓ | ✓ | | | d | ✓ | ✓ | ✓ | `serve-d` | | dart | ✓ | ✓ | ✓ | `dart` | | dbml | ✓ | | | | diff --git a/languages.toml b/languages.toml index 57d220b61..3d4d1f908 100644 --- a/languages.toml +++ b/languages.toml @@ -3845,7 +3845,18 @@ comment-tokens = ["#", "##"] indent = { tab-width = 2, unit = " " } language-servers = ["pylsp" ] - [[grammar]] name = "snakemake" source = { git = "https://github.com/osthomas/tree-sitter-snakemake", rev = "e909815acdbe37e69440261ebb1091ed52e1dec6" } + +[[language]] +name = "cylc" +scope = "source.cylc" +injection-regex = "cylc" +file-types = ["cylc", { glob = "suite.rc" }] +comment-tokens = "#" +indent = { tab-width = 4, unit = " " } + +[[grammar]] +name = "cylc" +source = { git = "https://github.com/elliotfontaine/tree-sitter-cylc", rev = "30dd40d9bf23912e4aefa93eeb4c7090bda3d0f6" } \ No newline at end of file diff --git a/runtime/queries/cylc/highlights.scm b/runtime/queries/cylc/highlights.scm new file mode 100644 index 000000000..e9e1194f1 --- /dev/null +++ b/runtime/queries/cylc/highlights.scm @@ -0,0 +1,100 @@ +(ERROR) @markup.bold + +[ + (jinja2_expression) + (jinja2_statement) + (jinja2_comment) + (jinja2_shebang) +] @special + +(include_statement + directive: _ @keyword.directive + path: _ @string.special.path) + +(comment) @comment.line + +(graph_section + name: _? @label) + +(task_section + name: (_ + (task_name) @namespace)) + +(top_section + brackets_open: _ @punctuation.bracket + name: _? @label + brackets_close: _ @punctuation.bracket) + +(sub_section_1 + brackets_open: _ @punctuation.bracket + name: _? @label + brackets_close: _ @punctuation.bracket) + +(sub_section_2 + brackets_open: _ @punctuation.bracket + name: _? @label + brackets_close: _ @punctuation.bracket) + +(runtime_section + brackets_open: _ @punctuation.bracket + name: _? @label + brackets_close: _ @punctuation.bracket) + +(graph_setting + key: (_) @constant.numeric.integer + operator: (_)? @operator) + +(quoted_graph_string + quotes_open: _ @string + quotes_close: _ @string) + +(multiline_graph_string + quotes_open: _ @string + quotes_close: _ @string) + +[ + (graph_logical) + (graph_arrow) + (graph_parenthesis) +] @operator + +(intercycle_annotation + (recurrence) @constant.numeric.integer) + +(graph_task + xtrigger: _? @operator + suicide: _? @operator + name: _ @namespace) + +(task_parameter + "<" @tag + name: (_)? @special + ","? @tag + "="? @tag + selection: (_)? @special + ">" @tag) + +(intercycle_annotation + "[" @tag + (recurrence)? @constant.numeric.integer + "]" @tag) + +(task_output + ":" @tag + (nametag) @variable.other) + +(task_output + "?"? @tag) + +(setting + key: (key) @variable + operator: (_)? @operator + value: [ + (unquoted_string) @string + (quoted_string) @string + (multiline_string) @string + (boolean) @constant.builtin.boolean + (integer) @constant.numeric.integer + ]?) + +(datetime) @constant.numeric.float diff --git a/runtime/queries/cylc/indents.scm b/runtime/queries/cylc/indents.scm new file mode 100644 index 000000000..865386c78 --- /dev/null +++ b/runtime/queries/cylc/indents.scm @@ -0,0 +1,19 @@ +[ + (top_section) + (sub_section_1) + (sub_section_2) + (graph_section) + (runtime_section) + (task_section) +] @indent + +[ + (top_section) + (sub_section_1) + (sub_section_2) + (graph_section) + (runtime_section) + (task_section) +] @extend + +(line_continuation) @indent.always diff --git a/runtime/queries/cylc/injections.scm b/runtime/queries/cylc/injections.scm new file mode 100644 index 000000000..d10931f45 --- /dev/null +++ b/runtime/queries/cylc/injections.scm @@ -0,0 +1,20 @@ +((setting + key: (key) @key + (#match? @key "^script$|-script$|^script-") + value: (_ + (string_content) @injection.content)) + (#set! "injection.language" "bash")) + +; Requires no spacing around "=" in environment settings for proper highlighting. +; Could be improved if Tree-sitter allowed to specify the target node of the injected +; language, instead of always using the root node. +; See this proposal: +; https://github.com/tree-sitter/tree-sitter/issues/3625 +((task_section + (sub_section_2 + name: (_) @section_name + (#eq? @section_name "environment") + (setting) @injection.content)) + (#set! "injection.language" "bash") + (#set! injection.combined) + (#set! injection.include-children)) diff --git a/runtime/queries/cylc/textobjects.scm b/runtime/queries/cylc/textobjects.scm new file mode 100644 index 000000000..00ed52ff8 --- /dev/null +++ b/runtime/queries/cylc/textobjects.scm @@ -0,0 +1,23 @@ +(comment) @comment.inside + +(comment)+ @comment.around + +(_ + brackets_open: _ + name: _? + brackets_close: _ + _* @class.inside) @class.around + +(setting + value: _? @function.inside) @function.around + +(graph_setting + value: _? @function.inside) @function.around + +(graph_string_content + (graph_task) @entry.inside) + +(task_parameter + ((_) @parameter.inside + . + ","? @parameter.around) @parameter.around) From c0920e779d7c105cb43c4d46f16dfa4541bd9d19 Mon Sep 17 00:00:00 2001 From: Poliorcetics Date: Tue, 5 Nov 2024 08:09:20 +0100 Subject: [PATCH 26/27] just: update tree-sitter-grammar to support 1.36.0 (#11606) Release notes: - https://github.com/casey/just/releases/tag/1.35.0 - https://github.com/casey/just/releases/tag/1.36.0 Notably, this adds `[private]` attributes on modules, which the current version of the grammar cannot parse, as well as unicode codepoint escape sequences. --- languages.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index 3d4d1f908..6686cec13 100644 --- a/languages.toml +++ b/languages.toml @@ -3140,7 +3140,7 @@ indent = { tab-width = 4, unit = " " } [[grammar]] name = "just" -source = { git = "https://github.com/poliorcetics/tree-sitter-just", rev = "f58a8fd869035ac4653081401e6c2030251240ab" } +source = { git = "https://github.com/poliorcetics/tree-sitter-just", rev = "6e28fa6cba511c694247cd802d1c3b14f8d34dbb" } [[language]] name = "gn" From b53dafe326d51b7f64a1c52379e3d4150cd2991e Mon Sep 17 00:00:00 2001 From: Yuki Kobayashi <137767097+aster-void@users.noreply.github.com> Date: Tue, 5 Nov 2024 16:09:49 +0900 Subject: [PATCH 27/27] Treat .prettierrc as YAML (#11997) --- languages.toml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/languages.toml b/languages.toml index 6686cec13..d55948ad5 100644 --- a/languages.toml +++ b/languages.toml @@ -449,7 +449,6 @@ file-types = [ { glob = "composer.lock" }, { glob = ".watchmanconfig" }, "avsc", - { glob = ".prettierrc" }, "ldtk", "ldtkl", ] @@ -1306,7 +1305,7 @@ source = { git = "https://github.com/ikatyang/tree-sitter-vue", rev = "91fe27547 [[language]] name = "yaml" scope = "source.yaml" -file-types = ["yml", "yaml"] +file-types = ["yml", "yaml", { glob = ".prettierrc" }] comment-token = "#" indent = { tab-width = 2, unit = " " } language-servers = [ "yaml-language-server", "ansible-language-server" ] @@ -3859,4 +3858,4 @@ indent = { tab-width = 4, unit = " " } [[grammar]] name = "cylc" -source = { git = "https://github.com/elliotfontaine/tree-sitter-cylc", rev = "30dd40d9bf23912e4aefa93eeb4c7090bda3d0f6" } \ No newline at end of file +source = { git = "https://github.com/elliotfontaine/tree-sitter-cylc", rev = "30dd40d9bf23912e4aefa93eeb4c7090bda3d0f6" }