Skip to main content

par_term_config/defaults/
misc.rs

1//! Default values that do not belong to a single focused subsystem.
2
3// ── Primitive helpers ──────────────────────────────────────────────────────
4
5/// Serde default returning `false`.
6pub fn bool_false() -> bool {
7    false
8}
9
10/// Serde default returning `true`.
11pub fn bool_true() -> bool {
12    true
13}
14
15/// Serde default returning `0`.
16pub fn zero() -> usize {
17    0
18}
19
20/// Default mDNS service discovery timeout in seconds.
21pub fn mdns_timeout() -> u32 {
22    3
23}
24
25// ── Update ─────────────────────────────────────────────────────────────────
26
27/// Default update check frequency.
28pub fn update_check_frequency() -> crate::types::UpdateCheckFrequency {
29    crate::types::UpdateCheckFrequency::Daily
30}
31
32// ── Keybindings ────────────────────────────────────────────────────────────
33
34pub fn keybindings() -> Vec<crate::types::KeyBinding> {
35    // macOS: Cmd+key is safe because Cmd is separate from Ctrl (terminal control codes).
36    // Windows/Linux: Ctrl+key conflicts with terminal control codes (Ctrl+C=SIGINT, Ctrl+D=EOF, etc.)
37    // so we use Ctrl+Shift+key following standard terminal emulator conventions
38    // (WezTerm, Kitty, Alacritty, GNOME Terminal, Windows Terminal).
39    #[cfg(target_os = "macos")]
40    let bindings = vec![
41        crate::types::KeyBinding {
42            key: "CmdOrCtrl+Shift+B".to_string(),
43            action: "toggle_background_shader".to_string(),
44        },
45        crate::types::KeyBinding {
46            key: "CmdOrCtrl+Shift+U".to_string(),
47            action: "toggle_cursor_shader".to_string(),
48        },
49        crate::types::KeyBinding {
50            key: "CmdOrCtrl+Shift+V".to_string(),
51            action: "paste_special".to_string(),
52        },
53        crate::types::KeyBinding {
54            key: "CmdOrCtrl+Shift+R".to_string(),
55            action: "toggle_session_logging".to_string(),
56        },
57        // Split pane shortcuts (Cmd+D / Cmd+Shift+D matches iTerm2)
58        crate::types::KeyBinding {
59            key: "CmdOrCtrl+D".to_string(),
60            action: "split_horizontal".to_string(),
61        },
62        crate::types::KeyBinding {
63            key: "CmdOrCtrl+Shift+D".to_string(),
64            action: "split_vertical".to_string(),
65        },
66        crate::types::KeyBinding {
67            key: "CmdOrCtrl+Shift+W".to_string(),
68            action: "close_pane".to_string(),
69        },
70        // Pane navigation shortcuts
71        crate::types::KeyBinding {
72            key: "CmdOrCtrl+Alt+Left".to_string(),
73            action: "navigate_pane_left".to_string(),
74        },
75        crate::types::KeyBinding {
76            key: "CmdOrCtrl+Alt+Right".to_string(),
77            action: "navigate_pane_right".to_string(),
78        },
79        crate::types::KeyBinding {
80            key: "CmdOrCtrl+Alt+Up".to_string(),
81            action: "navigate_pane_up".to_string(),
82        },
83        crate::types::KeyBinding {
84            key: "CmdOrCtrl+Alt+Down".to_string(),
85            action: "navigate_pane_down".to_string(),
86        },
87        // Pane resize shortcuts
88        crate::types::KeyBinding {
89            key: "CmdOrCtrl+Alt+Shift+Left".to_string(),
90            action: "resize_pane_left".to_string(),
91        },
92        crate::types::KeyBinding {
93            key: "CmdOrCtrl+Alt+Shift+Right".to_string(),
94            action: "resize_pane_right".to_string(),
95        },
96        crate::types::KeyBinding {
97            key: "CmdOrCtrl+Alt+Shift+Up".to_string(),
98            action: "resize_pane_up".to_string(),
99        },
100        crate::types::KeyBinding {
101            key: "CmdOrCtrl+Alt+Shift+Down".to_string(),
102            action: "resize_pane_down".to_string(),
103        },
104        // Broadcast input mode
105        crate::types::KeyBinding {
106            key: "CmdOrCtrl+Alt+I".to_string(),
107            action: "toggle_broadcast_input".to_string(),
108        },
109        // Throughput mode toggle
110        crate::types::KeyBinding {
111            key: "CmdOrCtrl+Shift+T".to_string(),
112            action: "toggle_throughput_mode".to_string(),
113        },
114        // tmux session picker
115        crate::types::KeyBinding {
116            key: "CmdOrCtrl+Alt+T".to_string(),
117            action: "toggle_tmux_session_picker".to_string(),
118        },
119        // Copy mode (vi-style keyboard-driven selection) - matches iTerm2
120        crate::types::KeyBinding {
121            key: "CmdOrCtrl+Shift+C".to_string(),
122            action: "toggle_copy_mode".to_string(),
123        },
124        // Command history fuzzy search
125        crate::types::KeyBinding {
126            key: "CmdOrCtrl+R".to_string(),
127            action: "toggle_command_history".to_string(),
128        },
129        // Reopen recently closed tab
130        crate::types::KeyBinding {
131            key: "CmdOrCtrl+Z".to_string(),
132            action: "reopen_closed_tab".to_string(),
133        },
134        // SSH Quick Connect
135        crate::types::KeyBinding {
136            key: "CmdOrCtrl+Shift+S".to_string(),
137            action: "ssh_quick_connect".to_string(),
138        },
139        // Duplicate Tab. Cmd+D / Cmd+Shift+D (the natural mnemonic) are the two
140        // split actions and Cmd+Shift+T is throughput mode, so J — free in both
141        // the default keybindings and every hardcoded key layer.
142        crate::types::KeyBinding {
143            key: "CmdOrCtrl+Shift+J".to_string(),
144            action: "duplicate_tab".to_string(),
145        },
146        // Profile drawer. The chord was only ever a hardcoded key layer, so it
147        // was invisible in Settings and could not be rebound; shipping it as a
148        // default makes it a first-class binding. The Profiles menu used to
149        // give this accelerator to `Manage Profiles...`, which meant the native
150        // menu bar consumed it before this registry ever ran.
151        crate::types::KeyBinding {
152            key: "CmdOrCtrl+Shift+P".to_string(),
153            action: "toggle_profile_drawer".to_string(),
154        },
155    ];
156
157    #[cfg(not(target_os = "macos"))]
158    let bindings = vec![
159        crate::types::KeyBinding {
160            key: "Ctrl+Shift+B".to_string(),
161            action: "toggle_background_shader".to_string(),
162        },
163        crate::types::KeyBinding {
164            key: "Ctrl+Shift+U".to_string(),
165            action: "toggle_cursor_shader".to_string(),
166        },
167        // Ctrl+Shift+V is standard paste on Linux terminals, so use Ctrl+Alt+V for paste special
168        crate::types::KeyBinding {
169            key: "Ctrl+Alt+V".to_string(),
170            action: "paste_special".to_string(),
171        },
172        crate::types::KeyBinding {
173            key: "Ctrl+Shift+R".to_string(),
174            action: "toggle_session_logging".to_string(),
175        },
176        // Split pane shortcuts
177        // Ctrl+D is EOF/logout - use Ctrl+Shift+D for horizontal split
178        crate::types::KeyBinding {
179            key: "Ctrl+Shift+D".to_string(),
180            action: "split_horizontal".to_string(),
181        },
182        // Ctrl+Shift+E for vertical split (Tilix/Terminator convention)
183        crate::types::KeyBinding {
184            key: "Ctrl+Shift+E".to_string(),
185            action: "split_vertical".to_string(),
186        },
187        // Ctrl+Shift+W is standard close tab - use Ctrl+Shift+X for close pane
188        crate::types::KeyBinding {
189            key: "Ctrl+Shift+X".to_string(),
190            action: "close_pane".to_string(),
191        },
192        // Pane navigation shortcuts
193        crate::types::KeyBinding {
194            key: "Ctrl+Alt+Left".to_string(),
195            action: "navigate_pane_left".to_string(),
196        },
197        crate::types::KeyBinding {
198            key: "Ctrl+Alt+Right".to_string(),
199            action: "navigate_pane_right".to_string(),
200        },
201        crate::types::KeyBinding {
202            key: "Ctrl+Alt+Up".to_string(),
203            action: "navigate_pane_up".to_string(),
204        },
205        crate::types::KeyBinding {
206            key: "Ctrl+Alt+Down".to_string(),
207            action: "navigate_pane_down".to_string(),
208        },
209        // Pane resize shortcuts
210        crate::types::KeyBinding {
211            key: "Ctrl+Alt+Shift+Left".to_string(),
212            action: "resize_pane_left".to_string(),
213        },
214        crate::types::KeyBinding {
215            key: "Ctrl+Alt+Shift+Right".to_string(),
216            action: "resize_pane_right".to_string(),
217        },
218        crate::types::KeyBinding {
219            key: "Ctrl+Alt+Shift+Up".to_string(),
220            action: "resize_pane_up".to_string(),
221        },
222        crate::types::KeyBinding {
223            key: "Ctrl+Alt+Shift+Down".to_string(),
224            action: "resize_pane_down".to_string(),
225        },
226        // Broadcast input mode
227        crate::types::KeyBinding {
228            key: "Ctrl+Alt+I".to_string(),
229            action: "toggle_broadcast_input".to_string(),
230        },
231        // Ctrl+Shift+T is standard new tab - use Ctrl+Shift+M for throughput mode
232        crate::types::KeyBinding {
233            key: "Ctrl+Shift+M".to_string(),
234            action: "toggle_throughput_mode".to_string(),
235        },
236        // tmux session picker
237        crate::types::KeyBinding {
238            key: "Ctrl+Alt+T".to_string(),
239            action: "toggle_tmux_session_picker".to_string(),
240        },
241        // Copy mode (vi-style keyboard-driven selection)
242        // Ctrl+Shift+C is standard copy on Linux, so use Ctrl+Shift+Space
243        crate::types::KeyBinding {
244            key: "Ctrl+Shift+Space".to_string(),
245            action: "toggle_copy_mode".to_string(),
246        },
247        // Command history fuzzy search
248        // Ctrl+R conflicts with terminal reverse search, so use Ctrl+Shift+R
249        // Note: Ctrl+Shift+R is session logging on Linux; users can reassign
250        crate::types::KeyBinding {
251            key: "Ctrl+Alt+R".to_string(),
252            action: "toggle_command_history".to_string(),
253        },
254        // Reopen recently closed tab
255        crate::types::KeyBinding {
256            key: "Ctrl+Shift+Z".to_string(),
257            action: "reopen_closed_tab".to_string(),
258        },
259        // SSH Quick Connect
260        crate::types::KeyBinding {
261            key: "Ctrl+Shift+S".to_string(),
262            action: "ssh_quick_connect".to_string(),
263        },
264        // Duplicate Tab. Ctrl+Shift+D is the horizontal split here, and the menu
265        // model's `cmd_or_ctrl` is itself Ctrl+Shift off macOS, so every letter
266        // it uses (N, W, Q, T, C, V, A) is spoken for too. J is free on both.
267        crate::types::KeyBinding {
268            key: "Ctrl+Shift+J".to_string(),
269            action: "duplicate_tab".to_string(),
270        },
271        // Profile drawer — see the macOS list above. Ctrl+Shift+P already
272        // reached the drawer here through the hardcoded key layer, because
273        // Linux cannot attach a native menu bar; the menu merely mislabelled it
274        // as `Manage Profiles...`.
275        crate::types::KeyBinding {
276            key: "Ctrl+Shift+P".to_string(),
277            action: "toggle_profile_drawer".to_string(),
278        },
279    ];
280
281    bindings
282}
283
284// ── Command separator ──────────────────────────────────────────────────────
285
286/// Default command separator line thickness in pixels.
287pub fn command_separator_thickness() -> f32 {
288    1.0 // 1 pixel line
289}
290
291/// Default command separator line opacity (0.0–1.0).
292pub fn command_separator_opacity() -> f32 {
293    0.4 // Subtle by default
294}
295
296// ── Cursor shadow / boost ──────────────────────────────────────────────────
297
298/// Default cursor drop shadow pixel offset as `[x, y]`.
299pub fn cursor_shadow_offset() -> [f32; 2] {
300    [2.0, 2.0] // 2 pixels offset in both directions
301}
302
303/// Default cursor drop shadow blur radius in pixels.
304pub fn cursor_shadow_blur() -> f32 {
305    3.0 // 3 pixel blur radius
306}
307
308/// Default cursor brightness boost amount (0.0 = disabled).
309pub fn cursor_boost() -> f32 {
310    0.0 // Disabled by default
311}
312
313// ── Badge ──────────────────────────────────────────────────────────────────
314
315/// Default badge format string.
316pub fn badge_format() -> String {
317    "\\(session.username)@\\(session.hostname)".to_string()
318}
319
320/// Default badge text opacity (0.0–1.0).
321pub fn badge_color_alpha() -> f32 {
322    0.5 // 50% opacity (semi-transparent)
323}
324
325/// Default badge top margin in pixels.
326pub fn badge_top_margin() -> f32 {
327    0.0 // 0 pixels from top
328}
329
330/// Default badge right margin in pixels.
331pub fn badge_right_margin() -> f32 {
332    16.0 // 16 pixels from right
333}
334
335/// Default badge maximum width as a fraction of terminal width (0.0–1.0).
336pub fn badge_max_width() -> f32 {
337    0.5 // 50% of terminal width
338}
339
340/// Default badge maximum height as a fraction of terminal height (0.0–1.0).
341pub fn badge_max_height() -> f32 {
342    0.2 // 20% of terminal height
343}
344
345// ── Progress bar ───────────────────────────────────────────────────────────
346
347/// Default progress bar height in pixels.
348pub fn progress_bar_height() -> f32 {
349    4.0 // Height in pixels
350}
351
352/// Default progress bar opacity (0.0–1.0).
353pub fn progress_bar_opacity() -> f32 {
354    0.8
355}
356
357// ── Unicode ────────────────────────────────────────────────────────────────
358
359/// Default Unicode version for character width calculations.
360pub fn unicode_version() -> crate::types::UnicodeVersion {
361    crate::types::UnicodeVersion::Auto
362}
363
364/// Default treatment of ambiguous-width Unicode characters.
365pub fn ambiguous_width() -> crate::types::AmbiguousWidth {
366    crate::types::AmbiguousWidth::Narrow
367}
368
369/// Default Unicode normalization form applied to terminal input.
370pub fn normalization_form() -> crate::types::NormalizationForm {
371    crate::types::NormalizationForm::NFC
372}
373
374// ── Pane layout ────────────────────────────────────────────────────────────
375
376/// Default split-pane divider visual width in pixels (`None` = use theme default).
377pub fn pane_divider_width() -> Option<f32> {
378    Some(2.0) // 2 pixel divider between panes
379}
380
381/// Default split-pane divider drag hit area width in pixels.
382pub fn pane_divider_hit_width() -> f32 {
383    5.0 // 5 pixel hit area for drag-to-resize (larger than visual for easier grabbing)
384}
385
386/// Default padding in pixels inside each pane (between content and border/divider).
387pub fn pane_padding() -> f32 {
388    1.0 // 1 pixel padding inside panes (space between content and border/divider)
389}
390
391/// Default minimum pane size in terminal cells (applies to both columns and rows).
392pub fn pane_min_size() -> usize {
393    10 // Minimum pane size in cells (columns or rows)
394}
395
396/// Default pane background opacity (1.0 = fully opaque).
397pub fn pane_background_opacity() -> f32 {
398    1.0 // Fully opaque by default
399}
400
401/// Default opacity for inactive (unfocused) panes (0.0–1.0).
402pub fn inactive_pane_opacity() -> f32 {
403    0.7 // 70% opacity for inactive panes
404}
405
406/// Default maximum number of panes allowed per tab.
407pub fn max_panes() -> usize {
408    16 // Maximum panes per tab
409}
410
411/// Default pane title bar height in pixels.
412pub fn pane_title_height() -> f32 {
413    20.0 // 20 pixel title bar height for panes
414}
415
416/// Default focused pane border width in pixels.
417pub fn pane_focus_width() -> f32 {
418    1.0 // 1 pixel border around focused pane
419}
420
421// ── tmux integration ───────────────────────────────────────────────────────
422
423pub fn tmux_path() -> String {
424    // First, try to find tmux in the user's PATH environment variable
425    if let Ok(path_env) = std::env::var("PATH") {
426        let separator = if cfg!(windows) { ';' } else { ':' };
427        let executable = if cfg!(windows) { "tmux.exe" } else { "tmux" };
428
429        for dir in path_env.split(separator) {
430            let candidate = std::path::Path::new(dir).join(executable);
431            if candidate.exists() {
432                return candidate.to_string_lossy().to_string();
433            }
434        }
435    }
436
437    // Fall back to common paths for environments where PATH might be incomplete
438    // (e.g., macOS app bundles launched from Finder)
439    #[cfg(target_os = "macos")]
440    {
441        let macos_paths = [
442            "/opt/homebrew/bin/tmux", // Homebrew on Apple Silicon
443            "/usr/local/bin/tmux",    // Homebrew on Intel / MacPorts
444        ];
445        for path in macos_paths {
446            if std::path::Path::new(path).exists() {
447                return path.to_string();
448            }
449        }
450    }
451
452    #[cfg(target_os = "linux")]
453    {
454        let linux_paths = [
455            "/usr/bin/tmux",       // Most distros
456            "/usr/local/bin/tmux", // Manual install
457            "/snap/bin/tmux",      // Snap package
458        ];
459        for path in linux_paths {
460            if std::path::Path::new(path).exists() {
461                return path.to_string();
462            }
463        }
464    }
465
466    // Final fallback - let the OS try to find it
467    "tmux".to_string()
468}
469
470/// Default tmux session name to connect to (`None` = no default).
471pub fn tmux_default_session() -> Option<String> {
472    None // No default session name
473}
474
475/// Default tmux session to auto-attach on startup (`None` = disabled).
476pub fn tmux_auto_attach_session() -> Option<String> {
477    None // No auto-attach session
478}
479
480/// Default tmux prefix key string (standard Ctrl+B).
481pub fn tmux_prefix_key() -> String {
482    "C-b".to_string() // Standard tmux prefix (Ctrl+B)
483}
484
485/// Default custom action prefix key (empty = disabled).
486pub fn custom_action_prefix_key() -> String {
487    String::new() // Disabled by default
488}
489
490/// Default tmux status bar refresh interval in milliseconds.
491pub fn tmux_status_bar_refresh_ms() -> u64 {
492    1000 // Default: 1 second refresh interval
493}
494
495/// Default tmux status bar left-side format string.
496pub fn tmux_status_bar_left() -> String {
497    "[{session}] {windows}".to_string()
498}
499
500/// Default tmux status bar right-side format string.
501pub fn tmux_status_bar_right() -> String {
502    "{pane} | {time:%H:%M}".to_string()
503}