Closed1
RustのCLIでluaのコンフィグファイルを使いたいときのサンプル

use mlua::prelude::*;
use mlua::{Lua, Result, Table, Value};
use std::fs;
#[derive(Debug)]
pub struct Config {
pub config_path: String,
pub slack_token: String,
}
pub fn init() -> anyhow::Result<Config> {
let config_path = get_config_path();
Ok(load_config(&config_path)?)
}
fn get_config_path() -> String {
if let Ok(path) = std::env::var("CLI_NAME_CONFIG_PATH") {
if !path.trim().is_empty() {
return path;
}
}
let home_dir = std::env::var("HOME").unwrap_or_else(|_| "/tmp".to_string());
format!("{}/.config/cliname", home_dir)
}
fn load_config(config_path: &str) -> Result<Config> {
let lua = Lua::new();
lua.load(format!(
r#"package.path = package.path .. ";{}/?.lua""#,
config_path
))
.exec()?;
let cliname_mod = lua.create_table()?;
let config_sub_mod = lua.create_table()?;
config_sub_mod.set("config_path", config_path)?;
cliname_mod.set("config", config_sub_mod)?;
let globals = lua.globals();
let package: LuaTable = globals.get("package")?;
let loaded: LuaTable = package.get("loaded")?;
loaded.set("cliname", cliname_mod)?;
let config_code = fs::read_to_string(&format!("{}/config.lua", config_path))?;
let config_eval = lua.load(&config_code).eval()?;
if let Value::Table(config_tbl) = config_eval {
let config_path: String = match config_tbl.get::<_, Option<String>>("config_path")? {
Some(v) => v,
None => config_path.to_string(),
};
let slack_tbl: Table = config_tbl.get("slack")?;
let token: String = slack_tbl.get("token")?;
Ok(Config {
config_path,
slack_token: token,
})
} else {
Err(mlua::Error::RuntimeError(
"config.lua did not return a table!".to_string(),
))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::fs;
#[test]
fn test_load_config() -> Result<()> {
let temp_dir = tempfile::tempdir()?;
let config_path = temp_dir.path();
let config_file_path = config_path.join("config.lua");
let secrets_file_path = config_path.join("secrets.lua");
let config_code = r#"
local secrets = require("secrets")
local cliname = require("cliname")
return {
slack = {
token = secrets.slack.token,
},
}
"#;
fs::write(&config_file_path, config_code)?;
let secrets_code = r#"
local M = {}
M.slack = {
token = "test_token"
}
return M
"#;
fs::write(&secrets_file_path, secrets_code)?;
let config = load_config(&config_path.to_string_lossy())?;
assert_eq!(config.config_path, config_path.to_string_lossy());
assert_eq!(config.slack_token, "test_token");
Ok(())
}
}
このスクラップは5ヶ月前にクローズされました