Skip to main content

tty_web/
config.rs

1//! CLI configuration parsed from flags and environment variables.
2
3use std::net::IpAddr;
4use std::path::PathBuf;
5
6use clap::{Parser, ValueEnum};
7
8/// Log output format.
9#[derive(ValueEnum, Debug, Clone, Copy, PartialEq, Eq)]
10pub enum LogFormat {
11    /// Human-readable text (default)
12    Text,
13    /// Structured JSON, one object per line
14    Json,
15}
16
17/// Application configuration.
18///
19/// Every field can be set via a CLI flag (`--address`) or an environment
20/// variable (`TTY_WEB_ADDRESS`). Defaults are suitable for local development.
21#[derive(Parser, Debug, Clone)]
22#[command(name = "tty-web", about = "Web-based terminal emulator")]
23pub struct Config {
24    /// Address to bind to
25    #[arg(long, default_value = "127.0.0.1", env = "TTY_WEB_ADDRESS")]
26    pub address: IpAddr,
27
28    /// Port to listen on
29    #[arg(long, default_value_t = 9090, env = "TTY_WEB_PORT")]
30    pub port: u16,
31
32    /// Shell to execute
33    #[arg(long, default_value = "/bin/bash", env = "TTY_WEB_SHELL")]
34    pub shell: String,
35
36    /// Log level (trace, debug, info, warn, error)
37    #[arg(long, default_value = "info", env = "TTY_WEB_LOG_LEVEL")]
38    pub log_level: String,
39
40    /// Log output format
41    #[arg(long, default_value = "text", env = "TTY_WEB_LOG_FORMAT")]
42    pub log_format: LogFormat,
43
44    /// Working directory for new shell sessions
45    #[arg(long, env = "TTY_WEB_PWD")]
46    pub pwd: Option<PathBuf>,
47
48    /// Scrollback buffer size in KiB (default: 256)
49    #[arg(long, default_value_t = 256, env = "TTY_WEB_SCROLLBACK_LIMIT")]
50    pub scrollback_limit: usize,
51
52    /// Session orphan timeout in seconds — remove session after this long with no clients
53    #[arg(long, default_value_t = 60, env = "TTY_WEB_ORPHAN_TIMEOUT")]
54    pub orphan_timeout: u64,
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn test_default_values() {
63        let config = Config::parse_from(["tty-web"]);
64        assert_eq!(config.address, "127.0.0.1".parse::<IpAddr>().unwrap());
65        assert_eq!(config.port, 9090);
66        assert_eq!(config.shell, "/bin/bash");
67        assert_eq!(config.log_level, "info");
68        assert_eq!(config.log_format, LogFormat::Text);
69        assert_eq!(config.pwd, None);
70        assert_eq!(config.scrollback_limit, 256);
71        assert_eq!(config.orphan_timeout, 60);
72    }
73
74    #[test]
75    fn test_custom_values() {
76        let config = Config::parse_from([
77            "tty-web",
78            "--port",
79            "8080",
80            "--shell",
81            "/bin/sh",
82            "--address",
83            "0.0.0.0",
84            "--log-level",
85            "debug",
86            "--log-format",
87            "json",
88        ]);
89        assert_eq!(config.address, "0.0.0.0".parse::<IpAddr>().unwrap());
90        assert_eq!(config.port, 8080);
91        assert_eq!(config.shell, "/bin/sh");
92        assert_eq!(config.log_level, "debug");
93        assert_eq!(config.log_format, LogFormat::Json);
94    }
95
96    #[test]
97    fn test_pwd_flag() {
98        let config = Config::parse_from(["tty-web", "--pwd", "/tmp"]);
99        assert_eq!(config.pwd, Some(PathBuf::from("/tmp")));
100    }
101}