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")]
50 pub show_clock: bool,
51}
52
53impl StatusLineConfig {
54 pub fn effective_mode(&self) -> StatusLineMode {
60 self.mode.clone()
61 }
62}
63
64impl Default for StatusLineConfig {
65 fn default() -> Self {
66 Self {
67 mode: default_status_line_mode(),
68 command: None,
69 refresh_interval_ms: default_status_line_refresh_interval_ms(),
70 command_timeout_ms: default_status_line_command_timeout_ms(),
71 show_clock: default_status_line_show_clock(),
72 }
73 }
74}
75
76const DEFAULT_STATUS_LINE_SHOW_CLOCK: bool = false;
78
79fn default_status_line_show_clock() -> bool {
80 DEFAULT_STATUS_LINE_SHOW_CLOCK
81}
82
83const DEFAULT_STATUS_LINE_MODE: StatusLineMode = StatusLineMode::Auto;
87
88fn default_status_line_mode() -> StatusLineMode {
89 DEFAULT_STATUS_LINE_MODE
90}
91
92fn default_status_line_refresh_interval_ms() -> u64 {
93 crate::constants::ui::STATUS_LINE_REFRESH_INTERVAL_MS
94}
95
96fn default_status_line_command_timeout_ms() -> u64 {
97 crate::constants::ui::STATUS_LINE_COMMAND_TIMEOUT_MS
98}
99
100#[cfg(test)]
101mod tests {
102 use super::{StatusLineConfig, StatusLineMode};
103
104 #[derive(Debug, serde::Deserialize)]
105 struct Wrapper {
106 mode: StatusLineMode,
107 }
108
109 #[test]
110 fn deserializes_lowercase_status_line_mode() {
111 for (input, expected) in [
112 ("\"auto\"", StatusLineMode::Auto),
113 ("\"command\"", StatusLineMode::Command),
114 ("\"hidden\"", StatusLineMode::Hidden),
115 ] {
116 let parsed: Wrapper =
117 toml::from_str(&format!("mode = {input}")).expect("lowercase status line mode must parse");
118 assert_eq!(parsed.mode, expected, "input {input}");
119 }
120 }
121
122 #[test]
123 fn serializes_lowercase_status_line_mode() {
124 for (mode, expected) in [
125 (StatusLineMode::Auto, "\"auto\""),
126 (StatusLineMode::Command, "\"command\""),
127 (StatusLineMode::Hidden, "\"hidden\""),
128 ] {
129 let serialized = serde_json::to_string(&mode).expect("serialize");
130 assert_eq!(serialized, expected);
131 }
132 }
133
134 #[test]
135 fn show_clock_defaults_to_false() {
136 let config = StatusLineConfig::default();
137 assert!(!config.show_clock);
138
139 let parsed: StatusLineConfig = toml::from_str("").expect("empty config must parse with defaults");
140 assert!(!parsed.show_clock);
141 }
142
143 #[test]
144 fn show_clock_deserializes_when_explicit() {
145 let parsed: StatusLineConfig = toml::from_str("show_clock = false").expect("show_clock = false must parse");
146 assert!(!parsed.show_clock);
147
148 let parsed: StatusLineConfig = toml::from_str("show_clock = true").expect("show_clock = true must parse");
149 assert!(parsed.show_clock);
150 }
151}