Detailed changes
@@ -776,6 +776,8 @@ actions!(
UniqueLinesCaseInsensitive,
/// Removes duplicate lines (case-sensitive).
UniqueLinesCaseSensitive,
+ /// Removes the surrounding syntax node (for example brackets, or closures)
+ /// from the current selections.
UnwrapSyntaxNode,
/// Wraps selections in tag specified by language.
WrapSelectionsInTag
@@ -142,7 +142,7 @@ use mouse_context_menu::MouseContextMenu;
use movement::TextLayoutDetails;
use multi_buffer::{
ExcerptInfo, ExpandExcerptDirection, MultiBufferDiffHunk, MultiBufferPoint, MultiBufferRow,
- MultiOrSingleBufferOffsetRange, ToOffsetUtf16,
+ ToOffsetUtf16,
};
use parking_lot::Mutex;
use persistence::DB;
@@ -14988,12 +14988,8 @@ impl Editor {
}
let mut new_range = old_range.clone();
- while let Some((node, containing_range)) = buffer.syntax_ancestor(new_range.clone())
- {
- new_range = match containing_range {
- MultiOrSingleBufferOffsetRange::Single(_) => break,
- MultiOrSingleBufferOffsetRange::Multi(range) => range,
- };
+ while let Some((node, range)) = buffer.syntax_ancestor(new_range.clone()) {
+ new_range = range;
if !node.is_named() {
continue;
}
@@ -15125,20 +15121,14 @@ impl Editor {
} else if let Some((_, ancestor_range)) =
buffer.syntax_ancestor(selection.start..selection.end)
{
- match ancestor_range {
- MultiOrSingleBufferOffsetRange::Single(range) => range,
- MultiOrSingleBufferOffsetRange::Multi(range) => range,
- }
+ ancestor_range
} else {
selection.range()
};
let mut parent = child.clone();
while let Some((_, ancestor_range)) = buffer.syntax_ancestor(parent.clone()) {
- parent = match ancestor_range {
- MultiOrSingleBufferOffsetRange::Single(range) => range,
- MultiOrSingleBufferOffsetRange::Multi(range) => range,
- };
+ parent = ancestor_range;
if parent.start < child.start || parent.end > child.end {
break;
}
@@ -9147,6 +9147,64 @@ async fn test_unwrap_syntax_nodes(cx: &mut gpui::TestAppContext) {
});
cx.assert_editor_state(indoc! { r#"use mod1::{mod2::«mod3ˇ», mod5::«mod7ˇ»};"# });
+
+ cx.set_state(indoc! { r#"fn a() {
+ // what
+ // a
+ // ˇlong
+ // method
+ // I
+ // sure
+ // hope
+ // it
+ // works
+ }"# });
+
+ let buffer = cx.update_multibuffer(|multibuffer, _| multibuffer.as_singleton().unwrap());
+ let multi_buffer = cx.new(|_| MultiBuffer::new(Capability::ReadWrite));
+ cx.update(|_, cx| {
+ multi_buffer.update(cx, |multi_buffer, cx| {
+ multi_buffer.set_excerpts_for_path(
+ PathKey::for_buffer(&buffer, cx),
+ buffer,
+ [Point::new(1, 0)..Point::new(1, 0)],
+ 3,
+ cx,
+ );
+ });
+ });
+
+ let editor2 = cx.new_window_entity(|window, cx| {
+ Editor::new(EditorMode::full(), multi_buffer, None, window, cx)
+ });
+
+ let mut cx = EditorTestContext::for_editor_in(editor2, &mut cx).await;
+ cx.update_editor(|editor, window, cx| {
+ editor.change_selections(SelectionEffects::default(), window, cx, |s| {
+ s.select_ranges([Point::new(3, 0)..Point::new(3, 0)]);
+ })
+ });
+
+ cx.assert_editor_state(indoc! { "
+ fn a() {
+ // what
+ // a
+ ˇ // long
+ // method"});
+
+ cx.update_editor(|editor, window, cx| {
+ editor.unwrap_syntax_node(&UnwrapSyntaxNode, window, cx);
+ });
+
+ // Although we could potentially make the action work when the syntax node
+ // is half-hidden, it seems a bit dangerous as you can't easily tell what it
+ // did. Maybe we could also expand the excerpt to contain the range?
+ cx.assert_editor_state(indoc! { "
+ fn a() {
+ // what
+ // a
+ ˇ // long
+ // method"});
}
#[gpui::test]
@@ -16,7 +16,7 @@ use itertools::Itertools;
use language::{DiagnosticEntry, Language, LanguageRegistry};
use lsp::DiagnosticSeverity;
use markdown::{Markdown, MarkdownElement, MarkdownStyle};
-use multi_buffer::{MultiOrSingleBufferOffsetRange, ToOffset, ToPoint};
+use multi_buffer::{ToOffset, ToPoint};
use project::{HoverBlock, HoverBlockKind, InlayHintLabelPart};
use settings::Settings;
use std::{borrow::Cow, cell::RefCell};
@@ -477,13 +477,8 @@ fn show_hover(
})
.or_else(|| {
let snapshot = &snapshot.buffer_snapshot;
- match snapshot.syntax_ancestor(anchor..anchor)?.1 {
- MultiOrSingleBufferOffsetRange::Multi(range) => Some(
- snapshot.anchor_before(range.start)
- ..snapshot.anchor_after(range.end),
- ),
- MultiOrSingleBufferOffsetRange::Single(_) => None,
- }
+ let range = snapshot.syntax_ancestor(anchor..anchor)?.1;
+ Some(snapshot.anchor_before(range.start)..snapshot.anchor_after(range.end))
})
.unwrap_or_else(|| anchor..anchor);
@@ -80,12 +80,6 @@ pub struct MultiBuffer {
buffer_changed_since_sync: Rc<Cell<bool>>,
}
-#[derive(Clone, Debug, PartialEq, Eq)]
-pub enum MultiOrSingleBufferOffsetRange {
- Single(Range<usize>),
- Multi(Range<usize>),
-}
-
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Event {
ExcerptsAdded {
@@ -6077,19 +6071,17 @@ impl MultiBufferSnapshot {
pub fn syntax_ancestor<T: ToOffset>(
&self,
range: Range<T>,
- ) -> Option<(tree_sitter::Node<'_>, MultiOrSingleBufferOffsetRange)> {
+ ) -> Option<(tree_sitter::Node<'_>, Range<usize>)> {
let range = range.start.to_offset(self)..range.end.to_offset(self);
let mut excerpt = self.excerpt_containing(range.clone())?;
let node = excerpt
.buffer()
.syntax_ancestor(excerpt.map_range_to_buffer(range))?;
let node_range = node.byte_range();
- let range = if excerpt.contains_buffer_range(node_range.clone()) {
- MultiOrSingleBufferOffsetRange::Multi(excerpt.map_range_from_buffer(node_range))
- } else {
- MultiOrSingleBufferOffsetRange::Single(node_range)
+ if !excerpt.contains_buffer_range(node_range.clone()) {
+ return None;
};
- Some((node, range))
+ Some((node, excerpt.map_range_from_buffer(node_range)))
}
pub fn syntax_next_sibling<T: ToOffset>(