use rust_i18n::t;
use crate::config::Config;
use crate::config_io::{ConfigLayer, ConfigResolver};
use crate::input::keybindings::KeybindingResolver;
use crate::services::lsp::manager::detect_language;
use super::Editor;
impl Editor {
pub fn toggle_line_numbers(&mut self) {
if let Some(state) = self.buffers.get_mut(&self.active_buffer()) {
let currently_shown = state.margins.show_line_numbers;
state.margins.set_line_numbers(!currently_shown);
if currently_shown {
self.set_status_message(t!("toggle.line_numbers_hidden").to_string());
} else {
let total_lines = state.buffer.line_count().unwrap_or(1);
state.margins.update_width_for_buffer(total_lines);
self.set_status_message(t!("toggle.line_numbers_shown").to_string());
}
}
}
pub fn toggle_debug_highlights(&mut self) {
if let Some(state) = self.buffers.get_mut(&self.active_buffer()) {
state.debug_highlight_mode = !state.debug_highlight_mode;
if state.debug_highlight_mode {
self.set_status_message(t!("toggle.debug_mode_on").to_string());
} else {
self.set_status_message(t!("toggle.debug_mode_off").to_string());
}
}
}
pub fn toggle_menu_bar(&mut self) {
self.menu_bar_visible = !self.menu_bar_visible;
self.menu_bar_auto_shown = false;
if !self.menu_bar_visible {
self.menu_state.close_menu();
}
let status = if self.menu_bar_visible {
t!("toggle.menu_bar_shown")
} else {
t!("toggle.menu_bar_hidden")
};
self.set_status_message(status.to_string());
}
pub fn toggle_tab_bar(&mut self) {
self.tab_bar_visible = !self.tab_bar_visible;
let status = if self.tab_bar_visible {
t!("toggle.tab_bar_shown")
} else {
t!("toggle.tab_bar_hidden")
};
self.set_status_message(status.to_string());
}
pub fn tab_bar_visible(&self) -> bool {
self.tab_bar_visible
}
pub fn reset_buffer_settings(&mut self) {
let buffer_id = self.active_buffer();
let file_path = self
.buffer_metadata
.get(&buffer_id)
.and_then(|m| m.file_path().cloned());
let (tab_size, use_tabs, show_whitespace_tabs) = if let Some(path) = &file_path {
if let Some(language) = detect_language(path, &self.config.languages) {
if let Some(lang_config) = self.config.languages.get(&language) {
(
lang_config.tab_size.unwrap_or(self.config.editor.tab_size),
lang_config.use_tabs,
lang_config.show_whitespace_tabs,
)
} else {
(self.config.editor.tab_size, false, true)
}
} else {
(self.config.editor.tab_size, false, true)
}
} else {
(self.config.editor.tab_size, false, true)
};
if let Some(state) = self.buffers.get_mut(&buffer_id) {
state.tab_size = tab_size;
state.use_tabs = use_tabs;
state.show_whitespace_tabs = show_whitespace_tabs;
}
self.set_status_message(t!("toggle.buffer_settings_reset").to_string());
}
pub fn toggle_mouse_capture(&mut self) {
use std::io::stdout;
self.mouse_enabled = !self.mouse_enabled;
if self.mouse_enabled {
let _ = crossterm::execute!(stdout(), crossterm::event::EnableMouseCapture);
self.set_status_message(t!("toggle.mouse_capture_enabled").to_string());
} else {
let _ = crossterm::execute!(stdout(), crossterm::event::DisableMouseCapture);
self.set_status_message(t!("toggle.mouse_capture_disabled").to_string());
}
}
pub fn is_mouse_enabled(&self) -> bool {
self.mouse_enabled
}
pub fn toggle_mouse_hover(&mut self) {
self.config.editor.mouse_hover_enabled = !self.config.editor.mouse_hover_enabled;
if self.config.editor.mouse_hover_enabled {
self.set_status_message(t!("toggle.mouse_hover_enabled").to_string());
} else {
self.mouse_state.lsp_hover_state = None;
self.mouse_state.lsp_hover_request_sent = false;
self.set_status_message(t!("toggle.mouse_hover_disabled").to_string());
}
}
pub fn is_mouse_hover_enabled(&self) -> bool {
self.config.editor.mouse_hover_enabled
}
pub fn set_gpm_active(&mut self, active: bool) {
self.gpm_active = active;
}
pub fn toggle_inlay_hints(&mut self) {
self.config.editor.enable_inlay_hints = !self.config.editor.enable_inlay_hints;
if self.config.editor.enable_inlay_hints {
self.request_inlay_hints_for_active_buffer();
self.set_status_message(t!("toggle.inlay_hints_enabled").to_string());
} else {
for state in self.buffers.values_mut() {
state.virtual_texts.clear(&mut state.marker_list);
}
self.set_status_message(t!("toggle.inlay_hints_disabled").to_string());
}
}
pub fn dump_config(&mut self) {
if let Err(e) = self.filesystem.create_dir_all(&self.dir_context.config_dir) {
self.set_status_message(
t!("error.config_dir_failed", error = e.to_string()).to_string(),
);
return;
}
let config_path = self.dir_context.config_path();
let resolver = ConfigResolver::new(self.dir_context.clone(), self.working_dir.clone());
match resolver.save_to_layer(&self.config, ConfigLayer::User) {
Ok(()) => {
match self.open_file(&config_path) {
Ok(_buffer_id) => {
self.set_status_message(
t!("config.saved", path = config_path.display().to_string())
.to_string(),
);
}
Err(e) => {
self.set_status_message(
t!("config.saved_failed_open", error = e.to_string()).to_string(),
);
}
}
}
Err(e) => {
self.set_status_message(
t!("error.config_save_failed", error = e.to_string()).to_string(),
);
}
}
}
pub fn save_config(&self) -> Result<(), String> {
self.filesystem
.create_dir_all(&self.dir_context.config_dir)
.map_err(|e| format!("Failed to create config directory: {}", e))?;
let resolver = ConfigResolver::new(self.dir_context.clone(), self.working_dir.clone());
resolver
.save_to_layer(&self.config, ConfigLayer::User)
.map_err(|e| format!("Failed to save config: {}", e))
}
pub fn reload_config(&mut self) {
let old_theme = self.config.theme.clone();
self.config = Config::load_with_layers(&self.dir_context, &self.working_dir);
if old_theme != self.config.theme {
if let Some(theme) = self.theme_registry.get_cloned(&self.config.theme) {
self.theme = theme;
tracing::info!("Theme changed to '{}'", self.config.theme.0);
} else {
tracing::error!("Theme '{}' not found", self.config.theme.0);
}
}
self.keybindings = KeybindingResolver::new(&self.config);
if let Some(ref mut lsp) = self.lsp {
for (language, lsp_config) in &self.config.lsp {
lsp.set_language_config(language.clone(), lsp_config.clone());
}
}
let config_path = Config::find_config_path(&self.working_dir);
self.emit_event(
"config_changed",
serde_json::json!({
"path": config_path.map(|p| p.to_string_lossy().into_owned()),
}),
);
}
pub fn reload_themes(&mut self) {
use crate::view::theme::ThemeLoader;
let theme_loader = ThemeLoader::new();
self.theme_registry = theme_loader.load_all();
if let Some(theme) = self.theme_registry.get_cloned(&self.config.theme) {
self.theme = theme;
}
tracing::info!(
"Theme registry reloaded ({} themes)",
self.theme_registry.len()
);
self.emit_event("themes_changed", serde_json::json!({}));
}
}