use super::{
read::{combine_path_like, read_path},
write::replace_path,
};
use clap::Parser;
use std::{cmp::min, io, path::PathBuf};
#[derive(Debug, Parser)]
pub struct MvOpt {
#[clap(default_value = ".")]
dir: PathBuf,
#[clap(default_value = "1")]
jump: usize,
#[clap(short, long)]
quiet: bool,
#[clap(short = 'H', long)]
history: bool,
#[clap(short = 'n', long = "dry-run")]
dry_run: bool,
}
impl MvOpt {
pub fn validate(&self) -> io::Result<()> {
Ok(())
}
}
fn change_priority(opts: &MvOpt, direction_factor: i8) -> io::Result<()> {
let current_path = read_path();
let idx = current_path.iter().position(|x| *x == opts.dir);
if let Some(i) = idx {
let i_signed = i as i8;
let signed_jump = direction_factor * (opts.jump as i8);
let signed_new_idx = i_signed + signed_jump;
let new_idx: usize;
if signed_new_idx < 0 {
new_idx = 0;
} else {
new_idx = min((signed_new_idx) as usize, current_path.len() - 1);
}
let vpath: Vec<PathBuf> = match signed_jump.cmp(&0) {
std::cmp::Ordering::Less => {
let mut _vpath: Vec<PathBuf> = (0..new_idx)
.into_iter()
.map(|j| current_path[j].clone())
.collect();
_vpath.push(opts.dir.clone());
_vpath.append(
&mut (new_idx..i)
.into_iter()
.map(|j| current_path[j].clone())
.collect(),
);
_vpath.append(
&mut ((i + 1)..current_path.len())
.into_iter()
.map(|j| current_path[j].clone())
.collect(),
);
_vpath
}
std::cmp::Ordering::Equal => current_path,
std::cmp::Ordering::Greater => {
let mut _vpath: Vec<PathBuf> = (0..i)
.into_iter()
.map(|j| current_path[j].clone())
.collect();
_vpath.append(
&mut ((i + 1)..(new_idx + 1))
.into_iter()
.map(|j| current_path[j].clone())
.collect(),
);
_vpath.push(opts.dir.clone());
_vpath.append(
&mut ((new_idx + 1)..current_path.len())
.into_iter()
.map(|j| current_path[j].clone())
.collect(),
);
_vpath
}
};
let newpath = combine_path_like(vpath)?;
match replace_path(newpath, opts.dry_run, opts.history, opts.quiet) {
Ok(()) => Ok(()),
Err(e) => {
if !opts.quiet {
eprintln!("{}", e);
}
Err(e)
}
}
} else {
let err = io::Error::new(
io::ErrorKind::NotFound,
format!(
"Directory `{}` not found in `$PATH`. No changes made.",
opts.dir.display()
),
);
if !opts.quiet {
eprintln!("{}", err);
}
Err(err)
}
}
pub fn increase_priority(opts: &MvOpt) -> io::Result<()> {
change_priority(opts, -1)
}
pub fn decrease_priority(opts: &MvOpt) -> io::Result<()> {
change_priority(opts, 1)
}