diff --git a/src/clipboard.rs b/src/clipboard.rs new file mode 100644 index 0000000..d9594b4 --- /dev/null +++ b/src/clipboard.rs @@ -0,0 +1,42 @@ +use std::{cell::RefCell, rc::Rc}; + +#[derive(Clone)] +pub struct Clipboard { + clipboard: Rc>, +} + +impl Clipboard { + pub fn new() -> Self { + Self { + clipboard: Rc::new(RefCell::new(Internal::new())), + } + } + + pub fn get(&self) -> String { + self.clipboard.borrow().get().to_owned() + } + + pub fn set(&mut self, text: String) { + self.clipboard.borrow_mut().set(text); + } +} + +struct Internal { + contents: String, +} + +impl Internal { + fn new() -> Self { + Self { + contents: String::new(), + } + } + + fn get(&self) -> &str { + &self.contents + } + + fn set(&mut self, text: String) { + self.contents = text; + } +} diff --git a/src/editor.rs b/src/editor.rs index 6d8ae98..31b847c 100644 --- a/src/editor.rs +++ b/src/editor.rs @@ -11,6 +11,7 @@ use termion::{ terminal_size, }; +use crate::clipboard::Clipboard; use crate::util::read_line; const TAB_SIZE: usize = 4; @@ -21,6 +22,7 @@ pub struct Editor { scroll: usize, cursor: Cursor, marker: Option, + clipboard: Clipboard, path: Option, active: bool, } @@ -35,7 +37,7 @@ struct Cursor { type Line = Range; impl Editor { - pub fn new(path: String) -> Self { + pub fn new(clipboard: Clipboard, path: String) -> Self { let text = fs::read_to_string(&path).unwrap_or_default(); let mut this = Editor { text, @@ -43,6 +45,7 @@ impl Editor { scroll: 0, cursor: Cursor { line: 0, column: 0 }, marker: None, + clipboard, path: Some(path), active: false, }; @@ -50,13 +53,14 @@ impl Editor { this } - pub fn new_empty() -> Self { + pub fn new_empty(clipboard: Clipboard) -> Self { Editor { text: String::new(), lines: vec![0..0], scroll: 0, cursor: Cursor { line: 0, column: 0 }, marker: None, + clipboard, path: None, active: false, } @@ -91,6 +95,9 @@ impl Editor { Key::End => self.move_end(), Key::Ctrl('s') => self.save(), Key::Ctrl('p') => self.toggle_marker(), + Key::Ctrl('c') => self.copy(), + Key::Ctrl('x') => self.cut(), + Key::Ctrl('v') => self.paste(), _ => (), } } @@ -129,7 +136,7 @@ impl Editor { if char == '\t' { print!("{:1$}", " ", TAB_SIZE); } else { - print!("{}", char); + print!("{char}"); } } color_reset(); @@ -272,6 +279,38 @@ impl Editor { } } + fn copy(&mut self) { + let cursor = self.char_index(); + let range = if let Some(marker) = self.marker { + marker.min(cursor)..marker.max(cursor) + } else { + self.current_line().clone() + }; + let text = self.text[range].to_owned(); + self.clipboard.set(text); + } + + fn cut(&mut self) { + let cursor = self.char_index(); + let range = if let Some(marker) = self.marker { + marker.min(cursor)..marker.max(cursor) + } else { + self.current_line().clone() + }; + let text = self.text[range.clone()].to_owned(); + self.clipboard.set(text); + self.text = self.text[..range.start].to_owned() + &self.text[range.end..]; + self.find_lines(); + self.marker = None; + } + + fn paste(&mut self) { + let cursor = self.char_index(); + self.text.insert_str(cursor, &self.clipboard.get()); + self.find_lines(); + // TODO move cursor to end + } + /// Byte position of current character. May be text.len if cursor is at the end of the file fn char_index(&self) -> usize { self.current_line().start + self.cursor.column diff --git a/src/main.rs b/src/main.rs index f1228e7..8c98bde 100644 --- a/src/main.rs +++ b/src/main.rs @@ -11,8 +11,10 @@ use termion::{ raw::{IntoRawMode, RawTerminal}, }; +mod clipboard; mod editor; mod util; +use clipboard::Clipboard; use editor::Editor; fn main() { @@ -22,18 +24,25 @@ fn main() { struct Navigator { editors: Vec, selected: Option, - path: String, + clipboard: Clipboard, _term: RawTerminal, } impl Navigator { fn new() -> Self { let term = stdout().into_raw_mode().unwrap(); - let editors = env::args().skip(1).map(Editor::new).collect(); + let clipboard = Clipboard::new(); + let mut editors: Vec = env::args() + .skip(1) + .map(|path| Editor::new(clipboard.clone(), path)) + .collect(); + if editors.is_empty() { + editors.push(Editor::new_empty(clipboard.clone())); + } Self { editors, selected: Some(0), - path: String::new(), + clipboard, _term: term, } } @@ -72,7 +81,7 @@ impl Navigator { for event in stdin().events().take(1).flatten() { if let Event::Key(key) = event { match key { - Key::Esc => self.quit(), + Key::Char('q') => self.quit(), Key::Char('\n') => self.open_selected(), Key::Ctrl('n') => self.new_editor(), Key::Up => self.nav_up(), @@ -105,7 +114,7 @@ impl Navigator { fn new_editor(&mut self) { self.selected = Some(self.editors.len()); - self.editors.push(Editor::new_empty()); + self.editors.push(Editor::new_empty(self.clipboard.clone())); self.open_selected(); }