Skip to content

Commit 0dcdfea

Browse files
feat: add CLI support with --testing, --verbose, and --port flags (#207)
* feat: add CLI support with --testing, --verbose, and --port flags Add command-line argument parsing via clap to match aw-qt's CLI interface. Flags: - --testing: Run in testing mode (port 5666, separate database) - --verbose/-v: Enable debug logging (sets AW_DEBUG) - --port: Override the port number The testing flag flows through to aw-server's config and database path, using the same infrastructure that was already in place but hardcoded to false. Port resolution priority: CLI flag > testing default (5666) > config file. Closes #127 * fix: clarify port priority comment to include testing default
1 parent 1ed8f1f commit 0dcdfea

4 files changed

Lines changed: 67 additions & 7 deletions

File tree

src-tauri/Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ crate-type = ["staticlib", "cdylib", "rlib"]
2020
tauri-build = { version = "2.0.5", features = [] }
2121

2222
[dependencies]
23+
clap = { version = "4", features = ["derive"] }
2324
shell-words = "1.1.0"
2425
tauri = { version = "2.2.2", features = ["tray-icon"] }
2526
tauri-plugin-shell = "2.2.0"

src-tauri/src/lib.rs

Lines changed: 40 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,25 @@ mod dirs;
1818
mod logging;
1919
mod manager;
2020

21+
/// CLI arguments passed from main()
22+
#[derive(Debug, Default)]
23+
pub struct CliArgs {
24+
pub testing: bool,
25+
pub verbose: bool,
26+
pub port: Option<u16>,
27+
}
28+
29+
static CLI_ARGS: OnceLock<CliArgs> = OnceLock::new();
30+
31+
/// Set CLI args before calling run(). Must be called at most once.
32+
pub fn set_cli_args(args: CliArgs) {
33+
CLI_ARGS.set(args).expect("CLI args already set");
34+
}
35+
36+
fn get_cli_args() -> &'static CliArgs {
37+
CLI_ARGS.get_or_init(CliArgs::default)
38+
}
39+
2140
use log::{info, trace, warn};
2241
use tauri::{
2342
menu::{Menu, MenuItem},
@@ -402,6 +421,13 @@ pub fn run() {
402421
eprintln!("Failed to rotate log: {}", e);
403422
}
404423

424+
let cli_args = get_cli_args();
425+
426+
// Set verbose env var before logging init so it picks it up
427+
if cli_args.verbose {
428+
std::env::set_var("AW_DEBUG", "1");
429+
}
430+
405431
// Initialize logging
406432
if let Err(e) = logging::setup_logging() {
407433
// Can't use log here since logging isn't initialized yet
@@ -460,11 +486,16 @@ pub fn run() {
460486
}
461487
}
462488

463-
let testing = false;
489+
let testing = cli_args.testing;
464490
let legacy_import = false;
465491

466492
let mut aw_config = aw_server::config::create_config(testing);
467-
aw_config.port = user_config.port;
493+
494+
// Port priority: CLI flag > testing default (5666) > config file
495+
let port = cli_args
496+
.port
497+
.unwrap_or(if testing { 5666 } else { user_config.port });
498+
aw_config.port = port;
468499
let db_path = aw_server::dirs::db_path(testing)
469500
.expect("Failed to get db path")
470501
.to_str()
@@ -494,17 +525,19 @@ pub fn run() {
494525
asset_resolver: aw_server::endpoints::AssetResolver::new(asset_path_opt),
495526
device_id,
496527
};
497-
if !is_port_available(user_config.port).expect("Failed to check port availability")
498-
{
528+
if !is_port_available(port).expect("Failed to check port availability") {
499529
app.dialog()
500-
.message(format!("Port {} is already in use", user_config.port))
530+
.message(format!("Port {} is already in use", port))
501531
.kind(MessageDialogKind::Error)
502532
.title("Error")
503533
.show(|_| {});
504-
panic!("Port {} is already in use", user_config.port);
534+
panic!("Port {} is already in use", port);
535+
}
536+
if testing {
537+
info!("Running in testing mode (port {})", port);
505538
}
506539
tauri::async_runtime::spawn(build_rocket(server_state, aw_config).launch());
507-
let url = format!("http://localhost:{}/", user_config.port)
540+
let url = format!("http://localhost:{}/", port)
508541
.parse()
509542
.expect("Failed to parse localhost url");
510543
// Create main window programmatically to attach initialization script.

src-tauri/src/main.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,31 @@
11
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
22
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
33

4+
use clap::Parser;
5+
6+
/// ActivityWatch UI built with Tauri
7+
#[derive(Parser, Debug)]
8+
#[command(name = "aw-tauri", version, about)]
9+
struct Cli {
10+
/// Run in testing mode (port 5666, separate database)
11+
#[arg(long)]
12+
testing: bool,
13+
14+
/// Enable verbose/debug logging
15+
#[arg(short, long)]
16+
verbose: bool,
17+
18+
/// Override the port number
19+
#[arg(long)]
20+
port: Option<u16>,
21+
}
22+
423
fn main() {
24+
let cli = Cli::parse();
25+
aw_tauri_lib::set_cli_args(aw_tauri_lib::CliArgs {
26+
testing: cli.testing,
27+
verbose: cli.verbose,
28+
port: cli.port,
29+
});
530
aw_tauri_lib::run();
631
}

0 commit comments

Comments
 (0)