fresh/app/
menu_context.rs1use super::Editor;
9use crate::view::ui::context_keys;
10
11impl Editor {
12 pub fn menu_context(&self) -> crate::view::ui::MenuContext {
18 self.menu_state.context.clone()
19 }
20
21 pub fn expanded_menu_definitions(&self) -> Vec<fresh_core::menu::Menu> {
25 use crate::config::{MenuConfig, MenuExt};
26
27 let mut menus = MenuConfig::translated_menus();
28 let themes_dir = self.menu_state.themes_dir.clone();
29 for menu in &mut menus {
30 menu.expand_dynamic_items(&themes_dir);
31 }
32 menus
33 }
34
35 pub fn update_menu_context(&mut self) {
38 let line_numbers = self.is_line_numbers_visible();
40 let line_wrap = self.is_line_wrap_enabled();
41 let compose_mode = self.is_compose_mode();
42 let file_explorer_visible = self.file_explorer_visible;
43 let file_explorer_focused = self.is_file_explorer_focused();
44 let mouse_capture = self.mouse_enabled;
45 let mouse_hover = self.config.editor.mouse_hover_enabled;
46 let inlay_hints = self.config.editor.enable_inlay_hints;
47 let has_selection = self.has_active_selection();
48 let menu_bar = self.menu_bar_visible;
49 let vertical_scrollbar = self.config.editor.show_vertical_scrollbar;
50 let horizontal_scrollbar = self.config.editor.show_horizontal_scrollbar;
51
52 let show_hidden = self.is_file_explorer_showing_hidden();
54 let show_gitignored = self.is_file_explorer_showing_gitignored();
55
56 let lsp_available = self.is_lsp_available();
58 let formatter_available = self.is_formatter_available();
59
60 let session_mode = self.session_mode;
62
63 let scroll_sync = self.same_buffer_scroll_sync;
65 let has_same_buffer_splits = self.has_same_buffer_splits();
66
67 self.menu_state
69 .context
70 .set(context_keys::LINE_NUMBERS, line_numbers)
71 .set(context_keys::LINE_WRAP, line_wrap)
72 .set(context_keys::COMPOSE_MODE, compose_mode)
73 .set(context_keys::FILE_EXPLORER, file_explorer_visible)
74 .set(context_keys::FILE_EXPLORER_FOCUSED, file_explorer_focused)
75 .set(context_keys::MOUSE_CAPTURE, mouse_capture)
76 .set(context_keys::MOUSE_HOVER, mouse_hover)
77 .set(context_keys::INLAY_HINTS, inlay_hints)
78 .set(context_keys::LSP_AVAILABLE, lsp_available)
79 .set(context_keys::FILE_EXPLORER_SHOW_HIDDEN, show_hidden)
80 .set(context_keys::FILE_EXPLORER_SHOW_GITIGNORED, show_gitignored)
81 .set(context_keys::HAS_SELECTION, has_selection)
82 .set(context_keys::MENU_BAR, menu_bar)
83 .set(context_keys::FORMATTER_AVAILABLE, formatter_available)
84 .set(context_keys::SESSION_MODE, session_mode)
85 .set(context_keys::VERTICAL_SCROLLBAR, vertical_scrollbar)
86 .set(context_keys::HORIZONTAL_SCROLLBAR, horizontal_scrollbar)
87 .set(context_keys::SCROLL_SYNC, scroll_sync)
88 .set(context_keys::HAS_SAME_BUFFER_SPLITS, has_same_buffer_splits);
89 }
90
91 fn is_line_numbers_visible(&self) -> bool {
93 let active_split = self.split_manager.active_split();
94 self.split_view_states
95 .get(&active_split)
96 .map(|vs| vs.show_line_numbers)
97 .unwrap_or(true)
98 }
99
100 fn is_line_wrap_enabled(&self) -> bool {
102 let active_split = self.split_manager.active_split();
103 self.split_view_states
104 .get(&active_split)
105 .map(|vs| vs.viewport.line_wrap_enabled)
106 .unwrap_or(false)
107 }
108
109 fn is_compose_mode(&self) -> bool {
111 let active_split = self.split_manager.active_split();
112 self.split_view_states
113 .get(&active_split)
114 .map(|vs| vs.view_mode == crate::state::ViewMode::Compose)
115 .unwrap_or(false)
116 }
117
118 fn is_file_explorer_focused(&self) -> bool {
120 self.key_context == crate::input::keybindings::KeyContext::FileExplorer
121 }
122
123 fn is_file_explorer_showing_hidden(&self) -> bool {
125 self.file_explorer
126 .as_ref()
127 .map(|fe| fe.ignore_patterns().show_hidden())
128 .unwrap_or(false)
129 }
130
131 fn is_file_explorer_showing_gitignored(&self) -> bool {
133 self.file_explorer
134 .as_ref()
135 .map(|fe| fe.ignore_patterns().show_gitignored())
136 .unwrap_or(false)
137 }
138
139 fn is_lsp_available(&self) -> bool {
141 let buffer_id = self.active_buffer();
142
143 if let Some(metadata) = self.buffer_metadata.get(&buffer_id) {
145 if !metadata.lsp_enabled {
146 return false;
147 }
148 } else {
149 return false;
150 }
151
152 self.buffers
154 .get(&buffer_id)
155 .and_then(|state| {
156 self.lsp
157 .as_ref()
158 .map(|lsp| lsp.is_server_ready(&state.language))
159 })
160 .unwrap_or(false)
161 }
162
163 fn has_same_buffer_splits(&self) -> bool {
165 let active_split = self.split_manager.active_split();
166 let active_buf_id = self.split_manager.buffer_for_split(active_split);
167 if let Some(buf_id) = active_buf_id {
168 self.split_view_states
169 .keys()
170 .filter(|&&s| {
171 s != active_split && self.split_manager.buffer_for_split(s) == Some(buf_id)
172 })
173 .next()
174 .is_some()
175 } else {
176 false
177 }
178 }
179
180 fn is_formatter_available(&self) -> bool {
182 let buffer_id = self.active_buffer();
183
184 self.buffers
186 .get(&buffer_id)
187 .and_then(|state| {
188 self.config
189 .languages
190 .get(&state.language)
191 .and_then(|lc| lc.formatter.as_ref())
192 .map(|_| true)
193 })
194 .unwrap_or(false)
195 }
196}