generated from GarandPLG/rust-flake-template
Add rustfmt configuration and reformat code
- Document new Rust formatting standards in AGENTS, CODE_MAP, and PROGRESS. - Add rustfmt.toml with style 2024, 2‑space indents, 100‑char width, LF endings. - Apply consistent 2‑space indentation and ordering across source files. - Minor clean‑up of imports and whitespace to match the new style.
This commit is contained in:
1 parent
9e09aaf75e
commit
c4313b4117
60 files changed
+3632
-3610
No files matched your search
+103
-108
@@ -1,14 +1,14 @@
|
||||
use crate::app::{
|
||||
helpers::block_single_title_helper,
|
||||
keybindings::{Action, Group, KeyBinding, binding_for},
|
||||
helpers::block_single_title_helper,
|
||||
keybindings::{Action, Group, KeyBinding, binding_for},
|
||||
};
|
||||
use clap::ValueEnum;
|
||||
use ratatui::{
|
||||
buffer::Buffer,
|
||||
layout::{Alignment, Constraint, Layout, Rect},
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
widgets::{Block, Borders, Padding, Paragraph, Widget},
|
||||
buffer::Buffer,
|
||||
layout::{Alignment, Constraint, Layout, Rect},
|
||||
style::{Color, Stylize},
|
||||
text::Line,
|
||||
widgets::{Block, Borders, Padding, Paragraph, Widget},
|
||||
};
|
||||
use std::collections::HashSet;
|
||||
|
||||
@@ -18,123 +18,118 @@ use std::collections::HashSet;
|
||||
/// logical group of keybindings (e.g. navigation, editing, etc.). The paragraphs
|
||||
/// are rendered side‑by‑side inside a bordered container.
|
||||
pub struct KeybindingsWidget {
|
||||
/// Paragraphs, one per used `Group`, containing the formatted keybinding lines.
|
||||
grouped: Vec<Paragraph<'static>>,
|
||||
/// Paragraphs, one per used `Group`, containing the formatted keybinding lines.
|
||||
grouped: Vec<Paragraph<'static>>,
|
||||
}
|
||||
|
||||
impl KeybindingsWidget {
|
||||
/// Create a new widget from a list of actions.
|
||||
///
|
||||
/// For each action, the corresponding static [`KeyBinding`] is looked up
|
||||
/// using [`binding_for`]. Only groups that have at least one binding are
|
||||
/// displayed. The resulting widget contains a paragraph for each group,
|
||||
/// formatted with the key symbol (red & bold) followed by its description.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `actions` – A slice of actions for which keybindings should be shown.
|
||||
/// * `area_height` – The height of the area in which the widget will be rendered.
|
||||
/// This value is used to calculate vertical padding so that the keybinding rows
|
||||
/// are vertically centered when the widget's allocated height is larger than the
|
||||
/// number of lines needed to display the bindings.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A fully‑initialised `KeybindingsWidget` ready for rendering.
|
||||
pub fn new(actions: &[Action], area_height: u16) -> Self {
|
||||
let keybindings: Vec<Option<&'static KeyBinding>> =
|
||||
actions.iter().map(|a| binding_for(*a)).collect();
|
||||
/// Create a new widget from a list of actions.
|
||||
///
|
||||
/// For each action, the corresponding static [`KeyBinding`] is looked up
|
||||
/// using [`binding_for`]. Only groups that have at least one binding are
|
||||
/// displayed. The resulting widget contains a paragraph for each group,
|
||||
/// formatted with the key symbol (red & bold) followed by its description.
|
||||
///
|
||||
/// # Parameters
|
||||
///
|
||||
/// * `actions` – A slice of actions for which keybindings should be shown.
|
||||
/// * `area_height` – The height of the area in which the widget will be rendered.
|
||||
/// This value is used to calculate vertical padding so that the keybinding rows
|
||||
/// are vertically centered when the widget's allocated height is larger than the
|
||||
/// number of lines needed to display the bindings.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A fully‑initialised `KeybindingsWidget` ready for rendering.
|
||||
pub fn new(actions: &[Action], area_height: u16) -> Self {
|
||||
let keybindings: Vec<Option<&'static KeyBinding>> =
|
||||
actions.iter().map(|a| binding_for(*a)).collect();
|
||||
|
||||
let used_groups: HashSet<Group> = keybindings
|
||||
.iter()
|
||||
.filter_map(|b| b.map(|binding| binding.group))
|
||||
.collect();
|
||||
let used_groups: HashSet<Group> = keybindings
|
||||
.iter()
|
||||
.filter_map(|b| b.map(|binding| binding.group))
|
||||
.collect();
|
||||
|
||||
let mut grouped_keybindings: Vec<Paragraph<'static>> = Vec::new();
|
||||
let mut grouped_keybindings: Vec<Paragraph<'static>> = Vec::new();
|
||||
|
||||
for group in Group::value_variants().iter() {
|
||||
if !used_groups.contains(group) {
|
||||
continue;
|
||||
}
|
||||
for group in Group::value_variants().iter() {
|
||||
if !used_groups.contains(group) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let grouped_lines: Vec<Line<'_>> = keybindings
|
||||
.iter()
|
||||
.filter(|b| b.as_ref().map_or(false, |kb| kb.group == *group))
|
||||
.filter_map(|b| {
|
||||
b.as_ref().map(|kb| {
|
||||
Line::from_iter([
|
||||
kb.symbol.red().bold(),
|
||||
" - ".into(),
|
||||
kb.description.into(),
|
||||
])
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
let grouped_lines: Vec<Line<'_>> = keybindings
|
||||
.iter()
|
||||
.filter(|b| b.as_ref().map_or(false, |kb| kb.group == *group))
|
||||
.filter_map(|b| {
|
||||
b.as_ref().map(|kb| {
|
||||
Line::from_iter([kb.symbol.red().bold(), " - ".into(), kb.description.into()])
|
||||
})
|
||||
})
|
||||
.collect();
|
||||
|
||||
let height_diff: u16 =
|
||||
area_height.saturating_sub(grouped_lines.len().saturating_add(2) as u16);
|
||||
let height_diff: u16 =
|
||||
area_height.saturating_sub(grouped_lines.len().saturating_add(2) as u16);
|
||||
|
||||
let padding_top: u16 = if height_diff <= 1 {
|
||||
height_diff
|
||||
} else {
|
||||
height_diff / 2
|
||||
};
|
||||
let padding_top: u16 = if height_diff <= 1 {
|
||||
height_diff
|
||||
} else {
|
||||
height_diff / 2
|
||||
};
|
||||
|
||||
let mut block: Block<'_> = Block::default().padding(Padding::new(1, 1, padding_top, 0));
|
||||
let mut block: Block<'_> = Block::default().padding(Padding::new(1, 1, padding_top, 0));
|
||||
|
||||
if !grouped_keybindings.is_empty() {
|
||||
block = block.borders(Borders::LEFT);
|
||||
}
|
||||
if !grouped_keybindings.is_empty() {
|
||||
block = block.borders(Borders::LEFT);
|
||||
}
|
||||
|
||||
grouped_keybindings.push(
|
||||
Paragraph::new(grouped_lines)
|
||||
.alignment(Alignment::Center)
|
||||
.block(block),
|
||||
);
|
||||
}
|
||||
|
||||
Self {
|
||||
grouped: grouped_keybindings,
|
||||
}
|
||||
grouped_keybindings.push(
|
||||
Paragraph::new(grouped_lines)
|
||||
.alignment(Alignment::Center)
|
||||
.block(block),
|
||||
);
|
||||
}
|
||||
|
||||
Self {
|
||||
grouped: grouped_keybindings,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Widget for KeybindingsWidget {
|
||||
/// Render the widget inside the given rectangular area.
|
||||
///
|
||||
/// The widget first draws a surrounding border with the title *Keybindings*.
|
||||
/// It then divides the inner area into equal horizontal slices—one per
|
||||
/// used group—and renders each group's paragraph into its slice.
|
||||
///
|
||||
/// If no groups are present, the function returns early without drawing
|
||||
/// anything.
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let count: u16 = self.grouped.len() as u16;
|
||||
/// Render the widget inside the given rectangular area.
|
||||
///
|
||||
/// The widget first draws a surrounding border with the title *Keybindings*.
|
||||
/// It then divides the inner area into equal horizontal slices—one per
|
||||
/// used group—and renders each group's paragraph into its slice.
|
||||
///
|
||||
/// If no groups are present, the function returns early without drawing
|
||||
/// anything.
|
||||
fn render(self, area: Rect, buf: &mut Buffer) {
|
||||
let count: u16 = self.grouped.len() as u16;
|
||||
|
||||
if count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let block: Block<'_> =
|
||||
Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.title(block_single_title_helper(
|
||||
"Keybindings".to_string(),
|
||||
Color::Magenta,
|
||||
));
|
||||
|
||||
let inner: Rect = block.inner(area);
|
||||
|
||||
block.render(area, buf);
|
||||
|
||||
let base: u16 = if count == 0 { 0 } else { 100u16 / count };
|
||||
|
||||
let constraints: Vec<Constraint> = vec![Constraint::Percentage(base); count as usize];
|
||||
|
||||
let chunks: Vec<Rect> = Layout::horizontal(constraints).split(inner).to_vec();
|
||||
|
||||
for (paragraph, chunk) in self.grouped.into_iter().zip(chunks.into_iter()) {
|
||||
paragraph.render(chunk, buf);
|
||||
}
|
||||
if count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let block: Block<'_> = Block::default()
|
||||
.borders(Borders::ALL)
|
||||
.title(block_single_title_helper(
|
||||
"Keybindings".to_string(),
|
||||
Color::Magenta,
|
||||
));
|
||||
|
||||
let inner: Rect = block.inner(area);
|
||||
|
||||
block.render(area, buf);
|
||||
|
||||
let base: u16 = if count == 0 { 0 } else { 100u16 / count };
|
||||
|
||||
let constraints: Vec<Constraint> = vec![Constraint::Percentage(base); count as usize];
|
||||
|
||||
let chunks: Vec<Rect> = Layout::horizontal(constraints).split(inner).to_vec();
|
||||
|
||||
for (paragraph, chunk) in self.grouped.into_iter().zip(chunks.into_iter()) {
|
||||
paragraph.render(chunk, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user