Make active panel in bold

This commit is contained in:
Dheepak Krishnamurthy 2020-10-24 23:52:04 -06:00
parent fe81fc4fa7
commit 5e2eabfba9
4 changed files with 166 additions and 98 deletions

View file

@ -4,9 +4,9 @@ use crate::table::{Row, Table, TableState};
use std::cmp::Ordering;
use std::convert::TryInto;
use std::error::Error;
use std::process::Command;
use std::result::Result;
use std::error::Error;
use task_hookrs::date::Date;
use task_hookrs::import::import;
@ -25,7 +25,7 @@ use tui::{
style::{Color, Modifier, Style},
terminal::Frame,
text::{Span, Spans, Text},
widgets::{Block, Borders, Clear, Paragraph},
widgets::{Block, BorderType, Borders, Clear, Paragraph},
};
use rustyline::error::ReadlineError;
@ -205,10 +205,7 @@ impl TaskReportTable {
self.columns = vec![];
self.labels = vec![];
let output = Command::new("task")
.arg("show")
.arg("report.next.columns")
.output()?;
let output = Command::new("task").arg("show").arg("report.next.columns").output()?;
let data = String::from_utf8(output.stdout)?;
for line in data.split('\n') {
@ -220,10 +217,7 @@ impl TaskReportTable {
}
}
let output = Command::new("task")
.arg("show")
.arg("report.next.labels")
.output()?;
let output = Command::new("task").arg("show").arg("report.next.labels").output()?;
let data = String::from_utf8(output.stdout)?;
for line in data.split('\n') {
@ -395,10 +389,7 @@ impl TTApp {
}
pub fn get_context(&mut self) -> Result<(), Box<dyn Error>> {
let output = Command::new("task")
.arg("_get")
.arg("rc.context")
.output()?;
let output = Command::new("task").arg("_get").arg("rc.context").output()?;
self.context_name = String::from_utf8(output.stdout)?;
self.context_name = self.context_name.strip_suffix('\n').unwrap_or("").to_string();
@ -434,21 +425,16 @@ impl TTApp {
.split(f.size());
let today = Local::today();
let c = Calendar::default()
.block(Block::default()
.title(Spans::from(vec![
Span::styled(
"Task",
Style::default().add_modifier(Modifier::DIM),
),
Span::from("|"),
Span::styled(
"Calendar",
Style::default().add_modifier(Modifier::BOLD),
),
]),
)
.borders(Borders::ALL)
)
.block(
Block::default()
.title(Spans::from(vec![
Span::styled("Task", Style::default().add_modifier(Modifier::DIM)),
Span::from("|"),
Span::styled("Calendar", Style::default().add_modifier(Modifier::BOLD)),
]))
.borders(Borders::ALL)
.border_type(BorderType::Rounded),
)
.year(self.calendar_year)
.date_style(dates_with_styles)
.months_per_row(self.config.uda_calendar_months_per_row);
@ -498,7 +484,12 @@ impl TTApp {
AppMode::TaskFilter => {
f.set_cursor(rects[1].x + self.filter.pos() as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]);
self.draw_command(f, rects[1], self.filter.as_str(), "Filter Tasks");
self.draw_command(
f,
rects[1],
self.filter.as_str(),
Span::styled("Filter Tasks", Style::default().add_modifier(Modifier::BOLD)),
);
}
AppMode::TaskModify => {
f.set_cursor(rects[1].x + self.modify.pos() as u16 + 1, rects[1].y + 1);
@ -507,18 +498,31 @@ impl TTApp {
f,
rects[1],
self.modify.as_str(),
format!("Modify Task {}", task_id).as_str(),
Span::styled(
format!("Modify Task {}", task_id).as_str(),
Style::default().add_modifier(Modifier::BOLD),
),
);
}
AppMode::TaskLog => {
f.set_cursor(rects[1].x + self.command.pos() as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]);
self.draw_command(f, rects[1], self.command.as_str(), "Log Task");
self.draw_command(
f,
rects[1],
self.command.as_str(),
Span::styled("Log Tasks", Style::default().add_modifier(Modifier::BOLD)),
);
}
AppMode::TaskSubprocess => {
f.set_cursor(rects[1].x + self.command.pos() as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]);
self.draw_command(f, rects[1], self.command.as_str(), "Shell Command");
self.draw_command(
f,
rects[1],
self.command.as_str(),
Span::styled("Shell Command", Style::default().add_modifier(Modifier::BOLD)),
);
}
AppMode::TaskAnnotate => {
f.set_cursor(rects[1].x + self.command.pos() as u16 + 1, rects[1].y + 1);
@ -527,17 +531,30 @@ impl TTApp {
f,
rects[1],
self.command.as_str(),
format!("Annotate Task {}", task_id).as_str(),
Span::styled(
format!("Annotate Task {}", task_id).as_str(),
Style::default().add_modifier(Modifier::BOLD),
),
);
}
AppMode::TaskAdd => {
f.set_cursor(rects[1].x + self.command.pos() as u16 + 1, rects[1].y + 1);
f.render_widget(Clear, rects[1]);
self.draw_command(f, rects[1], self.command.as_str(), "Add Task");
self.draw_command(
f,
rects[1],
self.command.as_str(),
Span::styled("Add Task", Style::default().add_modifier(Modifier::BOLD)),
);
}
AppMode::TaskError => {
f.render_widget(Clear, rects[1]);
self.draw_command(f, rects[1], self.error.as_str(), "Error");
self.draw_command(
f,
rects[1],
self.error.as_str(),
Span::styled("Error", Style::default().add_modifier(Modifier::BOLD)),
);
}
AppMode::TaskHelpPopup => {
self.draw_command(f, rects[1], self.filter.as_str(), "Filter Tasks");
@ -719,21 +736,40 @@ impl TTApp {
Spans::from(""),
];
let paragraph = Paragraph::new(text)
.block(Block::default().title("Help").borders(Borders::ALL))
.block(
Block::default()
.title(Span::styled("Help", Style::default().add_modifier(Modifier::BOLD)))
.borders(Borders::ALL)
.border_type(BorderType::Rounded),
)
.alignment(Alignment::Left);
let area = centered_rect(80, 90, rect);
f.render_widget(Clear, area);
f.render_widget(paragraph, area);
}
fn draw_command(&self, f: &mut Frame<impl Backend>, rect: Rect, text: &str, title: &str) {
let p = Paragraph::new(Text::from(text)).block(Block::default().borders(Borders::ALL).title(title));
fn draw_command<'a, T>(&self, f: &mut Frame<impl Backend>, rect: Rect, text: &str, title: T)
where
T: Into<Spans<'a>>,
{
let p = Paragraph::new(Text::from(text)).block(
Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(title.into()),
);
f.render_widget(p, rect);
}
fn draw_task_details(&mut self, f: &mut Frame<impl Backend>, rect: Rect) {
if self.tasks.lock().unwrap().is_empty() {
f.render_widget(Block::default().borders(Borders::ALL).title("Task not found"), rect);
f.render_widget(
Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title("Task not found"),
rect,
);
return;
}
let selected = self.state.selected().unwrap_or_default();
@ -747,6 +783,7 @@ impl TTApp {
let p = Paragraph::new(Text::from(&data[..])).block(
Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(format!("Task {}", task_id)),
);
f.render_widget(p, rect);
@ -798,20 +835,22 @@ impl TTApp {
fn draw_task_report(&mut self, f: &mut Frame<impl Backend>, rect: Rect) {
let (tasks, headers) = self.task_report();
if tasks.is_empty() {
f.render_widget(Block::default()
.borders(Borders::ALL)
.title(Spans::from(vec![
Span::styled(
"task next",
Style::default().add_modifier(Modifier::BOLD),
),
Span::from("|"),
Span::styled(
"Calendar",
Style::default().add_modifier(Modifier::DIM),
),
]),
), rect);
let mut style = Style::default();
match self.mode {
AppMode::TaskReport => style = style.add_modifier(Modifier::BOLD),
_ => style = style.add_modifier(Modifier::DIM),
}
f.render_widget(
Block::default()
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(Spans::from(vec![
Span::styled("Task", style),
Span::from("|"),
Span::styled("Calendar", Style::default().add_modifier(Modifier::DIM)),
])),
rect,
);
return;
}
@ -885,23 +924,22 @@ impl TTApp {
.map(|i| Constraint::Min((*i).try_into().unwrap_or(10)))
.collect();
let mut style = Style::default();
match self.mode {
AppMode::TaskReport => style = style.add_modifier(Modifier::BOLD),
_ => style = style.add_modifier(Modifier::DIM),
}
let t = Table::new(header, rows.into_iter())
.block(
Block::default()
.borders(Borders::ALL)
.title(Spans::from(vec![
Span::styled(
"Task",
Style::default().add_modifier(Modifier::BOLD),
),
Span::from("|"),
Span::styled(
"Calendar",
Style::default().add_modifier(Modifier::DIM),
),
]),
)
)
.borders(Borders::ALL)
.border_type(BorderType::Rounded)
.title(Spans::from(vec![
Span::styled("Task", style),
Span::from("|"),
Span::styled("Calendar", Style::default().add_modifier(Modifier::DIM)),
])),
)
.highlight_style(highlight_style)
.highlight_symbol(&self.config.uda_selection_indicator)
.widths(&constraints);
@ -1014,10 +1052,7 @@ impl TTApp {
self.command.update("", 0);
Ok(())
}
Err(_) => Err(format!(
"Shell command `{}` exited with non-zero output",
shell,
)),
Err(_) => Err(format!("Shell command `{}` exited with non-zero output", shell,)),
}
}
None => Err(format!("Cannot run subprocess. Unable to shlex split `{}`", shell)),
@ -1046,10 +1081,16 @@ impl TTApp {
self.command.update("", 0);
Ok(())
}
Err(_) => Err(format!("Cannot run `task log {}`. Check documentation for more information", shell))
Err(_) => Err(format!(
"Cannot run `task log {}`. Check documentation for more information",
shell
)),
}
}
None => Err(format!("Unable to run `task log`. Cannot shlex split `{}`", shell.as_str())),
None => Err(format!(
"Unable to run `task log`. Cannot shlex split `{}`",
shell.as_str()
)),
}
}
@ -1083,8 +1124,7 @@ impl TTApp {
}
None => Err(format!(
"Unable to run `task {} modify`. Cannot shlex split `{}`",
task_id,
shell,
task_id, shell,
)),
}
}
@ -1111,10 +1151,16 @@ impl TTApp {
self.command.update("", 0);
Ok(())
}
Err(_) => Err(format!("Cannot run `task {} annotate {}`. Check documentation for more information", task_id, shell)),
Err(_) => Err(format!(
"Cannot run `task {} annotate {}`. Check documentation for more information",
task_id, shell
)),
}
}
None => Err(format!("Unable to run `task {} annotate`. Cannot shlex split `{}`", task_id, shell)),
None => Err(format!(
"Unable to run `task {} annotate`. Cannot shlex split `{}`",
task_id, shell
)),
}
}
@ -1135,7 +1181,10 @@ impl TTApp {
self.command.update("", 0);
Ok(())
}
Err(_) => Err(format!("Cannot run `task add {}`. Check documentation for more information", shell)),
Err(_) => Err(format!(
"Cannot run `task add {}`. Check documentation for more information",
shell
)),
}
}
None => Err(format!("Unable to run `task add`. Cannot shlex split `{}`", shell)),
@ -1387,7 +1436,12 @@ impl TTApp {
}
}
pub fn handle_input(&mut self, input: Key, terminal: &mut Terminal<CrosstermBackend<io::Stdout>>, events: &Events) -> Result<(), Box<dyn Error>> {
pub fn handle_input(
&mut self,
input: Key,
terminal: &mut Terminal<CrosstermBackend<io::Stdout>>,
events: &Events,
) -> Result<(), Box<dyn Error>> {
match self.mode {
AppMode::TaskReport => match input {
Key::Ctrl('c') | Key::Char('q') => self.should_quit = true,
@ -1570,9 +1624,11 @@ impl TTApp {
Key::Char('[') => {
self.mode = AppMode::TaskReport;
}
Key::Up | Key::Char('k') => if self.calendar_year > 0 {
self.calendar_year -= 1
},
Key::Up | Key::Char('k') => {
if self.calendar_year > 0 {
self.calendar_year -= 1
}
}
Key::Down | Key::Char('j') => self.calendar_year += 1,
Key::Ctrl('c') | Key::Char('q') => self.should_quit = true,
_ => {}

View file

@ -1,8 +1,8 @@
use std::collections::HashMap;
use std::error::Error;
use std::process::Command;
use std::str;
use tui::style::{Color, Modifier};
use std::error::Error;
#[derive(Debug, Clone)]
pub struct TColor {
@ -94,10 +94,7 @@ impl TConfig {
fn get_color_collection() -> Result<HashMap<String, TColor>, Box<dyn Error>> {
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()?;
let data = String::from_utf8(output.stdout).expect("Unable to convert stdout to string");
for line in data.split('\n') {

View file

@ -12,8 +12,8 @@ use crate::util::{destruct_terminal, setup_terminal, Event, EventConfig, Events}
use clap::{App, Arg};
use std::env;
use std::error::Error;
use std::time::Duration;
use std::io::Write;
use std::time::Duration;
use crate::util::Key;
use app::{AppMode, TTApp};
@ -41,7 +41,10 @@ fn main() -> Result<(), Box<dyn Error>> {
match r {
Ok(_) => std::process::exit(0),
Err(error) => {
eprintln!("{}: {}. Please report as a github issue on https://github.com/kdheepak/taskwarrior-tui", "[taskwarrior-tui error]", error);
eprintln!(
"{}: {}. Please report as a github issue on https://github.com/kdheepak/taskwarrior-tui",
"[taskwarrior-tui error]", error
);
std::process::exit(1);
}
}
@ -71,16 +74,16 @@ fn tui_main(_config: &str) -> Result<(), Box<dyn Error>> {
let r = app.handle_input(input, &mut terminal, &events);
if r.is_err() {
destruct_terminal(terminal);
return r
return r;
}
},
}
Event::Tick => {
let r = app.update();
if r.is_err() {
destruct_terminal(terminal);
return r
return r;
}
},
}
}
if app.should_quit {
@ -90,10 +93,10 @@ fn tui_main(_config: &str) -> Result<(), Box<dyn Error>> {
}
Ok(())
},
}
Err(e) => {
destruct_terminal(terminal);
Err(e)
},
}
}
}

View file

@ -316,10 +316,22 @@ where
x = table_area.left();
for (c, (w, elt)) in solved_widths.iter().zip(data).enumerate() {
let s = if c == 0 {
buf.set_stringn(x, y + i as u16, format!("{symbol:^width$}", symbol="", width=area.width as usize), *w as usize, style);
buf.set_stringn(
x,
y + i as u16,
format!("{symbol:^width$}", symbol = "", width = area.width as usize),
*w as usize,
style,
);
format!("{}{}", symbol, elt)
} else {
buf.set_stringn(x - 1, y + i as u16, format!("{symbol:^width$}", symbol="", width=area.width as usize), *w as usize + 1, style);
buf.set_stringn(
x - 1,
y + i as u16,
format!("{symbol:^width$}", symbol = "", width = area.width as usize),
*w as usize + 1,
style,
);
format!("{}", elt)
};
buf.set_stringn(x, y + i as u16, s, *w as usize, style);