Skip to content

Commit

Permalink
fix cli parse error on giving no arguments
Browse files Browse the repository at this point in the history
However, this change is quite ugly program, therefore, it should be fix soon.
  • Loading branch information
tamada committed Jul 18, 2024
1 parent feed37d commit f84e4ed
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 26 deletions.
6 changes: 3 additions & 3 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ pub struct CliOpts {
#[arg(short, long, help = "specify the number of times to execute sibling", value_name = "COUNT", default_value_t = 1)]
pub step: i32,

#[arg(short, long, help = "generate the initialize script for the shell", value_name = "SHELL", hide = true)]
#[arg(short, long, help = "generate the initialize script for the shell", value_name = "SHELL", hide = true, default_missing_value = "bash")]
pub init: Option<String>,

#[arg(short = 't', long = "type", help = "specify the nexter type", value_enum, default_value_t = NexterType::Next, value_name = "TYPE", ignore_case = true)]
pub nexter: NexterType,

#[arg(index = 1, help = "the directory for listing the siblings", value_name = "DIR", default_value = ".")]
pub dir: PathBuf,
#[arg(index = 1, help = "the target directory", value_name = "DIR")]
pub dirs: Vec<PathBuf>,
}

#[derive(Debug, Parser)]
Expand Down
14 changes: 11 additions & 3 deletions src/dirs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl Dirs {
if current_dir == PathBuf::from(".") {
match std::env::current_dir() {
Ok(dir) =>
build_dirs(current_dir.parent(), dir),
build_dirs(dir.clone().parent(), dir),
Err(e) => Err(SiblingError::Io(e)),
}
} else if current_dir.exists() {
Expand Down Expand Up @@ -92,10 +92,18 @@ mod tests {

#[test]
fn test_dirs_new() {
let dirs = Dirs::new(PathBuf::from("testdata/b"));
let dirs = Dirs::new(PathBuf::from("testdata/d"));
assert!(dirs.is_ok());
let dirs = dirs.unwrap();
assert_eq!(dirs.dirs.len(), 26);
assert_eq!(dirs.current, 1);
assert_eq!(dirs.current, 3);
}

#[test]
fn test_dir_dot() {
let dirs = Dirs::new(PathBuf::from("."));
assert!(dirs.is_ok());
let dirs = dirs.unwrap();
assert_eq!(dirs.current_path().file_name().map(|s| s.to_str()), Some("sibling".into()));
}
}
78 changes: 66 additions & 12 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
use std::path::PathBuf;

use clap::Parser;
use crate::cli::{CliOpts, PrintingOpts, Result, SiblingError};
use crate::nexter::Nexter;
Expand All @@ -8,20 +10,43 @@ mod init;
mod nexter;
mod printer;

fn perform_impl(mut dirs: dirs::Dirs, nexter: Box<dyn Nexter>, step: i32, opts: PrintingOpts) -> Result<String> {
fn perform_impl(mut dirs: dirs::Dirs, nexter: &Box<dyn Nexter>, step: i32, opts: &PrintingOpts) -> Result<String> {
nexter.next(&mut dirs, step);
printer::result_string(&dirs, opts)
}

fn perform(opts: CliOpts) -> Result<String> {
fn perform_each(dir: std::path::PathBuf, nexter: &Box<dyn Nexter>, step: i32, opts: &PrintingOpts) -> Result<String> {
match dirs::Dirs::new(dir) {
Err(e) => Err(e),
Ok(dirs) => perform_impl(dirs, nexter, step, opts),
}
}

fn perform_sibling(opts: CliOpts) -> Vec<Result<String>> {
let nexter = nexter::build_nexter(opts.nexter);
let target_dirs = if opts.dirs.is_empty() {
vec![std::env::current_dir().unwrap()]
} else {
opts.dirs
};
let mut result = vec![];
for dir in target_dirs {
let dir = if dir == PathBuf::from(".") {
std::env::current_dir().unwrap()
} else {
std::path::PathBuf::from(dir)
};
let r = perform_each(dir, &nexter, opts.step, &opts.p_opts);
result.push(r);
}
result
}

fn perform(opts: CliOpts) -> Vec<Result<String>> {
if let Some(shell) = opts.init {
init::generate_init_script(shell)
vec![init::generate_init_script(shell)]
} else {
let nexter = nexter::build_nexter(opts.nexter);
match dirs::Dirs::new(opts.dir) {
Err(e) => Err(e),
Ok(dirs) => perform_impl(dirs, nexter, opts.step, opts.p_opts),
}
perform_sibling(opts)
}
}

Expand All @@ -39,9 +64,38 @@ fn print_error(e: &SiblingError) {
}

fn main() {
let opts = cli::CliOpts::parse();
match perform(opts) {
Ok(result) => println!("{}", result),
Err(e) => print_error(&e),
let mut args = std::env::args();
let args = if args.len() == 1 {
vec![args.next().unwrap(), ".".into()]
} else {
args.collect()
};
let opts = cli::CliOpts::parse_from(args);
for item in perform(opts) {
match item {
Ok(result) => println!("{}", result),
Err(e) => print_error(&e),
}
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_nexter_example() {
let opts_r = cli::CliOpts::try_parse_from(vec!["sibling", "."]);

if let Err(e) = &opts_r {
eprintln!("{}", e);
}
assert!(opts_r.is_ok());
let r = perform(opts_r.unwrap());
assert_eq!(r.len(), 1);
match r.get(0).unwrap() {
Err(e) => print_error(&e),
Ok(result) => println!("{}", result),
}
}
}
9 changes: 6 additions & 3 deletions src/nexter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,6 @@ fn next_impl(dirs: &mut Dirs, step: i32) -> Option<PathBuf> {
} else {
dirs.dirs.get(dirs.next as usize)
};
dirs.current = dirs.next as usize;
r.map(|f| f.to_path_buf())
}

Expand Down Expand Up @@ -122,7 +121,7 @@ mod tests {
Some(p) => assert_eq!(p, PathBuf::from("testdata/d")),
None => panic!("unexpected None"),
}
match nexter.next(&mut dirs, 1) {
match nexter.next(&mut dirs, 2) {
Some(p) => assert_eq!(p, PathBuf::from("testdata/e")),
None => panic!("unexpected None"),
}
Expand All @@ -144,8 +143,12 @@ mod tests {
Some(p) => assert_eq!(p, PathBuf::from("testdata/j")),
None => panic!("unexpected None"),
}
match nexter.next(&mut dirs, 1) {
Some(p) => assert_eq!(p, PathBuf::from("testdata/j")),
None => panic!("unexpected None"),
}
match nexter.next(&mut dirs, 4) {
Some(p) => assert_eq!(p, PathBuf::from("testdata/f")),
Some(p) => assert_eq!(p, PathBuf::from("testdata/g")),
None => panic!("unexpected None"),
}
match nexter.next(&mut dirs, 26) {
Expand Down
10 changes: 5 additions & 5 deletions src/printer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::path::PathBuf;
use crate::cli::{PrintingOpts, Result};
use crate::dirs::Dirs;

pub(crate) fn result_string(dirs: &Dirs, opts: PrintingOpts) -> Result<String> {
pub(crate) fn result_string(dirs: &Dirs, opts: &PrintingOpts) -> Result<String> {
if opts.csv {
csv_string(dirs, opts.absolute)
} else if dirs.no_more_dir {
Expand All @@ -22,15 +22,15 @@ fn csv_string(dirs: &Dirs, absolute: bool) -> Result<String> {
dirs.current + 1, dirs.next + 1, dirs.dirs.len()))
}

fn no_more_dir_string(dirs: &Dirs, opts: PrintingOpts) -> Result<String> {
fn no_more_dir_string(dirs: &Dirs, opts: &PrintingOpts) -> Result<String> {
if opts.parent {
Ok(pathbuf_to_string(Some(dirs.parent.clone()), opts.absolute))
} else {
Ok(String::from("no more sibling directory"))
}
}

fn list_string(dirs: &Dirs, opts: PrintingOpts) -> Result<String> {
fn list_string(dirs: &Dirs, opts: &PrintingOpts) -> Result<String> {
let mut result = vec![];
for (i, dir) in dirs.dirs.iter().enumerate() {
let prefix = if i == dirs.next as usize { "> " }
Expand All @@ -39,12 +39,12 @@ fn list_string(dirs: &Dirs, opts: PrintingOpts) -> Result<String> {
} else {
" "
};
result.push(format!("{}{}: {}", i + 1, prefix, pathbuf_to_string(Some(dir.to_path_buf()), opts.absolute)));
result.push(format!("{:>4} {}{}", i + 1, prefix, pathbuf_to_string(Some(dir.to_path_buf()), opts.absolute)));
}
Ok(result.join("\n"))
}

fn result_string_impl(dirs: &Dirs, opts: PrintingOpts) -> Result<String> {
fn result_string_impl(dirs: &Dirs, opts: &PrintingOpts) -> Result<String> {
let r = if opts.progress {
format!("{} ({}/{})", pathbuf_to_string(dirs.next_path(), opts.absolute), dirs.next + 1, dirs.dirs.len())
} else {
Expand Down

0 comments on commit f84e4ed

Please sign in to comment.