From 144a829d82db142d1f6ae76adf49dddd77751428 Mon Sep 17 00:00:00 2001 From: Jesse Luehrs Date: Sat, 22 Dec 2018 02:59:15 -0500 Subject: cargo fmt --- src/cmd/mod.rs | 17 +++--- src/cmd/recommend.rs | 53 +++++++++++------- src/cmd/sql.rs | 9 ++- src/cmd/sync.rs | 7 ++- src/db.rs | 144 ++++++++++++++++++++++++++---------------------- src/lastfm/api_types.rs | 1 - src/lastfm/mod.rs | 101 ++++++++++++++++----------------- src/main.rs | 11 ++-- src/util.rs | 7 ++- 9 files changed, 186 insertions(+), 164 deletions(-) (limited to 'src') diff --git a/src/cmd/mod.rs b/src/cmd/mod.rs index 021bc48..68ae2fb 100644 --- a/src/cmd/mod.rs +++ b/src/cmd/mod.rs @@ -1,6 +1,6 @@ +mod recommend; mod sql; mod sync; -mod recommend; const _DUMMY_DEPENDENCY: &'static str = include_str!("../../Cargo.toml"); @@ -18,16 +18,19 @@ fn get_command() -> failure::Fallible> { sql::subcommand(), recommend::subcommand(), ]; - let mut app = app_from_crate!() - .subcommands(subcommands.into_iter().map(|s| { - s.setting(clap::AppSettings::DisableVersion) - })); + let mut app = app_from_crate!().subcommands( + subcommands + .into_iter() + .map(|s| s.setting(clap::AppSettings::DisableVersion)), + ); let matches = app.clone().get_matches(); let command: Box = match matches.subcommand() { ("sync", Some(matches)) => Box::new(sync::Command::new(matches)), ("sql", Some(matches)) => Box::new(sql::Command::new(matches)), - ("recommend", Some(matches)) => Box::new(recommend::Command::new(matches)?), + ("recommend", Some(matches)) => { + Box::new(recommend::Command::new(matches)?) + } (name, Some(_)) => bail!("unknown subcommand: {}", name), (_, None) => { @@ -35,7 +38,7 @@ fn get_command() -> failure::Fallible> { app.write_long_help(&mut stderr)?; eprintln!(""); bail!("no subcommand given") - }, + } }; Ok(command) diff --git a/src/cmd/recommend.rs b/src/cmd/recommend.rs index 2f613fa..1d8eecc 100644 --- a/src/cmd/recommend.rs +++ b/src/cmd/recommend.rs @@ -19,40 +19,48 @@ pub fn subcommand<'a, 'b>() -> clap::App<'a, 'b> { .arg( clap::Arg::with_name("count") .default_value("20") - .help("number of results to return") + .help("number of results to return"), ) .arg( clap::Arg::with_name("random") .long("random") - .help("picks randomly instead of by weight") + .help("picks randomly instead of by weight"), ) .arg( clap::Arg::with_name("album") .long("album") - .help("also choose a random album by the chosen artists") + .help("also choose a random album by the chosen artists"), ) .arg( clap::Arg::with_name("include") .long("include") .default_value("yearly") - .possible_values(&["all", "yearly", "monthly", "weekly"]) + .possible_values(&["all", "yearly", "monthly", "weekly"]), ) .arg( clap::Arg::with_name("exclude") .long("exclude") .default_value("weekly") - .possible_values(&["all", "yearly", "monthly", "weekly", "none"]) + .possible_values(&[ + "all", "yearly", "monthly", "weekly", "none", + ]), ) } impl Command { - pub fn new<'a>(matches: &clap::ArgMatches<'a>) -> failure::Fallible { + pub fn new<'a>( + matches: &clap::ArgMatches<'a>, + ) -> failure::Fallible { Ok(Command { count: matches.value_of("count").unwrap().parse()?, random: matches.is_present("random"), album: matches.is_present("album"), - include: db::parse_timewindow(matches.value_of("include").unwrap()), - exclude: db::parse_timewindow(matches.value_of("exclude").unwrap()), + include: db::parse_timewindow( + matches.value_of("include").unwrap(), + ), + exclude: db::parse_timewindow( + matches.value_of("exclude").unwrap(), + ), db: db::DB::new(&util::db_path()?)?, }) @@ -65,21 +73,24 @@ impl super::Command for Command { self.count, self.random, self.include, - self.exclude + self.exclude, )?; if self.album { - artists = artists.iter().map(|artist| { - Ok(format!( - "{} - {}", - artist, - self.db.recommend_album( - &artist, - self.random, - self.include, - self.exclude - )? - )) - }).collect::>>()?; + artists = artists + .iter() + .map(|artist| { + Ok(format!( + "{} - {}", + artist, + self.db.recommend_album( + &artist, + self.random, + self.include, + self.exclude + )? + )) + }) + .collect::>>()?; } for line in artists { println!("{}", line); diff --git a/src/cmd/sql.rs b/src/cmd/sql.rs index 81fdaef..404c97e 100644 --- a/src/cmd/sql.rs +++ b/src/cmd/sql.rs @@ -14,12 +14,12 @@ pub fn subcommand<'a, 'b>() -> clap::App<'a, 'b> { .arg( clap::Arg::with_name("query") .required(true) - .help("query to run") + .help("query to run"), ) .arg( clap::Arg::with_name("tsv") .long("tsv") - .help("format output as tsv") + .help("format output as tsv"), ) } @@ -47,8 +47,7 @@ impl super::Command for Command { if self.tsv { print_tsv(&rows); - } - else { + } else { print_table(&cols, &rows); } @@ -100,7 +99,7 @@ fn print_row(widths: &[usize], row: &[String]) { let fixed_width_row: Vec = row .iter() .zip(widths.iter()) - .map(|(s, width)| format!("{:width$}", s, width=width)) + .map(|(s, width)| format!("{:width$}", s, width = width)) .collect(); println!("{}", &fixed_width_row.join(" | ")); } diff --git a/src/cmd/sync.rs b/src/cmd/sync.rs index 99e39f7..b6019c4 100644 --- a/src/cmd/sync.rs +++ b/src/cmd/sync.rs @@ -14,7 +14,7 @@ pub fn subcommand<'a, 'b>() -> clap::App<'a, 'b> { .arg( clap::Arg::with_name("username") .required(true) - .help("last.fm username to fetch tracks for") + .help("last.fm username to fetch tracks for"), ) } @@ -39,7 +39,10 @@ impl super::Command for Command { bar.set_style( indicatif::ProgressStyle::default_bar() .progress_chars("=> ") - .template("Downloading {pos}/{len} tracks...\n{percent:>3}% [{wide_bar}] {eta:5}") + .template( + "Downloading {pos}/{len} tracks...\n\ + {percent:>3}% [{wide_bar}] {eta:5}", + ), ); db.insert_tracks(bar.wrap_iter(lastfm.tracks(from)))?; diff --git a/src/db.rs b/src/db.rs index c428da8..27737cb 100644 --- a/src/db.rs +++ b/src/db.rs @@ -39,24 +39,22 @@ pub struct DB { impl DB { pub fn new>(path: &P) -> failure::Fallible { let conn = if path.as_ref().exists() { - rusqlite::Connection::open(path) - .map_err(|e| { - let msg = format!( - "couldn't open db at {}", - path.as_ref().display() - ); - e.context(msg) - })? - } - else { + rusqlite::Connection::open(path).map_err(|e| { + let msg = format!( + "couldn't open db at {}", + path.as_ref().display() + ); + e.context(msg) + })? + } else { Self::create(path)? }; - return Ok(DB { conn }) + return Ok(DB { conn }); } fn create>( - path: &P + path: &P, ) -> failure::Fallible { eprintln!( "Initializing database at {}", @@ -65,49 +63,50 @@ impl DB { if let Some(parent) = path.as_ref().parent() { std::fs::create_dir_all(parent)?; - let conn = rusqlite::Connection::open(path) - .map_err(|e| { - let msg = format!( - "couldn't create db at {}", - path.as_ref().display() - ); - e.context(msg) - })?; + let conn = rusqlite::Connection::open(path).map_err(|e| { + let msg = format!( + "couldn't create db at {}", + path.as_ref().display() + ); + e.context(msg) + })?; conn.execute(SCHEMA, rusqlite::NO_PARAMS) .map_err(|e| e.context("failed to execute schema"))?; Ok(conn) - } - else { + } else { unimplemented!(); } } pub fn most_recent_timestamp(&self) -> failure::Fallible> { - Ok(self.conn.query_row( - "SELECT timestamp FROM tracks ORDER BY timestamp DESC LIMIT 1", - rusqlite::NO_PARAMS, - |row| Some(row.get(0)) - ).or_else(|e| { - match e { + Ok(self + .conn + .query_row( + "SELECT timestamp FROM tracks ORDER BY timestamp DESC LIMIT 1", + rusqlite::NO_PARAMS, + |row| Some(row.get(0)), + ) + .or_else(|e| match e { rusqlite::Error::QueryReturnedNoRows => Ok(None), _ => Err(e), - } - })?) + })?) } pub fn insert_tracks( &self, - tracks: impl Iterator, + tracks: impl Iterator, ) -> failure::Fallible<()> { - let mut sth = self.conn.prepare("INSERT INTO tracks VALUES (?, ?, ?, ?)")?; + let mut sth = self + .conn + .prepare("INSERT INTO tracks VALUES (?, ?, ?, ?)")?; for track in tracks { - sth.execute( - &[ + sth.execute(&[ &track.artist as &rusqlite::types::ToSql, &track.album, &track.name, &track.timestamp, - ]).map(|_| ())?; + ]) + .map(|_| ())?; } Ok(()) } @@ -115,19 +114,16 @@ impl DB { pub fn query( &self, query: &str, - mut f: F + mut f: F, ) -> failure::Fallible> { let mut sth = self.conn.prepare(query)?; - let cols = sth.column_names() - .iter() - .map(|s| s.to_string()) - .collect(); + let cols = sth.column_names().iter().map(|s| s.to_string()).collect(); - let rows = sth.query_and_then( - rusqlite::NO_PARAMS, - |row| { f(row); Ok(()) }, - )?; + let rows = sth.query_and_then(rusqlite::NO_PARAMS, |row| { + f(row); + Ok(()) + })?; // this call to collect() forces it to actually consume the iterator // (and therefore call the callbacks). what i really want here is for // there to be a query_for_each or something like that, but the weird @@ -146,35 +142,44 @@ impl DB { exclude: TimeWindow, ) -> failure::Fallible> { let exclude = if exclude != TimeWindow::None { - format!(" + format!( + " WHERE artist NOT IN ( SELECT DISTINCT(artist) FROM {} ) - ", timewindow_table(&exclude)) - } - else { + ", + timewindow_table(&exclude) + ) + } else { "".to_string() }; let order = if random { "ORDER BY random()" - } - else { + } else { "ORDER BY count(artist) * (strftime('%s') - max(timestamp)) DESC" }; - let sql = format!(" + let sql = format!( + " SELECT artist FROM {} {} GROUP BY artist {} LIMIT {} - ", timewindow_table(&include), exclude, order, count); + ", + timewindow_table(&include), + exclude, + order, + count + ); let mut sth = self.conn.prepare(&sql)?; - let artists = sth.query_and_then(rusqlite::NO_PARAMS, |row| { - Ok(row.get_checked(0)?) - })?.collect::>>()?; + let artists = sth + .query_and_then(rusqlite::NO_PARAMS, |row| { + Ok(row.get_checked(0)?) + })? + .collect::>>()?; Ok(artists) } @@ -189,25 +194,27 @@ impl DB { let mut params = vec![artist]; let exclude = if exclude != TimeWindow::None { params.push(artist); - format!(" + format!( + " AND album NOT IN ( SELECT DISTINCT(album) FROM {} WHERE artist = ? ) - ", timewindow_table(&exclude)) - } - else { + ", + timewindow_table(&exclude) + ) + } else { "".to_string() }; let order = if random { "ORDER BY random()" - } - else { + } else { "ORDER BY count(album) * (strftime('%s') - max(timestamp)) DESC" }; - let sql = format!(" + let sql = format!( + " SELECT album FROM {} WHERE artist = ? @@ -215,11 +222,16 @@ impl DB { GROUP BY album {} LIMIT 1 - ", timewindow_table(&include), exclude, order); + ", + timewindow_table(&include), + exclude, + order + ); let mut sth = self.conn.prepare(&sql)?; - let artists = sth.query_row::, _, _>(¶ms, |row| { - Ok(row.get_checked(0)?) - })??; + let artists = sth.query_row::, _, _>( + ¶ms, + |row| Ok(row.get_checked(0)?), + )??; Ok(artists) } diff --git a/src/lastfm/api_types.rs b/src/lastfm/api_types.rs index a7c3712..148b17f 100644 --- a/src/lastfm/api_types.rs +++ b/src/lastfm/api_types.rs @@ -43,4 +43,3 @@ pub struct recent_tracks_recenttracks { pub struct recent_tracks { pub recenttracks: recent_tracks_recenttracks, } - diff --git a/src/lastfm/mod.rs b/src/lastfm/mod.rs index 081038a..ed6e81b 100644 --- a/src/lastfm/mod.rs +++ b/src/lastfm/mod.rs @@ -43,23 +43,20 @@ impl<'a> Tracks<'a> { } let page = self.page.unwrap(); if page < 1 { - return Ok(()) + return Ok(()); } - let req = self.client.client - .get(API_ROOT) - .query(&[ - ("method", "user.getrecenttracks"), - ("api_key", &self.client.api_key), - ("user", &self.client.user), - ("format", "json"), - ("page", &format!("{}", page)), - ("limit", "200"), - ]); + let req = self.client.client.get(API_ROOT).query(&[ + ("method", "user.getrecenttracks"), + ("api_key", &self.client.api_key), + ("user", &self.client.user), + ("format", "json"), + ("page", &format!("{}", page)), + ("limit", "200"), + ]); let req = if let Some(from) = self.from { req.query(&[("from", &format!("{}", from))]) - } - else { + } else { req }; @@ -67,9 +64,11 @@ impl<'a> Tracks<'a> { if res.status().is_success() { let data: api_types::recent_tracks = res.json()?; - self.buf = data.recenttracks.track + self.buf = data + .recenttracks + .track .iter() - .filter(|t| { t.date.is_some() }) + .filter(|t| t.date.is_some()) .map(|t| { Ok(Track { artist: t.artist.text.clone(), @@ -81,8 +80,7 @@ impl<'a> Tracks<'a> { .collect::>>()?; self.page = Some(page - 1); Ok(()) - } - else { + } else { Err(failure::err_msg(res.status().as_str().to_string())) } } @@ -129,19 +127,16 @@ impl LastFMClient { &self, from: Option, ) -> failure::Fallible { - let req = self.client - .get(API_ROOT) - .query(&[ - ("method", "user.getrecenttracks"), - ("api_key", &self.api_key), - ("user", &self.user), - ("format", "json"), - ("limit", "200"), - ]); + let req = self.client.get(API_ROOT).query(&[ + ("method", "user.getrecenttracks"), + ("api_key", &self.api_key), + ("user", &self.user), + ("format", "json"), + ("limit", "200"), + ]); let req = if let Some(from) = from { req.query(&[("from", &format!("{}", from))]) - } - else { + } else { req }; @@ -150,8 +145,7 @@ impl LastFMClient { if res.status().is_success() { let data: api_types::recent_tracks = res.json()?; Ok(data) - } - else { + } else { Err(failure::err_msg(res.status().as_str().to_string())) } } @@ -162,32 +156,31 @@ fn find_api_key() -> failure::Fallible { .map_err(|e| e.context("failed to determine api key path"))?; let api_key = if api_key_path.exists() { let mut api_key = String::new(); - let mut f = std::fs::File::open(&api_key_path) - .map_err(|e| { - e.context(format!("failed to open {}", api_key_path.display())) - })?; - f.read_to_string(&mut api_key) - .map_err(|e| { - e.context(format!("failed to read from {}", api_key_path.display())) - })?; - api_key - } - else { - let api_key = rpassword::prompt_password_stderr( - &format!( - "last.fm api key (will be stored in {}): ", + let mut f = std::fs::File::open(&api_key_path).map_err(|e| { + e.context(format!("failed to open {}", api_key_path.display())) + })?; + f.read_to_string(&mut api_key).map_err(|e| { + e.context(format!( + "failed to read from {}", api_key_path.display() - ) - )?; + )) + })?; + api_key + } else { + let api_key = rpassword::prompt_password_stderr(&format!( + "last.fm api key (will be stored in {}): ", + api_key_path.display() + ))?; std::fs::create_dir_all(api_key_path.parent().unwrap())?; - let mut f = std::fs::File::create(&api_key_path) - .map_err(|e| { - e.context(format!("failed to open {}", api_key_path.display())) - })?; - f.write_all(api_key.as_bytes()) - .map_err(|e| { - e.context(format!("failed to write to {}", api_key_path.display())) - })?; + let mut f = std::fs::File::create(&api_key_path).map_err(|e| { + e.context(format!("failed to open {}", api_key_path.display())) + })?; + f.write_all(api_key.as_bytes()).map_err(|e| { + e.context(format!( + "failed to write to {}", + api_key_path.display() + )) + })?; api_key }; Ok(api_key.trim_end().to_string()) diff --git a/src/main.rs b/src/main.rs index 4f9ce07..8432184 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,13 +19,12 @@ mod util; fn main() { match cmd::run() { - Ok(_) => {}, + Ok(_) => {} Err(e) => { - let name = util::program_name() - .unwrap_or_else(|e| { - eprintln!("{}", e); - "?".to_string() - }); + let name = util::program_name().unwrap_or_else(|e| { + eprintln!("{}", e); + "?".to_string() + }); let cause = e .iter_chain() .fold(String::new(), |acc, x| acc + ": " + &format!("{}", x)); diff --git a/src/util.rs b/src/util.rs index 3e95981..0e99fc8 100644 --- a/src/util.rs +++ b/src/util.rs @@ -3,7 +3,8 @@ pub fn program_name() -> failure::Fallible { .next() .ok_or_else(|| format_err!("no program name found"))?; let path = std::path::Path::new(&program); - let filename = path.file_name() + let filename = path + .file_name() .ok_or_else(|| format_err!("invalid filename found"))? .to_string_lossy() .to_string(); @@ -19,7 +20,9 @@ pub fn db_path() -> failure::Fallible { pub fn api_key_path() -> failure::Fallible { Ok(directories::ProjectDirs::from("", "", "lastfm-query") - .ok_or_else(|| failure::err_msg("couldn't determine config directory"))? + .ok_or_else(|| { + failure::err_msg("couldn't determine config directory") + })? .config_dir() .join("lastfm-api-key")) } -- cgit v1.2.3-54-g00ecf