Add support for native lua bindings

Ref: https://github.com/sayanarijit/xplr/discussions/146#discussioncomment-741580
pull/162/head v0.10.0-beta.0
Arijit Basu 3 years ago committed by Arijit Basu
parent 98687515d7
commit f744553a0a

59
Cargo.lock generated

@ -126,6 +126,12 @@ dependencies = [
"rustc_version", "rustc_version",
] ]
[[package]]
name = "cc"
version = "1.0.67"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c69b077ad434294d3ce9f1f6143a2a4b89a8a2d54ef813d85003a4fd1137fd"
[[package]] [[package]]
name = "cfg-if" name = "cfg-if"
version = "1.0.0" version = "1.0.0"
@ -332,6 +338,15 @@ version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
[[package]]
name = "erased-serde"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0465971a8cc1fa2455c8465aaa377131e1f1cf4983280f474a13e68793aa770c"
dependencies = [
"serde",
]
[[package]] [[package]]
name = "fake-simd" name = "fake-simd"
version = "0.1.2" version = "0.1.2"
@ -488,6 +503,24 @@ dependencies = [
"cfg-if", "cfg-if",
] ]
[[package]]
name = "lua-src"
version = "543.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "029180f994b9b36f47d905f92569b516acf7d073778e2e781c15ee375b1ca27d"
dependencies = [
"cc",
]
[[package]]
name = "luajit-src"
version = "210.1.3+restyfe08842"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "36d3de8377d8e0492b646527befb7eb826a9ecd2dc8c1f81ab0e654bc03a029b"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "maplit" name = "maplit"
version = "1.0.2" version = "1.0.2"
@ -547,6 +580,23 @@ dependencies = [
"winapi", "winapi",
] ]
[[package]]
name = "mlua"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dd448d3e7018f2ff38dd732a374045f5b037eb4ee477d9241d9bb8c209528c1c"
dependencies = [
"bstr",
"cc",
"erased-serde",
"lazy_static",
"lua-src",
"luajit-src",
"num-traits",
"pkg-config",
"serde",
]
[[package]] [[package]]
name = "natord" name = "natord"
version = "1.0.9" version = "1.0.9"
@ -677,6 +727,12 @@ dependencies = [
"sha-1", "sha-1",
] ]
[[package]]
name = "pkg-config"
version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3831453b3449ceb48b6d9c7ad7c96d5ea673e9b470a1dc578c2ce6521230884c"
[[package]] [[package]]
name = "plotters" name = "plotters"
version = "0.3.0" version = "0.3.0"
@ -1193,7 +1249,7 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "xplr" name = "xplr"
version = "0.9.1" version = "0.10.0-beta.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"chrono", "chrono",
@ -1205,6 +1261,7 @@ dependencies = [
"indexmap", "indexmap",
"lazy_static", "lazy_static",
"mime_guess", "mime_guess",
"mlua",
"natord", "natord",
"serde", "serde",
"serde_yaml", "serde_yaml",

@ -1,6 +1,6 @@
[package] [package]
name = "xplr" name = "xplr"
version = "0.9.1" # Update config.yml, config.rs version = "0.10.0-beta.0" # Update config.yml, config.rs
authors = ["Arijit Basu <sayanarijit@gmail.com>"] authors = ["Arijit Basu <sayanarijit@gmail.com>"]
edition = "2018" edition = "2018"
description = "A hackable, minimal, fast TUI file explorer" description = "A hackable, minimal, fast TUI file explorer"
@ -29,6 +29,7 @@ lazy_static = "1.4.0"
indexmap = { version = "1.6.2", features = ["serde"] } indexmap = { version = "1.6.2", features = ["serde"] }
natord = "1.0.9" natord = "1.0.9"
humansize = "1.1.0" humansize = "1.1.0"
mlua = { version = "0.5.4", features = ["luajit", "vendored", "serialize"] }
[dev-dependencies] [dev-dependencies]
criterion = "0.3" criterion = "0.3"

@ -5,6 +5,7 @@ use crate::ui::Layout;
use anyhow::{bail, Result}; use anyhow::{bail, Result};
use chrono::{DateTime, Local}; use chrono::{DateTime, Local};
use indexmap::set::IndexSet; use indexmap::set::IndexSet;
use mlua::LuaSerdeExt;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::cmp::Ordering; use std::cmp::Ordering;
use std::collections::HashMap; use std::collections::HashMap;
@ -1416,6 +1417,18 @@ impl History {
} }
} }
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct LuaData {
config: Config,
}
impl LuaData {
pub fn new(config: Config) -> Self {
Self { config }
}
}
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct App { pub struct App {
version: String, version: String,
@ -1442,14 +1455,16 @@ impl App {
let config_dir = dirs::config_dir() let config_dir = dirs::config_dir()
.unwrap_or_else(|| PathBuf::from(".")) .unwrap_or_else(|| PathBuf::from("."))
.join("xplr"); .join("xplr");
let yaml_config_file = config_dir.join("config.yml");
let lua_script_file = config_dir.join("init.lua");
let config_file = config_dir.join("config.yml");
let default_config = Config::default(); let default_config = Config::default();
let default_config_version = default_config.version().clone(); let default_config_version = default_config.version().clone();
let config: Config = if config_file.exists() { // TODO deprecate this ---------------------------------
let config: Config = if yaml_config_file.exists() {
let c: Config = let c: Config =
serde_yaml::from_reader(io::BufReader::new(&fs::File::open(&config_file)?))?; serde_yaml::from_reader(io::BufReader::new(&fs::File::open(&yaml_config_file)?))?;
c.extended() c.extended()
} else { } else {
default_config default_config
@ -1461,7 +1476,59 @@ impl App {
You config version is : {} You config version is : {}
Required version is : {} Required version is : {}
Visit {}", Visit {}",
config_file.to_string_lossy().to_string(), yaml_config_file.to_string_lossy().to_string(),
config.version(),
default_config_version,
UPGRADE_GUIDE_LINK,
)
};
// -------------------------------------------------------
let config: Config = if lua_script_file.exists() {
let lua = mlua::Lua::new();
let globals = lua.globals();
let lua_script = fs::read_to_string(&lua_script_file)?;
let luadata = LuaData::new(config);
// TODO: https://github.com/khvzak/mlua/issues/48
if let Err(e) = lua.to_value(&luadata).and_then(|v| globals.set("xplr", v)) {
bail!(e.to_string())
};
if let Err(e) = lua
.load(&lua_script)
.set_name("init")
.and_then(|l| l.exec())
{
bail!(e.to_string())
}
let version: String = match globals.get("version").and_then(|v| lua.from_value(v)) {
Ok(v) => v,
Err(_) => bail!(format!(
"'version' must globally be defined in {}",
&lua_script_file.to_string_lossy().to_string()
)),
};
let luadata: LuaData = match globals.get("xplr").and_then(|v| lua.from_value(v)) {
Ok(d) => d,
Err(e) => bail!(e.to_string()),
};
luadata.config.with_version(version)
} else {
config
};
if !config.is_compatible()? {
bail!(
"incompatible configuration version in {}
You config version is : {}
Required version is : {}
Visit {}",
lua_script_file.to_string_lossy().to_string(),
config.version(), config.version(),
default_config_version, default_config_version,
UPGRADE_GUIDE_LINK, UPGRADE_GUIDE_LINK,
@ -1542,7 +1609,7 @@ impl App {
if let Some(notif) = config.upgrade_notification()? { if let Some(notif) = config.upgrade_notification()? {
let notif = format!( let notif = format!(
"{}. To stop seeing this log, update your config version from {} to {}.", "{}. To stop seeing this log, update your config version from {} to {}",
&notif, &notif,
config.version(), config.version(),
app.version() app.version()
@ -1553,6 +1620,18 @@ impl App {
)); ));
} }
// if yaml_config_file.exists() && !lua_script_file.exists() {
// let notif = format!(
// "`config.yml` will be deprecated in favor of `init.lua`. To stop this warning, create empty file {}",
// lua_script_file.to_string_lossy().to_string()
// );
// app = app.enqueue(Task::new(
// MsgIn::External(ExternalMsg::LogWarning(notif)),
// None,
// ));
// }
app.write_pipes()?; app.write_pipes()?;
Ok(app) Ok(app)
} }

@ -1259,7 +1259,7 @@ impl Config {
self self
} }
fn parsed_version(&self) -> Result<(u16, u16, u16)> { fn parsed_version(&self) -> Result<(u16, u16, u16, Option<u16>)> {
let mut configv = self let mut configv = self
.version .version
.strip_prefix('v') .strip_prefix('v')
@ -1268,27 +1268,31 @@ impl Config {
let major = configv.next().unwrap_or_default().parse::<u16>()?; let major = configv.next().unwrap_or_default().parse::<u16>()?;
let minor = configv.next().unwrap_or_default().parse::<u16>()?; let minor = configv.next().unwrap_or_default().parse::<u16>()?;
let bugfix = configv.next().unwrap_or_default().parse::<u16>()?; let bugfix = configv
.next()
.and_then(|s| s.split('-').next())
.unwrap_or_default()
.parse::<u16>()?;
let beta = configv.next().unwrap_or_default().parse::<u16>().ok();
Ok((major, minor, bugfix)) Ok((major, minor, bugfix, beta))
} }
pub fn is_compatible(&self) -> Result<bool> { pub fn is_compatible(&self) -> Result<bool> {
let result = match self.parsed_version()? { let result = match self.parsed_version()? {
(0, 9, 1) => true, (0, 10, 0, Some(0)) => true,
(0, 9, 0) => true, (_, _, _, _) => false,
(_, _, _) => false,
}; };
Ok(result) Ok(result)
} }
pub fn upgrade_notification(&self) -> Result<Option<&str>> { pub fn upgrade_notification(&self) -> Result<Option<&str>> {
let result = match self.parsed_version()? { let result = None;
(0, 9, 1) => None, // let result = match self.parsed_version()? {
(0, 9, 0) => Some("App version updated. Improved remap feature"), // (_, _, _, _) => None,
(_, _, _) => None, // };
};
Ok(result) Ok(result)
} }
@ -1317,6 +1321,12 @@ impl Config {
pub fn modes(&self) -> &ModesConfig { pub fn modes(&self) -> &ModesConfig {
&self.modes &self.modes
} }
/// Set the config's version.
pub fn with_version(mut self, version: String) -> Self {
self.version = version;
self
}
} }
#[cfg(test)] #[cfg(test)]

@ -1,4 +1,4 @@
version: v0.9.1 version: v0.10.0-beta.0
layouts: layouts:
custom: {} custom: {}
builtin: builtin:

Loading…
Cancel
Save