Skip to content

Instantly share code, notes, and snippets.

@matthewjberger
Created January 6, 2024 23:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save matthewjberger/e6180831729483a10298aa797267d2a2 to your computer and use it in GitHub Desktop.
Save matthewjberger/e6180831729483a10298aa797267d2a2 to your computer and use it in GitHub Desktop.
A tiny command pattern in rust
#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize)]
pub enum Command {
#[default]
Empty,
Exit,
}
impl Command {
pub fn execute(&mut self, context: &mut Context) {
match self {
Self::Exit => context.should_exit = true,
_ => {}
}
}
pub fn undo(&mut self, _context: &mut Context) {
match self {
Self::Empty => {}
_ => {}
}
}
}
#[derive(Default, Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct CommandList {
pub pending_commands: Vec<Command>,
pub undo_commands: Vec<Command>,
pub redo_commands: Vec<Command>,
}
impl CommandList {
pub fn execute_pending_commands(&mut self, context: &mut Context) {
self.pending_commands
.drain(..)
.collect::<Vec<_>>()
.into_iter()
.for_each(|mut command| command.execute(context))
}
pub fn undo(&mut self, context: &mut Context) {
if let Some(mut command) = self.undo_commands.pop() {
command.undo(context);
self.redo_commands.push(command);
}
}
pub fn redo(&mut self, context: &mut Context) {
if let Some(mut command) = self.redo_commands.pop() {
command.execute(context);
self.undo_commands.push(command);
}
}
}
#[derive(Default, Debug)]
pub struct Context {
pub should_exit: bool,
}
fn main() {
let mut context = Context::default();
let mut command_list = CommandList::default();
command_list.pending_commands.push(Command::Exit);
command_list.execute_pending_commands(&mut context);
println!("Context after execution: {:?}", context);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment