autosway 0.5.0

Automation program
Documentation
use super::*;
use std::sync::{Arc, RwLock};
use swayipc::{Connection, EventType};

struct LuaI3Event(EventType);
impl LuaUserData for LuaI3Event {}

pub struct I3wm;

impl Module for I3wm {
    fn load(&self, state: &mut State) -> Result<(), LuaError> {
        let module = state.lua.create_table()?;

        module.set("EVENT_WORKSPACE", LuaI3Event(EventType::Workspace))?;
        module.set("EVENT_OUTPUT", LuaI3Event(EventType::Output))?;
        module.set("EVENT_MODE", LuaI3Event(EventType::Mode))?;
        module.set("EVENT_WINDOW", LuaI3Event(EventType::Window))?;
        module.set("EVENT_BINDING", LuaI3Event(EventType::Binding))?;
        module.set("EVENT_SHUTDOWN", LuaI3Event(EventType::Shutdown))?;
        module.set("EVENT_TICK", LuaI3Event(EventType::Tick))?;
        module.set("EVENT_INPUT", LuaI3Event(EventType::Input))?;

        module.set(
            "EVENT_BARCONFIG_UPDATE",
            LuaI3Event(EventType::BarConfigUpdate),
        )?;

        module.set(
            "EVENT_BARSTATE_UPDATE",
            LuaI3Event(EventType::BarStateUpdate),
        )?;

        module.set(
            "run_command",
            state.lua.create_function(|_, command: String| {
                match Connection::new() {
                    Ok(mut c) => match c.run_command(command) {
                        Ok(_) => {}
                        Err(_) => return Ok(LuaValue::Boolean(false)),
                    },
                    Err(_) => return Ok(LuaValue::Boolean(false)),
                }

                Ok(LuaValue::Boolean(true))
            })?,
        )?;

        module.set(
            "get_workspaces",
            state.lua.create_function(|_, _: ()| {
                let jsons = Arc::new(RwLock::new(vec![]));
                if let Ok(mut c) = Connection::new() {
                    if let Ok(ws) = c.get_workspaces() {
                        ws.par_iter().for_each(|w| {
                            if let Ok(s) = serde_json::to_string(&w) {
                                let mut lock = jsons.write().unwrap();
                                lock.push(s);
                            };
                        });
                    }
                };
                let lock = jsons.read().unwrap();
                Ok((*lock).clone())
            })?,
        )?;

        module.set(
            "get_outputs",
            state.lua.create_function(|_, _: ()| {
                let jsons = Arc::new(RwLock::new(vec![]));
                if let Ok(mut c) = Connection::new() {
                    if let Ok(ws) = c.get_outputs() {
                        ws.par_iter().for_each(|w| {
                            if let Ok(s) = serde_json::to_string(&w) {
                                let mut lock = jsons.write().unwrap();
                                lock.push(s);
                            };
                        });
                    }
                };
                let lock = jsons.read().unwrap();
                Ok((*lock).clone())
            })?,
        )?;

        module.set(
            "get_seats",
            state.lua.create_function(|_, _: ()| {
                let jsons = Arc::new(RwLock::new(vec![]));
                if let Ok(mut c) = Connection::new() {
                    if let Ok(ws) = c.get_seats() {
                        ws.par_iter().for_each(|w| {
                            if let Ok(s) = serde_json::to_string(&w) {
                                let mut lock = jsons.write().unwrap();
                                lock.push(s);
                            };
                        });
                    }
                };
                let lock = jsons.read().unwrap();
                Ok((*lock).clone())
            })?,
        )?;

        module.set(
            "get_inputs",
            state.lua.create_function(|_, _: ()| {
                let jsons = Arc::new(RwLock::new(vec![]));
                if let Ok(mut c) = Connection::new() {
                    if let Ok(ws) = c.get_inputs() {
                        ws.par_iter().for_each(|w| {
                            if let Ok(s) = serde_json::to_string(&w) {
                                let mut lock = jsons.write().unwrap();
                                lock.push(s);
                            };
                        });
                    }
                };
                let lock = jsons.read().unwrap();
                Ok((*lock).clone())
            })?,
        )?;

        module.set(
            "subscribe_event",
            state.lua.create_function(
                |_, (event_type, callback): (LuaAnyUserData, LuaFunction)| {
                    let event_type = if event_type.is::<LuaI3Event>() {
                        event_type.take::<LuaI3Event>()?
                    } else {
                        return Ok(LuaValue::Boolean(false));
                    };

                    let c = match Connection::new() {
                        Ok(c) => c,
                        Err(_) => return Ok(LuaValue::Boolean(false)),
                    };

                    let stream = match c.subscribe(vec![event_type.0]) {
                        Ok(s) => s,
                        Err(_) => return Ok(LuaValue::Boolean(false)),
                    };

                    for event in stream {
                        let event = match event {
                            Ok(e) => e,
                            Err(_) => continue,
                        };

                        match event.event_type() {
                            e if e == event_type.0 => {
                                match serde_json::to_string(&event) {
                                    Ok(s) => callback.call::<LuaValue>(s)?,
                                    Err(_) => callback.call::<LuaValue>(LuaValue::Nil)?,
                                };
                            }
                            _ => {}
                        }
                    }

                    Ok(LuaValue::Nil)
                },
            )?,
        )?;

        module.set(
            "get_tree",
            state.lua.create_function(|lua, _: ()| {
                if let Ok(mut c) = Connection::new() {
                    if let Ok(ws) = c.get_tree() {
                        if let Ok(s) = serde_json::to_string(&ws) {
                            return s.into_lua(lua);
                        };
                    }
                };
                Ok(LuaValue::Nil)
            })?,
        )?;

        create_module(&state.lua, "autosway.i3", module)?;

        Ok(())
    }
}