diff --git a/src/lib/config.rs b/src/lib/config.rs index 993bc81..bc9af07 100644 --- a/src/lib/config.rs +++ b/src/lib/config.rs @@ -7,7 +7,6 @@ use clap::{Parser, ValueEnum}; use serde::{Deserialize, Serialize}; use serde_json::Value; use thiserror::Error; -use which::which; #[derive(Debug)] pub enum ConfigurationError { @@ -138,64 +137,61 @@ impl FromStr for WrapMode { #[derive(Debug, Deserialize, Serialize, Clone, Parser)] #[clap(about = "Worf is a wofi clone written in rust, it aims to be a drop-in replacement")] +#[derive(Default)] pub struct Config { /// Forks the menu so you can close the terminal #[clap(short = 'f', long = "fork")] - pub fork: Option, + fork: Option, // todo support fork /// Selects a config file to use #[clap(short = 'c', long = "conf")] - pub config: Option, + config: Option, /// Prints the version and then exits #[clap(short = 'v', long = "version")] - pub version: Option, + version: Option, // todo support or drop /// Defines the style sheet to be loaded. /// Defaults to `$XDG_CONF_DIR/worf/style.css` /// or `$HOME/.config/worf/style.css` if `$XDG_CONF_DIR` is not set. - #[serde(default = "default_style")] #[clap(long = "style")] - pub style: Option, + style: Option, /// Defines the mode worf is running in #[clap(long = "show")] - pub show: Option, + show: Option, /// Default width of the window, defaults to 50% of the screen - #[serde(default = "default_width")] #[clap(long = "width")] - pub width: Option, + width: Option, /// Default height of the window, defaults to 40% of the screen - #[serde(default = "default_height")] #[clap(long = "height")] - pub height: Option, + height: Option, /// Defines which prompt is used. Default is selected 'show' #[clap(short = 'p', long = "prompt")] - pub prompt: Option, + prompt: Option, #[clap(short = 'x', long = "xoffset")] - pub xoffset: Option, + xoffset: Option, #[clap(short = 'y', long = "yoffset")] - pub yoffset: Option, + yoffset: Option, /// If true a normal window instead of a layer shell will be used - #[serde(default = "default_normal_window")] #[clap(short = 'n', long = "normal-window")] - pub normal_window: bool, + normal_window: bool, /// Set to 'false' to disable images, defaults to true #[clap(short = 'I', long = "allow-images")] - pub allow_images: Option, + allow_images: Option, #[clap(short = 'm', long = "allow-markup")] - pub allow_markup: Option, + allow_markup: Option, #[clap(short = 'k', long = "cache-file")] - pub cache_file: Option, + cache_file: Option, /// Defines which terminal to use. defaults to the first one found: /// * kitty @@ -209,442 +205,355 @@ pub struct Config { /// /// Must be configured including the needed arguments to launch something /// i.e. 'kitty -c' - #[serde(default = "default_terminal")] #[clap(short = 't', long = "term")] - pub term: Option, + term: Option, - #[serde(default = "default_password_char")] #[clap(short = 'P', long = "password")] - pub password: Option, + password: Option, #[clap(short = 'e', long = "exec-search")] - pub exec_search: Option, + exec_search: Option, /// Defines whether the scrollbar is visible #[clap(short = 'b', long = "hide-scroll")] - pub hide_scroll: Option, + hide_scroll: Option, /// Defines the matching method, defaults to contains - #[serde(default = "default_match_method")] #[clap(short = 'M', long = "matching")] - pub matching: Option, + matching: Option, #[clap(short = 'i', long = "insensitive")] - pub insensitive: Option, + insensitive: Option, #[clap(short = 'q', long = "parse-search")] - pub parse_search: Option, + parse_search: Option, /// set where the window is displayed. /// can be used to anchor a window to an edge by /// setting top,left for example - #[clap(short = 'l', long = "location", value_delimiter = ',', value_parser = clap::builder::ValueParser::new(Anchor::from_str))] - pub location: Option>, + #[clap(short = 'l', long = "location", value_delimiter = ',', value_parser = clap::builder::ValueParser::new(Anchor::from_str) + )] + location: Option>, #[clap(short = 'a', long = "no-actions")] - pub no_actions: Option, + no_actions: Option, #[clap(short = 'L', long = "lines")] - pub lines: Option, + lines: Option, - #[serde(default = "default_columns")] #[clap(short = 'w', long = "columns")] - pub columns: Option, + columns: Option, #[clap(short = 'O', long = "sort-order")] - pub sort_order: Option, + sort_order: Option, #[clap(short = 'G', long = "gtk-dark")] - pub gtk_dark: Option, + gtk_dark: Option, #[clap(short = 'Q', long = "search")] - pub search: Option, + search: Option, #[clap(short = 'o', long = "monitor")] - pub monitor: Option, + monitor: Option, #[clap(short = 'r', long = "pre-display-cmd")] - pub pre_display_cmd: Option, + pre_display_cmd: Option, - #[serde(default = "default_orientation")] #[clap(long = "orientation")] - pub orientation: Option, + orientation: Option, /// Horizontal alignment - #[serde(default = "default_halign")] #[clap(long = "halign")] - pub halign: Option, + halign: Option, /// Alignment of content - #[serde(default = "default_content_halign")] #[clap(long = "content-halign")] - pub content_halign: Option, + content_halign: Option, /// Vertical alignment #[clap(long = "valign")] - pub valign: Option, + valign: Option, - pub filter_rate: Option, + filter_rate: Option, /// Defines the image size in pixels - #[serde(default = "default_image_size")] #[clap(long = "image-size")] - pub image_size: Option, + image_size: Option, - pub key_up: Option, - pub key_down: Option, - pub key_left: Option, - pub key_right: Option, - pub key_forward: Option, - pub key_backward: Option, - pub key_submit: Option, - pub key_exit: Option, - pub key_pgup: Option, - pub key_pgdn: Option, - pub key_expand: Option, - pub key_hide_search: Option, - pub key_copy: Option, + key_up: Option, + key_down: Option, + key_left: Option, + key_right: Option, + key_forward: Option, + key_backward: Option, + key_submit: Option, + key_exit: Option, + key_pgup: Option, + key_pgdn: Option, + key_expand: Option, + key_hide_search: Option, + key_copy: Option, // todo re-add this // #[serde(flatten)] - // pub key_custom: Option>, - pub global_coords: Option, - pub hide_search: Option, - pub dynamic_lines: Option, - pub layer: Option, - pub copy_exec: Option, - pub single_click: Option, - pub pre_display_exec: Option, + // key_custom: Option>, + global_coords: Option, + hide_search: Option, + dynamic_lines: Option, + layer: Option, + copy_exec: Option, + single_click: Option, + pre_display_exec: Option, /// Minimum score for a fuzzy search to be shown - #[serde(default = "default_fuzzy_min_score")] #[clap(long = "fuzzy-min-score")] - pub fuzzy_min_score: Option, + fuzzy_min_score: Option, /// Orientation of items in the row box where items are displayed - #[serde(default = "default_row_box_orientation")] #[clap(long = "row-box-orientation")] - pub row_bow_orientation: Option, + row_bow_orientation: Option, - // /// Set to to true to wrap text after a given amount of chars - // #[serde(default = "default_text_wrap")] - // #[clap(long = "text-wrap")] - // pub text_wrap: Option, - // - // /// Defines after how many chars a line is broken over. - // /// Only cuts at spaces. - // #[serde(default = "default_text_wrap_length")] - // #[clap(long = "text-wrap-length")] - // pub text_wrap_length: Option, /// Defines how long it takes for the show animation to finish /// Defaults to 70ms - #[serde(default = "default_show_animation_time")] #[clap(long = "show-animation-time")] - pub show_animation_time: Option, + show_animation_time: Option, /// Defines how long it takes for the hide animation to finish /// Defaults to 100ms - #[serde(default = "default_hide_animation_time")] #[clap(long = "hide-animation-time")] - pub hide_animation_time: Option, + hide_animation_time: Option, - #[serde(default = "default_line_wrap")] #[clap(long = "line-wrap")] - pub line_wrap: Option, + line_wrap: Option, } -impl Default for Config { - fn default() -> Self { - Config { - fork: None, - config: None, - version: None, - style: default_style(), - show: None, - width: default_width(), - height: default_height(), - prompt: None, - xoffset: None, - yoffset: None, - normal_window: default_normal_window(), - allow_images: None, - allow_markup: None, - cache_file: None, - term: None, - password: None, - exec_search: None, - hide_scroll: None, - matching: None, - insensitive: None, - parse_search: None, - location: None, - no_actions: None, - lines: None, - columns: default_columns(), - sort_order: None, - gtk_dark: None, - search: None, - monitor: None, - pre_display_cmd: None, - orientation: default_row_box_orientation(), - halign: default_halign(), - content_halign: default_content_halign(), - valign: None, - filter_rate: None, - image_size: default_image_size(), - key_up: None, - key_down: None, - key_left: None, - key_right: None, - key_forward: None, - key_backward: None, - key_submit: None, - key_exit: None, - key_pgup: None, - key_pgdn: None, - key_expand: None, - key_hide_search: None, - key_copy: None, - //key_custom: None, - line_wrap: default_line_wrap(), - global_coords: None, - hide_search: None, - dynamic_lines: None, - layer: None, - copy_exec: None, - single_click: None, - pre_display_exec: None, - fuzzy_min_score: default_fuzzy_min_score(), - row_bow_orientation: default_row_box_orientation(), - show_animation_time: default_show_animation_time(), - hide_animation_time: default_hide_animation_time(), +impl Config { + #[must_use] + pub fn image_size(&self) -> i32 { + self.image_size.unwrap_or(32) + } + + #[must_use] + pub fn match_method(&self) -> MatchMethod { + self.matching.unwrap_or(MatchMethod::Contains) + } + + #[must_use] + pub fn fuzzy_min_score(&self) -> f64 { + self.fuzzy_min_score.unwrap_or(0.0) + } + + #[must_use] + pub fn style(&self) -> Option { + style_path(None) + .ok() + .map(|pb| pb.display().to_string()) + .or_else(|| { + log::error!("no stylesheet found, using system styles"); + None + }) + } + + #[must_use] + pub fn normal_window(&self) -> bool { + self.normal_window + } + + #[must_use] + pub fn location(&self) -> Option<&Vec> { + self.location.as_ref() + } + + #[must_use] + pub fn hide_scroll(&self) -> bool { + self.hide_scroll.unwrap_or(false) + } + + #[must_use] + pub fn columns(&self) -> u32 { + self.columns.unwrap_or(1) + } + + #[must_use] + pub fn halign(&self) -> Align { + self.halign.unwrap_or(Align::Fill) + } + + #[must_use] + pub fn content_halign(&self) -> Align { + self.content_halign.unwrap_or(Align::Fill) + } + + #[must_use] + pub fn valign(&self) -> Align { + self.valign.unwrap_or(Align::Center) + } + #[must_use] + pub fn orientation(&self) -> Orientation { + self.orientation.unwrap_or(Orientation::Vertical) + } + + #[must_use] + pub fn prompt(&self) -> String { + match &self.prompt { + None => match &self.show { + None => String::new(), + Some(mode) => match mode { + Mode::Run => "run".to_owned(), + Mode::Drun => "drun".to_owned(), + Mode::Dmenu => "dmenu".to_owned(), + Mode::Math => "math".to_owned(), + Mode::File => "file".to_owned(), + Mode::Auto => "auto".to_owned(), + Mode::Ssh => "ssh".to_owned(), + }, + }, + + Some(prompt) => prompt.clone(), } } -} -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_show_animation_time() -> Option { - Some(10) -} + #[must_use] + pub fn height(&self) -> String { + self.height.clone().unwrap_or("40%".to_owned()) + } -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_hide_animation_time() -> Option { - Some(0) -} + #[must_use] + pub fn width(&self) -> String { + self.width.clone().unwrap_or("50%".to_owned()) + } -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_row_box_orientation() -> Option { - Some(Orientation::Horizontal) -} + #[must_use] + pub fn show_animation_time(&self) -> u64 { + self.show_animation_time.unwrap_or(10) + } -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_orientation() -> Option { - Some(Orientation::Vertical) -} + #[must_use] + pub fn hide_animation_time(&self) -> u64 { + self.hide_animation_time.unwrap_or(10) + } + #[must_use] + pub fn row_bow_orientation(&self) -> Orientation { + self.row_bow_orientation.unwrap_or(Orientation::Horizontal) + } -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_halign() -> Option { - Some(Align::Fill) -} + #[must_use] + pub fn allow_images(&self) -> bool { + self.allow_images.unwrap_or(true) + } -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_content_halign() -> Option { - Some(Align::Fill) -} + #[must_use] + pub fn line_wrap(&self) -> WrapMode { + self.line_wrap.clone().unwrap_or(WrapMode::None) + } -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_columns() -> Option { - Some(1) -} + #[must_use] + pub fn term(&self) -> Option { + self.term.clone().or_else(|| { + let terminals = [ + ("gnome-terminal", vec!["--"]), + ("konsole", vec!["-e"]), + ("xfce4-terminal", vec!["--command"]), + ("xterm", vec!["-e"]), + ("alacritty", vec!["-e"]), + ("lxterminal", vec!["-e"]), + ("kitty", vec!["-e"]), + ("tilix", vec!["-e"]), + ]; -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_normal_window() -> bool { - false -} + for (term, launch) in &terminals { + if which::which(term).is_ok() { + return Some(format!("{} {}", term, launch.join(" "))); + } + } -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_line_wrap() -> Option { - Some(WrapMode::Word) -} - -// TODO -// GtkOrientation orientation = config_get_mnemonic(config, "orientation", "vertical", 2, "vertical", "horizontal"); -// outer_orientation = config_get_mnemonic(cstoonfig, "orientation", "vertical", 2, "horizontal", "vertical"); -// GtkAlign halign = config_get_mnemonic(config, "halign", "fill", 4, "fill", "start", "end", "center"); -// content_halign = config_get_mnemonic(config, "content_halign", "fill", 4, "fill", "start", "end", "center"); -// char* default_valign = "start"; -// if(outer_orientation == GTK_ORIENTATION_HORIZONTAL) { -// default_valign = "center"; -// } -// GtkAlign valign = config_get_mnemonic(config, "valign", default_valign, 4, "fill", "start", "end", "center"); -// char* prompt = config_get(config, "prompt", mode); -// uint64_t filter_rate = strtol(config_get(config, "filter_rate", "100"), NULL, 10); -// allow_images = strcmp(config_get(config, "allow_images", "false"), "true") == 0; -// allow_markup = strcmp(config_get(config, "allow_markup", "false"), "true") == 0; -// image_size = strtol(config_get(config, "image_size", "32"), NULL, 10); -// cache_file = map_get(config, "cache_file"); -// config_dir = map_get(config, "config_dir"); -// terminal = map_get(config, "term"); -// exec_search = strcmp(config_get(config, "exec_search", "false"), "true") == 0; -// bool hide_scroll = strcmp(config_get(config, "hide_scroll", "false"), "true") == 0; -// matching = config_get_mnemonic(config, "matching", "contains", 3, "contains", "multi-contains", "fuzzy"); -// insensitive = strcmp(config_get(config, "insensitive", "false"), "true") == 0; -// parse_search = strcmp(config_get(config, "parse_search", "false"), "true") == 0; -// location = config_get_mnemonic(config, "location", "center", 18, -// "center", "top_left", "top", "top_right", "right", "bottom_right", "bottom", "bottom_left", "left", -// "0", "1", "2", "3", "4", "5", "6", "7", "8"); -// no_actions = strcmp(config_get(config, "no_actions", "false"), "true") == 0; -// lines = strtol(config_get(config, "lines", "0"), NULL, 10); -// max_lines = lines; -// columns = strtol(config_get(config, "columns", "1"), NULL, 10); -// sort_order = config_get_mnemonic(config, "sort_order", "default", 2, "default", "alphabetical"); -// bool global_coords = strcmp(config_get(config, "global_coords", "false"), "true") == 0; -// hide_search = strcmp(config_get(config, "hide_search", "false"), "true") == 0; -// char* search = map_get(config, "search"); -// dynamic_lines = strcmp(config_get(config, "dynamic_lines", "false"), "true") == 0; -// char* monitor = map_get(config, "monitor"); -// char* layer = config_get(config, "layer", "top"); -// copy_exec = config_get(config, "copy_exec", "wl-copy"); -// pre_display_cmd = map_get(config, "pre_display_cmd"); -// pre_display_exec = strcmp(config_get(config, "pre_display_exec", "false"), "true") == 0; -// single_click = strcmp(config_get(config, "single_click", "false"), "true") == 0; -// -// keys = map_init_void(); -// mods = map_init_void(); -// -// map_put_void(mods, "Shift", &shift_mask); -// map_put_void(mods, "Ctrl", &ctrl_mask); -// map_put_void(mods, "Alt", &alt_mask); -// -// key_default = "Up"; -// char* key_up = (i == 0) ? "Up" : config_get(config, "key_up", key_default); -// key_default = "Down"; -// char* key_down = (i == 0) ? key_default : config_get(config, "key_down", key_default); -// key_default = "Left"; -// char* key_left = (i == 0) ? key_default : config_get(config, "key_left", key_default); -// key_default = "Right"; -// char* key_right = (i == 0) ? key_default : config_get(config, "key_right", key_default); -// key_default = "Tab"; -// char* key_forward = (i == 0) ? key_default : config_get(config, "key_forward", key_default); -// key_default = "Shift-ISO_Left_Tab"; -// char* key_backward = (i == 0) ? key_default : config_get(config, "key_backward", key_default); -// key_default = "Return"; -// char* key_submit = (i == 0) ? key_default : config_get(config, "key_submit", key_default); -// key_default = "Escape"; -// char* key_exit = (i == 0) ? key_default : config_get(config, "key_exit", key_default); -// key_default = "Page_Up"; -// char* key_pgup = (i == 0) ? key_default : config_get(config, "key_pgup", key_default); -// key_default = "Page_Down"; -// char* key_pgdn = (i == 0) ? key_default : config_get(config, "key_pgdn", key_default); -// key_default = ""; -// char* key_expand = (i == 0) ? key_default: config_get(config, "key_expand", key_default); -// key_default = ""; -// char* key_hide_search = (i == 0) ? key_default: config_get(config, "key_hide_search", key_default); -// key_default = "Ctrl-c"; -// char* key_copy = (i == 0) ? key_default : config_get(config, "key_copy", key_default); - -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_style() -> Option { - style_path(None) - .ok() - .map(|pb| pb.display().to_string()) - .or_else(|| { - log::error!("no stylesheet found, using system styles"); None }) -} - -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_height() -> Option { - Some("40%".to_owned()) -} - -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_width() -> Option { - Some("50%".to_owned()) -} - -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_terminal() -> Option { - let terminals = [ - ("gnome-terminal", vec!["--"]), - ("konsole", vec!["-e"]), - ("xfce4-terminal", vec!["--command"]), - ("xterm", vec!["-e"]), - ("alacritty", vec!["-e"]), - ("lxterminal", vec!["-e"]), - ("kitty", vec!["-e"]), - ("tilix", vec!["-e"]), - ]; - - for (term, launch) in &terminals { - if which(term).is_ok() { - return Some(format!("{term} {}", launch.join(" "))); - } } - None + + #[must_use] + pub fn show(&self) -> Option { + self.show.clone() + } } -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_password_char() -> Option { - Some("*".to_owned()) -} - -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_fuzzy_min_length() -> Option { - Some(10) -} - -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_fuzzy_min_score() -> Option { - Some(0.0) -} - -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_match_method() -> Option { - Some(MatchMethod::Contains) -} - -// allowed because option is needed for serde macro -#[allow(clippy::unnecessary_wraps)] -#[must_use] -pub fn default_image_size() -> Option { - Some(32) -} +// +// // TODO +// // GtkOrientation orientation = config_get_mnemonic(config, "orientation", "vertical", 2, "vertical", "horizontal"); +// // outer_orientation = config_get_mnemonic(cstoonfig, "orientation", "vertical", 2, "horizontal", "vertical"); +// // GtkAlign halign = config_get_mnemonic(config, "halign", "fill", 4, "fill", "start", "end", "center"); +// // content_halign = config_get_mnemonic(config, "content_halign", "fill", 4, "fill", "start", "end", "center"); +// // char* default_valign = "start"; +// // if(outer_orientation == GTK_ORIENTATION_HORIZONTAL) { +// // default_valign = "center"; +// // } +// // GtkAlign valign = config_get_mnemonic(config, "valign", default_valign, 4, "fill", "start", "end", "center"); +// // char* prompt = config_get(config, "prompt", mode); +// // uint64_t filter_rate = strtol(config_get(config, "filter_rate", "100"), NULL, 10); +// // allow_images = strcmp(config_get(config, "allow_images", "false"), "true") == 0; +// // allow_markup = strcmp(config_get(config, "allow_markup", "false"), "true") == 0; +// // image_size = strtol(config_get(config, "image_size", "32"), NULL, 10); +// // cache_file = map_get(config, "cache_file"); +// // config_dir = map_get(config, "config_dir"); +// // terminal = map_get(config, "term"); +// // exec_search = strcmp(config_get(config, "exec_search", "false"), "true") == 0; +// // bool hide_scroll = strcmp(config_get(config, "hide_scroll", "false"), "true") == 0; +// // matching = config_get_mnemonic(config, "matching", "contains", 3, "contains", "multi-contains", "fuzzy"); +// // insensitive = strcmp(config_get(config, "insensitive", "false"), "true") == 0; +// // parse_search = strcmp(config_get(config, "parse_search", "false"), "true") == 0; +// // location = config_get_mnemonic(config, "location", "center", 18, +// // "center", "top_left", "top", "top_right", "right", "bottom_right", "bottom", "bottom_left", "left", +// // "0", "1", "2", "3", "4", "5", "6", "7", "8"); +// // no_actions = strcmp(config_get(config, "no_actions", "false"), "true") == 0; +// // lines = strtol(config_get(config, "lines", "0"), NULL, 10); +// // max_lines = lines; +// // columns = strtol(config_get(config, "columns", "1"), NULL, 10); +// // sort_order = config_get_mnemonic(config, "sort_order", "default", 2, "default", "alphabetical"); +// // bool global_coords = strcmp(config_get(config, "global_coords", "false"), "true") == 0; +// // hide_search = strcmp(config_get(config, "hide_search", "false"), "true") == 0; +// // char* search = map_get(config, "search"); +// // dynamic_lines = strcmp(config_get(config, "dynamic_lines", "false"), "true") == 0; +// // char* monitor = map_get(config, "monitor"); +// // char* layer = config_get(config, "layer", "top"); +// // copy_exec = config_get(config, "copy_exec", "wl-copy"); +// // pre_display_cmd = map_get(config, "pre_display_cmd"); +// // pre_display_exec = strcmp(config_get(config, "pre_display_exec", "false"), "true") == 0; +// // single_click = strcmp(config_get(config, "single_click", "false"), "true") == 0; +// // +// // keys = map_init_void(); +// // mods = map_init_void(); +// // +// // map_put_void(mods, "Shift", &shift_mask); +// // map_put_void(mods, "Ctrl", &ctrl_mask); +// // map_put_void(mods, "Alt", &alt_mask); +// // +// // key_default = "Up"; +// // char* key_up = (i == 0) ? "Up" : config_get(config, "key_up", key_default); +// // key_default = "Down"; +// // char* key_down = (i == 0) ? key_default : config_get(config, "key_down", key_default); +// // key_default = "Left"; +// // char* key_left = (i == 0) ? key_default : config_get(config, "key_left", key_default); +// // key_default = "Right"; +// // char* key_right = (i == 0) ? key_default : config_get(config, "key_right", key_default); +// // key_default = "Tab"; +// // char* key_forward = (i == 0) ? key_default : config_get(config, "key_forward", key_default); +// // key_default = "Shift-ISO_Left_Tab"; +// // char* key_backward = (i == 0) ? key_default : config_get(config, "key_backward", key_default); +// // key_default = "Return"; +// // char* key_submit = (i == 0) ? key_default : config_get(config, "key_submit", key_default); +// // key_default = "Escape"; +// // char* key_exit = (i == 0) ? key_default : config_get(config, "key_exit", key_default); +// // key_default = "Page_Up"; +// // char* key_pgup = (i == 0) ? key_default : config_get(config, "key_pgup", key_default); +// // key_default = "Page_Down"; +// // char* key_pgdn = (i == 0) ? key_default : config_get(config, "key_pgdn", key_default); +// // key_default = ""; +// // char* key_expand = (i == 0) ? key_default: config_get(config, "key_expand", key_default); +// // key_default = ""; +// // char* key_hide_search = (i == 0) ? key_default: config_get(config, "key_hide_search", key_default); +// // key_default = "Ctrl-c"; +// // char* key_copy = (i == 0) ? key_default : config_get(config, "key_copy", key_default); +// } #[must_use] pub fn parse_args() -> Config { @@ -654,7 +563,7 @@ pub fn parse_args() -> Config { /// # Errors /// /// Will return Err when it cannot resolve any path or no style is found -pub fn style_path(full_path: Option) -> Result { +fn style_path(full_path: Option) -> Result { let alternative_paths = path_alternatives( vec![dirs::config_dir()], &PathBuf::from("worf").join("style.css"), @@ -720,24 +629,8 @@ pub fn load_config(args_opt: Option) -> Result {} - Some(mode) => match mode { - Mode::Run => merge_result.prompt = Some("run".to_owned()), - Mode::Drun => merge_result.prompt = Some("drun".to_owned()), - Mode::Dmenu => merge_result.prompt = Some("dmenu".to_owned()), - Mode::Math => merge_result.prompt = Some("math".to_owned()), - Mode::File => merge_result.prompt = Some("file".to_owned()), - Mode::Auto => merge_result.prompt = Some("auto".to_owned()), - Mode::Ssh => merge_result.prompt = Some("ssh".to_owned()), - }, - } - } - Ok(merge_result) } else { Ok(config) diff --git a/src/lib/gui.rs b/src/lib/gui.rs index 7fd3fda..7722d18 100644 --- a/src/lib/gui.rs +++ b/src/lib/gui.rs @@ -58,8 +58,8 @@ impl From for Orientation { } } -impl From<&WrapMode> for NaturalWrapMode { - fn from(value: &WrapMode) -> Self { +impl From for NaturalWrapMode { + fn from(value: WrapMode) -> Self { match value { WrapMode::None => NaturalWrapMode::None, WrapMode::Word => NaturalWrapMode::Word, @@ -164,7 +164,7 @@ where P: ItemProvider + 'static + Clone + Send, { log::debug!("Starting GUI"); - if let Some(ref css) = config.style { + if let Some(ref css) = config.style() { let provider = CssProvider::new(); let css_file_path = File::for_path(css); provider.load_from_file(&css_file_path); @@ -246,7 +246,7 @@ fn build_ui( ui_elements.window.set_widget_name("window"); - if !config.normal_window { + if !config.normal_window() { // Initialize the window as a layer ui_elements.window.init_layer_shell(); ui_elements @@ -260,13 +260,13 @@ fn build_ui( let window_done = Instant::now(); - if let Some(location) = config.location.as_ref() { + if let Some(location) = config.location() { for anchor in location { ui_elements.window.set_anchor(anchor.into(), true); } } - let outer_box = gtk4::Box::new(config.orientation.unwrap().into(), 0); + let outer_box = gtk4::Box::new(config.orientation().into(), 0); outer_box.set_widget_name("outer-box"); outer_box.append(&ui_elements.search); ui_elements.window.set_child(Some(&outer_box)); @@ -276,7 +276,7 @@ fn build_ui( scroll.set_hexpand(true); scroll.set_vexpand(true); - if config.hide_scroll.is_some_and(|hs| hs) { + if config.hide_scroll() { scroll.set_policy(PolicyType::External, PolicyType::External); } outer_box.append(&scroll); @@ -321,16 +321,12 @@ fn build_main_box(config: &Config, ui_elements: &Rc(config: &Config, ui_elements: &UiElements) { ui_elements.search.set_css_classes(&["input"]); ui_elements .search - .set_placeholder_text(config.prompt.as_deref()); + .set_placeholder_text(Some(config.prompt().as_ref())); ui_elements.search.set_can_focus(false); } @@ -533,13 +529,11 @@ fn animate_window_show(config: &Config, window: ApplicationWindow) { let monitor = display.monitor_at_surface(&surface); if let Some(monitor) = monitor { let geometry = monitor.geometry(); - let Some(target_width) = percent_or_absolute(config.width.as_ref(), geometry.width()) - else { + let Some(target_width) = percent_or_absolute(&config.width(), geometry.width()) else { return; }; - let Some(target_height) = - percent_or_absolute(config.height.as_ref(), geometry.height()) + let Some(target_height) = percent_or_absolute(&config.height(), geometry.height()) else { return; }; @@ -551,7 +545,7 @@ fn animate_window_show(config: &Config, window: ApplicationWindow) { let animation_start = Instant::now(); animate_window( window, - config.show_animation_time.unwrap_or(0), + config.show_animation_time(), target_height, target_width, move || { @@ -568,13 +562,7 @@ where // todo the target size might not work for higher dpi displays or bigger resolutions window.set_child(Widget::NONE); - animate_window( - window, - config.hide_animation_time.unwrap_or(0), - 10, - 10, - on_done_func, - ); + animate_window(window, config.hide_animation_time(), 10, 10, on_done_func); } fn ease_in_out_cubic(t: f32) -> f32 { @@ -782,23 +770,13 @@ fn create_menu_row( }); row.add_controller(click); - let row_box = gtk4::Box::new( - meta.config - .row_bow_orientation - .unwrap_or(config::Orientation::Horizontal) - .into(), - 0, - ); + let row_box = gtk4::Box::new(meta.config.row_bow_orientation().into(), 0); row_box.set_hexpand(true); row_box.set_vexpand(false); row_box.set_halign(Align::Fill); row.set_child(Some(&row_box)); - if meta - .config - .allow_images - .is_some_and(|allow_images| allow_images) - { + if meta.config.allow_images() { if let Some(image) = lookup_icon(element_to_add, &meta.config) { image.set_widget_name("img"); row_box.append(&image); @@ -806,26 +784,15 @@ fn create_menu_row( } let label = Label::new(Some(element_to_add.label.as_str())); - let wrap_mode: NaturalWrapMode = if let Some(config_wrap) = &meta.config.line_wrap { - config_wrap.into() - } else { - NaturalWrapMode::Word - }; - label.set_natural_wrap_mode(wrap_mode); + label.set_natural_wrap_mode(meta.config.line_wrap().into()); label.set_hexpand(true); label.set_widget_name("label"); label.set_wrap(true); row_box.append(&label); - if meta - .config - .content_halign - .is_some_and(|c| c == config::Align::Start) - || meta - .config - .content_halign - .is_some_and(|c| c == config::Align::Fill) + if meta.config.content_halign().eq(&config::Align::Start) + || meta.config.content_halign().eq(&config::Align::Fill) { label.set_xalign(0.0); } @@ -851,11 +818,7 @@ fn lookup_icon(menu_item: &MenuItem, config: &Config) -> Option( &menu_item.label.to_lowercase() ); - let matching = if let Some(matching) = &config.matching { - matching - } else { - &config::default_match_method().unwrap() - }; - - let (search_sort_score, visible) = match matching { + let (search_sort_score, visible) = match config.match_method() { MatchMethod::Fuzzy => { let mut score = strsim::jaro_winkler(&query, &menu_item_search); if score == 0.0 { score = -1.0; } - ( - score, - score - > config - .fuzzy_min_score - .unwrap_or(config::default_fuzzy_min_score().unwrap_or(0.0)) - && score > 0.0, - ) + (score, score > config.fuzzy_min_score() && score > 0.0) } MatchMethod::Contains => { if menu_item_search.contains(&query) { @@ -948,19 +898,15 @@ fn select_first_visible_child(ui: &UiElements) { // allowed because truncating is fine, we do no need the precision #[allow(clippy::cast_possible_truncation)] #[allow(clippy::cast_precision_loss)] -fn percent_or_absolute(value: Option<&String>, base_value: i32) -> Option { - if let Some(value) = value { - if value.contains('%') { - let value = value.replace('%', "").trim().to_string(); - match value.parse::() { - Ok(n) => Some(((n as f32 / 100.0) * base_value as f32) as i32), - Err(_) => None, - } - } else { - value.parse::().ok() +fn percent_or_absolute(value: &str, base_value: i32) -> Option { + if value.contains('%') { + let value = value.replace('%', "").trim().to_string(); + match value.parse::() { + Ok(n) => Some(((n as f32 / 100.0) * base_value as f32) as i32), + Err(_) => None, } } else { - None + value.parse::().ok() } } diff --git a/src/lib/mode.rs b/src/lib/mode.rs index 6cd06e2..ce28700 100644 --- a/src/lib/mode.rs +++ b/src/lib/mode.rs @@ -533,17 +533,15 @@ pub fn auto(config: &Config) -> Result<(), Error> { let mut provider = AutoItemProvider::new(); let cache_path = provider.drun.cache_path.clone(); let mut cache = provider.drun.cache.clone(); - let mut cfg_clone = config.clone(); loop { // todo ues a arc instead of cloning the config - let selection_result = gui::show(cfg_clone.clone(), provider.clone(), true); + let selection_result = gui::show(config.clone(), provider.clone(), true); if let Ok(mut selection_result) = selection_result { if let Some(data) = &selection_result.data { match data { AutoRunType::Math => { - cfg_clone.prompt = Some(selection_result.label.clone()); provider.math.elements.push(selection_result); } AutoRunType::DRun => { @@ -603,8 +601,7 @@ fn ssh_launch(menu_item: &MenuItem, config: &Config) -> Result<(), action.clone() } else { let cmd = config - .term - .clone() + .term() .map(|s| format!("{s} ssh {}", menu_item.label)); if let Some(cmd) = cmd { cmd @@ -615,7 +612,7 @@ fn ssh_launch(menu_item: &MenuItem, config: &Config) -> Result<(), let cmd = format!( "{} bash -c \"source ~/.bashrc; {ssh_cmd}\"", - config.term.clone().unwrap_or_default() + config.term().unwrap_or_default() ); spawn_fork(&cmd, menu_item.working_dir.as_ref()) } @@ -639,14 +636,12 @@ pub fn ssh(config: &Config) -> Result<(), Error> { /// Shows the math mode pub fn math(config: &Config) { - let mut cfg_clone = config.clone(); let mut calc: Vec> = vec![]; loop { let mut provider = MathProvider::new(String::new()); provider.add_elements(&mut calc.clone()); - let selection_result = gui::show(cfg_clone.clone(), provider, true); + let selection_result = gui::show(config.clone(), provider, true); if let Ok(mi) = selection_result { - cfg_clone.prompt = Some(mi.label.clone()); calc.push(mi); } else { log::error!("No item selected"); diff --git a/src/main.rs b/src/main.rs index 0b91117..6d6d81b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -14,7 +14,7 @@ fn main() -> anyhow::Result<()> { let args = config::parse_args(); let config = config::load_config(Some(args)).map_err(|e| anyhow!(e))?; - if let Some(show) = &config.show { + if let Some(show) = &config.show() { match show { Mode::Run => { todo!("run not implemented")