diff options
| -rw-r--r-- | src/cli.rs | 172 | ||||
| -rw-r--r-- | src/main.rs | 173 |
2 files changed, 177 insertions, 168 deletions
diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..4525781 --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,172 @@ +use std::path::PathBuf; + +use clap::Parser; +use repo2markdown::{ + logger::Verbosity, + renderer::{DEFAULT_MAX_FILE_SIZE, RenderOptions}, +}; + +#[derive(Debug, Parser)] +#[command(version, about, long_about = None)] +pub struct Cli { + /// Root path to which file paths displayed in the generated markdown are relative. + #[arg(long, default_value = ".")] + pub root: PathBuf, + + /// Base path used to resolve relative input paths. + #[arg(long, default_value = ".")] + pub origin: PathBuf, + + /// Project title to use in the markdown header. + #[arg(long)] + pub name: Option<String>, + + /// Wrap the entire output in a markdown code fence. + #[arg(long)] + pub fenced: bool, + + /// Maximum file size, in bytes, to include in the generated markdown. + #[arg(long, default_value_t = DEFAULT_MAX_FILE_SIZE, value_name = "BYTES")] + max_file_size: u64, + + /// Include a placeholder entry when a binary file is skipped. + #[arg(long)] + placeholder_binary_files: bool, + + /// Include a placeholder entry when a large file is skipped. + #[arg(long)] + placeholder_large_files: bool, + + /// Suppress warnings and informational logs. + #[arg(long, conflicts_with = "verbose")] + quiet: bool, + + /// Include informational logs. + #[arg(long, conflicts_with = "quiet")] + verbose: bool, +} + +impl Cli { + pub fn render_options(&self) -> RenderOptions { + RenderOptions { + max_file_size: self.max_file_size, + placeholder_for_binary_files: self.placeholder_binary_files, + placeholder_for_large_files: self.placeholder_large_files, + } + } + + pub fn verbosity(&self) -> Verbosity { + if self.quiet { + Verbosity::Quiet + } else if self.verbose { + Verbosity::Verbose + } else { + Verbosity::Normal + } + } +} + +#[cfg(test)] +mod tests { + use std::path::PathBuf; + + use clap::Parser; + use repo2markdown::logger::Verbosity; + + use super::{Cli, RenderOptions}; + + #[test] + fn cli_uses_default_paths_and_normal_verbosity() { + let cli = Cli::try_parse_from(["repo2markdown"]).unwrap(); + + assert_eq!(cli.root, PathBuf::from(".")); + assert_eq!(cli.origin, PathBuf::from(".")); + assert_eq!(cli.name, None); + assert_eq!(cli.verbosity(), Verbosity::Normal); + } + + #[test] + fn cli_accepts_root_origin_and_name() { + let cli = Cli::try_parse_from([ + "repo2markdown", + "--root", + "/repo", + "--origin", + "/repo/src", + "--name", + "My Project", + ]) + .unwrap(); + + assert_eq!(cli.root, PathBuf::from("/repo")); + assert_eq!(cli.origin, PathBuf::from("/repo/src")); + assert_eq!(cli.name.as_deref(), Some("My Project")); + } + + #[test] + fn cli_accepts_render_options() { + let cli = Cli::try_parse_from([ + "repo2markdown", + "--max-file-size", + "5", + "--placeholder-binary-files", + "--placeholder-large-files", + ]) + .unwrap(); + + let options = cli.render_options(); + + assert_eq!(options.max_file_size, 5); + assert!(options.placeholder_for_binary_files); + assert!(options.placeholder_for_large_files); + } + + #[test] + fn cli_defaults_unspecified_render_options() { + let cli = Cli::try_parse_from(["repo2markdown"]).unwrap(); + + assert_eq!(cli.render_options(), RenderOptions::default()); + } + + #[test] + fn cli_accepts_quiet_verbosity() { + let cli = Cli::try_parse_from(["repo2markdown", "--quiet"]).unwrap(); + + assert_eq!(cli.verbosity(), Verbosity::Quiet); + } + + #[test] + fn cli_accepts_verbose_verbosity() { + let cli = Cli::try_parse_from(["repo2markdown", "--verbose"]).unwrap(); + + assert_eq!(cli.verbosity(), Verbosity::Verbose); + } + + #[test] + fn cli_rejects_quiet_and_verbose_together() { + let result = Cli::try_parse_from(["repo2markdown", "--quiet", "--verbose"]); + + assert!(result.is_err()); + } + + #[test] + fn cli_rejects_invalid_max_file_size() { + let result = Cli::try_parse_from(["repo2markdown", "--max-file-size", "not-a-number"]); + + assert!(result.is_err()); + } + + #[test] + fn cli_does_not_use_fenced_output_by_default() { + let cli = Cli::try_parse_from(["repo2markdown"]).unwrap(); + + assert!(!cli.fenced); + } + + #[test] + fn cli_accepts_fenced_output_option() { + let cli = Cli::try_parse_from(["repo2markdown", "--fenced"]).unwrap(); + + assert!(cli.fenced); + } +} diff --git a/src/main.rs b/src/main.rs index bc193e8..0cb672f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,72 +1,14 @@ -use std::{io, path::PathBuf}; +mod cli; + +use std::io; use clap::Parser; use repo2markdown::{ - fenced_md_generator::generate_fenced_markdown, - logger::{Logger, Verbosity}, + fenced_md_generator::generate_fenced_markdown, logger::Logger, md_generator::generate_markdown_from_paths, - renderer::{DEFAULT_MAX_FILE_SIZE, RenderOptions}, }; -#[derive(Debug, Parser)] -#[command(version, about, long_about = None)] -struct Cli { - /// Root path to which file paths displayed in the generated markdown are relative. - #[arg(long, default_value = ".")] - root: PathBuf, - - /// Base path used to resolve relative input paths. - #[arg(long, default_value = ".")] - origin: PathBuf, - - /// Project title to use in the markdown header. - #[arg(long)] - name: Option<String>, - - /// Wrap the entire output in a markdown code fence. - #[arg(long)] - fenced: bool, - - /// Maximum file size, in bytes, to include in the generated markdown. - #[arg(long, default_value_t = DEFAULT_MAX_FILE_SIZE, value_name = "BYTES")] - max_file_size: u64, - - /// Include a placeholder entry when a binary file is skipped. - #[arg(long)] - placeholder_binary_files: bool, - - /// Include a placeholder entry when a large file is skipped. - #[arg(long)] - placeholder_large_files: bool, - - /// Suppress warnings and informational logs. - #[arg(long, conflicts_with = "verbose")] - quiet: bool, - - /// Include informational logs. - #[arg(long, conflicts_with = "quiet")] - verbose: bool, -} - -impl Cli { - fn render_options(&self) -> RenderOptions { - RenderOptions { - max_file_size: self.max_file_size, - placeholder_for_binary_files: self.placeholder_binary_files, - placeholder_for_large_files: self.placeholder_large_files, - } - } - - fn verbosity(&self) -> Verbosity { - if self.quiet { - Verbosity::Quiet - } else if self.verbose { - Verbosity::Verbose - } else { - Verbosity::Normal - } - } -} +use crate::cli::Cli; fn main() -> Result<(), Box<dyn std::error::Error>> { let cli = Cli::parse(); @@ -98,108 +40,3 @@ fn main() -> Result<(), Box<dyn std::error::Error>> { ) } } - -#[cfg(test)] -mod tests { - use std::path::PathBuf; - - use clap::Parser; - use repo2markdown::logger::Verbosity; - - use super::{Cli, RenderOptions}; - - #[test] - fn cli_uses_default_paths_and_normal_verbosity() { - let cli = Cli::try_parse_from(["repo2markdown"]).unwrap(); - - assert_eq!(cli.root, PathBuf::from(".")); - assert_eq!(cli.origin, PathBuf::from(".")); - assert_eq!(cli.name, None); - assert_eq!(cli.verbosity(), Verbosity::Normal); - } - - #[test] - fn cli_accepts_root_origin_and_name() { - let cli = Cli::try_parse_from([ - "repo2markdown", - "--root", - "/repo", - "--origin", - "/repo/src", - "--name", - "My Project", - ]) - .unwrap(); - - assert_eq!(cli.root, PathBuf::from("/repo")); - assert_eq!(cli.origin, PathBuf::from("/repo/src")); - assert_eq!(cli.name.as_deref(), Some("My Project")); - } - - #[test] - fn cli_accepts_render_options() { - let cli = Cli::try_parse_from([ - "repo2markdown", - "--max-file-size", - "5", - "--placeholder-binary-files", - "--placeholder-large-files", - ]) - .unwrap(); - - let options = cli.render_options(); - - assert_eq!(options.max_file_size, 5); - assert!(options.placeholder_for_binary_files); - assert!(options.placeholder_for_large_files); - } - - #[test] - fn cli_defaults_unspecified_render_options() { - let cli = Cli::try_parse_from(["repo2markdown"]).unwrap(); - - assert_eq!(cli.render_options(), RenderOptions::default()); - } - - #[test] - fn cli_accepts_quiet_verbosity() { - let cli = Cli::try_parse_from(["repo2markdown", "--quiet"]).unwrap(); - - assert_eq!(cli.verbosity(), Verbosity::Quiet); - } - - #[test] - fn cli_accepts_verbose_verbosity() { - let cli = Cli::try_parse_from(["repo2markdown", "--verbose"]).unwrap(); - - assert_eq!(cli.verbosity(), Verbosity::Verbose); - } - - #[test] - fn cli_rejects_quiet_and_verbose_together() { - let result = Cli::try_parse_from(["repo2markdown", "--quiet", "--verbose"]); - - assert!(result.is_err()); - } - - #[test] - fn cli_rejects_invalid_max_file_size() { - let result = Cli::try_parse_from(["repo2markdown", "--max-file-size", "not-a-number"]); - - assert!(result.is_err()); - } - - #[test] - fn cli_does_not_use_fenced_output_by_default() { - let cli = Cli::try_parse_from(["repo2markdown"]).unwrap(); - - assert!(!cli.fenced); - } - - #[test] - fn cli_accepts_fenced_output_option() { - let cli = Cli::try_parse_from(["repo2markdown", "--fenced"]).unwrap(); - - assert!(cli.fenced); - } -} |
