1use gpui::{App, Div, Entity, InteractiveElement as _, IntoElement, RenderOnce, Stateful, Window};
2
3use super::{EditorMode, InputBaseState, InputModeKind};
4
5pub type EditorState = InputBaseState<EditorMode>;
12
13impl InputModeKind for EditorMode {
14 const MULTI_LINE: bool = true;
15 const CODE_EDITOR: bool = true;
16
17 type Extras = super::EditorExtras;
18
19 fn hover_definition_style(
20 state: &InputBaseState<Self>,
21 _cx: &App,
22 ) -> Option<(std::ops::Range<usize>, gpui::HighlightStyle)> {
23 state.hover_definition_style()
24 }
25
26 fn hover_definition_hitbox(
27 state: &InputBaseState<Self>,
28 window: &mut Window,
29 _cx: &App,
30 ) -> Option<gpui::Hitbox> {
31 state.hover_definition_hitbox(window)
32 }
33
34 fn reset_language_features(state: &mut InputBaseState<Self>) {
35 state.extras.lsp.reset();
36 }
37
38 fn reset_annotations(state: &mut InputBaseState<Self>) {
39 state.extras.hover_popover = None;
40 state.extras.decorations.clear();
41 }
42
43 fn adjust_annotations(
44 state: &mut InputBaseState<Self>,
45 range: &std::ops::Range<usize>,
46 new_len: usize,
47 ) {
48 state.extras.decorations.adjust_for_edit(range, new_len);
49 }
50
51 fn refresh_language_features(
52 state: &mut InputBaseState<Self>,
53 window: &mut Window,
54 cx: &mut gpui::Context<InputBaseState<Self>>,
55 ) {
56 let text = state.text().clone();
57 state.extras.lsp.update(&text, window, cx);
58 }
59
60 fn accept_inline_completion(
61 state: &mut InputBaseState<Self>,
62 window: &mut Window,
63 cx: &mut gpui::Context<InputBaseState<Self>>,
64 ) -> bool {
65 state.accept_inline_completion(window, cx)
66 }
67
68 fn has_inline_completion(state: &InputBaseState<Self>) -> bool {
69 state.has_inline_completion()
70 }
71
72 fn on_click(
73 state: &mut InputBaseState<Self>,
74 event: &gpui::MouseDownEvent,
75 offset: usize,
76 window: &mut Window,
77 cx: &mut gpui::Context<InputBaseState<Self>>,
78 ) -> bool {
79 state.handle_click_hover_definition(event, offset, window, cx)
80 }
81
82 fn clear_hover_state(
83 state: &mut InputBaseState<Self>,
84 cx: &mut gpui::Context<InputBaseState<Self>>,
85 ) {
86 state.clear_hover_state(cx);
87 }
88
89 fn on_text_typed(
90 state: &mut InputBaseState<Self>,
91 range: &std::ops::Range<usize>,
92 text: &str,
93 window: &mut Window,
94 cx: &mut gpui::Context<InputBaseState<Self>>,
95 ) {
96 state.handle_completion_trigger(range, text, window, cx);
97 }
98
99 fn clear_inline_completion(
100 state: &mut InputBaseState<Self>,
101 cx: &mut gpui::Context<InputBaseState<Self>>,
102 ) {
103 state.clear_inline_completion(cx);
104 }
105
106 fn hide_context_menu(
107 state: &mut InputBaseState<Self>,
108 cx: &mut gpui::Context<InputBaseState<Self>>,
109 ) {
110 state.hide_context_menu(cx);
111 }
112
113 fn is_context_menu_open(state: &InputBaseState<Self>, cx: &App) -> bool {
114 state.is_context_menu_open(cx)
115 }
116
117 fn handle_context_menu_action(
118 state: &mut InputBaseState<Self>,
119 action: Box<dyn gpui::Action>,
120 window: &mut Window,
121 cx: &mut gpui::Context<InputBaseState<Self>>,
122 ) -> bool {
123 state.handle_action_for_context_menu(action, window, cx)
124 }
125
126 fn on_hover_definition(
127 state: &mut InputBaseState<Self>,
128 offset: usize,
129 window: &mut Window,
130 cx: &mut gpui::Context<InputBaseState<Self>>,
131 ) {
132 state.handle_hover_definition(offset, window, cx);
133 }
134
135 fn on_mouse_move(
136 state: &mut InputBaseState<Self>,
137 offset: usize,
138 event: &gpui::MouseMoveEvent,
139 window: &mut Window,
140 cx: &mut gpui::Context<InputBaseState<Self>>,
141 ) {
142 state.handle_mouse_move(offset, event, window, cx);
143 }
144
145 fn drive_highlighter(
146 highlighter: &std::rc::Rc<std::cell::RefCell<Option<Box<dyn super::InputHighlighter>>>>,
147 edit: super::InputEdit,
148 text: &ropey::Rope,
149 folding: bool,
150 window: &mut Window,
151 cx: &mut gpui::Context<InputBaseState<Self>>,
152 ) {
153 let mut highlighter = highlighter.borrow_mut();
154 let Some(highlighter) = highlighter.as_mut() else {
155 return;
156 };
157 highlighter.update(Some(edit), text, folding, window, cx);
158 }
159
160 fn register_actions(
161 element: Stateful<Div>,
162 entity: &Entity<InputBaseState<Self>>,
163 window: &mut Window,
164 ) -> Stateful<Div> {
165 element
166 .on_action(window.listener_for(entity, InputBaseState::on_action_toggle_code_actions))
167 .on_action(window.listener_for(entity, InputBaseState::on_action_go_to_definition))
168 }
169}
170
171impl EditorState {
172 pub fn lsp(&self) -> &super::Lsp {
177 &self.extras.lsp
178 }
179
180 pub fn lsp_mut(&mut self) -> &mut super::Lsp {
182 &mut self.extras.lsp
183 }
184}
185
186#[derive(IntoElement)]
188pub struct Editor {
189 state: Entity<EditorState>,
190}
191
192impl Editor {
193 pub fn new(state: &Entity<EditorState>) -> Self {
194 Self {
195 state: state.clone(),
196 }
197 }
198}
199
200impl RenderOnce for Editor {
201 fn render(self, _: &mut Window, _: &mut App) -> impl IntoElement {
202 self.state
203 }
204}
205
206impl crate::input::InputExtras for super::EditorExtras {
208 fn decoration_layers(&self) -> Vec<&[super::TextDecoration]> {
209 self.decorations.iter().collect()
210 }
211
212 fn semantic_token_styles(
213 &self,
214 text: &ropey::Rope,
215 range: &std::ops::Range<usize>,
216 resolver: &dyn crate::input::HighlightStyleResolver,
217 ) -> Vec<(std::ops::Range<usize>, gpui::HighlightStyle)> {
218 self.lsp.semantic_tokens_for_range(text, range, resolver)
219 }
220
221 fn document_color_swatches(
222 &self,
223 text: &ropey::Rope,
224 range: &std::ops::Range<usize>,
225 ) -> Vec<(std::ops::Range<usize>, gpui::Hsla)> {
226 self.lsp.document_colors_for_range(text, range)
227 }
228
229 fn hover_symbol_range(&self) -> Option<std::ops::Range<usize>> {
230 self.hover_popover
231 .as_ref()
232 .map(|session| session.symbol_range.clone())
233 }
234
235 fn inline_completion_item(&self) -> Option<&lsp_types::InlineCompletionItem> {
236 self.inline_completion.item.as_ref()
237 }
238
239 fn context_menu_capabilities(&self) -> (bool, bool) {
240 (
241 self.lsp.definition_provider.is_some(),
242 !self.lsp.code_action_providers.is_empty(),
243 )
244 }
245}