navigator skeleton
This commit is contained in:
parent
a65a1cc9b8
commit
1e827acfdd
3 changed files with 107 additions and 28 deletions
|
@ -1,6 +1,6 @@
|
||||||
use std::{
|
use std::{
|
||||||
fs::{self, File},
|
fs::{self, File},
|
||||||
io::{stdin, stdout, Stdout, Write},
|
io::{stdin, stdout, Write},
|
||||||
ops::Range,
|
ops::Range,
|
||||||
process::exit,
|
process::exit,
|
||||||
};
|
};
|
||||||
|
@ -8,7 +8,6 @@ use termion::{
|
||||||
clear, cursor,
|
clear, cursor,
|
||||||
event::{Event, Key},
|
event::{Event, Key},
|
||||||
input::TermRead,
|
input::TermRead,
|
||||||
raw::{IntoRawMode, RawTerminal},
|
|
||||||
terminal_size,
|
terminal_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -22,8 +21,7 @@ pub struct Editor {
|
||||||
scroll: usize,
|
scroll: usize,
|
||||||
cursor: Cursor,
|
cursor: Cursor,
|
||||||
path: Option<String>,
|
path: Option<String>,
|
||||||
_term: RawTerminal<Stdout>,
|
pub quit: bool,
|
||||||
quit: bool,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -47,33 +45,23 @@ impl Editor {
|
||||||
})
|
})
|
||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let term = stdout().into_raw_mode().unwrap();
|
let mut this = Editor {
|
||||||
|
|
||||||
Editor {
|
|
||||||
text,
|
text,
|
||||||
lines: Vec::new(),
|
lines: Vec::new(),
|
||||||
scroll: 0,
|
scroll: 0,
|
||||||
cursor: Cursor { line: 0, column: 0 },
|
cursor: Cursor { line: 0, column: 0 },
|
||||||
_term: term,
|
|
||||||
path,
|
path,
|
||||||
quit: false,
|
quit: false,
|
||||||
}
|
};
|
||||||
|
this.find_lines();
|
||||||
|
this
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run(mut self) {
|
pub fn name(&self) -> &str {
|
||||||
print!("{}", clear::All);
|
self.path.as_ref().map_or("untitled", |s| &s)
|
||||||
stdout().flush().unwrap();
|
|
||||||
|
|
||||||
self.find_lines();
|
|
||||||
|
|
||||||
while !self.quit {
|
|
||||||
self.draw();
|
|
||||||
self.input();
|
|
||||||
}
|
|
||||||
print!("{}", clear::All);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn input(&mut self) {
|
pub fn input(&mut self) {
|
||||||
for event in stdin().events().take(1).flatten() {
|
for event in stdin().events().take(1).flatten() {
|
||||||
// dbg!(&event);
|
// dbg!(&event);
|
||||||
if let Event::Key(key) = event {
|
if let Event::Key(key) = event {
|
||||||
|
@ -86,6 +74,8 @@ impl Editor {
|
||||||
Key::Right => self.move_right(),
|
Key::Right => self.move_right(),
|
||||||
Key::Up => self.move_up(),
|
Key::Up => self.move_up(),
|
||||||
Key::Down => self.move_down(),
|
Key::Down => self.move_down(),
|
||||||
|
Key::Home => self.move_home(),
|
||||||
|
Key::End => self.move_end(),
|
||||||
Key::Ctrl('s') => self.save(),
|
Key::Ctrl('s') => self.save(),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
@ -141,6 +131,15 @@ impl Editor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn move_home(&mut self) {
|
||||||
|
self.cursor.column = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn move_end(&mut self) {
|
||||||
|
self.cursor.column = self.current_line().len();
|
||||||
|
self.ensure_char_boundary();
|
||||||
|
}
|
||||||
|
|
||||||
/// 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
|
||||||
|
@ -169,7 +168,7 @@ impl Editor {
|
||||||
self.lines.push(this_line);
|
self.lines.push(this_line);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw(&self) {
|
pub fn draw(&self) {
|
||||||
print!("{}", clear::All);
|
print!("{}", clear::All);
|
||||||
|
|
||||||
let max_rows = terminal_size().unwrap().1 as usize - 1;
|
let max_rows = terminal_size().unwrap().1 as usize - 1;
|
||||||
|
|
87
src/main.rs
87
src/main.rs
|
@ -1,9 +1,92 @@
|
||||||
use std::env;
|
use std::{
|
||||||
|
env,
|
||||||
|
io::{stdin, stdout, Stdout, Write},
|
||||||
|
process::exit,
|
||||||
|
};
|
||||||
|
use termion::{
|
||||||
|
clear, color,
|
||||||
|
cursor::Goto,
|
||||||
|
event::{Event, Key},
|
||||||
|
input::TermRead,
|
||||||
|
raw::{IntoRawMode, RawTerminal},
|
||||||
|
};
|
||||||
|
|
||||||
mod editor;
|
mod editor;
|
||||||
mod util;
|
mod util;
|
||||||
use editor::Editor;
|
use editor::Editor;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
Editor::new(env::args().nth(1)).run();
|
Navigator::new(env::args().nth(1)).run();
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Navigator {
|
||||||
|
editors: Vec<Editor>,
|
||||||
|
active: Option<usize>,
|
||||||
|
selected: Option<usize>,
|
||||||
|
path: String,
|
||||||
|
_term: RawTerminal<Stdout>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Navigator {
|
||||||
|
fn new(immediate_file: Option<String>) -> Self {
|
||||||
|
let term = stdout().into_raw_mode().unwrap();
|
||||||
|
let editors = vec![Editor::new(immediate_file)];
|
||||||
|
Self {
|
||||||
|
editors,
|
||||||
|
active: Some(0),
|
||||||
|
selected: None,
|
||||||
|
path: String::new(), // TODO
|
||||||
|
_term: term,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run(mut self) {
|
||||||
|
print!("{}", clear::All);
|
||||||
|
stdout().flush().unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
if let Some(index) = self.active {
|
||||||
|
self.editors[index].draw();
|
||||||
|
self.editors[index].input();
|
||||||
|
|
||||||
|
if self.editors[index].quit {
|
||||||
|
self.selected = self.active;
|
||||||
|
self.active = None;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.draw();
|
||||||
|
self.input();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn draw(&self) {
|
||||||
|
print!("{}{}Open editors: {}", clear::All, Goto(1,1), self.editors.len());
|
||||||
|
|
||||||
|
for (index, editor) in self.editors.iter().enumerate() {
|
||||||
|
if Some(index) == self.selected {
|
||||||
|
print!("{}{}", color::Fg(color::Black), color::Bg(color::White));
|
||||||
|
}
|
||||||
|
print!("{}{}", Goto(2, index as u16 + 2), editor.name());
|
||||||
|
print!("{}{}", color::Fg(color::Reset), color::Bg(color::Reset));
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout().flush().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input(&mut self) {
|
||||||
|
for event in stdin().events().take(1).flatten() {
|
||||||
|
if let Event::Key(key) = event {
|
||||||
|
match key {
|
||||||
|
Key::Esc => self.quit(),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn quit(&self) {
|
||||||
|
print!("{}", clear::All);
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
use std::io::{stdin, stdout, Write};
|
use std::io::{stdin, stdout, Write};
|
||||||
|
|
||||||
use termion::{
|
use termion::{
|
||||||
cursor,
|
cursor,
|
||||||
event::{Event, Key},
|
event::{Event, Key},
|
||||||
|
@ -22,9 +21,7 @@ pub fn read_line(prompt: &str) -> Option<String> {
|
||||||
Key::Char('\n') => break,
|
Key::Char('\n') => break,
|
||||||
Key::Char(ch) => response.push(ch),
|
Key::Char(ch) => response.push(ch),
|
||||||
Key::Backspace => {
|
Key::Backspace => {
|
||||||
if !response.is_empty() {
|
response.pop();
|
||||||
response.remove(response.len() - 1);
|
|
||||||
}
|
|
||||||
print!("{start_pos}{:width$}", " ");
|
print!("{start_pos}{:width$}", " ");
|
||||||
}
|
}
|
||||||
Key::Esc => return None,
|
Key::Esc => return None,
|
||||||
|
|
Loading…
Reference in a new issue