Merge branch 'main' of https://git.tebibyte.media/emma/breed into emma-main

This commit is contained in:
mars 2023-04-12 12:57:36 -04:00
commit beab2783f7
2 changed files with 87 additions and 22 deletions

View File

@ -59,6 +59,10 @@ impl Buffer {
buf
}
pub fn to_bytes(&self) -> Vec<u8> {
self.text.to_string().into_bytes()
}
pub fn draw(
&self,
styles: &mut StyleStore,

View File

@ -19,9 +19,16 @@
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::Path,
sync::Arc,
};
@ -99,14 +106,15 @@ 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,
}
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()?;
@ -115,9 +123,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,
})
}
@ -331,12 +340,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.to_bytes();
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(())
}
@ -370,23 +420,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!(
@ -396,7 +457,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)?;