aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Davis2022-07-30 14:20:07 +0000
committerBlaž Hrastnik2022-10-03 14:44:08 +0000
commit274f2ea45979098a96b7a6d94ecc18351826eaea (patch)
tree3b6811253f16b8466060b4737914c4d7fd304693
parentf3958aa1fd4518aad0842e3015d991aadce1fd28 (diff)
Use requested direction for new textobject selection range
This changes the behavior of operations like `]f`/`[f` to set the direction of the new range to the direction of the action. The original behavior was to always use the head of the next function. This is inconsistent with the behavior of goto_next_paragraph and makes it impossible to create extend variants of the textobject motions. This causes a behavior change when there are nested functions. The behavior in the parent commit is that repeated uses of `]f` will select every function in the file even if nested. With this commit, functions are skipped. It's notable that it's possible to emulate the original behavior by using the `ensure_selections_forward` (A-:) command between invocations of `]f`.
-rw-r--r--helix-core/src/movement.rs8
-rw-r--r--helix-core/src/selection.rs12
-rw-r--r--helix-term/src/commands.rs1
3 files changed, 17 insertions, 4 deletions
diff --git a/helix-core/src/movement.rs b/helix-core/src/movement.rs
index c232484c..278375e8 100644
--- a/helix-core/src/movement.rs
+++ b/helix-core/src/movement.rs
@@ -389,6 +389,8 @@ fn reached_target(target: WordMotionTarget, prev_ch: char, next_ch: char) -> boo
}
}
+/// Finds the range of the next or previous textobject in the syntax sub-tree of `node`.
+/// Returns the range in the forwards direction.
pub fn goto_treesitter_object(
slice: RopeSlice,
range: Range,
@@ -419,8 +421,8 @@ pub fn goto_treesitter_object(
.filter(|n| n.start_byte() > byte_pos)
.min_by_key(|n| n.start_byte())?,
Direction::Backward => nodes
- .filter(|n| n.start_byte() < byte_pos)
- .max_by_key(|n| n.start_byte())?,
+ .filter(|n| n.end_byte() < byte_pos)
+ .max_by_key(|n| n.end_byte())?,
};
let len = slice.len_bytes();
@@ -434,7 +436,7 @@ pub fn goto_treesitter_object(
let end_char = slice.byte_to_char(end_byte);
// head of range should be at beginning
- Some(Range::new(end_char, start_char))
+ Some(Range::new(start_char, end_char))
};
(0..count).fold(range, |range, _| get_range(range).unwrap_or(range))
}
diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs
index 3463c1d3..1f28ecef 100644
--- a/helix-core/src/selection.rs
+++ b/helix-core/src/selection.rs
@@ -122,7 +122,7 @@ impl Range {
}
}
- // flips the direction of the selection
+ /// Flips the direction of the selection
pub fn flip(&self) -> Self {
Self {
anchor: self.head,
@@ -131,6 +131,16 @@ impl Range {
}
}
+ /// Returns the selection if it goes in the direction of `direction`,
+ /// flipping the selection otherwise.
+ pub fn with_direction(self, direction: Direction) -> Self {
+ if self.direction() == direction {
+ self
+ } else {
+ self.flip()
+ }
+ }
+
/// Check two ranges for overlap.
#[must_use]
pub fn overlaps(&self, other: &Self) -> bool {
diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs
index 0a192b4a..53a34c00 100644
--- a/helix-term/src/commands.rs
+++ b/helix-term/src/commands.rs
@@ -4294,6 +4294,7 @@ fn goto_ts_object_impl(cx: &mut Context, object: &'static str, direction: Direct
lang_config,
count,
)
+ .with_direction(direction)
});
doc.set_selection(view.id, selection);