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-view/src/info.rs | 51 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 helix-view/src/info.rs (limited to 'helix-view/src/info.rs') diff --git a/helix-view/src/info.rs b/helix-view/src/info.rs new file mode 100644 index 00000000..eef8d3a1 --- /dev/null +++ b/helix-view/src/info.rs @@ -0,0 +1,51 @@ +use crate::input::KeyEvent; +use std::fmt::Write; +use unicode_width::UnicodeWidthStr; + +#[derive(Debug)] +/// Info box used in editor. Rendering logic will be in other crate. +pub struct Info { + /// Title kept as static str for now. + pub title: &'static str, + /// Text body, should contains newline. + pub text: String, + /// Body width. + pub width: u16, + /// Body height. + pub height: u16, +} + +impl Info { + pub fn key(title: &'static str, body: Vec<(Vec, &'static str)>) -> Info { + let keymaps_width: u16 = body + .iter() + .map(|r| r.0.iter().map(|e| e.width() as u16 + 2).sum::() - 2) + .max() + .unwrap(); + let mut text = String::new(); + let mut width = 0; + let height = body.len() as u16; + for (mut keyevents, desc) in body { + let keyevent = keyevents.remove(0); + let mut left = keymaps_width - keyevent.width() as u16; + write!(text, "{}", keyevent).ok(); + for keyevent in keyevents { + write!(text, ", {}", keyevent).ok(); + left -= 2 + keyevent.width() as u16; + } + for _ in 0..left { + text.push(' '); + } + if keymaps_width + 2 + (desc.width() as u16) > width { + width = keymaps_width + 2 + desc.width() as u16; + } + writeln!(text, " {}", &desc).ok(); + } + Info { + title, + text, + width, + height, + } + } +} -- cgit v1.2.3-70-g09d2 From 9effe71b7d2133f18545d182cef384ea3fd1c0ff Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Wed, 30 Jun 2021 00:17:16 +0800 Subject: Apply suggestions from blaz for infobox --- Cargo.lock | 2 -- helix-term/src/ui/info.rs | 6 +----- helix-tui/Cargo.toml | 1 - helix-tui/src/backend/test.rs | 2 +- helix-tui/src/buffer.rs | 2 +- helix-tui/src/text.rs | 2 +- helix-tui/src/widgets/paragraph.rs | 2 +- helix-tui/src/widgets/reflow.rs | 2 +- helix-tui/src/widgets/table.rs | 2 +- helix-view/Cargo.toml | 1 - helix-view/src/info.rs | 2 +- helix-view/src/input.rs | 5 +++-- 12 files changed, 11 insertions(+), 18 deletions(-) (limited to 'helix-view/src/info.rs') diff --git a/Cargo.lock b/Cargo.lock index 59eb894e..2cd202f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -396,7 +396,6 @@ dependencies = [ "helix-view", "serde", "unicode-segmentation", - "unicode-width", ] [[package]] @@ -419,7 +418,6 @@ dependencies = [ "slotmap", "tokio", "toml", - "unicode-width", "url", "which", ] diff --git a/helix-term/src/ui/info.rs b/helix-term/src/ui/info.rs index 085a2d9b..c5709356 100644 --- a/helix-term/src/ui/info.rs +++ b/helix-term/src/ui/info.rs @@ -11,11 +11,7 @@ impl Component for Info { 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); + let Rect { x, y, .. } = block.inner(area); for (y, line) in (y..).zip(self.text.lines()) { surface.set_string(x, y, line, Style::default()); } diff --git a/helix-tui/Cargo.toml b/helix-tui/Cargo.toml index dde2eafe..7f98144c 100644 --- a/helix-tui/Cargo.toml +++ b/helix-tui/Cargo.toml @@ -19,7 +19,6 @@ default = ["crossterm"] bitflags = "1.0" cassowary = "0.3" unicode-segmentation = "1.2" -unicode-width = "0.1" crossterm = { version = "0.20", optional = true } serde = { version = "1", "optional" = true, features = ["derive"]} helix-view = { version = "0.3", path = "../helix-view", features = ["term"] } diff --git a/helix-tui/src/backend/test.rs b/helix-tui/src/backend/test.rs index a03bcd8e..3f56b49c 100644 --- a/helix-tui/src/backend/test.rs +++ b/helix-tui/src/backend/test.rs @@ -2,9 +2,9 @@ use crate::{ backend::Backend, buffer::{Buffer, Cell}, }; +use helix_core::unicode::width::UnicodeWidthStr; use helix_view::graphics::{CursorKind, Rect}; use std::{fmt::Write, io}; -use unicode_width::UnicodeWidthStr; /// A backend used for the integration tests. #[derive(Debug)] diff --git a/helix-tui/src/buffer.rs b/helix-tui/src/buffer.rs index 3a7ad144..377e3e39 100644 --- a/helix-tui/src/buffer.rs +++ b/helix-tui/src/buffer.rs @@ -1,7 +1,7 @@ use crate::text::{Span, Spans}; +use helix_core::unicode::width::UnicodeWidthStr; use std::cmp::min; use unicode_segmentation::UnicodeSegmentation; -use unicode_width::UnicodeWidthStr; use helix_view::graphics::{Color, Modifier, Rect, Style}; diff --git a/helix-tui/src/text.rs b/helix-tui/src/text.rs index 4af6b09d..b8e52479 100644 --- a/helix-tui/src/text.rs +++ b/helix-tui/src/text.rs @@ -47,10 +47,10 @@ //! ]); //! ``` use helix_core::line_ending::str_is_line_ending; +use helix_core::unicode::width::UnicodeWidthStr; use helix_view::graphics::Style; use std::borrow::Cow; use unicode_segmentation::UnicodeSegmentation; -use unicode_width::UnicodeWidthStr; /// A grapheme associated to a style. #[derive(Debug, Clone, PartialEq)] diff --git a/helix-tui/src/widgets/paragraph.rs b/helix-tui/src/widgets/paragraph.rs index bdfb5b9a..fee35d25 100644 --- a/helix-tui/src/widgets/paragraph.rs +++ b/helix-tui/src/widgets/paragraph.rs @@ -7,9 +7,9 @@ use crate::{ Block, Widget, }, }; +use helix_core::unicode::width::UnicodeWidthStr; use helix_view::graphics::{Rect, Style}; use std::iter; -use unicode_width::UnicodeWidthStr; fn get_line_offset(line_width: u16, text_area_width: u16, alignment: Alignment) -> u16 { match alignment { diff --git a/helix-tui/src/widgets/reflow.rs b/helix-tui/src/widgets/reflow.rs index ae561a4f..21847783 100644 --- a/helix-tui/src/widgets/reflow.rs +++ b/helix-tui/src/widgets/reflow.rs @@ -1,7 +1,7 @@ use crate::text::StyledGrapheme; use helix_core::line_ending::str_is_line_ending; +use helix_core::unicode::width::UnicodeWidthStr; use unicode_segmentation::UnicodeSegmentation; -use unicode_width::UnicodeWidthStr; const NBSP: &str = "\u{00a0}"; diff --git a/helix-tui/src/widgets/table.rs b/helix-tui/src/widgets/table.rs index ee5147b7..1ee4286a 100644 --- a/helix-tui/src/widgets/table.rs +++ b/helix-tui/src/widgets/table.rs @@ -9,9 +9,9 @@ use cassowary::{ WeightedRelation::*, {Expression, Solver}, }; +use helix_core::unicode::width::UnicodeWidthStr; use helix_view::graphics::{Rect, Style}; use std::collections::HashMap; -use unicode_width::UnicodeWidthStr; /// A [`Cell`] contains the [`Text`] to be displayed in a [`Row`] of a [`Table`]. /// diff --git a/helix-view/Cargo.toml b/helix-view/Cargo.toml index b6816d71..cb2032de 100644 --- a/helix-view/Cargo.toml +++ b/helix-view/Cargo.toml @@ -31,7 +31,6 @@ slotmap = "1" encoding_rs = "0.8" chardetng = "0.1" -unicode-width = "0.1" serde = { version = "1.0", features = ["derive"] } toml = "0.5" diff --git a/helix-view/src/info.rs b/helix-view/src/info.rs index eef8d3a1..0eaab783 100644 --- a/helix-view/src/info.rs +++ b/helix-view/src/info.rs @@ -1,6 +1,6 @@ use crate::input::KeyEvent; +use helix_core::unicode::width::UnicodeWidthStr; use std::fmt::Write; -use unicode_width::UnicodeWidthStr; #[derive(Debug)] /// Info box used in editor. Rendering logic will be in other crate. diff --git a/helix-view/src/input.rs b/helix-view/src/input.rs index 6e8292e9..2847bb69 100644 --- a/helix-view/src/input.rs +++ b/helix-view/src/input.rs @@ -1,5 +1,6 @@ //! Input event handling, currently backed by crossterm. use anyhow::{anyhow, Error}; +use helix_core::unicode::width::UnicodeWidthStr; use serde::de::{self, Deserialize, Deserializer}; use std::fmt; @@ -90,9 +91,9 @@ impl fmt::Display for KeyEvent { } } -impl unicode_width::UnicodeWidthStr for KeyEvent { +impl UnicodeWidthStr for KeyEvent { fn width(&self) -> usize { - use unicode_width::UnicodeWidthChar; + use helix_core::unicode::width::UnicodeWidthChar; let mut width = match self.code { KeyCode::Backspace => keys::BACKSPACE.len(), KeyCode::Enter => keys::ENTER.len(), -- cgit v1.2.3-70-g09d2 From 5977b07e197cc6ef9051dd34a28b9fe28e01e966 Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Fri, 2 Jul 2021 09:46:28 +0800 Subject: Reduce calculation and improve pattern in infobox - switch to use static OnceCell to calculate Info once - pass Vec<(&[KeyEvent], &str)> rather than Vec<(Vec, &str)> - expr -> tt to allow using | as separator, make it more like match --- helix-term/src/commands.rs | 21 ++++++++++----------- helix-term/src/keymap.rs | 7 ++----- helix-term/src/ui/info.rs | 2 +- helix-view/src/editor.rs | 2 +- helix-view/src/info.rs | 8 ++++---- 5 files changed, 18 insertions(+), 22 deletions(-) (limited to 'helix-view/src/info.rs') diff --git a/helix-term/src/commands.rs b/helix-term/src/commands.rs index b6f3c11f..351ec1fb 100644 --- a/helix-term/src/commands.rs +++ b/helix-term/src/commands.rs @@ -34,7 +34,6 @@ use movement::Movement; use crate::{ compositor::{self, Component, Compositor}, - key, ui::{self, Picker, Popup, Prompt, PromptEvent}, }; @@ -48,7 +47,7 @@ use std::{ path::{Path, PathBuf}, }; -use once_cell::sync::Lazy; +use once_cell::sync::{Lazy, OnceCell}; use serde::de::{self, Deserialize, Deserializer}; pub struct Context<'a> { @@ -3414,13 +3413,11 @@ fn select_register(cx: &mut Context) { } 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 + // TODO: reuse $mode for $stat (@join $first:expr $(,$rest:expr)*) => { concat!($first, $(", ", $rest),*) }; - {$mode:ident, $name:literal, $(#[doc = $desc:literal] $($key:expr),+ => $func:expr),+,} => { + {$mode:ident, $stat:ident, $name:literal, $(#[doc = $desc:literal] $($key:tt)|+ => $func:expr),+,} => { #[doc = $name] #[doc = ""] #[doc = ""] @@ -3439,12 +3436,14 @@ macro_rules! mode_info { )+ #[doc = "
keydesc
"] pub fn $mode(cx: &mut Context) { - cx.editor.autoinfo = Some(Info::key( + static $stat: OnceCell = OnceCell::new(); + cx.editor.autoinfo = Some($stat.get_or_init(|| Info::key( $name, - vec![$((vec![$($key.parse().unwrap()),+], $desc)),+], - )); + vec![$((&[$($key.parse().unwrap()),+], $desc)),+], + ))); use helix_core::hashmap; - let mut map = hashmap! { + // TODO: try and convert this to match later + let map = hashmap! { $($($key.parse::().unwrap() => $func as for<'r, 's> fn(&'r mut Context<'s>)),+),* }; cx.on_next_key_mode(map); @@ -3453,7 +3452,7 @@ macro_rules! mode_info { } mode_info! { - space_mode, "space mode", + space_mode, SPACE_MODE, "space mode", /// file picker "f" => file_picker, /// buffer picker diff --git a/helix-term/src/keymap.rs b/helix-term/src/keymap.rs index ef4a2138..3cd540ea 100644 --- a/helix-term/src/keymap.rs +++ b/helix-term/src/keymap.rs @@ -1,11 +1,7 @@ pub use crate::commands::Command; use crate::config::Config; use helix_core::hashmap; -use helix_view::{ - document::Mode, - input::KeyEvent, - keyboard::{KeyCode, KeyModifiers}, -}; +use helix_view::{document::Mode, input::KeyEvent}; use serde::Deserialize; use std::{ collections::HashMap, @@ -352,6 +348,7 @@ pub fn merge_keys(mut config: Config) -> Config { #[test] fn merge_partial_keys() { + use helix_view::keyboard::{KeyCode, KeyModifiers}; let config = Config { keys: Keymaps(hashmap! { Mode::Normal => hashmap! { diff --git a/helix-term/src/ui/info.rs b/helix-term/src/ui/info.rs index 87c2c213..c6f8db43 100644 --- a/helix-term/src/ui/info.rs +++ b/helix-term/src/ui/info.rs @@ -1,5 +1,5 @@ use crate::compositor::{Component, Context}; -use helix_view::graphics::{Margin, Rect, Style}; +use helix_view::graphics::Rect; use helix_view::info::Info; use tui::buffer::Buffer as Surface; use tui::widgets::{Block, Borders, Widget}; diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index b006a124..4f01cce4 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -33,7 +33,7 @@ pub struct Editor { pub syn_loader: Arc, pub theme_loader: Arc, - pub autoinfo: Option, + pub autoinfo: Option<&'static Info>, pub status_msg: Option<(String, Severity)>, } diff --git a/helix-view/src/info.rs b/helix-view/src/info.rs index 0eaab783..92c10351 100644 --- a/helix-view/src/info.rs +++ b/helix-view/src/info.rs @@ -16,7 +16,7 @@ pub struct Info { } impl Info { - pub fn key(title: &'static str, body: Vec<(Vec, &'static str)>) -> Info { + pub fn key(title: &'static str, body: Vec<(&[KeyEvent], &'static str)>) -> Info { let keymaps_width: u16 = body .iter() .map(|r| r.0.iter().map(|e| e.width() as u16 + 2).sum::() - 2) @@ -25,11 +25,11 @@ impl Info { let mut text = String::new(); let mut width = 0; let height = body.len() as u16; - for (mut keyevents, desc) in body { - let keyevent = keyevents.remove(0); + for (keyevents, desc) in body { + let keyevent = keyevents[0]; let mut left = keymaps_width - keyevent.width() as u16; write!(text, "{}", keyevent).ok(); - for keyevent in keyevents { + for keyevent in &keyevents[1..] { write!(text, ", {}", keyevent).ok(); left -= 2 + keyevent.width() as u16; } -- cgit v1.2.3-70-g09d2 From 916362d3a97ddc1b4a630f7d7ba5ae5dc405c21a Mon Sep 17 00:00:00 2001 From: Ivan Tham Date: Sun, 4 Jul 2021 00:12:02 +0800 Subject: Info box add horizontal padding --- helix-view/src/info.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'helix-view/src/info.rs') diff --git a/helix-view/src/info.rs b/helix-view/src/info.rs index 92c10351..f3df50fe 100644 --- a/helix-view/src/info.rs +++ b/helix-view/src/info.rs @@ -17,6 +17,7 @@ pub struct Info { impl Info { pub fn key(title: &'static str, body: Vec<(&[KeyEvent], &'static str)>) -> Info { + let (lpad, mpad, rpad) = (1, 2, 1); let keymaps_width: u16 = body .iter() .map(|r| r.0.iter().map(|e| e.width() as u16 + 2).sum::() - 2) @@ -28,18 +29,23 @@ impl Info { for (keyevents, desc) in body { let keyevent = keyevents[0]; let mut left = keymaps_width - keyevent.width() as u16; + for _ in 0..lpad { + text.push(' '); + } write!(text, "{}", keyevent).ok(); for keyevent in &keyevents[1..] { write!(text, ", {}", keyevent).ok(); left -= 2 + keyevent.width() as u16; } - for _ in 0..left { + for _ in 0..left + mpad { text.push(' '); } - if keymaps_width + 2 + (desc.width() as u16) > width { - width = keymaps_width + 2 + desc.width() as u16; + let desc = desc.trim(); + let w = lpad + keymaps_width + mpad + (desc.width() as u16) + rpad; + if w > width { + width = w; } - writeln!(text, " {}", &desc).ok(); + writeln!(text, "{}", desc).ok(); } Info { title, -- cgit v1.2.3-70-g09d2