From 8985c58fd328cde512df0ac7bc577bd8a8c949a0 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sat, 19 Jun 2021 23:54:37 +0800 Subject: Add infobox --- helix-term/src/commands.rs | 105 ++++++++++++++++++++++++++++++++++---------- helix-term/src/keymap.rs | 16 +++---- helix-term/src/ui/editor.rs | 7 ++- helix-term/src/ui/info.rs | 24 ++++++++++ helix-term/src/ui/mod.rs | 1 + 5 files changed, 119 insertions(+), 34 deletions(-) create mode 100644 helix-term/src/ui/info.rs (limited to 'helix-term/src') diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index d198b803..106c58d1 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -16,6 +16,7 @@ use helix_core::{ use helix_view::{ document::{IndentStyle, Mode}, editor::Action, + info::Info, input::KeyEvent, keyboard::KeyCode, view::{View, PADDING}, @@ -33,6 +34,7 @@ use movement::Movement; use crate::{ compositor::{self, Component, Compositor}, + key, ui::{self, Picker, Popup, Prompt, PromptEvent}, }; @@ -3400,33 +3402,88 @@ fn select_register(cx: &mut Context) { }) } -fn space_mode(cx: &mut Context) { - cx.on_next_key(move |cx, event| { - if let KeyEvent { - code: KeyCode::Char(ch), - .. - } = event - { - // TODO: temporarily show SPC in the mode list - match ch { - 'f' => file_picker(cx), - 'b' => buffer_picker(cx), - 's' => symbol_picker(cx), - 'w' => window_mode(cx), - 'y' => yank_joined_to_clipboard(cx), - 'Y' => yank_main_selection_to_clipboard(cx), - 'p' => paste_clipboard_after(cx), - 'P' => paste_clipboard_before(cx), - 'R' => replace_selections_with_clipboard(cx), - // ' ' => toggle_alternate_buffer(cx), - // TODO: temporary since space mode took its old key - ' ' => keep_primary_selection(cx), - _ => (), - } +macro_rules! mode_info { + // TODO: how to use one expr for both pat and expr? + // TODO: how to use replaced function name as str at compile time? + // TODO: extend to support multiple keys, but first solve the other two + {$name:literal, $cx:expr, $($key:expr => $func:expr; $funcs:literal),+,} => { + mode_info! { + $name, $cx, + $($key; $key => $func; $funcs,)+ } - }) + }; + {$name:literal, $cx:expr, $($key:expr; $keyp:pat => $func:expr; $funcs:literal),+,} => { + $cx.editor.autoinfo = Some(Info::key( + $name, + vec![ + $( + (vec![$key], $funcs), + )+ + ], + )); + $cx.on_next_key(move |cx, event| { + match event { + $( + $keyp => $func(cx), + )+ + _ => {} + } + }) + } } +fn space_mode(cx: &mut Context) { + mode_info! { + "space mode", cx, + key!('f'); key!('f') => file_picker; "file picker", + key!('b'); key!('b') => buffer_picker; "buffer picker", + key!('s'); key!('s') => symbol_picker; "symbol picker", + key!('w'); key!('w') => window_mode; "window mode", + key!('y'); key!('y') => yank_joined_to_clipboard; "yank joined to clipboard", + key!('Y'); key!('Y') => yank_main_selection_to_clipboard; "yank main selection to clipboard", + key!('p'); key!('p') => paste_clipboard_after; "paste clipboard after", + key!('P'); key!('P') => paste_clipboard_before; "paste clipboard before", + key!('R'); key!('R') => replace_selections_with_clipboard; "replace selections with clipboard", + key!(' '); key!(' ') => keep_primary_selection; "keep primary selection", + } +} + +// TODO: generated, delete it later +// fn space_mode(cx: &mut Context) { +// cx.editor.autoinfo = Some(Info::key( +// "space", +// vec![ +// (vec![key!('f')], "file picker"), +// (vec![key!('b')], "buffer picker"), +// (vec![key!('s')], "symbol picker"), +// (vec![key!('w')], "window mode"), +// (vec![key!('y')], "yank joined to clipboard"), +// (vec![key!('Y')], "yank main selection to clipboard"), +// (vec![key!('p')], "paste clipboard after"), +// (vec![key!('P')], "paste clipboard before"), +// (vec![key!('R')], "replace selections with clipboard"), +// (vec![key!(' ')], "keep primary selection"), +// ], +// )); +// cx.on_next_key(move |cx, event| { +// match event { +// key!('f') => file_picker(cx), +// key!('b') => buffer_picker(cx), +// key!('s') => symbol_picker(cx), +// key!('w') => window_mode(cx), +// key!('y') => yank_joined_to_clipboard(cx), +// key!('Y') => yank_main_selection_to_clipboard(cx), +// key!('p') => paste_clipboard_after(cx), +// key!('P') => paste_clipboard_before(cx), +// key!('R') => replace_selections_with_clipboard(cx), +// // key!(' ') => toggle_alternate_buffer(cx), +// // TODO: temporary since space mode took its old key +// key!(' ') => keep_primary_selection(cx), +// _ => {} +// } +// }) +// } + fn view_mode(cx: &mut Context) { cx.on_next_key(move |cx, event| { if let KeyEvent { diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index 53588a2b..53143c71 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -105,14 +105,14 @@ use std::{ macro_rules! key { ($key:ident) => { KeyEvent { - code: KeyCode::$key, - modifiers: KeyModifiers::NONE, + code: helix_view::keyboard::KeyCode::$key, + modifiers: helix_view::keyboard::KeyModifiers::NONE, } }; ($($ch:tt)*) => { KeyEvent { - code: KeyCode::Char($($ch)*), - modifiers: KeyModifiers::NONE, + code: helix_view::keyboard::KeyCode::Char($($ch)*), + modifiers: helix_view::keyboard::KeyModifiers::NONE, } }; } @@ -120,8 +120,8 @@ macro_rules! key { macro_rules! ctrl { ($($ch:tt)*) => { KeyEvent { - code: KeyCode::Char($($ch)*), - modifiers: KeyModifiers::CONTROL, + code: helix_view::keyboard::KeyCode::Char($($ch)*), + modifiers: helix_view::keyboard::KeyModifiers::CONTROL, } }; } @@ -129,8 +129,8 @@ macro_rules! ctrl { macro_rules! alt { ($($ch:tt)*) => { KeyEvent { - code: KeyCode::Char($($ch)*), - modifiers: KeyModifiers::ALT, + code: helix_view::keyboard::KeyCode::Char($($ch)*), + modifiers: helix_view::keyboard::KeyModifiers::ALT, } }; } diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 14c34493..8b7c92de 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -717,6 +717,10 @@ impl Component for EditorView { self.render_view(doc, view, area, surface, &cx.editor.theme, is_focused); } + if let Some(info) = std::mem::take(&mut cx.editor.autoinfo) { + info.render(area, surface, cx); + } + // render status msg if let Some((status_msg, severity)) = &cx.editor.status_msg { use helix_view::editor::Severity; @@ -735,8 +739,7 @@ impl Component for EditorView { } if let Some(completion) = &self.completion { - completion.render(area, surface, cx) - // render completion here + completion.render(area, surface, cx); } } diff --git a/helix-term/src/ui/info.rs b/helix-term/src/ui/info.rs new file mode 100644 index 00000000..085a2d9b --- /dev/null +++ b/helix-term/src/ui/info.rs @@ -0,0 +1,24 @@ +use crate::compositor::{Component, Context}; +use helix_view::graphics::{Margin, Rect, Style}; +use helix_view::info::Info; +use tui::buffer::Buffer as Surface; +use tui::widgets::{Block, Borders, Widget}; + +impl Component for Info { + fn render(&self, viewport: Rect, surface: &mut Surface, cx: &mut Context) { + let block = Block::default().title(self.title).borders(Borders::ALL); + let Info { width, height, .. } = self; + let (w, h) = (*width + 2, *height + 2); + // -2 to subtract command line + statusline. a bit of a hack, because of splits. + let area = Rect::new(viewport.width - w, viewport.height - h - 2, w, h); + let margin = Margin { + vertical: 1, + horizontal: 1, + }; + let Rect { x, y, .. } = area.inner(&margin); + for (y, line) in (y..).zip(self.text.lines()) { + surface.set_string(x, y, line, Style::default()); + } + block.render(area, surface); + } +} diff --git a/helix-term/src/ui/mod.rs b/helix-term/src/ui/mod.rs index 7111c968..288d3d2e 100644 --- a/helix-term/src/ui/mod.rs +++ b/helix-term/src/ui/mod.rs @@ -1,5 +1,6 @@ mod completion; mod editor; +mod info; mod markdown; mod menu; mod picker; -- cgit v1.2.3-70-g09d2