use crate::{ commands::{HelpManual, SimpleCommand, ViewCommand}, views::View, }; #[derive(Clone)] pub enum Command { Reactive(Box), View { cmd: Box, is_light: bool, }, } impl Command { pub fn view(command: C, is_light: bool) -> Self where C: ViewCommand + Clone + 'static, C::View: View, { let cmd = Box::new(ViewCmd(command)) as Box; Self::View { cmd, is_light } } pub fn reactive(command: C) -> Self where C: SimpleCommand + Clone + 'static, { let cmd = Box::new(command) as Box; Self::Reactive(cmd) } } impl Command { pub fn name(&self) -> &str { match self { Command::Reactive(cmd) => cmd.name(), Command::View { cmd, .. } => cmd.name(), } } pub fn parse(&mut self, args: &str) -> std::io::Result<()> { match self { Command::Reactive(cmd) => cmd.parse(args), Command::View { cmd, .. } => cmd.parse(args), } } } // type helper to deal with `Box`es #[derive(Clone)] struct ViewCmd(C); impl ViewCommand for ViewCmd where C: ViewCommand, C::View: View + 'static, { type View = Box; fn name(&self) -> &'static str { self.0.name() } fn usage(&self) -> &'static str { self.0.usage() } fn help(&self) -> Option { self.0.help() } fn display_config_option(&mut self, group: String, key: String, value: String) -> bool { self.0.display_config_option(group, key, value) } fn parse(&mut self, args: &str) -> std::io::Result<()> { self.0.parse(args) } fn spawn( &mut self, engine_state: &nu_protocol::engine::EngineState, stack: &mut nu_protocol::engine::Stack, value: Option, ) -> std::io::Result { let view = self.0.spawn(engine_state, stack, value)?; Ok(Box::new(view) as Box) } } pub trait SCommand: SimpleCommand + SCommandClone {} impl SCommand for T where T: 'static + SimpleCommand + Clone {} pub trait SCommandClone { fn clone_box(&self) -> Box; } impl SCommandClone for T where T: 'static + SCommand + Clone, { fn clone_box(&self) -> Box { Box::new(self.clone()) } } impl Clone for Box { fn clone(&self) -> Box { self.clone_box() } } pub trait VCommand: ViewCommand> + VCommandClone {} impl VCommand for T where T: 'static + ViewCommand> + Clone {} pub trait VCommandClone { fn clone_box(&self) -> Box; } impl VCommandClone for T where T: 'static + VCommand + Clone, { fn clone_box(&self) -> Box { Box::new(self.clone()) } } impl Clone for Box { fn clone(&self) -> Box { self.clone_box() } }