vtcode_config/
status_line.rs1use serde::{Deserialize, Serialize};
2
3#[derive(Debug, Clone, PartialEq, Eq, Deserialize, Serialize)]
4#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
5#[cfg_attr(feature = "schema", schemars(rename_all = "lowercase"))]
6#[serde(rename_all = "lowercase")]
7#[derive(Default)]
8pub enum StatusLineMode {
9 #[default]
11 Auto,
12 Command,
14 Hidden,
16 #[serde(other)]
18 Unknown,
19}
20
21impl std::str::FromStr for StatusLineMode {
22 type Err = String;
23
24 fn from_str(s: &str) -> Result<Self, Self::Err> {
25 match s.trim().to_lowercase().as_str() {
26 "auto" => Ok(StatusLineMode::Auto),
27 "command" => Ok(StatusLineMode::Command),
28 "hidden" => Ok(StatusLineMode::Hidden),
29 _ => Ok(StatusLineMode::Unknown),
30 }
31 }
32}
33
34#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
35#[derive(Debug, Clone, Deserialize, Serialize)]
36pub struct StatusLineConfig {
37 #[serde(default = "default_status_line_mode")]
38 pub mode: StatusLineMode,
39 #[serde(default)]
40 pub command: Option<String>,
41 #[serde(default = "default_status_line_refresh_interval_ms")]
42 pub refresh_interval_ms: u64,
43 #[serde(default = "default_status_line_command_timeout_ms")]
44 pub command_timeout_ms: u64,
45 #[serde(default = "default_status_line_show_clock")]
47 pub show_clock: bool,
48}
49
50impl StatusLineConfig {
51 pub fn effective_mode(&self) -> StatusLineMode {
57 self.mode.clone()
58 }
59}
60
61impl Default for StatusLineConfig {
62 fn default() -> Self {
63 Self {
64 mode: default_status_line_mode(),
65 command: None,
66 refresh_interval_ms: default_status_line_refresh_interval_ms(),
67 command_timeout_ms: default_status_line_command_timeout_ms(),
68 show_clock: default_status_line_show_clock(),
69 }
70 }
71}
72
73const DEFAULT_STATUS_LINE_SHOW_CLOCK: bool = true;
75
76fn default_status_line_show_clock() -> bool {
77 DEFAULT_STATUS_LINE_SHOW_CLOCK
78}
79
80const DEFAULT_STATUS_LINE_MODE: StatusLineMode = StatusLineMode::Auto;
84
85fn default_status_line_mode() -> StatusLineMode {
86 DEFAULT_STATUS_LINE_MODE
87}
88
89fn default_status_line_refresh_interval_ms() -> u64 {
90 crate::constants::ui::STATUS_LINE_REFRESH_INTERVAL_MS
91}
92
93fn default_status_line_command_timeout_ms() -> u64 {
94 crate::constants::ui::STATUS_LINE_COMMAND_TIMEOUT_MS
95}
96
97#[cfg(test)]
98mod tests {
99 use super::{StatusLineConfig, StatusLineMode};
100
101 #[derive(Debug, serde::Deserialize)]
102 struct Wrapper {
103 mode: StatusLineMode,
104 }
105
106 #[test]
107 fn deserializes_lowercase_status_line_mode() {
108 for (input, expected) in [
109 ("\"auto\"", StatusLineMode::Auto),
110 ("\"command\"", StatusLineMode::Command),
111 ("\"hidden\"", StatusLineMode::Hidden),
112 ] {
113 let parsed: Wrapper =
114 toml::from_str(&format!("mode = {input}")).expect("lowercase status line mode must parse");
115 assert_eq!(parsed.mode, expected, "input {input}");
116 }
117 }
118
119 #[test]
120 fn serializes_lowercase_status_line_mode() {
121 for (mode, expected) in [
122 (StatusLineMode::Auto, "\"auto\""),
123 (StatusLineMode::Command, "\"command\""),
124 (StatusLineMode::Hidden, "\"hidden\""),
125 ] {
126 let serialized = serde_json::to_string(&mode).expect("serialize");
127 assert_eq!(serialized, expected);
128 }
129 }
130
131 #[test]
132 fn show_clock_defaults_to_true() {
133 let config = StatusLineConfig::default();
134 assert!(config.show_clock);
135
136 let parsed: StatusLineConfig = toml::from_str("").expect("empty config must parse with defaults");
137 assert!(parsed.show_clock);
138 }
139
140 #[test]
141 fn show_clock_deserializes_when_explicit() {
142 let parsed: StatusLineConfig = toml::from_str("show_clock = false").expect("show_clock = false must parse");
143 assert!(!parsed.show_clock);
144
145 let parsed: StatusLineConfig = toml::from_str("show_clock = true").expect("show_clock = true must parse");
146 assert!(parsed.show_clock);
147 }
148}