mirror of
https://github.com/kdheepak/taskwarrior-tui.git
synced 2025-08-25 08:47:18 +02:00
Clippy changes
This commit is contained in:
parent
6b8425d8d3
commit
4f54f148f5
3 changed files with 117 additions and 132 deletions
216
src/app.rs
216
src/app.rs
|
@ -1,18 +1,14 @@
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use shlex;
|
|
||||||
use std::cmp::Ordering;
|
use std::cmp::Ordering;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::error::Error;
|
use std::process::{Command};
|
||||||
use std::process::{Command, Stdio};
|
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
|
|
||||||
use task_hookrs::date::Date;
|
use task_hookrs::date::Date;
|
||||||
use task_hookrs::import::import;
|
use task_hookrs::import::import;
|
||||||
use task_hookrs::task::Task;
|
use task_hookrs::task::Task;
|
||||||
use task_hookrs::uda::UDAValue;
|
use task_hookrs::uda::UDAValue;
|
||||||
use unicode_width::UnicodeWidthStr;
|
|
||||||
|
|
||||||
use chrono::{DateTime, Duration, Local, NaiveDateTime, TimeZone};
|
use chrono::{Local, NaiveDateTime};
|
||||||
|
|
||||||
use tui::{
|
use tui::{
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
|
@ -20,8 +16,7 @@ use tui::{
|
||||||
style::{Color, Modifier, Style},
|
style::{Color, Modifier, Style},
|
||||||
terminal::Frame,
|
terminal::Frame,
|
||||||
text::{Span, Spans, Text},
|
text::{Span, Spans, Text},
|
||||||
widgets::{BarChart, Block, Borders, Clear, Paragraph, Row, Table, TableState, Wrap},
|
widgets::{Block, Borders, Clear, Paragraph, Row, Table, TableState},
|
||||||
Terminal,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn cmp(t1: &Task, t2: &Task) -> Ordering {
|
pub fn cmp(t1: &Task, t2: &Task) -> Ordering {
|
||||||
|
@ -129,7 +124,7 @@ impl TaskwarriorTUIApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn draw(&mut self, f: &mut Frame<impl Backend>) {
|
pub fn draw(&mut self, f: &mut Frame<impl Backend>) {
|
||||||
while self.tasks.len() != 0 && self.state.selected().unwrap_or_default() >= self.tasks.len()
|
while !self.tasks.is_empty() && self.state.selected().unwrap_or_default() >= self.tasks.len()
|
||||||
{
|
{
|
||||||
self.previous();
|
self.previous();
|
||||||
}
|
}
|
||||||
|
@ -182,10 +177,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" /"),
|
Span::from(" /"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"task {string} ",
|
"task {string} ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Filter task report"),
|
Span::from("- Filter task report"),
|
||||||
]),
|
]),
|
||||||
|
@ -193,10 +188,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" a"),
|
Span::from(" a"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"task add {string} ",
|
"task add {string} ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Add new task"),
|
Span::from("- Add new task"),
|
||||||
]),
|
]),
|
||||||
|
@ -204,10 +199,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" d"),
|
Span::from(" d"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"task done {selected} ",
|
"task done {selected} ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Mark task as done"),
|
Span::from("- Mark task as done"),
|
||||||
]),
|
]),
|
||||||
|
@ -215,10 +210,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" e"),
|
Span::from(" e"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"task edit {selected} ",
|
"task edit {selected} ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Open selected task in editor"),
|
Span::from("- Open selected task in editor"),
|
||||||
]),
|
]),
|
||||||
|
@ -226,10 +221,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" j"),
|
Span::from(" j"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"{selected+=1} ",
|
"{selected+=1} ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Move down in task report"),
|
Span::from("- Move down in task report"),
|
||||||
]),
|
]),
|
||||||
|
@ -237,10 +232,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" k"),
|
Span::from(" k"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"{selected-=1} ",
|
"{selected-=1} ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Move up in task report"),
|
Span::from("- Move up in task report"),
|
||||||
]),
|
]),
|
||||||
|
@ -248,10 +243,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" l"),
|
Span::from(" l"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"task log {string} ",
|
"task log {string} ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Log new task"),
|
Span::from("- Log new task"),
|
||||||
]),
|
]),
|
||||||
|
@ -259,10 +254,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" m"),
|
Span::from(" m"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"task modify {string} ",
|
"task modify {string} ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Modify selected task"),
|
Span::from("- Modify selected task"),
|
||||||
]),
|
]),
|
||||||
|
@ -270,10 +265,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" q"),
|
Span::from(" q"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"exit ",
|
"exit ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Quit"),
|
Span::from("- Quit"),
|
||||||
]),
|
]),
|
||||||
|
@ -281,10 +276,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" s"),
|
Span::from(" s"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"task start/stop {selected} ",
|
"task start/stop {selected} ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Toggle start and stop"),
|
Span::from("- Toggle start and stop"),
|
||||||
]),
|
]),
|
||||||
|
@ -292,10 +287,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" u"),
|
Span::from(" u"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"task undo ",
|
"task undo ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Undo"),
|
Span::from("- Undo"),
|
||||||
]),
|
]),
|
||||||
|
@ -303,10 +298,10 @@ impl TaskwarriorTUIApp {
|
||||||
Spans::from(vec![
|
Spans::from(vec![
|
||||||
Span::from(" ?"),
|
Span::from(" ?"),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from(Span::styled(
|
Span::styled(
|
||||||
"help ",
|
"help ",
|
||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
),
|
||||||
Span::from(" "),
|
Span::from(" "),
|
||||||
Span::from("- Show this help menu"),
|
Span::from("- Show this help menu"),
|
||||||
]),
|
]),
|
||||||
|
@ -327,20 +322,19 @@ impl TaskwarriorTUIApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_task_details(&mut self, f: &mut Frame<impl Backend>, rect: Rect) {
|
fn draw_task_details(&mut self, f: &mut Frame<impl Backend>, rect: Rect) {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
Block::default()
|
Block::default()
|
||||||
.borders(Borders::ALL)
|
.borders(Borders::ALL)
|
||||||
.title("Task not found"),
|
.title("Task not found"),
|
||||||
rect,
|
rect,
|
||||||
);
|
);
|
||||||
return ();
|
return;
|
||||||
}
|
}
|
||||||
let selected = self.state.selected().unwrap_or_default();
|
let selected = self.state.selected().unwrap_or_default();
|
||||||
let task_id = self.tasks[selected].id().unwrap_or_default();
|
let task_id = self.tasks[selected].id().unwrap_or_default();
|
||||||
let output = Command::new("task").arg(format!("{}", task_id)).output();
|
let output = Command::new("task").arg(format!("{}", task_id)).output();
|
||||||
match output {
|
if let Ok(output) = output {
|
||||||
Ok(output) => {
|
|
||||||
let data = String::from_utf8(output.stdout).unwrap();
|
let data = String::from_utf8(output.stdout).unwrap();
|
||||||
let p = Paragraph::new(Text::from(&data[..])).block(
|
let p = Paragraph::new(Text::from(&data[..])).block(
|
||||||
Block::default()
|
Block::default()
|
||||||
|
@ -349,23 +343,21 @@ impl TaskwarriorTUIApp {
|
||||||
);
|
);
|
||||||
f.render_widget(p, rect);
|
f.render_widget(p, rect);
|
||||||
}
|
}
|
||||||
Err(_) => (),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn draw_task_report(&mut self, f: &mut Frame<impl Backend>, rect: Rect) {
|
fn draw_task_report(&mut self, f: &mut Frame<impl Backend>, rect: Rect) {
|
||||||
let active_style = Style::default()
|
let _active_style = Style::default()
|
||||||
.fg(Color::Blue)
|
.fg(Color::Blue)
|
||||||
.add_modifier(Modifier::BOLD);
|
.add_modifier(Modifier::BOLD);
|
||||||
let normal_style = Style::default();
|
let normal_style = Style::default();
|
||||||
|
|
||||||
let (tasks, headers, widths) = self.task_report();
|
let (tasks, headers, widths) = self.task_report();
|
||||||
if tasks.len() == 0 {
|
if tasks.is_empty() {
|
||||||
f.render_widget(
|
f.render_widget(
|
||||||
Block::default().borders(Borders::ALL).title("Task next"),
|
Block::default().borders(Borders::ALL).title("Task next"),
|
||||||
rect,
|
rect,
|
||||||
);
|
);
|
||||||
return ();
|
return;
|
||||||
}
|
}
|
||||||
let header = headers.iter();
|
let header = headers.iter();
|
||||||
let rows = tasks
|
let rows = tasks
|
||||||
|
@ -387,7 +379,7 @@ impl TaskwarriorTUIApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_string_attribute(&self, attribute: &str, task: &Task) -> String {
|
pub fn get_string_attribute(&self, attribute: &str, task: &Task) -> String {
|
||||||
let s = match attribute {
|
match attribute {
|
||||||
"id" => task.id().unwrap_or_default().to_string(),
|
"id" => task.id().unwrap_or_default().to_string(),
|
||||||
// "entry" => task.entry().unwrap().to_string(),
|
// "entry" => task.entry().unwrap().to_string(),
|
||||||
"entry" => vague_format_date_time(task.entry()),
|
"entry" => vague_format_date_time(task.entry()),
|
||||||
|
@ -397,13 +389,12 @@ impl TaskwarriorTUIApp {
|
||||||
},
|
},
|
||||||
"description" => task.description().to_string(),
|
"description" => task.description().to_string(),
|
||||||
"urgency" => match &task.uda()["urgency"] {
|
"urgency" => match &task.uda()["urgency"] {
|
||||||
UDAValue::Str(s) => "0.0".to_string(),
|
UDAValue::Str(_) => "0.0".to_string(),
|
||||||
UDAValue::U64(u) => (*u as f64).to_string(),
|
UDAValue::U64(u) => (*u as f64).to_string(),
|
||||||
UDAValue::F64(f) => (*f).to_string(),
|
UDAValue::F64(f) => (*f).to_string(),
|
||||||
},
|
},
|
||||||
_ => "".to_string(),
|
_ => "".to_string(),
|
||||||
};
|
}
|
||||||
return s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_report(&mut self) -> (Vec<Vec<String>>, Vec<String>, Vec<i16>) {
|
pub fn task_report(&mut self) -> (Vec<Vec<String>>, Vec<String>, Vec<i16>) {
|
||||||
|
@ -412,8 +403,8 @@ impl TaskwarriorTUIApp {
|
||||||
for task in &self.tasks {
|
for task in &self.tasks {
|
||||||
let mut item = vec![];
|
let mut item = vec![];
|
||||||
for name in &self.task_report_columns {
|
for name in &self.task_report_columns {
|
||||||
let attribute = name.split(".").collect::<Vec<&str>>()[0];
|
let attributes: Vec<_> = name.split('.').collect();
|
||||||
let s = self.get_string_attribute(attribute, task);
|
let s = self.get_string_attribute(attributes[0], task);
|
||||||
item.push(s);
|
item.push(s);
|
||||||
}
|
}
|
||||||
alltasks.push(item)
|
alltasks.push(item)
|
||||||
|
@ -421,7 +412,7 @@ impl TaskwarriorTUIApp {
|
||||||
|
|
||||||
// find which columns are empty
|
// find which columns are empty
|
||||||
let null_columns_len;
|
let null_columns_len;
|
||||||
if alltasks.len() > 0 {
|
if !alltasks.is_empty() {
|
||||||
null_columns_len = alltasks[0].len();
|
null_columns_len = alltasks[0].len();
|
||||||
} else {
|
} else {
|
||||||
return (vec![], vec![], vec![]);
|
return (vec![], vec![], vec![]);
|
||||||
|
@ -460,14 +451,12 @@ impl TaskwarriorTUIApp {
|
||||||
let mut widths: Vec<i16> = vec![0; tasks[0].len()];
|
let mut widths: Vec<i16> = vec![0; tasks[0].len()];
|
||||||
for task in &tasks {
|
for task in &tasks {
|
||||||
for (i, attr) in task.iter().enumerate() {
|
for (i, attr) in task.iter().enumerate() {
|
||||||
widths[i] = (attr.len() as i16 * 100
|
widths[i] = attr.len() as i16 * 100
|
||||||
/ task.iter().map(|s| s.len() as i16).sum::<i16>())
|
/ task.iter().map(|s| s.len() as i16).sum::<i16>()
|
||||||
.try_into()
|
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (tasks, headers, widths);
|
(tasks, headers, widths)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update(&mut self) {
|
pub fn update(&mut self) {
|
||||||
|
@ -475,7 +464,7 @@ impl TaskwarriorTUIApp {
|
||||||
self.export_headers();
|
self.export_headers();
|
||||||
}
|
}
|
||||||
pub fn next(&mut self) {
|
pub fn next(&mut self) {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let i = match self.state.selected() {
|
let i = match self.state.selected() {
|
||||||
|
@ -491,7 +480,7 @@ impl TaskwarriorTUIApp {
|
||||||
self.state.select(Some(i));
|
self.state.select(Some(i));
|
||||||
}
|
}
|
||||||
pub fn previous(&mut self) {
|
pub fn previous(&mut self) {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let i = match self.state.selected() {
|
let i = match self.state.selected() {
|
||||||
|
@ -518,10 +507,10 @@ impl TaskwarriorTUIApp {
|
||||||
.expect("Unable to run `task show report.next.columns`. Check documentation for more information");
|
.expect("Unable to run `task show report.next.columns`. Check documentation for more information");
|
||||||
let data = String::from_utf8(output.stdout).unwrap();
|
let data = String::from_utf8(output.stdout).unwrap();
|
||||||
|
|
||||||
for line in data.split("\n") {
|
for line in data.split('\n') {
|
||||||
if line.starts_with("report.next.columns") {
|
if line.starts_with("report.next.columns") {
|
||||||
let column_names: &str = line.split(" ").collect::<Vec<&str>>()[1];
|
let column_names: &str = line.split(' ').collect::<Vec<&str>>()[1];
|
||||||
for column in column_names.split(",") {
|
for column in column_names.split(',') {
|
||||||
self.task_report_columns.push(column.to_string());
|
self.task_report_columns.push(column.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -534,10 +523,10 @@ impl TaskwarriorTUIApp {
|
||||||
.expect("Unable to run `task show report.next.labels`. Check documentation for more information");
|
.expect("Unable to run `task show report.next.labels`. Check documentation for more information");
|
||||||
let data = String::from_utf8(output.stdout).unwrap();
|
let data = String::from_utf8(output.stdout).unwrap();
|
||||||
|
|
||||||
for line in data.split("\n") {
|
for line in data.split('\n') {
|
||||||
if line.starts_with("report.next.labels") {
|
if line.starts_with("report.next.labels") {
|
||||||
let label_names: &str = line.split(" ").collect::<Vec<&str>>()[1];
|
let label_names: &str = line.split(' ').collect::<Vec<&str>>()[1];
|
||||||
for label in label_names.split(",") {
|
for label in label_names.split(',') {
|
||||||
self.task_report_labels.push(label.to_string());
|
self.task_report_labels.push(label.to_string());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -563,15 +552,12 @@ impl TaskwarriorTUIApp {
|
||||||
|
|
||||||
let output = task
|
let output = task
|
||||||
.output()
|
.output()
|
||||||
.expect("Unable to run `task export`. Check documentation for more information");
|
.expect("Unable to run `task export`. Check documentation for more information.");
|
||||||
let data = String::from_utf8(output.stdout).unwrap();
|
let data = String::from_utf8(output.stdout).unwrap();
|
||||||
let imported = import(data.as_bytes());
|
let imported = import(data.as_bytes());
|
||||||
match imported {
|
if let Ok(i) = imported {
|
||||||
Ok(i) => {
|
self.tasks = i;
|
||||||
self.tasks = i;
|
self.tasks.sort_by(cmp);
|
||||||
self.tasks.sort_by(cmp);
|
|
||||||
}
|
|
||||||
_ => (),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -580,7 +566,7 @@ impl TaskwarriorTUIApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_log(&mut self) -> Result<(), String> {
|
pub fn task_log(&mut self) -> Result<(), String> {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -594,20 +580,25 @@ impl TaskwarriorTUIApp {
|
||||||
command.arg(&s);
|
command.arg(&s);
|
||||||
}
|
}
|
||||||
let output = command
|
let output = command
|
||||||
.output()
|
.output();
|
||||||
.expect("Cannot run `task log`. Check documentation for more information");
|
match output {
|
||||||
|
Ok(_) => {
|
||||||
self.command = "".to_string();
|
self.command = "".to_string();
|
||||||
return Ok(());
|
Ok(())
|
||||||
|
},
|
||||||
|
Err(_) => Err(
|
||||||
|
"Cannot run `task log` for task `{}`. Check documentation for more information".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Err(format!("Unable to run `task log` with `{}`", &self.command));
|
Err(format!("Unable to run `task log` with `{}`", &self.command))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_modify(&mut self) -> Result<(), String> {
|
pub fn task_modify(&mut self) -> Result<(), String> {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let selected = self.state.selected().unwrap_or_default();
|
let selected = self.state.selected().unwrap_or_default();
|
||||||
|
@ -621,23 +612,28 @@ impl TaskwarriorTUIApp {
|
||||||
command.arg(&s);
|
command.arg(&s);
|
||||||
}
|
}
|
||||||
let output = command
|
let output = command
|
||||||
.output()
|
.output();
|
||||||
.expect("Cannot run `task modify`. Check documentation for more information");
|
match output {
|
||||||
|
Ok(_) => {
|
||||||
self.modify = "".to_string();
|
self.modify = "".to_string();
|
||||||
return Ok(());
|
Ok(())
|
||||||
|
},
|
||||||
|
Err(_) => Err(
|
||||||
|
format!("Cannot run `task modify` for task `{}`. Check documentation for more information", task_id),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Err(format!(
|
Err(format!(
|
||||||
"Unable to run `task modify` with `{}` on task {}",
|
"Unable to run `task modify` with `{}` on task {}",
|
||||||
&self.modify, &task_id
|
&self.modify, &task_id
|
||||||
));
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_add(&mut self) -> Result<(), String> {
|
pub fn task_add(&mut self) -> Result<(), String> {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,14 +646,19 @@ impl TaskwarriorTUIApp {
|
||||||
command.arg(&s);
|
command.arg(&s);
|
||||||
}
|
}
|
||||||
let output = command
|
let output = command
|
||||||
.output()
|
.output();
|
||||||
.expect("Cannot run `task add`. Check documentation for more information");
|
match output {
|
||||||
|
Ok(_) => {
|
||||||
self.command = "".to_string();
|
self.command = "".to_string();
|
||||||
return Ok(());
|
Ok(())
|
||||||
|
},
|
||||||
|
Err(_) => Err(
|
||||||
|
"Cannot run `task add`. Check documentation for more information".to_string(),
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
return Err(format!("Unable to run `task add` with `{}`", &self.command));
|
Err(format!("Unable to run `task add` with `{}`", &self.command))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -670,17 +671,17 @@ impl TaskwarriorTUIApp {
|
||||||
match output {
|
match output {
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
let data = String::from_utf8(output.stdout).unwrap();
|
let data = String::from_utf8(output.stdout).unwrap();
|
||||||
for line in data.split("\n") {
|
for line in data.split('\n') {
|
||||||
if line.starts_with("Virtual tags") {
|
if line.starts_with("Virtual tags") {
|
||||||
let line = line.to_string();
|
let line = line.to_string();
|
||||||
let line = line.replace("Virtual tags", "");
|
let line = line.replace("Virtual tags", "");
|
||||||
return Ok(line);
|
return Ok(line);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return Err(format!(
|
Err(format!(
|
||||||
"Cannot find any tags for `task {}`. Check documentation for more information",
|
"Cannot find any tags for `task {}`. Check documentation for more information",
|
||||||
task_id
|
task_id
|
||||||
));
|
))
|
||||||
}
|
}
|
||||||
Err(_) => Err(format!(
|
Err(_) => Err(format!(
|
||||||
"Cannot run `task {}`. Check documentation for more information",
|
"Cannot run `task {}`. Check documentation for more information",
|
||||||
|
@ -690,13 +691,13 @@ impl TaskwarriorTUIApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_start_or_stop(&mut self) -> Result<(), String> {
|
pub fn task_start_or_stop(&mut self) -> Result<(), String> {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let selected = self.state.selected().unwrap_or_default();
|
let selected = self.state.selected().unwrap_or_default();
|
||||||
let task_id = self.tasks[selected].id().unwrap_or_default();
|
let task_id = self.tasks[selected].id().unwrap_or_default();
|
||||||
let mut command = "start";
|
let mut command = "start";
|
||||||
for tag in self.task_virtual_tags()?.split(" ") {
|
for tag in self.task_virtual_tags()?.split(' ') {
|
||||||
if tag == "ACTIVE" {
|
if tag == "ACTIVE" {
|
||||||
command = "stop"
|
command = "stop"
|
||||||
}
|
}
|
||||||
|
@ -709,14 +710,15 @@ impl TaskwarriorTUIApp {
|
||||||
match output {
|
match output {
|
||||||
Ok(_) => Ok(()),
|
Ok(_) => Ok(()),
|
||||||
Err(_) => Err(format!(
|
Err(_) => Err(format!(
|
||||||
"Cannot run `task done` for task `{}`. Check documentation for more information",
|
"Cannot run `task {}` for task `{}`. Check documentation for more information",
|
||||||
task_id
|
command,
|
||||||
|
task_id,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_delete(&self) -> Result<(), String> {
|
pub fn task_delete(&self) -> Result<(), String> {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let selected = self.state.selected().unwrap_or_default();
|
let selected = self.state.selected().unwrap_or_default();
|
||||||
|
@ -737,7 +739,7 @@ impl TaskwarriorTUIApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_done(&mut self) -> Result<(), String> {
|
pub fn task_done(&mut self) -> Result<(), String> {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let selected = self.state.selected().unwrap_or_default();
|
let selected = self.state.selected().unwrap_or_default();
|
||||||
|
@ -756,7 +758,7 @@ impl TaskwarriorTUIApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_undo(&self) -> Result<(), String> {
|
pub fn task_undo(&self) -> Result<(), String> {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let output = Command::new("task")
|
let output = Command::new("task")
|
||||||
|
@ -773,7 +775,7 @@ impl TaskwarriorTUIApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_edit(&self) -> Result<(), String> {
|
pub fn task_edit(&self) -> Result<(), String> {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
let selected = self.state.selected().unwrap_or_default();
|
let selected = self.state.selected().unwrap_or_default();
|
||||||
|
@ -789,14 +791,14 @@ impl TaskwarriorTUIApp {
|
||||||
match output {
|
match output {
|
||||||
Ok(output) => {
|
Ok(output) => {
|
||||||
if !output.status.success() {
|
if !output.status.success() {
|
||||||
return Err(format!(
|
Err(format!(
|
||||||
"`task edit` for task `{}` failed. {}{}",
|
"`task edit` for task `{}` failed. {}{}",
|
||||||
task_id,
|
task_id,
|
||||||
String::from_utf8(output.stdout).unwrap(),
|
String::from_utf8(output.stdout).unwrap(),
|
||||||
String::from_utf8(output.stderr).unwrap()
|
String::from_utf8(output.stderr).unwrap()
|
||||||
));
|
))
|
||||||
} else {
|
} else {
|
||||||
return Ok(());
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(err) => Err(format!(
|
Err(err) => Err(format!(
|
||||||
|
@ -813,11 +815,11 @@ impl TaskwarriorTUIApp {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn task_current(&self) -> Option<Task> {
|
pub fn task_current(&self) -> Option<Task> {
|
||||||
if self.tasks.len() == 0 {
|
if self.tasks.is_empty() {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let selected = self.state.selected().unwrap_or_default();
|
let selected = self.state.selected().unwrap_or_default();
|
||||||
return Some(self.tasks[selected].clone());
|
Some(self.tasks[selected].clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
25
src/main.rs
25
src/main.rs
|
@ -1,33 +1,18 @@
|
||||||
#![allow(dead_code)]
|
|
||||||
#![allow(unused_imports)]
|
|
||||||
#![allow(unused_variables)]
|
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
|
||||||
mod app;
|
mod app;
|
||||||
|
|
||||||
use crate::util::{destruct_terminal, setup_terminal, Event, EventConfig, Events};
|
use crate::util::{destruct_terminal, setup_terminal, Event, EventConfig, Events};
|
||||||
use clap::{App, Arg, SubCommand};
|
use clap::{App, Arg};
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use std::io;
|
use std::time::Duration;
|
||||||
use std::io::{stdout, Write};
|
|
||||||
use std::process::Command;
|
|
||||||
use std::time::{Duration, Instant};
|
|
||||||
use tui::backend::Backend;
|
|
||||||
use unicode_width::UnicodeWidthStr;
|
|
||||||
|
|
||||||
use crate::util::Key;
|
use crate::util::Key;
|
||||||
use app::{AppMode, TaskwarriorTUIApp};
|
use app::{AppMode, TaskwarriorTUIApp};
|
||||||
|
|
||||||
use std::sync::{
|
const APP_VERSION: &str = env!("CARGO_PKG_VERSION");
|
||||||
atomic::{AtomicBool, Ordering},
|
const APP_NAME: &str = env!("CARGO_PKG_NAME");
|
||||||
Arc,
|
|
||||||
};
|
|
||||||
|
|
||||||
const APP_VERSION: &'static str = env!("CARGO_PKG_VERSION");
|
|
||||||
const APP_NAME: &'static str = env!("CARGO_PKG_NAME");
|
|
||||||
|
|
||||||
fn main() -> Result<(), Box<dyn Error>> {
|
fn main() -> Result<(), Box<dyn Error>> {
|
||||||
let matches = App::new(APP_NAME)
|
let matches = App::new(APP_NAME)
|
||||||
|
@ -49,7 +34,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tui_main(config: &str) -> Result<(), Box<dyn Error>> {
|
fn tui_main(_config: &str) -> Result<(), Box<dyn Error>> {
|
||||||
// Terminal initialization
|
// Terminal initialization
|
||||||
let mut terminal = setup_terminal();
|
let mut terminal = setup_terminal();
|
||||||
terminal.clear()?;
|
terminal.clear()?;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#[cfg(feature = "crossterm")]
|
#[cfg(feature = "crossterm")]
|
||||||
use crossterm::{
|
use crossterm::{
|
||||||
event::{self, DisableMouseCapture, EnableMouseCapture, KeyCode},
|
event::{self, DisableMouseCapture, EnableMouseCapture},
|
||||||
execute,
|
execute,
|
||||||
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen},
|
||||||
};
|
};
|
||||||
|
@ -9,7 +9,6 @@ use tui::{backend::CrosstermBackend, Terminal};
|
||||||
|
|
||||||
use std::io::{self, Write};
|
use std::io::{self, Write};
|
||||||
use std::sync::{
|
use std::sync::{
|
||||||
atomic::{AtomicBool, Ordering},
|
|
||||||
Arc, Mutex,
|
Arc, Mutex,
|
||||||
};
|
};
|
||||||
use std::{sync::mpsc, thread, time::Duration};
|
use std::{sync::mpsc, thread, time::Duration};
|
||||||
|
@ -75,8 +74,7 @@ impl Events {
|
||||||
use crossterm::event::{KeyCode::*, KeyModifiers};
|
use crossterm::event::{KeyCode::*, KeyModifiers};
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = mpsc::channel();
|
||||||
let pause_stdin = Arc::new(Mutex::new(false));
|
let pause_stdin = Arc::new(Mutex::new(false));
|
||||||
let pause_stdin = pause_stdin.clone();
|
let _input_handle = {
|
||||||
let input_handle = {
|
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
loop {
|
loop {
|
||||||
|
@ -112,7 +110,7 @@ impl Events {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
let tick_handle = {
|
let _tick_handle = {
|
||||||
let tx = tx.clone();
|
let tx = tx.clone();
|
||||||
thread::spawn(move || loop {
|
thread::spawn(move || loop {
|
||||||
if tx.send(Event::Tick).is_err() {
|
if tx.send(Event::Tick).is_err() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue