Detailed changes
@@ -23,7 +23,7 @@ pub fn run(root: &Path, ids: &[String], json: bool) -> Result<()> {
} else {
let c = crate::color::stdout_theme();
for id in &closed {
- println!("{}closed{} {id}", c.green, c.reset);
+ println!("{}closed{} {id}", c.status(db::Status::Closed), c.reset);
}
}
@@ -1,9 +1,9 @@
use anyhow::Result;
use comfy_table::presets::NOTHING;
-use comfy_table::{Cell, Color, Table};
+use comfy_table::{Cell, Table};
use std::path::Path;
-use crate::color::{cell_bold, cell_fg, stdout_use_color};
+use crate::color::{cell_bold, cell_effort, cell_priority, cell_status, stdout_use_color};
use crate::db;
pub fn run(
@@ -52,13 +52,13 @@ pub fn run(
for t in &tasks {
table.add_row(vec![
cell_bold(&t.id, use_color),
- cell_fg(
+ cell_status(
format!("[{}]", db::status_label(t.status)),
- Color::Yellow,
+ t.status,
use_color,
),
- cell_fg(db::priority_label(t.priority), Color::Red, use_color),
- cell_fg(db::effort_label(t.effort), Color::Blue, use_color),
+ cell_priority(db::priority_label(t.priority), t.priority, use_color),
+ cell_effort(db::effort_label(t.effort), t.effort, use_color),
Cell::new(&t.title),
]);
}
@@ -1,9 +1,9 @@
use anyhow::Result;
use comfy_table::presets::NOTHING;
-use comfy_table::{Cell, Color, Table};
+use comfy_table::{Cell, Table};
use std::path::Path;
-use crate::color::{cell_bold, cell_fg, stdout_use_color};
+use crate::color::{cell_bold, cell_effort, cell_priority, stdout_use_color};
use crate::db;
pub fn run(root: &Path, json: bool) -> Result<()> {
@@ -32,8 +32,8 @@ pub fn run(root: &Path, json: bool) -> Result<()> {
for t in &tasks {
table.add_row(vec![
cell_bold(&t.id, use_color),
- cell_fg(db::priority_label(t.priority), Color::Red, use_color),
- cell_fg(db::effort_label(t.effort), Color::Blue, use_color),
+ cell_priority(db::priority_label(t.priority), t.priority, use_color),
+ cell_effort(db::effort_label(t.effort), t.effort, use_color),
Cell::new(&t.title),
]);
}
@@ -23,7 +23,7 @@ pub fn run(root: &Path, ids: &[String], json: bool) -> Result<()> {
} else {
let c = crate::color::stdout_theme();
for id in &reopened {
- println!("{}reopened{} {id}", c.green, c.reset);
+ println!("{}reopened{} {id}", c.status(db::Status::Open), c.reset);
}
}
@@ -22,7 +22,7 @@ pub fn run(root: &Path, id: &str, json: bool) -> Result<()> {
c.bold,
task.title,
c.reset,
- c.yellow,
+ c.status(task.status),
db::status_label(task.status),
c.reset
);
@@ -39,10 +39,10 @@ pub fn run(root: &Path, id: &str, json: bool) -> Result<()> {
task.id,
c.reset,
task.task_type,
- c.red,
+ c.priority(task.priority),
db::priority_label(task.priority),
c.reset,
- c.blue,
+ c.effort(task.effort),
db::effort_label(task.effort),
c.reset,
);
@@ -1,12 +1,17 @@
use comfy_table::{Attribute, Cell, Color};
use std::io::IsTerminal;
+use crate::db;
+
pub struct Theme {
pub red: &'static str,
pub green: &'static str,
pub yellow: &'static str,
pub blue: &'static str,
+ pub cyan: &'static str,
pub bold: &'static str,
+ pub bold_red: &'static str,
+ pub bold_yellow: &'static str,
pub reset: &'static str,
}
@@ -15,7 +20,10 @@ const ON: Theme = Theme {
green: "\x1b[32m",
yellow: "\x1b[33m",
blue: "\x1b[34m",
+ cyan: "\x1b[36m",
bold: "\x1b[1m",
+ bold_red: "\x1b[1;31m",
+ bold_yellow: "\x1b[1;33m",
reset: "\x1b[0m",
};
@@ -24,7 +32,10 @@ const OFF: Theme = Theme {
green: "",
yellow: "",
blue: "",
+ cyan: "",
bold: "",
+ bold_red: "",
+ bold_yellow: "",
reset: "",
};
@@ -74,3 +85,71 @@ pub fn cell_fg(text: impl ToString, color: Color, use_color: bool) -> Cell {
cell
}
}
+
+impl Theme {
+ /// ANSI escape for a task status.
+ pub fn status(&self, s: db::Status) -> &str {
+ match s {
+ db::Status::Open => self.green,
+ db::Status::InProgress => self.bold_yellow,
+ db::Status::Closed => "",
+ }
+ }
+
+ /// ANSI escape for a priority level.
+ pub fn priority(&self, p: db::Priority) -> &str {
+ match p {
+ db::Priority::High => self.bold_red,
+ db::Priority::Medium => "",
+ db::Priority::Low => self.cyan,
+ }
+ }
+
+ /// ANSI escape for an effort level.
+ pub fn effort(&self, e: db::Effort) -> &str {
+ match e {
+ db::Effort::High => self.bold_red,
+ db::Effort::Medium => "",
+ db::Effort::Low => self.cyan,
+ }
+ }
+}
+
+/// A table cell styled for a task status.
+pub fn cell_status(text: impl ToString, s: db::Status, use_color: bool) -> Cell {
+ let cell = Cell::new(text);
+ if !use_color {
+ return cell;
+ }
+ match s {
+ db::Status::Open => cell.fg(Color::Green),
+ db::Status::InProgress => cell.fg(Color::Yellow).add_attribute(Attribute::Bold),
+ db::Status::Closed => cell,
+ }
+}
+
+/// A table cell styled for a priority level.
+pub fn cell_priority(text: impl ToString, p: db::Priority, use_color: bool) -> Cell {
+ let cell = Cell::new(text);
+ if !use_color {
+ return cell;
+ }
+ match p {
+ db::Priority::High => cell.fg(Color::Red).add_attribute(Attribute::Bold),
+ db::Priority::Medium => cell,
+ db::Priority::Low => cell.fg(Color::Cyan),
+ }
+}
+
+/// A table cell styled for an effort level.
+pub fn cell_effort(text: impl ToString, e: db::Effort, use_color: bool) -> Cell {
+ let cell = Cell::new(text);
+ if !use_color {
+ return cell;
+ }
+ match e {
+ db::Effort::High => cell.fg(Color::Red).add_attribute(Attribute::Bold),
+ db::Effort::Medium => cell,
+ db::Effort::Low => cell.fg(Color::Cyan),
+ }
+}
@@ -21,9 +21,14 @@
<h2><a href="/projects/{{ name }}">{{ name }}</a></h2>
</header>
<div class="hstack gap-2">
- <span class="badge">{{ open }} open</span>
- <span class="badge secondary">{{ in_progress }} in progress</span>
- <span class="badge success">{{ closed }} closed</span>
+ {% if *in_progress > 0 %}
+ <span class="badge warning">{{ in_progress }} in progress</span>
+ {% endif %}
+ <span class="badge{% if *open > 0 %} success{% else %} secondary{% endif %}">{{ open }} open</span>
+ {% if *in_progress == 0 %}
+ <span class="badge secondary">0 in progress</span>
+ {% endif %}
+ <span class="badge secondary">{{ closed }} closed</span>
</div>
{% if *total > 0 %}
<progress value="{{ total - open - in_progress }}" max="{{ total }}" class="mt-2" aria-label="{{ closed }} of {{ total }} tasks closed in {{ name }}"></progress>
@@ -16,7 +16,7 @@
{% for t in tasks %}
<tr>
<td><a href="/projects/{{ project_name }}/tasks/{{ t.full_id }}"><code>{{ t.short_id }}</code></a></td>
- <td><span class="badge{% if t.status == "closed" %} success{% elif t.status == "in_progress" %} secondary{% endif %}">{{ t.status }}</span></td>
+ <td><span class="badge{% if t.status == "open" %} success{% elif t.status == "in_progress" %} warning{% endif %}">{{ t.status }}</span></td>
<td>{{ t.priority }}</td>
<td>{{ t.effort }}</td>
<td>{{ t.title }}</td>
@@ -47,7 +47,7 @@
{% for t in tasks %}
<tr>
<td><a href="/projects/{{ project_name }}/tasks/{{ t.full_id }}"><code>{{ t.short_id }}</code></a></td>
- <td><span class="badge{% if t.status == "closed" %} success{% elif t.status == "in_progress" %} secondary{% endif %}">{{ t.status }}</span></td>
+ <td><span class="badge{% if t.status == "open" %} success{% elif t.status == "in_progress" %} warning{% endif %}">{{ t.status }}</span></td>
<td>{{ t.priority }}</td>
<td>{{ t.effort }}</td>
<td>{{ t.title }}</td>
@@ -20,7 +20,7 @@
<article class="card mt-4">
<header>
<h1 class="task-title">{{ task.title }}</h1>
- <span class="badge{% if task.status == "closed" %} success{% elif task.status == "in_progress" %} secondary{% endif %}">{{ task.status }}</span>
+ <span class="badge{% if task.status == "open" %} success{% elif task.status == "in_progress" %} warning{% endif %}">{{ task.status }}</span>
</header>
{% if !task.description.is_empty() %}