add clipboard

This commit is contained in:
Crispy 2023-03-01 22:16:10 +01:00
parent 59b45f57c3
commit 5ece5b7198
3 changed files with 98 additions and 8 deletions

42
src/clipboard.rs Normal file
View file

@ -0,0 +1,42 @@
use std::{cell::RefCell, rc::Rc};
#[derive(Clone)]
pub struct Clipboard {
clipboard: Rc<RefCell<Internal>>,
}
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;
}
}

View file

@ -11,6 +11,7 @@ use termion::{
terminal_size, terminal_size,
}; };
use crate::clipboard::Clipboard;
use crate::util::read_line; use crate::util::read_line;
const TAB_SIZE: usize = 4; const TAB_SIZE: usize = 4;
@ -21,6 +22,7 @@ pub struct Editor {
scroll: usize, scroll: usize,
cursor: Cursor, cursor: Cursor,
marker: Option<usize>, marker: Option<usize>,
clipboard: Clipboard,
path: Option<String>, path: Option<String>,
active: bool, active: bool,
} }
@ -35,7 +37,7 @@ struct Cursor {
type Line = Range<usize>; type Line = Range<usize>;
impl Editor { 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 text = fs::read_to_string(&path).unwrap_or_default();
let mut this = Editor { let mut this = Editor {
text, text,
@ -43,6 +45,7 @@ impl Editor {
scroll: 0, scroll: 0,
cursor: Cursor { line: 0, column: 0 }, cursor: Cursor { line: 0, column: 0 },
marker: None, marker: None,
clipboard,
path: Some(path), path: Some(path),
active: false, active: false,
}; };
@ -50,13 +53,14 @@ impl Editor {
this this
} }
pub fn new_empty() -> Self { pub fn new_empty(clipboard: Clipboard) -> Self {
Editor { Editor {
text: String::new(), text: String::new(),
lines: vec![0..0], lines: vec![0..0],
scroll: 0, scroll: 0,
cursor: Cursor { line: 0, column: 0 }, cursor: Cursor { line: 0, column: 0 },
marker: None, marker: None,
clipboard,
path: None, path: None,
active: false, active: false,
} }
@ -91,6 +95,9 @@ impl Editor {
Key::End => self.move_end(), Key::End => self.move_end(),
Key::Ctrl('s') => self.save(), Key::Ctrl('s') => self.save(),
Key::Ctrl('p') => self.toggle_marker(), 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' { if char == '\t' {
print!("{:1$}", " ", TAB_SIZE); print!("{:1$}", " ", TAB_SIZE);
} else { } else {
print!("{}", char); print!("{char}");
} }
} }
color_reset(); 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 /// Byte position of current character. May be text.len if cursor is at the end of the file
fn char_index(&self) -> usize { fn char_index(&self) -> usize {
self.current_line().start + self.cursor.column self.current_line().start + self.cursor.column

View file

@ -11,8 +11,10 @@ use termion::{
raw::{IntoRawMode, RawTerminal}, raw::{IntoRawMode, RawTerminal},
}; };
mod clipboard;
mod editor; mod editor;
mod util; mod util;
use clipboard::Clipboard;
use editor::Editor; use editor::Editor;
fn main() { fn main() {
@ -22,18 +24,25 @@ fn main() {
struct Navigator { struct Navigator {
editors: Vec<Editor>, editors: Vec<Editor>,
selected: Option<usize>, selected: Option<usize>,
path: String, clipboard: Clipboard,
_term: RawTerminal<Stdout>, _term: RawTerminal<Stdout>,
} }
impl Navigator { impl Navigator {
fn new() -> Self { fn new() -> Self {
let term = stdout().into_raw_mode().unwrap(); 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<Editor> = env::args()
.skip(1)
.map(|path| Editor::new(clipboard.clone(), path))
.collect();
if editors.is_empty() {
editors.push(Editor::new_empty(clipboard.clone()));
}
Self { Self {
editors, editors,
selected: Some(0), selected: Some(0),
path: String::new(), clipboard,
_term: term, _term: term,
} }
} }
@ -72,7 +81,7 @@ impl Navigator {
for event in stdin().events().take(1).flatten() { for event in stdin().events().take(1).flatten() {
if let Event::Key(key) = event { if let Event::Key(key) = event {
match key { match key {
Key::Esc => self.quit(), Key::Char('q') => self.quit(),
Key::Char('\n') => self.open_selected(), Key::Char('\n') => self.open_selected(),
Key::Ctrl('n') => self.new_editor(), Key::Ctrl('n') => self.new_editor(),
Key::Up => self.nav_up(), Key::Up => self.nav_up(),
@ -105,7 +114,7 @@ impl Navigator {
fn new_editor(&mut self) { fn new_editor(&mut self) {
self.selected = Some(self.editors.len()); self.selected = Some(self.editors.len());
self.editors.push(Editor::new_empty()); self.editors.push(Editor::new_empty(self.clipboard.clone()));
self.open_selected(); self.open_selected();
} }