devalang_wasm/tools/cli/
mod.rs

1#![cfg(feature = "cli")]
2
3mod commands;
4pub mod config;
5pub mod io;
6pub mod state;
7
8use anyhow::Result;
9use clap::{Parser, Subcommand};
10use commands::devices::DevicesListCommand;
11use commands::play::PlayCommand;
12use state::CliContext;
13
14#[derive(Parser, Debug)]
15#[command(name = "devalang")]
16#[command(
17    version,
18    about = "🦊 Devalang – A programming language for music and sound."
19)]
20pub struct Cli {
21    #[command(subcommand)]
22    command: Commands,
23}
24
25#[derive(Subcommand, Debug)]
26pub enum Commands {
27    /// Build and play deva file(s)
28    Play(PlayCommand),
29    /// Initialize a new project
30    Init(commands::init::InitCommand),
31    /// Builds deva file(s)
32    Build(commands::build::BuildCommand),
33    /// Check syntax without building
34    Check(commands::check::CheckCommand),
35    /// Manages addons (install, update, remove, list, discover)
36    Addon(commands::addon::AddonCommand),
37    /// Login to Devalang (authenticate with token)
38    Login {
39        /// Authentication token (optional, will prompt if not provided)
40        token: Option<String>,
41    },
42    /// Logout from Devalang
43    Logout,
44    /// Check authentication status
45    Me,
46    /// Manage telemetry settings
47    Telemetry {
48        #[command(subcommand)]
49        action: TelemetryAction,
50    },
51    /// Manage MIDI devices
52    Devices {
53        #[command(subcommand)]
54        action: DevicesCommands,
55    },
56}
57
58#[derive(Subcommand, Debug)]
59pub enum DevicesCommands {
60    /// List MIDI devices
61    List(DevicesListCommand),
62    /// Preview incoming/outgoing notes (non-writing)
63    Preview(commands::devices::DevicesLiveCommand),
64    /// Record incoming notes and write to a file
65    Write(commands::devices::DevicesWriteCommand),
66}
67
68#[derive(Subcommand, Debug)]
69pub enum TelemetryAction {
70    /// Enable telemetry
71    Enable,
72    /// Disable telemetry
73    Disable,
74    /// Show telemetry status
75    Status,
76}
77
78pub fn run() -> Result<()> {
79    let cli = Cli::parse();
80    let ctx = CliContext::new();
81    let runtime = tokio::runtime::Runtime::new()?;
82
83    runtime.block_on(async move {
84        match cli.command {
85            Commands::Play(command) => commands::play::execute(command, &ctx).await?,
86            Commands::Init(command) => command.execute(&ctx).await?,
87            Commands::Build(command) => command.execute(&ctx).await?,
88            Commands::Check(command) => command.execute(&ctx).await?,
89            Commands::Addon(command) => command.execute(&ctx).await?,
90            Commands::Login { token } => commands::auth::login(token).await?,
91            Commands::Logout => commands::auth::logout().await?,
92            Commands::Me => commands::auth::check_auth_status().await?,
93            Commands::Telemetry { action } => {
94                let logger = ctx.logger();
95                match action {
96                    TelemetryAction::Enable => {
97                        config::telemetry::enable_telemetry()?;
98                        logger.success("Telemetry enabled");
99                        logger.info("Thank you for helping us improve Devalang!");
100                    }
101                    TelemetryAction::Disable => {
102                        config::telemetry::disable_telemetry()?;
103                        logger.success("Telemetry disabled");
104                    }
105                    TelemetryAction::Status => {
106                        let status = config::telemetry::get_telemetry_status();
107                        logger.info(format!("Telemetry is currently: {}", status));
108                    }
109                }
110            }
111            Commands::Devices { action } => match action {
112                DevicesCommands::List(cmd) => {
113                    commands::devices::execute_list(cmd, &ctx)?;
114                }
115                DevicesCommands::Preview(cmd) => {
116                    commands::devices::execute_preview(cmd, &ctx).await?;
117                }
118                DevicesCommands::Write(cmd) => {
119                    commands::devices::execute_write(cmd, &ctx).await?;
120                }
121            },
122        }
123        Ok(())
124    })
125}