use anyhow::{Result, anyhow};
use clap::{Parser, builder::ValueParser};
use code2prompt_core::{
sort::FileSortMethod, template::OutputFormat, tokenizer::TokenFormat, tokenizer::TokenizerType,
};
use serde::de::DeserializeOwned;
use std::path::PathBuf;
#[derive(Parser, Debug)]
#[clap(
name = env!("CARGO_PKG_NAME"),
version = env!("CARGO_PKG_VERSION"),
author = env!("CARGO_PKG_AUTHORS")
)]
#[command(arg_required_else_help = true)]
pub struct Cli {
#[arg(value_name = "PATH_TO_ANALYZE", default_value = ".")]
pub path: PathBuf,
#[arg(short = 'O', long = "output-file", value_name = "FILE")]
pub output_file: Option<String>,
#[clap(long)]
pub tui: bool,
#[clap(short = 'i', long = "include")]
pub include: Vec<String>,
#[clap(short = 'e', long = "exclude")]
pub exclude: Vec<String>,
#[clap(
short = 'F',
long = "output-format",
value_name = "markdown, json, xml",
value_parser = ValueParser::new(parse_serde::<OutputFormat>)
)]
pub output_format: Option<OutputFormat>,
#[clap(short, long, value_name = "TEMPLATE")]
pub template: Option<PathBuf>,
#[clap(long)]
pub full_directory_tree: bool,
#[clap(
long,
value_name = "cl100k, p50k, p50k_edit, r50k",
value_parser = ValueParser::new(parse_serde::<TokenizerType>),
)]
pub encoding: Option<TokenizerType>,
#[clap(
long,
value_name = "raw,format",
value_parser = ValueParser::new(parse_serde::<TokenFormat>),
)]
pub token_format: Option<TokenFormat>,
#[clap(short, long)]
pub diff: bool,
#[clap(long, value_name = "BRANCHES", num_args = 2, value_delimiter = ',')]
pub git_diff_branch: Option<Vec<String>>,
#[clap(long, value_name = "BRANCHES", num_args = 2, value_delimiter = ',')]
pub git_log_branch: Option<Vec<String>>,
#[clap(short, long)]
pub line_numbers: bool,
#[clap(long)]
pub absolute_paths: bool,
#[clap(short = 'L', long)]
pub follow_symlinks: bool,
#[clap(long)]
pub hidden: bool,
#[clap(long)]
pub no_codeblock: bool,
#[clap(short = 'c', long)]
pub clipboard: bool,
#[clap(long, hide = true)]
pub no_clipboard: bool,
#[clap(long)]
pub no_ignore: bool,
#[clap(
long,
value_name = "name_asc, name_desc, date_asc, date_desc",
value_parser = ValueParser::new(parse_serde::<FileSortMethod>),
)]
pub sort: Option<FileSortMethod>,
#[clap(short = 'q', long)]
pub quiet: bool,
#[clap(long)]
pub token_map: bool,
#[clap(long, value_name = "NUMBER")]
pub token_map_lines: Option<usize>,
#[clap(long, value_name = "PERCENT")]
pub token_map_min_percent: Option<f64>,
#[arg(long, hide = true)]
pub clipboard_daemon: bool,
}
fn parse_serde<T: DeserializeOwned>(s: &str) -> Result<T> {
serde_json::from_value(serde_json::Value::String(s.to_string()))
.map_err(|e| anyhow!("Failed to parse value: {}", e))
}