138 lines
5.3 KiB
Rust
138 lines
5.3 KiB
Rust
use std::{path::PathBuf, rc::Rc};
|
|
|
|
use super::{CommandResult, EditorBuffer, EditorBufferState};
|
|
use crate::{Point, TextBuffer, TextBufferReader, TextBufferWriter};
|
|
|
|
#[doc(hidden)]
|
|
impl EditorBuffer {
|
|
pub fn open_file(&self, filepath: PathBuf) -> CommandResult {
|
|
match std::fs::File::open(&filepath) {
|
|
Ok(mut file) => {
|
|
let mut buffer = TextBuffer::new();
|
|
match std::io::copy(&mut file, &mut TextBufferWriter::new(&mut buffer)) {
|
|
Ok(bytes_read) => {
|
|
let msg = format!(
|
|
"Read {bytes_read} bytes from \"{}\"",
|
|
filepath.to_string_lossy()
|
|
);
|
|
let state = Rc::new(EditorBufferState {
|
|
filepath: Some(filepath),
|
|
..*self.state
|
|
});
|
|
let cursor = Point::default();
|
|
let buffer = buffer;
|
|
CommandResult::success_with_message(
|
|
Self {
|
|
state,
|
|
cursor,
|
|
buffer,
|
|
..self.clone()
|
|
},
|
|
msg,
|
|
)
|
|
}
|
|
Err(err) => CommandResult::fail_with_message(self.clone(), format!("{}", err)),
|
|
}
|
|
}
|
|
Err(err) => {
|
|
if err.kind() == std::io::ErrorKind::NotFound {
|
|
CommandResult::fail_with_message(
|
|
self.clone(),
|
|
format!("File not found: \"{}\"", filepath.to_string_lossy()),
|
|
)
|
|
} else {
|
|
CommandResult::fail_with_message(self.clone(), format!("{}", err))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pub fn save_file(&self, filepath: Option<PathBuf>) -> CommandResult {
|
|
if let Some(filepath) = filepath.as_ref().or(self.state.filepath.as_ref()) {
|
|
match std::fs::File::create(filepath) {
|
|
Ok(mut file) => {
|
|
match std::io::copy(&mut TextBufferReader::new(&self.buffer), &mut file) {
|
|
Ok(bytes_read) => CommandResult::success_with_message(
|
|
self.clone(),
|
|
format!(
|
|
"Read {bytes_read} bytes to \"{}\"",
|
|
filepath.to_string_lossy()
|
|
),
|
|
),
|
|
Err(err) => {
|
|
CommandResult::fail_with_message(self.clone(), format!("{}", err))
|
|
}
|
|
}
|
|
}
|
|
Err(err) => CommandResult::fail_with_message(self.clone(), format!("{}", err)),
|
|
}
|
|
} else {
|
|
CommandResult::fail_with_message(self.clone(), "Attempting to same file with no name.")
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use crate::{Command, CommandResponse, EditorBuffer, TextBufferReader};
|
|
use std::{io::Read, path::PathBuf};
|
|
use tempfile::tempdir;
|
|
|
|
#[test]
|
|
fn load_file_loads_expected_contents() {
|
|
let test_file_path: PathBuf = [
|
|
env!("CARGO_MANIFEST_DIR"),
|
|
r"test_data/Les_Trois_Mousquetaires.txt",
|
|
]
|
|
.iter()
|
|
.collect();
|
|
let expected_text = std::fs::read_to_string(&test_file_path).unwrap();
|
|
let target = EditorBuffer::new();
|
|
let result = target.execute(Command::OpenFile(test_file_path));
|
|
assert!(result.is_ok());
|
|
let target = result.buffer;
|
|
|
|
let mut buffer_bytes = Vec::new();
|
|
TextBufferReader::new(&target.buffer)
|
|
.read_to_end(&mut buffer_bytes)
|
|
.unwrap();
|
|
let buffer_text = String::from_utf8(buffer_bytes).unwrap();
|
|
assert_eq!(&expected_text, &buffer_text);
|
|
}
|
|
|
|
#[test]
|
|
fn load_file_reports_error_with_missing_file() {
|
|
let test_file_path: PathBuf = [env!("CARGO_MANIFEST_DIR"), r"test_data/Not_a_File.txt"]
|
|
.iter()
|
|
.collect();
|
|
let expected_message = format!("File not found: \"{}\"", test_file_path.to_string_lossy());
|
|
let target = EditorBuffer::new();
|
|
let result = target.execute(Command::OpenFile(test_file_path));
|
|
assert!(!result.is_ok());
|
|
match result.response {
|
|
CommandResponse::Message(s) => assert_eq!(expected_message, s),
|
|
_ => panic!(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn save_file_saves_file_with_expected_contents() {
|
|
let test_file_path: PathBuf = [
|
|
env!("CARGO_MANIFEST_DIR"),
|
|
r"test_data/Les_Trois_Mousquetaires.txt",
|
|
]
|
|
.iter()
|
|
.collect();
|
|
let target = EditorBuffer::new();
|
|
let target = target.execute(Command::OpenFile(test_file_path.clone())).buffer;
|
|
let temp_dir = tempdir().unwrap();
|
|
let tmp_file_path = temp_dir.path().join(r"Les_Trois_Mousquetaires.txt");
|
|
let result = target.execute(Command::SaveAs(tmp_file_path.clone()));
|
|
assert!(result.is_ok());
|
|
|
|
let read_text = std::fs::read_to_string(&tmp_file_path).unwrap();
|
|
let expected_text = std::fs::read_to_string(&test_file_path).unwrap();
|
|
assert_eq!(&expected_text, &read_text);
|
|
}
|
|
}
|