add clipboard
This commit is contained in:
parent
59b45f57c3
commit
5ece5b7198
3 changed files with 98 additions and 8 deletions
42
src/clipboard.rs
Normal file
42
src/clipboard.rs
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
|
19
src/main.rs
19
src/main.rs
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue