diff options
author | Blaž Hrastnik | 2020-10-04 06:40:49 +0000 |
---|---|---|
committer | GitHub | 2020-10-04 06:40:49 +0000 |
commit | 197651eb309e88ba120dcb7a769acac6091483b1 (patch) | |
tree | 46fc50e8d3fb66182e05c4f81acf9c1f9fca479f /helix-view | |
parent | 7b4a4f6a3cec10f7b2d4a406cc68b5929b36b0a1 (diff) | |
parent | dc11124df54cd4f03d5bfa814e33262643483e87 (diff) |
Merge pull request #2 from helix-editor/tab-implementation
added tab to insert mode
Diffstat (limited to 'helix-view')
-rw-r--r-- | helix-view/src/commands.rs | 4 | ||||
-rw-r--r-- | helix-view/src/keymap.rs | 4 | ||||
-rw-r--r-- | helix-view/src/view.rs | 52 |
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)) + } } |