autosway 0.4.1

Automation program
Documentation
use std::fs::File;

use crate::common::*;
use mlua::prelude::*;
use std::future::Future;
use tokio::io::AsyncReadExt;
use urs::io::ReadExtra;

mod modules;

pub trait Module {
    fn load(&self, state: &mut State) -> impl Future<Output = Result<(), mlua::Error>>;
}

impl State {
    pub async fn setup_lua(&mut self) -> Result<(), LuaError> {
        if let Some(dir) = get_config_dir(ConfigDir::KnifeDir) {
            let s = if let Some(s) = dir.to_str() {
                s
            } else {
                log::log!(log::Error, "Could not add knife directory to load path");
                return Err(LuaError::RuntimeError("".to_string()));
            };

            let code = format!("package.path = package.path..';{}/?/init.lua'", s);
            self.lua.load(code).exec()?
        }

        self.load_module(modules::OS).await?;
        self.load_module(modules::FS).await?;
        self.load_module(modules::Net).await?;
        self.load_module(modules::I3).await?;
        self.load_module(modules::Util).await?;
        self.load_module(modules::Desktop).await?;
        self.load_module(modules::Multimedia).await?;
        self.load_module(modules::Extra).await?;

        self.lua.load(include_str!("../lua/globals.lua")).exec()?;

        if let Some(dir) = get_config_dir(ConfigDir::RootDir) {
            if let Ok(mut f) = File::open(dir.join("init.lua")) {
                self.lua.load(f.read_everything()?).exec()?;
            }
        }

        Ok(())
    }

    pub async fn load_module(&mut self, m: impl Module) -> Result<(), LuaError> {
        m.load(self).await?;
        Ok(())
    }

    pub async fn run_knife(&mut self, name: &str) -> Result<(), LuaError> {
        for knife in &self.knifes {
            if knife.name == name {
                let mut f = tokio::fs::File::open(&knife.init).await?;
                let mut buf = String::new();
                f.read_to_string(&mut buf).await?;
                self.lua.load(buf).exec_async().await?;
                return Ok(());
            }
        }

        log::log!(log::Error, "No knife found: {name}");
        Ok(())
    }
}