navigator skeleton

This commit is contained in:
Crispy 2023-02-28 12:41:34 +01:00
parent a65a1cc9b8
commit 1e827acfdd
3 changed files with 107 additions and 28 deletions

View file

@ -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;

View file

@ -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);
}
} }

View file

@ -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,