1use std::{
2 collections::HashMap,
3 sync::Mutex,
4};
5
6use lazy_static::lazy_static;
7
8use emacs::{defun, Env, Value, Result};
9use emacs::raw::emacs_env;
10
11use libloading::{Library, Symbol};
12
13emacs::plugin_is_GPL_compatible!();
14
15lazy_static! {
16 static ref LIBRARIES: Mutex<HashMap<String, Library>> = Mutex::new(HashMap::new());
17}
18
19const INIT_FROM_ENV: &str = "emacs_rs_module_init";
20
21macro_rules! message {
22 ($env:expr, $fmt:expr $(, $args:expr)*) => {
23 $env.message(format!($fmt $(, $args)*))
24 };
25}
26
27#[emacs::module(name = "rs-module", separator = "/")]
29fn init(env: &Env) -> Result<Value<'_>> {
30 message!(env, "[rs-module]: defined functions...")
31}
32
33#[defun]
37fn load(env: &Env, path: String) -> Result<Value<'_>> {
38 let mut libraries = LIBRARIES.lock()
39 .expect("Failed to acquire lock for module map");
40 match libraries.remove(&path) {
42 Some(l) => message!(env, "[{}]: unloaded {:?}...", path, l)?,
43 None => message!(env, "[{}]: not loaded yet", path)?,
44 };
45 message!(env, "[{}]: loading...", path)?;
46 let lib = Library::new(&path)?;
47 message!(env, "[{}]: initializing...", path)?;
48 unsafe {
49 let rs_init: Symbol<'_, unsafe extern fn(*mut emacs_env) -> u32> =
50 lib.get(INIT_FROM_ENV.as_bytes())?;
51 rs_init(env.raw());
52 }
53 libraries.insert(path.clone(), lib);
54 message!(env, "[{}]: loaded and initialized", path)
55}