From 6c8dd2edbec7b5a3999a986c130f6bb38e3b87da Mon Sep 17 00:00:00 2001 From: CrispyPin Date: Tue, 28 Feb 2023 21:52:12 +0100 Subject: [PATCH] text selection by placing a marker --- src/editor.rs | 60 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 53 insertions(+), 7 deletions(-) diff --git a/src/editor.rs b/src/editor.rs index d50d7d3..69287e4 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -2,11 +2,10 @@ use std::{ fs::{self, File}, io::{stdin, stdout, Write}, ops::Range, - process::exit, vec, }; use termion::{ - clear, cursor, + clear, color, cursor, event::{Event, Key}, input::TermRead, terminal_size, @@ -21,6 +20,7 @@ pub struct Editor { lines: Vec, scroll: usize, cursor: Cursor, + marker: Option, path: Option, active: bool, } @@ -42,6 +42,7 @@ impl Editor { lines: Vec::new(), scroll: 0, cursor: Cursor { line: 0, column: 0 }, + marker: None, path: Some(path), active: false, }; @@ -55,6 +56,7 @@ impl Editor { lines: vec![0..0], scroll: 0, cursor: Cursor { line: 0, column: 0 }, + marker: None, path: None, active: false, } @@ -88,6 +90,7 @@ impl Editor { Key::Home => self.move_home(), Key::End => self.move_end(), Key::Ctrl('s') => self.save(), + Key::Ctrl('p') => self.toggle_marker(), _ => (), } } @@ -101,13 +104,36 @@ impl Editor { let end = (self.scroll + max_rows).min(self.lines.len()); let visible_rows = self.scroll..end; + let cursor = self.char_index(); + let marker = self.marker.unwrap_or(0); + let selection = (marker.min(cursor))..(marker.max(cursor)); + for (line_index, line) in self.lines[visible_rows].iter().enumerate() { let text = &self.text[line.clone()]; - print!( - "{}{}", - cursor::Goto(1, line_index as u16 + 1), - text.replace('\t', &" ".repeat(TAB_SIZE)) - ); + + print!("{}", cursor::Goto(1, line_index as u16 + 1)); + + if self.marker.is_none() { + print!("{}", text.replace('\t', &" ".repeat(TAB_SIZE))); + } else { + let mut in_selection = false; + for (i, char) in text.chars().enumerate() { + let char_i = line.start + i; + if char_i >= selection.start && char_i <= selection.end && !in_selection { + color_selection(); + in_selection = true; + } else if char_i > selection.end && in_selection { + color_reset(); + in_selection = false; + } + if char == '\t' { + print!("{:1$}", " ", TAB_SIZE); + } else { + print!("{}", char); + } + } + color_reset(); + } } self.status_line(); print!( @@ -188,6 +214,14 @@ impl Editor { self.ensure_char_boundary(); } + fn toggle_marker(&mut self) { + if self.marker.is_some() { + self.marker = None; + } else { + self.marker = Some(self.char_index()); + } + } + /// Moves cursor left until it is on a character (in case it was in the middle of a multi-byte character) fn ensure_char_boundary(&mut self) { while !self @@ -281,3 +315,15 @@ impl Editor { file.write_all(self.text.as_bytes()).unwrap(); } } + +fn color_selection() { + print!( + "{}{}", + color::Fg(color::Black), + color::Bg(color::LightBlack) + ); +} + +fn color_reset() { + print!("{}{}", color::Fg(color::Reset), color::Bg(color::Reset)); +}