1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
use std::fs::read_to_string;
use mlua::{Function, Lua, Table};
use rust_embed::RustEmbed;
#[cfg(feature = "audio")]
pub mod audio;
#[cfg(feature = "clipboard")]
pub mod clipboard;
#[cfg(feature = "command")]
pub mod command;
#[cfg(feature = "displays")]
pub mod displays;
pub mod env;
#[cfg(feature = "events")]
pub mod event_handler;
#[cfg(feature = "events")]
pub mod event_sender;
pub mod json;
pub mod log;
#[cfg(feature = "network")]
pub mod network;
#[cfg(feature = "notify")]
pub mod notify;
#[cfg(feature = "open")]
pub mod open;
pub mod utils;
pub mod versions;
#[macro_export]
macro_rules! create_body {
($lua:expr, $($key:expr => $value:expr),*) => {
{
let tb = $lua.create_table()?;
$(tb.set($key, $value)?;)*
Ok(tb)
}
}
}
#[derive(RustEmbed)]
#[folder = "src/std/"]
struct StdFiles;
impl StdFiles {
pub fn get_lua_file(name: &str) -> Option<String> {
std::str::from_utf8(Self::get(&format!("{name}.lua"))?.data.as_ref())
.map(|x| x.to_string())
.ok()
}
}
pub async fn require(lua: &Lua, module: String) -> mlua::Result<Table> {
let loaded_modules = lua.globals().get::<_, Table>("__INTERNAL_LOADED_MODULES")?;
if let Ok(table) = loaded_modules.get::<_, Table>(&*module) {
return Ok(table);
}
let load_std = || async {
let code =
StdFiles::get_lua_file(&module).ok_or(mlua::Error::RuntimeError(format!("module {module} not found")))?;
let table: Table = lua.load(&code).set_name(&module)?.call_async(()).await?;
Ok::<_, mlua::Error>(table)
};
let load_teal = || async {
let table: Table = lua.load(tl::TEAL_LUA).set_name(&module)?.call_async(()).await?;
loaded_modules.set("tl", table.clone())?;
Ok::<_, mlua::Error>(table)
};
let globals = lua.globals();
#[rustfmt::skip]
let result: Table = match module.as_str() {
#[cfg(feature = "audio")] "audio" => audio::init(lua)?,
#[cfg(feature = "clipboard")] "clipboard" => clipboard::init(lua)?,
#[cfg(feature = "command")] "command" => command::init(lua)?,
#[cfg(feature = "displays")] "displays" => displays::init(lua)?,
"env" => env::init(lua)?,
#[cfg(feature = "events")] "event_handler_internal" => event_handler::init(lua)?,
#[cfg(feature = "events")] "event_handler" => load_std().await?,
#[cfg(feature = "events")] "event_sender_internal" => event_sender::init(lua)?,
#[cfg(feature = "events")] "event_sender" => load_std().await?,
"json" => json::init(lua)?,
"log" => log::init(lua)?,
#[cfg(feature = "network")] "network" => network::init(lua)?,
#[cfg(feature = "notify")] "notify" => notify::init(lua)?,
#[cfg(feature = "open")] "open" => open::init(lua)?,
"tl" => load_teal().await?,
"utils_internal" => utils::init(lua)?,
"versions" => versions::init(lua)?,
#[cfg(feature = "events")] "shortcuts" => load_std().await?,
"utils" => load_std().await?,
m if m.ends_with(".tl") => {
let tl = if let Ok(table) = loaded_modules.get::<_, Table>("tl") {
table
} else {
load_teal().await?
};
let load = tl.get::<_, Function>("load")?;
let data = read_to_string(m)?;
load.call::<_, Function>((data, m))?.call::<_, Table>(())?
}
_ => {
return globals
.get::<_, mlua::Function>("require_ref")?
.call_async(module)
.await;
}
};
loaded_modules.set(module, result.clone())?;
Ok(result)
}