Add initial support for hooks

A new optional section of the configuration defined using the lua return
statement, which can be used to define append only things, such as hooks
and callbacks, specific to each config file.

Example

```lua
version = "0.0.0"

return {
  -- Adds messages to pass when xplr loads (similar to `--on-load`)
  on_load = {
    { LogInfo = "Hello xplr user," },
    { LogSuccess = "Configuration successfully loaded!" },
  }
}
```
pull/523/head
Arijit Basu 2 years ago committed by Arijit Basu
parent 723dd6ec2c
commit deb28fa14a

@ -76,3 +76,25 @@ in `xplr.fn.custom`.
You can also use nested tables such as
`xplr.fn.custom.my_plugin.my_function` to define custom functions.
## Hooks
This section of the configuration cannot be overwritten by another config
file, as it is an optional lua return statement specific to each config
file. It can be used to define things that are append only, such as various
hooks and callbacks.
Example:
```lua
return {
-- Messages to send when the config file loads.
-- This is similar to the `--on-load` command-line option.
--
-- Type: list of [Message](https://xplr.dev/en/message#message)s
on_load = {
{ LogInfo = "Hello xplr user," },
{ LogSuccess = "Configuration successfully loaded!" },
}
}
```

@ -4,7 +4,6 @@ import os
from dataclasses import dataclass
from typing import List
# Messages --------------------------------------------------------------------
MESSAGES_DOC_TEMPLATE = """
@ -157,6 +156,7 @@ def gen_configuration():
line.startswith("-- # Configuration ")
or line.startswith("-- ## Config ")
or line.startswith("-- ## Function ")
or line.startswith("-- ## On Load ")
):
reading = configuration

@ -1,4 +1,5 @@
use crate::config::Config;
use crate::config::Hooks;
use crate::config::Mode;
pub use crate::directory_buffer::DirectoryBuffer;
use crate::explorer;
@ -190,8 +191,8 @@ impl App {
lua: &mlua::Lua,
config_file: Option<PathBuf>,
extra_config_files: Vec<PathBuf>,
) -> Result<Self> {
let mut config = lua::init(lua)?;
) -> Result<(Self, Option<Hooks>)> {
let (mut config, mut hooks) = lua::init(lua)?;
let config_file = if let Some(path) = config_file {
Some(path)
@ -218,8 +219,13 @@ impl App {
let mut load_errs = vec![];
for config_file in config_files {
match lua::extend(lua, &config_file.to_string_lossy()) {
Ok(c) => {
Ok((c, maybe_hooks)) => {
config = c;
match (hooks.as_mut(), maybe_hooks) {
(Some(h1), Some(h2)) => h1.on_load.extend(h2.on_load),
(None, Some(h2)) => hooks = Some(h2),
(_, _) => {}
}
}
Err(e) => {
load_errs.push(e.to_string());
@ -328,7 +334,7 @@ impl App {
app = app.switch_mode_builtin("debug_error")?;
}
Ok(app)
Ok((app, hooks))
}
pub fn focused_node(&self) -> Option<&Node> {

@ -612,3 +612,10 @@ pub struct Config {
#[serde(default)]
pub modes: ModesConfig,
}
#[derive(Debug, Default, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Hooks {
#[serde(default)]
pub on_load: Vec<ExternalMsg>,
}

@ -2563,3 +2563,29 @@ end
-- You can also use nested tables such as
-- `xplr.fn.custom.my_plugin.my_function` to define custom functions.
xplr.fn.custom = {}
-- ## Hooks -------------------------------------------------------------------
--
-- This section of the configuration cannot be overwritten by another config
-- file, as it is an optional lua return statement specific to each config
-- file. It can be used to define things that are append only, such as various
-- hooks and callbacks.
--
-- Example:
--
-- ```lua
-- return {
-- -- Add messages to send when the xplr loads.
-- -- This is similar to the `--on-load` command-line option.
-- --
-- -- Type: list of [Message](https://xplr.dev/en/message#message)s
-- on_load = {
-- { LogInfo = "Hello xplr user," },
-- { LogSuccess = "Configuration successfully loaded!" },
-- }
-- }
-- ```
return {
on_load = {},
}

@ -1,5 +1,6 @@
use crate::app::VERSION;
use crate::config::Config;
use crate::config::Hooks;
use anyhow::bail;
use anyhow::Error;
use anyhow::Result;
@ -57,7 +58,7 @@ pub fn check_version(version: &str, path: &str) -> Result<()> {
}
/// Used to initialize Lua globals
pub fn init(lua: &Lua) -> Result<Config> {
pub fn init(lua: &Lua) -> Result<(Config, Option<Hooks>)> {
let config = Config::default();
let globals = lua.globals();
@ -73,20 +74,28 @@ pub fn init(lua: &Lua) -> Result<Config> {
lua_xplr.set("fn", lua_xplr_fn)?;
globals.set("xplr", lua_xplr)?;
lua.load(DEFAULT_LUA_SCRIPT).set_name("init")?.exec()?;
let hooks: Option<Hooks> = lua
.load(DEFAULT_LUA_SCRIPT)
.set_name("xplr init")?
.call(())
.and_then(|v| lua.from_value(v))?;
let lua_xplr: mlua::Table = globals.get("xplr")?;
let config: Config = lua.from_value(lua_xplr.get("config")?)?;
Ok(config)
Ok((config, hooks))
}
/// Used to extend Lua globals
pub fn extend(lua: &Lua, path: &str) -> Result<Config> {
pub fn extend(lua: &Lua, path: &str) -> Result<(Config, Option<Hooks>)> {
let globals = lua.globals();
let script = fs::read_to_string(path)?;
lua.load(&script).set_name("init")?.exec()?;
let hooks: Option<Hooks> = lua
.load(&script)
.set_name(path)?
.call(())
.and_then(|v| lua.from_value(v))?;
let version: String = match globals.get("version").and_then(|v| lua.from_value(v)) {
Ok(v) => v,
@ -98,7 +107,7 @@ pub fn extend(lua: &Lua, path: &str) -> Result<Config> {
let lua_xplr: mlua::Table = globals.get("xplr")?;
let config: Config = lua.from_value(lua_xplr.get("config")?)?;
Ok(config)
Ok((config, hooks))
}
fn resolve_fn_recursive<'lua, 'a>(

@ -245,7 +245,7 @@ impl Runner {
pub fn run(self) -> Result<Option<String>> {
// Why unsafe? See https://github.com/sayanarijit/xplr/issues/309
let lua = unsafe { mlua::Lua::unsafe_new() };
let mut app = app::App::create(
let (mut app, hooks) = app::App::create(
self.bin,
self.pwd,
&lua,
@ -329,7 +329,12 @@ impl Runner {
event_reader.start();
// Enqueue on_load messages
for msg in self.on_load {
for msg in hooks
.unwrap_or_default()
.on_load
.into_iter()
.chain(self.on_load)
{
tx_msg_in.send(app::Task::new(app::MsgIn::External(msg), None))?;
}

Loading…
Cancel
Save