1use serde::{Deserialize, Serialize};
18use std::collections::HashMap;
19
20#[derive(Debug, Serialize, Deserialize, Default, Clone)]
22pub struct Config {
23 #[serde(default)]
24 pub defaults: Defaults,
25
26 #[serde(default)]
27 pub clusters: HashMap<String, Cluster>,
28
29 #[serde(default)]
30 pub interactive: InteractiveConfig,
31}
32
33#[derive(Debug, Serialize, Deserialize, Default, Clone)]
35pub struct Defaults {
36 pub user: Option<String>,
37 pub port: Option<u16>,
38 pub ssh_key: Option<String>,
39 pub parallel: Option<usize>,
40 pub timeout: Option<u64>,
41}
42
43#[derive(Debug, Serialize, Deserialize, Default, Clone)]
45pub struct InteractiveConfig {
46 #[serde(default = "default_interactive_mode")]
47 pub default_mode: InteractiveMode,
48
49 #[serde(default = "default_prompt_format")]
50 pub prompt_format: String,
51
52 #[serde(default)]
53 pub history_file: Option<String>,
54
55 #[serde(default)]
56 pub colors: HashMap<String, String>,
57
58 #[serde(default)]
59 pub keybindings: KeyBindings,
60
61 #[serde(default)]
62 pub broadcast_prefix: Option<String>,
63
64 #[serde(default)]
65 pub node_switch_prefix: Option<String>,
66
67 #[serde(default)]
68 pub show_timestamps: bool,
69
70 #[serde(default)]
71 pub work_dir: Option<String>,
72}
73
74#[derive(Debug, Serialize, Deserialize, Clone)]
76#[serde(rename_all = "snake_case")]
77#[derive(Default)]
78pub enum InteractiveMode {
79 #[default]
80 SingleNode,
81 Multiplex,
82}
83
84#[derive(Debug, Serialize, Deserialize, Default, Clone)]
86pub struct KeyBindings {
87 #[serde(default = "default_switch_node")]
88 pub switch_node: String,
89
90 #[serde(default = "default_broadcast_toggle")]
91 pub broadcast_toggle: String,
92
93 #[serde(default = "default_quit")]
94 pub quit: String,
95
96 #[serde(default)]
97 pub clear_screen: Option<String>,
98}
99
100#[derive(Debug, Serialize, Deserialize, Clone)]
102pub struct Cluster {
103 pub nodes: Vec<NodeConfig>,
104
105 #[serde(flatten)]
106 pub defaults: ClusterDefaults,
107
108 #[serde(default)]
109 pub interactive: Option<InteractiveConfig>,
110}
111
112#[derive(Debug, Serialize, Deserialize, Default, Clone)]
114pub struct ClusterDefaults {
115 pub user: Option<String>,
116 pub port: Option<u16>,
117 pub ssh_key: Option<String>,
118 pub parallel: Option<usize>,
119 pub timeout: Option<u64>,
120}
121
122#[derive(Debug, Serialize, Deserialize, Clone)]
124#[serde(untagged)]
125pub enum NodeConfig {
126 Simple(String),
127 Detailed {
128 host: String,
129 #[serde(default)]
130 port: Option<u16>,
131 #[serde(default)]
132 user: Option<String>,
133 },
134}
135
136#[derive(Debug, Default)]
138pub struct InteractiveConfigUpdate {
139 pub default_mode: Option<InteractiveMode>,
140 pub prompt_format: Option<String>,
141 pub history_file: Option<String>,
142 pub work_dir: Option<String>,
143 pub show_timestamps: Option<bool>,
144 pub colors: Option<HashMap<String, String>>,
145}
146
147pub(super) fn default_interactive_mode() -> InteractiveMode {
149 InteractiveMode::SingleNode
150}
151
152pub(super) fn default_prompt_format() -> String {
153 "[{node}:{user}@{host}:{pwd}]$ ".to_string()
154}
155
156pub(super) fn default_switch_node() -> String {
157 "Ctrl+N".to_string()
158}
159
160pub(super) fn default_broadcast_toggle() -> String {
161 "Ctrl+B".to_string()
162}
163
164pub(super) fn default_quit() -> String {
165 "Ctrl+Q".to_string()
166}