added a buffer to make moving around the file smoother
This commit is contained in:
+131
-50
@@ -1,25 +1,100 @@
|
||||
extern crate ncurses;
|
||||
|
||||
use std::{env, fs::{self, File, OpenOptions}, io::Write};
|
||||
use std::{
|
||||
borrow::BorrowMut,
|
||||
env,
|
||||
fs::{self, OpenOptions},
|
||||
io::Write,
|
||||
};
|
||||
|
||||
struct EditorData {
|
||||
buffer: Vec<Vec<char>>, // outer vec is the line, inner is col;
|
||||
file_line: i32,
|
||||
file_col: i32,
|
||||
buff_line: i32,
|
||||
buff_col: i32,
|
||||
screen_line: i32,
|
||||
screen_col: i32,
|
||||
editmode: bool,
|
||||
}
|
||||
|
||||
impl EditorData {
|
||||
fn new() -> EditorData {
|
||||
EditorData {
|
||||
buffer: Vec::new(),
|
||||
file_line: 0,
|
||||
file_col: 0,
|
||||
buff_line: 0,
|
||||
buff_col: 0,
|
||||
screen_line: 0,
|
||||
screen_col: 0,
|
||||
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() {
|
||||
@@ -32,36 +107,53 @@ fn main() {
|
||||
// "new" => new(&args[2]),
|
||||
// "mv" => mv(&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(),
|
||||
_ => help(),
|
||||
}
|
||||
} else {
|
||||
help();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn help() {
|
||||
println!("Usage:
|
||||
println!(
|
||||
"Usage:
|
||||
cmd open <path/to/file> // opens the specified file
|
||||
Write
|
||||
cmd rm <path/to/file> // deletes the specified file
|
||||
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 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
|
||||
")
|
||||
"
|
||||
)
|
||||
}
|
||||
|
||||
fn open(filename: &str) -> Result<(), &'static str> {
|
||||
let filestr = match fs::read_to_string(filename) {
|
||||
Ok(s) => s,
|
||||
Err(_) => return Err("file not found"),
|
||||
let mut data = match fs::read_to_string(filename) {
|
||||
Ok(s) => EditorData::from(s),
|
||||
Err(_) => EditorData::new(),
|
||||
};
|
||||
|
||||
let mut data = EditorData::new();
|
||||
|
||||
ncurses::initscr();
|
||||
ncurses::raw();
|
||||
ncurses::noecho();
|
||||
@@ -70,14 +162,14 @@ fn open(filename: &str) -> Result<(), &'static str> {
|
||||
let mut max_x = 0;
|
||||
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();
|
||||
return Err("error writing file to buffer");
|
||||
};
|
||||
|
||||
ncurses::mv(0, 0);
|
||||
|
||||
|
||||
loop {
|
||||
ncurses::refresh();
|
||||
let keystroke = ncurses::getch();
|
||||
@@ -86,27 +178,36 @@ fn open(filename: &str) -> Result<(), &'static str> {
|
||||
match keystroke {
|
||||
27 => data.editmode = false,
|
||||
ncurses::KEY_BACKSPACE => {
|
||||
mv_cursor(&mut data, 0, -1);
|
||||
ncurses::delch();
|
||||
},
|
||||
ncurses::KEY_DC => { ncurses::delch(); },
|
||||
ncurses::KEY_LEFT => mv_cursor(&mut data, 0, -1),
|
||||
ncurses::KEY_RIGHT => mv_cursor(&mut data, 0, 1),
|
||||
ncurses::KEY_UP => mv_cursor(&mut data, -1, 0),
|
||||
ncurses::KEY_DOWN => mv_cursor(&mut data, 1, 0),
|
||||
_ => { ncurses::insch(keystroke as u32); mv_cursor(&mut data, 0, 1); },
|
||||
data.mv_cursor(0, -1);
|
||||
data.delchar();
|
||||
}
|
||||
ncurses::KEY_DC => {
|
||||
data.delchar();
|
||||
}
|
||||
ncurses::KEY_LEFT => data.mv_cursor(0, -1),
|
||||
ncurses::KEY_RIGHT => data.mv_cursor(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 {
|
||||
match keystroke {
|
||||
105 => {
|
||||
data.editmode = true;
|
||||
},
|
||||
}
|
||||
119 => {
|
||||
let buff_size = max_y * max_x;
|
||||
let mut buff = vec![0; buff_size as usize];
|
||||
|
||||
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();
|
||||
|
||||
@@ -121,29 +222,9 @@ fn open(filename: &str) -> Result<(), &'static str> {
|
||||
113 => {
|
||||
ncurses::endwin();
|
||||
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);
|
||||
}
|
||||
Reference in New Issue
Block a user