From 1e44a7e1c5ce45777a09028222794878b615e363 Mon Sep 17 00:00:00 2001 From: Dheepak Krishnamurthy Date: Thu, 1 Apr 2021 17:59:35 -0600 Subject: [PATCH] Speed up start up --- Cargo.lock | 1 + Cargo.toml | 39 +++++---- src/app.rs | 51 +++++++++-- src/config.rs | 213 ++++++++++++++++++--------------------------- src/keyconfig.rs | 201 ++++++++++++++++++++++++------------------ src/task_report.rs | 15 ++-- 6 files changed, 280 insertions(+), 240 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 847c6b1..5410feb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1384,6 +1384,7 @@ dependencies = [ "futures", "futures-timer", "itertools", + "lazy_static", "rand", "regex", "rustyline", diff --git a/Cargo.toml b/Cargo.toml index 3a65753..842f589 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,29 +18,30 @@ default = ["crossterm-backend"] crossterm-backend = ["tui/crossterm", "crossterm"] [dependencies] -regex = "1" -itertools = "0.9" -serde = { version = "1", features = ["derive"] } -serde_json = "1" -clap = "2.33" -cassowary = "0.3.0" -task-hookrs = { git = "https://github.com/matthiasbeyer/task-hookrs" } -rand = "0.7" -shlex = "0.1" -chrono = "0.4" -unicode-width = "0.1" -unicode-segmentation = "1.6" -tui = { version = "0.12", optional = true, default-features = false } -crossterm = { version = "0.17", optional = true, default-features = false, features = ["event-stream"] } -rustyline = "8" -uuid = { version = "0.8.1", features = ["serde", "v4"] } -better-panic = "0.2.0" -shellexpand = "2.1" anyhow = "1" async-std = { version = "1", features = ["attributes", "unstable"] } +better-panic = "0.2.0" +cassowary = "0.3.0" +chrono = "0.4" +clap = "2.33" +crossterm = { version = "0.17", optional = true, default-features = false, features = ["event-stream"] } +dirs = "2.0.2" futures = "0.3" futures-timer = "3.0" -dirs = "2.0.2" +itertools = "0.9" +lazy_static = "1.4.0" +rand = "0.7" +regex = "1" +rustyline = "8" +serde = { version = "1", features = ["derive"] } +serde_json = "1" +shellexpand = "2.1" +shlex = "0.1" +task-hookrs = { git = "https://github.com/matthiasbeyer/task-hookrs" } +tui = { version = "0.12", optional = true, default-features = false } +unicode-segmentation = "1.6" +unicode-width = "0.1" +uuid = { version = "0.8.1", features = ["serde", "v4"] } [package.metadata.rpm] package = "taskwarrior-tui" diff --git a/src/app.rs b/src/app.rs index ff4bd69..4c7d7fa 100644 --- a/src/app.rs +++ b/src/app.rs @@ -32,14 +32,15 @@ use unicode_segmentation::UnicodeSegmentation; use chrono::{Datelike, Local, NaiveDate, NaiveDateTime, TimeZone, Timelike}; +use anyhow::Context as AnyhowContext; use anyhow::Result; use async_std::prelude::*; use async_std::stream::StreamExt; use async_std::task; use futures::future::join_all; -use futures::join; use futures::stream::FuturesOrdered; +use futures::{join, try_join}; use std::sync::{Arc, Mutex}; @@ -66,8 +67,16 @@ use tui::{backend::CrosstermBackend, Terminal}; use regex::Regex; +use lazy_static::lazy_static; + +use std::time::Instant; + const MAX_LINE: usize = 4096; +lazy_static! { + static ref START_TIME: Instant = Instant::now(); +} + pub fn cmp(t1: &Task, t2: &Task) -> Ordering { let urgency1 = match t1.urgency() { Some(f) => *f, @@ -189,10 +198,31 @@ pub struct TaskwarriorTuiApp { impl TaskwarriorTuiApp { pub fn new() -> Result { - let c = Config::default()?; - let mut kc = KeyConfig::default(); - kc.update()?; + let output = std::process::Command::new("task") + .arg("rc.color=off") + .arg("show") + .output() + .context("Unable to run `task show`.") + .unwrap(); + + if !output.status.success() { + let output = Command::new("task") + .arg("diagnostics") + .output() + .context("Unable to run `task diagnostics`.") + .unwrap(); + panic!( + "Unable to run `task show`.\n{}\n{}\nPlease check your configuration or open a issue on github.", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr), + ); + } + + let data = String::from_utf8_lossy(&output.stdout); + let (c, kc) = task::block_on(async { try_join!(Config::new(&data), KeyConfig::new(&data)) })?; + let (w, h) = crossterm::terminal::size()?; + let mut app = Self { should_quit: false, dirty: true, @@ -213,7 +243,7 @@ impl TaskwarriorTuiApp { task_details_scroll: 0, task_report_show_info: c.uda_task_report_show_info, config: c, - task_report_table: TaskReportTable::new()?, + task_report_table: TaskReportTable::new(&data)?, calendar_year: Local::today().year(), help_popup: Help::new(), contexts: vec![], @@ -224,6 +254,7 @@ impl TaskwarriorTuiApp { filter_history_context: HistoryContext::new("filter.history"), command_history_context: HistoryContext::new("command.history"), }; + for c in app.config.filter.chars() { app.filter.insert(c, 1); } @@ -874,7 +905,7 @@ impl TaskwarriorTuiApp { pub fn update(&mut self, force: bool) -> Result<()> { if force || self.dirty || self.tasks_changed_since(self.last_export)? { self.last_export = Some(std::time::SystemTime::now()); - self.task_report_table.export_headers()?; + self.task_report_table.export_headers(None)?; let _ = self.export_tasks(); self.export_contexts()?; self.update_tags(); @@ -2323,6 +2354,14 @@ mod tests { std::fs::remove_dir_all(cd).unwrap(); } + #[test] + fn test_taskwarrior_timing() { + let app = TaskwarriorTuiApp::new(); + if app.is_err() { + return; + } + } + #[test] fn test_taskwarrior_tui() { let app = TaskwarriorTuiApp::new(); diff --git a/src/config.rs b/src/config.rs index 8850ba4..0c77cae 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,9 +1,9 @@ use anyhow::{Context, Result}; +use async_std::process::Command; use async_std::task; use futures::join; use std::collections::HashMap; use std::error::Error; -use std::process::Command; use std::str; use tui::style::{Color, Modifier, Style}; @@ -64,34 +64,34 @@ pub struct Config { } impl Config { - pub fn default() -> Result { + pub async fn new(data: &str) -> Result { let bool_collection = Self::get_bool_collection(); let enabled = true; let obfuscate = bool_collection.get("obfuscate").cloned().unwrap_or(false); let print_empty_columns = bool_collection.get("print_empty_columns").cloned().unwrap_or(false); - let color = Self::get_color_collection(); - let filter = Self::get_filter(); - let data_location = Self::get_data_location(); - let due = Self::get_due(); - let rule_precedence_color = Self::get_rule_precedence_color(); - let uda_tick_rate = Self::get_uda_tick_rate(); - let uda_prefill_task_metadata = Self::get_uda_prefill_task_metadata(); - let uda_task_detail_prefetch = Self::get_uda_task_detail_prefetch(); - let uda_task_report_show_info = Self::get_uda_task_report_show_info(); - let uda_task_report_looping = Self::get_uda_task_report_looping(); - let uda_selection_indicator = Self::get_uda_selection_indicator(); - let uda_mark_indicator = Self::get_uda_mark_indicator(); - let uda_unmark_indicator = Self::get_uda_unmark_indicator(); - let uda_selection_bold = Self::get_uda_selection_bold(); - let uda_selection_italic = Self::get_uda_selection_italic(); - let uda_selection_dim = Self::get_uda_selection_dim(); - let uda_selection_blink = Self::get_uda_selection_blink(); - let uda_calendar_months_per_row = Self::get_uda_months_per_row(); - let uda_style_calendar_title = Self::get_uda_style("calendar.title"); - let uda_style_context_active = Self::get_uda_style("context.active"); - let uda_shortcuts = Self::get_uda_shortcuts(); + let color = Self::get_color_collection(data); + let filter = Self::get_filter(data); + let data_location = Self::get_data_location(data); + let due = Self::get_due(data); + let rule_precedence_color = Self::get_rule_precedence_color(data); + let uda_tick_rate = Self::get_uda_tick_rate(data); + let uda_prefill_task_metadata = Self::get_uda_prefill_task_metadata(data); + let uda_task_detail_prefetch = Self::get_uda_task_detail_prefetch(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_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_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_calendar_months_per_row = Self::get_uda_months_per_row(data); + let uda_style_calendar_title = Self::get_uda_style("calendar.title", data); + let uda_style_context_active = Self::get_uda_style("context.active", data); + let uda_shortcuts = Self::get_uda_shortcuts(data); let ( color, @@ -115,31 +115,29 @@ impl Config { uda_style_calendar_title, uda_style_context_active, uda_shortcuts, - ) = task::block_on(async { - join!( - color, - filter, - data_location, - due, - rule_precedence_color, - uda_tick_rate, - uda_prefill_task_metadata, - uda_task_detail_prefetch, - uda_task_report_show_info, - uda_task_report_looping, - uda_selection_indicator, - uda_mark_indicator, - uda_unmark_indicator, - uda_selection_bold, - uda_selection_italic, - uda_selection_dim, - uda_selection_blink, - uda_calendar_months_per_row, - uda_style_calendar_title, - uda_style_context_active, - uda_shortcuts, - ) - }); + ) = join!( + color, + filter, + data_location, + due, + rule_precedence_color, + uda_tick_rate, + uda_prefill_task_metadata, + uda_task_detail_prefetch, + uda_task_report_show_info, + uda_task_report_looping, + uda_selection_indicator, + uda_mark_indicator, + uda_unmark_indicator, + uda_selection_bold, + uda_selection_italic, + uda_selection_dim, + uda_selection_blink, + uda_calendar_months_per_row, + uda_style_calendar_title, + uda_style_context_active, + uda_shortcuts, + ); let color = color?; let uda_style_calendar_title = uda_style_calendar_title.unwrap_or_default(); @@ -177,31 +175,24 @@ impl Config { HashMap::new() } - async fn get_uda_shortcuts() -> Vec { + async 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).await.unwrap_or_default(); + let s = Self::get_config(&c, data).await.unwrap_or_default(); v.push(s); } v } - async fn get_uda_style(config: &str) -> Option