added a buffer to make moving around the file smoother

This commit is contained in:
FantasyPvP
2024-11-02 15:20:24 +00:00
parent 0f65124ded
commit 3d3eeb142f
+135 -54
View File
@@ -1,25 +1,100 @@
extern crate ncurses; extern crate ncurses;
use std::{env, fs::{self, File, OpenOptions}, io::Write}; use std::{
borrow::BorrowMut,
env,
fs::{self, OpenOptions},
io::Write,
};
struct EditorData { struct EditorData {
buffer: Vec<Vec<char>>, // outer vec is the line, inner is col;
file_line: i32, file_line: i32,
file_col: i32, file_col: i32,
buff_line: i32, screen_line: i32,
buff_col: i32, screen_col: i32,
editmode: bool, editmode: bool,
} }
impl EditorData { impl EditorData {
fn new() -> EditorData { fn new() -> EditorData {
EditorData { EditorData {
buffer: Vec::new(),
file_line: 0, file_line: 0,
file_col: 0, file_col: 0,
buff_line: 0, screen_line: 0,
buff_col: 0, screen_col: 0,
editmode: false, editmode: false,
} }
} }
fn from(s: String) -> EditorData {
EditorData {
buffer: s
.lines()
.map(|l| l.chars().collect())
.collect::<Vec<Vec<char>>>(),
file_line: 0,
file_col: 0,
screen_line: 0,
screen_col: 0,
editmode: false,
}
}
fn mv_cursor(&mut self, dy: i32, dx: i32) {
if dy != 0
&& self.screen_line + dy >= 0
&& self.screen_line + dy <= self.buffer.len() as i32
{
self.screen_line += dy;
let line_width = self.buffer[self.screen_line as usize].len() as i32;
if self.screen_col > line_width {
self.screen_col = line_width;
}
} else if self.screen_col + dx < 0 {
if self.screen_line - 1 >= 0 {
self.screen_line -= 1;
self.screen_col = self.buffer[self.screen_line as usize].len() as i32;
}
} else if self.screen_col + dx > self.buffer[self.screen_line as usize].len() as i32 {
if self.screen_line + 1 <= self.buffer.len() as i32 {
self.screen_col = 0;
self.screen_line += 1;
}
} else if dx != 0 {
self.screen_col += dx;
}
ncurses::mv(self.screen_line, self.screen_col);
}
fn delchar(&mut self) {
if self.screen_col == self.buffer[self.screen_line as usize].len() as i32 {
let oldline = self.buffer[1 + self.screen_line as usize].clone();
self.buffer[self.screen_line as usize].extend(&oldline);
self.buffer.remove(1 + self.screen_line as usize);
ncurses::clear();
let s = self.to_string();
ncurses::addstr(&s).unwrap();
}
self.buffer[self.file_line as usize].remove(self.file_col as usize);
ncurses::delch();
}
fn addchar(&mut self, c: char) {
self.buffer[self.screen_line as usize].insert(self.screen_col as usize, c);
}
}
impl ToString for EditorData {
fn to_string(&self) -> String {
self.buffer
.iter()
.map(|line| line.iter().collect::<String>())
.collect::<Vec<String>>()
.join("\n")
}
} }
fn main() { fn main() {
@@ -32,36 +107,53 @@ fn main() {
// "new" => new(&args[2]), // "new" => new(&args[2]),
// "mv" => mv(&args[2], &args[3]), // "mv" => mv(&args[2], &args[3]),
// "cp" => cp(&args[2], &args[3]), // "cp" => cp(&args[2], &args[3]),
// "len" => len(&args[2]), "lenc" => {
if let Ok(string) = fs::read_to_string(&args[2]) {
println!("{}", string.len());
}
}
"lenl" => {
if let Ok(string) = fs::read_to_string(&args[2]) {
println!(
"{}",
string
.chars()
.filter(|x| *x == '\n')
.collect::<String>()
.len()
);
}
}
// "log" => log(), // "log" => log(),
_ => help(), _ => help(),
} }
} else { } else {
help(); help();
} }
} }
fn help() { fn help() {
println!("Usage: println!(
"Usage:
cmd open <path/to/file> // opens the specified file cmd open <path/to/file> // opens the specified file
Write
cmd rm <path/to/file> // deletes the specified file cmd rm <path/to/file> // deletes the specified file
cmd new <path/to/file> // creates a new empty file at the specified path cmd new <path/to/file> // creates a new empty file at the specified path
cmd mv <path/to/file> <new/path> // moves the specified file to the new path cmd mv <path/to/file> <new/path> // moves the specified file to the new path
cmd cp <path/to/file> <new/path> // copies the specified file to the new path cmd cp <path/to/file> <new/path> // copies the specified file to the new path
cmd len <path/to/file> // returns the length of the specified file cmd lenc <path/to/file> // returns the length of the specified file in chars
cmd lenl <path/to/file> // returns the length of the specified file in lines
cmd log // prints a list of all changes made to the file cmd log // prints a list of all changes made to the file
") "
)
} }
fn open(filename: &str) -> Result<(), &'static str> { fn open(filename: &str) -> Result<(), &'static str> {
let filestr = match fs::read_to_string(filename) { let mut data = match fs::read_to_string(filename) {
Ok(s) => s, Ok(s) => EditorData::from(s),
Err(_) => return Err("file not found"), Err(_) => EditorData::new(),
}; };
let mut data = EditorData::new();
ncurses::initscr(); ncurses::initscr();
ncurses::raw(); ncurses::raw();
ncurses::noecho(); ncurses::noecho();
@@ -70,14 +162,14 @@ fn open(filename: &str) -> Result<(), &'static str> {
let mut max_x = 0; let mut max_x = 0;
ncurses::getmaxyx(ncurses::stdscr(), &mut max_y, &mut max_x); ncurses::getmaxyx(ncurses::stdscr(), &mut max_y, &mut max_x);
if let Err(_) = ncurses::addstr(&filestr) { let s = data.to_string();
if let Err(_) = ncurses::addstr(&s) {
ncurses::endwin(); ncurses::endwin();
return Err("error writing file to buffer"); return Err("error writing file to buffer");
}; };
ncurses::mv(0, 0); ncurses::mv(0, 0);
loop { loop {
ncurses::refresh(); ncurses::refresh();
let keystroke = ncurses::getch(); let keystroke = ncurses::getch();
@@ -85,28 +177,37 @@ fn open(filename: &str) -> Result<(), &'static str> {
if data.editmode { if data.editmode {
match keystroke { match keystroke {
27 => data.editmode = false, 27 => data.editmode = false,
ncurses::KEY_BACKSPACE => { ncurses::KEY_BACKSPACE => {
mv_cursor(&mut data, 0, -1); data.mv_cursor(0, -1);
ncurses::delch(); data.delchar();
}, }
ncurses::KEY_DC => { ncurses::delch(); }, ncurses::KEY_DC => {
ncurses::KEY_LEFT => mv_cursor(&mut data, 0, -1), data.delchar();
ncurses::KEY_RIGHT => mv_cursor(&mut data, 0, 1), }
ncurses::KEY_UP => mv_cursor(&mut data, -1, 0), ncurses::KEY_LEFT => data.mv_cursor(0, -1),
ncurses::KEY_DOWN => mv_cursor(&mut data, 1, 0), ncurses::KEY_RIGHT => data.mv_cursor(0, 1),
_ => { ncurses::insch(keystroke as u32); mv_cursor(&mut data, 0, 1); }, ncurses::KEY_UP => data.mv_cursor(-1, 0),
ncurses::KEY_DOWN => data.mv_cursor(1, 0),
_ => {
ncurses::insch(keystroke as u32);
data.addchar(char::from_u32(keystroke as u32).unwrap());
data.mv_cursor(0, 1);
}
} }
} else { } else {
match keystroke { match keystroke {
105 => { 105 => {
data.editmode = true; data.editmode = true;
}, }
119 => { 119 => {
let buff_size = max_y * max_x; let buff_size = max_y * max_x;
let mut buff = vec![0; buff_size as usize]; let mut buff = vec![0; buff_size as usize];
for i in 0..buff_size { for i in 0..buff_size {
buff[i as usize] = (ncurses::mvwinch(ncurses::stdscr(), i / max_x, i % max_x) & ncurses::A_CHARTEXT) as u8; buff[i as usize] =
(ncurses::mvwinch(ncurses::stdscr(), i / max_x, i % max_x)
& ncurses::A_CHARTEXT) as u8;
} }
ncurses::endwin(); ncurses::endwin();
@@ -121,29 +222,9 @@ fn open(filename: &str) -> Result<(), &'static str> {
113 => { 113 => {
ncurses::endwin(); ncurses::endwin();
return Ok(()); return Ok(());
}, }
_ => {}, _ => {}
} }
} }
} }
} }
fn mv_cursor(pos: &mut EditorData, dy: i32, dx: i32) {
if pos.file_col + dx >= 0 {
pos.file_col += dx;
}
if pos.buff_col + dx >= 0 {
pos.buff_col += dx;
}
if pos.file_line + dy >= 0 {
pos.file_line += dy;
}
if pos.buff_line + dy >= 0 {
pos.buff_line += dy;
}
ncurses::mv(pos.buff_line, pos.buff_col);
}