1mod color;
2mod convert;
3mod diff;
4mod dump;
5mod progress_handler;
6mod tree;
7mod verify;
8
9#[cfg(feature = "color")]
10use self::color::get_styles;
11use self::convert::{convert, tokio_convert};
12use crate::logger::LogLevel;
13use clap::CommandFactory as _;
14use serde_hkx_features::{
15 convert::OutFormat,
16 diff::write_diff,
17 dump as hexdump,
18 error::{Error, Result},
19 tree::write_tree,
20};
21use std::{io, path::PathBuf};
22
23pub(crate) async fn run(args: Args) -> Result<()> {
24 crate::logger::init(args.log_file, args.log_level, args.stdout)?;
25
26 if let Some(input) = args.input {
28 let out_fmt = OutFormat::from_input(&input)?;
29 let output: Option<PathBuf> = None;
30 return tokio_convert(input, output, out_fmt).await;
31 }
32
33 if let Some(command) = args.subcommand {
34 match command {
35 SubCommands::Convert(args) => {
36 convert(&args.input, args.output, args.format, args.runtime).await
37 }
38 SubCommands::Tree(args) => write_tree(args.input, args.output).await,
39 SubCommands::Dump(args) => match args.reverse {
40 true => hexdump::to_bytes(args.input, args.output).await,
41 false => hexdump::to_string(args.input, args.output).await,
42 },
43 SubCommands::Diff(args) => {
44 write_diff(args.old, args.new, args.output, args.color).await
45 }
46 SubCommands::Verify(args) => self::verify::verify(&args.path, args.color),
47 SubCommands::Completions { shell } => {
48 shell.generate(&mut Args::command(), &mut io::stdout());
49 Ok(())
50 }
51 }
52 } else {
53 Args::command().print_long_help()?;
54 pub const ERR_MSG: &str = color_print::cstr!(
55 r#"
56<red>error:</red> '<red>hkxc</red>' requires a subcommand or hkx/xml path.
57For more information, try '<cyan!>--help</cyan!>'.
58"#
59 );
60 Err(Error::IoError {
61 source: io::Error::new(io::ErrorKind::InvalidInput, ERR_MSG),
62 })
63 }
64}
65
66#[derive(Debug, clap::Parser)]
68#[clap(version, about, author)]
69#[cfg_attr(feature = "color", clap(styles=get_styles()))]
70#[clap(arg_required_else_help = true, args_conflicts_with_subcommands = true, after_long_help = convert::EXAMPLES)]
71pub(crate) struct Args {
72 pub input: Option<PathBuf>,
74
75 #[clap(subcommand)]
76 subcommand: Option<SubCommands>,
77
78 #[clap(global = true, long, display_order = 100)]
80 pub stdout: bool,
82 #[clap(global = true, long, display_order = 101)]
83 #[clap(ignore_case = true, default_value = "error")]
84 pub log_level: LogLevel,
86 #[clap(global = true, long, display_order = 102)]
87 pub log_file: Option<PathBuf>,
89}
90
91#[derive(Debug, clap::Parser)]
92pub(crate) enum SubCommands {
93 Convert(convert::Args),
95
96 Tree(tree::Args),
98
99 Dump(dump::Args),
101
102 Diff(diff::Args),
104
105 Verify(verify::Args),
107
108 #[clap(arg_required_else_help = true)]
110 Completions {
111 #[arg(value_enum)]
113 shell: clap_complete_command::Shell,
114 },
115}