davis 0.1.1

An CLI client for MPD.
use crate::ansi::{FormattedString, Style};
use crate::config::{Config, Tag};
use crate::error::Error;
use crate::table::{Row, Table};
use crate::tags::Tags;
use mpdrs::Song;

pub fn now_playing(client: &mut mpdrs::Client, conf: &Config) -> Result<(), Error> {
    let song = match client.currentsong()? {
        None => {
            println!("Not playing.");
            return Ok(());
        }
        Some(s) => s,
    };

    let tags = Tags::from_song_and_raw_comments(
        &song,
        client
            .readcomments(&*song.file)?
            .collect::<Result<_, _>>()?,
    );

    let table_rows = conf
        .tags
        .iter()
        .map(|Tag { tag, label }| {
            tags.get(&*tag)
                .iter()
                .map(|value| {
                    Row::new(vec![
                        FormattedString::new(&*label.as_ref().unwrap_or(tag)).style(Style::Bold),
                        FormattedString::new(*value),
                    ])
                })
                .collect::<Vec<_>>()
        })
        .flat_map(IntoIterator::into_iter)
        .collect::<Vec<_>>();

    println!("{}", header(&song, &tags));
    if !table_rows.is_empty() {
        println!("\n{}", Table { rows: &*table_rows },);
    }
    Ok(())
}

fn header(song: &Song, tags: &Tags) -> String {
    classical_work_description(tags)
        .or_else(|| popular_music_title(song))
        .unwrap_or_else(|| song.file.clone())
}

fn classical_work_description(tags: &Tags) -> Option<String> {
    let title = tags
        .joined(&["MOVEMENTNUMBER", "MOVEMENT"], ". ")
        .or_else(|| tags.get_option_joined("TITLE"))?;

    Some(format!(
        "{}\n{}\n{}",
        FormattedString::new(&*tags.get_option_joined("COMPOSER")?).style(Style::Bold),
        FormattedString::new(&*tags.get_option_joined("WORK")?).style(Style::Bold),
        FormattedString::new(&*title).style(Style::Bold)
    ))
}

fn popular_music_title(song: &Song) -> Option<String> {
    Some(format!(
        "{}\n{}",
        FormattedString::new(song.artist.as_deref()?).style(Style::Bold),
        FormattedString::new(&*song.title.as_deref()?).style(Style::Bold),
    ))
}