hkxc/args/
mod.rs

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    // For drag & drop
27    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/// CLI command arguments
67#[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    /// The path of the target for drag and drop hkx(64bit) <-> xml conversion (The converted file will be created in the same location)
73    pub input: Option<PathBuf>,
74
75    #[clap(subcommand)]
76    subcommand: Option<SubCommands>,
77
78    // --logger (Global options)
79    #[clap(global = true, long, display_order = 100)]
80    /// Enable standard output of the log
81    pub stdout: bool,
82    #[clap(global = true, long, display_order = 101)]
83    #[clap(ignore_case = true, default_value = "error")]
84    /// Log level to be recorded in logger
85    pub log_level: LogLevel,
86    #[clap(global = true, long, display_order = 102)]
87    /// Output path of log file
88    pub log_file: Option<PathBuf>,
89}
90
91#[derive(Debug, clap::Parser)]
92pub(crate) enum SubCommands {
93    /// Convert hkx <-> xml
94    Convert(convert::Args),
95
96    /// Show dependency tree from havok behavior(hkx/xml file)
97    Tree(tree::Args),
98
99    /// Dump binary data in hexadecimal
100    Dump(dump::Args),
101
102    /// Show diff between two files.(In the case of `.hkx`, it is automatically converted to hexdump)
103    Diff(diff::Args),
104
105    /// Parallel hkx reproduction checks. If an error occurs, return a diff showing the location of each error.
106    Verify(verify::Args),
107
108    /// Generate shell completions
109    #[clap(arg_required_else_help = true)]
110    Completions {
111        /// The shell to generate the completions for
112        #[arg(value_enum)]
113        shell: clap_complete_command::Shell,
114    },
115}