cargo_near/
lib.rs

1#![allow(clippy::large_enum_variant)]
2
3pub use near_cli_rs::{CliResult, GlobalContext, Verbosity};
4
5use strum::{EnumDiscriminants, EnumIter, EnumMessage};
6
7pub mod commands;
8pub mod types;
9
10pub(crate) mod posthog_tracking;
11
12#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
13#[interactive_clap(context = near_cli_rs::GlobalContext)]
14pub struct Cmd {
15    #[interactive_clap(subcommand)]
16    pub opts: Opts,
17}
18
19#[derive(Debug, EnumDiscriminants, Clone, interactive_clap::InteractiveClap)]
20#[interactive_clap(context = near_cli_rs::GlobalContext)]
21#[strum_discriminants(derive(EnumMessage, EnumIter))]
22#[interactive_clap(disable_back)]
23/// Near
24pub enum Opts {
25    #[strum_discriminants(strum(message = "near"))]
26    /// Which subcommand of `near` extension do you want to use?
27    Near(NearArgs),
28}
29
30#[derive(Debug, Clone, interactive_clap::InteractiveClap)]
31#[interactive_clap(context = near_cli_rs::GlobalContext)]
32pub struct NearArgs {
33    /// TEACH-ME mode, more verbose logging for each action that the CLI performs
34    #[interactive_clap(long)]
35    teach_me: bool,
36    #[interactive_clap(subcommand)]
37    pub cmd: self::commands::NearCommand,
38}
39
40pub fn setup_tracing(rust_log_env_is_set: bool, teach_me_flag_is_set: bool) -> CliResult {
41    use colored::Colorize;
42    use tracing::{Event, Level, Subscriber};
43    use tracing_indicatif::style::ProgressStyle;
44    use tracing_indicatif::IndicatifLayer;
45    use tracing_subscriber::layer::SubscriberExt;
46    use tracing_subscriber::util::SubscriberInitExt;
47    use tracing_subscriber::EnvFilter;
48    use tracing_subscriber::{fmt::format, prelude::*};
49    use tracing_subscriber::{
50        fmt::{format::Writer, FmtContext, FormatEvent, FormatFields},
51        registry::LookupSpan,
52    };
53
54    use cargo_near_build::env_keys;
55
56    struct SimpleFormatter;
57
58    impl<S, N> FormatEvent<S, N> for SimpleFormatter
59    where
60        S: Subscriber + for<'a> LookupSpan<'a>,
61        N: for<'a> FormatFields<'a> + 'static,
62    {
63        fn format_event(
64            &self,
65            ctx: &FmtContext<'_, S, N>,
66            mut writer: Writer<'_>,
67            event: &Event<'_>,
68        ) -> std::fmt::Result {
69            let level = *event.metadata().level();
70            let (icon, color_code) = match level {
71                Level::TRACE => ("TRACE ", "\x1b[35m"),  // Magenta
72                Level::DEBUG => ("DEBUG ", "\x1b[34m"),  // Blue
73                Level::INFO => ("", ""),                 // Default
74                Level::WARN => ("Warning ", "\x1b[33m"), // Yellow
75                Level::ERROR => ("ERROR ", "\x1b[31m"),  // Red
76            };
77
78            write!(writer, "{}├  {}", color_code, icon)?;
79
80            write!(writer, "\x1b[0m")?;
81
82            ctx.field_format().format_fields(writer.by_ref(), event)?;
83
84            writeln!(writer)
85        }
86    }
87
88    if rust_log_env_is_set {
89        let environment = if std::env::var(env_keys::nep330::BUILD_ENVIRONMENT).is_ok() {
90            "container".cyan()
91        } else {
92            "host".purple()
93        };
94        let my_formatter = types::my_formatter::MyFormatter::from_environment(environment);
95
96        let format = format::debug_fn(move |writer, _field, value| write!(writer, "{value:?}"));
97
98        let _e = tracing_subscriber::registry()
99            .with(
100                tracing_subscriber::fmt::layer()
101                    .event_format(my_formatter)
102                    .fmt_fields(format)
103                    .with_filter(EnvFilter::from_default_env()),
104            )
105            .try_init();
106    } else if teach_me_flag_is_set {
107        let env_filter = EnvFilter::from_default_env()
108            .add_directive(tracing::Level::WARN.into())
109            .add_directive("near_teach_me=info".parse()?)
110            .add_directive("near_cli_rs=info".parse()?)
111            .add_directive("tracing_instrument=info".parse()?);
112        tracing_subscriber::registry()
113            .with(tracing_subscriber::fmt::layer().event_format(SimpleFormatter))
114            .with(env_filter)
115            .init();
116    } else {
117        let indicatif_layer = IndicatifLayer::new()
118            .with_progress_style(
119                ProgressStyle::with_template(
120                    "{spinner:.blue}{span_child_prefix} {span_name} {msg} {span_fields}",
121                )
122                .unwrap()
123                .tick_strings(&["◐", "◓", "◑", "◒"]),
124            )
125            .with_span_child_prefix_symbol("↳ ");
126        let env_filter = EnvFilter::from_default_env()
127            .add_directive(tracing::Level::WARN.into())
128            .add_directive("near_cli_rs=info".parse()?)
129            .add_directive("tracing_instrument=info".parse()?);
130        tracing_subscriber::registry()
131            .with(
132                tracing_subscriber::fmt::layer()
133                    .event_format(SimpleFormatter)
134                    .with_writer(indicatif_layer.get_stderr_writer()),
135            )
136            .with(indicatif_layer)
137            .with(env_filter)
138            .init();
139    };
140    Ok(())
141}