Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 16 additions & 5 deletions src/cmd/io_commands/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,12 +160,15 @@ pub fn write_to_file(
};

// If not wq, parse path
let (q, path) = if in_path != "q" {
(false, parse_path(in_path).unwrap_or(Path::File(&state.file)))
let (q, path, overwrite) = if in_path != "q" {
match parse_path(in_path) {
Some(p) => (false, p, false),
None => (false, Path::File(&state.file), true),
}
}
// If wq, use current file path
else {
(true, (Path::File(&state.file)))
(true, Path::File(&state.file), true)
};
// If the 'q' flag is set the whole buffer must be selected
if q && sel.is_some() { return Err(EdError::UnsavedChanges); }
Expand All @@ -177,10 +180,18 @@ pub fn write_to_file(
// Write into command or file, print nr of bytes written
match path {
Path::File(file) => {
let append = command == 'W';
let wtype = if command == 'W' {
WriteType::Append
} else {
if overwrite {
WriteType::Overwrite
} else {
WriteType::Create
}
};
let written = state.io.write_file(
file,
append,
wtype,
data,
)?;
ui.print_message(&format!(
Expand Down
2 changes: 1 addition & 1 deletion src/cmd/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{Ed, Substitution, Line, Clipboard, Buffer};
use crate::{Ed, Substitution, Line, Clipboard, Buffer, WriteType};
use crate::ui::{UI, ScriptedUI};
use crate::error::*;
use crate::messages::*;
Expand Down
7 changes: 5 additions & 2 deletions src/io/dummy_io.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::{
io::IO,
io::{
IO,
WriteType,
},
ui::UILock,
buffer::iters::LinesIter,
};
Expand Down Expand Up @@ -42,7 +45,7 @@ impl IO for DummyIO {
}
fn write_file(&mut self,
_path: &str,
_append: bool,
_type: WriteType,
_data: LinesIter,
) -> Result<usize> {
unimplemented!()
Expand Down
26 changes: 14 additions & 12 deletions src/io/fake_io.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
use crate::{
io::IO,
io::{
IO,
WriteType,
},
ui::UILock,
buffer::iters::LinesIter,
};
Expand All @@ -9,13 +12,15 @@ use super::Result;
pub enum FakeIOError {
ChildExitError,
NotFound,
Overwrite,
}
impl std::fmt::Display for FakeIOError {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use FakeIOError::*;
use FakeIOError as FIE;
match self {
ChildExitError => write!(f,"Child process returned error after running."),
NotFound => write!(f,"Could not open file. Not found or invalid path."),
FIE::ChildExitError => write!(f,"Child process returned error after running."),
FIE::NotFound => write!(f,"Could not open file. Not found or invalid path."),
FIE::Overwrite => write!(f,"Will not overwrite existing file.")
}
}
}
Expand Down Expand Up @@ -103,16 +108,13 @@ impl IO for FakeIO {
}
fn write_file(&mut self,
path: &str,
append: bool,
wtype: WriteType,
data: LinesIter,
) -> Result<usize> {
let base_data = if append {
match self.fake_fs.get(path) {
Some(x) => x.clone(),
None => String::new(),
}
} else {
String::new()
let base_data = match self.fake_fs.get(path) {
Some(x) if wtype == WriteType::Append => x.clone(),
Some(_) if wtype != WriteType::Overwrite => { return Err(FakeIOError::Overwrite.into()); },
_ => String::new(),
};
let data = data.fold(base_data, |mut s, x|{s.push_str(x); s});
let datalen = data.len();
Expand Down
28 changes: 17 additions & 11 deletions src/io/local_io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use std::process::{
Command,
Stdio,
};
use crate::IO;
use crate::{IO, WriteType};
use super::LinesIter;
use crate::UILock;
use super::Result;
Expand Down Expand Up @@ -48,17 +48,23 @@ impl LocalIO {
}
fn write_internal<'a>(
path: &str,
append: bool,
wtype: WriteType,
data: impl Iterator<Item = &'a str>,
) -> std::io::Result<usize> {
use std::io::Write;
let mut file = std::fs::OpenOptions::new()
.write(true)
.append(append)
.truncate(!append)
.create(true)
.open(path)
?;
let mut options = std::fs::OpenOptions::new();
match wtype {
WriteType::Create => options
.write(true)
.create_new(true),
WriteType::Append => options
.append(true),
WriteType::Overwrite => options
.create(true) // May, but is not required to, create new file
.write(true)
.truncate(true),
};
let mut file = options.open(path)?;
let mut written = 0;
for line in data {
written += line.len();
Expand Down Expand Up @@ -187,11 +193,11 @@ impl IO for LocalIO {

fn write_file(&mut self,
path: &str,
append: bool,
wtype: WriteType,
data: LinesIter,
) -> Result<usize> {
if path.len() == 0 { return Err(LocalIOError::NoPath.into()); }
Self::write_internal(path, append, data)
Self::write_internal(path, wtype, data)
.map_err(|e| LocalIOError::file_error(path, e).into())
}
fn read_file(&mut self,
Expand Down
8 changes: 4 additions & 4 deletions src/io/local_io/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ fn test_file_io() {
// Create new file
io.write_file(
path,
false, // don't append
WriteType::Create,
Box::new("1\n2\n".split_inclusive('\n')).into(),
).unwrap();
let read = std::fs::read_to_string(path).unwrap();
Expand All @@ -33,7 +33,7 @@ fn test_file_io() {
// File path must not be empty for writing
let ret = io.write_file(
"",
false,
WriteType::Create,
Box::new("data\n".split_inclusive('\n')).into(),
);
assert!(
Expand All @@ -43,7 +43,7 @@ fn test_file_io() {
// Overwrite the file
io.write_file(
path,
false, // don't append
WriteType::Overwrite,
Box::new("1\n2\n".split_inclusive('\n')).into(),
).unwrap();
let read = std::fs::read_to_string(path).unwrap();
Expand All @@ -56,7 +56,7 @@ fn test_file_io() {
// Append to the file
io.write_file(
path,
true, // Append
WriteType::Append,
Box::new("1\n2\n".split_inclusive('\n')).into(),
).unwrap();
let read = std::fs::read_to_string(path).unwrap();
Expand Down
15 changes: 13 additions & 2 deletions src/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,17 @@ pub mod local_io;
#[cfg(feature = "local_io")]
pub use local_io::LocalIO;

/// Simple enum only used for the IO trait's write_file method
#[derive(PartialEq, Debug)]
pub enum WriteType {
/// Used for 'w' interactions with an explicit path, prohibits overwriting
Create,
/// Used for all 'W' interactions
Append,
/// Only used for 'w' when writing to current file
Overwrite,
}

/// Trait that abstracts file interactions and running shell commands
///
/// Intended to allow modifying how and where system interactions occur.
Expand Down Expand Up @@ -97,8 +108,8 @@ pub trait IO {
fn write_file(&mut self,
// Path to file as give by user. Not checked beyond shell escape parsing
path: &str,
// If appending
append: bool,
// Write type, see above
wtype: WriteType,
// Data to write to file
data: LinesIter,
) -> Result<usize>;
Expand Down
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ mod cmd;
pub mod ui;
use ui::{UI, UILock, ScriptedUI};
pub mod io;
use io::IO;
use io::{IO, WriteType};

mod history;
pub use history::History;
Expand Down