1use crate::subcommands::{self, BuildArgs, CleanArgs, InitArgs};
2
3use anyhow::Result;
4use clap::{Parser, Subcommand, ValueEnum};
5use const_format::formatcp;
6use tracing::Level;
7use tracing_subscriber::FmtSubscriber;
8
9static VERSION: &str = formatcp!(
10 "v{cli_version}\nshulkerscript-lang v{lang_version}",
11 cli_version = env!("CARGO_PKG_VERSION"),
12 lang_version = shulkerscript::VERSION
13);
14
15#[derive(Debug, Clone, Parser)]
16#[command(version, about, long_about = None, disable_version_flag = false, version = VERSION)]
17pub struct Args {
18 #[command(subcommand)]
19 cmd: Command,
20 #[arg(
24 long,
25 global = true,
26 default_missing_value = "info",
27 require_equals = true,
28 num_args = 0..=1,
29 value_name = "LEVEL"
30 )]
31 trace: Option<TracingLevel>,
32}
33
34#[derive(Debug, Clone, Subcommand)]
35pub enum Command {
36 Init(InitArgs),
38 Build(BuildArgs),
40 Clean(CleanArgs),
43 #[cfg(feature = "lang-debug")]
44 LangDebug(subcommands::LangDebugArgs),
46 #[cfg(feature = "migrate")]
47 Migrate(subcommands::MigrateArgs),
49 #[cfg(feature = "watch")]
50 Watch(subcommands::WatchArgs),
52}
53
54#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, ValueEnum)]
55pub enum TracingLevel {
56 Trace,
57 Debug,
58 #[default]
59 Info,
60 Warn,
61 Error,
62}
63
64impl Args {
65 pub fn run(&self) -> Result<()> {
66 if let Some(level) = self.trace {
67 setup_tracing(level)?;
68 }
69
70 self.cmd.run()
71 }
72}
73
74impl Command {
75 pub fn run(&self) -> Result<()> {
76 match self {
77 Command::Init(args) => subcommands::init(args)?,
78 Command::Build(args) => subcommands::build(args)?,
79 Command::Clean(args) => subcommands::clean(args)?,
80 #[cfg(feature = "lang-debug")]
81 Command::LangDebug(args) => subcommands::lang_debug(args)?,
82 #[cfg(feature = "migrate")]
83 Command::Migrate(args) => subcommands::migrate(args)?,
84 #[cfg(feature = "watch")]
85 Command::Watch(args) => subcommands::watch(args)?,
86 }
87
88 Ok(())
89 }
90}
91
92impl From<TracingLevel> for Level {
93 fn from(value: TracingLevel) -> Self {
94 match value {
95 TracingLevel::Trace => Level::TRACE,
96 TracingLevel::Debug => Level::DEBUG,
97 TracingLevel::Info => Level::INFO,
98 TracingLevel::Warn => Level::WARN,
99 TracingLevel::Error => Level::ERROR,
100 }
101 }
102}
103
104fn setup_tracing(level: TracingLevel) -> Result<()> {
105 let subscriber = FmtSubscriber::builder()
107 .with_max_level(Level::from(level))
110 .finish();
112
113 tracing::subscriber::set_global_default(subscriber)?;
114
115 Ok(())
116}
117
118#[cfg(test)]
119mod tests {
120 use clap::CommandFactory;
121
122 use super::*;
123
124 #[test]
125 fn verify_cli() {
126 Args::command().debug_assert();
127 }
128}