on master help sign in
Render code actions as a menu, allow adding padding to popup
commit094a0aa3f9877e3b1049f262e65c8efea2b7b73e authorBlaž Hrastnik <blaz@mxxn.io> dateMon 31 Jan 2022, 13:42 (5 years ago) parentf7f5514
5 files changed+59−24
helix-term/src/commands.rs+26−14 helix-term/src/ui/menu.rs+11−4 helix-term/src/ui/mod.rs+1−1 helix-term/src/ui/popup.rs+20−4 helix-tui/src/widgets/block.rs+1−1
helix-term/src/commands.rs+26−14
@@ -39,7 +39,7 @@ use movement::Movement;
3939use crate::{
4040 args,
4141 compositor::{self, Component, Compositor},
42− ui::{self, FilePicker, Picker, Popup, Prompt, PromptEvent},
42+ ui::{self, FilePicker, Popup, Prompt, PromptEvent},
4343};
4444
4545use crate::job::{self, Job, Jobs};
@@ -3463,6 +3463,15 @@ fn workspace_symbol_picker(cx: &mut Context) {
34633463 )
34643464}
34653465
3466+impl ui::menu::Item for lsp::CodeActionOrCommand {
3467+ fn label(&self) -> &str {
3468+ match self {
3469+ lsp::CodeActionOrCommand::CodeAction(action) => action.title.as_str(),
3470+ lsp::CodeActionOrCommand::Command(command) => command.title.as_str(),
3471+ }
3472+ }
3473+}
3474+
34663475pub fn code_action(cx: &mut Context) {
34673476 let (view, doc) = current!(cx.editor);
34683477
@@ -3491,16 +3500,15 @@ pub fn code_action(cx: &mut Context) {
34913500 return;
34923501 }
34933502
3494− let picker = Picker::new(
3495− false,
3496− actions,
3497− |action| match action {
3498− lsp::CodeActionOrCommand::CodeAction(action) => {
3499− action.title.as_str().into()
3500− }
3501− lsp::CodeActionOrCommand::Command(command) => command.title.as_str().into(),
3502− },
3503− move |editor, code_action, _action| match code_action {
3503+ let picker = ui::Menu::new(actions, move |editor, code_action, event| {
3504+ if event != PromptEvent::Validate {
3505+ return;
3506+ }
3507+
3508+ // always present here
3509+ let code_action = code_action.unwrap();
3510+
3511+ match code_action {
35043512 lsp::CodeActionOrCommand::Command(command) => {
35053513 log::debug!("code action command: {:?}", command);
35063514 execute_lsp_command(editor, command.clone());
@@ -3518,9 +3526,13 @@ pub fn code_action(cx: &mut Context) {
35183526 execute_lsp_command(editor, command.clone());
35193527 }
35203528 }
3521− },
3522− );
3523− let popup = Popup::new("code-action", picker);
3529+ }
3530+ });
3531+ let popup =
3532+ Popup::new("code-action", picker).margin(helix_view::graphics::Margin {
3533+ vertical: 1,
3534+ horizontal: 1,
3535+ });
35243536 compositor.push(Box::new(popup))
35253537 }
35263538 },
helix-term/src/ui/menu.rs+11−4
@@ -14,11 +14,18 @@ use helix_view::{graphics::Rect, Editor};
1414use tui::layout::Constraint;
1515
1616pub trait Item {
17− fn sort_text(&self) -> &str;
18− fn filter_text(&self) -> &str;
19−
2017 fn label(&self) -> &str;
21− fn row(&self) -> Row;
18+
19+ fn sort_text(&self) -> &str {
20+ self.label()
21+ }
22+ fn filter_text(&self) -> &str {
23+ self.label()
24+ }
25+
26+ fn row(&self) -> Row {
27+ Row::new(vec![Cell::from(self.label())])
28+ }
2229}
2330
2431pub struct Menu<T: Item> {
helix-term/src/ui/mod.rs+1−1
@@ -2,7 +2,7 @@ mod completion;
22pub(crate) mod editor;
33mod info;
44mod markdown;
5−mod menu;
5+pub mod menu;
66mod picker;
77mod popup;
88mod prompt;
helix-term/src/ui/popup.rs+20−4
@@ -6,7 +6,7 @@ use crossterm::event::Event;
66use tui::buffer::Buffer as Surface;
77
88use helix_core::Position;
9−use helix_view::graphics::Rect;
9+use helix_view::graphics::{Margin, Rect};
1010
1111// TODO: share logic with Menu, it's essentially Popup(render_fn), but render fn needs to return
1212// a width/height hint. maybe Popup(Box<Component>)
@@ -14,6 +14,7 @@ use helix_view::graphics::Rect;
1414pub struct Popup<T: Component> {
1515 contents: T,
1616 position: Option<Position>,
17+ margin: Margin,
1718 size: (u16, u16),
1819 child_size: (u16, u16),
1920 scroll: usize,
@@ -25,6 +26,10 @@ impl<T: Component> Popup<T> {
2526 Self {
2627 contents,
2728 position: None,
29+ margin: Margin {
30+ vertical: 0,
31+ horizontal: 0,
32+ },
2833 size: (0, 0),
2934 child_size: (0, 0),
3035 scroll: 0,
@@ -36,6 +41,11 @@ impl<T: Component> Popup<T> {
3641 self.position = pos;
3742 }
3843
44+ pub fn margin(mut self, margin: Margin) -> Self {
45+ self.margin = margin;
46+ self
47+ }
48+
3949 pub fn get_rel_position(&mut self, viewport: Rect, cx: &Context) -> (u16, u16) {
4050 let position = self
4151 .position
@@ -126,13 +136,18 @@ impl<T: Component> Component for Popup<T> {
126136 let max_width = 120.min(viewport.0);
127137 let max_height = 26.min(viewport.1.saturating_sub(2)); // add some spacing in the viewport
128138
139+ let inner = Rect::new(0, 0, max_width, max_height).inner(&self.margin);
140+
129141 let (width, height) = self
130142 .contents
131− .required_size((max_width, max_height))
143+ .required_size((inner.width, inner.height))
132144 .expect("Component needs required_size implemented in order to be embedded in a popup");
133145
134146 self.child_size = (width, height);
135− self.size = (width.min(max_width), height.min(max_height));
147+ self.size = (
148+ (width + self.margin.horizontal * 2).min(max_width),
149+ (height + self.margin.vertical * 2).min(max_height),
150+ );
136151
137152 // re-clamp scroll offset
138153 let max_offset = self.child_size.1.saturating_sub(self.size.1);
@@ -156,7 +171,8 @@ impl<T: Component> Component for Popup<T> {
156171 let background = cx.editor.theme.get("ui.popup");
157172 surface.clear_with(area, background);
158173
159− self.contents.render(area, surface, cx);
174+ let inner = area.inner(&self.margin);
175+ self.contents.render(inner, surface, cx);
160176 }
161177
162178 fn id(&self) -> Option<&'static str> {
helix-tui/src/widgets/block.rs+1−1
@@ -134,7 +134,7 @@ impl<'a> Widget for Block<'a> {
134134 if area.area() == 0 {
135135 return;
136136 }
137− buf.set_style(area, self.style);
137+ buf.clear_with(area, self.style);
138138 let symbols = BorderType::line_symbols(self.border_type);
139139
140140 // Sides