From 1671db14c15cc04ed93d020fe547f97c72f204ac Mon Sep 17 00:00:00 2001 From: Rasmus Larsen Date: Mon, 20 May 2019 22:15:12 +0200 Subject: [PATCH] Move to enum-based commands --- src/command.rs | 64 ++++++++++++++++ src/commands.rs | 126 +++++++++++++++--------------- src/config.rs | 3 +- src/main.rs | 4 + src/traits.rs | 18 +---- src/ui/album.rs | 10 +-- src/ui/artist.rs | 10 +-- src/ui/layout.rs | 37 ++++----- src/ui/library.rs | 10 +-- src/ui/listview.rs | 182 +++++++++++++++++++++----------------------- src/ui/playlist.rs | 10 +-- src/ui/playlists.rs | 21 +++-- src/ui/queue.rs | 83 ++++++++++---------- src/ui/search.rs | 40 +++++----- src/ui/tabview.rs | 42 +++++----- 15 files changed, 343 insertions(+), 317 deletions(-) create mode 100644 src/command.rs diff --git a/src/command.rs b/src/command.rs new file mode 100644 index 0000000..aa507cf --- /dev/null +++ b/src/command.rs @@ -0,0 +1,64 @@ +#[derive(Clone, Serialize, Deserialize, Debug)] +pub enum PlaylistCommands { + Update, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub enum SeekInterval { + Forward, + Backwards, + Custom(usize), +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub enum TargetMode { + Current, + Selected, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub enum MoveMode { + Up, + Down, + Left, + Right, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub enum ShiftMode { + Up, + Down, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub enum GotoMode { + Album, + Artist, +} + +#[derive(Clone, Serialize, Deserialize, Debug)] +pub enum Command { + Quit, + TogglePlay, + Playlists(PlaylistCommands), + Stop, + Previous, + Next, + Clear, + Queue, + Play, + Save, + SaveQueue, + Delete, + Focus(String), + Seek(SeekInterval), + Repeat, + Shuffle, + Share(TargetMode), + Back, + Open, + Goto(GotoMode), + Move(MoveMode, Option), + Shift(ShiftMode, Option), + Search(String), +} diff --git a/src/commands.rs b/src/commands.rs index b0662b4..3b92d49 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -6,6 +6,16 @@ use cursive::event::{Event, Key}; use cursive::views::ViewRef; use cursive::Cursive; +use command::Command::{ + Back, Clear, Delete, Focus, Goto, Move, Next, Open, Play, Playlists, Previous, Quit, Repeat, + Save, SaveQueue, Seek, Share, Shift, Shuffle, Stop, TogglePlay, +}; +use command::GotoMode::{Album, Artist}; +use command::MoveMode::{Down, Left, Right, Up}; +use command::PlaylistCommands::Update; +use command::SeekInterval::{Backwards, Forward}; +use command::TargetMode::{Current, Selected}; +use command::{Command, ShiftMode}; use library::Library; use queue::{Queue, RepeatSetting}; use spotify::Spotify; @@ -227,15 +237,10 @@ impl CommandManager { } } - fn handle_callbacks( - &self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result, String> { + fn handle_callbacks(&self, s: &mut Cursive, cmd: &Command) -> Result, String> { let local = { let mut main: ViewRef = s.find_id("main").unwrap(); - main.on_command(s, cmd, args)? + main.on_command(s, cmd)? }; if let CommandResult::Consumed(output) = local { @@ -246,24 +251,18 @@ impl CommandManager { }); Ok(None) - } else if let Some(callback) = self.callbacks.get(cmd) { + } + /* handle default commands + else if let Some(callback) = self.callbacks.get(cmd) { callback.as_ref().map(|cb| cb(s, args)).unwrap_or(Ok(None)) - } else { + } */ + else { Err("Unknown command.".to_string()) } } - pub fn handle(&self, s: &mut Cursive, cmd: String) { - let components: Vec = cmd - .trim() - .split(' ') - .map(std::string::ToString::to_string) - .collect(); - - let cmd = self.handle_aliases(&components[0]); - let args = components[1..].to_vec(); - - let result = self.handle_callbacks(s, &cmd, &args); + pub fn handle(&self, s: &mut Cursive, cmd: Command) { + let result = self.handle_callbacks(s, &cmd); s.call_on_id("main", |v: &mut Layout| { v.set_result(result); @@ -272,22 +271,21 @@ impl CommandManager { s.on_event(Event::Refresh); } - pub fn register_keybinding, S: Into>( + pub fn register_keybinding>( this: Arc, cursive: &mut Cursive, event: E, - command: S, + command: Command, ) { - let cmd = command.into(); cursive.add_global_callback(event, move |s| { - this.handle(s, cmd.clone()); + this.handle(s, command.clone()); }); } pub fn register_keybindings( this: Arc, cursive: &mut Cursive, - keybindings: Option>, + keybindings: Option>, ) { let mut kb = Self::default_keybindings(); kb.extend(keybindings.unwrap_or_default()); @@ -301,51 +299,51 @@ impl CommandManager { } } - fn default_keybindings() -> HashMap { + fn default_keybindings() -> HashMap { let mut kb = HashMap::new(); - kb.insert("q".into(), "quit".into()); - kb.insert("P".into(), "toggleplay".into()); - kb.insert("R".into(), "playlists update".into()); - kb.insert("S".into(), "stop".into()); - kb.insert("<".into(), "previous".into()); - kb.insert(">".into(), "next".into()); - kb.insert("c".into(), "clear".into()); - kb.insert(" ".into(), "queue".into()); - kb.insert("Enter".into(), "play".into()); - kb.insert("s".into(), "save".into()); - kb.insert("Ctrl+s".into(), "save queue".into()); - kb.insert("d".into(), "delete".into()); - kb.insert("/".into(), "focus search".into()); - kb.insert(".".into(), "seek +500".into()); - kb.insert(",".into(), "seek -500".into()); - kb.insert("r".into(), "repeat".into()); - kb.insert("z".into(), "shuffle".into()); - kb.insert("x".into(), "share current".into()); - kb.insert("Shift+x".into(), "share selected".into()); + kb.insert("q".into(), Quit); + kb.insert("P".into(), TogglePlay); + kb.insert("R".into(), Playlists(Update)); + kb.insert("S".into(), Stop); + kb.insert("<".into(), Previous); + kb.insert(">".into(), Next); + kb.insert("c".into(), Clear); + kb.insert(" ".into(), Command::Queue); + kb.insert("Enter".into(), Play); + kb.insert("s".into(), Save); + kb.insert("Ctrl+s".into(), SaveQueue); + kb.insert("d".into(), Delete); + kb.insert("/".into(), Focus("search".into())); + kb.insert(".".into(), Seek(Forward)); + kb.insert(",".into(), Seek(Backwards)); + kb.insert("r".into(), Repeat); + kb.insert("z".into(), Shuffle); + kb.insert("x".into(), Share(Current)); + kb.insert("Shift+x".into(), Share(Selected)); - kb.insert("F1".into(), "focus queue".into()); - kb.insert("F2".into(), "focus search".into()); - kb.insert("F3".into(), "focus library".into()); - kb.insert("Backspace".into(), "back".into()); + kb.insert("F1".into(), Focus("queue".into())); + kb.insert("F2".into(), Focus("search".into())); + kb.insert("F3".into(), Focus("library".into())); + kb.insert("Backspace".into(), Back); - kb.insert("o".into(), "open".into()); - kb.insert("a".into(), "goto album".into()); - kb.insert("A".into(), "goto artist".into()); + kb.insert("o".into(), Open); + kb.insert("a".into(), Goto(Album)); + kb.insert("A".into(), Goto(Artist)); - kb.insert("Up".into(), "move up".into()); - kb.insert("Down".into(), "move down".into()); - kb.insert("Left".into(), "move left".into()); - kb.insert("Right".into(), "move right".into()); - kb.insert("PageUp".into(), "move up 5".into()); - kb.insert("PageDown".into(), "move down 5".into()); - kb.insert("k".into(), "move up".into()); - kb.insert("j".into(), "move down".into()); - kb.insert("h".into(), "move left".into()); - kb.insert("l".into(), "move right".into()); + kb.insert("Up".into(), Move(Up, None)); + kb.insert("Down".into(), Move(Down, None)); + kb.insert("Left".into(), Move(Left, None)); + kb.insert("Right".into(), Move(Right, None)); + kb.insert("PageUp".into(), Move(Up, Some(5))); + kb.insert("PageDown".into(), Move(Down, Some(5))); + kb.insert("k".into(), Move(Up, None)); + kb.insert("j".into(), Move(Down, None)); + kb.insert("h".into(), Move(Left, None)); + kb.insert("l".into(), Move(Right, None)); - kb.insert("Shift+Up".into(), "shift up".into()); - kb.insert("Shift+Down".into(), "shift down".into()); + kb.insert("Shift+Up".into(), Shift(ShiftMode::Up, None)); + kb.insert("Shift+Down".into(), Shift(ShiftMode::Down, None)); kb } diff --git a/src/config.rs b/src/config.rs index 977316b..4318853 100644 --- a/src/config.rs +++ b/src/config.rs @@ -3,13 +3,14 @@ use std::fs; use std::path::{Path, PathBuf}; use std::sync::RwLock; +use command::Command; use directories::ProjectDirs; pub const CLIENT_ID: &str = "d420a117a32841c2b3474932e49fb54b"; #[derive(Serialize, Deserialize, Debug, Default)] pub struct Config { - pub keybindings: Option>, + pub keybindings: Option>, pub theme: Option, pub use_nerdfont: Option, } diff --git a/src/main.rs b/src/main.rs index c78ea94..90cadb1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -46,6 +46,7 @@ use librespot::core::authentication::Credentials; mod album; mod artist; mod authentication; +mod command; mod commands; mod config; mod events; @@ -232,6 +233,8 @@ fn main() { }); }); + /* + TODO: Write parser for commands { let ev = event_manager.clone(); let cmd_manager = cmd_manager.clone(); @@ -244,6 +247,7 @@ fn main() { ev.trigger(); }); } + */ cursive.add_fullscreen_layer(layout.with_id("main")); diff --git a/src/traits.rs b/src/traits.rs index aae2c70..7fde625 100644 --- a/src/traits.rs +++ b/src/traits.rs @@ -6,6 +6,7 @@ use cursive::Cursive; use album::Album; use artist::Artist; +use command::Command; use commands::CommandResult; use library::Library; use queue::Queue; @@ -34,25 +35,14 @@ pub trait ViewExt: View { "".into() } - fn on_command( - &mut self, - _s: &mut Cursive, - _cmd: &str, - _args: &[String], - ) -> Result { + fn on_command(&mut self, _s: &mut Cursive, _cmd: &Command) -> Result { Ok(CommandResult::Ignored) } } impl ViewExt for IdView { - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - self.with_view_mut(move |v| v.on_command(s, cmd, args)) - .unwrap() + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + self.with_view_mut(move |v| v.on_command(s, cmd)).unwrap() } } diff --git a/src/ui/album.rs b/src/ui/album.rs index dbb4047..4f2a194 100644 --- a/src/ui/album.rs +++ b/src/ui/album.rs @@ -5,6 +5,7 @@ use cursive::Cursive; use album::Album; use artist::Artist; +use command::Command; use commands::CommandResult; use library::Library; use queue::Queue; @@ -69,12 +70,7 @@ impl ViewExt for AlbumView { format!("{} ({})", self.album.title, self.album.year) } - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - self.tabs.on_command(s, cmd, args) + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + self.tabs.on_command(s, cmd) } } diff --git a/src/ui/artist.rs b/src/ui/artist.rs index e7e8038..6b6716e 100644 --- a/src/ui/artist.rs +++ b/src/ui/artist.rs @@ -5,6 +5,7 @@ use cursive::view::ViewWrapper; use cursive::Cursive; use artist::Artist; +use command::Command; use commands::CommandResult; use library::Library; use queue::Queue; @@ -110,12 +111,7 @@ impl ViewExt for ArtistView { self.artist.name.clone() } - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - self.tabs.on_command(s, cmd, args) + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + self.tabs.on_command(s, cmd) } } diff --git a/src/ui/layout.rs b/src/ui/layout.rs index 849d534..5b6be84 100644 --- a/src/ui/layout.rs +++ b/src/ui/layout.rs @@ -12,6 +12,8 @@ use cursive::views::EditView; use cursive::{Cursive, Printer}; use unicode_width::UnicodeWidthStr; +use command::Command; +use command::Command::Focus; use commands::CommandResult; use events; use traits::{IntoBoxedViewExt, ViewExt}; @@ -283,29 +285,28 @@ impl View for Layout { } impl ViewExt for Layout { - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - if cmd == "focus" { - if let Some(view) = args.get(0) { + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + match cmd { + Command::Focus(view) => { if self.views.keys().any(|k| k == view) { self.set_view(view.clone()); let screen = self.views.get_mut(view).unwrap(); - screen.view.on_command(s, cmd, args)?; + screen.view.on_command(s, cmd)?; + } + + Ok(CommandResult::Consumed(None)) + } + Command::Back => { + self.pop_view(); + Ok(CommandResult::Consumed(None)) + } + _ => { + if let Some(screen) = self.get_current_screen_mut() { + screen.view.on_command(s, cmd) + } else { + Ok(CommandResult::Ignored) } } - - Ok(CommandResult::Consumed(None)) - } else if cmd == "back" { - self.pop_view(); - Ok(CommandResult::Consumed(None)) - } else if let Some(screen) = self.get_current_screen_mut() { - screen.view.on_command(s, cmd, args) - } else { - Ok(CommandResult::Ignored) } } } diff --git a/src/ui/library.rs b/src/ui/library.rs index c3ab05c..3163d6d 100644 --- a/src/ui/library.rs +++ b/src/ui/library.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use cursive::view::ViewWrapper; use cursive::Cursive; +use command::Command; use commands::CommandResult; use library::Library; use queue::Queue; @@ -48,12 +49,7 @@ impl ViewWrapper for LibraryView { } impl ViewExt for LibraryView { - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - self.tabs.on_command(s, cmd, args) + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + self.tabs.on_command(s, cmd) } } diff --git a/src/ui/listview.rs b/src/ui/listview.rs index f60c221..89defc9 100644 --- a/src/ui/listview.rs +++ b/src/ui/listview.rs @@ -10,6 +10,7 @@ use cursive::{Cursive, Printer, Rect, Vec2}; use unicode_width::UnicodeWidthStr; use clipboard::{ClipboardContext, ClipboardProvider}; +use command::{Command, GotoMode, MoveMode, TargetMode}; use commands::CommandResult; use library::Library; use queue::Queue; @@ -277,123 +278,116 @@ impl View for ListView { } impl ViewExt for ListView { - fn on_command( - &mut self, - _s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - if cmd == "play" { - self.queue.clear(); + fn on_command(&mut self, _s: &mut Cursive, cmd: &Command) -> Result { + match cmd { + Command::Play => { + self.queue.clear(); - if !self.attempt_play_all_tracks() { + if !self.attempt_play_all_tracks() { + let mut content = self.content.write().unwrap(); + if let Some(item) = content.get_mut(self.selected) { + item.play(self.queue.clone()); + } + } + + return Ok(CommandResult::Consumed(None)); + } + Command::Queue => { let mut content = self.content.write().unwrap(); if let Some(item) = content.get_mut(self.selected) { - item.play(self.queue.clone()); + item.queue(self.queue.clone()); + } + + return Ok(CommandResult::Consumed(None)); + } + Command::Save => { + let mut item = { + let content = self.content.read().unwrap(); + content.get(self.selected).cloned() + }; + + if let Some(item) = item.as_mut() { + item.toggle_saved(self.library.clone()); } } - return Ok(CommandResult::Consumed(None)); - } - - if cmd == "queue" { - let mut content = self.content.write().unwrap(); - if let Some(item) = content.get_mut(self.selected) { - item.queue(self.queue.clone()); - } - return Ok(CommandResult::Consumed(None)); - } - - if cmd == "save" { - let mut item = { - let content = self.content.read().unwrap(); - content.get(self.selected).cloned() - }; - - if let Some(item) = item.as_mut() { - item.toggle_saved(self.library.clone()); - } - } - - if cmd == "share" { - let source = args.get(0); - let url = - source.and_then(|source| match source.as_str() { - "selected" => self.content.read().ok().and_then(|content| { + Command::Share(mode) => { + let url = match mode { + TargetMode::Selected => self.content.read().ok().and_then(|content| { content.get(self.selected).and_then(ListItem::share_url) }), - "current" => self.queue.get_current().and_then(|t| t.share_url()), - _ => None, - }); + TargetMode::Current => self.queue.get_current().and_then(|t| t.share_url()), + }; - if let Some(url) = url { - ClipboardProvider::new() - .and_then(|mut ctx: ClipboardContext| ctx.set_contents(url)) - .ok(); - }; + if let Some(url) = url { + ClipboardProvider::new() + .and_then(|mut ctx: ClipboardContext| ctx.set_contents(url)) + .ok(); + } - return Ok(CommandResult::Consumed(None)); - } - - if cmd == "move" { - if let Some(dir) = args.get(0) { - let amount: usize = args - .get(1) - .unwrap_or(&"1".to_string()) - .parse() - .map_err(|e| format!("{:?}", e))?; + return Ok(CommandResult::Consumed(None)); + } + Command::Move(mode, amount) => { + let amount = match amount { + Some(amount) => *amount, + _ => 1, + }; let len = self.content.read().unwrap().len(); - if dir == "up" && self.selected > 0 { - self.move_focus(-(amount as i32)); - return Ok(CommandResult::Consumed(None)); - } - - if dir == "down" { - if self.selected < len.saturating_sub(1) { + match mode { + MoveMode::Up if self.selected > 0 => { + self.move_focus(-(amount as i32)); + return Ok(CommandResult::Consumed(None)); + } + MoveMode::Down if self.selected < len.saturating_sub(1) => { self.move_focus(amount as i32); return Ok(CommandResult::Consumed(None)); - } else if self.selected == len.saturating_sub(1) && self.can_paginate() { + } + MoveMode::Down + if self.selected == len.saturating_sub(1) && self.can_paginate() => + { self.pagination.call(&self.content); } + _ => {} } } - } - - if cmd == "open" { - let mut content = self.content.write().unwrap(); - if let Some(item) = content.get_mut(self.selected) { - let queue = self.queue.clone(); - let library = self.library.clone(); - if let Some(view) = item.open(queue, library) { - return Ok(CommandResult::View(view)); - } - } - } - - if cmd == "goto" { - let mut content = self.content.write().unwrap(); - if let Some(item) = content.get_mut(self.selected) { - let queue = self.queue.clone(); - let library = self.library.clone(); - let arg = args.get(0).cloned().unwrap_or_default(); - - if arg == "album" { - if let Some(album) = item.album(queue.clone()) { - let view = AlbumView::new(queue, library, &album).as_boxed_view_ext(); - return Ok(CommandResult::View(view)); - } - } - - if arg == "artist" { - if let Some(artist) = item.artist() { - let view = ArtistView::new(queue, library, &artist).as_boxed_view_ext(); + Command::Open => { + let mut content = self.content.write().unwrap(); + if let Some(item) = content.get_mut(self.selected) { + let queue = self.queue.clone(); + let library = self.library.clone(); + if let Some(view) = item.open(queue, library) { return Ok(CommandResult::View(view)); } } } - } + Command::Goto(mode) => { + let mut content = self.content.write().unwrap(); + if let Some(item) = content.get_mut(self.selected) { + let queue = self.queue.clone(); + let library = self.library.clone(); + + match mode { + GotoMode::Album => { + if let Some(album) = item.album(queue.clone()) { + let view = + AlbumView::new(queue, library, &album).as_boxed_view_ext(); + return Ok(CommandResult::View(view)); + } + } + GotoMode::Artist => { + if let Some(artist) = item.artist() { + let view = + ArtistView::new(queue, library, &artist).as_boxed_view_ext(); + return Ok(CommandResult::View(view)); + } + } + } + } + } + _ => {} + }; Ok(CommandResult::Ignored) } diff --git a/src/ui/playlist.rs b/src/ui/playlist.rs index 70b6667..f3da363 100644 --- a/src/ui/playlist.rs +++ b/src/ui/playlist.rs @@ -3,6 +3,7 @@ use std::sync::{Arc, RwLock}; use cursive::view::ViewWrapper; use cursive::Cursive; +use command::Command; use commands::CommandResult; use library::Library; use playlist::Playlist; @@ -43,12 +44,7 @@ impl ViewExt for PlaylistView { self.playlist.name.clone() } - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - self.list.on_command(s, cmd, args) + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + self.list.on_command(s, cmd) } } diff --git a/src/ui/playlists.rs b/src/ui/playlists.rs index 2912b01..57071a2 100644 --- a/src/ui/playlists.rs +++ b/src/ui/playlists.rs @@ -4,6 +4,7 @@ use cursive::view::ViewWrapper; use cursive::views::Dialog; use cursive::Cursive; +use command::Command; use commands::CommandResult; use library::Library; use playlist::Playlist; @@ -52,19 +53,17 @@ impl ViewWrapper for PlaylistsView { } impl ViewExt for PlaylistsView { - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - if cmd == "delete" { - if let Some(dialog) = self.delete_dialog() { - s.add_layer(dialog); + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + match cmd { + Command::Delete => { + if let Some(dialog) = self.delete_dialog() { + s.add_layer(dialog); + } + return Ok(CommandResult::Consumed(None)); } - return Ok(CommandResult::Consumed(None)); + _ => {} } - self.list.on_command(s, cmd, args) + self.list.on_command(s, cmd) } } diff --git a/src/ui/queue.rs b/src/ui/queue.rs index 78b6873..17e872a 100644 --- a/src/ui/queue.rs +++ b/src/ui/queue.rs @@ -6,6 +6,7 @@ use cursive::Cursive; use std::cmp::min; use std::sync::Arc; +use command::{Command, ShiftMode}; use commands::CommandResult; use library::Library; use queue::Queue; @@ -88,55 +89,51 @@ impl ViewWrapper for QueueView { } impl ViewExt for QueueView { - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - if cmd == "play" { - self.queue.play(self.list.get_selected_index(), true); - return Ok(CommandResult::Consumed(None)); - } + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + match cmd { + Command::Play => { + self.queue.play(self.list.get_selected_index(), true); + return Ok(CommandResult::Consumed(None)); + } + Command::Queue => { + return Ok(CommandResult::Ignored); + } + Command::Delete => { + self.queue.remove(self.list.get_selected_index()); + return Ok(CommandResult::Consumed(None)); + } + Command::Shift(mode, amount) => { + let amount = match amount { + Some(amount) => *amount, + _ => 1, + }; - if cmd == "queue" { - return Ok(CommandResult::Ignored); - } - - if cmd == "delete" { - self.queue.remove(self.list.get_selected_index()); - return Ok(CommandResult::Consumed(None)); - } - - if cmd == "shift" { - if let Some(dir) = args.get(0) { - let amount: usize = args - .get(1) - .unwrap_or(&"1".to_string()) - .parse() - .map_err(|e| format!("{:?}", e))?; let selected = self.list.get_selected_index(); let len = self.queue.len(); - if dir == "up" && selected > 0 { - self.queue.shift(selected, selected.saturating_sub(amount)); - self.list.move_focus(-(amount as i32)); - return Ok(CommandResult::Consumed(None)); - } else if dir == "down" && selected < len.saturating_sub(1) { - self.queue - .shift(selected, min(selected + amount as usize, len - 1)); - self.list.move_focus(amount as i32); - return Ok(CommandResult::Consumed(None)); + + match mode { + ShiftMode::Up if selected > 0 => { + self.queue.shift(selected, selected.saturating_sub(amount)); + self.list.move_focus(-(amount as i32)); + return Ok(CommandResult::Consumed(None)); + } + ShiftMode::Down if selected < len.saturating_sub(1) => { + self.queue + .shift(selected, min(selected + amount as usize, len - 1)); + self.list.move_focus(amount as i32); + return Ok(CommandResult::Consumed(None)); + } + _ => {} } } + Command::SaveQueue => { + let dialog = Self::save_dialog(self.queue.clone(), self.library.clone()); + s.add_layer(dialog); + return Ok(CommandResult::Consumed(None)); + } + _ => {} } - if cmd == "save" && args.get(0).unwrap_or(&"".to_string()) == "queue" { - let dialog = Self::save_dialog(self.queue.clone(), self.library.clone()); - s.add_layer(dialog); - return Ok(CommandResult::Consumed(None)); - } - - self.with_view_mut(move |v| v.on_command(s, cmd, args)) - .unwrap() + self.with_view_mut(move |v| v.on_command(s, cmd)).unwrap() } } diff --git a/src/ui/search.rs b/src/ui/search.rs index 9e19853..aa184fb 100644 --- a/src/ui/search.rs +++ b/src/ui/search.rs @@ -11,6 +11,7 @@ use std::sync::{Arc, Mutex, RwLock}; use album::Album; use artist::Artist; +use command::{Command, MoveMode}; use commands::CommandResult; use events::EventManager; use library::Library; @@ -435,42 +436,37 @@ impl View for SearchView { } impl ViewExt for SearchView { - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - if cmd == "search" && !args.is_empty() { - self.run_search(args.join(" ")); - return Ok(CommandResult::Consumed(None)); - } - - if cmd == "focus" { - self.edit_focused = true; - self.clear(); - return Ok(CommandResult::Consumed(None)); + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + match cmd { + Command::Search(query) => self.run_search(query.to_string()), + Command::Focus(view) => { + self.edit_focused = true; + self.clear(); + return Ok(CommandResult::Consumed(None)); + } + _ => {} } let result = if !self.edit_focused { - self.tabs.on_command(s, cmd, args)? + self.tabs.on_command(s, cmd)? } else { CommandResult::Ignored }; if let CommandResult::Ignored = result { - if cmd == "move" { - if let Some(dir) = args.get(0) { - if dir == "up" && !self.edit_focused { + match cmd { + Command::Move(mode, amount) => match mode { + MoveMode::Up if !self.edit_focused => { self.edit_focused = true; return Ok(CommandResult::Consumed(None)); } - - if dir == "down" && self.edit_focused { + MoveMode::Down if self.edit_focused => { self.edit_focused = false; return Ok(CommandResult::Consumed(None)); } - } + _ => {} + }, + _ => {} } } diff --git a/src/ui/tabview.rs b/src/ui/tabview.rs index 3d71c0d..23658e3 100644 --- a/src/ui/tabview.rs +++ b/src/ui/tabview.rs @@ -7,6 +7,7 @@ use cursive::traits::View; use cursive::{Cursive, Printer, Vec2}; use unicode_width::UnicodeWidthStr; +use command::{Command, MoveMode}; use commands::CommandResult; use traits::{IntoBoxedViewExt, ViewExt}; @@ -102,36 +103,33 @@ impl View for TabView { } impl ViewExt for TabView { - fn on_command( - &mut self, - s: &mut Cursive, - cmd: &str, - args: &[String], - ) -> Result { - if cmd == "move" { - if let Some(dir) = args.get(0) { - let amount: i32 = args - .get(1) - .unwrap_or(&"1".to_string()) - .parse() - .map_err(|e| format!("{:?}", e))?; + fn on_command(&mut self, s: &mut Cursive, cmd: &Command) -> Result { + match cmd { + Command::Move(mode, amount) => { + let amount = match amount { + Some(amount) => *amount, + _ => 1, + }; let len = self.tabs.len(); - if dir == "left" && self.selected > 0 { - self.move_focus(-amount); - return Ok(CommandResult::Consumed(None)); - } - - if dir == "right" && self.selected < len - 1 { - self.move_focus(amount); - return Ok(CommandResult::Consumed(None)); + match mode { + MoveMode::Left if self.selected > 0 => { + self.move_focus(-(amount as i32)); + return Ok(CommandResult::Consumed(None)); + } + MoveMode::Right if self.selected < len - 1 => { + self.move_focus(amount as i32); + return Ok(CommandResult::Consumed(None)); + } + _ => {} } } + _ => {} } if let Some(tab) = self.tabs.get_mut(self.selected) { - tab.view.on_command(s, cmd, args) + tab.view.on_command(s, cmd) } else { Ok(CommandResult::Ignored) }