text selection by placing a marker
This commit is contained in:
parent
33ee68acad
commit
6c8dd2edbe
1 changed files with 53 additions and 7 deletions
|
@ -2,11 +2,10 @@ use std::{
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{stdin, stdout, Write},
|
io::{stdin, stdout, Write},
|
||||||
ops::Range,
|
ops::Range,
|
||||||
process::exit,
|
|
||||||
vec,
|
vec,
|
||||||
};
|
};
|
||||||
use termion::{
|
use termion::{
|
||||||
clear, cursor,
|
clear, color, cursor,
|
||||||
event::{Event, Key},
|
event::{Event, Key},
|
||||||
input::TermRead,
|
input::TermRead,
|
||||||
terminal_size,
|
terminal_size,
|
||||||
|
@ -21,6 +20,7 @@ pub struct Editor {
|
||||||
lines: Vec<Line>,
|
lines: Vec<Line>,
|
||||||
scroll: usize,
|
scroll: usize,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
|
marker: Option<usize>,
|
||||||
path: Option<String>,
|
path: Option<String>,
|
||||||
active: bool,
|
active: bool,
|
||||||
}
|
}
|
||||||
|
@ -42,6 +42,7 @@ impl Editor {
|
||||||
lines: Vec::new(),
|
lines: Vec::new(),
|
||||||
scroll: 0,
|
scroll: 0,
|
||||||
cursor: Cursor { line: 0, column: 0 },
|
cursor: Cursor { line: 0, column: 0 },
|
||||||
|
marker: None,
|
||||||
path: Some(path),
|
path: Some(path),
|
||||||
active: false,
|
active: false,
|
||||||
};
|
};
|
||||||
|
@ -55,6 +56,7 @@ impl Editor {
|
||||||
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,
|
||||||
path: None,
|
path: None,
|
||||||
active: false,
|
active: false,
|
||||||
}
|
}
|
||||||
|
@ -88,6 +90,7 @@ impl Editor {
|
||||||
Key::Home => self.move_home(),
|
Key::Home => self.move_home(),
|
||||||
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(),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,13 +104,36 @@ impl Editor {
|
||||||
let end = (self.scroll + max_rows).min(self.lines.len());
|
let end = (self.scroll + max_rows).min(self.lines.len());
|
||||||
let visible_rows = self.scroll..end;
|
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() {
|
for (line_index, line) in self.lines[visible_rows].iter().enumerate() {
|
||||||
let text = &self.text[line.clone()];
|
let text = &self.text[line.clone()];
|
||||||
print!(
|
|
||||||
"{}{}",
|
print!("{}", cursor::Goto(1, line_index as u16 + 1));
|
||||||
cursor::Goto(1, line_index as u16 + 1),
|
|
||||||
text.replace('\t', &" ".repeat(TAB_SIZE))
|
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();
|
self.status_line();
|
||||||
print!(
|
print!(
|
||||||
|
@ -188,6 +214,14 @@ impl Editor {
|
||||||
self.ensure_char_boundary();
|
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)
|
/// 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) {
|
fn ensure_char_boundary(&mut self) {
|
||||||
while !self
|
while !self
|
||||||
|
@ -281,3 +315,15 @@ impl Editor {
|
||||||
file.write_all(self.text.as_bytes()).unwrap();
|
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));
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue