mirror of https://github.com/sayanarijit/xplr
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
175 lines
4.7 KiB
Rust
175 lines
4.7 KiB
Rust
use crate::explorer;
|
|
use crate::lua;
|
|
use crate::msg::in_::external::ExplorerConfig;
|
|
use anyhow::Result;
|
|
use mlua::Error as LuaError;
|
|
use mlua::Lua;
|
|
use mlua::LuaSerdeExt;
|
|
use mlua::Table;
|
|
use mlua::Value;
|
|
use path_absolutize::*;
|
|
use serde::de::Error;
|
|
use std::path::PathBuf;
|
|
use std::process::Command;
|
|
|
|
pub(crate) fn create_table(lua: &Lua) -> Result<Table> {
|
|
let mut util = lua.create_table()?;
|
|
|
|
util = dirname(util, lua)?;
|
|
util = basename(util, lua)?;
|
|
util = absolute(util, lua)?;
|
|
util = explore(util, lua)?;
|
|
util = shell_execute(util, lua)?;
|
|
util = shell_quote(util, lua)?;
|
|
|
|
Ok(util)
|
|
}
|
|
|
|
/// Get the directory name of a given path.
|
|
///
|
|
/// Type: function( path:string ) -> path:string|nil
|
|
///
|
|
/// Example:
|
|
///
|
|
/// ```lua
|
|
/// xplr.util.dirname("/foo/bar")
|
|
/// -- "/foo"
|
|
/// ```
|
|
pub fn dirname<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
|
|
let func = lua.create_function(|_, path: String| {
|
|
let parent = PathBuf::from(path)
|
|
.parent()
|
|
.map(|p| p.to_string_lossy().to_string());
|
|
Ok(parent)
|
|
})?;
|
|
util.set("dirname", func)?;
|
|
Ok(util)
|
|
}
|
|
|
|
/// Get the base name of a given path.
|
|
///
|
|
/// Type: function( path:string ) -> path:string|nil
|
|
///
|
|
/// Example:
|
|
///
|
|
/// ```lua
|
|
/// xplr.util.basename("/foo/bar")
|
|
/// -- "bar"
|
|
/// ```
|
|
pub fn basename<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
|
|
let func = lua.create_function(|_, path: String| {
|
|
let parent = PathBuf::from(path)
|
|
.file_name()
|
|
.map(|p| p.to_string_lossy().to_string());
|
|
Ok(parent)
|
|
})?;
|
|
util.set("basename", func)?;
|
|
Ok(util)
|
|
}
|
|
|
|
/// Get the absolute path of the given path by prepending $PWD.
|
|
/// It doesn't check if the path exists.
|
|
///
|
|
/// Type: function( path:string ) -> path:string
|
|
///
|
|
/// Example:
|
|
///
|
|
/// ```lua
|
|
/// xplr.util.absolute("foo/bar")
|
|
/// -- "/tmp/foo/bar"
|
|
/// ```
|
|
pub fn absolute<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
|
|
let func = lua.create_function(|_, path: String| {
|
|
let parent = PathBuf::from(path)
|
|
.absolutize()?
|
|
.to_string_lossy()
|
|
.to_string();
|
|
Ok(parent)
|
|
})?;
|
|
util.set("absolute", func)?;
|
|
Ok(util)
|
|
}
|
|
|
|
/// Explore directories with the given explorer config.
|
|
///
|
|
/// Type: function( path:string, config:[Explorer Config][1]|nil )
|
|
/// -> { node:[Node][2]... }
|
|
///
|
|
/// Example:
|
|
///
|
|
/// ```lua
|
|
///
|
|
/// xplr.util.explore("/tmp")
|
|
/// xplr.util.explore("/tmp", app.explorer_config)
|
|
/// -- { { absolute_path = "/tmp/a", ... }, ... }
|
|
/// ```
|
|
///
|
|
/// [1]: https://xplr.dev/en/lua-function-calls#explorer-config
|
|
/// [2]: https://xplr.dev/en/lua-function-calls#node
|
|
pub fn explore<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
|
|
let func = lua.create_function(|lua, (path, config): (String, Option<Table>)| {
|
|
let config: ExplorerConfig = if let Some(cfg) = config {
|
|
lua.from_value(Value::Table(cfg))?
|
|
} else {
|
|
ExplorerConfig::default()
|
|
};
|
|
|
|
let nodes = explorer::explore(&PathBuf::from(path), &config)
|
|
.map_err(LuaError::custom)?;
|
|
let res = lua::serialize(lua, &nodes).map_err(LuaError::custom)?;
|
|
Ok(res)
|
|
})?;
|
|
util.set("explore", func)?;
|
|
Ok(util)
|
|
}
|
|
|
|
/// Execute shell commands safely.
|
|
///
|
|
/// Type: function( program:string, args:{ arg:string... }|nil )
|
|
/// -> { stdout = string, stderr = string, returncode = number|nil }
|
|
///
|
|
/// Example:
|
|
///
|
|
/// ```lua
|
|
/// xplr.util.shell_execute("pwd"})
|
|
/// xplr.util.shell_execute("bash", {"-c", "xplr --help"})
|
|
/// -- { stdout = "xplr...", stderr = "", returncode = 0 }
|
|
/// ```
|
|
pub fn shell_execute<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
|
|
let func =
|
|
lua.create_function(|lua, (program, args): (String, Option<Vec<String>>)| {
|
|
let mut cmd = Command::new(program);
|
|
let mut cmd_ref = &mut cmd;
|
|
if let Some(args) = args {
|
|
cmd_ref = cmd_ref.args(args)
|
|
};
|
|
let output = cmd_ref.output()?;
|
|
|
|
let res = lua.create_table()?;
|
|
res.set("stdout", String::from_utf8_lossy(&output.stdout))?;
|
|
res.set("stderr", String::from_utf8_lossy(&output.stderr))?;
|
|
res.set("returncode", output.status.code())?;
|
|
Ok(res)
|
|
})?;
|
|
util.set("shell_execute", func)?;
|
|
Ok(util)
|
|
}
|
|
|
|
/// Quote commands and paths safely.
|
|
///
|
|
/// Type: function( string ) -> string
|
|
///
|
|
/// Example:
|
|
///
|
|
/// ```lua
|
|
/// xplr.util.shell_quote("a'b\"c")
|
|
/// -- 'a'"'"'b"c'
|
|
/// ```
|
|
pub fn shell_quote<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
|
|
let func = lua.create_function(|_, string: String| {
|
|
Ok(format!("'{}'", string.replace('\'', r#"'"'"'"#)))
|
|
})?;
|
|
util.set("shell_quote", func)?;
|
|
Ok(util)
|
|
}
|