aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--helix-core/src/selection.rs7
-rw-r--r--helix-term/src/ui/editor.rs43
-rw-r--r--helix-view/src/view.rs43
3 files changed, 37 insertions, 56 deletions
diff --git a/helix-core/src/selection.rs b/helix-core/src/selection.rs
index 14c54295..a3ea2ed4 100644
--- a/helix-core/src/selection.rs
+++ b/helix-core/src/selection.rs
@@ -329,11 +329,18 @@ pub struct Selection {
impl Selection {
// eq
+ #[inline]
#[must_use]
pub fn primary(&self) -> Range {
self.ranges[self.primary_index]
}
+ #[inline]
+ #[must_use]
+ pub fn primary_mut(&mut self) -> &mut Range {
+ &mut self.ranges[self.primary_index]
+ }
+
/// Ensure selection containing only the primary selection.
pub fn into_single(self) -> Self {
if self.ranges.len() == 1 {
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index 7a2a07ed..a2b169ed 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -815,25 +815,21 @@ impl Component for EditorView {
let editor = &mut cx.editor;
let result = editor.tree.views().find_map(|(view, _focus)| {
- view.pos_at_screen_coords(
- &editor.documents[view.doc],
- row as usize,
- column as usize,
- )
- .map(|pos| (pos, view.id))
+ view.pos_at_screen_coords(&editor.documents[view.doc], row, column)
+ .map(|pos| (pos, view.id))
});
- if let Some((pos, id)) = result {
- let doc = &mut editor.documents[editor.tree.get(id).doc];
+ if let Some((pos, view_id)) = result {
+ let doc = &mut editor.documents[editor.tree.get(view_id).doc];
if modifiers == crossterm::event::KeyModifiers::ALT {
- let selection = doc.selection(id).clone();
- doc.set_selection(id, selection.push(Range::point(pos)));
+ let selection = doc.selection(view_id).clone();
+ doc.set_selection(view_id, selection.push(Range::point(pos)));
} else {
- doc.set_selection(id, Selection::point(pos));
+ doc.set_selection(view_id, Selection::point(pos));
}
- editor.tree.focus = id;
+ editor.tree.focus = view_id;
return EventResult::Consumed(None);
}
@@ -849,22 +845,15 @@ impl Component for EditorView {
}) => {
let (view, doc) = current!(cx.editor);
- let pos = view.pos_at_screen_coords(doc, row as usize, column as usize);
-
- if pos == None {
- return EventResult::Ignored;
- }
-
- let selection = doc.selection(view.id).clone();
- let primary_anchor = selection.primary().anchor;
- let new_selection = selection.transform(|range| -> Range {
- if range.anchor == primary_anchor {
- return Range::new(primary_anchor, pos.unwrap());
- }
- range
- });
+ let pos = match view.pos_at_screen_coords(doc, row, column) {
+ Some(pos) => pos,
+ None => return EventResult::Ignored,
+ };
- doc.set_selection(view.id, new_selection);
+ let mut selection = doc.selection(view.id).clone();
+ let primary = selection.primary_mut();
+ *primary = Range::new(primary.anchor, pos);
+ doc.set_selection(view.id, selection);
EventResult::Consumed(None)
}
Event::Mouse(_) => EventResult::Ignored,
diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs
index d61fbe4a..1b350172 100644
--- a/helix-view/src/view.rs
+++ b/helix-view/src/view.rs
@@ -166,38 +166,26 @@ impl View {
Some(Position::new(row, col))
}
- /// Verifies whether a screen position is inside the view
- /// Returns true when position is inside the view
- pub fn verify_screen_coords(&self, row: usize, column: usize) -> bool {
- // 2 for status
- if row < self.area.y as usize || row > self.area.y as usize + self.area.height as usize - 2
- {
- return false;
- }
-
- // TODO: not ideal
- const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter
-
- if column < self.area.x as usize + OFFSET
- || column > self.area.x as usize + self.area.width as usize
- {
- return false;
- }
- true
- }
-
pub fn text_pos_at_screen_coords(
&self,
text: &RopeSlice,
- row: usize,
- column: usize,
+ row: u16,
+ column: u16,
tab_width: usize,
) -> Option<usize> {
- if !self.verify_screen_coords(row, column) {
+ // TODO: not ideal
+ const OFFSET: u16 = 7; // 1 diagnostic + 5 linenr + 1 gutter
+
+ // 2 for status
+ if row < self.area.top() || row > self.area.bottom().saturating_sub(2) {
return None;
}
- let line_number = row - self.area.y as usize + self.first_line;
+ if column < self.area.left() + OFFSET || column > self.area.right() {
+ return None;
+ }
+
+ let line_number = (row - self.area.y) as usize + self.first_line;
if line_number > text.len_lines() - 1 {
return Some(text.len_chars());
@@ -207,10 +195,7 @@ impl View {
let current_line = text.line(line_number);
- // TODO: not ideal
- const OFFSET: usize = 7; // 1 diagnostic + 5 linenr + 1 gutter
-
- let target = column - OFFSET - self.area.x as usize + self.first_col;
+ let target = (column - OFFSET - self.area.x) as usize + self.first_col;
let mut selected = 0;
for grapheme in RopeGraphemes::new(current_line) {
@@ -231,7 +216,7 @@ impl View {
/// Translates a screen position to position in the text document.
/// Returns a usize typed position in bounds of the text if found in this view, None if out of view.
- pub fn pos_at_screen_coords(&self, doc: &Document, row: usize, column: usize) -> Option<usize> {
+ pub fn pos_at_screen_coords(&self, doc: &Document, row: u16, column: u16) -> Option<usize> {
self.text_pos_at_screen_coords(&doc.text().slice(..), row, column, doc.tab_width())
}
// pub fn traverse<F>(&self, text: RopeSlice, start: usize, end: usize, fun: F)