From 7162632eb739557ededaee902b23e48a577817b4 Mon Sep 17 00:00:00 2001 From: Blaž Hrastnik Date: Thu, 25 Feb 2021 18:07:47 +0900 Subject: lsp: Hover documentation draft. --- helix-term/src/ui/popup.rs | 95 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 helix-term/src/ui/popup.rs (limited to 'helix-term/src/ui/popup.rs') diff --git a/helix-term/src/ui/popup.rs b/helix-term/src/ui/popup.rs new file mode 100644 index 00000000..ca860707 --- /dev/null +++ b/helix-term/src/ui/popup.rs @@ -0,0 +1,95 @@ +use crate::compositor::{Component, Compositor, Context, EventResult}; +use crossterm::event::{Event, KeyCode, KeyEvent, KeyModifiers}; +use tui::buffer::Buffer as Surface; +use tui::{ + layout::Rect, + style::{Color, Style}, + widgets::{Block, Borders}, +}; + +use std::borrow::Cow; + +use helix_core::Position; +use helix_view::Editor; + +pub struct Popup { + contents: String, + position: Position, +} + +impl Popup { + // TODO: it's like a slimmed down picker, share code? (picker = menu + prompt with different + // rendering) + pub fn new(contents: String) -> Self { + Self { + contents, + position: Position::default(), + } + } + + pub fn set_position(&mut self, pos: Position) { + self.position = pos; + } +} + +impl Component for Popup { + fn handle_event(&mut self, event: Event, cx: &mut Context) -> EventResult { + let event = match event { + Event::Key(event) => event, + _ => return EventResult::Ignored, + }; + + let close_fn = EventResult::Consumed(Some(Box::new( + |compositor: &mut Compositor, editor: &mut Editor| { + // remove the layer + compositor.pop(); + }, + ))); + + match event { + // esc or ctrl-c aborts the completion and closes the menu + KeyEvent { + code: KeyCode::Esc, .. + } + | KeyEvent { + code: KeyCode::Char('c'), + modifiers: KeyModifiers::CONTROL, + } => { + return close_fn; + } + _ => (), + } + // for some events, we want to process them but send ignore, specifically all input except + // tab/enter/ctrl-k or whatever will confirm the selection/ ctrl-n/ctrl-p for scroll. + // EventResult::Consumed(None) + EventResult::Consumed(None) + } + fn render(&self, area: Rect, surface: &mut Surface, cx: &mut Context) { + // render a box at x, y. Width equal to max width of item. + const MAX: usize = 15; + let rows = std::cmp::min(self.contents.lines().count(), MAX) as u16; // inefficient + let area = Rect::new(self.position.col as u16, self.position.row as u16, 80, rows); + + // clear area + let background = cx.editor.theme.get("ui.popup"); + for y in area.top()..area.bottom() { + for x in area.left()..area.right() { + let cell = surface.get_mut(x, y); + cell.reset(); + // cell.symbol.clear(); + cell.set_style(background); + } + } + + // -- Render the contents: + + let style = Style::default().fg(Color::Rgb(164, 160, 232)); // lavender + + use tui::text::Text; + use tui::widgets::{Paragraph, Widget, Wrap}; + let contents = Text::from(self.contents.clone()); + let par = Paragraph::new(contents).wrap(Wrap { trim: false }); + + par.render(area, surface); + } +} -- cgit v1.2.3-70-g09d2