aboutsummaryrefslogtreecommitdiff
path: root/helix-term/src/ui
diff options
context:
space:
mode:
authorBlaž Hrastnik2021-02-25 09:07:47 +0000
committerBlaž Hrastnik2021-02-25 09:07:47 +0000
commit7162632eb739557ededaee902b23e48a577817b4 (patch)
tree22dbfc57f04e72e2f7dfbbcc2f3dee42bf00cd0a /helix-term/src/ui
parent8289bd1cb0cf34d26a9f452850081799311e3f45 (diff)
lsp: Hover documentation draft.
Diffstat (limited to 'helix-term/src/ui')
-rw-r--r--helix-term/src/ui/editor.rs7
-rw-r--r--helix-term/src/ui/mod.rs2
-rw-r--r--helix-term/src/ui/popup.rs95
3 files changed, 100 insertions, 4 deletions
diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs
index af9d0414..b071292c 100644
--- a/helix-term/src/ui/editor.rs
+++ b/helix-term/src/ui/editor.rs
@@ -100,6 +100,7 @@ impl EditorView {
let mut spans = Vec::new();
let mut visual_x = 0;
let mut line = 0u16;
+ let text = view.doc.text();
'outer: for event in highlights {
match event.unwrap() {
@@ -113,7 +114,6 @@ impl EditorView {
// TODO: filter out spans out of viewport for now..
// TODO: do these before iterating
- let text = view.doc.text();
let start = text.byte_to_char(start);
let end = text.byte_to_char(end);
@@ -160,8 +160,7 @@ impl EditorView {
let grapheme = Cow::from(grapheme);
let width = grapheme_width(&grapheme) as u16;
- // ugh, improve with a traverse method
- // or interleave highlight spans with selection and diagnostic spans
+ // ugh,interleave highlight spans with diagnostic spans
let is_diagnostic = view.doc.diagnostics.iter().any(|diagnostic| {
diagnostic.range.0 <= char_index && diagnostic.range.1 > char_index
});
@@ -191,12 +190,12 @@ impl EditorView {
// render selections
if is_focused {
- let text = view.doc.text().slice(..);
let screen = {
let start = text.line_to_char(view.first_line);
let end = text.line_to_char(last_line + 1);
Range::new(start, end)
};
+ let text = text.slice(..);
let cursor_style = Style::default().bg(Color::Rgb(255, 255, 255));
// cedar
diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs
index e1899144..ea1d22ab 100644
--- a/helix-term/src/ui/mod.rs
+++ b/helix-term/src/ui/mod.rs
@@ -1,11 +1,13 @@
mod editor;
mod menu;
mod picker;
+mod popup;
mod prompt;
pub use editor::EditorView;
pub use menu::Menu;
pub use picker::Picker;
+pub use popup::Popup;
pub use prompt::{Prompt, PromptEvent};
pub use tui::layout::Rect;
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);
+ }
+}