chore: Update to edition 2024

* chore(deps): `cargo update`

* chore: update to Rust edition 2024 and apply fixes

Update the Rust edition and apply changes required in the new edition.
Also update the Cargo manifests to reflect the edition change, and
ensure changes automatically apply to workspace members in the future.

* chore: format all code with `rustfmt`

The new Rust edition comes with some new formatting defaults, which need
to be applied since the edition was increased.

* style: change suggested matches back to `if let`

There has been a breaking change in Rust edition 2024 that changed the
behavior of `if let` statements slightly. The new behavior is more in
line with what users would expect, but could lead to problems in
existing code. The automatic edition update therefore changed such `if
let` statements to match statements instead. That lead to deeply nested
code which was hard to reason about.

This changes most of them back to regular `if let` chains, as the new
behavior shouldn't cause problems for these cases.

---------

Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
This commit is contained in:
Thomas Frans
2025-03-11 10:06:39 +01:00
committed by GitHub
parent 7599a39970
commit 9c3c7f7c87
37 changed files with 334 additions and 408 deletions

560
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +1,14 @@
[package] [package]
authors = ["Henrik Friedrichsen <henrik@affekt.org>"]
description = "ncurses Spotify client written in Rust using librespot, inspired by ncmpc and the likes."
edition = "2021"
exclude = ["images/**"]
keywords = ["spotify", "ncurses", "librespot", "terminal"]
license = "BSD-2-Clause"
name = "ncspot" name = "ncspot"
readme = "README.md" readme = "README.md"
repository = "https://github.com/hrkfdn/ncspot"
version = "1.2.2" version = "1.2.2"
description = "ncurses Spotify client written in Rust using librespot, inspired by ncmpc and the likes."
exclude = ["images/**"]
keywords = ["spotify", "ncurses", "librespot", "terminal"]
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
[badges] [badges]
maintenance = {status = "actively-developed"} maintenance = {status = "actively-developed"}
@@ -19,6 +19,12 @@ members = [
"xtask" "xtask"
] ]
[workspace.package]
authors = ["Henrik Friedrichsen <henrik@affekt.org>"]
edition = "2024"
license = "BSD-2-Clause"
repository = "https://github.com/hrkfdn/ncspot"
[workspace.lints.clippy] [workspace.lints.clippy]
enum_glob_use = "warn" enum_glob_use = "warn"
use_self = "deny" use_self = "deny"

View File

@@ -790,7 +790,7 @@ pub fn parse(input: &str) -> Result<Vec<Command>, CommandParseError> {
_ => { _ => {
return Err(E::NoSuchCommand { return Err(E::NoSuchCommand {
cmd: command.into(), cmd: command.into(),
}) });
} }
}; };
commands.push(command); commands.push(command);

View File

@@ -4,9 +4,9 @@ use std::time::Duration;
use crate::application::UserData; use crate::application::UserData;
use crate::command::{ use crate::command::{
parse, Command, GotoMode, JumpMode, MoveAmount, MoveMode, SeekDirection, ShiftMode, TargetMode, Command, GotoMode, JumpMode, MoveAmount, MoveMode, SeekDirection, ShiftMode, TargetMode, parse,
}; };
use crate::config::{user_configuration_directory, Config}; use crate::config::{Config, user_configuration_directory};
use crate::events::EventManager; use crate::events::EventManager;
use crate::ext_traits::CursiveExt; use crate::ext_traits::CursiveExt;
use crate::library::Library; use crate::library::Library;
@@ -20,10 +20,10 @@ use crate::ui::help::HelpView;
use crate::ui::layout::Layout; use crate::ui::layout::Layout;
use crate::ui::modal::Modal; use crate::ui::modal::Modal;
use crate::ui::search_results::SearchResultsView; use crate::ui::search_results::SearchResultsView;
use cursive::Cursive;
use cursive::event::{Event, Key}; use cursive::event::{Event, Key};
use cursive::traits::View; use cursive::traits::View;
use cursive::views::Dialog; use cursive::views::Dialog;
use cursive::Cursive;
use log::{debug, error, info}; use log::{debug, error, info};
use ncspot::CONFIGURATION_FILE_NAME; use ncspot::CONFIGURATION_FILE_NAME;
use std::cell::RefCell; use std::cell::RefCell;

View File

@@ -12,7 +12,7 @@ use platform_dirs::AppDirs;
use crate::command::{SortDirection, SortKey}; use crate::command::{SortDirection, SortKey};
use crate::model::playable::Playable; use crate::model::playable::Playable;
use crate::queue; use crate::queue;
use crate::serialization::{Serializer, CBOR, TOML}; use crate::serialization::{CBOR, Serializer, TOML};
pub const CACHE_VERSION: u16 = 1; pub const CACHE_VERSION: u16 = 1;
pub const DEFAULT_COMMAND_KEY: char = ':'; pub const DEFAULT_COMMAND_KEY: char = ':';

View File

@@ -1,4 +1,4 @@
use crossbeam_channel::{unbounded, Receiver, Sender, TryIter}; use crossbeam_channel::{Receiver, Sender, TryIter, unbounded};
use cursive::{CbSink, Cursive}; use cursive::{CbSink, Cursive};
use crate::queue::QueueEvent; use crate::queue::QueueEvent;

View File

@@ -5,8 +5,8 @@ use log::{debug, error, info};
use tokio::net::{UnixListener, UnixStream}; use tokio::net::{UnixListener, UnixStream};
use tokio::runtime::Handle; use tokio::runtime::Handle;
use tokio::sync::watch::{Receiver, Sender}; use tokio::sync::watch::{Receiver, Sender};
use tokio_stream::wrappers::WatchStream;
use tokio_stream::StreamExt; use tokio_stream::StreamExt;
use tokio_stream::wrappers::WatchStream;
use tokio_util::codec::{FramedRead, FramedWrite, LinesCodec}; use tokio_util::codec::{FramedRead, FramedWrite, LinesCodec};
use crate::events::{Event, EventManager}; use crate::events::{Event, EventManager};

View File

@@ -7,8 +7,8 @@ use std::thread;
use log::{debug, error, info}; use log::{debug, error, info};
use rspotify::model::Id; use rspotify::model::Id;
use serde::de::DeserializeOwned;
use serde::Serialize; use serde::Serialize;
use serde::de::DeserializeOwned;
use crate::config::Config; use crate::config::Config;
use crate::config::{self, CACHE_VERSION}; use crate::config::{self, CACHE_VERSION};

View File

@@ -5,7 +5,7 @@ extern crate serde;
use std::{path::PathBuf, process::exit}; use std::{path::PathBuf, process::exit};
use application::{setup_logging, Application}; use application::{Application, setup_logging};
use config::set_configuration_base_path; use config::set_configuration_base_path;
use log::error; use log::error;
use ncspot::program_arguments; use ncspot::program_arguments;

View File

@@ -1,8 +1,8 @@
use std::fmt; use std::fmt;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use rspotify::model::artist::{FullArtist, SimplifiedArtist};
use rspotify::model::Id; use rspotify::model::Id;
use rspotify::model::artist::{FullArtist, SimplifiedArtist};
use crate::library::Library; use crate::library::Library;
use crate::model::playable::Playable; use crate::model::playable::Playable;

View File

@@ -4,8 +4,8 @@ use crate::queue::Queue;
use crate::traits::{ListItem, ViewExt}; use crate::traits::{ListItem, ViewExt};
use crate::utils::ms_to_hms; use crate::utils::ms_to_hms;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use rspotify::model::show::{FullEpisode, SimplifiedEpisode};
use rspotify::model::Id; use rspotify::model::Id;
use rspotify::model::show::{FullEpisode, SimplifiedEpisode};
use std::fmt; use std::fmt;
use std::sync::Arc; use std::sync::Arc;

View File

@@ -5,8 +5,8 @@ use std::{cmp::Ordering, iter::Iterator};
use rand::{rng, seq::IteratorRandom}; use rand::{rng, seq::IteratorRandom};
use log::{debug, warn}; use log::{debug, warn};
use rspotify::model::playlist::{FullPlaylist, SimplifiedPlaylist};
use rspotify::model::Id; use rspotify::model::Id;
use rspotify::model::playlist::{FullPlaylist, SimplifiedPlaylist};
use crate::model::playable::Playable; use crate::model::playable::Playable;
use crate::model::track::Track; use crate::model::track::Track;

View File

@@ -5,8 +5,8 @@ use crate::queue::Queue;
use crate::spotify::Spotify; use crate::spotify::Spotify;
use crate::traits::{IntoBoxedViewExt, ListItem, ViewExt}; use crate::traits::{IntoBoxedViewExt, ListItem, ViewExt};
use crate::ui::show::ShowView; use crate::ui::show::ShowView;
use rspotify::model::show::{FullShow, SimplifiedShow};
use rspotify::model::Id; use rspotify::model::Id;
use rspotify::model::show::{FullShow, SimplifiedShow};
use std::fmt; use std::fmt;
use std::sync::Arc; use std::sync::Arc;

View File

@@ -4,9 +4,9 @@ use std::sync::{Arc, RwLock};
use crate::config; use crate::config;
use crate::utils::ms_to_hms; use crate::utils::ms_to_hms;
use chrono::{DateTime, Utc}; use chrono::{DateTime, Utc};
use rspotify::model::Id;
use rspotify::model::album::FullAlbum; use rspotify::model::album::FullAlbum;
use rspotify::model::track::{FullTrack, SavedTrack, SimplifiedTrack}; use rspotify::model::track::{FullTrack, SavedTrack, SimplifiedTrack};
use rspotify::model::Id;
use crate::library::Library; use crate::library::Library;
use crate::model::album::Album; use crate::model::album::Album;

View File

@@ -6,8 +6,8 @@ use std::error::Error;
use std::sync::Arc; use std::sync::Arc;
use std::time::Duration; use std::time::Duration;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio_stream::wrappers::UnboundedReceiverStream;
use tokio_stream::StreamExt; use tokio_stream::StreamExt;
use tokio_stream::wrappers::UnboundedReceiverStream;
use zbus::object_server::SignalEmitter; use zbus::object_server::SignalEmitter;
use zbus::zvariant::{ObjectPath, Value}; use zbus::zvariant::{ObjectPath, Value};
use zbus::{connection, interface}; use zbus::{connection, interface};

View File

@@ -13,8 +13,8 @@ use librespot_playback::audio_backend;
use librespot_playback::audio_backend::SinkBuilder; use librespot_playback::audio_backend::SinkBuilder;
use librespot_playback::config::Bitrate; use librespot_playback::config::Bitrate;
use librespot_playback::config::PlayerConfig; use librespot_playback::config::PlayerConfig;
use librespot_playback::mixer::softmixer::SoftMixer;
use librespot_playback::mixer::MixerConfig; use librespot_playback::mixer::MixerConfig;
use librespot_playback::mixer::softmixer::SoftMixer;
use librespot_playback::player::Player; use librespot_playback::player::Player;
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use tokio::sync::mpsc; use tokio::sync::mpsc;
@@ -167,10 +167,9 @@ impl Spotify {
credentials: Credentials, credentials: Credentials,
) -> Result<Session, librespot_core::Error> { ) -> Result<Session, librespot_core::Error> {
let librespot_cache_path = config::cache_path("librespot"); let librespot_cache_path = config::cache_path("librespot");
let audio_cache_path = if let Some(false) = cfg.values().audio_cache { let audio_cache_path = match cfg.values().audio_cache {
None Some(false) => None,
} else { _ => Some(librespot_cache_path.join("files")),
Some(librespot_cache_path.join("files"))
}; };
let cache = Cache::new( let cache = Cache::new(
Some(librespot_cache_path.clone()), Some(librespot_cache_path.clone()),
@@ -206,9 +205,12 @@ impl Spotify {
info!("Initializing audio backend {}", backend_name); info!("Initializing audio backend {}", backend_name);
if backend_name == "pulseaudio" { if backend_name == "pulseaudio" {
env::set_var("PULSE_PROP_application.name", "ncspot"); // TODO: Audit that the environment access only happens in single-threaded code.
env::set_var("PULSE_PROP_stream.description", "ncurses Spotify client"); unsafe { env::set_var("PULSE_PROP_application.name", "ncspot") };
env::set_var("PULSE_PROP_media.role", "music"); // TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::set_var("PULSE_PROP_stream.description", "ncurses Spotify client") };
// TODO: Audit that the environment access only happens in single-threaded code.
unsafe { env::set_var("PULSE_PROP_media.role", "music") };
} }
Ok(backend.1) Ok(backend.1)
@@ -376,10 +378,13 @@ impl Spotify {
#[cfg(feature = "mpris")] #[cfg(feature = "mpris")]
fn send_mpris(&self, cmd: MprisCommand) { fn send_mpris(&self, cmd: MprisCommand) {
debug!("Sending mpris command: {:?}", cmd); debug!("Sending mpris command: {:?}", cmd);
if let Some(mpris_manager) = self.mpris.lock().unwrap().as_ref() { match self.mpris.lock().unwrap().as_ref() {
mpris_manager.send(cmd); Some(mpris_manager) => {
} else { mpris_manager.send(cmd);
warn!("mpris context is unitialized"); }
_ => {
warn!("mpris context is unitialized");
}
} }
} }

View File

@@ -14,7 +14,7 @@ use rspotify::model::{
PlaylistResult, PrivateUser, Recommendations, SavedAlbum, SavedTrack, SearchResult, SearchType, PlaylistResult, PrivateUser, Recommendations, SavedAlbum, SavedTrack, SearchResult, SearchType,
Show, ShowId, SimplifiedTrack, TrackId, UserId, Show, ShowId, SimplifiedTrack, TrackId, UserId,
}; };
use rspotify::{prelude::*, AuthCodeSpotify, ClientError, ClientResult, Config, Token}; use rspotify::{AuthCodeSpotify, ClientError, ClientResult, Config, Token, prelude::*};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio::task::JoinHandle; use tokio::task::JoinHandle;
@@ -101,21 +101,27 @@ impl WebApi {
channel.send(cmd).unwrap(); channel.send(cmd).unwrap();
let api_token = self.api.token.clone(); let api_token = self.api.token.clone();
let api_token_expiration = self.token_expiration.clone(); let api_token_expiration = self.token_expiration.clone();
Some(ASYNC_RUNTIME.get().unwrap().spawn_blocking(move || { Some(
if let Ok(Some(token)) = token_rx.recv() { ASYNC_RUNTIME
*api_token.lock().unwrap() = Some(Token { .get()
access_token: token.access_token, .unwrap()
expires_in: chrono::Duration::from_std(token.expires_in).unwrap(), .spawn_blocking(move || match token_rx.recv() {
scopes: HashSet::from_iter(token.scopes), Ok(Some(token)) => {
expires_at: None, *api_token.lock().unwrap() = Some(Token {
refresh_token: None, access_token: token.access_token,
}); expires_in: chrono::Duration::from_std(token.expires_in).unwrap(),
*api_token_expiration.write().unwrap() = scopes: HashSet::from_iter(token.scopes),
Utc::now() + ChronoDuration::from_std(token.expires_in).unwrap(); expires_at: None,
} else { refresh_token: None,
error!("Failed to update token"); });
} *api_token_expiration.write().unwrap() =
})) Utc::now() + ChronoDuration::from_std(token.expires_in).unwrap();
}
_ => {
error!("Failed to update token");
}
}),
)
} else { } else {
panic!("worker channel is not set"); panic!("worker channel is not set");
} }
@@ -131,8 +137,8 @@ impl WebApi {
Ok(v) => Some(v), Ok(v) => Some(v),
Err(ClientError::Http(error)) => { Err(ClientError::Http(error)) => {
debug!("http error: {:?}", error); debug!("http error: {:?}", error);
if let HttpError::StatusCode(response) = error.as_ref() { match error.as_ref() {
match response.status() { HttpError::StatusCode(response) => match response.status() {
429 => { 429 => {
let waiting_duration = response let waiting_duration = response
.header("Retry-After") .header("Retry-After")
@@ -150,9 +156,8 @@ impl WebApi {
error!("unhandled api error: {:?}", response); error!("unhandled api error: {:?}", response);
None None
} }
} },
} else { _ => None,
None
} }
} }
Err(e) => { Err(e) => {

View File

@@ -10,14 +10,14 @@ use librespot_core::token::Token;
use librespot_playback::mixer::Mixer; use librespot_playback::mixer::Mixer;
use librespot_playback::player::{Player, PlayerEvent as LibrespotPlayerEvent}; use librespot_playback::player::{Player, PlayerEvent as LibrespotPlayerEvent};
use log::{debug, error, info, warn}; use log::{debug, error, info, warn};
use std::sync::mpsc::Sender;
use std::sync::Arc; use std::sync::Arc;
use std::sync::mpsc::Sender;
use std::time::Duration; use std::time::Duration;
use std::{pin::Pin, time::SystemTime}; use std::{pin::Pin, time::SystemTime};
use tokio::sync::mpsc; use tokio::sync::mpsc;
use tokio::time; use tokio::time;
use tokio_stream::wrappers::UnboundedReceiverStream;
use tokio_stream::StreamExt; use tokio_stream::StreamExt;
use tokio_stream::wrappers::UnboundedReceiverStream;
#[derive(Debug)] #[derive(Debug)]
pub(crate) enum WorkerCommand { pub(crate) enum WorkerCommand {

View File

@@ -20,7 +20,7 @@ use crate::config::ConfigTheme;
/// load_color!(config_theme, primary, TerminalDefault) /// load_color!(config_theme, primary, TerminalDefault)
/// ``` /// ```
macro_rules! load_color { macro_rules! load_color {
( $theme: expr, $member: ident, $default: expr ) => { ( $theme: expr_2021, $member: ident, $default: expr_2021 ) => {
$theme $theme
.as_ref() .as_ref()
.and_then(|t| t.$member.clone()) .and_then(|t| t.$member.clone())

View File

@@ -1,8 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use cursive::Cursive;
use cursive::view::{View, ViewWrapper}; use cursive::view::{View, ViewWrapper};
use cursive::views::NamedView; use cursive::views::NamedView;
use cursive::Cursive;
use crate::command::Command; use crate::command::Command;
use crate::commands::CommandResult; use crate::commands::CommandResult;

View File

@@ -1,7 +1,7 @@
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use cursive::view::ViewWrapper;
use cursive::Cursive; use cursive::Cursive;
use cursive::view::ViewWrapper;
use crate::command::Command; use crate::command::Command;
use crate::commands::CommandResult; use crate::commands::CommandResult;

View File

@@ -1,8 +1,8 @@
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use std::thread; use std::thread;
use cursive::view::ViewWrapper;
use cursive::Cursive; use cursive::Cursive;
use cursive::view::ViewWrapper;
use rspotify::model::AlbumType; use rspotify::model::AlbumType;
use crate::command::Command; use crate::command::Command;

View File

@@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use cursive::view::ViewWrapper;
use cursive::Cursive; use cursive::Cursive;
use cursive::view::ViewWrapper;
use crate::command::Command; use crate::command::Command;
use crate::commands::CommandResult; use crate::commands::CommandResult;

View File

@@ -1,8 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use cursive::Cursive;
use cursive::view::{Margins, ViewWrapper}; use cursive::view::{Margins, ViewWrapper};
use cursive::views::{Dialog, NamedView, ScrollView, SelectView}; use cursive::views::{Dialog, NamedView, ScrollView, SelectView};
use cursive::Cursive;
use crate::commands::CommandResult; use crate::commands::CommandResult;
use crate::ext_traits::SelectViewExt; use crate::ext_traits::SelectViewExt;

View File

@@ -7,7 +7,7 @@ use std::sync::{Arc, RwLock};
use cursive::theme::{ColorStyle, ColorType, PaletteColor}; use cursive::theme::{ColorStyle, ColorType, PaletteColor};
use cursive::{Cursive, Printer, Vec2, View}; use cursive::{Cursive, Printer, Vec2, View};
use ioctl_rs::{ioctl, TIOCGWINSZ}; use ioctl_rs::{TIOCGWINSZ, ioctl};
use log::{debug, error}; use log::{debug, error};
use crate::command::{Command, GotoMode}; use crate::command::{Command, GotoMode};
@@ -117,9 +117,12 @@ impl CoverView {
draw_offset.x += (draw_size.x - size.x) / 2; draw_offset.x += (draw_size.x - size.x) / 2;
draw_offset.y += (draw_size.y - size.y) - (draw_size.y - size.y) / 2; draw_offset.y += (draw_size.y - size.y) - (draw_size.y - size.y) / 2;
let cmd = format!("{{\"action\":\"add\",\"scaler\":\"fit_contain\",\"identifier\":\"cover\",\"x\":{},\"y\":{},\"width\":{},\"height\":{},\"path\":\"{}\"}}\n", let cmd = format!(
draw_offset.x, draw_offset.y, "{{\"action\":\"add\",\"scaler\":\"fit_contain\",\"identifier\":\"cover\",\"x\":{},\"y\":{},\"width\":{},\"height\":{},\"path\":\"{}\"}}\n",
size.x, size.y, draw_offset.x,
draw_offset.y,
size.x,
size.y,
path.to_str().unwrap() path.to_str().unwrap()
); );

View File

@@ -1,10 +1,10 @@
use std::collections::HashMap; use std::collections::HashMap;
use cursive::Cursive;
use cursive::theme::Effect; use cursive::theme::Effect;
use cursive::utils::markup::StyledString; use cursive::utils::markup::StyledString;
use cursive::view::ViewWrapper; use cursive::view::ViewWrapper;
use cursive::views::{ScrollView, TextView}; use cursive::views::{ScrollView, TextView};
use cursive::Cursive;
use ncspot::CONFIGURATION_FILE_NAME; use ncspot::CONFIGURATION_FILE_NAME;
use crate::command::{Command, MoveAmount, MoveMode}; use crate::command::{Command, MoveAmount, MoveMode};

View File

@@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use cursive::view::ViewWrapper;
use cursive::Cursive; use cursive::Cursive;
use cursive::view::ViewWrapper;
use strum::IntoEnumIterator; use strum::IntoEnumIterator;
use crate::command::Command; use crate::command::Command;

View File

@@ -1,6 +1,6 @@
use cursive::view::scroll::Scroller; use cursive::view::scroll::Scroller;
use log::info; use log::info;
use std::cmp::{max, min, Ordering}; use std::cmp::{Ordering, max, min};
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use cursive::align::HAlign; use cursive::align::HAlign;

View File

@@ -1,7 +1,7 @@
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
use cursive::view::ViewWrapper;
use cursive::Cursive; use cursive::Cursive;
use cursive::view::ViewWrapper;
use crate::command::Command; use crate::command::Command;
use crate::commands::CommandResult; use crate::commands::CommandResult;

View File

@@ -1,8 +1,8 @@
use std::sync::Arc; use std::sync::Arc;
use cursive::Cursive;
use cursive::view::{Margins, ViewWrapper}; use cursive::view::{Margins, ViewWrapper};
use cursive::views::Dialog; use cursive::views::Dialog;
use cursive::Cursive;
use crate::command::Command; use crate::command::Command;
use crate::commands::CommandResult; use crate::commands::CommandResult;

View File

@@ -1,7 +1,7 @@
use cursive::Cursive;
use cursive::traits::{Nameable, Resizable}; use cursive::traits::{Nameable, Resizable};
use cursive::view::{Margins, ViewWrapper}; use cursive::view::{Margins, ViewWrapper};
use cursive::views::{Dialog, EditView, ScrollView, SelectView}; use cursive::views::{Dialog, EditView, ScrollView, SelectView};
use cursive::Cursive;
use std::cmp::min; use std::cmp::min;
use std::sync::Arc; use std::sync::Arc;

View File

@@ -16,10 +16,10 @@ use crate::traits::{ListItem, ViewExt};
use crate::ui::listview::ListView; use crate::ui::listview::ListView;
use crate::ui::pagination::Pagination; use crate::ui::pagination::Pagination;
use crate::ui::tabbedview::TabbedView; use crate::ui::tabbedview::TabbedView;
use cursive::view::ViewWrapper;
use cursive::Cursive; use cursive::Cursive;
use rspotify::model::search::SearchResult; use cursive::view::ViewWrapper;
use rspotify::model::SearchType; use rspotify::model::SearchType;
use rspotify::model::search::SearchResult;
use std::sync::{Arc, RwLock}; use std::sync::{Arc, RwLock};
pub struct SearchResultsView { pub struct SearchResultsView {

View File

@@ -1,7 +1,7 @@
use std::sync::Arc; use std::sync::Arc;
use cursive::view::ViewWrapper;
use cursive::Cursive; use cursive::Cursive;
use cursive::view::ViewWrapper;
use crate::command::Command; use crate::command::Command;
use crate::commands::CommandResult; use crate::commands::CommandResult;

View File

@@ -1,11 +1,11 @@
use std::sync::Arc; use std::sync::Arc;
use cursive::Printer;
use cursive::align::HAlign; use cursive::align::HAlign;
use cursive::event::{Event, EventResult, MouseButton, MouseEvent}; use cursive::event::{Event, EventResult, MouseButton, MouseEvent};
use cursive::theme::{ColorStyle, ColorType, PaletteColor}; use cursive::theme::{ColorStyle, ColorType, PaletteColor};
use cursive::traits::View; use cursive::traits::View;
use cursive::vec::Vec2; use cursive::vec::Vec2;
use cursive::Printer;
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;
use crate::library::Library; use crate::library::Library;

View File

@@ -1,12 +1,12 @@
use std::cmp::min; use std::cmp::min;
use cursive::{ use cursive::{
Cursive, Printer, Vec2, View,
align::HAlign, align::HAlign,
event::{Event, EventResult, MouseButton, MouseEvent}, event::{Event, EventResult, MouseButton, MouseEvent},
theme::ColorStyle, theme::ColorStyle,
view::Nameable, view::Nameable,
views::NamedView, views::NamedView,
Cursive, Printer, Vec2, View,
}; };
use unicode_width::UnicodeWidthStr; use unicode_width::UnicodeWidthStr;

View File

@@ -3,7 +3,10 @@
[package] [package]
name = "xtask" name = "xtask"
version = "0.1.0" version = "0.1.0"
edition = "2021" authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
[dependencies] [dependencies]
clap_mangen = "0.2.26" clap_mangen = "0.2.26"

View File

@@ -1,9 +1,9 @@
use std::path::PathBuf; use std::path::PathBuf;
use std::{env, fs}; use std::{env, fs};
use clap::ArgMatches;
use clap::builder::PathBufValueParser; use clap::builder::PathBufValueParser;
use clap::error::{Error, ErrorKind}; use clap::error::{Error, ErrorKind};
use clap::ArgMatches;
use clap_complete::Shell; use clap_complete::Shell;
use ncspot::{AUTHOR, BIN_NAME}; use ncspot::{AUTHOR, BIN_NAME};