Skip to content

Commit 7798c17

Browse files
committed
refactor(ui): share typed picker adapters
1 parent 9cd13e6 commit 7798c17

2 files changed

Lines changed: 47 additions & 17 deletions

File tree

src/ui.rs

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,14 @@ pub trait Pickable: Clone {
5656
fn column_constraints(max_widths: &[usize]) -> Vec<Constraint>;
5757
}
5858

59+
trait WrappedPickable: Pickable {
60+
type Inner;
61+
62+
fn from_inner(inner: Self::Inner) -> Self;
63+
64+
fn into_inner(self) -> Self::Inner;
65+
}
66+
5967
/// Configuration options for the generic picker UI.
6068
#[derive(Debug, Clone, Copy, Default)]
6169
pub struct PickerOpts {
@@ -614,9 +622,7 @@ pub fn pick_container(
614622
opts: PickerOpts,
615623
on_delete: Option<&mut dyn FnMut(&ContainerItem)>,
616624
) -> Result<Option<crate::container::Container>> {
617-
let items: Vec<ContainerItem> = containers.into_iter().map(ContainerItem).collect();
618-
let selected = pick(items, opts, on_delete)?;
619-
Ok(selected.map(|item| item.0))
625+
pick_wrapped::<ContainerItem>(containers, opts, on_delete)
620626
}
621627

622628
/// Launches a picker for stored devcontainer configs.
@@ -625,22 +631,28 @@ pub fn pick_config(
625631
opts: PickerOpts,
626632
on_delete: Option<&mut dyn FnMut(&ConfigItem)>,
627633
) -> Result<Option<crate::config_store::ConfigEntry>> {
628-
let items: Vec<ConfigItem> = configs.into_iter().map(ConfigItem).collect();
629-
let selected = pick(items, opts, on_delete)?;
630-
Ok(selected.map(|item| item.0))
634+
pick_wrapped::<ConfigItem>(configs, opts, on_delete)
631635
}
632636

633637
/// Launches a picker for devcontainer selection.
634638
pub fn pick_devcontainer(
635639
dev_containers: Vec<crate::workspace::DevContainer>,
636640
) -> Result<Option<crate::workspace::DevContainer>> {
637-
let items: Vec<DevContainerItem> = dev_containers.into_iter().map(DevContainerItem).collect();
638641
let opts = PickerOpts {
639642
hide_instructions: false,
640643
hide_info: false,
641644
};
642-
let selected = pick(items, opts, None)?;
643-
Ok(selected.map(|item| item.0))
645+
pick_wrapped::<DevContainerItem>(dev_containers, opts, None)
646+
}
647+
648+
fn pick_wrapped<T: WrappedPickable>(
649+
values: Vec<T::Inner>,
650+
opts: PickerOpts,
651+
on_delete: Option<&mut dyn FnMut(&T)>,
652+
) -> Result<Option<T::Inner>> {
653+
let items = values.into_iter().map(T::from_inner).collect();
654+
let selected = pick(items, opts, on_delete)?;
655+
Ok(selected.map(T::into_inner))
644656
}
645657

646658
fn add_num_opt(o1: Option<u32>, o2: Option<u32>) -> Option<u32> {

src/ui/items.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
1-
use super::Pickable;
1+
use super::{Pickable, WrappedPickable};
22
use crate::history::{Entry, EntryId};
33
use chrono::{DateTime, Local};
44
use ratatui::layout::Constraint;
55
use std::borrow::Cow;
66

7+
macro_rules! impl_wrapped_pickable {
8+
($wrapper:ty, $inner:ty) => {
9+
impl WrappedPickable for $wrapper {
10+
type Inner = $inner;
11+
12+
fn from_inner(inner: Self::Inner) -> Self {
13+
Self(inner)
14+
}
15+
16+
fn into_inner(self) -> Self::Inner {
17+
self.0
18+
}
19+
}
20+
};
21+
}
22+
723
#[derive(Debug, Clone)]
824
pub struct HistoryItem {
925
pub id: EntryId,
@@ -113,13 +129,9 @@ impl Pickable for ContainerItem {
113129
}
114130

115131
fn search_fields(&self) -> Vec<String> {
116-
vec![
117-
self.0.short_id.clone(),
118-
self.0.status.clone(),
119-
self.0.image.clone(),
120-
self.0.local_folder.clone(),
121-
self.0.config_file.clone(),
122-
]
132+
let mut fields = self.cells();
133+
fields.push(self.0.config_file.clone());
134+
fields
123135
}
124136

125137
fn status_lines(&self) -> Vec<String> {
@@ -137,6 +149,8 @@ impl Pickable for ContainerItem {
137149
}
138150
}
139151

152+
impl_wrapped_pickable!(ContainerItem, crate::container::Container);
153+
140154
#[derive(Clone, Debug)]
141155
pub struct ConfigItem(pub crate::config_store::ConfigEntry);
142156

@@ -180,6 +194,8 @@ impl Pickable for ConfigItem {
180194
}
181195
}
182196

197+
impl_wrapped_pickable!(ConfigItem, crate::config_store::ConfigEntry);
198+
183199
#[derive(Clone, Debug)]
184200
pub struct DevContainerItem(pub crate::workspace::DevContainer);
185201

@@ -218,3 +234,5 @@ impl Pickable for DevContainerItem {
218234
]
219235
}
220236
}
237+
238+
impl_wrapped_pickable!(DevContainerItem, crate::workspace::DevContainer);

0 commit comments

Comments
 (0)