From c446c396453f3fd8f52aab900202b9835806e22e Mon Sep 17 00:00:00 2001 From: wongjiahau Date: Mon, 6 Feb 2023 22:11:48 +0800 Subject: [PATCH] feat(explorer/position): right According to https://github.com/helix-editor/helix/pull/5768#issuecomment-1413162928 --- helix-term/src/ui/editor.rs | 30 ++++++++++----- helix-term/src/ui/explore.rs | 74 +++++++++++++++++++++++++++--------- helix-view/src/editor.rs | 19 ++++++--- 3 files changed, 89 insertions(+), 34 deletions(-) diff --git a/helix-term/src/ui/editor.rs b/helix-term/src/ui/editor.rs index 07b27f59..73bc7173 100644 --- a/helix-term/src/ui/editor.rs +++ b/helix-term/src/ui/editor.rs @@ -17,7 +17,7 @@ use helix_core::{ }; use helix_view::{ document::Mode, - editor::{CompleteAction, CursorShapeConfig}, + editor::{CompleteAction, CursorShapeConfig, ExplorerPosition}, graphics::{Color, CursorKind, Modifier, Rect, Style}, input::{KeyEvent, MouseButton, MouseEvent, MouseEventKind}, keyboard::{KeyCode, KeyModifiers}, @@ -1266,16 +1266,26 @@ impl Component for EditorView { // clear with background color surface.set_style(area, cx.editor.theme.get("ui.background")); let config = cx.editor.config(); + // if the terminal size suddenly changed, we need to trigger a resize - let mut editor_area = area.clip_bottom(1); - if self.explorer.is_some() && (config.explorer.is_embed()) { - editor_area = editor_area.clip_left(config.explorer.column_width as u16 + 2); - } + let editor_area = area.clip_bottom(1); + let explorer_column_width = config.explorer.column_width as u16 + 2; + let editor_area = if self.explorer.is_some() { + match config.explorer.position { + ExplorerPosition::Overlay => editor_area, + ExplorerPosition::Left => editor_area.clip_left(explorer_column_width), + ExplorerPosition::Right => editor_area.clip_right(explorer_column_width), + } + } else { + editor_area + }; cx.editor.resize(editor_area); // -1 from bottom for commandline - if let Some(explore) = self.explorer.as_mut() { - if !explore.content.is_focus() && config.explorer.is_embed() { - explore.content.render(area, surface, cx); + if let Some(explorer) = self.explorer.as_mut() { + if !explorer.content.is_focus() { + if let Some(position) = config.explorer.is_embed() { + explorer.content.render_embed(area, surface, cx, &position); + } } } @@ -1356,8 +1366,8 @@ impl Component for EditorView { if let Some(explore) = self.explorer.as_mut() { if explore.content.is_focus() { - if config.explorer.is_embed() { - explore.content.render(area, surface, cx); + if let Some(position) = config.explorer.is_embed() { + explore.content.render_embed(area, surface, cx, &position); } else { explore.render(area, surface, cx); } diff --git a/helix-term/src/ui/explore.rs b/helix-term/src/ui/explore.rs index af54d129..3d5ccbbf 100644 --- a/helix-term/src/ui/explore.rs +++ b/helix-term/src/ui/explore.rs @@ -6,7 +6,7 @@ use crate::{ use anyhow::{bail, ensure, Result}; use helix_core::Position; use helix_view::{ - editor::Action, + editor::{Action, ExplorerPositionEmbed}, graphics::{CursorKind, Modifier, Rect}, input::{Event, KeyEvent}, Editor, @@ -496,19 +496,39 @@ impl Explorer { self.tree.render(list_area, surface, cx, &mut self.state); } - fn render_embed(&mut self, area: Rect, surface: &mut Surface, cx: &mut Context) { + pub fn render_embed( + &mut self, + area: Rect, + surface: &mut Surface, + cx: &mut Context, + position: &ExplorerPositionEmbed, + ) { let config = &cx.editor.config().explorer; - let side_area = area - .with_width(area.width.min(config.column_width as u16 + 2)) - .clip_bottom(1); + + let width = area.width.min(config.column_width as u16 + 2); + + let side_area = match position { + ExplorerPositionEmbed::Left => Rect { width, ..area }, + ExplorerPositionEmbed::Right => Rect { + x: area.width - width, + width, + ..area + }, + } + .clip_bottom(1); let background = cx.editor.theme.get("ui.background"); surface.clear_with(side_area, background); - let preview_area = area.clip_left(side_area.width).clip_bottom(2); let prompt_area = area.clip_top(side_area.height); - let list_area = - render_block(side_area.clip_left(1), surface, Borders::RIGHT).clip_bottom(1); + let list_area = match position { + ExplorerPositionEmbed::Left => { + render_block(side_area.clip_left(1), surface, Borders::RIGHT).clip_bottom(1) + } + ExplorerPositionEmbed::Right => { + render_block(side_area.clip_right(1), surface, Borders::LEFT).clip_bottom(1) + } + }; self.tree.render(list_area, surface, cx, &mut self.state); { @@ -517,7 +537,11 @@ impl Explorer { } else { cx.editor.theme.get("ui.statusline.inactive") }; - let area = side_area.clip_top(list_area.height).clip_right(1); + let area = side_area.clip_top(list_area.height); + let area = match position { + ExplorerPositionEmbed::Left => area.clip_right(1), + ExplorerPositionEmbed::Right => area.clip_left(1), + }; surface.clear_with(area, statusline); // surface.set_string_truncated( // area.x, @@ -531,16 +555,30 @@ impl Explorer { } if self.is_focus() { + const PREVIEW_AREA_MAX_WIDTH: u16 = 90; + const PREVIEW_AREA_MAX_HEIGHT: u16 = 25; + let preview_area_width = (area.width - side_area.width).min(PREVIEW_AREA_MAX_WIDTH); + let preview_area_height = area.height.min(PREVIEW_AREA_MAX_HEIGHT); + + let preview_area = match position { + ExplorerPositionEmbed::Left => area.clip_left(side_area.width).clip_bottom(2), + ExplorerPositionEmbed::Right => (Rect { + x: area.width - side_area.width - preview_area_width, + ..area + }) + .clip_right(side_area.width) + .clip_bottom(2), + }; if preview_area.width < 30 || preview_area.height < 3 { return; } - let width = preview_area.width.min(90); - let mut y = self.tree.row().saturating_sub(1) as u16; - let height = (preview_area.height).min(25); - if (height + y) > preview_area.height { - y = preview_area.height - height; - } - let area = Rect::new(preview_area.x, y, width, height); + let y = self.tree.row().saturating_sub(1) as u16; + let y = if (preview_area_height + y) > preview_area.height { + preview_area.height - preview_area_height + } else { + y + }; + let area = Rect::new(preview_area.x, y, preview_area_width, preview_area_height); surface.clear_with(area, background); let area = render_block(area, surface, Borders::all()); self.render_preview(area, surface, cx.editor); @@ -800,8 +838,8 @@ impl Component for Explorer { return; } let config = &cx.editor.config().explorer; - if config.is_embed() { - self.render_embed(area, surface, cx); + if let Some(position) = config.is_embed() { + self.render_embed(area, surface, cx, &position); } else { self.render_float(area, surface, cx); } diff --git a/helix-view/src/editor.rs b/helix-view/src/editor.rs index bc549249..4bb386fa 100644 --- a/helix-view/src/editor.rs +++ b/helix-view/src/editor.rs @@ -119,8 +119,14 @@ pub enum ExplorerStyle { #[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)] #[serde(rename_all = "kebab-case")] pub enum ExplorerPosition { - Embed, Overlay, + Left, + Right, +} + +pub enum ExplorerPositionEmbed { + Left, + Right, } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] @@ -133,17 +139,18 @@ pub struct ExplorerConfig { } impl ExplorerConfig { - pub fn is_embed(&self) -> bool { + pub fn is_embed(&self) -> Option { match self.position { - ExplorerPosition::Embed => true, - ExplorerPosition::Overlay => false, + ExplorerPosition::Overlay => None, + ExplorerPosition::Left => Some(ExplorerPositionEmbed::Left), + ExplorerPosition::Right => Some(ExplorerPositionEmbed::Right), } } pub fn is_overlay(&self) -> bool { match self.position { - ExplorerPosition::Embed => false, ExplorerPosition::Overlay => true, + _ => false, } } @@ -166,7 +173,7 @@ impl Default for ExplorerConfig { fn default() -> Self { Self { style: ExplorerStyle::Tree, - position: ExplorerPosition::Overlay, + position: ExplorerPosition::Left, column_width: 30, } }