forked from mars/breed
basic file handling
This commit is contained in:
parent
9c633b4c72
commit
aee17365c6
65
src/main.rs
65
src/main.rs
|
@ -19,7 +19,8 @@
|
|||
|
||||
use std::{
|
||||
env::args,
|
||||
fs::File,
|
||||
ffi::OsString,
|
||||
fs::{ File, write },
|
||||
io::{
|
||||
Read,
|
||||
stdout,
|
||||
|
@ -27,6 +28,7 @@ use std::{
|
|||
Write,
|
||||
},
|
||||
os::fd::FromRawFd,
|
||||
path::{ Path }
|
||||
};
|
||||
|
||||
use crossterm::{
|
||||
|
@ -194,22 +196,24 @@ enum Direction {
|
|||
struct State {
|
||||
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 (cols, rows) = terminal::size()?;
|
||||
|
||||
Ok(Self {
|
||||
buffer: Buffer::from_str(text),
|
||||
cursor: Cursor::default(),
|
||||
file: file_name,
|
||||
mode: Mode::default(),
|
||||
scroll: Cursor::default(),
|
||||
size: (cols as usize, rows as usize),
|
||||
mode: Mode::default(),
|
||||
quit: false,
|
||||
})
|
||||
}
|
||||
|
@ -410,12 +414,40 @@ impl State {
|
|||
}
|
||||
}
|
||||
|
||||
fn write_buffer(&mut self, file: OsString) -> std::result::Result<(), String> {
|
||||
let out = self.buffer.text.bytes().collect::<Vec<u8>>();
|
||||
|
||||
let handle = file
|
||||
.clone()
|
||||
.into_string()
|
||||
.map_err(|err| {
|
||||
format!("{:?}", err)
|
||||
})?;
|
||||
|
||||
write(handle, out.as_slice())
|
||||
.map_err(|err| {
|
||||
format!("{:?}", err)
|
||||
})?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_command(&mut self, command: &str) -> std::result::Result<(), String> {
|
||||
match command {
|
||||
"q" => self.quit = true,
|
||||
command => return Err(format!("unrecognized command {:?}", command)),
|
||||
}
|
||||
"w" => {
|
||||
let handle = self.file.clone().unwrap_or_else(|| {
|
||||
OsString::from("file")
|
||||
});
|
||||
|
||||
self.write_buffer(handle)?;
|
||||
},
|
||||
command => {
|
||||
return Err(
|
||||
format!("{:?}: Unrecognized command.", command)
|
||||
);
|
||||
},
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -449,21 +481,28 @@ 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]
|
||||
);
|
||||
let input_file = Path::new(path);
|
||||
file_name = input_file.clone().file_name().map(|f| f.to_owned());
|
||||
|
||||
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);
|
||||
})
|
||||
},
|
||||
|
@ -476,7 +515,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)?;
|
||||
|
|
Loading…
Reference in New Issue