forked from extern/nushell
Merge pull request #307 from androbtech/qwrapport
Refactoring and unwrap cleanup beginnings.
This commit is contained in:
commit
095f4645c0
@ -21,7 +21,7 @@ impl PerItemCommand for Cpy {
|
||||
call_info: &CallInfo,
|
||||
_registry: &CommandRegistry,
|
||||
shell_manager: &ShellManager,
|
||||
input: Tagged<Value>,
|
||||
_input: Tagged<Value>,
|
||||
) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
call_info.process(shell_manager, cp)?.run()
|
||||
}
|
||||
@ -75,7 +75,7 @@ pub fn cp(
|
||||
|
||||
let mut sources: FileStructure = FileStructure::new();
|
||||
|
||||
sources.walk_decorate(&entry);
|
||||
sources.walk_decorate(&entry)?;
|
||||
|
||||
if entry.is_file() {
|
||||
let strategy = |(source_file, _depth_level)| {
|
||||
|
@ -1,3 +1,4 @@
|
||||
use crate::commands::command::RunnablePerItemContext;
|
||||
use crate::errors::ShellError;
|
||||
use crate::parser::hir::SyntaxType;
|
||||
use crate::parser::registry::{CommandRegistry, Signature};
|
||||
@ -9,6 +10,12 @@ use crate::utils::FileStructure;
|
||||
|
||||
pub struct Move;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct MoveArgs {
|
||||
source: Tagged<PathBuf>,
|
||||
destination: Tagged<PathBuf>,
|
||||
}
|
||||
|
||||
impl PerItemCommand for Move {
|
||||
fn run(
|
||||
&self,
|
||||
@ -17,7 +24,7 @@ impl PerItemCommand for Move {
|
||||
shell_manager: &ShellManager,
|
||||
_input: Tagged<Value>,
|
||||
) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
mv(call_info, shell_manager)
|
||||
call_info.process(shell_manager, mv)?.run()
|
||||
}
|
||||
|
||||
fn name(&self) -> &str {
|
||||
@ -25,59 +32,77 @@ impl PerItemCommand for Move {
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("mv").named("file", SyntaxType::Any)
|
||||
Signature::build("mv")
|
||||
.required("source", SyntaxType::Path)
|
||||
.required("destination", SyntaxType::Path)
|
||||
.named("file", SyntaxType::Any)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mv(
|
||||
call_info: &CallInfo,
|
||||
shell_manager: &ShellManager,
|
||||
args: MoveArgs,
|
||||
context: &RunnablePerItemContext,
|
||||
) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
let mut source = PathBuf::from(shell_manager.path());
|
||||
let mut destination = PathBuf::from(shell_manager.path());
|
||||
let span = call_info.name_span;
|
||||
let mut source = PathBuf::from(context.shell_manager.path());
|
||||
let mut destination = PathBuf::from(context.shell_manager.path());
|
||||
let name_span = context.name;
|
||||
|
||||
match call_info
|
||||
.args
|
||||
.nth(0)
|
||||
.ok_or_else(|| ShellError::string(&format!("No file or directory specified")))?
|
||||
.as_string()?
|
||||
.as_str()
|
||||
{
|
||||
file => {
|
||||
source.push(file);
|
||||
}
|
||||
}
|
||||
source.push(&args.source.item);
|
||||
|
||||
match call_info
|
||||
.args
|
||||
.nth(1)
|
||||
.ok_or_else(|| ShellError::string(&format!("No file or directory specified")))?
|
||||
.as_string()?
|
||||
.as_str()
|
||||
{
|
||||
file => {
|
||||
destination.push(file);
|
||||
}
|
||||
}
|
||||
destination.push(&args.destination.item);
|
||||
|
||||
let sources = glob::glob(&source.to_string_lossy());
|
||||
|
||||
if sources.is_err() {
|
||||
let sources: Vec<_> = match glob::glob(&source.to_string_lossy()) {
|
||||
Ok(files) => files.collect(),
|
||||
Err(_) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Invalid pattern.",
|
||||
"Invalid pattern.",
|
||||
call_info.args.nth(0).unwrap().span(),
|
||||
));
|
||||
args.source.tag,
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let sources: Vec<_> = sources.unwrap().collect();
|
||||
let destination_file_name = {
|
||||
let path = &destination;
|
||||
|
||||
match path.file_name() {
|
||||
Some(name) => PathBuf::from(name),
|
||||
None => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Rename aborted. Not a valid destination",
|
||||
"Rename aborted. Not a valid destination",
|
||||
name_span,
|
||||
))
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if sources.len() == 1 {
|
||||
if let Ok(entry) = &sources[0] {
|
||||
let entry_file_name = match entry.file_name() {
|
||||
Some(name) => name,
|
||||
None => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Rename aborted. Not a valid entry name",
|
||||
"Rename aborted. Not a valid entry name",
|
||||
name_span,
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
if destination.exists() && destination.is_dir() {
|
||||
destination = dunce::canonicalize(&destination).unwrap();
|
||||
destination.push(source.file_name().unwrap());
|
||||
destination = match dunce::canonicalize(&destination) {
|
||||
Ok(path) => path,
|
||||
Err(e) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
format!("Rename aborted. {:}", e.to_string()),
|
||||
format!("Rename aborted. {:}", e.to_string()),
|
||||
name_span,
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
destination.push(entry_file_name);
|
||||
}
|
||||
|
||||
if entry.is_file() {
|
||||
@ -86,17 +111,17 @@ pub fn mv(
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
span,
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
@ -109,17 +134,17 @@ pub fn mv(
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
span,
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
@ -131,17 +156,17 @@ pub fn mv(
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
span,
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
@ -151,10 +176,11 @@ pub fn mv(
|
||||
{
|
||||
let mut sources: FileStructure = FileStructure::new();
|
||||
|
||||
sources.walk_decorate(&entry);
|
||||
sources.walk_decorate(&entry)?;
|
||||
|
||||
let strategy = |(source_file, depth_level)| {
|
||||
let mut new_dst = destination.clone();
|
||||
|
||||
let path = dunce::canonicalize(&source_file).unwrap();
|
||||
|
||||
let mut comps: Vec<_> = path
|
||||
@ -181,21 +207,21 @@ pub fn mv(
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
span,
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -205,42 +231,78 @@ pub fn mv(
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
span,
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
match std::fs::remove_dir_all(entry) {
|
||||
Err(e) => {
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
std::fs::remove_dir_all(entry).expect("can not remove directory");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if destination.exists() {
|
||||
if !sources.iter().all(|x| (x.as_ref().unwrap()).is_file()) {
|
||||
if !sources.iter().all(|x| {
|
||||
if let Ok(entry) = x.as_ref() {
|
||||
entry.is_file()
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}) {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Rename aborted (directories found). Renaming in patterns not supported yet (try moving the directory directly)",
|
||||
"Rename aborted (directories found). Renaming in patterns not supported yet (try moving the directory directly)",
|
||||
call_info.args.nth(0).unwrap().span(),
|
||||
args.source.tag,
|
||||
));
|
||||
}
|
||||
|
||||
for entry in sources {
|
||||
if let Ok(entry) = entry {
|
||||
let entry_file_name = match entry.file_name() {
|
||||
Some(name) => name,
|
||||
None => {
|
||||
return Err(ShellError::labeled_error(
|
||||
"Rename aborted. Not a valid entry name",
|
||||
"Rename aborted. Not a valid entry name",
|
||||
name_span,
|
||||
))
|
||||
}
|
||||
};
|
||||
|
||||
let mut to = PathBuf::from(&destination);
|
||||
to.push(&entry.file_name().unwrap());
|
||||
to.push(entry_file_name);
|
||||
|
||||
if entry.is_file() {
|
||||
match std::fs::rename(&entry, &to) {
|
||||
@ -248,17 +310,17 @@ pub fn mv(
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
format!(
|
||||
"Rename {:?} to {:?} aborted. {:}",
|
||||
entry.file_name().unwrap(),
|
||||
destination.file_name().unwrap(),
|
||||
entry_file_name,
|
||||
destination_file_name,
|
||||
e.to_string(),
|
||||
),
|
||||
span,
|
||||
name_span,
|
||||
));
|
||||
}
|
||||
Ok(o) => o,
|
||||
@ -268,15 +330,9 @@ pub fn mv(
|
||||
}
|
||||
} else {
|
||||
return Err(ShellError::labeled_error(
|
||||
format!(
|
||||
"Rename aborted. (Does {:?} exist?)",
|
||||
&destination.file_name().unwrap()
|
||||
),
|
||||
format!(
|
||||
"Rename aborted. (Does {:?} exist?)",
|
||||
&destination.file_name().unwrap()
|
||||
),
|
||||
call_info.args.nth(1).unwrap().span(),
|
||||
format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
|
||||
format!("Rename aborted. (Does {:?} exist?)", destination_file_name),
|
||||
args.destination.span(),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -28,7 +28,16 @@ pub trait Plugin {
|
||||
pub fn serve_plugin(plugin: &mut dyn Plugin) {
|
||||
let args = std::env::args();
|
||||
if args.len() > 1 {
|
||||
let input = std::fs::read_to_string(args.skip(1).next().unwrap());
|
||||
let input = args.skip(1).next();
|
||||
|
||||
let input = match input {
|
||||
Some(arg) => std::fs::read_to_string(arg),
|
||||
None => {
|
||||
send_response(ShellError::string(format!("No input given.")));
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if let Ok(input) = input {
|
||||
let command = serde_json::from_str::<NuCommand>(&input);
|
||||
match command {
|
||||
@ -128,8 +137,12 @@ impl<T> JsonRpc<T> {
|
||||
|
||||
fn send_response<T: Serialize>(result: T) {
|
||||
let response = JsonRpc::new("response", result);
|
||||
let response_raw = serde_json::to_string(&response).unwrap();
|
||||
println!("{}", response_raw);
|
||||
let response_raw = serde_json::to_string(&response);
|
||||
|
||||
match response_raw {
|
||||
Ok(response) => println!("{}", response),
|
||||
Err(err) => println!("{}", err),
|
||||
}
|
||||
}
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
#[serde(tag = "method")]
|
||||
|
@ -1,7 +1,7 @@
|
||||
use indexmap::IndexMap;
|
||||
use nu::{
|
||||
serve_plugin, CallInfo, NamedType, Plugin, Primitive, ReturnSuccess,
|
||||
ReturnValue, ShellError, Signature, Tagged, TaggedItem, Value,
|
||||
serve_plugin, CallInfo, NamedType, Plugin, Primitive, ReturnSuccess, ReturnValue, ShellError,
|
||||
Signature, Tagged, TaggedItem, Value,
|
||||
};
|
||||
|
||||
enum Action {
|
||||
@ -30,16 +30,13 @@ impl Inc {
|
||||
}
|
||||
}
|
||||
|
||||
fn apply(&self, input: &str) -> Value {
|
||||
match &self.action {
|
||||
fn apply(&self, input: &str) -> Result<Value, ShellError> {
|
||||
let applied = match &self.action {
|
||||
Some(Action::SemVerAction(act_on)) => {
|
||||
let ver = semver::Version::parse(&input);
|
||||
|
||||
if ver.is_err() {
|
||||
return Value::string(input.to_string());
|
||||
}
|
||||
|
||||
let mut ver = ver.unwrap();
|
||||
let mut ver = match semver::Version::parse(&input) {
|
||||
Ok(parsed_ver) => parsed_ver,
|
||||
Err(_) => return Ok(Value::string(input.to_string())),
|
||||
};
|
||||
|
||||
match act_on {
|
||||
SemVerAction::Major => ver.increment_major(),
|
||||
@ -53,7 +50,9 @@ impl Inc {
|
||||
Ok(v) => Value::string(format!("{}", v + 1)),
|
||||
Err(_) => Value::string(input),
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
Ok(applied)
|
||||
}
|
||||
|
||||
fn for_semver(&mut self, part: SemVerAction) {
|
||||
@ -83,7 +82,7 @@ impl Inc {
|
||||
Ok(Value::bytes(b + 1 as u64).tagged(value.tag()))
|
||||
}
|
||||
Value::Primitive(Primitive::String(ref s)) => {
|
||||
Ok(Tagged::from_item(self.apply(&s), value.tag()))
|
||||
Ok(Tagged::from_item(self.apply(&s)?, value.tag()))
|
||||
}
|
||||
Value::Object(_) => match self.field {
|
||||
Some(ref f) => {
|
||||
@ -187,8 +186,8 @@ mod tests {
|
||||
use super::{Inc, SemVerAction};
|
||||
use indexmap::IndexMap;
|
||||
use nu::{
|
||||
CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Span, Tag, Tagged, TaggedDictBuilder,
|
||||
TaggedItem, Value,
|
||||
CallInfo, EvaluatedArgs, Plugin, ReturnSuccess, SourceMap, Span, Tag, Tagged,
|
||||
TaggedDictBuilder, TaggedItem, Value,
|
||||
};
|
||||
|
||||
struct CallStub {
|
||||
@ -237,7 +236,7 @@ mod tests {
|
||||
fn inc_plugin_configuration_flags_wired() {
|
||||
let mut plugin = Inc::new();
|
||||
|
||||
let configured = plugin.config().unwrap();
|
||||
let configured = plugin.config().expect("Can not configure plugin");
|
||||
|
||||
for action_flag in &["major", "minor", "patch"] {
|
||||
assert!(configured.named.get(*action_flag).is_some());
|
||||
@ -304,21 +303,21 @@ mod tests {
|
||||
fn incs_major() {
|
||||
let mut inc = Inc::new();
|
||||
inc.for_semver(SemVerAction::Major);
|
||||
assert_eq!(inc.apply("0.1.3"), Value::string("1.0.0"));
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), Value::string("1.0.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn incs_minor() {
|
||||
let mut inc = Inc::new();
|
||||
inc.for_semver(SemVerAction::Minor);
|
||||
assert_eq!(inc.apply("0.1.3"), Value::string("0.2.0"));
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), Value::string("0.2.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn incs_patch() {
|
||||
let mut inc = Inc::new();
|
||||
inc.for_semver(SemVerAction::Patch);
|
||||
assert_eq!(inc.apply("0.1.3"), Value::string("0.1.4"));
|
||||
assert_eq!(inc.apply("0.1.3").unwrap(), Value::string("0.1.4"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
@ -36,19 +36,15 @@ impl Str {
|
||||
}
|
||||
}
|
||||
|
||||
fn apply(&self, input: &str) -> Value {
|
||||
if self.action.is_none() {
|
||||
return Value::string(input.to_string());
|
||||
}
|
||||
|
||||
match self.action.as_ref().unwrap() {
|
||||
Action::Downcase => Value::string(input.to_ascii_lowercase()),
|
||||
Action::Upcase => Value::string(input.to_ascii_uppercase()),
|
||||
Action::ToInteger => match input.trim().parse::<i64>() {
|
||||
fn apply(&self, input: &str) -> Result<Value, ShellError> {
|
||||
let applied = match self.action.as_ref() {
|
||||
Some(Action::Downcase) => Value::string(input.to_ascii_lowercase()),
|
||||
Some(Action::Upcase) => Value::string(input.to_ascii_uppercase()),
|
||||
Some(Action::ToInteger) => match input.trim().parse::<i64>() {
|
||||
Ok(v) => Value::int(v),
|
||||
Err(_) => Value::string(input),
|
||||
},
|
||||
Action::Replace(ref mode) => match mode {
|
||||
Some(Action::Replace(ref mode)) => match mode {
|
||||
ReplaceAction::Direct => Value::string(self.first_param()),
|
||||
ReplaceAction::FindAndReplace => {
|
||||
let regex = Regex::new(self.first_param());
|
||||
@ -59,7 +55,10 @@ impl Str {
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
None => Value::string(input),
|
||||
};
|
||||
|
||||
Ok(applied)
|
||||
}
|
||||
|
||||
fn did_supply_field(&self) -> bool {
|
||||
@ -133,7 +132,7 @@ impl Str {
|
||||
fn strutils(&self, value: Tagged<Value>) -> Result<Tagged<Value>, ShellError> {
|
||||
match value.item {
|
||||
Value::Primitive(Primitive::String(ref s)) => {
|
||||
Ok(Tagged::from_item(self.apply(&s), value.tag()))
|
||||
Ok(Tagged::from_item(self.apply(&s)?, value.tag()))
|
||||
}
|
||||
Value::Object(_) => match self.field {
|
||||
Some(ref f) => {
|
||||
@ -431,21 +430,21 @@ mod tests {
|
||||
fn str_downcases() {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_downcase();
|
||||
assert_eq!(strutils.apply("ANDRES"), Value::string("andres"));
|
||||
assert_eq!(strutils.apply("ANDRES").unwrap(), Value::string("andres"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_upcases() {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_upcase();
|
||||
assert_eq!(strutils.apply("andres"), Value::string("ANDRES"));
|
||||
assert_eq!(strutils.apply("andres").unwrap(), Value::string("ANDRES"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn str_to_int() {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_to_int();
|
||||
assert_eq!(strutils.apply("9999"), Value::int(9999 as i64));
|
||||
assert_eq!(strutils.apply("9999").unwrap(), Value::int(9999 as i64));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -453,7 +452,7 @@ mod tests {
|
||||
let mut strutils = Str::new();
|
||||
strutils.for_replace(ReplaceAction::Direct);
|
||||
strutils.replace_with("robalino");
|
||||
assert_eq!(strutils.apply("andres"), Value::string("robalino"));
|
||||
assert_eq!(strutils.apply("andres").unwrap(), Value::string("robalino"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@ -462,7 +461,10 @@ mod tests {
|
||||
strutils.for_replace(ReplaceAction::FindAndReplace);
|
||||
strutils.find_with(r"kittens");
|
||||
strutils.replace_with("jotandrehuda");
|
||||
assert_eq!(strutils.apply("wykittens"), Value::string("wyjotandrehuda"));
|
||||
assert_eq!(
|
||||
strutils.apply("wykittens").unwrap(),
|
||||
Value::string("wyjotandrehuda")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
32
src/utils.rs
32
src/utils.rs
@ -1,3 +1,4 @@
|
||||
use crate::errors::ShellError;
|
||||
use std::ops::Div;
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
@ -71,7 +72,6 @@ impl<T: AsRef<str>> Div<T> for &RelativePath {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug, Eq, Ord, PartialEq, PartialOrd)]
|
||||
pub struct Res {
|
||||
pub loc: PathBuf,
|
||||
@ -108,23 +108,25 @@ impl FileStructure {
|
||||
.collect()
|
||||
}
|
||||
|
||||
pub fn walk_decorate(&mut self, start_path: &Path) {
|
||||
self.set_root(&dunce::canonicalize(start_path).unwrap());
|
||||
pub fn walk_decorate(&mut self, start_path: &Path) -> Result<(), ShellError> {
|
||||
self.set_root(&dunce::canonicalize(start_path)?);
|
||||
self.resources = Vec::<Res>::new();
|
||||
self.build(start_path, 0);
|
||||
self.build(start_path, 0)?;
|
||||
self.resources.sort();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn build(&mut self, src: &'a Path, lvl: usize) {
|
||||
let source = dunce::canonicalize(src).unwrap();
|
||||
fn build(&mut self, src: &'a Path, lvl: usize) -> Result<(), ShellError> {
|
||||
let source = dunce::canonicalize(src)?;
|
||||
|
||||
if source.is_dir() {
|
||||
for entry in std::fs::read_dir(&source).unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
for entry in std::fs::read_dir(&source)? {
|
||||
let entry = entry?;
|
||||
let path = entry.path();
|
||||
|
||||
if path.is_dir() {
|
||||
self.build(&path, lvl + 1);
|
||||
self.build(&path, lvl + 1)?;
|
||||
}
|
||||
|
||||
self.resources.push(Res {
|
||||
@ -138,6 +140,8 @@ impl FileStructure {
|
||||
at: lvl,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
@ -152,13 +156,18 @@ mod tests {
|
||||
sdx.push("tests");
|
||||
sdx.push("fixtures");
|
||||
sdx.push("formats");
|
||||
dunce::canonicalize(sdx).unwrap()
|
||||
|
||||
match dunce::canonicalize(sdx) {
|
||||
Ok(path) => path,
|
||||
Err(_) => panic!("Wrong path."),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn prepares_and_decorates_source_files_for_copying() {
|
||||
let mut res = FileStructure::new();
|
||||
res.walk_decorate(fixtures().as_path());
|
||||
|
||||
res.walk_decorate(fixtures().as_path()).expect("Can not decorate files traversal.");
|
||||
|
||||
assert_eq!(
|
||||
res.resources,
|
||||
@ -195,4 +204,3 @@ mod tests {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,7 +151,20 @@ impl Playground {
|
||||
}
|
||||
|
||||
pub fn glob_vec(pattern: &str) -> Vec<PathBuf> {
|
||||
glob(pattern).unwrap().map(|r| r.unwrap()).collect()
|
||||
let glob = glob(pattern);
|
||||
|
||||
match glob {
|
||||
Ok(paths) => paths
|
||||
.map(|path| {
|
||||
if let Ok(path) = path {
|
||||
path
|
||||
} else {
|
||||
unreachable!()
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
Err(_) => panic!("Invalid pattern."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -178,11 +191,10 @@ pub fn normalize_string(input: &str) -> String {
|
||||
pub fn create_file_at(full_path: impl AsRef<Path>) -> Result<(), std::io::Error> {
|
||||
let full_path = full_path.as_ref();
|
||||
|
||||
assert!(
|
||||
full_path.parent().unwrap().is_dir(),
|
||||
"{:?} exists",
|
||||
full_path.parent().unwrap().display(),
|
||||
);
|
||||
if let Some(parent) = full_path.parent() {
|
||||
panic!(format!("{:?} exists", parent.display()));
|
||||
}
|
||||
|
||||
std::fs::write(full_path, "fake data".as_bytes())
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user