mirror of
https://github.com/helix-editor/helix.git
synced 2024-11-22 09:26:19 +04:00
Implement a separate RenderContext
This commit is contained in:
parent
7622643117
commit
3c0e11d69e
@ -209,7 +209,6 @@ fn render(&mut self) {
|
|||||||
let mut cx = crate::compositor::Context {
|
let mut cx = crate::compositor::Context {
|
||||||
editor: &mut self.editor,
|
editor: &mut self.editor,
|
||||||
jobs: &mut self.jobs,
|
jobs: &mut self.jobs,
|
||||||
scroll: None,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
self.compositor.render(&mut cx);
|
self.compositor.render(&mut cx);
|
||||||
@ -358,7 +357,6 @@ pub fn handle_idle_timeout(&mut self) {
|
|||||||
let mut cx = crate::compositor::Context {
|
let mut cx = crate::compositor::Context {
|
||||||
editor: &mut self.editor,
|
editor: &mut self.editor,
|
||||||
jobs: &mut self.jobs,
|
jobs: &mut self.jobs,
|
||||||
scroll: None,
|
|
||||||
};
|
};
|
||||||
if let EventResult::Consumed(_) = editor_view.handle_idle_timeout(&mut cx) {
|
if let EventResult::Consumed(_) = editor_view.handle_idle_timeout(&mut cx) {
|
||||||
self.render();
|
self.render();
|
||||||
@ -369,7 +367,6 @@ pub fn handle_terminal_events(&mut self, event: Option<Result<Event, crossterm::
|
|||||||
let mut cx = crate::compositor::Context {
|
let mut cx = crate::compositor::Context {
|
||||||
editor: &mut self.editor,
|
editor: &mut self.editor,
|
||||||
jobs: &mut self.jobs,
|
jobs: &mut self.jobs,
|
||||||
scroll: None,
|
|
||||||
};
|
};
|
||||||
// Handle key events
|
// Handle key events
|
||||||
let should_redraw = match event {
|
let should_redraw = match event {
|
||||||
|
@ -164,7 +164,6 @@ pub fn execute(&self, cx: &mut Context) {
|
|||||||
let mut cx = compositor::Context {
|
let mut cx = compositor::Context {
|
||||||
editor: cx.editor,
|
editor: cx.editor,
|
||||||
jobs: cx.jobs,
|
jobs: cx.jobs,
|
||||||
scroll: None,
|
|
||||||
};
|
};
|
||||||
if let Err(e) = (command.fun)(&mut cx, &args[..], PromptEvent::Validate) {
|
if let Err(e) = (command.fun)(&mut cx, &args[..], PromptEvent::Validate) {
|
||||||
cx.editor.set_error(format!("{}", e));
|
cx.editor.set_error(format!("{}", e));
|
||||||
|
@ -21,10 +21,14 @@ pub enum EventResult {
|
|||||||
|
|
||||||
pub struct Context<'a> {
|
pub struct Context<'a> {
|
||||||
pub editor: &'a mut Editor,
|
pub editor: &'a mut Editor,
|
||||||
pub scroll: Option<usize>,
|
|
||||||
pub jobs: &'a mut Jobs,
|
pub jobs: &'a mut Jobs,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct RenderContext<'a> {
|
||||||
|
pub editor: &'a Editor,
|
||||||
|
pub scroll: Option<usize>,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait Component: Any + AnyComponent {
|
pub trait Component: Any + AnyComponent {
|
||||||
/// Process input events, return true if handled.
|
/// Process input events, return true if handled.
|
||||||
fn handle_event(&mut self, _event: Event, _ctx: &mut Context) -> EventResult {
|
fn handle_event(&mut self, _event: Event, _ctx: &mut Context) -> EventResult {
|
||||||
@ -38,7 +42,7 @@ fn should_update(&self) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Render the component onto the provided surface.
|
/// Render the component onto the provided surface.
|
||||||
fn render(&mut self, area: Rect, frame: &mut Surface, ctx: &mut Context);
|
fn render(&mut self, area: Rect, frame: &mut Surface, ctx: &mut RenderContext);
|
||||||
|
|
||||||
/// Get cursor position and cursor kind.
|
/// Get cursor position and cursor kind.
|
||||||
fn cursor(&self, _area: Rect, _ctx: &Editor) -> (Option<Position>, CursorKind) {
|
fn cursor(&self, _area: Rect, _ctx: &Editor) -> (Option<Position>, CursorKind) {
|
||||||
@ -169,18 +173,25 @@ pub fn handle_event(&mut self, event: Event, cx: &mut Context) -> bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn render(&mut self, cx: &mut Context) {
|
pub fn render(&mut self, cx: &mut Context) {
|
||||||
self.terminal
|
let area = self
|
||||||
|
.terminal
|
||||||
.autoresize()
|
.autoresize()
|
||||||
.expect("Unable to determine terminal size");
|
.expect("Unable to determine terminal size");
|
||||||
|
|
||||||
// TODO: need to recalculate view tree if necessary
|
// if the terminal size suddenly changed, we need to trigger a resize
|
||||||
|
cx.editor.resize(area.clip_bottom(1)); // -1 from bottom for commandline
|
||||||
|
|
||||||
let surface = self.terminal.current_buffer_mut();
|
let surface = self.terminal.current_buffer_mut();
|
||||||
|
|
||||||
let area = *surface.area();
|
// let area = *surface.area();
|
||||||
|
|
||||||
|
let mut cx = RenderContext {
|
||||||
|
editor: cx.editor,
|
||||||
|
scroll: None,
|
||||||
|
};
|
||||||
|
|
||||||
for layer in &mut self.layers {
|
for layer in &mut self.layers {
|
||||||
layer.render(area, surface, cx);
|
layer.render(area, surface, &mut cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (pos, kind) = self.cursor(area, cx.editor);
|
let (pos, kind) = self.cursor(area, cx.editor);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::compositor::{Component, Context, EventResult};
|
use crate::compositor::{Component, Context, EventResult, RenderContext};
|
||||||
use crossterm::event::{Event, KeyCode, KeyEvent};
|
use crossterm::event::{Event, KeyCode, KeyEvent};
|
||||||
use helix_view::editor::CompleteAction;
|
use helix_view::editor::CompleteAction;
|
||||||
use tui::buffer::Buffer as Surface;
|
use tui::buffer::Buffer as Surface;
|
||||||
@ -301,7 +301,7 @@ fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
|
|||||||
self.popup.required_size(viewport)
|
self.popup.required_size(viewport)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
self.popup.render(area, surface, cx);
|
self.popup.render(area, surface, cx);
|
||||||
|
|
||||||
// if we have a selection, render a markdown popup on top/below with info
|
// if we have a selection, render a markdown popup on top/below with info
|
||||||
@ -311,7 +311,7 @@ fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
|||||||
// ---
|
// ---
|
||||||
// option.documentation
|
// option.documentation
|
||||||
|
|
||||||
let (view, doc) = current!(cx.editor);
|
let (view, doc) = current_ref!(cx.editor);
|
||||||
let language = doc
|
let language = doc
|
||||||
.language()
|
.language()
|
||||||
.and_then(|scope| scope.strip_prefix("source."))
|
.and_then(|scope| scope.strip_prefix("source."))
|
||||||
@ -369,7 +369,7 @@ fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
|||||||
None => return,
|
None => return,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (popup_x, popup_y) = self.popup.get_rel_position(area, cx);
|
let (popup_x, popup_y) = self.popup.get_rel_position(area, cx.editor);
|
||||||
let (popup_width, _popup_height) = self.popup.get_size();
|
let (popup_width, _popup_height) = self.popup.get_size();
|
||||||
let mut width = area
|
let mut width = area
|
||||||
.width
|
.width
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
commands,
|
commands,
|
||||||
compositor::{Component, Context, EventResult},
|
compositor::{Component, Context, EventResult, RenderContext},
|
||||||
key,
|
key,
|
||||||
keymap::{KeymapResult, Keymaps},
|
keymap::{KeymapResult, Keymaps},
|
||||||
ui::{Completion, ProgressSpinners},
|
ui::{Completion, ProgressSpinners},
|
||||||
@ -1201,7 +1201,6 @@ fn handle_event(
|
|||||||
let mut cx = Context {
|
let mut cx = Context {
|
||||||
editor: cx.editor,
|
editor: cx.editor,
|
||||||
jobs: cx.jobs,
|
jobs: cx.jobs,
|
||||||
scroll: None,
|
|
||||||
};
|
};
|
||||||
let res = completion.handle_event(event, &mut cx);
|
let res = completion.handle_event(event, &mut cx);
|
||||||
|
|
||||||
@ -1288,12 +1287,10 @@ fn handle_event(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
// clear with background color
|
// clear with background color
|
||||||
surface.set_style(area, cx.editor.theme.get("ui.background"));
|
surface.set_style(area, cx.editor.theme.get("ui.background"));
|
||||||
let config = cx.editor.config();
|
let config = cx.editor.config();
|
||||||
// if the terminal size suddenly changed, we need to trigger a resize
|
|
||||||
cx.editor.resize(area.clip_bottom(1)); // -1 from bottom for commandline
|
|
||||||
|
|
||||||
for (view, is_focused) in cx.editor.tree.views() {
|
for (view, is_focused) in cx.editor.tree.views() {
|
||||||
let doc = cx.editor.document(view.doc).unwrap();
|
let doc = cx.editor.document(view.doc).unwrap();
|
||||||
@ -1301,9 +1298,10 @@ fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if config.auto_info {
|
if config.auto_info {
|
||||||
if let Some(mut info) = cx.editor.autoinfo.take() {
|
// TODO: drop &mut self on render
|
||||||
|
if let Some(mut info) = cx.editor.autoinfo.clone() {
|
||||||
info.render(area, surface, cx);
|
info.render(area, surface, cx);
|
||||||
cx.editor.autoinfo = Some(info)
|
// cx.editor.autoinfo = Some(info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
use crate::compositor::{Component, Context};
|
use crate::compositor::{Component, RenderContext};
|
||||||
use helix_view::graphics::{Margin, Rect};
|
use helix_view::graphics::{Margin, Rect};
|
||||||
use helix_view::info::Info;
|
use helix_view::info::Info;
|
||||||
use tui::buffer::Buffer as Surface;
|
use tui::buffer::Buffer as Surface;
|
||||||
use tui::widgets::{Block, Borders, Paragraph, Widget};
|
use tui::widgets::{Block, Borders, Paragraph, Widget};
|
||||||
|
|
||||||
impl Component for Info {
|
impl Component for Info {
|
||||||
fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut Context) {
|
fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
let text_style = cx.editor.theme.get("ui.text.info");
|
let text_style = cx.editor.theme.get("ui.text.info");
|
||||||
let popup_style = cx.editor.theme.get("ui.popup.info");
|
let popup_style = cx.editor.theme.get("ui.popup.info");
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::compositor::{Component, Context};
|
use crate::compositor::{Component, RenderContext};
|
||||||
use tui::{
|
use tui::{
|
||||||
buffer::Buffer as Surface,
|
buffer::Buffer as Surface,
|
||||||
text::{Span, Spans, Text},
|
text::{Span, Spans, Text},
|
||||||
@ -259,7 +259,7 @@ fn parse(&self, theme: Option<&Theme>) -> tui::text::Text<'_> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Markdown {
|
impl Component for Markdown {
|
||||||
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
use tui::widgets::{Paragraph, Widget, Wrap};
|
use tui::widgets::{Paragraph, Widget, Wrap};
|
||||||
|
|
||||||
let text = self.parse(Some(&cx.editor.theme));
|
let text = self.parse(Some(&cx.editor.theme));
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
compositor::{Callback, Component, Compositor, Context, EventResult},
|
compositor::{Callback, Component, Compositor, Context, EventResult, RenderContext},
|
||||||
ctrl, key, shift,
|
ctrl, key, shift,
|
||||||
};
|
};
|
||||||
use crossterm::event::Event;
|
use crossterm::event::Event;
|
||||||
@ -265,7 +265,7 @@ fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
|
|||||||
Some(self.size)
|
Some(self.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
let theme = &cx.editor.theme;
|
let theme = &cx.editor.theme;
|
||||||
let style = theme
|
let style = theme
|
||||||
.try_get("ui.menu")
|
.try_get("ui.menu")
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
};
|
};
|
||||||
use tui::buffer::Buffer;
|
use tui::buffer::Buffer;
|
||||||
|
|
||||||
use crate::compositor::{Component, Context, EventResult};
|
use crate::compositor::{Component, Context, EventResult, RenderContext};
|
||||||
|
|
||||||
/// Contains a component placed in the center of the parent component
|
/// Contains a component placed in the center of the parent component
|
||||||
pub struct Overlay<T> {
|
pub struct Overlay<T> {
|
||||||
@ -44,7 +44,7 @@ fn mul_and_cast(size: u16, factor: u8) -> u16 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Component + 'static> Component for Overlay<T> {
|
impl<T: Component + 'static> Component for Overlay<T> {
|
||||||
fn render(&mut self, area: Rect, frame: &mut Buffer, ctx: &mut Context) {
|
fn render(&mut self, area: Rect, frame: &mut Buffer, ctx: &mut RenderContext<'_>) {
|
||||||
let dimensions = (self.calc_child_size)(area);
|
let dimensions = (self.calc_child_size)(area);
|
||||||
self.content.render(dimensions, frame, ctx)
|
self.content.render(dimensions, frame, ctx)
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
compositor::{Component, Compositor, Context, EventResult},
|
compositor::{Component, Compositor, Context, EventResult, RenderContext},
|
||||||
ctrl, key, shift,
|
ctrl, key, shift,
|
||||||
ui::{self, EditorView},
|
ui::{self, EditorView},
|
||||||
};
|
};
|
||||||
@ -164,7 +164,7 @@ fn get_preview<'picker, 'editor>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: 'static> Component for FilePicker<T> {
|
impl<T: 'static> Component for FilePicker<T> {
|
||||||
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
// +---------+ +---------+
|
// +---------+ +---------+
|
||||||
// |prompt | |preview |
|
// |prompt | |preview |
|
||||||
// +---------+ | |
|
// +---------+ | |
|
||||||
@ -552,7 +552,7 @@ fn handle_event(&mut self, event: Event, cx: &mut Context) -> EventResult {
|
|||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
let text_style = cx.editor.theme.get("ui.text");
|
let text_style = cx.editor.theme.get("ui.text");
|
||||||
let selected = cx.editor.theme.get("ui.text.focus");
|
let selected = cx.editor.theme.get("ui.text.focus");
|
||||||
let highlighted = cx.editor.theme.get("special").add_modifier(Modifier::BOLD);
|
let highlighted = cx.editor.theme.get("special").add_modifier(Modifier::BOLD);
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
compositor::{Callback, Component, Context, EventResult},
|
compositor::{Callback, Component, Context, EventResult, RenderContext},
|
||||||
ctrl, key,
|
ctrl, key,
|
||||||
};
|
};
|
||||||
use crossterm::event::Event;
|
use crossterm::event::Event;
|
||||||
use tui::buffer::Buffer as Surface;
|
use tui::buffer::Buffer as Surface;
|
||||||
|
|
||||||
use helix_core::Position;
|
use helix_core::Position;
|
||||||
use helix_view::graphics::{Margin, Rect};
|
use helix_view::{
|
||||||
|
graphics::{Margin, Rect},
|
||||||
|
Editor,
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: share logic with Menu, it's essentially Popup(render_fn), but render fn needs to return
|
// TODO: share logic with Menu, it's essentially Popup(render_fn), but render fn needs to return
|
||||||
// a width/height hint. maybe Popup(Box<Component>)
|
// a width/height hint. maybe Popup(Box<Component>)
|
||||||
@ -53,10 +56,10 @@ pub fn auto_close(mut self, auto_close: bool) -> Self {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_rel_position(&mut self, viewport: Rect, cx: &Context) -> (u16, u16) {
|
pub fn get_rel_position(&mut self, viewport: Rect, editor: &Editor) -> (u16, u16) {
|
||||||
let position = self
|
let position = self
|
||||||
.position
|
.position
|
||||||
.get_or_insert_with(|| cx.editor.cursor().0.unwrap_or_default());
|
.get_or_insert_with(|| editor.cursor().0.unwrap_or_default());
|
||||||
|
|
||||||
let (width, height) = self.size;
|
let (width, height) = self.size;
|
||||||
|
|
||||||
@ -176,13 +179,13 @@ fn required_size(&mut self, viewport: (u16, u16)) -> Option<(u16, u16)> {
|
|||||||
Some(self.size)
|
Some(self.size)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut Context) {
|
fn render(&mut self, viewport: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
// trigger required_size so we recalculate if the child changed
|
// trigger required_size so we recalculate if the child changed
|
||||||
self.required_size((viewport.width, viewport.height));
|
self.required_size((viewport.width, viewport.height));
|
||||||
|
|
||||||
cx.scroll = Some(self.scroll);
|
cx.scroll = Some(self.scroll);
|
||||||
|
|
||||||
let (rel_x, rel_y) = self.get_rel_position(viewport, cx);
|
let (rel_x, rel_y) = self.get_rel_position(viewport, cx.editor);
|
||||||
|
|
||||||
// clip to viewport
|
// clip to viewport
|
||||||
let area = viewport.intersection(Rect::new(rel_x, rel_y, self.size.0, self.size.1));
|
let area = viewport.intersection(Rect::new(rel_x, rel_y, self.size.0, self.size.1));
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::compositor::{Component, Compositor, Context, EventResult};
|
use crate::compositor::{Component, Compositor, Context, EventResult, RenderContext};
|
||||||
use crate::{alt, ctrl, key, shift, ui};
|
use crate::{alt, ctrl, key, shift, ui};
|
||||||
use crossterm::event::Event;
|
use crossterm::event::Event;
|
||||||
use helix_view::input::KeyEvent;
|
use helix_view::input::KeyEvent;
|
||||||
@ -327,7 +327,7 @@ pub fn exit_selection(&mut self) {
|
|||||||
const BASE_WIDTH: u16 = 30;
|
const BASE_WIDTH: u16 = 30;
|
||||||
|
|
||||||
impl Prompt {
|
impl Prompt {
|
||||||
pub fn render_prompt(&self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
pub fn render_prompt(&self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
let theme = &cx.editor.theme;
|
let theme = &cx.editor.theme;
|
||||||
let prompt_color = theme.get("ui.text");
|
let prompt_color = theme.get("ui.text");
|
||||||
let completion_color = theme.get("ui.statusline");
|
let completion_color = theme.get("ui.statusline");
|
||||||
@ -547,7 +547,7 @@ fn handle_event(&mut self, event: Event, cx: &mut Context) -> EventResult {
|
|||||||
EventResult::Consumed(None)
|
EventResult::Consumed(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) {
|
fn render(&mut self, area: Rect, surface: &mut Surface, cx: &mut RenderContext<'_>) {
|
||||||
self.render_prompt(area, surface, cx)
|
self.render_prompt(area, surface, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
use crate::compositor::{Component, Context};
|
use crate::compositor::{Component, RenderContext};
|
||||||
use tui::buffer::Buffer as Surface;
|
use tui::buffer::Buffer as Surface;
|
||||||
|
|
||||||
use helix_view::graphics::Rect;
|
use helix_view::graphics::Rect;
|
||||||
@ -30,7 +30,7 @@ fn from(contents: tui::text::Text<'static>) -> Self {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Component for Text {
|
impl Component for Text {
|
||||||
fn render(&mut self, area: Rect, surface: &mut Surface, _cx: &mut Context) {
|
fn render(&mut self, area: Rect, surface: &mut Surface, _cx: &mut RenderContext<'_>) {
|
||||||
use tui::widgets::{Paragraph, Widget, Wrap};
|
use tui::widgets::{Paragraph, Widget, Wrap};
|
||||||
|
|
||||||
let par = Paragraph::new(self.contents.clone()).wrap(Wrap { trim: false });
|
let par = Paragraph::new(self.contents.clone()).wrap(Wrap { trim: false });
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
use helix_core::{register::Registers, unicode::width::UnicodeWidthStr};
|
use helix_core::{register::Registers, unicode::width::UnicodeWidthStr};
|
||||||
use std::{collections::BTreeSet, fmt::Write};
|
use std::{collections::BTreeSet, fmt::Write};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone)]
|
||||||
/// Info box used in editor. Rendering logic will be in other crate.
|
/// Info box used in editor. Rendering logic will be in other crate.
|
||||||
pub struct Info {
|
pub struct Info {
|
||||||
/// Title shown at top.
|
/// Title shown at top.
|
||||||
|
Loading…
Reference in New Issue
Block a user