Skip to content

Commit

Permalink
Improve popup position
Browse files Browse the repository at this point in the history
Make the popup positions more consistent.
Improvements:
1. if the signature popup content is bigger than the available space,
   then the popup is always shown under the cursor, even if there more
   space above the cursor than below
2. There is no mutation anymore inside required_size. Maybe in the future
   we can update all widgets to have no mutations and change the trait
3. completion logic doesn't have any dependencies to SignatureHelp Popup

Signed-off-by: Ben Fekih, Hichem <[email protected]>
  • Loading branch information
karthago1 committed Apr 11, 2024
1 parent c9ae694 commit 38b7815
Show file tree
Hide file tree
Showing 8 changed files with 139 additions and 149 deletions.
13 changes: 2 additions & 11 deletions helix-term/src/handlers/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ use crate::events::{OnModeSwitch, PostCommand, PostInsertChar};
use crate::job::{dispatch, dispatch_blocking};
use crate::keymap::MappableCommand;
use crate::ui::editor::InsertEvent;
use crate::ui::lsp::SignatureHelp;
use crate::ui::{self, CompletionItem, Popup};
use crate::ui::{self, CompletionItem};

use super::Handlers;

Expand Down Expand Up @@ -306,20 +305,12 @@ fn show_completion(
return;
}

let size = compositor.size();
let ui = compositor.find::<ui::EditorView>().unwrap();
if ui.completion.is_some() {
return;
}

let completion_area = ui.set_completion(editor, savepoint, items, trigger.pos, size);
let signature_help_area = compositor
.find_id::<Popup<SignatureHelp>>(SignatureHelp::ID)
.map(|signature_help| signature_help.area(size, editor));
// Delete the signature help popup if they intersect.
if matches!((completion_area, signature_help_area),(Some(a), Some(b)) if a.intersects(b)) {
compositor.remove(SignatureHelp::ID);
}
ui.set_completion(editor, savepoint, items, trigger.pos);
}

pub fn trigger_auto_completion(
Expand Down
28 changes: 4 additions & 24 deletions helix-term/src/handlers/signature_help.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,11 @@ use helix_view::Editor;
use tokio::sync::mpsc::Sender;
use tokio::time::Instant;

use crate::commands::Open;
use crate::compositor::Compositor;
use crate::events::{OnModeSwitch, PostInsertChar};
use crate::handlers::Handlers;
use crate::ui::lsp::SignatureHelp;
use crate::ui::Popup;
use crate::{job, ui};
use crate::job;
use crate::ui::signature_help::{SignatureHelp, SignaturePopup};

#[derive(Debug)]
enum State {
Expand Down Expand Up @@ -231,26 +229,8 @@ pub fn show_signature_help(
};
contents.set_active_param_range(active_param_range());

let old_popup = compositor.find_id::<Popup<SignatureHelp>>(SignatureHelp::ID);
let mut popup = Popup::new(SignatureHelp::ID, contents)
.position(old_popup.and_then(|p| p.get_position()))
.position_bias(Open::Above)
.ignore_escape_key(true);

// Don't create a popup if it intersects the auto-complete menu.
let size = compositor.size();
if compositor
.find::<ui::EditorView>()
.unwrap()
.completion
.as_mut()
.map(|completion| completion.area(size, editor))
.filter(|area| area.intersects(popup.area(size, editor)))
.is_some()
{
return;
}

let old_popup = compositor.find_id::<SignaturePopup>(SignatureHelp::ID);
let popup = SignaturePopup::new(contents, old_popup.and_then(|p| p.get_position()));
compositor.replace_or_push(SignatureHelp::ID, popup);
}

Expand Down
19 changes: 5 additions & 14 deletions helix-term/src/ui/completion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ use helix_view::{
document::SavePoint,
editor::CompleteAction,
graphics::Margin,
handlers::lsp::SignatureHelpInvoked,
theme::{Modifier, Style},
ViewId,
};
Expand Down Expand Up @@ -329,13 +328,6 @@ impl Completion {
trigger_auto_completion(&editor.handlers.completions, editor, true);
}
};

// In case the popup was deleted because of an intersection w/ the auto-complete menu.
if event != PromptEvent::Update {
editor
.handlers
.trigger_signature_help(SignatureHelpInvoked::Automatic, editor);
}
});

let margin = if editor.menu_border() {
Expand Down Expand Up @@ -436,6 +428,10 @@ impl Component for Completion {
}

fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
cx.editor.completion_areas.clear();
let popup_area = self.popup.area(area, cx.editor);
cx.editor.completion_areas.push(popup_area);

self.popup.render(area, surface, cx);

// if we have a selection, render a markdown popup on top/below with info
Expand Down Expand Up @@ -493,12 +489,6 @@ impl Component for Completion {
None => return,
};

let popup_area = {
let (popup_x, popup_y) = self.popup.get_rel_position(area, cx.editor);
let (popup_width, popup_height) = self.popup.get_size();
Rect::new(popup_x, popup_y, popup_width, popup_height)
};

let doc_width_available = area.width.saturating_sub(popup_area.right());
let doc_area = if doc_width_available > 30 {
let mut doc_width = doc_width_available;
Expand Down Expand Up @@ -544,6 +534,7 @@ impl Component for Completion {
Widget::render(Block::default().borders(Borders::ALL), doc_area, surface);
}

cx.editor.completion_areas.push(doc_area);
markdown_doc.render(doc_area, surface, cx);
}
}
Expand Down
12 changes: 4 additions & 8 deletions helix-term/src/ui/editor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1020,27 +1020,23 @@ impl EditorView {
savepoint: Arc<SavePoint>,
items: Vec<CompletionItem>,
trigger_offset: usize,
size: Rect,
) -> Option<Rect> {
let mut completion = Completion::new(editor, savepoint, items, trigger_offset);

) {
let completion = Completion::new(editor, savepoint, items, trigger_offset);
if completion.is_empty() {
// skip if we got no completion results
return None;
return;
}

let area = completion.area(size, editor);
editor.last_completion = Some(CompleteAction::Triggered);
self.last_insert.1.push(InsertEvent::TriggerCompletion);

// TODO : propagate required size on resize to completion too
completion.required_size((size.width, size.height));
self.completion = Some(completion);
Some(area)
}

pub fn clear_completion(&mut self, editor: &mut Editor) {
self.completion = None;
editor.completion_areas.clear();
if let Some(last_completion) = editor.last_completion.take() {
match last_completion {
CompleteAction::Triggered => (),
Expand Down
8 changes: 3 additions & 5 deletions helix-term/src/ui/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,18 @@ mod completion;
mod document;
pub(crate) mod editor;
mod info;
pub mod lsp;
mod markdown;
pub mod menu;
pub mod overlay;
pub mod picker;
pub mod popup;
mod prompt;
pub mod signature_help;
mod spinner;
mod statusline;
mod text;

use crate::compositor::{Component, Compositor};
use crate::compositor::Compositor;
use crate::filter_picker_entry;
use crate::job::{self, Callback};
pub use completion::{Completion, CompletionItem};
Expand Down Expand Up @@ -143,14 +143,12 @@ pub fn raw_regex_prompt(
move |_editor: &mut Editor, compositor: &mut Compositor| {
let contents = Text::new(format!("{}", err));
let size = compositor.size();
let mut popup = Popup::new("invalid-regex", contents)
let popup = Popup::new("invalid-regex", contents)
.position(Some(helix_core::Position::new(
size.height as usize - 2, // 2 = statusline + commandline
0,
)))
.auto_close(true);
popup.required_size((size.width, size.height));

compositor.replace_or_push("invalid-regex", popup);
},
));
Expand Down
Loading

0 comments on commit 38b7815

Please sign in to comment.