fresh/
types.rs

1//! Shared configuration types used by both schema generation and runtime.
2//!
3//! These types are kept in a separate module so that the schema generator
4//! can import them without pulling in heavy runtime dependencies.
5
6use schemars::JsonSchema;
7use serde::{Deserialize, Serialize};
8
9/// Constants for menu context state keys
10/// These are used both in menu item `when` conditions and `checkbox` states
11pub mod context_keys {
12    pub const LINE_NUMBERS: &str = "line_numbers";
13    pub const LINE_WRAP: &str = "line_wrap";
14    pub const COMPOSE_MODE: &str = "compose_mode";
15    pub const FILE_EXPLORER: &str = "file_explorer";
16    pub const MENU_BAR: &str = "menu_bar";
17    pub const FILE_EXPLORER_FOCUSED: &str = "file_explorer_focused";
18    pub const MOUSE_CAPTURE: &str = "mouse_capture";
19    pub const MOUSE_HOVER: &str = "mouse_hover";
20    pub const LSP_AVAILABLE: &str = "lsp_available";
21    pub const FILE_EXPLORER_SHOW_HIDDEN: &str = "file_explorer_show_hidden";
22    pub const FILE_EXPLORER_SHOW_GITIGNORED: &str = "file_explorer_show_gitignored";
23    pub const HAS_SELECTION: &str = "has_selection";
24    pub const FORMATTER_AVAILABLE: &str = "formatter_available";
25    pub const INLAY_HINTS: &str = "inlay_hints";
26}
27
28/// Configuration for process resource limits
29#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, JsonSchema)]
30pub struct ProcessLimits {
31    /// Maximum memory usage as percentage of total system memory (None = no limit)
32    /// Default is 50% of total system memory
33    #[serde(default)]
34    pub max_memory_percent: Option<u32>,
35
36    /// Maximum CPU usage as percentage of total CPU (None = no limit)
37    /// For multi-core systems, 100% = 1 core, 200% = 2 cores, etc.
38    #[serde(default)]
39    pub max_cpu_percent: Option<u32>,
40
41    /// Enable resource limiting (can be disabled per-platform)
42    #[serde(default = "default_true")]
43    pub enabled: bool,
44}
45
46fn default_true() -> bool {
47    true
48}
49
50impl Default for ProcessLimits {
51    fn default() -> Self {
52        Self {
53            max_memory_percent: Some(50),       // 50% of total memory
54            max_cpu_percent: Some(90),          // 90% of total CPU
55            enabled: cfg!(target_os = "linux"), // Only enabled on Linux by default
56        }
57    }
58}
59
60impl ProcessLimits {
61    /// Create a new ProcessLimits with no restrictions
62    pub fn unlimited() -> Self {
63        Self {
64            max_memory_percent: None,
65            max_cpu_percent: None,
66            enabled: false,
67        }
68    }
69
70    /// Get the default CPU limit (90% of total CPU)
71    pub fn default_cpu_limit_percent() -> u32 {
72        90
73    }
74}
75
76/// LSP server configuration
77#[derive(Debug, Clone, Default, Serialize, Deserialize, JsonSchema)]
78#[schemars(extend("x-display-field" = "/command"))]
79pub struct LspServerConfig {
80    /// Command to spawn the server.
81    /// Required when enabled=true, ignored when enabled=false.
82    #[serde(default)]
83    pub command: String,
84
85    /// Arguments to pass to the server
86    #[serde(default)]
87    pub args: Vec<String>,
88
89    /// Whether the server is enabled
90    #[serde(default = "default_true")]
91    pub enabled: bool,
92
93    /// Whether to auto-start this LSP server when opening matching files
94    /// If false (default), the server must be started manually via command palette
95    #[serde(default)]
96    pub auto_start: bool,
97
98    /// Process resource limits (memory and CPU)
99    #[serde(default)]
100    pub process_limits: ProcessLimits,
101
102    /// Custom initialization options to send to the server
103    /// These are passed in the `initializationOptions` field of the LSP Initialize request
104    #[serde(default)]
105    pub initialization_options: Option<serde_json::Value>,
106}
107
108impl LspServerConfig {
109    /// Merge this config with defaults, using default values for empty/unset fields.
110    ///
111    /// This is used when loading configs where fields like `command` may be empty
112    /// (serde's default) because they weren't specified in the user's config file.
113    pub fn merge_with_defaults(self, defaults: &LspServerConfig) -> LspServerConfig {
114        LspServerConfig {
115            command: if self.command.is_empty() {
116                defaults.command.clone()
117            } else {
118                self.command
119            },
120            args: if self.args.is_empty() {
121                defaults.args.clone()
122            } else {
123                self.args
124            },
125            enabled: self.enabled,
126            auto_start: self.auto_start,
127            process_limits: self.process_limits,
128            initialization_options: self
129                .initialization_options
130                .or_else(|| defaults.initialization_options.clone()),
131        }
132    }
133}