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