aboutsummaryrefslogtreecommitdiff
path: root/helix-view/src
diff options
context:
space:
mode:
Diffstat (limited to 'helix-view/src')
-rw-r--r--helix-view/src/commands.rs4
-rw-r--r--helix-view/src/keymap.rs4
-rw-r--r--helix-view/src/view.rs52
3 files changed, 58 insertions, 2 deletions
diff --git a/helix-view/src/commands.rs b/helix-view/src/commands.rs
index 1fb9c90e..6dd1101c 100644
--- a/helix-view/src/commands.rs
+++ b/helix-view/src/commands.rs
@@ -301,6 +301,10 @@ pub fn insert_char(view: &mut View, c: char) {
// TODO: need to store into history if successful
}
+pub fn insert_tab(view: &mut View, _count: usize) {
+ insert_char(view, '\t');
+}
+
pub fn insert_newline(view: &mut View, _count: usize) {
insert_char(view, '\n');
}
diff --git a/helix-view/src/keymap.rs b/helix-view/src/keymap.rs
index d4ab85a2..ef23ff2a 100644
--- a/helix-view/src/keymap.rs
+++ b/helix-view/src/keymap.rs
@@ -157,6 +157,10 @@ pub fn default() -> Keymaps {
code: KeyCode::Enter,
modifiers: Modifiers::NONE
}] => commands::insert_newline,
+ vec![Key {
+ code: KeyCode::Tab,
+ modifiers: Modifiers::NONE
+ }] => commands::insert_tab,
)
)
}
diff --git a/helix-view/src/view.rs b/helix-view/src/view.rs
index d96752d0..ac342d61 100644
--- a/helix-view/src/view.rs
+++ b/helix-view/src/view.rs
@@ -1,9 +1,13 @@
use anyhow::Error;
-use std::path::PathBuf;
+use std::{borrow::Cow, path::PathBuf};
use crate::theme::Theme;
-use helix_core::State;
+use helix_core::{
+ graphemes::{grapheme_width, RopeGraphemes},
+ Position, RopeSlice, State,
+};
+use tui::layout::Rect;
pub struct View {
pub state: State,
@@ -44,4 +48,48 @@ impl View {
self.first_line = line.saturating_sub(padding);
}
}
+
+ /// Calculates the last visible line on screen
+ #[inline]
+ pub fn last_line(&self, viewport: Rect) -> usize {
+ std::cmp::min(
+ (self.first_line + viewport.height - 1) as usize,
+ self.state.doc().len_lines() - 1,
+ )
+ }
+
+ /// Translates a document position to an absolute position in the terminal.
+ /// Returns a (line, col) position if the position is visible on screen.
+ // TODO: Could return width as well for the character width at cursor.
+ pub fn screen_coords_at_pos(
+ &self,
+ text: &RopeSlice,
+ pos: usize,
+ viewport: Rect,
+ ) -> Option<Position> {
+ let line = text.char_to_line(pos);
+
+ if line < self.first_line as usize || line > self.last_line(viewport) {
+ // Line is not visible on screen
+ return None;
+ }
+
+ let line_start = text.line_to_char(line);
+ let line_slice = text.slice(line_start..pos);
+ let mut col = 0;
+
+ for grapheme in RopeGraphemes::new(&line_slice) {
+ if grapheme == "\t" {
+ // TODO: this should be const TAB_WIDTH
+ col += 4;
+ } else {
+ let grapheme = Cow::from(grapheme);
+ col += grapheme_width(&grapheme);
+ }
+ }
+
+ let row = line - self.first_line as usize;
+
+ Some(Position::new(row, col))
+ }
}