This commit is contained in:
mars 2023-04-12 17:14:51 -04:00
commit 6f81bab277
2 changed files with 83 additions and 23 deletions

View File

@ -33,7 +33,7 @@ use crate::{Cursor, Direction};
#[derive(Clone, Debug)]
pub struct Buffer {
styles: Arc<Mutex<StyleStore>>,
text: Rope,
pub text: Rope,
syntax_set: Arc<SyntaxSet>,
parser: ParseState,
style_dirty: bool,

View File

@ -19,8 +19,14 @@
use std::{
env::args,
fs::File,
io::{stdout, Read, Stdout, Write},
ffi::OsString,
fs::{ File, OpenOptions },
io::{
Read,
stdout,
Stdout,
Write,
},
os::fd::FromRawFd,
path::PathBuf,
sync::Arc,
@ -103,15 +109,16 @@ pub struct State {
pub styles: Arc<Mutex<StyleStore>>,
pub buffer: Buffer,
pub cursor: Cursor,
pub file: Option<OsString>,
pub mode: Mode,
pub scroll: Cursor,
pub size: (usize, usize),
pub mode: Mode,
pub quit: bool,
pub theme_tx: Sender<PathBuf>,
}
impl State {
pub fn from_str(text: &str) -> Result<Self> {
pub fn from_str(file_name: Option<OsString>, text: &str) -> Result<Self> {
let styles = Arc::new(Mutex::new(StyleStore::default()));
let buffer = Buffer::from_str(styles.clone(), text);
let (cols, rows) = terminal::size()?;
@ -121,9 +128,10 @@ impl State {
styles,
buffer,
cursor: Cursor::default(),
file: file_name,
mode: Mode::default(),
scroll: Cursor::default(),
size: (cols as usize, rows as usize),
mode: Mode::default(),
quit: false,
theme_tx,
})
@ -321,12 +329,53 @@ impl State {
}
}
fn execute_command(&mut self, command: &str) -> std::result::Result<(), String> {
match command {
"q" => self.quit = true,
command => return Err(format!("unrecognized command {:?}", command)),
}
fn write_buffer(&mut self, file: OsString) -> Result<()> {
let out = self.buffer.text.bytes().collect::<Vec<u8>>();
let mut handle = OpenOptions::new().write(true).open(file)?;
handle.write_all(out.as_slice())?;
Ok(())
}
fn execute_command(&mut self, command: &str) -> std::result::Result<(), String> {
let command_parts = command.split(' ').collect::<Vec<&str>>();
let commands = match command_parts.get(0) {
Some(parts) => parts.chars().collect::<Vec<char>>(),
None => return Ok(()),
};
for command in commands.clone().iter() {
match command {
'q' => self.quit = true,
'w' => {
let handle: OsString;
if let Some(part) = self.file.clone() {
handle = part;
} else {
handle = match command_parts.get(1) {
Some(part) => OsString::from(part),
None => {
return Err(
format!("{}: No file name.", command)
);
},
};
}
self.write_buffer(handle).map_err(|err| {
format!("{}", err)
})?;
},
command => {
return Err(
format!("{}: Unrecognized command.", command)
);
},
}
}
Ok(())
}
@ -363,23 +412,34 @@ fn screen_main(stdout: &mut Stdout, mut state: State) -> Result<()> {
fn main() -> Result<()> {
let argv = args().collect::<Vec<String>>();
let mut buf = Vec::new();
let file_name: Option<OsString>;
match argv.get(1).map(|s| s.as_str()) {
Some("-") | None => {
file_name = None;
let stdin = 0; // get stdin as a file descriptor
if unsafe { libc::isatty(stdin) } == 0 {
unsafe { File::from_raw_fd(stdin) }
} else {
File::open("/dev/null").unwrap()
}
}
Some(path) => std::fs::File::open(path).unwrap_or_else(|_| {
eprintln!("{}: {}: No such file or directory.", argv[0], argv[1]);
exit(EX_UNAVAILABLE);
}),
}
.read_to_end(&mut buf)
.unwrap();
} else { File::open("/dev/null").unwrap() }
},
Some(path) => {
let input_file = Path::new(path);
file_name = Some(OsString::from(
input_file.clone().display().to_string()
));
File::open(input_file).unwrap_or_else(|_| {
let mut err = String::new();
if !input_file.exists() {
err = "No such file or directory.".to_string();
} else if input_file.is_dir() {
err = "Is a directory.".to_string();
}
eprintln!("{}: {}: {}", argv[0], path, err);
exit(EX_UNAVAILABLE);
})
},
}.read_to_end(&mut buf).unwrap();
let text = String::from_utf8(buf).unwrap_or_else(|_| {
eprintln!(
@ -389,7 +449,7 @@ fn main() -> Result<()> {
exit(EX_DATAERR);
});
let state = State::from_str(&text)?;
let state = State::from_str(file_name, &text)?;
let mut stdout = stdout();
terminal::enable_raw_mode()?;
stdout.execute(terminal::EnterAlternateScreen)?;