merge: feat: help scrolling and styling

closes #28
This commit is contained in:
Jeremy Wall 2025-02-28 21:27:06 -05:00
commit 48aad97f5b
5 changed files with 96 additions and 123 deletions

92
Cargo.lock generated
View File

@ -511,41 +511,6 @@ dependencies = [
"thiserror",
]
[[package]]
name = "darling"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]]
name = "deranged"
version = "0.3.11"
@ -555,29 +520,6 @@ dependencies = [
"powerfmt",
]
[[package]]
name = "derive-getters"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74ef43543e701c01ad77d3a5922755c6a1d71b22d942cb8042be4994b380caff"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "derive_setters"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4e8ef033054e131169b8f0f9a7af8f5533a9436fadf3c500ed547f730f07090d"
dependencies = [
"darling",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "diff"
version = "0.1.13"
@ -595,15 +537,6 @@ dependencies = [
"subtle",
]
[[package]]
name = "document-features"
version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0"
dependencies = [
"litrs",
]
[[package]]
name = "either"
version = "1.13.0"
@ -846,12 +779,6 @@ dependencies = [
"cc",
]
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]]
name = "indexmap"
version = "2.6.0"
@ -986,12 +913,6 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
[[package]]
name = "litrs"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
[[package]]
name = "lock_api"
version = "0.4.12"
@ -1594,7 +1515,6 @@ dependencies = [
"slice-utils",
"thiserror",
"tui-markdown",
"tui-popup",
"tui-prompts",
"tui-textarea",
]
@ -1855,18 +1775,6 @@ dependencies = [
"tracing",
]
[[package]]
name = "tui-popup"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d9ee3d08800c83ba0a2efaec44d225bcc3f885f30e2b520a17e2cd962b7da6ab"
dependencies = [
"derive-getters",
"derive_setters",
"document-features",
"ratatui",
]
[[package]]
name = "tui-prompts"
version = "0.5.0"

View File

@ -18,7 +18,6 @@ thiserror = "1.0.65"
tui-textarea = "0.7.0"
tui-prompts = "0.5.0"
slice-utils = { git = "https://dev.zaphar.net/zaphar/slice-cursor-rs.git" }
tui-popup = "0.6.0"
serde_json = "1.0.133"
colorsys = "0.6.7"
tui-markdown = { version = "0.3.1", features = [] }

View File

@ -77,6 +77,7 @@ pub struct AppState<'ws> {
pub numeric_prefix: Vec<char>,
pub char_queue: Vec<char>,
pub range_select: RangeSelection,
pub dialog_scroll: u16,
dirty: bool,
popup: Text<'ws>,
clipboard: Option<ClipboardContents>,
@ -91,6 +92,7 @@ impl<'ws> Default for AppState<'ws> {
numeric_prefix: Default::default(),
char_queue: Default::default(),
range_select: Default::default(),
dialog_scroll: 0,
dirty: Default::default(),
popup: Default::default(),
clipboard: Default::default(),
@ -332,6 +334,12 @@ impl<'ws> Workspace<'ws> {
KeyCode::Char('h') if key.modifiers == KeyModifiers::ALT => {
self.exit_dialog_mode()?
}
KeyCode::Char('j') | KeyCode::Down => {
self.state.dialog_scroll = self.state.dialog_scroll.saturating_add(1);
}
KeyCode::Char('k') | KeyCode::Up => {
self.state.dialog_scroll = self.state.dialog_scroll.saturating_sub(1);
}
_ => {
// NOOP
}

56
src/ui/render/dialog.rs Normal file
View File

@ -0,0 +1,56 @@
use ratatui::{
self,
layout::{Constraint, Layout, Rect},
style::{Color, Style, Stylize},
text::Text,
widgets::{Block, Paragraph, Widget, Wrap},
};
pub struct Dialog<'w> {
content: Text<'w>,
title: &'w str,
scroll: (u16, u16),
}
impl<'w> Dialog<'w> {
pub fn new(content: Text<'w>, title: &'w str) -> Self {
Self {
content,
title,
scroll: (0, 0),
}
}
pub fn scroll(mut self, line: u16) -> Self {
self.scroll.0 = line;
self
}
}
impl<'w> Widget for Dialog<'w> {
fn render(self, area: Rect, buf: &mut ratatui::prelude::Buffer)
where
Self: Sized,
{
// First find the center of the area.
let content_width = self.content.width();
let sidebar_width = (area.width - (content_width as u16) + 2) / 2;
let [_, dialog_area, _] = Layout::horizontal(vec![
Constraint::Length(sidebar_width),
Constraint::Fill(1),
Constraint::Length(sidebar_width),
])
.areas(area);
let dialog_block = Block::bordered()
.title_top(self.title)
.title_bottom("j,k or up,down to scroll")
.style(Style::default().on_black());
let dialog = Paragraph::new(self.content.clone())
.wrap(Wrap::default())
.scroll(self.scroll.clone())
.block(dialog_block)
.style(Style::default());
dialog.render(dialog_area, buf);
}
}

View File

@ -5,12 +5,12 @@ use ratatui::{
widgets::{Block, Paragraph, Tabs, Widget},
Frame,
};
use tui_popup::Popup;
use super::*;
pub mod viewport;
pub use viewport::Viewport;
pub mod dialog;
#[cfg(test)]
mod test;
@ -98,38 +98,40 @@ impl<'widget, 'ws: 'widget> Widget for &'widget mut Workspace<'ws> {
where
Self: Sized,
{
let outer_block = Block::bordered()
.title(Line::from(
self.name
.file_name()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_else(|| String::from("Unknown")),
))
.title_bottom(match self.state.modality() {
Modality::Navigate => "navigate",
Modality::CellEdit => "edit",
Modality::Command => "command",
Modality::Dialog => "",
Modality::RangeSelect => "range-copy",
})
.title_bottom(
Line::from(format!(
"{},{}",
self.book.location.row, self.book.location.col
))
.right_aligned(),
);
for (rect, f) in self.get_render_parts(area.clone()) {
f(rect, buf, self);
}
outer_block.render(area, buf);
if self.state.modality() == &Modality::Dialog {
// Use a popup here.
let lines = Text::from_iter(self.state.popup.iter().cloned());
let popup = Popup::new(lines);
let popup = dialog::Dialog::new(lines, "Help").scroll(self.state.dialog_scroll);
//let popup = Paragraph::new(lines);
popup.render(area, buf);
} else {
let outer_block = Block::bordered()
.title(Line::from(
self.name
.file_name()
.map(|p| p.to_string_lossy().to_string())
.unwrap_or_else(|| String::from("Unknown")),
))
.title_bottom(match self.state.modality() {
Modality::Navigate => "navigate",
Modality::CellEdit => "edit",
Modality::Command => "command",
Modality::Dialog => "",
Modality::RangeSelect => "range-copy",
})
.title_bottom(
Line::from(format!(
"{},{}",
self.book.location.row, self.book.location.col
))
.right_aligned(),
);
for (rect, f) in self.get_render_parts(area.clone()) {
f(rect, buf, self);
}
outer_block.render(area, buf);
}
}
}