mirror of
https://github.com/kdheepak/taskwarrior-tui.git
synced 2025-08-26 03:07:18 +02:00
Use anyhow
This commit is contained in:
parent
66a26b88d0
commit
bf0fb46f90
7 changed files with 36 additions and 22 deletions
7
Cargo.lock
generated
7
Cargo.lock
generated
|
@ -35,6 +35,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "anyhow"
|
||||||
|
version = "1.0.40"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atty"
|
name = "atty"
|
||||||
version = "0.2.14"
|
version = "0.2.14"
|
||||||
|
@ -794,6 +800,7 @@ dependencies = [
|
||||||
name = "taskwarrior-tui"
|
name = "taskwarrior-tui"
|
||||||
version = "0.12.2"
|
version = "0.12.2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
"better-panic",
|
"better-panic",
|
||||||
"cassowary",
|
"cassowary",
|
||||||
"chrono",
|
"chrono",
|
||||||
|
|
|
@ -36,6 +36,7 @@ rustyline = "7.1.0"
|
||||||
uuid = { version = "0.8.1", features = ["serde", "v4"] }
|
uuid = { version = "0.8.1", features = ["serde", "v4"] }
|
||||||
better-panic = "0.2.0"
|
better-panic = "0.2.0"
|
||||||
shellexpand = "2.1"
|
shellexpand = "2.1"
|
||||||
|
anyhow = "1"
|
||||||
|
|
||||||
[package.metadata.rpm]
|
[package.metadata.rpm]
|
||||||
package = "taskwarrior-tui"
|
package = "taskwarrior-tui"
|
||||||
|
|
23
src/app.rs
23
src/app.rs
|
@ -12,11 +12,9 @@ use crate::util::{Event, Events};
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::collections::{HashMap, HashSet};
|
use std::collections::{HashMap, HashSet};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::error::Error;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::result::Result;
|
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
use task_hookrs::date::Date;
|
use task_hookrs::date::Date;
|
||||||
|
@ -30,6 +28,8 @@ use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use chrono::{Datelike, Local, NaiveDate, NaiveDateTime, TimeZone};
|
use chrono::{Datelike, Local, NaiveDate, NaiveDateTime, TimeZone};
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use std::{sync::mpsc, thread, time::Duration};
|
use std::{sync::mpsc, thread, time::Duration};
|
||||||
use tui::{
|
use tui::{
|
||||||
|
@ -170,7 +170,7 @@ pub struct TaskwarriorTuiApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskwarriorTuiApp {
|
impl TaskwarriorTuiApp {
|
||||||
pub fn new() -> Result<Self, Box<dyn Error>> {
|
pub fn new() -> Result<Self> {
|
||||||
let c = Config::default()?;
|
let c = Config::default()?;
|
||||||
let mut kc = KeyConfig::default();
|
let mut kc = KeyConfig::default();
|
||||||
kc.update()?;
|
kc.update()?;
|
||||||
|
@ -210,7 +210,7 @@ impl TaskwarriorTuiApp {
|
||||||
Ok(app)
|
Ok(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_context(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn get_context(&mut self) -> Result<()> {
|
||||||
let output = Command::new("task").arg("_get").arg("rc.context").output()?;
|
let output = Command::new("task").arg("_get").arg("rc.context").output()?;
|
||||||
self.current_context = String::from_utf8_lossy(&output.stdout).to_string();
|
self.current_context = String::from_utf8_lossy(&output.stdout).to_string();
|
||||||
self.current_context = self.current_context.strip_suffix('\n').unwrap_or("").to_string();
|
self.current_context = self.current_context.strip_suffix('\n').unwrap_or("").to_string();
|
||||||
|
@ -825,7 +825,7 @@ impl TaskwarriorTuiApp {
|
||||||
(tasks, headers)
|
(tasks, headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self, force: bool) -> Result<(), Box<dyn Error>> {
|
pub fn update(&mut self, force: bool) -> Result<()> {
|
||||||
if force || self.tasks_changed_since(self.last_export)? {
|
if force || self.tasks_changed_since(self.last_export)? {
|
||||||
self.last_export = Some(std::time::SystemTime::now());
|
self.last_export = Some(std::time::SystemTime::now());
|
||||||
self.task_report_table.export_headers()?;
|
self.task_report_table.export_headers()?;
|
||||||
|
@ -980,7 +980,7 @@ impl TaskwarriorTuiApp {
|
||||||
self.current_selection = i;
|
self.current_selection = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export_contexts(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn export_contexts(&mut self) -> Result<()> {
|
||||||
let output = Command::new("task").arg("context").output()?;
|
let output = Command::new("task").arg("context").output()?;
|
||||||
let data = String::from_utf8_lossy(&output.stdout);
|
let data = String::from_utf8_lossy(&output.stdout);
|
||||||
|
|
||||||
|
@ -1014,7 +1014,7 @@ impl TaskwarriorTuiApp {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_task_files_max_mtime(&self) -> Result<SystemTime, Box<dyn Error>> {
|
fn get_task_files_max_mtime(&self) -> Result<SystemTime> {
|
||||||
let data_dir = shellexpand::tilde(&self.config.data_location).into_owned();
|
let data_dir = shellexpand::tilde(&self.config.data_location).into_owned();
|
||||||
let mut mtimes = Vec::new();
|
let mut mtimes = Vec::new();
|
||||||
for fname in &["backlog.data", "completed.data", "pending.data"] {
|
for fname in &["backlog.data", "completed.data", "pending.data"] {
|
||||||
|
@ -1025,7 +1025,7 @@ impl TaskwarriorTuiApp {
|
||||||
Ok(*mtimes.iter().max().unwrap())
|
Ok(*mtimes.iter().max().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tasks_changed_since(&mut self, prev: Option<SystemTime>) -> Result<bool, Box<dyn Error>> {
|
pub fn tasks_changed_since(&mut self, prev: Option<SystemTime>) -> Result<bool> {
|
||||||
if let Some(prev) = prev {
|
if let Some(prev) = prev {
|
||||||
match self.get_task_files_max_mtime() {
|
match self.get_task_files_max_mtime() {
|
||||||
Ok(mtime) => {
|
Ok(mtime) => {
|
||||||
|
@ -1047,7 +1047,7 @@ impl TaskwarriorTuiApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export_tasks(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn export_tasks(&mut self) -> Result<()> {
|
||||||
let mut task = Command::new("task");
|
let mut task = Command::new("task");
|
||||||
|
|
||||||
task.arg("rc.json.array=on");
|
task.arg("rc.json.array=on");
|
||||||
|
@ -1076,10 +1076,11 @@ impl TaskwarriorTuiApp {
|
||||||
let data = String::from_utf8_lossy(&output.stdout);
|
let data = String::from_utf8_lossy(&output.stdout);
|
||||||
let error = String::from_utf8_lossy(&output.stderr);
|
let error = String::from_utf8_lossy(&output.stderr);
|
||||||
if !error.contains("The expression could not be evaluated.") {
|
if !error.contains("The expression could not be evaluated.") {
|
||||||
let imported = import(data.as_bytes())?;
|
if let Ok(imported) = import(data.as_bytes()) {
|
||||||
*(self.tasks.lock().unwrap()) = imported;
|
*(self.tasks.lock().unwrap()) = imported;
|
||||||
self.tasks.lock().unwrap().sort_by(cmp);
|
self.tasks.lock().unwrap().sort_by(cmp);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -1653,7 +1654,7 @@ impl TaskwarriorTuiApp {
|
||||||
input: Key,
|
input: Key,
|
||||||
terminal: &mut Terminal<CrosstermBackend<io::Stdout>>,
|
terminal: &mut Terminal<CrosstermBackend<io::Stdout>>,
|
||||||
events: &Events,
|
events: &Events,
|
||||||
) -> Result<(), Box<dyn Error>> {
|
) -> Result<()> {
|
||||||
match self.mode {
|
match self.mode {
|
||||||
AppMode::TaskReport => {
|
AppMode::TaskReport => {
|
||||||
if input == Key::Esc {
|
if input == Key::Esc {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use anyhow::Result;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
|
@ -58,7 +59,7 @@ pub struct Config {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Config {
|
impl Config {
|
||||||
pub fn default() -> Result<Self, Box<dyn Error>> {
|
pub fn default() -> Result<Self> {
|
||||||
let bool_collection = Self::get_bool_collection();
|
let bool_collection = Self::get_bool_collection();
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
|
@ -105,7 +106,7 @@ impl Config {
|
||||||
Some(Self::get_tcolor(&s))
|
Some(Self::get_tcolor(&s))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_color_collection() -> Result<HashMap<String, Style>, Box<dyn Error>> {
|
fn get_color_collection() -> Result<HashMap<String, Style>> {
|
||||||
let mut color_collection = HashMap::new();
|
let mut color_collection = HashMap::new();
|
||||||
let output = Command::new("task").arg("rc.color=off").arg("show").output()?;
|
let output = Command::new("task").arg("rc.color=off").arg("show").output()?;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
use crate::util::Key;
|
use crate::util::Key;
|
||||||
|
use anyhow::anyhow;
|
||||||
|
use anyhow::Result;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
@ -89,7 +91,7 @@ impl Default for KeyConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl KeyConfig {
|
impl KeyConfig {
|
||||||
pub fn update(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn update(&mut self) -> Result<()> {
|
||||||
self.quit = self
|
self.quit = self
|
||||||
.get_config("uda.taskwarrior-tui.keyconfig.quit")
|
.get_config("uda.taskwarrior-tui.keyconfig.quit")
|
||||||
.unwrap_or(self.quit);
|
.unwrap_or(self.quit);
|
||||||
|
@ -162,7 +164,7 @@ impl KeyConfig {
|
||||||
self.check()
|
self.check()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check(&self) -> Result<(), Box<dyn Error>> {
|
pub fn check(&self) -> Result<()> {
|
||||||
let mut elements = vec![
|
let mut elements = vec![
|
||||||
&self.quit,
|
&self.quit,
|
||||||
&self.refresh,
|
&self.refresh,
|
||||||
|
@ -196,7 +198,7 @@ impl KeyConfig {
|
||||||
if l == elements.len() {
|
if l == elements.len() {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
Err("Duplicate keys found in key config".into())
|
Err(anyhow!("Duplicate keys found in key config"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,7 @@ mod task_report;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
use crate::util::{destruct_terminal, setup_terminal, Event, EventConfig, Events};
|
use crate::util::{destruct_terminal, setup_terminal, Event, EventConfig, Events};
|
||||||
|
use anyhow::Result;
|
||||||
use clap::{App, Arg};
|
use clap::{App, Arg};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
@ -26,7 +27,7 @@ use app::{AppMode, TaskwarriorTuiApp};
|
||||||
const APP_VERSION: &str = env!("CARGO_PKG_VERSION");
|
const APP_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
const APP_NAME: &str = env!("CARGO_PKG_NAME");
|
const APP_NAME: &str = env!("CARGO_PKG_NAME");
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<()> {
|
||||||
better_panic::install();
|
better_panic::install();
|
||||||
let matches = App::new(APP_NAME)
|
let matches = App::new(APP_NAME)
|
||||||
.version(APP_VERSION)
|
.version(APP_VERSION)
|
||||||
|
@ -62,7 +63,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tui_main(_config: &str) -> Result<(), Box<dyn Error>> {
|
fn tui_main(_config: &str) -> Result<()> {
|
||||||
// Terminal initialization
|
// Terminal initialization
|
||||||
let mut terminal = setup_terminal();
|
let mut terminal = setup_terminal();
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use anyhow::Result;
|
||||||
use chrono::{Datelike, Local, NaiveDate, NaiveDateTime, TimeZone};
|
use chrono::{Datelike, Local, NaiveDate, NaiveDateTime, TimeZone};
|
||||||
use itertools::join;
|
use itertools::join;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
@ -42,7 +43,7 @@ pub struct TaskReportTable {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TaskReportTable {
|
impl TaskReportTable {
|
||||||
pub fn new() -> Result<Self, Box<dyn Error>> {
|
pub fn new() -> Result<Self> {
|
||||||
let virtual_tags = vec![
|
let virtual_tags = vec![
|
||||||
"PROJECT",
|
"PROJECT",
|
||||||
"BLOCKED",
|
"BLOCKED",
|
||||||
|
@ -89,7 +90,7 @@ impl TaskReportTable {
|
||||||
Ok(task_report_table)
|
Ok(task_report_table)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn export_headers(&mut self) -> Result<(), Box<dyn Error>> {
|
pub fn export_headers(&mut self) -> Result<()> {
|
||||||
self.columns = vec![];
|
self.columns = vec![];
|
||||||
self.labels = vec![];
|
self.labels = vec![];
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue