use ratatui::text::Span;
use super::appearance::AppearanceSetting;
use super::layout::LayoutSetting;
use super::rendering::RenderingSetting;
use super::statusline::StatusLineSetting;
use super::theme::groups::scheme;
use super::Settings;
use crate::ui::controller::picker::{PickerItem, PickerTab, PickerValue, Row};
use crate::ui::controller::EditorEvent;
pub trait SettingRow: Copy + Send + 'static {
fn label(self) -> &'static str;
fn description(self, settings: Settings) -> &'static str;
fn value(self, settings: Settings) -> PickerValue;
fn adjust(self, settings: &mut Settings, delta: i8);
fn applies(self, _settings: Settings) -> bool {
true
}
fn row(self, settings: Settings) -> Box<dyn PickerItem> {
let label = Span::styled(self.label(), scheme().settings_item_label());
Row::adjust(vec![label.into()], move |delta| {
let mut stepped = settings;
self.adjust(&mut stepped, delta);
EditorEvent::SetSettings(stepped)
})
.with_value(self.value(settings))
.described(self.description(settings))
.selectable_if(self.applies(settings))
.into()
}
}
pub fn tabs(settings: Settings) -> Vec<PickerTab> {
vec![
tab("appearance", AppearanceSetting::CHOICES, settings),
tab("layout", LayoutSetting::CHOICES, settings),
tab("statusline", StatusLineSetting::CHOICES, settings),
tab("rendering", RenderingSetting::CHOICES, settings),
]
}
fn tab<Setting: SettingRow>(
label: &'static str,
rows: &[Setting],
settings: Settings,
) -> PickerTab {
PickerTab {
label,
items: rows.iter().map(|row| row.row(settings)).collect(),
}
}
pub fn restore_defaults() -> Box<dyn PickerItem> {
let label = Span::styled("restore defaults", scheme().settings_button());
Row::enter(vec![label.into()], || EditorEvent::RestoreDefaults)
.described("reset settings, keymaps and appearance")
.into()
}
#[cfg(test)]
mod tests {
use super::*;
fn assert_steps_back<Setting: SettingRow>(rows: &[Setting]) {
let settings = Settings::default();
for row in rows {
let mut stepped = settings;
row.adjust(&mut stepped, 1);
row.adjust(&mut stepped, -1);
assert_eq!(stepped, settings, "{}", row.label());
}
}
#[test]
fn stepping_any_setting_forward_then_back_restores_it() {
assert_steps_back(AppearanceSetting::CHOICES);
assert_steps_back(LayoutSetting::CHOICES);
assert_steps_back(StatusLineSetting::CHOICES);
assert_steps_back(RenderingSetting::CHOICES);
}
}