From ddb549055197b4118b99d766c9057a134ff497f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E4=B8=89=E5=92=B2=E9=9B=85=20=C2=B7=20Misaki=20Masa?= Date: Sat, 21 Oct 2023 05:42:13 +0800 Subject: [PATCH] feat: line mode (#291) --- app/src/executor.rs | 1 + config/preset/keymap.toml | 6 +++ config/src/manager/linemode.rs | 26 --------- config/src/manager/manager.rs | 15 ++++-- config/src/manager/mod.rs | 2 - config/src/manager/sorting.rs | 14 +++++ core/src/files/file.rs | 4 +- core/src/files/files.rs | 8 +-- core/src/files/sorter.rs | 3 +- core/src/manager/tabs.rs | 2 +- core/src/tab/commands/linemode.rs | 16 ++++++ core/src/tab/commands/mod.rs | 1 + core/src/tab/config.rs | 10 ++-- core/src/tasks/tasks.rs | 2 +- plugin/preset/components/folder.lua | 81 ++++++++++++++++++----------- plugin/preset/components/status.lua | 28 +++++----- plugin/src/bindings/active.rs | 11 ++++ plugin/src/bindings/files.rs | 51 +++++++++++++----- plugin/src/bindings/tabs.rs | 1 + 19 files changed, 174 insertions(+), 108 deletions(-) delete mode 100644 config/src/manager/linemode.rs create mode 100644 core/src/tab/commands/linemode.rs diff --git a/app/src/executor.rs b/app/src/executor.rs index 681bff7d1..6a156a770 100644 --- a/app/src/executor.rs +++ b/app/src/executor.rs @@ -127,6 +127,7 @@ impl Executor { exec.named.contains_key("confirm"), ), "hidden" => cx.manager.active_mut().hidden(exec), + "linemode" => cx.manager.active_mut().linemode(exec), "search" => match exec.args.get(0).map(|s| s.as_str()).unwrap_or("") { "rg" => cx.manager.active_mut().search(true), "fd" => cx.manager.active_mut().search(false), diff --git a/config/preset/keymap.toml b/config/preset/keymap.toml index 05ec6e4d8..491b9a67f 100644 --- a/config/preset/keymap.toml +++ b/config/preset/keymap.toml @@ -67,6 +67,12 @@ keymap = [ { on = [ "z" ], exec = "jump zoxide", desc = "Jump to a directory using zoxide" }, { on = [ "Z" ], exec = "jump fzf", desc = "Jump to a directory, or reveal a file using fzf" }, + # Linemode + { on = [ "m", "s" ], exec = "linemode size", desc = "Set linemode to size" }, + { on = [ "m", "p" ], exec = "linemode permissions", desc = "Set linemode to permissions" }, + { on = [ "m", "m" ], exec = "linemode mtime", desc = "Set linemode to mtime" }, + { on = [ "m", "n" ], exec = "linemode none", desc = "Set linemode to none" }, + # Copy { on = [ "c", "c" ], exec = "copy path", desc = "Copy the absolute path" }, { on = [ "c", "d" ], exec = "copy dirname", desc = "Copy the path of the parent directory" }, diff --git a/config/src/manager/linemode.rs b/config/src/manager/linemode.rs deleted file mode 100644 index b87b98ed7..000000000 --- a/config/src/manager/linemode.rs +++ /dev/null @@ -1,26 +0,0 @@ -use anyhow::bail; -use serde::{Deserialize, Serialize}; - -#[derive(Clone, Copy, Debug, Default, Deserialize, Serialize, PartialEq, Eq)] -#[serde(try_from = "String")] -pub enum Linemode { - #[default] - None, - Size, - Mtime, - Permissions, -} - -impl TryFrom for Linemode { - type Error = anyhow::Error; - - fn try_from(s: String) -> Result { - Ok(match s.as_str() { - "none" => Self::None, - "size" => Self::Size, - "mtime" => Self::Mtime, - "permissions" => Self::Permissions, - _ => bail!("invalid linemode value: {s}"), - }) - } -} diff --git a/config/src/manager/manager.rs b/config/src/manager/manager.rs index 9f209a86d..6f8e8eada 100644 --- a/config/src/manager/manager.rs +++ b/config/src/manager/manager.rs @@ -1,9 +1,10 @@ use serde::{Deserialize, Serialize}; +use validator::Validate; -use super::{Linemode, ManagerLayout, SortBy}; -use crate::MERGED_YAZI; +use super::{ManagerLayout, SortBy}; +use crate::{validation::check_validation, MERGED_YAZI}; -#[derive(Debug, Deserialize, Serialize)] +#[derive(Debug, Deserialize, Serialize, Validate)] pub struct Manager { pub layout: ManagerLayout, @@ -14,7 +15,8 @@ pub struct Manager { pub sort_dir_first: bool, // Display - pub linemode: Linemode, + #[validate(length(min = 1, max = 20, message = "must be between 1 and 20 characters"))] + pub linemode: String, pub show_hidden: bool, pub show_symlink: bool, } @@ -26,6 +28,9 @@ impl Default for Manager { manager: Manager, } - toml::from_str::(&MERGED_YAZI).unwrap().manager + let manager = toml::from_str::(&MERGED_YAZI).unwrap().manager; + + check_validation(manager.validate()); + manager } } diff --git a/config/src/manager/mod.rs b/config/src/manager/mod.rs index 607f874e7..08394cbf1 100644 --- a/config/src/manager/mod.rs +++ b/config/src/manager/mod.rs @@ -1,9 +1,7 @@ mod layout; -mod linemode; mod manager; mod sorting; pub use layout::*; -pub use linemode::*; pub use manager::*; pub use sorting::*; diff --git a/config/src/manager/sorting.rs b/config/src/manager/sorting.rs index 39a6ae018..41dc29f80 100644 --- a/config/src/manager/sorting.rs +++ b/config/src/manager/sorting.rs @@ -36,3 +36,17 @@ impl TryFrom for SortBy { fn try_from(s: String) -> Result { Self::from_str(&s) } } + +impl ToString for SortBy { + fn to_string(&self) -> String { + match self { + Self::None => "none", + Self::Alphabetical => "alphabetical", + Self::Created => "created", + Self::Modified => "modified", + Self::Natural => "natural", + Self::Size => "size", + } + .to_string() + } +} diff --git a/core/src/files/file.rs b/core/src/files/file.rs index d2b8a4053..1c7cad5ee 100644 --- a/core/src/files/file.rs +++ b/core/src/files/file.rs @@ -8,7 +8,6 @@ use tokio::fs; pub struct File { pub url: Url, pub meta: Metadata, - pub length: u64, pub(super) link_to: Option, pub is_link: bool, pub is_hidden: bool, @@ -30,9 +29,8 @@ impl File { link_to = fs::read_link(&url).await.map(Url::from).ok(); } - let length = meta.len(); let is_hidden = url.file_name().map(|s| s.to_string_lossy().starts_with('.')).unwrap_or(false); - Self { url, meta, length, link_to, is_link, is_hidden } + Self { url, meta, link_to, is_link, is_hidden } } #[inline] diff --git a/core/src/files/files.rs b/core/src/files/files.rs index 4cad09d2b..1b0e8490f 100644 --- a/core/src/files/files.rs +++ b/core/src/files/files.rs @@ -13,8 +13,8 @@ pub struct Files { ticket: u64, pub(crate) version: u64, - sizes: BTreeMap, - selected: BTreeSet, + pub sizes: BTreeMap, + selected: BTreeSet, sorter: FilesSorter, show_hidden: bool, @@ -268,10 +268,6 @@ impl Files { #[inline] pub fn position(&self, url: &Url) -> Option { self.iter().position(|f| &f.url == url) } - // --- Sizes - #[inline] - pub fn size(&self, url: &Url) -> Option { self.sizes.get(url).copied() } - // --- Selected pub fn selected(&self, pending: &BTreeSet, unset: bool) -> Vec<&File> { if self.selected.is_empty() && (unset || pending.is_empty()) { diff --git a/core/src/files/sorter.rs b/core/src/files/sorter.rs index c336a3bf4..21c1dea63 100644 --- a/core/src/files/sorter.rs +++ b/core/src/files/sorter.rs @@ -48,7 +48,7 @@ impl FilesSorter { SortBy::Size => items.sort_unstable_by(|a, b| { let aa = if a.is_dir() { sizes.get(&a.url).copied() } else { None }; let bb = if b.is_dir() { sizes.get(&b.url).copied() } else { None }; - self.cmp(aa.unwrap_or(a.length), bb.unwrap_or(b.length), self.promote(a, b)) + self.cmp(aa.unwrap_or(a.meta.len()), bb.unwrap_or(b.meta.len()), self.promote(a, b)) }), } true @@ -75,7 +75,6 @@ impl FilesSorter { let dummy = File { url: Default::default(), meta: items[0].meta.clone(), - length: 0, link_to: None, is_link: false, is_hidden: false, diff --git a/core/src/manager/tabs.rs b/core/src/manager/tabs.rs index 708d2a2f9..02a813152 100644 --- a/core/src/manager/tabs.rs +++ b/core/src/manager/tabs.rs @@ -23,7 +23,7 @@ impl Tabs { } let mut tab = Tab::from(url); - tab.conf = self.active().conf; + tab.conf = self.active().conf.clone(); tab.apply_files_attrs(false); self.items.insert(self.idx + 1, tab); diff --git a/core/src/tab/commands/linemode.rs b/core/src/tab/commands/linemode.rs new file mode 100644 index 000000000..bd8c82338 --- /dev/null +++ b/core/src/tab/commands/linemode.rs @@ -0,0 +1,16 @@ +use config::keymap::Exec; + +use crate::tab::Tab; + +impl Tab { + pub fn linemode(&mut self, e: &Exec) -> bool { + self.conf.patch(|c| { + let Some(mode) = e.args.get(0) else { + return; + }; + if !mode.is_empty() && mode.len() <= 20 { + c.linemode = mode.to_owned(); + } + }) + } +} diff --git a/core/src/tab/commands/mod.rs b/core/src/tab/commands/mod.rs index 370ba68a1..47fa94f78 100644 --- a/core/src/tab/commands/mod.rs +++ b/core/src/tab/commands/mod.rs @@ -8,6 +8,7 @@ mod find; mod hidden; mod jump; mod leave; +mod linemode; mod search; mod select; mod shell; diff --git a/core/src/tab/config.rs b/core/src/tab/config.rs index 2f4ebf834..6c0a900a7 100644 --- a/core/src/tab/config.rs +++ b/core/src/tab/config.rs @@ -1,8 +1,8 @@ -use config::{manager::{Linemode, SortBy}, MANAGER}; +use config::{manager::SortBy, MANAGER}; use crate::files::FilesSorter; -#[derive(Clone, Copy, PartialEq)] +#[derive(Clone, PartialEq)] pub struct Config { // Sorting pub sort_by: SortBy, @@ -11,7 +11,7 @@ pub struct Config { pub sort_dir_first: bool, // Display - pub linemode: Linemode, + pub linemode: String, pub show_hidden: bool, } @@ -25,7 +25,7 @@ impl Default for Config { sort_dir_first: MANAGER.sort_dir_first, // Display - linemode: MANAGER.linemode, + linemode: MANAGER.linemode.to_owned(), show_hidden: MANAGER.show_hidden, } } @@ -33,7 +33,7 @@ impl Default for Config { impl Config { pub(super) fn patch(&mut self, f: F) -> bool { - let old = *self; + let old = self.clone(); f(self); *self != old } diff --git a/core/src/tasks/tasks.rs b/core/src/tasks/tasks.rs index 0f6edd34d..3b7682e83 100644 --- a/core/src/tasks/tasks.rs +++ b/core/src/tasks/tasks.rs @@ -237,7 +237,7 @@ impl Tasks { let targets: Vec<_> = targets .iter() - .filter(|f| f.is_dir() && targets.size(&f.url).is_none()) + .filter(|f| f.is_dir() && !targets.sizes.contains_key(&f.url)) .map(|f| &f.url) .collect(); diff --git a/plugin/preset/components/folder.lua b/plugin/preset/components/folder.lua index f589095a5..7c01d7f16 100644 --- a/plugin/preset/components/folder.lua +++ b/plugin/preset/components/folder.lua @@ -14,6 +14,56 @@ function Folder:by_kind(kind) end end +function Folder:highlighted_name(file) + -- Complete prefix when searching across directories + local prefix = file:prefix() or "" + if prefix ~= "" then + prefix = prefix .. "/" + end + + -- Range highlighting for filenames + local highlights = file:highlights() + local spans = ui.highlight_ranges(prefix .. file.name, highlights) + + -- Show symlink target + if MANAGER.show_symlink and file.link_to ~= nil then + spans[#spans + 1] = ui.Span(" -> " .. tostring(file.link_to)):italic() + end + + if highlights == nil or not file:is_hovered() then + return spans + end + + local found = file:found() + if found ~= nil then + spans[#spans + 1] = ui.Span(" ") + spans[#spans + 1] = ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position) + end + return spans +end + +function Folder:linemode(area) + local mode = cx.active.conf.linemode + if mode == "none" then + return {} + end + + local lines = {} + for _, f in ipairs(self:by_kind(self.CURRENT).window) do + local spans = { ui.Span(" ") } + if mode == "size" then + local size = f:size() + spans[#spans + 1] = ui.Span(size and utils.readable_size(size) or "") + elseif mode == "mtime" then + spans[#spans + 1] = ui.Span(os.date("%y-%m-%d %H:%M", f.modified)) + elseif mode == "permissions" then + spans[#spans + 1] = ui.Span(f:permissions() or "") + end + lines[#lines + 1] = ui.Line(spans) + end + return ui.Paragraph(area:padding(ui.Padding.right(1)), lines):align(ui.Alignment.RIGHT) +end + function Folder:markers(area, markers) if #markers == 0 then return {} @@ -55,34 +105,6 @@ function Folder:markers(area, markers) return elements end -function Folder:highlighted_name(file) - -- Complete prefix when searching across directories - local prefix = file:prefix() or "" - if prefix ~= "" then - prefix = prefix .. "/" - end - - -- Range highlighting for filenames - local highlights = file:highlights() - local spans = ui.highlight_ranges(prefix .. file.name, highlights) - - -- Show symlink target - if MANAGER.show_symlink and file.link_to ~= nil then - spans[#spans + 1] = ui.Span(" -> " .. tostring(file.link_to)):italic() - end - - if highlights == nil or not file:is_hovered() then - return spans - end - - local found = file:found() - if found ~= nil then - spans[#spans + 1] = ui.Span(" ") - spans[#spans + 1] = ui.Span(string.format("[%d/%d]", found[1] + 1, found[2])):style(THEME.manager.find_position) - end - return spans -end - function Folder:parent(area) local folder = self:by_kind(self.PARENT) if folder == nil then @@ -127,8 +149,7 @@ function Folder:current(area) markers[#markers + 1] = { i, 3 } end end - - return { ui.List(area, items), table.unpack(self:markers(area, markers)) } + return utils.flat { ui.List(area, items), self:linemode(area), table.unpack(self:markers(area, markers)) } end function Folder:preview(area) diff --git a/plugin/preset/components/status.lua b/plugin/preset/components/status.lua index 115ccb4ac..de98ac6dc 100644 --- a/plugin/preset/components/status.lua +++ b/plugin/preset/components/status.lua @@ -31,7 +31,7 @@ function Status:size() local style = self.style() return ui.Line { - ui.Span(" " .. utils.readable_size(h.length) .. " "):fg(style.bg):bg(THEME.status.separator_style.bg), + ui.Span(" " .. utils.readable_size(h:size() or h.length) .. " "):fg(style.bg):bg(THEME.status.separator_style.bg), ui.Span(THEME.status.separator_close):fg(THEME.status.separator_style.fg), } end @@ -47,13 +47,18 @@ end function Status:permissions() local h = cx.active.current.hovered - if h == nil or h.permissions == nil then + if h == nil then + return ui.Span("") + end + + local perm = h:permissions() + if perm == nil then return ui.Span("") end local spans = {} - for i = 1, #h.permissions do - local c = h.permissions:sub(i, i) + for i = 1, #perm do + local c = perm:sub(i, i) local style = THEME.status.permissions_t if c == "-" then style = THEME.status.permissions_s @@ -109,9 +114,9 @@ function Status:progress(area, offset) end local gauge = ui.Gauge(ui.Rect { - x = area.x + math.max(0, area.w - offset - 21), + x = math.max(0, area.w - offset - 21), y = area.y, - w = math.min(20, area.w), + w = math.max(0, math.min(20, area.w - offset - 1)), h = 1, }) @@ -134,17 +139,12 @@ function Status:progress(area, offset) end function Status:render(area) - local chunks = ui.Layout() - :direction(ui.Direction.HORIZONTAL) - :constraints({ ui.Constraint.Percentage(50), ui.Constraint.Percentage(50) }) - :split(area) - local left = ui.Line { self:mode(), self:size(), self:name() } local right = ui.Line { self:permissions(), self:percentage(), self:position() } - local progress = self:progress(chunks[2], right:width()) + local progress = self:progress(area, right:width()) return { - ui.Paragraph(chunks[1], { left }), - ui.Paragraph(chunks[2], { right }):align(ui.Alignment.RIGHT), + ui.Paragraph(area, { left }), + ui.Paragraph(area, { right }):align(ui.Alignment.RIGHT), table.unpack(progress), } end diff --git a/plugin/src/bindings/active.rs b/plugin/src/bindings/active.rs index 00f3d8d4e..951743fcc 100644 --- a/plugin/src/bindings/active.rs +++ b/plugin/src/bindings/active.rs @@ -24,6 +24,16 @@ impl<'a, 'b> Active<'a, 'b> { reg.add_meta_method(MetaMethod::ToString, |_, me, ()| Ok(me.to_string())); })?; + LUA.register_userdata_type::(|reg| { + reg.add_field_method_get("sort_by", |_, me| Ok(me.sort_by.to_string())); + reg.add_field_method_get("sort_sensitive", |_, me| Ok(me.sort_sensitive)); + reg.add_field_method_get("sort_reverse", |_, me| Ok(me.sort_reverse)); + reg.add_field_method_get("sort_dir_first", |_, me| Ok(me.sort_dir_first)); + + reg.add_field_method_get("linemode", |_, me| Ok(me.linemode.to_owned())); + reg.add_field_method_get("show_hidden", |_, me| Ok(me.show_hidden)); + })?; + LUA.register_userdata_type::(|reg| { reg.add_field_method_get("cwd", |_, me| Ok(Url::from(&me.cwd))); reg.add_field_method_get("offset", |_, me| Ok(me.offset)); @@ -48,6 +58,7 @@ impl<'a, 'b> Active<'a, 'b> { pub(crate) fn make(&self) -> mlua::Result> { let ud = self.scope.create_any_userdata_ref(self.inner)?; ud.set_named_user_value("mode", self.scope.create_any_userdata_ref(&self.inner.mode)?)?; + ud.set_named_user_value("conf", self.scope.create_any_userdata_ref(&self.inner.conf)?)?; ud.set_named_user_value( "parent", self.inner.parent.as_ref().and_then(|p| self.folder(p, None).ok()), diff --git a/plugin/src/bindings/files.rs b/plugin/src/bindings/files.rs index 02eb23d33..b6fb07309 100644 --- a/plugin/src/bindings/files.rs +++ b/plugin/src/bindings/files.rs @@ -1,3 +1,5 @@ +use std::time::UNIX_EPOCH; + use config::THEME; use mlua::{AnyUserData, IntoLua, MetaMethod, UserData, UserDataFields, UserDataMethods, UserDataRef}; @@ -13,7 +15,6 @@ impl From<&core::files::File> for File { impl UserData for File { fn add_fields<'lua, F: UserDataFields<'lua, Self>>(fields: &mut F) { fields.add_field_method_get("url", |_, me| Ok(Url::from(&me.0.url))); - fields.add_field_method_get("length", |_, me| Ok(me.0.length)); fields.add_field_method_get("link_to", |_, me| Ok(me.0.link_to().map(Url::from))); fields.add_field_method_get("is_link", |_, me| Ok(me.0.is_link)); fields.add_field_method_get("is_hidden", |_, me| Ok(me.0.is_hidden)); @@ -48,24 +49,55 @@ impl Files { LUA.register_userdata_type::(|reg| { reg.add_field_method_get("url", |_, me| Ok(Url::from(&me.url))); - reg.add_field_method_get("length", |_, me| Ok(me.length)); reg.add_field_method_get("link_to", |_, me| Ok(me.link_to().map(Url::from))); reg.add_field_method_get("is_link", |_, me| Ok(me.is_link)); reg.add_field_method_get("is_hidden", |_, me| Ok(me.is_hidden)); + // Metadata + reg.add_field_method_get("is_file", |_, me| Ok(me.is_file())); + reg.add_field_method_get("is_dir", |_, me| Ok(me.is_dir())); + reg.add_field_method_get("is_symlink", |_, me| Ok(me.meta.is_symlink())); + #[cfg(unix)] + { + use std::os::unix::prelude::FileTypeExt; + reg.add_field_method_get("is_block_device", |_, me| { + Ok(me.meta.file_type().is_block_device()) + }); + reg + .add_field_method_get("is_char_device", |_, me| Ok(me.meta.file_type().is_char_device())); + reg.add_field_method_get("is_fifo", |_, me| Ok(me.meta.file_type().is_fifo())); + reg.add_field_method_get("is_socket", |_, me| Ok(me.meta.file_type().is_socket())); + } + reg.add_field_method_get("length", |_, me| Ok(me.meta.len())); + reg.add_field_method_get("created", |_, me| { + Ok(me.meta.created()?.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()) + }); + reg.add_field_method_get("modified", |_, me| { + Ok(me.meta.modified()?.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()) + }); + reg.add_field_method_get("accessed", |_, me| { + Ok(me.meta.accessed()?.duration_since(UNIX_EPOCH).map(|d| d.as_secs_f64()).ok()) + }); + reg.add_method("permissions", |_, me, ()| Ok(shared::permissions(me.meta.permissions()))); + + // Extension reg.add_field_method_get("name", |_, me| { Ok(me.url.file_name().map(|n| n.to_string_lossy().to_string())) }); - reg.add_field_method_get("permissions", |_, me| { - Ok(shared::permissions(me.meta.permissions())) - }); + reg.add_function("size", |_, me: AnyUserData| { + let file = me.borrow::()?; + if !file.is_dir() { + return Ok(Some(file.meta.len())); + } + let folder = me.named_user_value::>("folder")?; + Ok(folder.files.sizes.get(&file.url).copied()) + }); reg.add_function("mime", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; let file = me.borrow::()?; Ok(manager.mimetype.get(&file.url).cloned()) }); - reg.add_function("prefix", |_, me: AnyUserData| { let folder = me.named_user_value::>("folder")?; if !folder.cwd.is_search() { @@ -77,7 +109,6 @@ impl Files { p.next_back(); Ok(Some(p.as_path().to_string_lossy().to_string())) }); - reg.add_method("icon", |_, me, ()| { Ok( THEME @@ -87,7 +118,6 @@ impl Files { .map(|x| x.display.to_string()), ) }); - reg.add_function("style", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; let file = me.borrow::()?; @@ -100,13 +130,11 @@ impl Files { .map(|x| Style::from(x.style)), ) }); - reg.add_function("is_hovered", |_, me: AnyUserData| { let folder = me.named_user_value::>("folder")?; let file = me.borrow::()?; Ok(matches!(folder.hovered(), Some(f) if f.url == file.url)) }); - reg.add_function("is_yanked", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; let file = me.borrow::()?; @@ -118,7 +146,6 @@ impl Files { 1u8 }) }); - reg.add_function("is_selected", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; let folder = me.named_user_value::>("folder")?; @@ -132,7 +159,6 @@ impl Files { manager.active().mode.pending(folder.offset + idx, selected) }) }); - reg.add_function("found", |lua, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; let Some(finder) = &manager.active().finder else { @@ -148,7 +174,6 @@ impl Files { } Ok(None) }); - reg.add_function("highlights", |_, me: AnyUserData| { let manager = me.named_user_value::>("manager")?; let Some(finder) = &manager.active().finder else { diff --git a/plugin/src/bindings/tabs.rs b/plugin/src/bindings/tabs.rs index 68ca35de4..657bade50 100644 --- a/plugin/src/bindings/tabs.rs +++ b/plugin/src/bindings/tabs.rs @@ -33,6 +33,7 @@ impl<'a, 'b> Tabs<'a, 'b> { }); reg.add_field_function_get("mode", |_, me| me.named_user_value::("mode")); + reg.add_field_function_get("conf", |_, me| me.named_user_value::("conf")); reg.add_field_function_get("parent", |_, me| me.named_user_value::("parent")); reg.add_field_function_get("current", |_, me| me.named_user_value::("current")); reg.add_field_function_get("preview", |_, me| me.named_user_value::("preview"));