From 902d93e957b5ec2f60afdf1faadc99465ea06017 Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sun, 8 Feb 2015 19:17:48 -0800 Subject: [PATCH] Line numbers are now displayed in left-hand gutter. --- src/editor/mod.rs | 23 +++++++++++++++++++++-- src/main.rs | 1 + src/term_ui/mod.rs | 27 +++++++++++++++++++++++---- src/utils.rs | 34 ++++++++++++++++++++++++++++++++++ todo.md | 1 - 5 files changed, 79 insertions(+), 7 deletions(-) create mode 100644 src/utils.rs diff --git a/src/editor/mod.rs b/src/editor/mod.rs index 5592906..4b23452 100644 --- a/src/editor/mod.rs +++ b/src/editor/mod.rs @@ -7,6 +7,7 @@ use formatter::RoundingBehavior::*; use std::old_path::Path; use std::cmp::{min, max}; use string_utils::grapheme_count; +use utils::digit_count; use self::cursor::CursorSet; mod cursor; @@ -21,7 +22,11 @@ pub struct Editor { pub soft_tab_width: u8, pub dirty: bool, - // The dimensions and position of the editor's view within the buffer + // The dimensions of the total editor in screen space, including the + // header, gutter, etc. + pub editor_dim: (usize, usize), + + // The dimensions and position of just the text view portion of the editor pub view_dim: (usize, usize), // (height, width) pub view_pos: (usize, usize), // (grapheme index, visual horizontal offset) @@ -41,6 +46,7 @@ impl Editor { soft_tabs: false, soft_tab_width: 4, dirty: false, + editor_dim: (0, 0), view_dim: (0, 0), view_pos: (0, 0), cursors: CursorSet::new(), @@ -63,6 +69,7 @@ impl Editor { soft_tabs: false, soft_tab_width: 4, dirty: false, + editor_dim: (0, 0), view_dim: (0, 0), view_pos: (0, 0), cursors: CursorSet::new(), @@ -255,7 +262,19 @@ impl Editor { pub fn update_dim(&mut self, h: usize, w: usize) { - self.view_dim = (h, w); + self.editor_dim = (h, w); + self.update_view_dim(); + } + + + pub fn update_view_dim(&mut self) { + // TODO: generalize for non-terminal UI. Maybe this isn't where it + // belongs, in fact. But for now, this is the easiest place to put + // it. + let line_count_digits = digit_count(self.buffer.line_count() as u32, 10) as usize; + // Minus 1 vertically for the header, minus one more than the digits in + // the line count for the gutter. + self.view_dim = (self.editor_dim.0 - 1, self.editor_dim.1 - line_count_digits - 1); } diff --git a/src/main.rs b/src/main.rs index 724b435..151453b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -20,6 +20,7 @@ use term_ui::formatter::ConsoleLineFormatter; //use gui::formatter::GUILineFormatter; mod string_utils; +mod utils; mod buffer; mod formatter; mod editor; diff --git a/src/term_ui/mod.rs b/src/term_ui/mod.rs index 6a4169c..80b2855 100644 --- a/src/term_ui/mod.rs +++ b/src/term_ui/mod.rs @@ -7,6 +7,7 @@ use formatter::LineFormatter; use std::char; use std::time::duration::Duration; use string_utils::{is_line_ending}; +use utils::digit_count; use buffer::line::{line_ending_to_str, LineEnding}; use self::formatter::ConsoleLineFormatter; @@ -88,6 +89,8 @@ impl TermUI { loop { // Draw the editor to screen + self.editor.update_view_dim(); + self.editor.formatter.wrap_width = self.editor.view_dim.1; self.rb.clear(); self.draw_editor(&self.editor, (0, 0), (self.height-1, self.width-1)); self.rb.present(); @@ -195,9 +198,7 @@ impl TermUI { if let Some((h, w)) = resize { self.width = w as usize; self.height = h as usize; - self.editor.update_dim(self.height-1, self.width); - self.editor.formatter.wrap_width = self.width; - println!("Resized window!"); + self.editor.update_dim(self.height, self.width); } resize = None; @@ -220,6 +221,8 @@ impl TermUI { loop { // Draw the editor to screen + self.editor.update_view_dim(); + self.editor.formatter.wrap_width = self.editor.view_dim.1; self.rb.clear(); self.draw_editor(&self.editor, (0, 0), (self.height-1, self.width-1)); for i in 0..self.width { @@ -353,14 +356,29 @@ impl TermUI { fn draw_editor_text(&self, editor: &Editor, c1: (usize, usize), c2: (usize, usize)) { // Calculate all the starting info + let gutter_width = editor.editor_dim.1 - editor.view_dim.1; let (starting_line, _) = editor.buffer.index_to_line_col(editor.view_pos.0); let mut grapheme_index = editor.buffer.line_col_to_index((starting_line, 0)); let (vis_line_offset, _) = editor.formatter.index_to_v2d(editor.buffer.get_line(starting_line), editor.view_pos.0 - grapheme_index); let mut screen_line = c1.0 as isize - vis_line_offset as isize; - let screen_col = c1.1 as isize; + let screen_col = c1.1 as isize + gutter_width as isize; + // Fill in the gutter with the appropriate background + for y in c1.0..(c2.0+1) { + for x in c1.1..(c1.1+gutter_width-1) { + self.rb.print(x, y, rustbox::RB_NORMAL, Color::White, Color::Blue, " "); + } + } + + let mut line_num = starting_line + 1; for line in editor.buffer.line_iter_at_index(starting_line) { + // Print line number + let lnx = c1.1 + (gutter_width - 1 - digit_count(line_num as u32, 10) as usize); + let lny = screen_line as usize; + if lny >= c1.0 && lny <= c2.0 { + self.rb.print(lnx, lny, rustbox::RB_NORMAL, Color::White, Color::Blue, format!("{}", line_num).as_slice()); + } // Loop through the graphemes of the line and print them to // the screen. @@ -417,6 +435,7 @@ impl TermUI { let (dim_y, _) = editor.formatter.dimensions(line); screen_line += dim_y as isize; + line_num += 1; } diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..c9adb10 --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,34 @@ +pub fn digit_count(mut n: u32, b: u32) -> u32 { + let mut d = 0; + loop { + n /= b; + d += 1; + if n == 0 { + return d; + } + } +} + + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn digit_count_base_10() { + assert_eq!(digit_count(0, 10), 1); + assert_eq!(digit_count(9, 10), 1); + assert_eq!(digit_count(10, 10), 2); + assert_eq!(digit_count(99, 10), 2); + assert_eq!(digit_count(100, 10), 3); + assert_eq!(digit_count(999, 10), 3); + assert_eq!(digit_count(1000, 10), 4); + assert_eq!(digit_count(9999, 10), 4); + assert_eq!(digit_count(10000, 10), 5); + assert_eq!(digit_count(99999, 10), 5); + assert_eq!(digit_count(100000, 10), 6); + assert_eq!(digit_count(999999, 10), 6); + assert_eq!(digit_count(1000000, 10), 7); + assert_eq!(digit_count(9999999, 10), 7); + } +} \ No newline at end of file diff --git a/todo.md b/todo.md index f872e3d..3e9575c 100644 --- a/todo.md +++ b/todo.md @@ -17,7 +17,6 @@ - Word wrap. - Get non-wrapping text working again. -- Line number display - File opening by entering path - UI that wraps editors, for split view. - Persistent infinite undo