1use serde::{Deserialize, Serialize};
4use std::path::PathBuf;
5
6#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
14#[serde(rename_all = "lowercase")]
15#[allow(dead_code)]
16pub enum KeyModifier {
17 Ctrl,
19 Alt,
21 Shift,
23 CmdOrCtrl,
25 Super,
27}
28
29#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
31pub struct KeyBinding {
32 pub key: String,
34 pub action: String,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Default)]
40#[serde(rename_all = "lowercase")]
41pub enum VsyncMode {
42 Immediate,
44 Mailbox,
46 #[default]
48 Fifo,
49}
50
51impl VsyncMode {
52 #[cfg(feature = "wgpu-types")]
54 pub fn to_present_mode(self) -> wgpu::PresentMode {
55 match self {
56 VsyncMode::Immediate => wgpu::PresentMode::Immediate,
57 VsyncMode::Mailbox => wgpu::PresentMode::Mailbox,
58 VsyncMode::Fifo => wgpu::PresentMode::Fifo,
59 }
60 }
61}
62
63#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Default)]
68#[serde(rename_all = "snake_case")]
69pub enum PowerPreference {
70 #[default]
72 None,
73 LowPower,
75 HighPerformance,
77}
78
79impl PowerPreference {
80 #[cfg(feature = "wgpu-types")]
82 pub fn to_wgpu(self) -> wgpu::PowerPreference {
83 match self {
84 PowerPreference::None => wgpu::PowerPreference::None,
85 PowerPreference::LowPower => wgpu::PowerPreference::LowPower,
86 PowerPreference::HighPerformance => wgpu::PowerPreference::HighPerformance,
87 }
88 }
89
90 pub fn display_name(&self) -> &'static str {
92 match self {
93 PowerPreference::None => "None (System Default)",
94 PowerPreference::LowPower => "Low Power (Integrated GPU)",
95 PowerPreference::HighPerformance => "High Performance (Discrete GPU)",
96 }
97 }
98
99 pub fn all() -> &'static [PowerPreference] {
101 &[
102 PowerPreference::None,
103 PowerPreference::LowPower,
104 PowerPreference::HighPerformance,
105 ]
106 }
107}
108
109#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
111#[serde(rename_all = "lowercase")]
112pub enum CursorStyle {
113 #[default]
115 Block,
116 Beam,
118 Underline,
120}
121
122#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
124#[serde(rename_all = "lowercase")]
125pub enum UnfocusedCursorStyle {
126 #[default]
128 Hollow,
129 Same,
131 Hidden,
133}
134
135#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
139#[serde(rename_all = "lowercase")]
140pub enum ImageScalingMode {
141 Nearest,
143 #[default]
145 Linear,
146}
147
148impl ImageScalingMode {
149 pub fn display_name(&self) -> &'static str {
151 match self {
152 ImageScalingMode::Nearest => "Nearest (Sharp)",
153 ImageScalingMode::Linear => "Linear (Smooth)",
154 }
155 }
156
157 pub fn all() -> &'static [ImageScalingMode] {
159 &[ImageScalingMode::Nearest, ImageScalingMode::Linear]
160 }
161
162 #[cfg(feature = "wgpu-types")]
164 pub fn to_filter_mode(self) -> wgpu::FilterMode {
165 match self {
166 ImageScalingMode::Nearest => wgpu::FilterMode::Nearest,
167 ImageScalingMode::Linear => wgpu::FilterMode::Linear,
168 }
169 }
170}
171
172#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
174#[serde(rename_all = "lowercase")]
175pub enum BackgroundImageMode {
176 Fit,
178 Fill,
180 #[default]
182 Stretch,
183 Tile,
185 Center,
187}
188
189#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
191#[serde(rename_all = "snake_case")]
192pub enum DownloadSaveLocation {
193 #[default]
195 Downloads,
196 LastUsed,
198 Cwd,
200 Custom(String),
202}
203
204impl DownloadSaveLocation {
205 pub fn variants() -> &'static [DownloadSaveLocation] {
207 &[
208 DownloadSaveLocation::Downloads,
209 DownloadSaveLocation::LastUsed,
210 DownloadSaveLocation::Cwd,
211 ]
212 }
213
214 pub fn display_name(&self) -> &str {
216 match self {
217 DownloadSaveLocation::Downloads => "Downloads folder",
218 DownloadSaveLocation::LastUsed => "Last used directory",
219 DownloadSaveLocation::Cwd => "Current working directory",
220 DownloadSaveLocation::Custom(_) => "Custom directory",
221 }
222 }
223}
224
225#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
227#[serde(rename_all = "lowercase")]
228pub enum BackgroundMode {
229 #[default]
231 Default,
232 Color,
234 Image,
236}
237
238#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
240pub struct PaneBackgroundConfig {
241 pub index: usize,
243 pub image: String,
245 #[serde(default)]
247 pub mode: BackgroundImageMode,
248 #[serde(default = "crate::defaults::background_image_opacity")]
250 pub opacity: f32,
251}
252
253#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
258#[serde(rename_all = "snake_case")]
259pub enum TabStyle {
260 #[default]
262 Dark,
263 Light,
265 Compact,
267 Minimal,
269 HighContrast,
271 Automatic,
273}
274
275impl TabStyle {
276 pub fn display_name(&self) -> &'static str {
278 match self {
279 TabStyle::Dark => "Dark",
280 TabStyle::Light => "Light",
281 TabStyle::Compact => "Compact",
282 TabStyle::Minimal => "Minimal",
283 TabStyle::HighContrast => "High Contrast",
284 TabStyle::Automatic => "Automatic",
285 }
286 }
287
288 pub fn all() -> &'static [TabStyle] {
290 &[
291 TabStyle::Dark,
292 TabStyle::Light,
293 TabStyle::Compact,
294 TabStyle::Minimal,
295 TabStyle::HighContrast,
296 TabStyle::Automatic,
297 ]
298 }
299
300 pub fn all_concrete() -> &'static [TabStyle] {
302 &[
303 TabStyle::Dark,
304 TabStyle::Light,
305 TabStyle::Compact,
306 TabStyle::Minimal,
307 TabStyle::HighContrast,
308 ]
309 }
310}
311
312#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
314#[serde(rename_all = "snake_case")]
315pub enum TabBarPosition {
316 #[default]
318 Top,
319 Bottom,
321 Left,
323}
324
325impl TabBarPosition {
326 pub fn display_name(&self) -> &'static str {
328 match self {
329 TabBarPosition::Top => "Top",
330 TabBarPosition::Bottom => "Bottom",
331 TabBarPosition::Left => "Left",
332 }
333 }
334
335 pub fn all() -> &'static [TabBarPosition] {
337 &[
338 TabBarPosition::Top,
339 TabBarPosition::Bottom,
340 TabBarPosition::Left,
341 ]
342 }
343
344 pub fn is_horizontal(&self) -> bool {
346 matches!(self, TabBarPosition::Top | TabBarPosition::Bottom)
347 }
348}
349
350#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
352#[serde(rename_all = "snake_case")]
353pub enum TabBarMode {
354 Always,
356 #[default]
358 WhenMultiple,
359 Never,
361}
362
363#[derive(Debug, Clone, Copy, PartialEq, Eq, Deserialize, Serialize, Default)]
365#[serde(rename_all = "lowercase")]
366pub enum StatusBarPosition {
367 Top,
369 #[default]
371 Bottom,
372}
373
374#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
376#[serde(rename_all = "snake_case")]
377pub enum WindowType {
378 #[default]
380 Normal,
381 Fullscreen,
383 EdgeTop,
386 EdgeBottom,
388 EdgeLeft,
390 EdgeRight,
392}
393
394impl WindowType {
395 pub fn display_name(&self) -> &'static str {
397 match self {
398 WindowType::Normal => "Normal",
399 WindowType::Fullscreen => "Fullscreen",
400 WindowType::EdgeTop => "Edge (Top)",
401 WindowType::EdgeBottom => "Edge (Bottom)",
402 WindowType::EdgeLeft => "Edge (Left)",
403 WindowType::EdgeRight => "Edge (Right)",
404 }
405 }
406
407 pub fn all() -> &'static [WindowType] {
409 &[
410 WindowType::Normal,
411 WindowType::Fullscreen,
412 WindowType::EdgeTop,
413 WindowType::EdgeBottom,
414 WindowType::EdgeLeft,
415 WindowType::EdgeRight,
416 ]
417 }
418
419 pub fn is_edge(&self) -> bool {
421 matches!(
422 self,
423 WindowType::EdgeTop
424 | WindowType::EdgeBottom
425 | WindowType::EdgeLeft
426 | WindowType::EdgeRight
427 )
428 }
429}
430
431#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
435#[serde(rename_all = "snake_case")]
436pub enum DroppedFileQuoteStyle {
437 #[default]
440 SingleQuotes,
441 DoubleQuotes,
444 Backslash,
447 None,
449}
450
451impl DroppedFileQuoteStyle {
452 pub fn display_name(&self) -> &'static str {
454 match self {
455 DroppedFileQuoteStyle::SingleQuotes => "Single quotes ('...')",
456 DroppedFileQuoteStyle::DoubleQuotes => "Double quotes (\"...\")",
457 DroppedFileQuoteStyle::Backslash => "Backslash escaping (\\)",
458 DroppedFileQuoteStyle::None => "None (raw path)",
459 }
460 }
461
462 pub fn all() -> &'static [DroppedFileQuoteStyle] {
464 &[
465 DroppedFileQuoteStyle::SingleQuotes,
466 DroppedFileQuoteStyle::DoubleQuotes,
467 DroppedFileQuoteStyle::Backslash,
468 DroppedFileQuoteStyle::None,
469 ]
470 }
471}
472
473#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
479#[serde(rename_all = "lowercase")]
480pub enum OptionKeyMode {
481 Normal,
484 Meta,
487 #[default]
491 Esc,
492}
493
494#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
503#[serde(rename_all = "lowercase")]
504pub enum ModifierTarget {
505 #[default]
507 None,
508 Ctrl,
510 Alt,
512 Shift,
514 Super,
516}
517
518impl ModifierTarget {
519 pub fn display_name(&self) -> &'static str {
521 match self {
522 ModifierTarget::None => "None (disabled)",
523 ModifierTarget::Ctrl => "Ctrl",
524 ModifierTarget::Alt => "Alt/Option",
525 ModifierTarget::Shift => "Shift",
526 ModifierTarget::Super => "Super/Cmd",
527 }
528 }
529
530 pub fn all() -> &'static [ModifierTarget] {
532 &[
533 ModifierTarget::None,
534 ModifierTarget::Ctrl,
535 ModifierTarget::Alt,
536 ModifierTarget::Shift,
537 ModifierTarget::Super,
538 ]
539 }
540}
541
542#[derive(Debug, Clone, Copy, PartialEq, Eq, Default, Serialize, Deserialize)]
550pub struct ModifierRemapping {
551 #[serde(default)]
553 pub left_ctrl: ModifierTarget,
554 #[serde(default)]
556 pub right_ctrl: ModifierTarget,
557 #[serde(default)]
559 pub left_alt: ModifierTarget,
560 #[serde(default)]
562 pub right_alt: ModifierTarget,
563 #[serde(default)]
565 pub left_super: ModifierTarget,
566 #[serde(default)]
568 pub right_super: ModifierTarget,
569}
570
571#[derive(Debug, Clone, Serialize, Deserialize)]
573pub struct FontRange {
574 pub start: u32,
576 pub end: u32,
578 pub font_family: String,
580}
581
582#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
587#[serde(rename_all = "snake_case")]
588pub enum ThinStrokesMode {
589 Never,
591 #[default]
593 RetinaOnly,
594 DarkBackgroundsOnly,
596 RetinaDarkBackgroundsOnly,
598 Always,
600}
601
602#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
607#[serde(rename_all = "snake_case")]
608pub enum ShaderInstallPrompt {
609 #[default]
611 Ask,
612 Never,
614 Installed,
616}
617
618#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
620#[serde(rename_all = "snake_case")]
621pub enum InstallPromptState {
622 #[default]
624 Ask,
625 Never,
627 Installed,
629}
630
631impl InstallPromptState {
632 pub fn display_name(&self) -> &'static str {
634 match self {
635 Self::Ask => "Ask",
636 Self::Never => "Never",
637 Self::Installed => "Installed",
638 }
639 }
640}
641
642#[derive(Debug, Clone, Default, Serialize, Deserialize)]
644pub struct IntegrationVersions {
645 pub shaders_installed_version: Option<String>,
647 pub shaders_prompted_version: Option<String>,
649 pub shell_integration_installed_version: Option<String>,
651 pub shell_integration_prompted_version: Option<String>,
653}
654
655#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
659#[serde(rename_all = "snake_case")]
660pub enum StartupDirectoryMode {
661 #[default]
663 Home,
664 Previous,
666 Custom,
668}
669
670impl StartupDirectoryMode {
671 pub fn display_name(&self) -> &'static str {
673 match self {
674 Self::Home => "Home Directory",
675 Self::Previous => "Previous Session",
676 Self::Custom => "Custom Directory",
677 }
678 }
679
680 pub fn all() -> &'static [StartupDirectoryMode] {
682 &[
683 StartupDirectoryMode::Home,
684 StartupDirectoryMode::Previous,
685 StartupDirectoryMode::Custom,
686 ]
687 }
688}
689
690#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
694#[serde(rename_all = "snake_case")]
695pub enum ShellExitAction {
696 #[default]
698 Close,
699 Keep,
701 RestartImmediately,
703 RestartWithPrompt,
705 RestartAfterDelay,
707}
708
709impl ShellExitAction {
710 pub fn display_name(&self) -> &'static str {
712 match self {
713 Self::Close => "Close tab/pane",
714 Self::Keep => "Keep open",
715 Self::RestartImmediately => "Restart immediately",
716 Self::RestartWithPrompt => "Restart with prompt",
717 Self::RestartAfterDelay => "Restart after 1s delay",
718 }
719 }
720
721 pub fn all() -> &'static [ShellExitAction] {
723 &[
724 ShellExitAction::Close,
725 ShellExitAction::Keep,
726 ShellExitAction::RestartImmediately,
727 ShellExitAction::RestartWithPrompt,
728 ShellExitAction::RestartAfterDelay,
729 ]
730 }
731
732 pub fn is_restart(&self) -> bool {
734 matches!(
735 self,
736 Self::RestartImmediately | Self::RestartWithPrompt | Self::RestartAfterDelay
737 )
738 }
739}
740
741#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
743#[serde(rename_all = "lowercase")]
744pub enum ShellType {
745 Bash,
746 Zsh,
747 Fish,
748 #[default]
749 Unknown,
750}
751
752impl ShellType {
753 pub fn detect() -> Self {
755 if let Ok(shell) = std::env::var("SHELL") {
756 if shell.contains("zsh") {
757 Self::Zsh
758 } else if shell.contains("bash") {
759 Self::Bash
760 } else if shell.contains("fish") {
761 Self::Fish
762 } else {
763 Self::Unknown
764 }
765 } else {
766 Self::Unknown
767 }
768 }
769
770 pub fn display_name(&self) -> &'static str {
772 match self {
773 Self::Bash => "Bash",
774 Self::Zsh => "Zsh",
775 Self::Fish => "Fish",
776 Self::Unknown => "Unknown",
777 }
778 }
779
780 pub fn extension(&self) -> &'static str {
782 match self {
783 Self::Bash => "bash",
784 Self::Zsh => "zsh",
785 Self::Fish => "fish",
786 Self::Unknown => "sh",
787 }
788 }
789}
790
791#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
795#[serde(rename_all = "snake_case")]
796pub enum UpdateCheckFrequency {
797 Never,
799 #[default]
801 Daily,
802 Weekly,
804 Monthly,
806}
807
808impl UpdateCheckFrequency {
809 pub fn as_seconds(&self) -> Option<u64> {
811 match self {
812 UpdateCheckFrequency::Never => None,
813 UpdateCheckFrequency::Daily => Some(24 * 60 * 60), UpdateCheckFrequency::Weekly => Some(7 * 24 * 60 * 60), UpdateCheckFrequency::Monthly => Some(30 * 24 * 60 * 60), }
817 }
818
819 pub fn display_name(&self) -> &'static str {
821 match self {
822 UpdateCheckFrequency::Never => "Never",
823 UpdateCheckFrequency::Daily => "Daily",
824 UpdateCheckFrequency::Weekly => "Weekly",
825 UpdateCheckFrequency::Monthly => "Monthly",
826 }
827 }
828}
829
830#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
838#[serde(rename_all = "lowercase")]
839pub enum SessionLogFormat {
840 Plain,
842 Html,
844 #[default]
846 Asciicast,
847}
848
849impl SessionLogFormat {
850 pub fn display_name(&self) -> &'static str {
852 match self {
853 SessionLogFormat::Plain => "Plain Text",
854 SessionLogFormat::Html => "HTML",
855 SessionLogFormat::Asciicast => "Asciicast (asciinema)",
856 }
857 }
858
859 pub fn all() -> &'static [SessionLogFormat] {
861 &[
862 SessionLogFormat::Plain,
863 SessionLogFormat::Html,
864 SessionLogFormat::Asciicast,
865 ]
866 }
867
868 pub fn extension(&self) -> &'static str {
870 match self {
871 SessionLogFormat::Plain => "txt",
872 SessionLogFormat::Html => "html",
873 SessionLogFormat::Asciicast => "cast",
874 }
875 }
876}
877
878#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
883#[serde(rename_all = "lowercase")]
884pub enum LogLevel {
885 #[default]
887 Off,
888 Error,
890 Warn,
892 Info,
894 Debug,
896 Trace,
898}
899
900impl LogLevel {
901 pub fn display_name(&self) -> &'static str {
903 match self {
904 LogLevel::Off => "Off",
905 LogLevel::Error => "Error",
906 LogLevel::Warn => "Warn",
907 LogLevel::Info => "Info",
908 LogLevel::Debug => "Debug",
909 LogLevel::Trace => "Trace",
910 }
911 }
912
913 pub fn all() -> &'static [LogLevel] {
915 &[
916 LogLevel::Off,
917 LogLevel::Error,
918 LogLevel::Warn,
919 LogLevel::Info,
920 LogLevel::Debug,
921 LogLevel::Trace,
922 ]
923 }
924
925 pub fn to_level_filter(self) -> log::LevelFilter {
927 match self {
928 LogLevel::Off => log::LevelFilter::Off,
929 LogLevel::Error => log::LevelFilter::Error,
930 LogLevel::Warn => log::LevelFilter::Warn,
931 LogLevel::Info => log::LevelFilter::Info,
932 LogLevel::Debug => log::LevelFilter::Debug,
933 LogLevel::Trace => log::LevelFilter::Trace,
934 }
935 }
936}
937
938#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
942#[serde(rename_all = "snake_case")]
943pub enum SemanticHistoryEditorMode {
944 Custom,
946 #[default]
948 EnvironmentVariable,
949 SystemDefault,
951}
952
953impl SemanticHistoryEditorMode {
954 pub fn display_name(&self) -> &'static str {
956 match self {
957 SemanticHistoryEditorMode::Custom => "Custom Editor",
958 SemanticHistoryEditorMode::EnvironmentVariable => "Environment Variable ($EDITOR)",
959 SemanticHistoryEditorMode::SystemDefault => "System Default",
960 }
961 }
962
963 pub fn all() -> &'static [SemanticHistoryEditorMode] {
965 &[
966 SemanticHistoryEditorMode::Custom,
967 SemanticHistoryEditorMode::EnvironmentVariable,
968 SemanticHistoryEditorMode::SystemDefault,
969 ]
970 }
971}
972
973#[derive(Debug, Clone, Default, Serialize, Deserialize)]
981pub struct ShaderMetadata {
982 pub name: Option<String>,
984 pub author: Option<String>,
986 pub description: Option<String>,
988 pub version: Option<String>,
990 #[serde(default)]
992 pub defaults: ShaderConfig,
993}
994
995#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)]
1000pub struct ShaderConfig {
1001 pub animation_speed: Option<f32>,
1003 pub brightness: Option<f32>,
1005 pub text_opacity: Option<f32>,
1007 pub full_content: Option<bool>,
1009 pub channel0: Option<String>,
1011 pub channel1: Option<String>,
1013 pub channel2: Option<String>,
1015 pub channel3: Option<String>,
1017 pub cubemap: Option<String>,
1019 pub cubemap_enabled: Option<bool>,
1021 pub use_background_as_channel0: Option<bool>,
1023}
1024
1025#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
1029pub struct CursorShaderConfig {
1030 #[serde(flatten)]
1032 pub base: ShaderConfig,
1033 pub hides_cursor: Option<bool>,
1035 pub disable_in_alt_screen: Option<bool>,
1037 pub glow_radius: Option<f32>,
1039 pub glow_intensity: Option<f32>,
1041 pub trail_duration: Option<f32>,
1043 pub cursor_color: Option<[u8; 3]>,
1045}
1046
1047#[derive(Debug, Clone, Default, Serialize, Deserialize)]
1052pub struct CursorShaderMetadata {
1053 pub name: Option<String>,
1055 pub author: Option<String>,
1057 pub description: Option<String>,
1059 pub version: Option<String>,
1061 #[serde(default)]
1063 pub defaults: CursorShaderConfig,
1064}
1065
1066#[derive(Debug, Clone)]
1070#[allow(dead_code)]
1071pub struct ResolvedShaderConfig {
1072 pub animation_speed: f32,
1074 pub brightness: f32,
1076 pub text_opacity: f32,
1078 pub full_content: bool,
1080 pub channel0: Option<PathBuf>,
1082 pub channel1: Option<PathBuf>,
1084 pub channel2: Option<PathBuf>,
1086 pub channel3: Option<PathBuf>,
1088 pub cubemap: Option<PathBuf>,
1090 pub cubemap_enabled: bool,
1092 pub use_background_as_channel0: bool,
1094}
1095
1096impl Default for ResolvedShaderConfig {
1097 fn default() -> Self {
1098 Self {
1099 animation_speed: 1.0,
1100 brightness: 1.0,
1101 text_opacity: 1.0,
1102 full_content: false,
1103 channel0: None,
1104 channel1: None,
1105 channel2: None,
1106 channel3: None,
1107 cubemap: None,
1108 cubemap_enabled: true,
1109 use_background_as_channel0: false,
1110 }
1111 }
1112}
1113
1114#[derive(Debug, Clone)]
1116#[allow(dead_code)]
1117pub struct ResolvedCursorShaderConfig {
1118 pub base: ResolvedShaderConfig,
1120 pub hides_cursor: bool,
1122 pub disable_in_alt_screen: bool,
1124 pub glow_radius: f32,
1126 pub glow_intensity: f32,
1128 pub trail_duration: f32,
1130 pub cursor_color: [u8; 3],
1132}
1133
1134impl Default for ResolvedCursorShaderConfig {
1135 fn default() -> Self {
1136 Self {
1137 base: ResolvedShaderConfig::default(),
1138 hides_cursor: false,
1139 disable_in_alt_screen: true,
1140 glow_radius: 80.0,
1141 glow_intensity: 0.3,
1142 trail_duration: 0.5,
1143 cursor_color: [255, 255, 255],
1144 }
1145 }
1146}
1147
1148#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
1154#[serde(rename_all = "lowercase")]
1155pub enum ProgressBarStyle {
1156 #[default]
1158 Bar,
1159 BarWithText,
1161}
1162
1163impl ProgressBarStyle {
1164 pub fn display_name(&self) -> &'static str {
1166 match self {
1167 ProgressBarStyle::Bar => "Bar",
1168 ProgressBarStyle::BarWithText => "Bar with Text",
1169 }
1170 }
1171
1172 pub fn all() -> &'static [ProgressBarStyle] {
1174 &[ProgressBarStyle::Bar, ProgressBarStyle::BarWithText]
1175 }
1176}
1177
1178#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
1180#[serde(rename_all = "lowercase")]
1181pub enum ProgressBarPosition {
1182 #[default]
1184 Top,
1185 Bottom,
1187}
1188
1189impl ProgressBarPosition {
1190 pub fn display_name(&self) -> &'static str {
1192 match self {
1193 ProgressBarPosition::Bottom => "Bottom",
1194 ProgressBarPosition::Top => "Top",
1195 }
1196 }
1197
1198 pub fn all() -> &'static [ProgressBarPosition] {
1200 &[ProgressBarPosition::Top, ProgressBarPosition::Bottom]
1201 }
1202}
1203
1204#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
1213#[serde(rename_all = "snake_case")]
1214pub enum SmartSelectionPrecision {
1215 VeryLow,
1217 Low,
1219 #[default]
1221 Normal,
1222 High,
1224 VeryHigh,
1226}
1227
1228impl SmartSelectionPrecision {
1229 pub fn value(&self) -> f64 {
1231 match self {
1232 SmartSelectionPrecision::VeryLow => 0.00001,
1233 SmartSelectionPrecision::Low => 0.001,
1234 SmartSelectionPrecision::Normal => 1.0,
1235 SmartSelectionPrecision::High => 1000.0,
1236 SmartSelectionPrecision::VeryHigh => 1_000_000.0,
1237 }
1238 }
1239
1240 pub fn display_name(&self) -> &'static str {
1242 match self {
1243 SmartSelectionPrecision::VeryLow => "Very Low",
1244 SmartSelectionPrecision::Low => "Low",
1245 SmartSelectionPrecision::Normal => "Normal",
1246 SmartSelectionPrecision::High => "High",
1247 SmartSelectionPrecision::VeryHigh => "Very High",
1248 }
1249 }
1250}
1251
1252#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
1254#[serde(rename_all = "snake_case")]
1255pub enum PaneTitlePosition {
1256 #[default]
1258 Top,
1259 Bottom,
1261}
1262
1263impl PaneTitlePosition {
1264 pub const ALL: &'static [PaneTitlePosition] =
1266 &[PaneTitlePosition::Top, PaneTitlePosition::Bottom];
1267
1268 pub fn display_name(&self) -> &'static str {
1270 match self {
1271 PaneTitlePosition::Top => "Top",
1272 PaneTitlePosition::Bottom => "Bottom",
1273 }
1274 }
1275}
1276
1277#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
1279#[serde(rename_all = "snake_case")]
1280pub enum DividerStyle {
1281 #[default]
1283 Solid,
1284 Double,
1286 Dashed,
1288 Shadow,
1290}
1291
1292impl DividerStyle {
1293 pub const ALL: &'static [DividerStyle] = &[
1295 DividerStyle::Solid,
1296 DividerStyle::Double,
1297 DividerStyle::Dashed,
1298 DividerStyle::Shadow,
1299 ];
1300
1301 pub fn display_name(&self) -> &'static str {
1303 match self {
1304 DividerStyle::Solid => "Solid",
1305 DividerStyle::Double => "Double",
1306 DividerStyle::Dashed => "Dashed",
1307 DividerStyle::Shadow => "Shadow",
1308 }
1309 }
1310}
1311
1312#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
1314#[serde(rename_all = "snake_case")]
1315pub enum AlertEvent {
1316 Bell,
1318 CommandComplete,
1320 NewTab,
1322 TabClose,
1324}
1325
1326impl AlertEvent {
1327 pub fn display_name(&self) -> &'static str {
1329 match self {
1330 AlertEvent::Bell => "Bell",
1331 AlertEvent::CommandComplete => "Command Complete",
1332 AlertEvent::NewTab => "New Tab",
1333 AlertEvent::TabClose => "Tab Close",
1334 }
1335 }
1336
1337 pub fn all() -> &'static [AlertEvent] {
1339 &[
1340 AlertEvent::Bell,
1341 AlertEvent::CommandComplete,
1342 AlertEvent::NewTab,
1343 AlertEvent::TabClose,
1344 ]
1345 }
1346}
1347
1348#[derive(Debug, Clone, Serialize, Deserialize)]
1350pub struct AlertSoundConfig {
1351 #[serde(default = "crate::defaults::bool_true")]
1353 pub enabled: bool,
1354 #[serde(default = "crate::defaults::bell_sound")]
1356 pub volume: u8,
1357 #[serde(default)]
1360 pub sound_file: Option<String>,
1361 #[serde(default = "default_alert_frequency")]
1363 pub frequency: f32,
1364 #[serde(default = "default_alert_duration_ms")]
1366 pub duration_ms: u64,
1367}
1368
1369fn default_alert_frequency() -> f32 {
1370 800.0
1371}
1372
1373fn default_alert_duration_ms() -> u64 {
1374 100
1375}
1376
1377impl Default for AlertSoundConfig {
1378 fn default() -> Self {
1379 Self {
1380 enabled: true,
1381 volume: 50,
1382 sound_file: None,
1383 frequency: 800.0,
1384 duration_ms: 100,
1385 }
1386 }
1387}
1388
1389#[derive(Debug, Clone, Serialize, Deserialize)]
1394pub struct SmartSelectionRule {
1395 pub name: String,
1397 pub regex: String,
1399 #[serde(default)]
1401 pub precision: SmartSelectionPrecision,
1402 #[serde(default = "default_enabled")]
1404 pub enabled: bool,
1405}
1406
1407fn default_enabled() -> bool {
1408 true
1409}
1410
1411impl SmartSelectionRule {
1412 pub fn new(
1414 name: impl Into<String>,
1415 regex: impl Into<String>,
1416 precision: SmartSelectionPrecision,
1417 ) -> Self {
1418 Self {
1419 name: name.into(),
1420 regex: regex.into(),
1421 precision,
1422 enabled: true,
1423 }
1424 }
1425}
1426
1427pub fn default_smart_selection_rules() -> Vec<SmartSelectionRule> {
1429 vec![
1430 SmartSelectionRule::new(
1432 "HTTP URL",
1433 r"https?://[^\s<>\[\]{}|\\^`\x00-\x1f]+",
1434 SmartSelectionPrecision::VeryHigh,
1435 ),
1436 SmartSelectionRule::new(
1437 "SSH URL",
1438 r"\bssh://([a-zA-Z0-9_]+@)?([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+(/[^\s]*)?",
1439 SmartSelectionPrecision::VeryHigh,
1440 ),
1441 SmartSelectionRule::new(
1442 "Git URL",
1443 r"\bgit://([a-zA-Z0-9_]+@)?([a-zA-Z0-9\-]+\.)*[a-zA-Z0-9\-]+(/[^\s]*)?",
1444 SmartSelectionPrecision::VeryHigh,
1445 ),
1446 SmartSelectionRule::new(
1447 "File URL",
1448 r"file://[^\s]+",
1449 SmartSelectionPrecision::VeryHigh,
1450 ),
1451 SmartSelectionRule::new(
1453 "Email address",
1454 r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}\b",
1455 SmartSelectionPrecision::High,
1456 ),
1457 SmartSelectionRule::new(
1458 "IPv4 address",
1459 r"\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b",
1460 SmartSelectionPrecision::High,
1461 ),
1462 SmartSelectionRule::new(
1464 "File path",
1465 r"~?/?(?:[a-zA-Z0-9._-]+/)+[a-zA-Z0-9._-]+/?",
1466 SmartSelectionPrecision::Normal,
1467 ),
1468 SmartSelectionRule::new(
1469 "Java/Python import",
1470 r"(?:[a-zA-Z_][a-zA-Z0-9_]*\.){2,}[a-zA-Z_][a-zA-Z0-9_]*",
1472 SmartSelectionPrecision::Normal,
1473 ),
1474 SmartSelectionRule::new(
1475 "C++ namespace",
1476 r"(?:[a-zA-Z_][a-zA-Z0-9_]*::)+[a-zA-Z_][a-zA-Z0-9_]*",
1477 SmartSelectionPrecision::Normal,
1478 ),
1479 SmartSelectionRule::new(
1480 "Quoted string",
1481 r#""(?:[^"\\]|\\.)*""#,
1482 SmartSelectionPrecision::Normal,
1483 ),
1484 SmartSelectionRule::new(
1485 "UUID",
1486 r"\b[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}\b",
1487 SmartSelectionPrecision::Normal,
1488 ),
1489 ]
1493}
1494
1495#[derive(Debug, Clone, Default)]
1501pub struct PaneBackground {
1502 pub image_path: Option<String>,
1504 pub mode: BackgroundImageMode,
1506 pub opacity: f32,
1508}
1509
1510impl PaneBackground {
1511 pub fn new() -> Self {
1513 Self {
1514 image_path: None,
1515 mode: BackgroundImageMode::default(),
1516 opacity: 1.0,
1517 }
1518 }
1519
1520 pub fn has_image(&self) -> bool {
1522 self.image_path.is_some()
1523 }
1524}
1525
1526#[derive(Debug, Clone, Copy)]
1528pub struct DividerRect {
1529 pub x: f32,
1531 pub y: f32,
1533 pub width: f32,
1535 pub height: f32,
1537 pub is_horizontal: bool,
1539}
1540
1541impl DividerRect {
1542 pub fn new(x: f32, y: f32, width: f32, height: f32, is_horizontal: bool) -> Self {
1544 Self {
1545 x,
1546 y,
1547 width,
1548 height,
1549 is_horizontal,
1550 }
1551 }
1552
1553 pub fn contains(&self, px: f32, py: f32, padding: f32) -> bool {
1555 px >= self.x - padding
1556 && px < self.x + self.width + padding
1557 && py >= self.y - padding
1558 && py < self.y + self.height + padding
1559 }
1560}
1561
1562pub type SeparatorMark = (usize, Option<i32>, Option<(u8, u8, u8)>);