From f760d6078d884a020b642bc0d5993ac0f8130b9d Mon Sep 17 00:00:00 2001 From: Nathan Vegdahl Date: Sat, 3 Jan 2015 13:09:12 -0800 Subject: [PATCH] Added jump-to-line functionality and fixed some display bugs. --- src/editor.rs | 10 ++++ src/main.rs | 2 +- src/term_ui.rs | 160 ++++++++++++++++++++++++++++++++++++++++++------- todo.md | 1 + 4 files changed, 150 insertions(+), 23 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index 2fc1d1c..3eee76e 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -296,4 +296,14 @@ impl Editor { // Adjust view self.move_view_to_cursor(); } + + pub fn jump_to_line(&mut self, n: uint) { + let pos = self.buffer.pos_2d_to_closest_1d((n, 0)); + let (v, _) = self.buffer.pos_1d_to_closest_vis_2d(pos); + self.cursor.range.0 = self.buffer.pos_vis_2d_to_closest_1d((v, self.cursor.vis_start)); + self.cursor.range.1 = self.cursor.range.0; + + // Adjust view + self.move_view_to_cursor(); + } } diff --git a/src/main.rs b/src/main.rs index 77f049f..1a50265 100644 --- a/src/main.rs +++ b/src/main.rs @@ -50,7 +50,7 @@ fn main() { // Initialize and start UI let mut ui = TermUI::new_from_editor(editor); - ui.ui_loop(); + ui.main_ui_loop(); //println!("{}", editor.buffer.root.tree_height); } diff --git a/src/term_ui.rs b/src/term_ui.rs index 5f7ed64..4eb946b 100644 --- a/src/term_ui.rs +++ b/src/term_ui.rs @@ -20,6 +20,8 @@ const K_DOWN: u16 = 65516; const K_LEFT: u16 = 65515; const K_RIGHT: u16 = 65514; const K_ESC: u16 = 27; +const K_CTRL_L: u16 = 12; +const K_CTRL_O: u16 = 15; const K_CTRL_Q: u16 = 17; const K_CTRL_S: u16 = 19; @@ -27,36 +29,52 @@ const K_CTRL_S: u16 = 19; pub struct TermUI { rb: rustbox::RustBox, editor: Editor, + width: uint, + height: uint, } impl TermUI { pub fn new() -> TermUI { + let rb = rustbox::RustBox::init(&[Some(rustbox::InitOption::BufferStderr)]).unwrap(); + let w = rb.width(); + let h = rb.height(); + let mut editor = Editor::new(); + editor.update_dim(h-1, w); + TermUI { - rb: rustbox::RustBox::init(&[Some(rustbox::InitOption::BufferStderr)]).unwrap(), - editor: Editor::new(), - } - } - - pub fn new_from_editor(editor: Editor) -> TermUI { - TermUI { - rb: rustbox::RustBox::init(&[Some(rustbox::InitOption::BufferStderr)]).unwrap(), + rb: rb, editor: editor, + width: w, + height: h, } } - pub fn ui_loop(&mut self) { + pub fn new_from_editor(ed: Editor) -> TermUI { + let rb = rustbox::RustBox::init(&[Some(rustbox::InitOption::BufferStderr)]).unwrap(); + let w = rb.width(); + let h = rb.height(); + let mut editor = ed; + editor.update_dim(h-1, w); + + TermUI { + rb: rb, + editor: editor, + width: w, + height: h, + } + } + + pub fn main_ui_loop(&mut self) { // Quitting flag let mut quit = false; - let mut width = self.rb.width(); - let mut height = self.rb.height(); - self.editor.update_dim(height, width); + self.editor.update_dim(self.height-1, self.width); loop { // Draw the editor to screen self.rb.clear(); - self.draw_editor(&self.editor, (0, 0), (height-1, width-1)); + self.draw_editor(&self.editor, (0, 0), (self.height-1, self.width-1)); self.rb.present(); @@ -70,7 +88,7 @@ impl TermUI { Ok(rustbox::Event::KeyEvent(modifier, key, character)) => { //println!(" {} {} {}", modifier, key, character); match key { - K_CTRL_Q | K_ESC => { + K_CTRL_Q => { quit = true; break; }, @@ -79,6 +97,10 @@ impl TermUI { self.editor.save_if_dirty(); }, + K_CTRL_L => { + self.go_to_line_ui_loop(); + }, + K_PAGEUP => { self.editor.page_up(); }, @@ -135,10 +157,10 @@ impl TermUI { }, Ok(rustbox::Event::ResizeEvent(w, h)) => { - width = w as uint; - height = h as uint; - self.editor.update_dim(height, width); - } + self.width = w as uint; + self.height = h as uint; + self.editor.update_dim(self.height-1, self.width); + }, _ => { break; @@ -157,7 +179,101 @@ impl TermUI { } - pub fn draw_editor(&self, editor: &Editor, c1: (uint, uint), c2: (uint, uint)) { + fn go_to_line_ui_loop(&mut self) { + let foreground = Color::Black; + let background = Color::Cyan; + + let mut cancel = false; + let mut confirm = false; + let prefix = "Jump to line: "; + let mut line = String::new(); + + loop { + // Draw the editor to screen + self.rb.clear(); + self.draw_editor(&self.editor, (0, 0), (self.height-1, self.width-1)); + for i in range(0, self.width) { + self.rb.print(i, 0, rustbox::RB_NORMAL, foreground, background, " "); + } + self.rb.print(1, 0, rustbox::RB_NORMAL, foreground, background, prefix); + self.rb.print(prefix.len() + 1, 0, rustbox::RB_NORMAL, foreground, background, line.as_slice()); + self.rb.present(); + + + // Handle events. We block on the first event, so that the + // program doesn't loop like crazy, but then continue pulling + // events in a non-blocking way until we run out of events + // to handle. + let mut e = self.rb.poll_event(); // Block until we get an event + loop { + match e { + Ok(rustbox::Event::KeyEvent(modifier, key, character)) => { + match key { + K_ESC => { + cancel = true; + break; + }, + + K_ENTER => { + confirm = true; + break; + }, + + K_BACKSPACE => { + line.pop(); + }, + + // Character + 0 => { + if let Option::Some(c) = char::from_u32(character) { + if c.is_numeric() { + line.push(c); + } + } + }, + + _ => {} + } + }, + + Ok(rustbox::Event::ResizeEvent(w, h)) => { + self.width = w as uint; + self.height = h as uint; + self.editor.update_dim(self.height-1, self.width); + }, + + _ => { + break; + } + } + + e = self.rb.peek_event(Duration::milliseconds(0)); // Get next event (if any) + } + + + // Cancel if flag is set + if cancel { + break; + } + + // Jump to line! + if confirm { + if let Some(n) = line.parse() { + let n2: uint = n; // Weird work-around: the type of n wasn't being inferred + if n2 > 0 { + self.editor.jump_to_line(n2-1); + } + else { + self.editor.jump_to_line(0); + } + } + break; + } + } + } + + + fn draw_editor(&self, editor: &Editor, c1: (uint, uint), c2: (uint, uint)) { let foreground = Color::Black; let background = Color::Cyan; @@ -191,7 +307,7 @@ impl TermUI { } - pub fn draw_editor_text(&self, editor: &Editor, c1: (uint, uint), c2: (uint, uint)) { + fn draw_editor_text(&self, editor: &Editor, c1: (uint, uint), c2: (uint, uint)) { let mut line_iter = editor.buffer.line_iter_at_index(editor.view_pos.0); let mut grapheme_index; @@ -202,8 +318,8 @@ impl TermUI { let mut print_line_num = c1.0; let mut print_col_num = c1.1; - let max_print_line = c2.0 - c1.0; - let max_print_col = c2.1 - c1.1; + let max_print_line = c2.0; + let max_print_col = c2.1; loop { if let Some(line) = line_iter.next() { diff --git a/todo.md b/todo.md index 7b8107a..8028a23 100644 --- a/todo.md +++ b/todo.md @@ -1,3 +1,4 @@ - Line number display - File opening by entering path - UI that wraps editors, for split view. +- Undo functionality \ No newline at end of file