mirror of
https://github.com/kdheepak/taskwarrior-tui.git
synced 2025-08-25 08:47:18 +02:00
Add history files
This commit is contained in:
parent
ba84e3fff0
commit
690ce7004f
5 changed files with 194 additions and 62 deletions
89
Cargo.lock
generated
89
Cargo.lock
generated
|
@ -41,6 +41,18 @@ version = "1.0.40"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
|
checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayref"
|
||||||
|
version = "0.3.6"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a4c527152e37cf757a3f78aae5a06fbeefdb07ccc535c980a3208ee3060dd544"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "arrayvec"
|
||||||
|
version = "0.5.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "async-attributes"
|
name = "async-attributes"
|
||||||
version = "1.1.2"
|
version = "1.1.2"
|
||||||
|
@ -218,6 +230,12 @@ dependencies = [
|
||||||
"rustc-demangle",
|
"rustc-demangle",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "base64"
|
||||||
|
version = "0.13.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "better-panic"
|
name = "better-panic"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
@ -234,6 +252,17 @@ version = "1.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "blake2b_simd"
|
||||||
|
version = "0.5.11"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "afa748e348ad3be8263be728124b24a24f268266f6f5d58af9d75f6a40b5c587"
|
||||||
|
dependencies = [
|
||||||
|
"arrayref",
|
||||||
|
"arrayvec",
|
||||||
|
"constant_time_eq",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "blocking"
|
name = "blocking"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
|
@ -357,6 +386,12 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "constant_time_eq"
|
||||||
|
version = "0.1.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "245097e9a4535ee1e3e3931fcfcd55a796a44c643e8596ff6566d68f09b87bbc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.3"
|
version = "0.8.3"
|
||||||
|
@ -464,6 +499,16 @@ dependencies = [
|
||||||
"syn",
|
"syn",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs"
|
||||||
|
version = "2.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "13aea89a5c93364a98e9b37b2fa237effbb694d5cfe01c5b70941f7eb087d5e3"
|
||||||
|
dependencies = [
|
||||||
|
"cfg-if 0.1.10",
|
||||||
|
"dirs-sys",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-next"
|
name = "dirs-next"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
@ -474,6 +519,17 @@ dependencies = [
|
||||||
"dirs-sys-next",
|
"dirs-sys-next",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "dirs-sys"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e93d7f5705de3e49895a2b5e0b8855a1c27f080192ae9c32a6432d50741a57a"
|
||||||
|
dependencies = [
|
||||||
|
"libc",
|
||||||
|
"redox_users 0.3.5",
|
||||||
|
"winapi",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dirs-sys-next"
|
name = "dirs-sys-next"
|
||||||
version = "0.1.2"
|
version = "0.1.2"
|
||||||
|
@ -481,7 +537,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"redox_users",
|
"redox_users 0.4.0",
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -1074,6 +1130,17 @@ dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "redox_users"
|
||||||
|
version = "0.3.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "de0737333e7a9502c789a36d7c7fa6092a49895d4faa31ca5df163857ded2e9d"
|
||||||
|
dependencies = [
|
||||||
|
"getrandom 0.1.16",
|
||||||
|
"redox_syscall 0.1.57",
|
||||||
|
"rust-argon2",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_users"
|
name = "redox_users"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
|
@ -1101,6 +1168,18 @@ version = "0.6.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rust-argon2"
|
||||||
|
version = "0.8.3"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4b18820d944b33caa75a71378964ac46f58517c92b6ae5f762636247c09e78fb"
|
||||||
|
dependencies = [
|
||||||
|
"base64",
|
||||||
|
"blake2b_simd",
|
||||||
|
"constant_time_eq",
|
||||||
|
"crossbeam-utils",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc-demangle"
|
name = "rustc-demangle"
|
||||||
version = "0.1.18"
|
version = "0.1.18"
|
||||||
|
@ -1301,6 +1380,7 @@ dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"clap",
|
"clap",
|
||||||
"crossterm",
|
"crossterm",
|
||||||
|
"dirs",
|
||||||
"futures",
|
"futures",
|
||||||
"futures-timer",
|
"futures-timer",
|
||||||
"itertools",
|
"itertools",
|
||||||
|
@ -1316,6 +1396,7 @@ dependencies = [
|
||||||
"unicode-segmentation",
|
"unicode-segmentation",
|
||||||
"unicode-width",
|
"unicode-width",
|
||||||
"uuid",
|
"uuid",
|
||||||
|
"xdg",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1538,3 +1619,9 @@ name = "winapi-x86_64-pc-windows-gnu"
|
||||||
version = "0.4.0"
|
version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "xdg"
|
||||||
|
version = "2.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d089681aa106a86fade1b0128fb5daf07d5867a509ab036d99988dec80429a57"
|
||||||
|
|
|
@ -40,6 +40,8 @@ anyhow = "1"
|
||||||
async-std = { version = "1", features = ["attributes", "unstable"] }
|
async-std = { version = "1", features = ["attributes", "unstable"] }
|
||||||
futures = "0.3"
|
futures = "0.3"
|
||||||
futures-timer = "3.0"
|
futures-timer = "3.0"
|
||||||
|
dirs = "2.0.2"
|
||||||
|
xdg = "2"
|
||||||
|
|
||||||
[package.metadata.rpm]
|
[package.metadata.rpm]
|
||||||
package = "taskwarrior-tui"
|
package = "taskwarrior-tui"
|
||||||
|
|
77
src/app.rs
77
src/app.rs
|
@ -14,6 +14,11 @@ use std::collections::{HashMap, HashSet};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
use std::io::Read;
|
||||||
|
use std::io::Write;
|
||||||
|
use xdg::BaseDirectories;
|
||||||
|
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
|
||||||
|
@ -49,14 +54,14 @@ use tui::{
|
||||||
widgets::{Block, BorderType, Borders, Clear, Paragraph},
|
widgets::{Block, BorderType, Borders, Clear, Paragraph},
|
||||||
};
|
};
|
||||||
|
|
||||||
use rustyline::error::ReadlineError;
|
|
||||||
use rustyline::history::Direction as HistoryDirection;
|
use rustyline::history::Direction as HistoryDirection;
|
||||||
use rustyline::history::History;
|
|
||||||
use rustyline::line_buffer::LineBuffer;
|
use rustyline::line_buffer::LineBuffer;
|
||||||
use rustyline::At;
|
use rustyline::At;
|
||||||
use rustyline::Editor;
|
use rustyline::Editor;
|
||||||
use rustyline::Word;
|
use rustyline::Word;
|
||||||
|
|
||||||
|
use crate::history::HistoryContext;
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use tui::{backend::CrosstermBackend, Terminal};
|
use tui::{backend::CrosstermBackend, Terminal};
|
||||||
|
|
||||||
|
@ -150,63 +155,6 @@ pub enum AppMode {
|
||||||
Calendar,
|
Calendar,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct HistoryContext {
|
|
||||||
history: History,
|
|
||||||
history_index: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl HistoryContext {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let history = History::new();
|
|
||||||
Self {
|
|
||||||
history,
|
|
||||||
history_index: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn history(&self) -> &History {
|
|
||||||
&self.history
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn history_index(&self) -> usize {
|
|
||||||
self.history_index
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn history_search(&mut self, buf: &str, dir: HistoryDirection) -> Option<String> {
|
|
||||||
if self.history.is_empty() {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
if self.history_index == self.history.len().saturating_sub(1) && dir == HistoryDirection::Forward
|
|
||||||
|| self.history_index == 0 && dir == HistoryDirection::Reverse
|
|
||||||
{
|
|
||||||
return Some(self.history.get(self.history_index).unwrap().clone());
|
|
||||||
}
|
|
||||||
let history_index = match dir {
|
|
||||||
HistoryDirection::Reverse => self.history_index - 1,
|
|
||||||
HistoryDirection::Forward => self.history_index + 1,
|
|
||||||
};
|
|
||||||
if let Some(history_index) = self.history.starts_with(buf, history_index, dir) {
|
|
||||||
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 {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn add(&mut self, buf: &str) {
|
|
||||||
if self.history.add(buf) {
|
|
||||||
self.history_index = self.history.len() - 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn last(&mut self) {
|
|
||||||
self.history_index = self.history.len().saturating_sub(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct TaskwarriorTuiApp {
|
pub struct TaskwarriorTuiApp {
|
||||||
pub should_quit: bool,
|
pub should_quit: bool,
|
||||||
pub dirty: bool,
|
pub dirty: bool,
|
||||||
|
@ -282,7 +230,9 @@ impl TaskwarriorTuiApp {
|
||||||
}
|
}
|
||||||
app.get_context()?;
|
app.get_context()?;
|
||||||
app.update(true)?;
|
app.update(true)?;
|
||||||
|
app.filter_history_context.load("filter.history")?;
|
||||||
app.filter_history_context.add(app.filter.as_str());
|
app.filter_history_context.add(app.filter.as_str());
|
||||||
|
app.command_history_context.load("command.history")?;
|
||||||
Ok(app)
|
Ok(app)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -931,6 +881,7 @@ impl TaskwarriorTuiApp {
|
||||||
self.update_tags();
|
self.update_tags();
|
||||||
self.task_details.clear();
|
self.task_details.clear();
|
||||||
self.dirty = false;
|
self.dirty = false;
|
||||||
|
self.save_history()?;
|
||||||
}
|
}
|
||||||
self.cursor_fix();
|
self.cursor_fix();
|
||||||
self.update_task_table_state();
|
self.update_task_table_state();
|
||||||
|
@ -940,6 +891,12 @@ impl TaskwarriorTuiApp {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn save_history(&mut self) -> Result<()> {
|
||||||
|
self.filter_history_context.write("filter.history")?;
|
||||||
|
self.command_history_context.write("command.history")?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn cursor_fix(&mut self) {
|
pub fn cursor_fix(&mut self) {
|
||||||
while !self.tasks.is_empty() && self.current_selection >= self.tasks.len() {
|
while !self.tasks.is_empty() && self.current_selection >= self.tasks.len() {
|
||||||
self.task_report_previous();
|
self.task_report_previous();
|
||||||
|
@ -2351,8 +2308,6 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup() {
|
fn setup() {
|
||||||
use std::io::Read;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::process::Stdio;
|
use std::process::Stdio;
|
||||||
let mut f = File::open(Path::new(env!("TASKDATA")).parent().unwrap().join("export.json")).unwrap();
|
let mut f = File::open(Path::new(env!("TASKDATA")).parent().unwrap().join("export.json")).unwrap();
|
||||||
let mut s = String::new();
|
let mut s = String::new();
|
||||||
|
|
87
src/history.rs
Normal file
87
src/history.rs
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use rustyline::error::ReadlineError;
|
||||||
|
use rustyline::history::Direction;
|
||||||
|
use rustyline::history::History;
|
||||||
|
use std::fs::File;
|
||||||
|
use xdg::BaseDirectories;
|
||||||
|
|
||||||
|
pub struct HistoryContext {
|
||||||
|
history: History,
|
||||||
|
history_index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl HistoryContext {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
let history = History::new();
|
||||||
|
Self {
|
||||||
|
history,
|
||||||
|
history_index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn load(&mut self, filename: &str) -> Result<()> {
|
||||||
|
let d = BaseDirectories::with_prefix("taskwarrior-tui")?;
|
||||||
|
if let Some(path) = d.find_config_file(filename) {
|
||||||
|
self.history.load(&path)?;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let path = d.place_config_file(filename)?;
|
||||||
|
self.history.save(&path)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn write(&mut self, filename: &str) -> Result<()> {
|
||||||
|
let d = BaseDirectories::with_prefix("taskwarrior-tui")?;
|
||||||
|
if let Some(path) = d.find_config_file(filename) {
|
||||||
|
self.history.save(&path)?;
|
||||||
|
Ok(())
|
||||||
|
} else {
|
||||||
|
let path = d.place_config_file(filename)?;
|
||||||
|
self.history.save(&path)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn history(&self) -> &History {
|
||||||
|
&self.history
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn history_index(&self) -> usize {
|
||||||
|
self.history_index
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn history_search(&mut self, buf: &str, dir: Direction) -> Option<String> {
|
||||||
|
if self.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
|
||||||
|
{
|
||||||
|
return Some(self.history.get(self.history_index).unwrap().clone());
|
||||||
|
}
|
||||||
|
let history_index = match dir {
|
||||||
|
Direction::Reverse => self.history_index - 1,
|
||||||
|
Direction::Forward => self.history_index + 1,
|
||||||
|
};
|
||||||
|
if let Some(history_index) = self.history.starts_with(buf, history_index, dir) {
|
||||||
|
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 {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add(&mut self, buf: &str) {
|
||||||
|
if self.history.add(buf) {
|
||||||
|
self.history_index = self.history.len() - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn last(&mut self) {
|
||||||
|
self.history_index = self.history.len().saturating_sub(1);
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@ mod calendar;
|
||||||
mod config;
|
mod config;
|
||||||
mod context;
|
mod context;
|
||||||
mod help;
|
mod help;
|
||||||
|
mod history;
|
||||||
mod keyconfig;
|
mod keyconfig;
|
||||||
mod table;
|
mod table;
|
||||||
mod task_report;
|
mod task_report;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue