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:
GarandPLG committed 2026-10-19 12:21:20 +02:00
1 parent 9e09aaf75e
commit c4313b4117
60 files changed
+3632 -3610

No files matched your search

+103 -108
View File
@@ -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);
}
}
}