use anyhow::{Context, Result}; use std::collections::HashMap; use std::error::Error; use std::str; use tui::{ style::{Color, Modifier, Style}, symbols::bar::FULL, symbols::line::DOUBLE_VERTICAL, }; trait TaskWarriorBool { fn get_bool(&self) -> Option; } impl TaskWarriorBool for String { fn get_bool(&self) -> Option { if self == "true" || self == "1" || self == "y" || self == "yes" || self == "on" { Some(true) } else if self == "false" || self == "0" || self == "n" || self == "no" || self == "off" { Some(false) } else { None } } } impl TaskWarriorBool for str { fn get_bool(&self) -> Option { if self == "true" || self == "1" || self == "y" || self == "yes" || self == "on" { Some(true) } else if self == "false" || self == "0" || self == "n" || self == "no" || self == "off" { Some(false) } else { None } } } #[derive(Debug)] pub struct Uda { label: String, kind: String, values: Option>, default: Option, urgency: Option, } #[derive(Debug)] pub struct Config { pub enabled: bool, pub color: HashMap, pub filter: String, pub data_location: String, pub obfuscate: bool, pub print_empty_columns: bool, pub due: usize, pub weekstart: bool, pub rule_precedence_color: Vec, pub uda_priority_values: Vec, pub uda_tick_rate: u64, pub uda_auto_insert_double_quotes_on_add: bool, pub uda_auto_insert_double_quotes_on_annotate: bool, pub uda_auto_insert_double_quotes_on_log: bool, pub uda_prefill_task_metadata: bool, pub uda_reset_filter_on_esc: bool, pub uda_task_detail_prefetch: usize, pub uda_task_report_use_all_tasks_for_completion: bool, pub uda_task_report_show_info: bool, pub uda_task_report_looping: bool, pub uda_task_report_jump_to_task_on_add: bool, pub uda_selection_indicator: String, pub uda_mark_indicator: String, pub uda_unmark_indicator: String, pub uda_scrollbar_indicator: String, pub uda_scrollbar_area: String, pub uda_style_report_scrollbar: Style, pub uda_style_report_scrollbar_area: Style, pub uda_selection_bold: bool, pub uda_selection_italic: bool, pub uda_selection_dim: bool, pub uda_selection_blink: bool, pub uda_selection_reverse: bool, pub uda_calendar_months_per_row: usize, pub uda_style_context_active: Style, pub uda_style_report_selection: Style, pub uda_style_calendar_title: Style, pub uda_style_calendar_today: Style, pub uda_style_navbar: Style, pub uda_style_command: Style, pub uda_style_report_completion_pane: Style, pub uda_style_report_completion_pane_highlight: Style, pub uda_shortcuts: Vec, pub uda_change_focus_rotate: bool, pub uda_background_process: String, pub uda_background_process_period: usize, pub uda_quick_tag_name: String, pub uda_task_report_prompt_on_delete: bool, pub uda_task_report_prompt_on_done: bool, pub uda_task_report_date_time_vague_more_precise: bool, pub uda_context_menu_select_on_move: bool, pub uda: Vec, } impl Config { pub fn new(data: &str, report: &str) -> Result { let bool_collection = Self::get_bool_collection(); let enabled = true; let obfuscate = bool_collection.get("obfuscate").copied().unwrap_or(false); let print_empty_columns = bool_collection.get("print_empty_columns").copied().unwrap_or(false); let color = Self::get_color_collection(data); let filter = Self::get_filter(data, report)?; let filter = if filter.trim_start().trim_end().is_empty() { filter } else { format!("{} ", filter) }; let data_location = Self::get_data_location(data); let due = Self::get_due(data); let weekstart = Self::get_weekstart(data); let rule_precedence_color = Self::get_rule_precedence_color(data); let uda_priority_values = Self::get_uda_priority_values(data); let uda_tick_rate = Self::get_uda_tick_rate(data); let uda_change_focus_rotate = Self::get_uda_change_focus_rotate(data); let uda_auto_insert_double_quotes_on_add = Self::get_uda_auto_insert_double_quotes_on_add(data); let uda_auto_insert_double_quotes_on_annotate = Self::get_uda_auto_insert_double_quotes_on_annotate(data); let uda_auto_insert_double_quotes_on_log = Self::get_uda_auto_insert_double_quotes_on_log(data); let uda_prefill_task_metadata = Self::get_uda_prefill_task_metadata(data); let uda_reset_filter_on_esc = Self::get_uda_reset_filter_on_esc(data); let uda_task_detail_prefetch = Self::get_uda_task_detail_prefetch(data); let uda_task_report_use_all_tasks_for_completion = Self::get_uda_task_report_use_all_tasks_for_completion(data); let uda_task_report_show_info = Self::get_uda_task_report_show_info(data); let uda_task_report_looping = Self::get_uda_task_report_looping(data); let uda_task_report_jump_to_task_on_add = Self::get_uda_task_report_jump_to_task_on_add(data); let uda_selection_indicator = Self::get_uda_selection_indicator(data); let uda_mark_indicator = Self::get_uda_mark_indicator(data); let uda_unmark_indicator = Self::get_uda_unmark_indicator(data); let uda_scrollbar_indicator = Self::get_uda_scrollbar_indicator(data); let uda_scrollbar_area = Self::get_uda_scrollbar_area(data); let uda_selection_bold = Self::get_uda_selection_bold(data); let uda_selection_italic = Self::get_uda_selection_italic(data); let uda_selection_dim = Self::get_uda_selection_dim(data); let uda_selection_blink = Self::get_uda_selection_blink(data); let uda_selection_reverse = Self::get_uda_selection_reverse(data); let uda_calendar_months_per_row = Self::get_uda_months_per_row(data); let uda_style_report_selection = Self::get_uda_style("report.selection", data); let uda_style_report_scrollbar = Self::get_uda_style("report.scrollbar", data); let uda_style_report_scrollbar_area = Self::get_uda_style("report.scrollbar.area", data); let uda_style_calendar_title = Self::get_uda_style("calendar.title", data); let uda_style_calendar_today = Self::get_uda_style("calendar.today", data); let uda_style_navbar = Self::get_uda_style("navbar", data); let uda_style_command = Self::get_uda_style("command", data); let uda_style_context_active = Self::get_uda_style("context.active", data); let uda_style_report_completion_pane = Self::get_uda_style("report.completion-pane", data); let uda_style_report_completion_pane_highlight = Self::get_uda_style("report.completion-pane-highlight", data); let uda_shortcuts = Self::get_uda_shortcuts(data); let uda_background_process = Self::get_uda_background_process(data); let uda_background_process_period = Self::get_uda_background_process_period(data); let uda_style_report_selection = uda_style_report_selection.unwrap_or_default(); let uda_style_report_scrollbar = uda_style_report_scrollbar.unwrap_or_else(|| Style::default().fg(Color::Black)); let uda_style_report_scrollbar_area = uda_style_report_scrollbar_area.unwrap_or_default(); let uda_style_calendar_title = uda_style_calendar_title.unwrap_or_default(); let uda_style_calendar_today = uda_style_calendar_today.unwrap_or_else(|| Style::default().add_modifier(Modifier::BOLD)); let uda_style_navbar = uda_style_navbar.unwrap_or_else(|| Style::default().add_modifier(Modifier::REVERSED)); let uda_style_command = uda_style_command.unwrap_or_else(|| Style::default().add_modifier(Modifier::REVERSED)); let uda_style_context_active = uda_style_context_active.unwrap_or_default(); let uda_style_report_completion_pane = uda_style_report_completion_pane.unwrap_or_else(|| Style::default().fg(Color::Black).bg(Color::Rgb(223, 223, 223))); let uda_style_report_completion_pane_highlight = uda_style_report_completion_pane_highlight.unwrap_or(uda_style_report_completion_pane); let uda_quick_tag_name = Self::get_uda_quick_tag_name(data); let uda_task_report_prompt_on_delete = Self::get_uda_task_report_prompt_on_delete(data); let uda_task_report_prompt_on_done = Self::get_uda_task_report_prompt_on_done(data); let uda_context_menu_select_on_move = Self::get_uda_context_menu_select_on_move(data); let uda_task_report_date_time_vague_more_precise = Self::get_uda_task_report_date_time_vague_more_precise(data); Ok(Self { enabled, color, filter, data_location, obfuscate, print_empty_columns, due, weekstart, rule_precedence_color, uda_priority_values, uda_tick_rate, uda_change_focus_rotate, uda_auto_insert_double_quotes_on_add, uda_auto_insert_double_quotes_on_annotate, uda_auto_insert_double_quotes_on_log, uda_prefill_task_metadata, uda_reset_filter_on_esc, uda_task_detail_prefetch, uda_task_report_use_all_tasks_for_completion, uda_task_report_show_info, uda_task_report_looping, uda_task_report_jump_to_task_on_add, uda_selection_indicator, uda_mark_indicator, uda_unmark_indicator, uda_scrollbar_indicator, uda_scrollbar_area, uda_selection_bold, uda_selection_italic, uda_selection_dim, uda_selection_blink, uda_selection_reverse, uda_calendar_months_per_row, uda_style_report_selection, uda_style_context_active, uda_style_calendar_title, uda_style_calendar_today, uda_style_navbar, uda_style_command, uda_style_report_completion_pane, uda_style_report_completion_pane_highlight, uda_style_report_scrollbar, uda_style_report_scrollbar_area, uda_shortcuts, uda_background_process, uda_background_process_period, uda_quick_tag_name, uda_task_report_prompt_on_delete, uda_task_report_prompt_on_done, uda_task_report_date_time_vague_more_precise, uda_context_menu_select_on_move, uda: vec![], }) } fn get_bool_collection() -> HashMap { HashMap::new() } fn get_uda_background_process(data: &str) -> String { Self::get_config("uda.taskwarrior-tui.background_process", data).unwrap_or_default() } fn get_uda_background_process_period(data: &str) -> usize { Self::get_config("uda.taskwarrior-tui.background_process_period", data) .unwrap_or_default() .parse::() .unwrap_or(60) } fn get_uda_shortcuts(data: &str) -> Vec { let mut v = vec![]; for s in 0..=9 { let c = format!("uda.taskwarrior-tui.shortcuts.{}", s); let s = Self::get_config(&c, data).unwrap_or_default(); v.push(s); } v } fn get_uda_style(config: &str, data: &str) -> Option