diff options
Diffstat (limited to 'src')
43 files changed, 769 insertions, 395 deletions
diff --git a/src/commands/bookmark.rs b/src/commands/bookmark.rs index 4372a58..ce83d95 100644 --- a/src/commands/bookmark.rs +++ b/src/commands/bookmark.rs @@ -7,7 +7,7 @@ use ratatui::widgets::Clear; use termion::event::Event; use crate::config::raw::bookmarks::{BookmarkRaw, BookmarksRaw}; -use crate::config::search_directories; +use crate::config::{search_directories, ConfigType}; use crate::context::AppContext; use crate::error::AppResult; use crate::event::{process_event, AppEvent}; @@ -17,7 +17,7 @@ use crate::ui::widgets::TuiMenu; use crate::ui::AppBackend; use crate::util::unix; -use crate::{BOOKMARKS_FILE, BOOKMARKS_T, CONFIG_HIERARCHY}; +use crate::{BOOKMARKS_T, CONFIG_HIERARCHY}; use super::change_directory::change_directory; @@ -33,10 +33,11 @@ fn find_bookmark_file() -> Option<path::PathBuf> { pub fn add_bookmark(context: &mut AppContext, backend: &mut AppBackend) -> AppResult { let cwd = std::env::current_dir()?; - let bookmark_path = match search_directories(BOOKMARKS_FILE, &CONFIG_HIERARCHY) { - Some(file_path) => Some(file_path), - None => find_bookmark_file(), - }; + let bookmark_path = + match search_directories(ConfigType::Bookmarks.as_filename(), &CONFIG_HIERARCHY) { + Some(file_path) => Some(file_path), + None => find_bookmark_file(), + }; if let Some(bookmark_path) = bookmark_path { let key = poll_for_bookmark_key(context, backend); @@ -108,19 +109,20 @@ fn poll_for_bookmark_key(context: &mut AppContext, backend: &mut AppBackend) -> frame.render_widget(view, area); } - let menu_widget = TuiMenu::new(bookmarks_str.as_slice()); - let menu_len = menu_widget.len(); - let menu_y = if menu_len + 1 > area.height as usize { - 0 + let (menu_widget, menu_y) = if bookmarks_str.len() > area.height as usize - 1 { + (TuiMenu::new(&bookmarks_str[0..area.height as usize - 1]), 0) } else { - (area.height as usize - menu_len - 1) as u16 + ( + TuiMenu::new(bookmarks_str.as_slice()), + (area.height as usize - bookmarks_str.len() - 1) as u16, + ) }; let menu_rect = Rect { x: 0, - y: menu_y - 1, + y: menu_y, width: area.width, - height: menu_len as u16 + 1, + height: menu_widget.len() as u16 + 1, }; frame.render_widget(Clear, menu_rect); frame.render_widget(menu_widget, menu_rect); diff --git a/src/commands/bulk_rename.rs b/src/commands/bulk_rename.rs index f7009ae..9cc7f26 100644 --- a/src/commands/bulk_rename.rs +++ b/src/commands/bulk_rename.rs @@ -128,7 +128,7 @@ pub fn bulk_rename(context: &mut AppContext, backend: &mut AppBackend) -> AppRes context.remove_external_preview(); backend.terminal_drop(); let res = _bulk_rename(context); - backend.terminal_restore()?; + backend.terminal_restore(context.config_ref().mouse_support)?; reload::soft_reload_curr_tab(context)?; res } diff --git a/src/commands/custom_search.rs b/src/commands/custom_search.rs index 422143e..a9d4405 100644 --- a/src/commands/custom_search.rs +++ b/src/commands/custom_search.rs @@ -57,7 +57,7 @@ pub fn custom_search( .stdout(Stdio::piped()) .spawn()? .wait_with_output()?; - backend.terminal_restore()?; + backend.terminal_restore(context.config_ref().mouse_support)?; cmd_result } else { cmd.output()? diff --git a/src/commands/fzf.rs b/src/commands/fzf.rs index 8aeaa1b..9c60c54 100644 --- a/src/commands/fzf.rs +++ b/src/commands/fzf.rs @@ -25,7 +25,7 @@ pub fn fzf( CaseSensitivity::Smart => {} } - fzf_impl(backend, items, args) + fzf_impl(context, backend, items, args) } pub fn fzf_multi( @@ -47,10 +47,15 @@ pub fn fzf_multi( } args.push("-m".to_owned()); - fzf_impl(backend, items, args) + fzf_impl(context, backend, items, args) } -fn fzf_impl(backend: &mut AppBackend, items: Vec<String>, args: Vec<String>) -> AppResult<String> { +fn fzf_impl( + context: &mut AppContext, + backend: &mut AppBackend, + items: Vec<String>, + args: Vec<String>, +) -> AppResult<String> { backend.terminal_drop(); let mut cmd = Command::new("fzf"); @@ -63,7 +68,7 @@ fn fzf_impl(backend: &mut AppBackend, items: Vec<String>, args: Vec<String>) -> let mut fzf = match cmd.spawn() { Ok(child) => child, Err(e) => { - backend.terminal_restore()?; + backend.terminal_restore(context.config_ref().mouse_support)?; return Err(AppError::from(e)); } }; @@ -77,7 +82,7 @@ fn fzf_impl(backend: &mut AppBackend, items: Vec<String>, args: Vec<String>) -> } let fzf_output = fzf.wait_with_output(); - backend.terminal_restore()?; + backend.terminal_restore(context.config_ref().mouse_support)?; if let Ok(output) = fzf_output { if output.status.success() { diff --git a/src/commands/open_file.rs b/src/commands/open_file.rs index 0d248e9..d206f35 100644 --- a/src/commands/open_file.rs +++ b/src/commands/open_file.rs @@ -60,7 +60,7 @@ where } else { backend.terminal_drop(); let res = execute_and_wait(option, files); - backend.terminal_restore()?; + backend.terminal_restore(context.config_ref().mouse_support)?; res?; } Ok(()) @@ -79,7 +79,7 @@ fn _open_with_xdg( backend.terminal_drop(); let handle = open::that_in_background(path); let result = handle.join(); - backend.terminal_restore()?; + backend.terminal_restore(context.config_ref().mouse_support)?; if let Ok(result) = result { result?; } @@ -136,7 +136,7 @@ where let mut option = ProgramEntry::new(String::from(cmd)); option.args(args_iter); let res = execute_and_wait(&option, files); - backend.terminal_restore()?; + backend.terminal_restore(context.config_ref().mouse_support)?; res? } } diff --git a/src/commands/preview_cursor_move.rs b/src/commands/preview_cursor_move.rs index a59faa6..6959fb8 100644 --- a/src/commands/preview_cursor_move.rs +++ b/src/commands/preview_cursor_move.rs @@ -14,7 +14,7 @@ fn preview_cursor_move(context: &mut AppContext, new_index: usize) -> AppResult let preview_context = context.preview_context_mut(); if let Some(file_path) = file_path { - if let Some(PreviewFileState::Success { data }) = + if let Some(PreviewFileState::Success(data)) = preview_context.previews_mut().get_mut(&file_path) { data.index = new_index; @@ -32,7 +32,7 @@ pub fn preview_up(context: &mut AppContext, u: usize) -> AppResult { let preview_context = context.preview_context_ref(); if let Some(file_path) = file_path { - if let Some(PreviewFileState::Success { data }) = + if let Some(PreviewFileState::Success(data)) = preview_context.previews_ref().get(file_path) { if data.index < u { @@ -62,7 +62,7 @@ pub fn preview_down(context: &mut AppContext, u: usize) -> AppResult { let preview_context = context.preview_context_ref(); if let Some(file_path) = file_path { - if let Some(PreviewFileState::Success { data }) = + if let Some(PreviewFileState::Success(data)) = preview_context.previews_ref().get(file_path) { Some(data.index + u) diff --git a/src/commands/sort.rs b/src/commands/sort.rs index f78fd0a..7bea48f 100644 --- a/src/commands/sort.rs +++ b/src/commands/sort.rs @@ -25,5 +25,22 @@ pub fn toggle_reverse(context: &mut AppContext) -> AppResult { fn refresh(context: &mut AppContext) -> AppResult { reload::soft_reload_curr_tab(context)?; + + let ui_context = context.ui_context_ref().clone(); + let display_options = context.config_ref().display_options_ref().clone(); + let curr_tab = context.tab_context_mut().curr_tab_mut(); + + macro_rules! update_viewport { + ($x_list_mut: ident) => { + if let Some(list) = curr_tab.$x_list_mut() { + list.update_viewport(&ui_context, &display_options); + } + }; + } + + update_viewport!(curr_list_mut); + update_viewport!(parent_list_mut); + update_viewport!(child_list_mut); + Ok(()) } diff --git a/src/commands/sub_process.rs b/src/commands/sub_process.rs index 437112e..58bfdc1 100644 --- a/src/commands/sub_process.rs +++ b/src/commands/sub_process.rs @@ -81,7 +81,7 @@ pub fn sub_process( ) -> AppResult { backend.terminal_drop(); let res = execute_sub_process(context, words, spawn); - backend.terminal_restore()?; + backend.terminal_restore(context.config_ref().mouse_support)?; let _ = reload::soft_reload_curr_tab(context); context.message_queue_mut().push_info(format!( "{}: {}", diff --git a/src/commands/zoxide.rs b/src/commands/zoxide.rs index 222bb9d..a065117 100644 --- a/src/commands/zoxide.rs +++ b/src/commands/zoxide.rs @@ -49,7 +49,7 @@ pub fn zoxide_query_interactive(context: &mut AppContext, backend: &mut AppBacke .spawn()?; let zoxide_output = zoxide_process.wait_with_output()?; - backend.terminal_restore()?; + backend.terminal_restore(context.config_ref().mouse_support)?; if zoxide_output.status.success() { if let Ok(zoxide_str) = std::str::from_utf8(&zoxide_output.stdout) { diff --git a/src/config/clean/app/config.rs b/src/config/clean/app/config.rs index 0995e8d..ee3a24b 100644 --- a/src/config/clean/app/config.rs +++ b/src/config/clean/app/config.rs @@ -2,9 +2,8 @@ use std::collections::HashMap; use crate::{ config::{ - parse_config_or_default, raw::app::{AppConfigRaw, CustomCommand}, - TomlConfigFile, + ConfigType, TomlConfigFile, }, error::AppResult, }; @@ -22,6 +21,7 @@ pub struct AppConfig { pub watch_files: bool, pub custom_commands: Vec<CustomCommand>, pub focus_on_create: bool, + pub mouse_support: bool, pub cmd_aliases: HashMap<String, String>, pub _display_options: DisplayOption, pub _preview_options: PreviewOption, @@ -71,8 +71,10 @@ impl std::default::Default for AppConfig { } impl TomlConfigFile for AppConfig { - fn get_config(file_name: &str) -> Self { - parse_config_or_default::<AppConfigRaw, AppConfig>(file_name) + type Raw = AppConfigRaw; + + fn get_type() -> ConfigType { + ConfigType::App } } @@ -85,6 +87,7 @@ impl From<AppConfigRaw> for AppConfig { watch_files: raw.watch_files, cmd_aliases: raw.cmd_aliases, focus_on_create: raw.focus_on_create, + mouse_support: raw.mouse_support, _display_options: DisplayOption::from(raw.display_options), _preview_options: PreviewOption::from(raw.preview_options), _search_options: SearchOption::from(raw.search_options), diff --git a/src/config/clean/app/mod.rs b/src/config/clean/app/mod.rs index 11fb46a..d517b31 100644 --- a/src/config/clean/app/mod.rs +++ b/src/config/clean/app/mod.rs @@ -7,7 +7,7 @@ pub mod tab; pub use config::*; #[cfg(not(target_os = "windows"))] -const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("../../../../config/joshuto.toml"); +pub const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("../../../../config/joshuto.toml"); #[cfg(target_os = "windows")] -const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("..\\..\\..\\..\\config\\joshuto.toml"); +pub const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("..\\..\\..\\..\\config\\joshuto.toml"); diff --git a/src/config/clean/app/preview/config.rs b/src/config/clean/app/preview/config.rs index 2fd50e5..e14407e 100644 --- a/src/config/clean/app/preview/config.rs +++ b/src/config/clean/app/preview/config.rs @@ -1,18 +1,18 @@ use std::path; use crate::{ - config::{raw::app::display::preview::PreviewOptionRaw, search_directories}, + config::{ + raw::app::display::preview::{default_max_preview_size, PreviewOptionRaw, PreviewProtocol}, + search_directories, + }, util::unix, CONFIG_HIERARCHY, }; -const fn default_max_preview_size() -> u64 { - 2 * 1024 * 1024 // 2 MB -} - #[derive(Clone, Debug)] pub struct PreviewOption { pub max_preview_size: u64, + pub preview_protocol: PreviewProtocol, pub preview_script: Option<path::PathBuf>, pub preview_shown_hook_script: Option<path::PathBuf>, pub preview_removed_hook_script: Option<path::PathBuf>, @@ -22,6 +22,7 @@ impl std::default::Default for PreviewOption { fn default() -> Self { Self { max_preview_size: default_max_preview_size(), + preview_protocol: PreviewProtocol::Auto, preview_script: None, preview_shown_hook_script: None, preview_removed_hook_script: None, @@ -46,6 +47,7 @@ impl From<PreviewOptionRaw> for PreviewOption { Self { max_preview_size: raw.max_preview_size, + preview_protocol: raw.preview_protocol, preview_script, preview_shown_hook_script, preview_removed_hook_script, diff --git a/src/config/clean/bookmarks.rs b/src/config/clean/bookmarks.rs index 370fef2..155755d 100644 --- a/src/config/clean/bookmarks.rs +++ b/src/config/clean/bookmarks.rs @@ -3,16 +3,16 @@ use termion::event::Event; use std::collections::HashMap; use crate::config::raw::bookmarks::BookmarksRaw; -use crate::config::TomlConfigFile; +use crate::config::{ConfigType, TomlConfigFile}; use crate::util::keyparse; -use crate::config::parse_config_or_default; - pub type Bookmarks = HashMap<Event, String>; impl TomlConfigFile for Bookmarks { - fn get_config(file_name: &str) -> Self { - parse_config_or_default::<BookmarksRaw, Bookmarks>(file_name) + type Raw = BookmarksRaw; + + fn get_type() -> ConfigType { + ConfigType::Bookmarks } } diff --git a/src/config/clean/icon/config.rs b/src/config/clean/icon/config.rs index 02a80c3..a0c25af 100644 --- a/src/config/clean/icon/config.rs +++ b/src/config/clean/icon/config.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use crate::{ - config::{parse_config_or_default, raw::icon::IconsRaw, TomlConfigFile}, + config::{raw::icon::IconsRaw, ConfigType, TomlConfigFile}, error::AppResult, }; @@ -30,8 +30,10 @@ impl std::default::Default for Icons { } impl TomlConfigFile for Icons { - fn get_config(file_name: &str) -> Self { - parse_config_or_default::<IconsRaw, Icons>(file_name) + type Raw = IconsRaw; + + fn get_type() -> ConfigType { + ConfigType::Icons } } diff --git a/src/config/clean/icon/mod.rs b/src/config/clean/icon/mod.rs index ac4a11a..e23656d 100644 --- a/src/config/clean/icon/mod.rs +++ b/src/config/clean/icon/mod.rs @@ -2,7 +2,8 @@ mod config; pub use config::*; -const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("../../../../config/icons.toml"); +#[cfg(not(target_os = "windows"))] +pub const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("../../../../config/icons.toml"); #[cfg(target_os = "windows")] -const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("..\\..\\..\\..\\config\\icons.toml"); +pub const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("..\\..\\..\\..\\config\\icons.toml"); diff --git a/src/config/clean/keymap/config.rs b/src/config/clean/keymap/config.rs index 55e1bf9..c51721a 100644 --- a/src/config/clean/keymap/config.rs +++ b/src/config/clean/keymap/config.rs @@ -5,7 +5,7 @@ use std::str::FromStr; use termion::event::Event; use crate::config::raw::keymap::{AppKeyMappingRaw, CommandKeymap}; -use crate::config::{parse_config_or_default, TomlConfigFile}; +use crate::config::{ConfigType, TomlConfigFile}; use crate::error::AppResult; use crate::key_command::{Command, CommandKeybind}; use crate::traits::ToString; @@ -113,8 +113,10 @@ impl From<AppKeyMappingRaw> for AppKeyMapping { } impl TomlConfigFile for AppKeyMapping { - fn get_config(file_name: &str) -> Self { - parse_config_or_default::<AppKeyMappingRaw, AppKeyMapping>(file_name) + type Raw = AppKeyMappingRaw; + + fn get_type() -> ConfigType { + ConfigType::Keymap } } diff --git a/src/config/clean/keymap/mod.rs b/src/config/clean/keymap/mod.rs index f68fbef..4398f8d 100644 --- a/src/config/clean/keymap/mod.rs +++ b/src/config/clean/keymap/mod.rs @@ -3,7 +3,7 @@ mod config; pub use self::config::*; #[cfg(not(target_os = "windows"))] -const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("../../../../config/keymap.toml"); +pub const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("../../../../config/keymap.toml"); #[cfg(target_os = "windows")] -const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("..\\..\\..\\..\\config\\keymap.toml"); +pub const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("..\\..\\..\\..\\config\\keymap.toml"); diff --git a/src/config/clean/mimetype/config.rs b/src/config/clean/mimetype/config.rs index 166e7e2..2419f88 100644 --- a/src/config/clean/mimetype/config.rs +++ b/src/config/clean/mimetype/config.rs @@ -1,8 +1,6 @@ use std::collections::HashMap; -use crate::config::{ - parse_config_or_default, raw::mimetype::AppProgramRegistryRaw, TomlConfigFile, -}; +use crate::config::{raw::mimetype::AppProgramRegistryRaw, ConfigType, TomlConfigFile}; use super::{ExtensionAppList, MimetypeAppList}; @@ -69,7 +67,9 @@ impl From<AppProgramRegistryRaw> for AppProgramRegistry { } impl TomlConfigFile for AppProgramRegistry { - fn get_config(file_name: &str) -> Self { - parse_config_or_default::<AppProgramRegistryRaw, AppProgramRegistry>(file_name) + type Raw = AppProgramRegistryRaw; + + fn get_type() -> ConfigType { + ConfigType::Mimetype } } diff --git a/src/config/clean/mimetype/entry.rs b/src/config/clean/mimetype/entry.rs index 790fe7c..ee18998 100644 --- a/src/config/clean/mimetype/entry.rs +++ b/src/config/clean/mimetype/entry.rs @@ -12,8 +12,8 @@ pub struct ProgramEntry { _fork: bool, #[serde(default, rename = "silent")] _silent: bool, - #[serde(default, rename = "confirm_exit")] - _confirm_exit: bool, + #[serde(default, rename = "pager")] + _pager: bool, } impl ProgramEntry { @@ -23,7 +23,7 @@ impl ProgramEntry { _args: Vec::new(), _fork: false, _silent: false, - _confirm_exit: false, + _pager: false, } } @@ -54,12 +54,6 @@ impl ProgramEntry { self } - #[allow(dead_code)] - pub fn confirm_exit(&mut self, confirm_exit: bool) -> &mut Self { - self._confirm_exit = confirm_exit; - self - } - pub fn get_command(&self) -> &str { self._command.as_str() } @@ -76,8 +70,8 @@ impl ProgramEntry { self._silent } - pub fn get_confirm_exit(&self) -> bool { - self._confirm_exit + pub fn get_pager(&self) -> bool { + self._pager } // TODO: Windows support @@ -96,7 +90,7 @@ impl std::default::Default for ProgramEntry { _args: Vec::new(), _fork: false, _silent: false, - _confirm_exit: false, + _pager: false, } } } @@ -115,8 +109,8 @@ impl std::fmt::Display for ProgramEntry { if self.get_silent() { f.write_str("[silent]").unwrap(); } - if self.get_confirm_exit() { - f.write_str("[confirm-exit]").unwrap(); + if self.get_pager() { + f.write_str("[pager]").unwrap(); } f.write_str("") } diff --git a/src/config/clean/preview/config.rs b/src/config/clean/preview/config.rs index 0588c5f..1490cb3 100644 --- a/src/config/clean/preview/config.rs +++ b/src/config/clean/preview/config.rs @@ -2,7 +2,7 @@ use std::collections::HashMap; use serde::Deserialize; -use crate::config::{parse_config_or_default, raw::preview::FileEntryPreviewRaw, TomlConfigFile}; +use crate::config::{raw::preview::FileEntryPreviewRaw, ConfigType, TomlConfigFile}; #[derive(Debug, Deserialize)] pub struct FileEntryPreviewEntry { @@ -17,8 +17,10 @@ pub struct FileEntryPreview { } impl TomlConfigFile for FileEntryPreview { - fn get_config(file_name: &str) -> Self { - parse_config_or_default::<FileEntryPreviewRaw, FileEntryPreview>(file_name) + type Raw = FileEntryPreviewRaw; + + fn get_type() -> ConfigType { + ConfigType::Preview } } diff --git a/src/config/clean/theme/config.rs b/src/config/clean/theme/config.rs index 9028490..7fd25cd 100644 --- a/src/config/clean/theme/config.rs +++ b/src/config/clean/theme/config.rs @@ -1,7 +1,8 @@ +use lscolors::LsColors; use std::collections::HashMap; use crate::config::raw::theme::AppThemeRaw; -use crate::config::{parse_config_or_default, TomlConfigFile}; +use crate::config::{ConfigType, TomlConfigFile}; use crate::error::AppResult; use super::style::AppStyle; @@ -20,6 +21,7 @@ pub struct AppTheme { pub link_invalid: AppStyle, pub socket: AppStyle, pub ext: HashMap<String, AppStyle>, + pub lscolors: Option<LsColors>, } impl AppTheme { @@ -30,8 +32,10 @@ impl AppTheme { } impl TomlConfigFile for AppTheme { - fn get_config(file_name: &str) -> Self { - parse_config_or_default::<AppThemeRaw, AppTheme>(file_name) + type Raw = AppThemeRaw; + + fn get_type() -> ConfigType { + ConfigType::Theme } } @@ -62,6 +66,13 @@ impl From<AppThemeRaw> for AppTheme { (k.clone(), style) }) .collect(); + let lscolors = if raw.lscolors_enabled { + let lscolors = LsColors::from_env(); + let default = Some(LsColors::default()); + lscolors.or(default) + } else { + None + }; Self { selection, @@ -74,6 +85,7 @@ impl From<AppThemeRaw> for AppTheme { socket, ext, tabs: TabTheme::from(tabs), + lscolors, } } } diff --git a/src/config/clean/theme/mod.rs b/src/config/clean/theme/mod.rs index a9f7cbb..a6694c9 100644 --- a/src/config/clean/theme/mod.rs +++ b/src/config/clean/theme/mod.rs @@ -5,7 +5,7 @@ pub mod tab; pub use config::*; #[cfg(not(target_os = "windows"))] -const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("../../../../config/theme.toml"); +pub const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("../../../../config/theme.toml"); #[cfg(target_os = "windows")] -const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("..\\..\\..\\..\\config\\theme.toml"); +pub const DEFAULT_CONFIG_FILE_PATH: &str = include_str!("..\\..\\..\\..\\config\\theme.toml"); diff --git a/src/config/config_type.rs b/src/config/config_type.rs new file mode 100644 index 0000000..7a4755a --- /dev/null +++ b/src/config/config_type.rs @@ -0,0 +1,75 @@ +#[derive(Copy, Clone, Debug)] +pub enum ConfigType { + App, + Mimetype, + Keymap, + Theme, + Preview, + Bookmarks, + Icons, +} + +impl std::fmt::Display for ConfigType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.as_str()) + } +} + +impl clap::ValueEnum for ConfigType { + fn value_variants<'a>() -> &'a [Self] { + Self::enumerate() + } + + fn to_possible_value(&self) -> Option<clap::builder::PossibleValue> { + Some(clap::builder::PossibleValue::new(self.as_str())) + } +} |