mirror of
https://github.com/kdheepak/taskwarrior-tui.git
synced 2025-08-26 03:07:18 +02:00
feat: Add logging and fix history ✨
This commit is contained in:
parent
5c7f7fe9fd
commit
7effb72f41
6 changed files with 242 additions and 15 deletions
1
.envrc
1
.envrc
|
@ -1,3 +1,4 @@
|
|||
export TASKRC=`pwd`/tests/data/.taskrc
|
||||
export TASKDATA=`pwd`/tests/data/.task
|
||||
export XDG_STATE_HOME=`pwd`/tests/data/.config
|
||||
export TASKWARRIOR_TUI_LOG_LEVEL=debug
|
||||
|
|
176
Cargo.lock
generated
176
Cargo.lock
generated
|
@ -32,6 +32,12 @@ version = "1.0.45"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee10e43ae4a853c0a3591d4e2ada1719e553be18199d9da9d4a83f5927c2f5c7"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dabe5a181f83789739c194cbe5a897dde195078fac08568d09221fd6137a7ba8"
|
||||
|
||||
[[package]]
|
||||
name = "async-attributes"
|
||||
version = "1.1.2"
|
||||
|
@ -476,6 +482,17 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derivative"
|
||||
version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "derive_builder"
|
||||
version = "0.9.0"
|
||||
|
@ -542,6 +559,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dtoa"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56899898ce76aaf4a0f24d914c97ea6ed976d42fec6ad33fcbb0a1103e07b2b0"
|
||||
|
||||
[[package]]
|
||||
name = "either"
|
||||
version = "1.6.1"
|
||||
|
@ -792,6 +815,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4"
|
||||
|
||||
[[package]]
|
||||
name = "ident_case"
|
||||
version = "1.0.1"
|
||||
|
@ -862,6 +891,12 @@ version = "0.2.107"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fbe5e23404da5b4f555ef85ebed98fb4083e55a00c317800bc2a50ede9f3d219"
|
||||
|
||||
[[package]]
|
||||
name = "linked-hash-map"
|
||||
version = "0.5.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7fb9b38af92608140b86b693604b9ffcc5824240a484d1ecd4795bacb2fe88f3"
|
||||
|
||||
[[package]]
|
||||
name = "lock_api"
|
||||
version = "0.4.5"
|
||||
|
@ -878,9 +913,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"serde",
|
||||
"value-bag",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "log-mdc"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a94d21414c1f4a51209ad204c1776a3d0765002c76c6abcb602a6f09f1e881c7"
|
||||
|
||||
[[package]]
|
||||
name = "log4rs"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1572a880d1115ff867396eee7ae2bc924554225e67a0d3c85c745b3e60ca211"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"chrono",
|
||||
"derivative",
|
||||
"fnv",
|
||||
"humantime",
|
||||
"libc",
|
||||
"log",
|
||||
"log-mdc",
|
||||
"parking_lot",
|
||||
"regex",
|
||||
"serde",
|
||||
"serde-value",
|
||||
"serde_json",
|
||||
"serde_yaml",
|
||||
"thiserror",
|
||||
"thread-id",
|
||||
"typemap",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.4.1"
|
||||
|
@ -1010,6 +1079,15 @@ version = "1.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
|
||||
[[package]]
|
||||
name = "ordered-float"
|
||||
version = "2.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97c9d06878b3a851e8026ef94bf7fef9ba93062cd412601da4d9cf369b1cc62d"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "4.2.0"
|
||||
|
@ -1045,7 +1123,7 @@ dependencies = [
|
|||
"cfg-if",
|
||||
"instant",
|
||||
"libc",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.2.10",
|
||||
"smallvec",
|
||||
"winapi",
|
||||
]
|
||||
|
@ -1185,6 +1263,12 @@ dependencies = [
|
|||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.1.57"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce"
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.10"
|
||||
|
@ -1201,7 +1285,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
"redox_syscall",
|
||||
"redox_syscall 0.2.10",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1272,6 +1356,16 @@ dependencies = [
|
|||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde-value"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
|
||||
dependencies = [
|
||||
"ordered-float",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.130"
|
||||
|
@ -1294,6 +1388,18 @@ dependencies = [
|
|||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_yaml"
|
||||
version = "0.8.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d8c608a35705a5d3cdc9fbe403147647ff34b921f8e833e49306df898f9b20af"
|
||||
dependencies = [
|
||||
"dtoa",
|
||||
"indexmap",
|
||||
"serde",
|
||||
"yaml-rust",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "shellexpand"
|
||||
version = "2.1.0"
|
||||
|
@ -1434,6 +1540,8 @@ dependencies = [
|
|||
"futures-timer",
|
||||
"itertools",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"log4rs",
|
||||
"rand",
|
||||
"regex",
|
||||
"rustyline",
|
||||
|
@ -1477,6 +1585,37 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "854babe52e4df1653706b98fcfc05843010039b406875930a70e4d9644e5c417"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "aa32fd3f627f367fe16f893e2597ae3c05020f8bba2666a4e6ea73d377e5714b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thread-id"
|
||||
version = "3.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c7fbf4c9d56b320106cd64fd024dadfa0be7cb4706725fc44a7d7ce952d820c1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_syscall 0.1.57",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "time"
|
||||
version = "0.1.44"
|
||||
|
@ -1488,6 +1627,12 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "traitobject"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efd1f82c56340fdf16f2a953d7bda4f8fdffba13d93b00844c25572110b26079"
|
||||
|
||||
[[package]]
|
||||
name = "tui"
|
||||
version = "0.16.0"
|
||||
|
@ -1501,6 +1646,15 @@ dependencies = [
|
|||
"unicode-width",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typemap"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "653be63c80a3296da5551e1bfd2cca35227e13cdd08c6668903ae2f4f77aa1f6"
|
||||
dependencies = [
|
||||
"unsafe-any",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.6.0"
|
||||
|
@ -1537,6 +1691,15 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3"
|
||||
|
||||
[[package]]
|
||||
name = "unsafe-any"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f30360d7979f5e9c6e6cea48af192ea8fab4afb3cf72597154b8f08935bc9c7f"
|
||||
dependencies = [
|
||||
"traitobject",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "utf8parse"
|
||||
version = "0.2.0"
|
||||
|
@ -1706,3 +1869,12 @@ name = "winapi-x86_64-pc-windows-gnu"
|
|||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
|
||||
dependencies = [
|
||||
"linked-hash-map",
|
||||
]
|
||||
|
|
|
@ -30,6 +30,8 @@ futures = "0.3.16"
|
|||
futures-timer = "3.0.2"
|
||||
itertools = "0.10.1"
|
||||
lazy_static = "1.4.0"
|
||||
log = "0.4.14"
|
||||
log4rs = "1.0.0"
|
||||
rand = "0.8.4"
|
||||
regex = "1.5.4"
|
||||
rustyline = "8.2"
|
||||
|
|
|
@ -80,6 +80,8 @@ use task_hookrs::project::Project;
|
|||
|
||||
use versions::Versioning;
|
||||
|
||||
use log::{debug, error, info, log_enabled, trace, warn, Level, LevelFilter};
|
||||
|
||||
const MAX_LINE: usize = 4096;
|
||||
|
||||
lazy_static! {
|
||||
|
@ -1283,6 +1285,7 @@ impl TaskwarriorTui {
|
|||
}
|
||||
|
||||
pub fn update(&mut self, force: bool) -> Result<()> {
|
||||
trace!("self.update({:?});", force);
|
||||
if force || self.dirty || self.tasks_changed_since(self.last_export).unwrap_or(true) {
|
||||
let task_uuids = self.selected_task_uuids();
|
||||
if self.current_selection_uuid.is_none() && self.current_selection_id.is_none() && task_uuids.len() == 1 {
|
||||
|
@ -1410,6 +1413,7 @@ impl TaskwarriorTui {
|
|||
}
|
||||
|
||||
pub fn update_task_table_state(&mut self) {
|
||||
trace!("self.update_task_table_state()");
|
||||
self.task_table_state.select(Some(self.current_selection));
|
||||
|
||||
for uuid in self.marked.clone() {
|
||||
|
|
|
@ -15,13 +15,6 @@ impl HistoryContext {
|
|||
pub fn new(filename: &str) -> Self {
|
||||
let history = History::new();
|
||||
|
||||
#[cfg(target_family = "unix")]
|
||||
let config_dir_op = std::env::var_os("XDG_STATE_HOME")
|
||||
.map(PathBuf::from)
|
||||
.filter(|p| p.is_absolute())
|
||||
.or_else(|| dirs::home_dir().map(|d| d.join(".config")));
|
||||
|
||||
#[cfg(not(target_family = "unix"))]
|
||||
let config_dir_op = dirs::config_dir();
|
||||
|
||||
let config_path = config_dir_op.map(|d| d.join("taskwarrior-tui")).unwrap();
|
||||
|
@ -44,6 +37,7 @@ impl HistoryContext {
|
|||
self.history.save(&self.config_path)?;
|
||||
}
|
||||
self.history_index = self.history.len();
|
||||
log::debug!("Loading history of length {}", self.history.len());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -61,25 +55,40 @@ impl HistoryContext {
|
|||
}
|
||||
|
||||
pub fn history_search(&mut self, buf: &str, dir: Direction) -> Option<String> {
|
||||
log::debug!(
|
||||
"Searching history for {:?} in direction {:?} with history index = {:?}",
|
||||
buf,
|
||||
dir,
|
||||
self.history_index()
|
||||
);
|
||||
if self.history.is_empty() {
|
||||
log::debug!("History is empty");
|
||||
return None;
|
||||
}
|
||||
if self.history_index == self.history.len().saturating_sub(1) && dir == Direction::Forward
|
||||
|| self.history_index == 0 && dir == Direction::Reverse
|
||||
{
|
||||
log::debug!("No more history left to search");
|
||||
return None;
|
||||
}
|
||||
let history_index = match dir {
|
||||
Direction::Reverse => self.history_index,
|
||||
Direction::Forward => self.history_index,
|
||||
Direction::Reverse => self.history_index.saturating_sub(1),
|
||||
Direction::Forward => self
|
||||
.history_index
|
||||
.saturating_add(1)
|
||||
.min(self.history_len().saturating_sub(1)),
|
||||
};
|
||||
log::debug!("Using history index = {} for searching", history_index);
|
||||
if let Some(history_index) = self.history.starts_with(buf, history_index, dir) {
|
||||
log::debug!("Found index {:?}", history_index);
|
||||
log::debug!("Previous index {:?}", self.history_index);
|
||||
self.history_index = history_index;
|
||||
Some(self.history.get(history_index).unwrap().clone())
|
||||
} else if buf.is_empty() {
|
||||
self.history_index = history_index;
|
||||
Some(self.history.get(history_index).unwrap().clone())
|
||||
} else {
|
||||
log::debug!("History index = {}. Found no match.", history_index);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
47
src/main.rs
47
src/main.rs
|
@ -16,6 +16,10 @@ mod pane;
|
|||
mod table;
|
||||
mod task_report;
|
||||
|
||||
use log::{debug, error, info, log_enabled, trace, warn, Level, LevelFilter};
|
||||
use log4rs::append::file::FileAppender;
|
||||
use log4rs::config::{Appender, Config, Logger, Root};
|
||||
use log4rs::encode::pattern::PatternEncoder;
|
||||
use std::env;
|
||||
use std::error::Error;
|
||||
use std::io::{self, Write};
|
||||
|
@ -41,8 +45,8 @@ use crate::action::Action;
|
|||
use crate::event::{Event, EventConfig, Events, Key};
|
||||
use crate::keyconfig::KeyConfig;
|
||||
|
||||
/// # Panics
|
||||
/// Will panic if could not obtain terminal
|
||||
const LOG_PATTERN: &str = "{d(%Y-%m-%d %H:%M:%S)} | {l} | {f}:{L} | {m}{n}";
|
||||
|
||||
pub fn setup_terminal() -> Terminal<CrosstermBackend<io::Stdout>> {
|
||||
enable_raw_mode().expect("Running not in terminal");
|
||||
let mut stdout = io::stdout();
|
||||
|
@ -51,8 +55,7 @@ pub fn setup_terminal() -> Terminal<CrosstermBackend<io::Stdout>> {
|
|||
let backend = CrosstermBackend::new(stdout);
|
||||
Terminal::new(backend).unwrap()
|
||||
}
|
||||
/// # Panics
|
||||
/// Will panic if could not `disable_raw_mode`
|
||||
|
||||
pub fn destruct_terminal() {
|
||||
disable_raw_mode().unwrap();
|
||||
execute!(io::stdout(), LeaveAlternateScreen, DisableMouseCapture).unwrap();
|
||||
|
@ -61,10 +64,44 @@ pub fn destruct_terminal() {
|
|||
|
||||
fn main() {
|
||||
better_panic::install();
|
||||
|
||||
let data_local_dir = dirs::data_local_dir()
|
||||
.expect("Unable to open data local directory.")
|
||||
.join("taskwarrior-tui");
|
||||
std::fs::create_dir_all(&data_local_dir).unwrap_or_else(|_| panic!("Unable to create {:?}", data_local_dir));
|
||||
|
||||
let logfile = FileAppender::builder()
|
||||
.encoder(Box::new(PatternEncoder::new(LOG_PATTERN)))
|
||||
.append(false)
|
||||
.build(data_local_dir.join("taskwarrior-tui.log"))
|
||||
.unwrap();
|
||||
|
||||
let levelfilter = match std::env::var("TASKWARRIOR_TUI_LOG_LEVEL")
|
||||
.unwrap_or_else(|_| "info".to_string())
|
||||
.as_str()
|
||||
{
|
||||
"off" => LevelFilter::Off,
|
||||
"warn" => LevelFilter::Warn,
|
||||
"info" => LevelFilter::Info,
|
||||
"debug" => LevelFilter::Debug,
|
||||
"trace" => LevelFilter::Trace,
|
||||
_ => LevelFilter::Info,
|
||||
};
|
||||
let config = Config::builder()
|
||||
.appender(Appender::builder().build("logfile", Box::new(logfile)))
|
||||
.logger(Logger::builder().build("taskwarrior_tui", levelfilter))
|
||||
.build(Root::builder().appender("logfile").build(LevelFilter::Info))
|
||||
.unwrap();
|
||||
|
||||
log4rs::init_config(config).unwrap();
|
||||
|
||||
let matches = cli::generate_cli_app().get_matches();
|
||||
|
||||
debug!("getting matches from clap...");
|
||||
let config = matches.value_of("config").unwrap_or("~/.taskrc");
|
||||
let report = matches.value_of("report").unwrap_or("next");
|
||||
debug!("report = {:?}", &report);
|
||||
debug!("config = {:?}", &config);
|
||||
let r = task::block_on(tui_main(config, report));
|
||||
if let Err(err) = r {
|
||||
eprintln!("\x1b[0;31m[taskwarrior-tui error]\x1b[0m: {}\n\nIf you need additional help, please report as a github issue on https://github.com/kdheepak/taskwarrior-tui", err);
|
||||
|
@ -99,6 +136,7 @@ async fn tui_main(_config: &str, report: &str) -> Result<()> {
|
|||
// Handle input
|
||||
match events.next().await? {
|
||||
Event::Input(input) => {
|
||||
debug!("Received input = {:?}", input);
|
||||
if (input == app.keyconfig.edit
|
||||
|| input == app.keyconfig.shortcut1
|
||||
|| input == app.keyconfig.shortcut2
|
||||
|
@ -136,6 +174,7 @@ async fn tui_main(_config: &str, report: &str) -> Result<()> {
|
|||
}
|
||||
}
|
||||
Event::Tick => {
|
||||
trace!("Tick event");
|
||||
let r = app.update(false);
|
||||
if r.is_err() {
|
||||
destruct_terminal();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue