Improve working with file permissions

Implements:

- xplr.util.permissions_rwx
- xplr.util.permissions_octal
pull/591/head
Arijit Basu 1 year ago
parent 0b03fda363
commit 71674fb482

@ -469,6 +469,38 @@ xplr.util.layout_replace(layout, "Table", "Selection")
-- }
```
### xplr.util.permissions_rwx
Convert [Permission][8] to rwxrwxrwx representation with special bits.
Type: function( [Permission][8] ) -> string
Example:
```lua
xplr.util.permissions_rwx({ user_read = true }))
-- "r--------"
xplr.util.permissions_rwx(app.focused_node.permission))
-- "rwxrwsrwT"
```
### xplr.util.permissions_octal
Convert [Permission][8] to octal representation.
Type: function( [Permission][8] ) -> { number, number, number, number }
Example:
```lua
xplr.util.permissions_octal({ user_read = true }))
-- { 0, 4, 0, 0 }
xplr.util.permissions_octal(app.focused_node.permission))
-- { 0, 7, 5, 4 }
```
[1]: https://xplr.dev/en/lua-function-calls#explorer-config
[2]: https://xplr.dev/en/lua-function-calls#node
[3]: https://xplr.dev/en/style
@ -476,3 +508,4 @@ xplr.util.layout_replace(layout, "Table", "Selection")
[5]: https://xplr.dev/en/lua-function-calls#node
[6]: https://xplr.dev/en/node-type
[7]: https://xplr.dev/en/node_types
[8]: https://xplr.dev/en/column-renderer#permission

@ -159,7 +159,7 @@ xplr.config.general.logs.error.style = { fg = "Red" }
xplr.config.general.table.header.cols = {
{ format = " index", style = {} },
{ format = "╭─── path", style = {} },
{ format = "permissions", style = {} },
{ format = "perm", style = {} },
{ format = "size", style = {} },
{ format = "modified", style = {} },
}
@ -481,7 +481,7 @@ xplr.config.general.sort_and_filter_ui.search_identifiers = {
--
-- Type: nullable string
xplr.config.general.sort_and_filter_ui.search_direction_identifiers.ordered.format =
""
""
-- The shape of unordered indicator for search ordering identifiers in Sort & filter panel.
--
@ -1288,19 +1288,19 @@ xplr.config.modes.builtin.default = {
}
xplr.config.modes.builtin.default.key_bindings.on_key["v"] =
xplr.config.modes.builtin.default.key_bindings.on_key["space"]
xplr.config.modes.builtin.default.key_bindings.on_key["space"]
xplr.config.modes.builtin.default.key_bindings.on_key["V"] =
xplr.config.modes.builtin.default.key_bindings.on_key["ctrl-a"]
xplr.config.modes.builtin.default.key_bindings.on_key["ctrl-a"]
xplr.config.modes.builtin.default.key_bindings.on_key["/"] =
xplr.config.modes.builtin.default.key_bindings.on_key["ctrl-f"]
xplr.config.modes.builtin.default.key_bindings.on_key["ctrl-f"]
xplr.config.modes.builtin.default.key_bindings.on_key["h"] =
xplr.config.modes.builtin.default.key_bindings.on_key["left"]
xplr.config.modes.builtin.default.key_bindings.on_key["left"]
xplr.config.modes.builtin.default.key_bindings.on_key["j"] =
xplr.config.modes.builtin.default.key_bindings.on_key["down"]
xplr.config.modes.builtin.default.key_bindings.on_key["down"]
xplr.config.modes.builtin.default.key_bindings.on_key["k"] =
xplr.config.modes.builtin.default.key_bindings.on_key["up"]
xplr.config.modes.builtin.default.key_bindings.on_key["up"]
xplr.config.modes.builtin.default.key_bindings.on_key["l"] =
xplr.config.modes.builtin.default.key_bindings.on_key["right"]
xplr.config.modes.builtin.default.key_bindings.on_key["right"]
-- The builtin debug error mode.
--
@ -1761,9 +1761,9 @@ xplr.config.modes.builtin.number = {
}
xplr.config.modes.builtin.number.key_bindings.on_key["j"] =
xplr.config.modes.builtin.number.key_bindings.on_key["down"]
xplr.config.modes.builtin.number.key_bindings.on_key["down"]
xplr.config.modes.builtin.number.key_bindings.on_key["k"] =
xplr.config.modes.builtin.number.key_bindings.on_key["up"]
xplr.config.modes.builtin.number.key_bindings.on_key["up"]
-- The builtin go to mode.
--
@ -2216,9 +2216,9 @@ xplr.config.modes.builtin.search = {
}
xplr.config.modes.builtin.search.key_bindings.on_key["ctrl-n"] =
xplr.config.modes.builtin.search.key_bindings.on_key["down"]
xplr.config.modes.builtin.search.key_bindings.on_key["down"]
xplr.config.modes.builtin.search.key_bindings.on_key["ctrl-p"] =
xplr.config.modes.builtin.search.key_bindings.on_key["up"]
xplr.config.modes.builtin.search.key_bindings.on_key["up"]
-- The builtin filter mode.
--
@ -2759,62 +2759,23 @@ end
-- Renders the third column in the table
xplr.fn.builtin.fmt_general_table_row_cols_2 = function(m)
local green = { fg = "Green" }
local yellow = { fg = "Yellow" }
local red = { fg = "Red" }
local function bit(x, color, cond)
if cond then
return xplr.util.paint(x, color)
else
return xplr.util.paint("-", color)
end
end
local p = m.permissions
local r = ""
r = r .. bit("r", green, p.user_read)
r = r .. bit("w", yellow, p.user_write)
if p.user_execute == false and p.setuid == false then
r = r .. bit("-", red, p.user_execute)
elseif p.user_execute == true and p.setuid == false then
r = r .. bit("x", red, p.user_execute)
elseif p.user_execute == false and p.setuid == true then
r = r .. bit("S", red, p.user_execute)
else
r = r .. bit("s", red, p.user_execute)
end
r = r .. bit("r", green, p.group_read)
r = r .. bit("w", yellow, p.group_write)
if p.group_execute == false and p.setuid == false then
r = r .. bit("-", red, p.group_execute)
elseif p.group_execute == true and p.setuid == false then
r = r .. bit("x", red, p.group_execute)
elseif p.group_execute == false and p.setuid == true then
r = r .. bit("S", red, p.group_execute)
else
r = r .. bit("s", red, p.group_execute)
end
r = r .. bit("r", green, p.other_read)
r = r .. bit("w", yellow, p.other_write)
if p.other_execute == false and p.setuid == false then
r = r .. bit("-", red, p.other_execute)
elseif p.other_execute == true and p.setuid == false then
r = r .. bit("x", red, p.other_execute)
elseif p.other_execute == false and p.setuid == true then
r = r .. bit("T", red, p.other_execute)
else
r = r .. bit("t", red, p.other_execute)
end
return r
local r = xplr.util.paint("r", { fg = "Green" })
local w = xplr.util.paint("w", { fg = "Yellow" })
local x = xplr.util.paint("x", { fg = "Red" })
local s = xplr.util.paint("s", { fg = "Red" })
local S = xplr.util.paint("S", { fg = "Red" })
local t = xplr.util.paint("t", { fg = "Red" })
local T = xplr.util.paint("T", { fg = "Red" })
return xplr.util
.permissions_rwx(m.permissions)
:gsub("r", r)
:gsub("w", w)
:gsub("x", x)
:gsub("s", s)
:gsub("S", S)
:gsub("t", t)
:gsub("T", T)
end
-- Renders the fourth column in the table

@ -6,6 +6,8 @@ use crate::msg::in_::external::ExplorerConfig;
use crate::node::Node;
use crate::path;
use crate::path::RelativityConfig;
use crate::permissions::Octal;
use crate::permissions::Permissions;
use crate::ui;
use crate::ui::Layout;
use crate::ui::Style;
@ -776,6 +778,53 @@ pub fn layout_replace<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
Ok(util)
}
/// Convert [Permission][8] to rwxrwxrwx representation with special bits.
///
/// Type: function( [Permission][8] ) -> string
///
/// Example:
///
/// ```lua
/// xplr.util.permissions_rwx({ user_read = true }))
/// -- "r--------"
///
/// xplr.util.permissions_rwx(app.focused_node.permission))
/// -- "rwxrwsrwT"
/// ```
pub fn permissions_rwx<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
let func = lua.create_function(|lua, permission: Table| {
let permissions: Permissions = lua.from_value(Value::Table(permission))?;
let permissions = permissions.to_string();
Ok(permissions)
})?;
util.set("permissions_rwx", func)?;
Ok(util)
}
/// Convert [Permission][8] to octal representation.
///
/// Type: function( [Permission][8] ) -> { number, number, number, number }
///
/// Example:
///
/// ```lua
/// xplr.util.permissions_octal({ user_read = true }))
/// -- { 0, 4, 0, 0 }
///
/// xplr.util.permissions_octal(app.focused_node.permission))
/// -- { 0, 7, 5, 4 }
/// ```
pub fn permissions_octal<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
let func = lua.create_function(|lua, permission: Table| {
let permissions: Permissions = lua.from_value(Value::Table(permission))?;
let permissions: Octal = permissions.into();
let permissions = lua::serialize(lua, &permissions).map_err(LuaError::custom)?;
Ok(permissions)
})?;
util.set("permissions_octal", func)?;
Ok(util)
}
///
/// [1]: https://xplr.dev/en/lua-function-calls#explorer-config
/// [2]: https://xplr.dev/en/lua-function-calls#node
@ -784,6 +833,7 @@ pub fn layout_replace<'a>(util: Table<'a>, lua: &Lua) -> Result<Table<'a>> {
/// [5]: https://xplr.dev/en/lua-function-calls#node
/// [6]: https://xplr.dev/en/node-type
/// [7]: https://xplr.dev/en/node_types
/// [8]: https://xplr.dev/en/column-renderer#permission
pub(crate) fn create_table(lua: &Lua) -> Result<Table> {
let mut util = lua.create_table()?;
@ -816,6 +866,8 @@ pub(crate) fn create_table(lua: &Lua) -> Result<Table> {
util = style_mix(util, lua)?;
util = textwrap(util, lua)?;
util = layout_replace(util, lua)?;
util = permissions_rwx(util, lua)?;
util = permissions_octal(util, lua)?;
Ok(util)
}

@ -1,27 +1,52 @@
// Stolen from https://github.com/Peltoche/lsd/blob/master/src/meta/permissions.rs
use serde::{Deserialize, Serialize};
use std::fs::Metadata;
use std::{fmt::Display, fs::Metadata};
#[derive(Debug, PartialEq, Eq, Copy, Clone, Serialize, Deserialize, Hash, Default)]
pub type RWX = (char, char, char, char, char, char, char, char, char);
pub type Octal = (u8, u8, u8, u8);
#[derive(Debug, Default, PartialEq, Eq, Copy, Clone, Serialize, Deserialize, Hash)]
pub struct Permissions {
#[serde(default)]
pub user_read: bool,
#[serde(default)]
pub user_write: bool,
#[serde(default)]
pub user_execute: bool,
#[serde(default)]
pub group_read: bool,
#[serde(default)]
pub group_write: bool,
#[serde(default)]
pub group_execute: bool,
#[serde(default)]
pub other_read: bool,
#[serde(default)]
pub other_write: bool,
#[serde(default)]
pub other_execute: bool,
#[serde(default)]
pub sticky: bool,
#[serde(default)]
pub setgid: bool,
#[serde(default)]
pub setuid: bool,
}
impl Permissions {}
impl<'a> From<&'a Metadata> for Permissions {
#[cfg(unix)]
fn from(meta: &Metadata) -> Self {
@ -55,6 +80,68 @@ impl<'a> From<&'a Metadata> for Permissions {
}
}
impl Display for Permissions {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let (ur, uw, ux, gr, gw, gx, or, ow, ox) = (*self).into();
write!(f, "{ur}{uw}{ux}{gr}{gw}{gx}{or}{ow}{ox}")
}
}
impl Into<RWX> for Permissions {
fn into(self) -> RWX {
let bit = |bit: bool, chr: char| {
if bit {
chr
} else {
'-'
}
};
let ur = bit(self.user_read, 'r');
let uw = bit(self.user_write, 'w');
let ux = match (self.user_execute, self.setuid) {
(true, true) => 's',
(true, false) => 'x',
(false, true) => 'S',
(false, false) => '-',
};
let gr = bit(self.group_read, 'r');
let gw = bit(self.group_write, 'w');
let gx = match (self.group_execute, self.setgid) {
(true, true) => 's',
(true, false) => 'x',
(false, true) => 'S',
(false, false) => '-',
};
let or = bit(self.other_read, 'r');
let ow = bit(self.other_write, 'w');
let ox = match (self.other_execute, self.sticky) {
(true, true) => 't',
(true, false) => 'x',
(false, true) => 'T',
(false, false) => '-',
};
(ur, uw, ux, gr, gw, gx, or, ow, ox)
}
}
impl Into<Octal> for Permissions {
fn into(self) -> Octal {
let bits_to_octal =
|r: bool, w: bool, x: bool| (r as u8) * 4 + (w as u8) * 2 + (x as u8);
(
bits_to_octal(self.setuid, self.setgid, self.sticky),
bits_to_octal(self.user_read, self.user_write, self.user_execute),
bits_to_octal(self.group_read, self.group_write, self.group_execute),
bits_to_octal(self.other_read, self.other_write, self.other_execute),
)
}
}
// More readable aliases for the permission bits exposed by libc.
#[allow(trivial_numeric_casts)]
#[cfg(unix)]

Loading…
Cancel
Save