caprice 0.3.3

A REPL for Rust projects featuring an easy to use, zsh like autocomplete feature.
Documentation
// cargo run --example spinning_square
//
// The tutorial is based entirely on the spinning square tutorial
// from the Piston Game Engine
// https://github.com/PistonDevelopers/Piston-Tutorials/tree/master/getting-started
extern crate graphics;
extern crate piston;

extern crate glutin_window;
extern crate opengl_graphics;

use glutin_window::GlutinWindow as Window;
use opengl_graphics::{GlGraphics, OpenGL};
use piston::event_loop::*;
use piston::input::*;
use piston::window::WindowSettings;

use caprice::{Caprice, CapriceCommand};

pub struct App {
    gl: GlGraphics, // OpenGL drawing backend.
    rotation: f64,  // Rotation for the square.
    pub bg_color: [f32; 4],
    pub fg_color: [f32; 4],
}

impl App {
    fn render(&mut self, args: &RenderArgs) {
        use graphics::*;

        let fg_color = self.fg_color;
        let bg_color = self.bg_color;

        let square = rectangle::square(0.0, 0.0, 50.0);
        let rotation = self.rotation;
        let (x, y) = (args.window_size[0] / 2.0, args.window_size[1] / 2.0);

        self.gl.draw(args.viewport(), |c, gl| {
            // Clear the screen.
            clear(bg_color, gl);

            let transform = c
                .transform
                .trans(x, y)
                .rot_rad(rotation)
                .trans(-25.0, -25.0);

            // Draw a box rotating around the middle of the screen.
            rectangle(fg_color, square, transform, gl);
        });
    }

    fn update(&mut self, args: &UpdateArgs) {
        // Rotate 2 radians per second.
        self.rotation += 2.0 * args.dt;
    }
}

fn main() {
    // create a caprice instance
    let caprice = Caprice::new()
        .disable_ctrl_c()
        // set keywords
        .set_keywords(vec![
            "exit".to_owned(),
            "red_square".to_owned(),
            "green_square".to_owned(),
            "red_background".to_owned(),
            "green_background".to_owned(),
            "blue_square".to_owned(),
            "blue_background".to_owned(),
        ])
        .init();

    // get the caprice channels
    let (tx, rx, handle) = caprice.run().unwrap();

    let opengl = OpenGL::V3_2;

    let mut window: Window = WindowSettings::new("spinning-square", [200, 200])
        .graphics_api(opengl)
        .exit_on_esc(true)
        .automatic_close(false)
        .build()
        .unwrap();
    let mut app = App {
        gl: GlGraphics::new(opengl),
        rotation: 0.0,
        bg_color: [0.0, 1.0, 0.0, 1.0],
        fg_color: [1.0, 0.0, 0.0, 1.0],
    };
    let mut events = Events::new(EventSettings::new());

    while let Some(e) = events.next(&mut window) {
        if let Some(r) = e.render_args() {
            app.render(&r);
        }

        if let Some(u) = e.update_args() {
            // check if we received a token from caprice
            if let Ok(color) = rx.try_recv() {
                // and react accordingly
                match color.as_str() {
                    "red_background" => app.bg_color = [1.0, 0.0, 0.0, 1.0],
                    "green_background" => app.bg_color = [0.0, 1.0, 0.0, 1.0],
                    "blue_background" => app.bg_color = [0.0, 0.0, 1.0, 1.0],
                    "red_square" => app.fg_color = [1.0, 0.0, 0.0, 1.0],
                    "green_square" => app.fg_color = [0.0, 1.0, 0.0, 1.0],
                    "blue_square" => app.fg_color = [0.0, 0.0, 1.0, 1.0],
                    "exit" => {
                        tx.send(CapriceCommand::Exit).unwrap();
                        // wait for caprice to exit, otherwise the terminal
                        // might be left in raw mode on exit
                        handle.join().unwrap().unwrap();
                        // exit the main application
                        break;
                    }
                    _ => {}
                }
                // It's necessary to send a continue command, otherwise the
                // Caprice thread will block.
                tx.send(CapriceCommand::Continue).unwrap();
            };
            app.update(&u);
        }
    }
}