use std::default::Default; use mio::Token; use strum_macros::{Display, EnumIter}; use crate::command::{CommandNew, CommandSet, Parse, ParserError}; use crate::database::Db; use crate::queue::SendQueue; use crate::result::RudeResult; use crate::try_log; /// Root level of command. /// /// Every command must be implemented here, either directly or nested inside /// a subcommand somewhere. /// /// The parser matches against lowercase string representations of the enum /// variants #[derive(Clone, Debug, Display, EnumIter, Eq, Ord, PartialEq, PartialOrd)] pub enum Command { N, S, E, W, U, D, North, South, East, West, Up, Down, Dig, Help, Look, New(CommandNew), Quit, Save, Say, Set(CommandSet), Default, } impl Default for Command { fn default() -> Self { Self::Default } } impl Parse for Command { fn help(&self) -> &str { match self { Self::N => "n :: Move one room to the north.", Self::S => "s :: Move one room to the south.", Self::E => "e :: Move one room to the east.", Self::W => "w :: Move one room to the west.", Self::U => "u :: Move one room up.", Self::D => "d :: Move one room down.", Self::North => "north :: Move one room to the north.", Self::South => "south :: Move one room to the south.", Self::East => "east :: Move one room to the east.", Self::West => "west :: Move one room to the west.", Self::Up => "up :: Move one room up.", Self::Down => "down :: Move one room down.", Self::Dig => "dig DIRECTION:: Dig a new path to a new room in the provided direction.", Self::Help => "help [COMMAND]:: Provide help on a specific command, or an overview.", Self::Look => "look :: Take a look around the current room.", Self::New(_) => "new :: Create new things.", Self::Quit => "quit :: Quit playing and disconnect from the game.", Self::Save => "save :: Write player information to disk.", Self::Say => "say MESSAGE:: Say something to the room.", Self::Set(_) => "set OPTIONS :: Set various parameters.", Self::Default => "", } } fn parse_subcommand(&self, s: String) -> RudeResult<(Self, String)> { match self { Self::New(_) => { let (command, args) = try_log!(CommandNew::parse(s), "Unable to parse new subcommand"); Ok((Self::New(command), args)) } Self::Set(_) => { let (command, args) = try_log!(CommandSet::parse(s), "Unable to parse set subcommand"); Ok((Self::Set(command), args)) } Self::Default => Err(ParserError::Default.into()), _ => Ok((self.clone(), s)), } } fn subcommand_help(&self) -> Option { match self { Self::New(command_new) => Some(command_new.help_all()), Self::Set(command_set) => Some(command_set.help_all()), _ => None, } } fn dispatch_map_subcommand(&self, args: String, token: Token, db: &mut Db) -> SendQueue { match self { Self::New(command_new) => command_new.dispatch(command_new, args, token, db), Self::Set(command_set) => command_set.dispatch(command_set, args, token, db), _ => SendQueue::new(), } } fn dispatch_map(&self) -> fn(&Self, String, Token, &mut Db) -> SendQueue { match self { Self::N | Self::North => Self::dispatch_move_room, Self::S | Self::South => Self::dispatch_move_room, Self::E | Self::East => Self::dispatch_move_room, Self::W | Self::West => Self::dispatch_move_room, Self::U | Self::Up => Self::dispatch_move_room, Self::D | Self::Down => Self::dispatch_move_room, Self::Dig => Self::dispatch_dig, Self::Help => Self::dispatch_help, Self::New(_) => Self::dispatch_map_subcommand, Self::Look => Self::dispatch_look, Self::Quit => Self::dispatch_quit, Self::Save => Self::dispatch_save, Self::Say => Self::dispatch_say, Self::Set(_) => Self::dispatch_map_subcommand, Self::Default => Self::dispatch_default, } } }