Skip to main content

es_fluent_cli/commands/
watch.rs

1//! Watch command implementation.
2
3use crate::commands::{WorkspaceArgs, WorkspaceCrates};
4use crate::core::{CliError, FluentParseMode};
5use crate::tui::watch_all;
6use crate::utils::ui;
7use clap::Parser;
8
9/// Arguments for the watch command.
10#[derive(Parser)]
11pub struct WatchArgs {
12    #[command(flatten)]
13    pub workspace: WorkspaceArgs,
14
15    /// Parse mode for FTL generation
16    #[arg(short, long, value_enum, default_value_t = FluentParseMode::default())]
17    pub mode: FluentParseMode,
18}
19
20/// Run the watch command.
21pub fn run_watch(args: WatchArgs) -> Result<(), CliError> {
22    let workspace = WorkspaceCrates::discover(args.workspace)?;
23
24    if !workspace.print_discovery(ui::print_header) {
25        return Ok(());
26    }
27
28    watch_all(&workspace.crates, &workspace.workspace_info, &args.mode).map_err(CliError::from)
29}
30
31#[cfg(test)]
32mod tests {
33    use super::*;
34    use std::fs;
35    use tempfile::tempdir;
36
37    fn create_test_crate_workspace() -> tempfile::TempDir {
38        let temp = tempdir().unwrap();
39
40        fs::create_dir_all(temp.path().join("src")).unwrap();
41        fs::create_dir_all(temp.path().join("i18n/en")).unwrap();
42        fs::write(
43            temp.path().join("Cargo.toml"),
44            r#"[package]
45name = "test-app"
46version = "0.1.0"
47edition = "2024"
48"#,
49        )
50        .unwrap();
51        fs::write(temp.path().join("src/lib.rs"), "pub struct Demo;\n").unwrap();
52        fs::write(
53            temp.path().join("i18n.toml"),
54            "fallback_language = \"en\"\nassets_dir = \"i18n\"\n",
55        )
56        .unwrap();
57
58        temp
59    }
60
61    #[test]
62    fn run_watch_returns_ok_when_package_filter_matches_nothing() {
63        let temp = create_test_crate_workspace();
64
65        let result = run_watch(WatchArgs {
66            workspace: WorkspaceArgs {
67                path: Some(temp.path().to_path_buf()),
68                package: Some("missing-crate".to_string()),
69            },
70            mode: FluentParseMode::default(),
71        });
72
73        assert!(result.is_ok());
74    }
75
76    #[test]
77    fn run_watch_returns_error_for_invalid_path() {
78        let result = run_watch(WatchArgs {
79            workspace: WorkspaceArgs {
80                path: Some(std::path::PathBuf::from("/definitely/missing/path")),
81                package: None,
82            },
83            mode: FluentParseMode::default(),
84        });
85
86        assert!(result.is_err());
87    }
88}