pass whole state to setter, to emit tasks

This commit is contained in:
🪞👃🪞 2025-03-24 04:54:35 +02:00
parent d26c46d6e1
commit 859da8e5d1
5 changed files with 85 additions and 48 deletions

View file

@ -78,19 +78,27 @@ impl Taggart {
{ {
let value = (column.getter)(&self.entries[self.cursor]); let value = (column.getter)(&self.entries[self.cursor]);
let value = format!("{}", value.unwrap_or_default()); let value = format!("{}", value.unwrap_or_default());
self.mode = Some(Mode::Edit { index: value.len(), value }); self.mode = Some(Mode::Edit {
index: value.len(),
value: value.into(),
});
} }
} }
pub fn edit_cancel (&mut self) { pub fn edit_cancel (&mut self) {
self.mode = None; self.mode = None;
} }
pub fn edit_confirm (&mut self) { pub fn edit_confirm (&mut self) {
if let Some(Mode::Edit { value, .. }) = &self.mode let value = if let Some(Mode::Edit { value, .. }) = &self.mode {
Some(value.clone())
} else {
None
};
if let Some(value) = value
&& let Some(column) = self.columns.0.get(self.column) && let Some(column) = self.columns.0.get(self.column)
&& let Some(setter) = &column.setter && let Some(setter) = &column.setter
&& self.entries.get_mut(self.cursor).is_some() && self.entries.get_mut(self.cursor).is_some()
{ {
setter(self.entries.as_mut_slice(), self.cursor, value); setter(self, self.cursor, value.as_ref());
self.mode = None; self.mode = None;
} }
} }
@ -98,7 +106,7 @@ impl Taggart {
if let Some(Mode::Edit { value, index }) = &self.mode { if let Some(Mode::Edit { value, index }) = &self.mode {
self.mode = Some(Mode::Edit { self.mode = Some(Mode::Edit {
index: *index + 1, index: *index + 1,
value: format!("{value}{c}") value: format!("{value}{c}").into()
}); });
} }
} }

View file

@ -12,7 +12,7 @@ pub struct Taggart {
pub cursor: usize, pub cursor: usize,
pub offset: usize, pub offset: usize,
pub column: usize, pub column: usize,
pub columns: Columns<fn(&Entry)->Option<Arc<str>>, fn(&mut [Entry], usize, &str)>, pub columns: Columns<fn(&Entry)->Option<Arc<str>>, fn(&mut Self, usize, &str)>,
pub display: Measure<TuiOut>, pub display: Measure<TuiOut>,
pub tasks: Vec<Task>, pub tasks: Vec<Task>,
pub mode: Option<Mode>, pub mode: Option<Mode>,
@ -22,7 +22,7 @@ pub struct Taggart {
pub enum Mode { pub enum Mode {
Help, Help,
Edit { Edit {
value: String, value: Arc<str>,
index: usize, index: usize,
}, },
Apply { Apply {

View file

@ -1,20 +1,21 @@
use crate::*; use crate::*;
pub struct Columns<G, S>(pub Vec<Column<G, S>>);
pub struct Column<G, S> { pub struct Column<G, S> {
pub title: Arc<str>, pub title: Arc<str>,
pub width: usize, pub width: usize,
pub getter: G, pub getter: G,
pub setter: Option<S>, pub setter: Option<S>,
//pub styler: Option<U>, //pub styler: Option<U>,
} }
impl<T> Column<fn(&T)->Option<Arc<str>>, fn(&mut [T], usize, &str)> { type Getter<T> = fn(&T)->Option<Arc<str>>;
type Setter<T> = fn(&mut T, usize, &str);
impl<G, S> Column<Getter<G>, Setter<S>> {
pub fn new ( pub fn new (
title: &impl AsRef<str>, title: &impl AsRef<str>,
width: usize, width: usize,
getter: fn(&T)->Option<Arc<str>>, getter: Getter<G>,
) -> Self { ) -> Self {
Self { Self {
width, width,
@ -23,37 +24,49 @@ impl<T> Column<fn(&T)->Option<Arc<str>>, fn(&mut [T], usize, &str)> {
setter: None, setter: None,
} }
} }
fn setter (mut self, setter: fn(&mut [T], usize, &str)) -> Self { fn setter (mut self, setter: Setter<S>) -> Self {
self.setter = Some(setter); self.setter = Some(setter);
self self
} }
} }
macro_rules! setter { macro_rules! setter {
($method:ident) => { ($name:ident) => {{
|entries: &mut [Entry], index: usize, value: &str|{ fn $name (
if let Some(entries) = entries_under(entries, index) { state: &mut Taggart,
index: usize,
value: &str
) {
if let Some(entries) = entries_under(&mut state.entries, index) {
for entry in entries.iter() { for entry in entries.iter() {
entry.write().unwrap().$method(&value); entry.write().unwrap().$name(&value);
} }
} else if let Some(entry) = entries.get_mut(index) { } else if let Some(entry) = state.entries.get_mut(index) {
entry.$method(&value) entry.$name(&value);
} }
} }
} $name
}}
} }
impl Default for Columns<fn(&Entry)->Option<Arc<str>>, fn(&mut [Entry], usize, &str)> { pub struct Columns<G, S>(pub Vec<Column<G, S>>);
impl Default for Columns<fn(&Entry)->Option<Arc<str>>, fn(&mut Taggart, usize, &str)> {
fn default () -> Self { fn default () -> Self {
Self(vec![ Self(vec![
Column::new(&"Hash", 8, |entry: &Entry|entry.hash()), Column::new(&"Hash", 8, |entry: &Entry|entry.hash()),
Column::new(&"Size", 8, |entry: &Entry|entry.size()), Column::new(&"Size", 8, |entry: &Entry|entry.size()),
Column::new(&"File", 80, |entry: &Entry|entry.name()), Column::new(&"File", 80, |entry: &Entry|entry.name()),
Column::new(&"Artist", 30, |entry: &Entry|entry.artist()).setter(setter!(set_artist)), Column::new(&"Artist", 30, |entry: &Entry|entry.artist())
Column::new(&"Year", 5, |entry: &Entry|entry.year()).setter(setter!(set_year)), .setter(setter!(set_artist)),
Column::new(&"Release", 30, |entry: &Entry|entry.album()).setter(setter!(set_album)), Column::new(&"Year", 5, |entry: &Entry|entry.year())
Column::new(&"Track", 5, |entry: &Entry|entry.track()).setter(setter!(set_track)), .setter(setter!(set_year)),
Column::new(&"Title", 80, |entry: &Entry|entry.title()).setter(setter!(set_title)), Column::new(&"Release", 30, |entry: &Entry|entry.album())
.setter(setter!(set_album)),
Column::new(&"Track", 5, |entry: &Entry|entry.track())
.setter(setter!(set_track)),
Column::new(&"Title", 80, |entry: &Entry|entry.title())
.setter(setter!(set_title)),
]) ])
} }
} }

View file

@ -68,19 +68,19 @@ impl Entry {
pub fn track (&self) -> Option<Arc<str>> { pub fn track (&self) -> Option<Arc<str>> {
self.info.read().unwrap().track() self.info.read().unwrap().track()
} }
pub fn set_artist (&self, value: &impl AsRef<str> ) { pub fn set_artist (&self, value: &impl AsRef<str>) -> Option<Task> {
self.info.write().unwrap().set_artist(value) self.info.write().unwrap().set_artist(value)
} }
pub fn set_year (&self, value: &impl AsRef<str> ) { pub fn set_year (&self, value: &impl AsRef<str>) -> Option<Task> {
self.info.write().unwrap().set_year(value) self.info.write().unwrap().set_year(value)
} }
pub fn set_album (&self, value: &impl AsRef<str> ) { pub fn set_album (&self, value: &impl AsRef<str>) -> Option<Task> {
self.info.write().unwrap().set_album(value) self.info.write().unwrap().set_album(value)
} }
pub fn set_title (&self, value: &impl AsRef<str> ) { pub fn set_title (&self, value: &impl AsRef<str>) -> Option<Task> {
self.info.write().unwrap().set_title(value) self.info.write().unwrap().set_title(value)
} }
pub fn set_track (&self, value: &impl AsRef<str> ) { pub fn set_track (&self, value: &impl AsRef<str>) -> Option<Task> {
self.info.write().unwrap().set_track(value) self.info.write().unwrap().set_track(value)
} }
} }

View file

@ -159,42 +159,58 @@ impl Metadata {
_ => None _ => None
} }
} }
pub fn set_artist (&mut self, value: &impl AsRef<str> ) { pub fn set_artist (&mut self, value: &impl AsRef<str>) -> Option<Task> {
match self { match self {
Metadata::Music { artist, .. } => *artist = Some(value.as_ref().into()), Metadata::Music { artist, .. } => {
_ => {} *artist = Some(value.as_ref().into());
//todo!("emit task");
None
},
_ => None
} }
} }
pub fn set_year (&mut self, value: &impl AsRef<str> ) { pub fn set_year (&mut self, value: &impl AsRef<str> ) -> Option<Task> {
match self { match self {
Metadata::Music { year, .. } => { Metadata::Music { year, .. } => {
if let Ok(value) = value.as_ref().trim().parse::<u32>() { if let Ok(value) = value.as_ref().trim().parse::<u32>() {
*year = Some(value) *year = Some(value);
} }
//todo!("emit task");
None
}, },
_ => {} _ => None
} }
} }
pub fn set_album (&mut self, value: &impl AsRef<str> ) { pub fn set_album (&mut self, value: &impl AsRef<str>) -> Option<Task> {
match self { match self {
Metadata::Music { album, .. } => *album = Some(value.as_ref().into()), Metadata::Music { album, .. } => {
_ => {} *album = Some(value.as_ref().into());
//todo!("emit task");
None
},
_ => None
} }
} }
pub fn set_title (&mut self, value: &impl AsRef<str> ) { pub fn set_title (&mut self, value: &impl AsRef<str>) -> Option<Task> {
match self { match self {
Metadata::Music { title, .. } => *title = Some(value.as_ref().into()), Metadata::Music { title, .. } => {
_ => {} *title = Some(value.as_ref().into());
//todo!("emit task");
None
},
_ => None
} }
} }
pub fn set_track (&mut self, value: &impl AsRef<str>) { pub fn set_track (&mut self, value: &impl AsRef<str>) -> Option<Task> {
match self { match self {
Metadata::Music { track, .. } => { Metadata::Music { track, .. } => {
if let Ok(value) = value.as_ref().trim().parse::<u32>() { if let Ok(value) = value.as_ref().trim().parse::<u32>() {
*track = Some(value) *track = Some(value);
} }
//todo!("emit task");
None
}, },
_ => {} _ => None
} }
} }
} }