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