From 6e2164aeaaf02bf61099e773a0341a38652c5da4 Mon Sep 17 00:00:00 2001 From: Jeff Zhao Date: Wed, 20 Oct 2021 15:52:41 -0400 Subject: rework config structure --- config/joshuto.toml | 4 +- src/commands/sort.rs | 2 +- src/config/general/app.rs | 52 ++++++++++++ src/config/general/app_crude.rs | 51 ++++++++++++ src/config/general/config.rs | 101 ----------------------- src/config/general/display.rs | 93 --------------------- src/config/general/display_crude.rs | 108 ++++++++++++++++++++++++ src/config/general/mod.rs | 18 ++-- src/config/general/preview.rs | 66 --------------- src/config/general/preview_crude.rs | 51 ++++++++++++ src/config/general/sort.rs | 50 ----------- src/config/general/sort_crude.rs | 51 ++++++++++++ src/config/general/tab.rs | 57 ------------- src/config/general/tab_crude.rs | 37 +++++++++ src/config/keymap/keymapping.rs | 85 +++++++++---------- src/config/mimetype/registry.rs | 57 ++++++------- src/config/mod.rs | 19 ++--- src/config/option/display_option.rs | 128 +++++++++++++++++++++++++++++ src/config/option/mod.rs | 11 +++ src/config/option/preview_option.rs | 27 ++++++ src/config/option/sort_option.rs | 54 ++++++++++++ src/config/option/sort_type.rs | 160 ++++++++++++++++++++++++++++++++++++ src/config/option/tab_option.rs | 27 ++++++ src/config/preview.rs | 22 ++--- src/config/sort/mod.rs | 11 --- src/config/sort/sort.rs | 49 ----------- src/config/theme/app_theme.rs | 32 ++++---- src/fs/dirlist.rs | 28 ++++--- src/fs/entry.rs | 2 +- src/history.rs | 2 +- src/key_command/command.rs | 2 +- src/key_command/impl_comment.rs | 2 +- src/key_command/impl_from_str.rs | 2 +- src/main.rs | 2 +- src/tab.rs | 2 +- src/ui/tui_backend.rs | 2 +- src/util/display_option.rs | 122 --------------------------- src/util/mod.rs | 3 - src/util/sort_option.rs | 53 ------------ src/util/sort_type.rs | 160 ------------------------------------ 40 files changed, 900 insertions(+), 905 deletions(-) create mode 100644 src/config/general/app.rs create mode 100644 src/config/general/app_crude.rs delete mode 100644 src/config/general/config.rs delete mode 100644 src/config/general/display.rs create mode 100644 src/config/general/display_crude.rs delete mode 100644 src/config/general/preview.rs create mode 100644 src/config/general/preview_crude.rs delete mode 100644 src/config/general/sort.rs create mode 100644 src/config/general/sort_crude.rs delete mode 100644 src/config/general/tab.rs create mode 100644 src/config/general/tab_crude.rs create mode 100644 src/config/option/display_option.rs create mode 100644 src/config/option/mod.rs create mode 100644 src/config/option/preview_option.rs create mode 100644 src/config/option/sort_option.rs create mode 100644 src/config/option/sort_type.rs create mode 100644 src/config/option/tab_option.rs delete mode 100644 src/config/sort/mod.rs delete mode 100644 src/config/sort/sort.rs delete mode 100644 src/util/display_option.rs delete mode 100644 src/util/sort_option.rs delete mode 100644 src/util/sort_type.rs diff --git a/config/joshuto.toml b/config/joshuto.toml index a3b797c..4b8616a 100644 --- a/config/joshuto.toml +++ b/config/joshuto.toml @@ -1,6 +1,3 @@ -# currently does not work -scroll_offset = 6 - xdg_open = false use_trash = true @@ -9,6 +6,7 @@ automatically_count_files = false collapse_preview = true # ratios for parent view, current view and preview column_ratio = [1, 4, 4] +scroll_offset = 6 show_borders = true show_hidden = false show_icons = true diff --git a/src/commands/sort.rs b/src/commands/sort.rs index 7102fc3..ba9f103 100644 --- a/src/commands/sort.rs +++ b/src/commands/sort.rs @@ -1,7 +1,7 @@ +use crate::config::option::SortType; use crate::context::AppContext; use crate::error::JoshutoResult; use crate::history::DirectoryHistory; -use crate::util::sort_type::SortType; use super::reload; diff --git a/src/config/general/app.rs b/src/config/general/app.rs new file mode 100644 index 0000000..5c3c3cf --- /dev/null +++ b/src/config/general/app.rs @@ -0,0 +1,52 @@ +use serde_derive::Deserialize; + +use crate::config::option::{DisplayOption, PreviewOption, SortOption, TabOption}; +use crate::config::{parse_to_config_file, TomlConfigFile}; + +#[derive(Debug, Clone)] +pub struct AppConfig { + pub use_trash: bool, + pub xdg_open: bool, + pub _display_options: DisplayOption, + pub _preview_options: PreviewOption, + pub _tab_options: TabOption, +} + +impl AppConfig { + pub fn display_options_ref(&self) -> &DisplayOption { + &self._display_options + } + pub fn display_options_mut(&mut self) -> &mut DisplayOption { + &mut self._display_options + } + + pub fn preview_options_ref(&self) -> &PreviewOption { + &self._preview_options + } + pub fn preview_options_mut(&mut self) -> &mut PreviewOption { + &mut self._preview_options + } + + pub fn sort_options_ref(&self) -> &SortOption { + self.display_options_ref().sort_options_ref() + } + pub fn sort_options_mut(&mut self) -> &mut SortOption { + self.display_options_mut().sort_options_mut() + } + + pub fn tab_options_ref(&self) -> &TabOption { + &self._tab_options + } +} + +impl std::default::Default for AppConfig { + fn default() -> Self { + Self { + use_trash: true, + xdg_open: false, + _display_options: DisplayOption::default(), + _preview_options: PreviewOption::default(), + _tab_options: TabOption::default(), + } + } +} diff --git a/src/config/general/app_crude.rs b/src/config/general/app_crude.rs new file mode 100644 index 0000000..d24eff9 --- /dev/null +++ b/src/config/general/app_crude.rs @@ -0,0 +1,51 @@ +use std::convert::From; + +use serde_derive::Deserialize; + +use crate::config::option::{DisplayOption, PreviewOption, TabOption}; +use crate::config::{parse_to_config_file, AppConfig, TomlConfigFile}; + +use super::display_crude::DisplayOptionCrude; +use super::preview_crude::PreviewOptionCrude; +use super::tab_crude::TabOptionCrude; + +const fn default_true() -> bool { + true +} +const fn default_scroll_offset() -> usize { + 6 +} + +#[derive(Clone, Debug, Deserialize)] +pub struct AppConfigCrude { + #[serde(default = "default_scroll_offset")] + pub scroll_offset: usize, + #[serde(default = "default_true")] + pub use_trash: bool, + #[serde(default)] + pub xdg_open: bool, + #[serde(default, rename = "display")] + pub display_options: DisplayOptionCrude, + #[serde(default, rename = "preview")] + pub preview_options: PreviewOptionCrude, + #[serde(default, rename = "tab")] + pub tab_options: TabOptionCrude, +} + +impl From for AppConfig { + fn from(crude: AppConfigCrude) -> Self { + Self { + use_trash: crude.use_trash, + xdg_open: crude.xdg_open, + _display_options: DisplayOption::from(crude.display_options), + _preview_options: PreviewOption::from(crude.preview_options), + _tab_options: TabOption::from(crude.tab_options), + } + } +} + +impl TomlConfigFile for AppConfig { + fn get_config(file_name: &str) -> Self { + parse_to_config_file::(file_name).unwrap_or_else(Self::default) + } +} diff --git a/src/config/general/config.rs b/src/config/general/config.rs deleted file mode 100644 index 3196017..0000000 --- a/src/config/general/config.rs +++ /dev/null @@ -1,101 +0,0 @@ -use serde_derive::Deserialize; - -use super::preview::{PreviewOption, PreviewRawOption}; -use super::tab::{TabOption, TabRawOption}; -use super::DisplayRawOption; - -use crate::config::{parse_to_config_file, ConfigStructure, Flattenable}; -use crate::util::display_option::DisplayOption; -use crate::util::sort_option::SortOption; - -const fn default_true() -> bool { - true -} -const fn default_scroll_offset() -> usize { - 6 -} - -#[derive(Clone, Debug, Deserialize)] -pub struct RawAppConfig { - #[serde(default = "default_scroll_offset")] - scroll_offset: usize, - #[serde(default = "default_true")] - use_trash: bool, - #[serde(default)] - xdg_open: bool, - #[serde(default, rename = "display")] - display_options: DisplayRawOption, - #[serde(default, rename = "preview")] - preview_options: PreviewRawOption, - #[serde(default, rename = "tab")] - tab_options: TabRawOption, -} - -impl Flattenable for RawAppConfig { - fn flatten(self) -> AppConfig { - AppConfig { - scroll_offset: self.scroll_offset, - use_trash: self.use_trash, - xdg_open: self.xdg_open, - _display_options: self.display_options.flatten(), - _preview_options: self.preview_options.flatten(), - _tab_options: self.tab_options.flatten(), - } - } -} - -#[derive(Debug, Clone)] -pub struct AppConfig { - pub scroll_offset: usize, - pub use_trash: bool, - pub xdg_open: bool, - _display_options: DisplayOption, - _preview_options: PreviewOption, - _tab_options: TabOption, -} - -impl AppConfig { - pub fn display_options_ref(&self) -> &DisplayOption { - &self._display_options - } - pub fn display_options_mut(&mut self) -> &mut DisplayOption { - &mut self._display_options - } - - pub fn preview_options_ref(&self) -> &PreviewOption { - &self._preview_options - } - pub fn preview_options_mut(&mut self) -> &mut PreviewOption { - &mut self._preview_options - } - - pub fn sort_options_ref(&self) -> &SortOption { - self.display_options_ref().sort_options_ref() - } - pub fn sort_options_mut(&mut self) -> &mut SortOption { - self.display_options_mut().sort_options_mut() - } - - pub fn tab_options_ref(&self) -> &TabOption { - &self._tab_options - } -} - -impl ConfigStructure for AppConfig { - fn get_config(file_name: &str) -> Self { - parse_to_config_file::(file_name).unwrap_or_else(Self::default) - } -} - -impl std::default::Default for AppConfig { - fn default() -> Self { - Self { - scroll_offset: default_scroll_offset(), - use_trash: true, - xdg_open: false, - _display_options: DisplayOption::default(), - _preview_options: PreviewOption::default(), - _tab_options: TabOption::default(), - } - } -} diff --git a/src/config/general/display.rs b/src/config/general/display.rs deleted file mode 100644 index 7ca6456..0000000 --- a/src/config/general/display.rs +++ /dev/null @@ -1,93 +0,0 @@ -use serde_derive::Deserialize; -use tui::layout::Constraint; - -use crate::config::Flattenable; -use crate::util::display_option::{default_column_ratio, DisplayOption}; - -use super::SortRawOption; - -const fn default_true() -> bool { - true -} - -#[derive(Clone, Debug, Deserialize)] -pub struct DisplayRawOption { - #[serde(default)] - automatically_count_files: bool, - - #[serde(default = "default_true")] - collapse_preview: bool, - - #[serde(default)] - column_ratio: Option<[usize; 3]>, - - #[serde(default = "default_true")] - show_borders: bool, - - #[serde(default)] - show_hidden: bool, - - #[serde(default)] - show_icons: bool, - - #[serde(default = "default_true")] - show_preview: bool, - - #[serde(default = "default_true")] - tilde_in_titlebar: bool, - - #[serde(default, rename = "sort")] - sort_options: SortRawOption, -} - -impl Flattenable for DisplayRawOption { - fn flatten(self) -> DisplayOption { - let column_ratio = match self.column_ratio { - Some(s) => (s[0], s[1], s[2]), - _ => default_column_ratio(), - }; - - let total = (column_ratio.0 + column_ratio.1 + column_ratio.2) as u32; - - let default_layout = [ - Constraint::Ratio(column_ratio.0 as u32, total), - Constraint::Ratio(column_ratio.1 as u32, total), - Constraint::Ratio(column_ratio.2 as u32, total), - ]; - let no_preview_layout = [ - Constraint::Ratio(column_ratio.0 as u32, total), - Constraint::Ratio(column_ratio.1 as u32 + column_ratio.2 as u32, total), - Constraint::Ratio(0, total), - ]; - - DisplayOption { - _automatically_count_files: self.automatically_count_files, - _collapse_preview: self.collapse_preview, - column_ratio, - _show_borders: self.show_borders, - _show_hidden: self.show_hidden, - _show_icons: self.show_icons, - _show_preview: self.show_preview, - _sort_options: self.sort_options.into(), - _tilde_in_titlebar: self.tilde_in_titlebar, - default_layout, - no_preview_layout, - } - } -} - -impl std::default::Default for DisplayRawOption { - fn default() -> Self { - Self { - automatically_count_files: false, - collapse_preview: true, - column_ratio: None, - show_borders: true, - show_hidden: false, - show_icons: false, - show_preview: true, - sort_options: SortRawOption::default(), - tilde_in_titlebar: true, - } - } -} diff --git a/src/config/general/display_crude.rs b/src/config/general/display_crude.rs new file mode 100644 index 0000000..ba3c307 --- /dev/null +++ b/src/config/general/display_crude.rs @@ -0,0 +1,108 @@ +use std::convert::From; + +use serde_derive::Deserialize; +use tui::layout::Constraint; + +use crate::config::option::DisplayOption; + +use super::sort_crude::SortOptionCrude; + +pub const fn default_column_ratio() -> (usize, usize, usize) { + (1, 3, 4) +} + +const fn default_true() -> bool { + true +} + +const fn default_scroll_offset() -> usize { + 4 +} + +#[derive(Clone, Debug, Deserialize)] +pub struct DisplayOptionCrude { + #[serde(default)] + pub automatically_count_files: bool, + + #[serde(default = "default_true")] + pub collapse_preview: bool, + + #[serde(default)] + pub column_ratio: Option<[usize; 3]>, + + #[serde(default = "default_scroll_offset")] + pub scroll_offset: usize, + + #[serde(default = "default_true")] + pub show_borders: bool, + + #[serde(default)] + pub show_hidden: bool, + + #[serde(default)] + pub show_icons: bool, + + #[serde(default = "default_true")] + pub show_preview: bool, + + #[serde(default = "default_true")] + pub tilde_in_titlebar: bool, + + #[serde(default, rename = "sort")] + pub sort_options: SortOptionCrude, +} + +impl std::default::Default for DisplayOptionCrude { + fn default() -> Self { + Self { + automatically_count_files: false, + collapse_preview: true, + column_ratio: None, + scroll_offset: 4, + show_borders: true, + show_hidden: false, + show_icons: false, + show_preview: true, + sort_options: SortOptionCrude::default(), + tilde_in_titlebar: true, + } + } +} + +impl From for DisplayOption { + fn from(crude: DisplayOptionCrude) -> Self { + let column_ratio = match crude.column_ratio { + Some(s) => (s[0], s[1], s[2]), + _ => default_column_ratio(), + }; + + let total = (column_ratio.0 + column_ratio.1 + column_ratio.2) as u32; + + let default_layout = [ + Constraint::Ratio(column_ratio.0 as u32, total), + Constraint::Ratio(column_ratio.1 as u32, total), + Constraint::Ratio(column_ratio.2 as u32, total), + ]; + let no_preview_layout = [ + Constraint::Ratio(column_ratio.0 as u32, total), + Constraint::Ratio(column_ratio.1 as u32 + column_ratio.2 as u32, total), + Constraint::Ratio(0, total), + ]; + + Self { + _automatically_count_files: crude.automatically_count_files, + _collapse_preview: crude.collapse_preview, + _scroll_offset: crude.scroll_offset, + _show_borders: crude.show_borders, + _show_hidden: crude.show_hidden, + _show_icons: crude.show_icons, + _show_preview: crude.show_preview, + _sort_options: crude.sort_options.into(), + _tilde_in_titlebar: crude.tilde_in_titlebar, + + column_ratio, + default_layout, + no_preview_layout, + } + } +} diff --git a/src/config/general/mod.rs b/src/config/general/mod.rs index dc8617c..ff42b69 100644 --- a/src/config/general/mod.rs +++ b/src/config/general/mod.rs @@ -1,11 +1,9 @@ -pub mod config; -pub mod display; -pub mod preview; -pub mod sort; -pub mod tab; +pub mod app; -pub use self::config::AppConfig; -pub use self::display::DisplayRawOption; -pub use self::preview::{PreviewOption, PreviewRawOption}; -pub use self::sort::SortRawOption; -pub use self::tab::{TabOption, TabRawOption}; +mod app_crude; +mod display_crude; +mod preview_crude; +mod sort_crude; +mod tab_crude; + +pub use self::app::AppConfig; diff --git a/src/config/general/preview.rs b/src/config/general/preview.rs deleted file mode 100644 index 5d9436f..0000000 --- a/src/config/general/preview.rs +++ /dev/null @@ -1,66 +0,0 @@ -use std::path; - -use serde_derive::Deserialize; - -use crate::config::{search_directories, Flattenable}; -use crate::CONFIG_HIERARCHY; - -const fn default_max_preview_size() -> u64 { - 2 * 1024 * 1024 // 2 MB -} - -#[derive(Clone, Debug, Deserialize)] -pub struct PreviewRawOption { - #[serde(default = "default_max_preview_size")] - max_preview_size: u64, - #[serde(default)] - preview_images: bool, - #[serde(default)] - preview_script: Option, -} - -impl std::default::Default for PreviewRawOption { - fn default() -> Self { - Self { - max_preview_size: default_max_preview_size(), - preview_images: false, - preview_script: None, - } - } -} - -impl Flattenable for PreviewRawOption { - fn flatten(self) -> PreviewOption { - let preview_script = match self.preview_script { - Some(s) => { - let tilde_cow = shellexpand::tilde_with_context(s.as_str(), dirs_next::home_dir); - let tilde_path = path::PathBuf::from(tilde_cow.as_ref()); - Some(tilde_path) - } - None => search_directories("preview.sh", &CONFIG_HIERARCHY), - }; - - PreviewOption { - max_preview_size: self.max_preview_size, - preview_images: self.preview_images, - preview_script, - } - } -} - -#[derive(Clone, Debug)] -pub struct PreviewOption { - pub max_preview_size: u64, - pub preview_images: bool, - pub preview_script: Option, -} - -impl std::default::Default for PreviewOption { - fn default() -> Self { - Self { - max_preview_size: default_max_preview_size(), - preview_images: false, - preview_script: None, - } - } -} diff --git a/src/config/general/preview_crude.rs b/src/config/general/preview_crude.rs new file mode 100644 index 0000000..0d9c670 --- /dev/null +++ b/src/config/general/preview_crude.rs @@ -0,0 +1,51 @@ +use std::convert::From; +use std::path; + +use serde_derive::Deserialize; + +use crate::config::option::PreviewOption; +use crate::config::search_directories; +use crate::CONFIG_HIERARCHY; + +pub const fn default_max_preview_size() -> u64 { + 2 * 1024 * 1024 // 2 MB +} + +#[derive(Clone, Debug, Deserialize)] +pub struct PreviewOptionCrude { + #[serde(default = "default_max_preview_size")] + pub max_preview_size: u64, + #[serde(default)] + pub preview_images: bool, + #[serde(default)] + pub preview_script: Option, +} + +impl std::default::Default for PreviewOptionCrude { + fn default() -> Self { + Self { + max_preview_size: default_max_preview_size(), + preview_images: false, + preview_script: None, + } + } +} + +impl From for PreviewOption { + fn from(crude: PreviewOptionCrude) -> Self { + let preview_script = match crude.preview_script { + Some(s) => { + let tilde_cow = shellexpand::tilde_with_context(s.as_str(), dirs_next::home_dir); + let tilde_path = path::PathBuf::from(tilde_cow.as_ref()); + Some(tilde_path) + } + None => search_directories("preview.sh", &CONFIG_HIERARCHY), + }; + + Self { + max_preview_size: crude.max_preview_size, + preview_images: crude.preview_images, + preview_script, + } + } +} diff --git a/src/config/general/sort.rs b/src/config/general/sort.rs deleted file mode 100644 index fea3db2..0000000 --- a/src/config/general/sort.rs +++ /dev/null @@ -1,50 +0,0 @@ -use serde_derive::Deserialize; - -use crate::util::sort_option::SortOption; -use crate::util::sort_type::{SortType, SortTypes}; - -const fn default_true() -> bool { - true -} - -#[derive(Clone, Debug, Deserialize)] -pub struct SortRawOption { - #[serde(default = "default_true")] - pub directories_first: bool, - #[serde(default)] - pub case_sensitive: bool, - #[serde(default)] - pub reverse: bool, - #[serde(default)] - pub sort_method: Option, -} - -impl SortRawOption { - pub fn into(self) -> SortOption { - let sort_method = match self.sort_method.as_ref() { - Some(s) => SortType::parse(s).unwrap_or(SortType::Natural), - None => SortType::Natural, - }; - - let mut sort_methods = SortTypes::default(); - sort_methods.reorganize(sort_method); - - SortOption { - directories_first: self.directories_first, - case_sensitive: self.case_sensitive, - reverse: self.reverse, - sort_methods, - } - } -} - -impl std::default::Default for SortRawOption { - fn default() -> Self { - Self { - directories_first: default_true(), - case_sensitive: bool::default(), - reverse: bool::default(), - sort_method: None, - } - } -} diff --git a/src/config/general/sort_crude.rs b/src/config/general/sort_crude.rs new file mode 100644 index 0000000..f7a1836 --- /dev/null +++ b/src/config/general/sort_crude.rs @@ -0,0 +1,51 @@ +use std::convert::From; + +use serde_derive::Deserialize; + +use crate::config::option::{SortOption, SortType, SortTypes}; + +const fn default_true() -> bool { + true +} + +#[derive(Clone, Debug, Deserialize)] +pub struct SortOptionCrude { + #[serde(default = "default_true")] + pub directories_first: bool, + #[serde(default)] + pub case_sensitive: bool, + #[serde(default)] + pub reverse: bool, + #[serde(default)] + pub sort_method: Option, +} + +impl std::default::Default for SortOptionCrude { + fn default() -> Self { + Self { + directories_first: default_true(), + case_sensitive: bool::default(), + reverse: bool::default(), + sort_method: None, + } + } +} + +impl From for SortOption { + fn from(crude: SortOptionCrude) -> Self { + let sort_method = match crude.sort_method.as_ref() { + Some(s) => SortType::parse(s).unwrap_or(SortType::Natural), + None => SortType::Natural, + }; + + let mut sort_methods = SortTypes::default(); + sort_methods.reorganize(sort_method); + + Self { + directories_first: crude.directories_first, + case_sensitive: crude.case_sensitive, + reverse: crude.reverse, + sort_methods, + } + } +} diff --git a/src/config/general/tab.rs b/src/config/general/tab.rs deleted file mode 100644 index 1cd6a88..0000000 --- a/src/config/general/tab.rs +++ /dev/null @@ -1,57 +0,0 @@ -use serde_derive::Deserialize; - -use crate::config::Flattenable; -use crate::tab::TabHomePage; - -fn default_home_page() -> String { - "home".to_string() -} - -#[derive(Clone, Debug, Deserialize)] -pub struct TabRawOption { - #[serde(default = "default_home_page")] - home_page: String, -} - -impl std::default::Default for TabRawOption { - fn default() -> Self { - Self { - home_page: default_home_page(), - } - } -} - -impl Flattenable for TabRawOption { - fn flatten(self) -> TabOption { - let home_page = match self.home_page.as_str() { - "inherit" => TabHomePage::Inherit, - "home" => TabHomePage::Home, - "root" => TabHomePage::Root, - _ => TabHomePage::Home, - }; - - TabOption::new(home_page) - } -} - -#[derive(Clone, Debug)] -pub struct TabOption { - _home_page: TabHomePage, -} - -impl TabOption { - pub fn new(_home_page: TabHomePage) -> Self { - Self { _home_page } - } - pub fn home_page(&self) -> TabHomePage { - self._home_page - } -} - -impl std::default::Default for TabOption { - fn default() -> Self { - Self { - _home_page: TabHomePage::Home, - } - } -} diff --git a/src/config/general/tab_crude.rs b/src/config/general/tab_crude.rs new file mode 100644 index 0000000..2a8f8f3 --- /dev/null +++ b/src/config/general/tab_crude.rs @@ -0,0 +1,37 @@ +use std::convert::From; + +use serde_derive::Deserialize; + +use crate::config::option::TabOption; +use crate::tab::TabHomePage; + +fn default_home_page() -> String { + "home".to_string() +} + +#[derive(Clone, Debug, Deserialize)] +pub struct TabOptionCrude { + #[serde(default = "default_home_page")] + pub home_page: String, +} + +impl std::default::Default for TabOptionCrude { + fn default() -> Self { + Self { + home_page: default_home_page(), + } + } +} + +impl From for TabOption { + fn from(crude: TabOptionCrude) -> Self { + let home_page = match crude.home_page.as_str() { + "inherit" => TabHomePage::Inherit, + "home" => TabHomePage::Home, + "root" => TabHomePage::Root, + _ => TabHomePage::Home, + }; + + Self::new(home_page) + } +} diff --git a/src/config/keymap/keymapping.rs b/src/config/keymap/keymapping.rs index 0f42e94..3c3f68c 100644 --- a/src/config/keymap/keymapping.rs +++ b/src/config/keymap/keymapping.rs @@ -1,13 +1,14 @@ use serde_derive::Deserialize; use std::collections::{hash_map::Entry, HashMap}; +use std::convert::{AsMut, AsRef, From}; use std::str::FromStr; #[cfg(feature = "mouse")] use termion::event::MouseEvent; use termion::event::{Event, Key}; -use crate::config::{parse_to_config_file, ConfigStructure, Flattenable}; +use crate::config::{parse_to_config_file, TomlConfigFile}; use crate::error::JoshutoResult; use crate::io::IoWorkerOptions; use crate::key_command::{Command, CommandKeybind}; @@ -22,15 +23,46 @@ struct CommandKeymap { } #[derive(Debug, Deserialize)] -struct RawAppKeyMapping { +struct AppKeyMappingCrude { #[serde(default)] - mapcommand: Vec, + pub mapcommand: Vec, } -impl Flattenable for RawAppKeyMapping { - fn flatten(self) -> AppKeyMapping { - let mut keymaps = AppKeyMapping::new(); - for m in self.mapcommand { +#[derive(Debug)] +pub struct AppKeyMapping { + map: HashMap, +} + +impl AppKeyMapping { + pub fn new() -> Self { + Self { + map: HashMap::new(), + } + } + + pub fn default_res() -> JoshutoResult { + let crude: AppKeyMappingCrude = toml::from_str(DEFAULT_KEYMAP)?; + let keymapping: Self = Self::from(crude); + Ok(keymapping) + } +} + +impl AsRef> for AppKeyMapping { + fn as_ref(&self) -> &HashMap { + &self.map + } +} + +impl AsMut> for AppKeyMapping { + fn as_mut(&mut self) -> &mut HashMap { + &mut self.map + } +} + +impl From for AppKeyMapping { + fn from(crude: AppKeyMappingCrude) -> Self { + let mut keymaps = Self::new(); + for m in crude.mapcommand { match Command::from_str(m.command.as_str()) { Ok(command) => { let events: Vec = m @@ -57,34 +89,10 @@ impl Flattenable for RawAppKeyMapping { } } -#[derive(Debug)] -pub struct AppKeyMapping { - map: HashMap, -} - -impl std::convert::AsRef> for AppKeyMapping { - fn as_ref(&self) -> &HashMap { - &self.map - } -} - -impl std::convert::AsMut> for AppKeyMapping { - fn as_mut(&mut self) -> &mut HashMap { - &mut self.map - } -} - -impl AppKeyMapping { - pub fn new() -> Self { - Self { - map: HashMap::new(), - } - } - - pub fn default_res() -> JoshutoResult { - let raw: RawAppKeyMapping = toml::from_str(DEFAULT_KEYMAP)?; - let keymapping: Self = raw.flatten(); - Ok(keymapping) +impl TomlConfigFile for AppKeyMapping { + fn get_config(file_name: &str) -> Self { + parse_to_config_file::(file_name) + .unwrap_or_else(Self::default) } } @@ -94,13 +102,6 @@ impl std::default::Default for AppKeyMapping { } } -impl ConfigStructure for AppKeyMapping { - fn get_config(file_name: &str) -> Self { - parse_to_config_file::(file_name) - .unwrap_or_else(Self::default) - } -} - fn insert_keycommand( keymap: &mut AppKeyMapping, keycommand: Command, diff --git a/src/config/mimetype/registry.rs b/src/config/mimetype/registry.rs index f3736eb..26ba824 100644 --- a/src/config/mimetype/registry.rs +++ b/src/config/mimetype/registry.rs @@ -1,41 +1,20 @@ use serde_derive::Deserialize; use std::collections::HashMap; +use crate::config::{parse_to_config_file, TomlConfigFile}; + use super::{AppList, AppMimetypeEntry}; -use crate::config::{parse_to_config_file, ConfigStructure, Flattenable}; pub type MimetypeRegistry = HashMap; #[derive(Debug, Deserialize)] -pub struct RawAppMimetypeRegistry { +pub struct AppMimetypeRegistryCrude { #[serde(default, rename = "class")] pub _class: HashMap>, #[serde(default, rename = "extension")] pub _extension: MimetypeRegistry, } -impl Flattenable for RawAppMimetypeRegistry { - fn flatten(self) -> AppMimetypeRegistry { - let mut registry = MimetypeRegistry::new(); - - for (ext, app_list) in self._extension { - let class = app_list.parent(); - let mut combined_app_list: Vec = self - ._class - .get(class) - .map(|v| (*v).clone()) - .unwrap_or_default(); - combined_app_list.extend_from_slice(app_list.app_list()); - let combined_app_list = AppList::new(class.to_string(), combined_app_list); - registry.insert(ext, combined_app_list); - } - - AppMimetypeRegistry { - _extension: registry, - } - } -} - #[derive(Debug)] pub struct AppMimetypeRegistry { // pub _class: HashMap>, @@ -53,10 +32,25 @@ impl AppMimetypeRegistry { } } -impl ConfigStructure for AppMimetypeRegistry { - fn get_config(file_name: &str) -> Self { - parse_to_config_file::(file_name) - .unwrap_or_else(Self::default) +impl From for AppMimetypeRegistry { + fn from(crude: AppMimetypeRegistryCrude) -> Self { + let mut registry = MimetypeRegistry::new(); + + for (ext, app_list) in crude._extension { + let class = app_list.parent(); + let mut combined_app_list: Vec = crude + ._class + .get(class) + .map(|v| (*v).clone()) + .unwrap_or_default(); + combined_app_list.extend_from_slice(app_list.app_list()); + let combined_app_list = AppList::new(class.to_string(), combined_app_list); + registry.insert(ext, combined_app_list); + } + + Self { + _extension: registry, + } } } @@ -67,3 +61,10 @@ impl std::default::Default for AppMimetypeRegistry { } } } + +impl TomlConfigFile for AppMimetypeRegistry { + fn get_config(file_name: &str) -> Self { + parse_to_config_file::(file_name) + .unwrap_or_else(Self::default) + } +} diff --git a/src/config/mod.rs b/src/config/mod.rs index 23a3e7d..cd79299 100644 --- a/src/config/mod.rs +++ b/src/config/mod.rs @@ -1,14 +1,15 @@ pub mod general; pub mod keymap; pub mod mimetype; +pub mod option; pub mod preview; pub mod theme; pub use self::general::AppConfig; pub use self::keymap::AppKeyMapping; -pub use self::mimetype::{AppMimetypeEntry, AppMimetypeRegistry}; -pub use self::preview::{JoshutoPreview, JoshutoPreviewEntry}; -pub use self::theme::{AppStyle, AppTheme}; +pub use self::mimetype::*; +pub use self::preview::*; +pub use self::theme::*; use serde::de::DeserializeOwned; use std::fs; @@ -16,15 +17,10 @@ use std::path::{Path, PathBuf}; use crate::CONFIG_HIERARCHY; -pub trait ConfigStructure { +pub trait TomlConfigFile { fn get_config(file_name: &str) -> Self; } -// implemented by config file implementations to turn a RawConfig into a Config -trait Flattenable { - fn flatten(self) -> T; -} - // searches a list of folders for a given file in order of preference pub fn search_directories

(filename: &str, directories: &[P]) -> Option where @@ -42,7 +38,8 @@ where // parses a config file into its appropriate format fn parse_to_config_file(filename: &str) -> Option where - T: DeserializeOwned + Flattenable, + T: DeserializeOwned, + S: From, { let file_path = search_directories(filename, &CONFIG_HIERARCHY)?; let file_contents = match fs::read_to_string(&file_path) { @@ -59,5 +56,5 @@ where return None; } }; - Some(config.flatten()) + Some(S::from(config)) } diff --git a/src/config/option/display_option.rs b/src/config/option/display_option.rs new file mode 100644 index 0000000..3624840 --- /dev/null +++ b/src/config/option/display_option.rs @@ -0,0 +1,128 @@ +use std::convert::From; +use std::fs; + +use tui::layout::Constraint; + +use crate::config::option::SortOption; + +pub const fn default_column_ratio() -> (usize, usize, usize) { + (1, 3, 4) +} + +#[derive(Clone, Debug)] +pub struct DisplayOption { + pub _automatically_count_files: bool, + pub _collapse_preview: bool, + pub _scroll_offset: usize, + pub _show_borders: bool, + pub _show_hidden: bool, + pub _show_icons: bool, + pub _show_preview: bool, + pub _sort_options: SortOption, + pub _tilde_in_titlebar: bool, + pub column_ratio: (usize, usize, usize), + pub default_layout: [Constraint; 3], + pub no_preview_layout: [Constraint; 3], +} + +impl DisplayOption { + pub fn automatically_count_files(&self) -> bool { + self._automatically_count_files + } + + pub fn collapse_preview(&self) -> bool { + self._collapse_preview + } + + pub fn scroll_offset(&self) -> usize { + self._scroll_offset + } + + pub fn show_borders(&self) -> bool { + self._show_borders + } + + pub fn show_hidden(&self) -> bool { + self._show_hidden + } + + pub fn show_icons(&self) -> bool { + self._show_icons + } + + pub fn show_preview(&self) -> bool { + self._show_preview + } + + pub fn set_show_hidden(&mut self, show_hidden: bool) { + self._show_hidden = show_hidden; + } + + pub fn sort_options_ref(&self) -> &SortOption { + &self._sort_options + } + + pub fn sort_options_mut(&mut self) -> &mut SortOption { + &mut self._sort_options + } + + pub fn tilde_in_titlebar(&self) -> bool { + self._tilde_in_titlebar + } + + pub fn filter_func(&self) -> fn(&Result) -> bool { + if self.show_hidden() { + no_filter + } else { + filter_hidden + } + } +} + +impl std::default::Default for DisplayOption { + fn default() -> Self { + let column_ratio = default_column_ratio(); + + let total = (column_ratio.0 + column_ratio.1 + column_ratio.2) as u32; + let default_layout = [ + Constraint::Ratio(column_ratio.0 as u32, total), + Constraint::Ratio(column_ratio.1 as u32, total), + Constraint::Ratio(column_ratio.2 as u32, total), + ]; + let no_preview_layout = [ + Constraint::Ratio(column_ratio.0 as u32, total), + Constraint::Ratio(column_ratio.1 as u32 + column_ratio.2 as u32, total), + Constraint::Ratio(0, total), + ]; + + Self { + _automatically_count_files: false, + _collapse_preview: true, + column_ratio, + _scroll_offset: 4, + _show_borders: true, + _show_hidden: false, + _show_icons: false, + _show_preview: true, + _sort_options: SortOption::default(), + _tilde_in_titlebar: true, + default_layout, + no_preview_layout, + } + } +} + +const fn no_filter(_: &Result) -> bool { + true +} + +fn filter_hidden(result: &Result) -> bool { + match result { + Err(_) => true, + Ok(entry) => { + let file_name = entry.file_name(); + let lossy_string = file_name.as_os_str().to_string_lossy(); + !lossy_string.starts_with('.') + } + } +} diff --git a/src/config/option/mod.rs b/src/config/option/mod.rs new file mode 100644 index 0000000..6d0dec9 --- /dev/null +++ b/src/config/option/mod.rs @@ -0,0 +1,11 @@ +pub mod display_option; +pub mod preview_option; +pub mod sort_option; +pub mod sort_type; +pub mod tab_option; + +pub use self::display_option::*; +pub use self::preview_option::*; +pub use self::sort_option::*; +pub use self::sort_type::*; +pub use self::tab_option::*; diff --git a/src/config/option/preview_option.rs b/src/config/option/preview_option.rs new file mode 100644 index 0000000..16fe7ff --- /dev/null +++ b/src/config/option/preview_option.rs @@ -0,0 +1,27 @@ +use std::convert::From; +use std::path; + +use serde_derive::Deserialize; + +use crate::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_images: bool, + pub preview_script: Option, +} + +impl std::default::Default for PreviewOption { + fn default() -> Self { + Self { + max_preview_size: default_max_preview_size(), + preview_images: false, + preview_script: None, + } + } +} diff --git a/src/config/option/sort_option.rs b/src/config/option/sort_option.rs new file mode 100644 index 0000000..e83b049 --- /dev/null +++ b/src/config/option/sort_option.rs @@ -0,0 +1,54 @@ +use std::cmp; +use std::convert::From; + +use crate::config::option::{SortType, SortTypes}; +use crate::fs::JoshutoDirEntry; + +#[derive(Clone, Debug)] +pub struct SortOption { + pub directories_first: bool, + pub case_sensitive: bool, + pub reverse: bool, + pub sort_methods: SortTypes, +} + +impl SortOption { + pub fn set_sort_method(&mut self, method: SortType) { + self.sort_methods.reorganize(method); + } + + pub fn compare(&self, f1: &JoshutoDirEntry, f2: &JoshutoDirEntry) -> cmp::Ordering { + if self.directories_first { + let f1_isdir = f1.file_path().is_dir(); + let f2_isdir = f2.file_path().is_dir(); + + if f1_isdir && !f2_isdir { + return cmp::Ordering::Less; + } else if !f1_isdir && f2_isdir { + return cmp::Ordering::Greater; + } + } + + // let mut res = self.sort_method.cmp(f1, f2, &self); + let mut res = self.sort_methods.cmp(f1, f2, &self); + if self.reverse { + res = match res { + cmp::Ordering::Less => cmp::Ordering::Greater, + cmp::Ordering::Greater => cmp::Ordering::Less, + s => s, + }; + }; + res + } +} + +impl std::default::Default for SortOption { + fn default() -> Self { + SortOption { + directories_first: true, + case_sensitive: false, + reverse: false, + sort_methods: SortTypes::default(), + } + } +} diff --git a/src/config/option/sort_type.rs b/src/config/option/sort_type.rs new file mode 100644 index 0000000..442eb45 --- /dev/null +++ b/src/config/option/sort_type.rs @@ -0,0 +1,160 @@ +use std::cmp; +use std::collections::VecDeque; +use std::fs; +use std::time; + +use serde_derive::Deserialize; + +use crate::config::option::SortOption; +use crate::fs::JoshutoDirEntry; + +#[derive(Clone, Copy, Debug, Deserialize, PartialEq)] +pub enum SortType { + Lexical, + Mtime, + Natural, + Size, + Ext, +} + +impl SortType { + pub fn parse(s: &str) -> Option { + match s { + "lexical" => Some(SortType::Lexical), + "mtime" => Some(SortType::Mtime), + "natural" => Some(SortType::Natural), + "size" => Some(SortType::Size), + "ext" => Some(SortType::Ext), + _ => None, + } + } + pub const fn as_str(&self) -> &str { + match *self { + SortType::Lexical => "lexical", + SortType::Mtime => "mtime", + SortType::Natural => "natural", + SortType::Size => "size", + SortType::Ext => "ext", + } + } + pub fn cmp( + &self, + f1: &JoshutoDirEntry, + f2: &JoshutoDirEntry, + sort_option: &SortOption, + ) -> cmp::Ordering { + match &self { + SortType::Natural => natural_sort(f1, f2, sort_option), + SortType::Lexical => lexical_sort(f1, f2, sort_option), + SortType::Size => size_sort(f1, f2), + SortType::Mtime => mtime_sort(f1, f2), + SortType::Ext => ext_sort(f1, f2), + } + } +} + +impl std::fmt::Display for SortType { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + write!(f, "{}", self.as_str()) + } +} + +#[derive(Clone, Debug)] +pub struct SortTypes { + pub list: VecDeque, +} + +impl SortTypes { + pub fn reorganize(&mut self, st: SortType) { + self.list.push_front(st); + self.list.pop_back(); + } + + pub fn cmp( + &self, + f1: &JoshutoDirEntry, + f2: &JoshutoDirEntry, + sort_option: &SortOption, + ) -> cmp::Ordering { + for st in &self.list { + let res = st.cmp(f1, f2, sort_option); + if res != cmp::Ordering::Equal { + return res; + } + } + cmp::Ordering::Equal + } +} + +impl std::default::Default for SortTypes { + fn default() -> Self { + let list: VecDeque = vec![ + SortType::Natural, + SortType::Lexical, + SortType::Size, + SortType::Ext, + SortType::Mtime, + ] + .into_iter() + .collect(); + + Self { list } + } +} + +fn mtime_sort(file1: &JoshutoDirEntry, file2: &JoshutoDirEntry) -> cmp::Ordering { + fn compare( + file1: &JoshutoDirEntry, + file2: &JoshutoDirEntry, + ) -> Result { + let f1_meta: fs::Metadata = std::fs::metadata(file1.file_path())?; + let f2_meta: fs::Metadata = std::fs::metadata(file2.file_path())?; + + let f1_mtime: time::SystemTime = f1_meta.modified()?; + let f2_mtime: time::SystemTime = f2_meta.modified()?; + Ok(f1_mtime.cmp(&f2_mtime)) + } + compare(file1, file2).unwrap_or(cmp::Ordering::Equal) +} + +fn size_sort(file1: &JoshutoDirEntry, file2: &JoshutoDirEntry) -> cmp::Ordering { + file1.metadata.len().cmp(&file2.metadata.len()) +} + +fn ext_sort(file1: &JoshutoDirEntry, file2: &JoshutoDirEntry) -> cmp::Ordering { + let f1_ext = file1.get_ext(); + let f2_ext = file2.get_ext(); + alphanumeric_sort::compare_str(&f1_ext, &f2_ext) +} + +fn lexical_sort( + f1: &JoshutoDirEntry, + f2: &JoshutoDirEntry, + sort_option: &SortOption, +) -> cmp::Ordering { + let f1_name = f1.file_name(); + let f2_name = f2.file_name(); + if sort_option.case_sensitive { + f1_name.cmp(f2_name) + } else { + let f1_name = f1_name.to_lowercase(); + let f2_name = f2_name.to_lowercase(); + f1_name.cmp(&f2_name) + } +} + +fn natural_sort( + f1: &JoshutoDirEntry, + f2: &JoshutoDirEntry, + sort_option: &SortOption, +) -> cmp::Ordering { + let f1_name = f1.file_name(); + let f2_name = f2.file_name(); + if sort_option.case_sensitive { + alphanumeric_sort::compare_str(&f1_name, &f2_name) + } else { + let f1_name = f1_name.to_lowercase(); + let f2_name = f2_name.to_lowercase(); + alphanumeric_sort::compare_str(&f1_name, &f2_name) + } +} diff --git a/src/config/option/tab_option.rs b/src/config/option/tab_option.rs new file mode 100644 index 0000000..d7f0eac --- /dev/null +++ b/src/config/option/tab_option.rs @@ -0,0 +1,27 @@ +use std::convert::From; + +use serde_derive::Deserialize; + +use crate::tab::TabHomePage; + +#[derive(Clone, Debug)] +pub struct TabOption { + pub _home_page: TabHomePage, +} + +impl TabOption { + pub fn new(_home_page: TabHomePage) -> Self { + Self { _home_page } + } + pub fn home_page(&self) -> TabHomePage { + self._home_page + } +} + +impl std::default::Default for TabOption { + fn default() -> Self { + Self { + _home_page: TabHomePage::Home, + } + } +} diff --git a/src/config/preview.rs b/src/config/preview.rs index 14693b6..62883c8 100644 --- a/src/config/preview.rs +++ b/src/config/preview.rs @@ -1,7 +1,7 @@ use serde_derive::Deserialize; use std::collections::HashMap; -use super::{parse_to_config_file, ConfigStructure, Flattenable}; +use super::{parse_to_config_file, TomlConfigFile}; #[derive(Debug, Deserialize)] pub struct JoshutoPreviewEntry { @@ -10,26 +10,26 @@ pub struct JoshutoPreviewEntry { } #[derive(Debug, Deserialize)] -struct JoshutoRawPreview { +struct JoshutoPreviewCrude { pub extension: Option>, pub mimetype: Option>, } -impl std::default::Default for JoshutoRawPreview { +impl std::default::Default for JoshutoPreviewCrude { fn default() -> Self { - JoshutoRawPreview { + Self { extension: None, mimetype: None, } } } -impl Flattenable for JoshutoRawPreview { - fn flatten(self) -> JoshutoPreview { - let extension = self.extension.unwrap_or_default(); - let mimetype = self.mimetype.unwrap_or_default(); +impl From for JoshutoPreview { + fn from(crude: JoshutoPreviewCrude) -> Self { + let extension = crude.extension.unwrap_or_default(); + let mimetype = crude.mimetype.unwrap_or_default(); - JoshutoPreview { + Self { extension, mimetype, } @@ -42,9 +42,9 @@ pub struct JoshutoPreview { pub mimetype: HashMap, } -impl ConfigStructure for JoshutoPreview { +impl TomlConfigFile for JoshutoPreview { fn get_config(file_name: &str) -> Self { - parse_to_config_file::(file_name) + parse_to_config_file::(file_name) .unwrap_or_else(JoshutoPreview::default) } } diff --git a/src/config/sort/mod.rs b/src/config/sort/mod.rs deleted file mode 100644 index dc8617c..0000000 --- a/src/config/sort/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -pub mod config; -pub mod display; -pub mod preview; -pub mod sort; -pub mod tab; - -pub use self::config::AppConfig; -pub use self::display::DisplayRawOption; -pub use self::preview::{PreviewOption, PreviewRawOption}; -pub use self::sort::SortRawOption; -pub use self::tab::{TabOption, TabRawOption}; diff --git a/src/config/sort/sort.rs b/src/config/sort/sort.rs deleted file mode 100644 index 0768c98..0000000 --- a/src/config/sort/sort.rs +++ /dev/null @@ -1,49 +0,0 @@ -use serde_derive::Deserialize; - -use crate::util::sort; - -const fn default_true() -> bool { - true -} - -#[derive(Clone, Debug, Deserialize)] -pub struct SortRawOption { - #[serde(default = "default_true")] - pub directories_first: bool, - #[serde(default)] - pub case_sensitive: bool, - #[serde(default)] - pub reverse: bool, - #[serde(default)] - pub sort_method: Option, -} - -impl SortRawOption { - pub fn into(self) -> sort::SortOption { - let sort_method = match self.sort_method.as_ref() { - Some(s) => sort::SortType::parse(s).unwrap_or(sort::SortType::Natural), - None => sort::SortType::Natural, - }; - - let mut sort_methods = sort::SortTypes::default(); - sort_methods.reorganize(sort_method); - - sort::SortOption { - directories_first: self.directories_first, - case_sensitive: self.case_sensitive, - reverse: self.reverse, - sort_methods, - } - } -} - -impl std::default::Default for SortRawOption { - fn default() -> Self { - Self { - directories_first: default_true(), - case_sensitive: bool::default(), - reverse: bool::default(), - sort_method: None, - } - } -} diff --git a/src/config/theme/app_theme.rs b/src/config/theme/app_theme.rs index 1b7eab5..62a296a 100644 --- a/src/config/theme/app_theme.rs +++ b/src/config/theme/app_theme.rs @@ -4,10 +4,10 @@ use std::collections::HashMap; use tui::style::{Color, Modifier}; use super::{AppStyle, RawAppStyle}; -use crate::config::{parse_to_config_file, ConfigStructure, Flattenable}; +use crate::config::{parse_to_config_file, TomlConfigFile}; #[derive(Clone, Debug, Deserialize)] -pub struct RawAppTheme { +pub struct AppThemeCrude { #[serde(default)] pub regular: RawAppStyle, #[serde(default)] @@ -26,7 +26,7 @@ pub struct RawAppTheme { pub ext: HashMap, } -impl std::default::Default for RawAppTheme { +impl std::default::Default for AppThemeCrude { fn default() -> Self { Self { regular: RawAppStyle::default(), @@ -41,16 +41,16 @@ impl std::default::Default for RawAppTheme { } } -impl Flattenable for RawAppTheme { - fn flatten(self) -> AppTheme { - let selection = self.selection.to_style_theme(); - let executable = self.executable.to_style_theme(); - let regular = self.regular.to_style_theme(); - let directory = self.directory.to_style_theme(); - let link = self.link.to_style_theme(); - let link_invalid = self.link_invalid.to_style_theme(); - let socket = self.socket.to_style_theme(); - let ext: HashMap = self +impl From for AppTheme { + fn from(crude: AppThemeCrude) -> Self { + let selection = crude.selection.to_style_theme(); + let executable = crude.executable.to_style_theme(); + let regular = crude.regular.to_style_theme(); + let directory = crude.directory.to_style_theme(); + let link = crude.link.to_style_theme(); + let link_invalid = crude.link_invalid.to_style_theme(); + let socket = crude.socket.to_style_theme(); + let ext: HashMap = crude .ext .iter() .map(|(k, v)| { @@ -59,7 +59,7 @@ impl Flattenable for RawAppTheme { }) .collect(); - AppTheme { + Self { selection, executable, regular, @@ -84,9 +84,9 @@ pub struct AppTheme { pub ext: HashMap, } -impl ConfigStructure for AppTheme { +impl TomlConfigFile for AppTheme { fn get_config(file_name: &str) -> Self { - parse_to_config_file::(file_name).unwrap_or_else(Self::default) + parse_to_config_file::(file_name).unwrap_or_else(Self::default) } } diff --git a/src/fs/dirlist.rs b/src/fs/dirlist.rs index 698e1ac..b8b252a 100644 --- a/src/fs/dirlist.rs +++ b/src/fs/dirlist.rs @@ -1,17 +1,18 @@ use std::path; use std::slice::{Iter, IterMut}; +use crate::config::option::DisplayOption; use crate::fs::{JoshutoDirEntry, JoshutoMetadata}; use crate::history::read_directory; -use crate::util::display_option::DisplayOption; #[derive(Clone, Debug)] pub struct JoshutoDirList { - pub index: Option, path: path::PathBuf, - _need_update: bool, - pub metadata: JoshutoMetadata, pub contents: Vec, + pub metadata: JoshutoMetadata, + pub index: Option, + pub viewport_index: usize, + _need_update: bool, } impl JoshutoDirList { @@ -22,11 +23,12 @@ impl JoshutoDirList { metadata: JoshutoMetadata, ) -> Self { Self { - index, path, - _need_update: false, - metadata, contents, + metadata, + index, + viewport_index: 0, + _need_update: false, } } @@ -39,14 +41,20 @@ impl JoshutoDirList { let index = if contents.is_empty() { None } else { Some(0) }; + let viewport_index = match index { + None => 0, + Some(index) => 0, + }; + let metadata = JoshutoMetadata::from(&path)?; Ok(Self { - index, path, - _need_update: false, - metadata, contents, + metadata, + _need_update: false, + index, + viewport_index, }) } diff --git a/src/fs/entry.rs b/src/fs/entry.rs index fb62f2e..8d7b11d 100644 --- a/src/fs/entry.rs +++ b/src/fs/entry.rs @@ -1,10 +1,10 @@ use std::{fs, io, path}; +use crate::config::option::DisplayOption; use crate::fs::{FileType, JoshutoMetadata}; #[cfg(feature = "devicons")] use crate::util::devicons::*; -use crate::util::display_option::DisplayOption; #[derive(Clone, Debug)] pub struct JoshutoDirEntry { diff --git a/src/history.rs b/src/history.rs index 90f7c92..e754705 100644 --- a/src/history.rs +++ b/src/history.rs @@ -3,8 +3,8 @@ use std::fs; use std::io; use std::path::{Path, PathBuf}; +use crate::config::option::DisplayOption; use crate::fs::{JoshutoDirEntry, JoshutoDirList, JoshutoMetadata}; -use crate::util::display_option::DisplayOption; pub trait DirectoryHistory { fn populate_to_root(&mut self, path: &Path, options: &DisplayOption) -> io::Result<()>; diff --git a/src/key_command/command.rs b/src/key_command/command.rs index ed2e249..a9f9498 100644 --- a/src/key_command/command.rs +++ b/src/key_command/command.rs @@ -1,8 +1,8 @@ use std::path; +use crate::config::option::SortType; use crate::io::IoWorkerOptions; use crate::util::select::SelectOption; -use crate::util::sort_type::SortType; #[derive(Clone, Debug)] pub enum Command { diff --git a/src/key_command/impl_comment.rs b/src/key_command/impl_comment.rs index 90c7a4a..58b51c8 100644 --- a/src/key_command/impl_comment.rs +++ b/src/key_command/impl_comment.rs @@ -1,5 +1,5 @@ +use crate::config::option::SortType; use crate::io::IoWorkerOptions; -use crate::util::sort_type::SortType; use super::{Command, CommandComment}; diff --git a/src/key_command/impl_from_str.rs b/src/key_command/impl_from_str.rs index 592f3db..5770668 100644 --- a/src/key_command/impl_from_str.rs +++ b/src/key_command/impl_from_str.rs @@ -3,10 +3,10 @@ use std::path; use dirs_next::home_dir; use shellexpand::tilde_with_context; +use crate::config::option::SortType; use crate::error::{JoshutoError, JoshutoErrorKind}; use crate::io::IoWorkerOptions; use crate::util::select::SelectOption; -use crate::util::sort_type::SortType; use crate::HOME_DIR; diff --git a/src/main.rs b/src/main.rs index 184d979..ddfc5af 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,7 @@ use std::process; use structopt::StructOpt; use crate::config::{ - AppConfig, AppKeyMapping, AppMimetypeRegistry, AppTheme, ConfigStructure, JoshutoPreview, + AppConfig, AppKeyMapping, AppMimetypeRegistry, AppTheme, JoshutoPreview, TomlConfigFile, }; use crate::context::{AppContext, QuitType}; use crate::error::JoshutoError; diff --git a/src/tab.rs b/src/tab.rs index c3f8595..4e2f2e4 100644 --- a/src/tab.rs +++ b/src/tab.rs @@ -1,8 +1,8 @@ use std::path; +use crate::config::option::DisplayOption; use crate::fs::JoshutoDirList; use crate::history::{DirectoryHistory, JoshutoHistory}; -use crate::util::display_option::DisplayOption; #[derive(Clone, Copy, Debug)] pub enum TabHomePage { diff --git a/src/ui/tui_backend.rs b/src/ui/tui_backend.rs index 336226f..dc15f03 100644 --- a/src/ui/tui_backend.rs +++ b/src/ui/tui_backend.rs @@ -10,7 +10,7 @@ use tui::widgets::{Block, Borders, Widget}; #[cfg(feature = "mouse")] use termion::input::MouseTerminal; -use crate::util::display_option::DisplayOption; +use crate::config::option::DisplayOption; trait New { fn new() -> std::io::Result diff --git a/src/util/display_option.rs b/src/util/display_option.rs deleted file mode 100644 index bc2d247..0000000 --- a/src/util/display_option.rs +++ /dev/null @@ -1,122 +0,0 @@ -use std::fs; - -use tui::layout::Constraint; - -use crate::util::sort_option::SortOption; - -pub const fn default_column_ratio() -> (usize, usize, usize) { - (1, 3, 4) -} - -#[derive(Clone, Debug)] -pub struct DisplayOption { - pub _automatically_count_files: bool, - pub _collapse_preview: bool, - pub column_ratio: (usize, usize, usize), - pub _show_borders: bool, - pub _show_hidden: bool, - pub _show_icons: bool, - pub _show_preview: bool, - pub _sort_options: SortOption, - pub _tilde_in_titlebar: bool, - pub default_layout: [Constraint; 3], - pub no_preview_layout: [Constraint; 3], -} - -impl DisplayOption { - pub fn automatically_count_files(&self) -> bool { - self._automatically_count_files - } - - pub fn collapse_preview(&self) -> bool { - self._collapse_preview - } - - pub fn show_borders(&self) -> bool { - self._show_borders - } - - pub fn show_hidden(&self) -> bool { - self._show_hidden - } - - pub fn show_icons(&self) -> bool { - self._show_icons - } - - #[allow(dead_code)] - pub fn show_preview(&self) -> bool { - self._show_preview - } - - pub fn set_show_hidden(&mut self, show_hidden: bool) { - self._show_hidden = show_hidden; - } - - pub fn sort_options_ref(&self) -> &SortOption { - &self._sort_options - } - - pub fn sort_options_mut(&mut self) -> &mut SortOption { - &mut self._sort_options - } - - pub fn tilde_in_titlebar(&self) -> bool { - self._tilde_in_titlebar - } - - pub fn filter_func(&self) -> fn(&Result) -> bool { - if self.show_hidden() { - no_filter - } else { - filter_hidden - } - } -} - -impl std::default::Default for DisplayOption { - fn default() -> Self { - let column_ratio = default_column_ratio(); - - let total = (column_ratio.0 + column_ratio.1 + column_ratio.2) as u32; - let default_layout = [ - Constraint::Ratio(column_ratio.0 as u32, total), - Constraint::Ratio(column_ratio.1 as u32, total), - Constraint::Ratio(column_ratio.2 as u32, total), - ]; - let no_preview_layout = [ - Constraint::Ratio(column_ratio.0 as u32, total), - Constraint::Ratio(column_ratio.1 as u32 + column_ratio.2 as u32, total), - Constraint::Ratio(0, total), - ]; - - Self { - _automatically_count_files: false, - _collapse_preview: true, - column_ratio, - _show_borders: true, - _show_hidden: false, - _show_icons: false, - _show_preview: true, - _sort_options: SortOption::default(), - _tilde_in_titlebar: true, - default_layout, - no_preview_layout, - } - } -} - -const fn no_filter(_: &Result) -> bool { - true -} - -fn filter_hidden(result: &Result) -> bool { - match result { - Err(_) => true, - Ok(entry) => { - let file_name = entry.file_name(); - let lossy_string = file_name.as_os_str().to_string_lossy(); - !lossy_string.starts_with('.') - } - } -} diff --git a/src/util/mod.rs b/src/util/mod.rs index ae3a590..2bf95d2 100644 --- a/src/util/mod.rs +++ b/src/util/mod.rs @@ -1,15 +1,12 @@ #[cfg(feature = "devicons")] pub mod devicons; -pub mod display_option; pub mod format; pub mod input; pub mod keyparse; pub mod name_resolution; pub mod search; pub mod select; -pub mod sort_option; -pub mod sort_type; pub mod string; pub mod style; pub mod to_string; diff --git a/src/util/sort_option.rs b/src/util/sort_option.rs deleted file mode 100644 index df38702..0000000 --- a/src/util/sort_option.rs +++ /dev/null @@ -1,53 +0,0 @@ -use std::cmp; - -use crate::fs::JoshutoDirEntry; -use crate::util::sort_type::{SortType, SortTypes}; - -#[derive(Clone, Debug)] -pub struct SortOption { - pub directories_first: bool, - pub case_sensitive: bool, - pub reverse: bool, - pub sort_methods: SortTypes, -} - -impl SortOption { - pub fn set_sort_method(&mut self, method: SortType) { - self.sort_methods.reorganize(method); - } - - pub fn compare(&self, f1: &JoshutoDirEntry, f2: &JoshutoDirEntry) -> cmp::Ordering { - if self.directories_first { - let f1_isdir = f1.file_path().is_dir(); - let f2_isdir = f2.file_path().is_dir(); - - if f1_isdir && !f2_isdir { - return cmp::Ordering::Less; - } else if !f1_isdir && f2_isdir { - return cmp::Ordering::Greater; - } - } - - // let mut res = self.sort_method.cmp(f1, f2, &self); - let mut res = self.sort_methods.cmp(f1, f2, &self); - if self.reverse { - res = match res { - cmp::Ordering::Less => cmp::Ordering::Greater, - cmp::Ordering::Greater => cmp::Ordering::Less, - s => s, - }; - }; - res - } -} - -impl std::default::Default for SortOption { - fn default() -> Self { - SortOption { - directories_first: true, - case_sensitive: false, - reverse: false, - sort_methods: SortTypes::default(), - } - } -} diff --git a/src/util/sort_type.rs b/src/util/sort_type.rs deleted file mode 100644 index 6e4180e..0000000 --- a/src/util/sort_type.rs +++ /dev/null @@ -1,160 +0,0 @@ -use std::cmp; -use std::collections::VecDeque; -use std::fs; -use std::time; - -use serde_derive::Deserialize; - -use crate::fs::JoshutoDirEntry; -use crate::util::sort_option::SortOption; - -#[derive(Clone, Copy, Debug, Deserialize, PartialEq)] -pub enum SortType { - Lexical, - Mtime, - Natural, - Size, - Ext, -} - -impl SortType { - pub fn parse(s: &str) -> Option { - match s { -