mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-07-07 20:06:36 +02:00
commit
d923dc7bae
7 changed files with 71 additions and 26 deletions
|
@ -162,10 +162,22 @@ fn named_date<Tz: TimeZone>(
|
||||||
// TODO: lots more!
|
// TODO: lots more!
|
||||||
"eod" => Ok((remaining, local_today + Duration::days(1))),
|
"eod" => Ok((remaining, local_today + Duration::days(1))),
|
||||||
"sod" => Ok((remaining, local_today)),
|
"sod" => Ok((remaining, local_today)),
|
||||||
"eow" => Ok((remaining,local_today + Duration::days((6-day_index).into()))),
|
"eow" => Ok((
|
||||||
"eoww" => Ok((remaining,local_today + Duration::days((5-day_index).into()))),
|
remaining,
|
||||||
"sow" => Ok((remaining,local_today + Duration::days((6-day_index).into()))),
|
local_today + Duration::days((6 - day_index).into()),
|
||||||
"soww" => Ok((remaining,local_today + Duration::days((7-day_index).into()))),
|
)),
|
||||||
|
"eoww" => Ok((
|
||||||
|
remaining,
|
||||||
|
local_today + Duration::days((5 - day_index).into()),
|
||||||
|
)),
|
||||||
|
"sow" => Ok((
|
||||||
|
remaining,
|
||||||
|
local_today + Duration::days((6 - day_index).into()),
|
||||||
|
)),
|
||||||
|
"soww" => Ok((
|
||||||
|
remaining,
|
||||||
|
local_today + Duration::days((7 - day_index).into()),
|
||||||
|
)),
|
||||||
_ => Err(Err::Error(Error::new(input, ErrorKind::Tag))),
|
_ => Err(Err::Error(Error::new(input, ErrorKind::Tag))),
|
||||||
}
|
}
|
||||||
.map(|(rem, dt)| (rem, dt.and_hms(0, 0, 0).with_timezone(&Utc)))
|
.map(|(rem, dt)| (rem, dt.and_hms(0, 0, 0).with_timezone(&Utc)))
|
||||||
|
|
|
@ -3,16 +3,26 @@
|
||||||
|
|
||||||
This crate implements the core of TaskChampion, the [replica](crate::Replica).
|
This crate implements the core of TaskChampion, the [replica](crate::Replica).
|
||||||
|
|
||||||
|
Users of this crate can manipulate a task database using this API, including synchronizing that task database with others via a synchronization server.
|
||||||
|
|
||||||
|
Example uses of this crate:
|
||||||
|
* user interfaces for task management, such as mobile apps, web apps, or command-line interfaces
|
||||||
|
* integrations for task management, such as synchronization with ticket-tracking systems or
|
||||||
|
request forms.
|
||||||
|
|
||||||
# Replica
|
# Replica
|
||||||
|
|
||||||
A TaskChampion replica is a local copy of a user's task data. As the name suggests, several
|
A TaskChampion replica is a local copy of a user's task data. As the name suggests, several
|
||||||
replicas of the same data can exist (such as on a user's laptop and on their phone) and can
|
replicas of the same data can exist (such as on a user's laptop and on their phone) and can
|
||||||
synchronize with one another.
|
synchronize with one another.
|
||||||
|
|
||||||
Replicas are accessed using the [`Replica`](crate::replica) type.
|
Replicas are accessed using the [`Replica`](crate::Replica) type.
|
||||||
|
|
||||||
# Task Storage
|
# Task Storage
|
||||||
|
|
||||||
|
Replicas access the task database via a [storage object](crate::storage::Storage).
|
||||||
|
Create a storage object with [`StorageConfig`](crate::storage::StorageConfig).
|
||||||
|
|
||||||
The [`storage`](crate::storage) module supports pluggable storage for a replica's data.
|
The [`storage`](crate::storage) module supports pluggable storage for a replica's data.
|
||||||
An implementation is provided, but users of this crate can provide their own implementation as well.
|
An implementation is provided, but users of this crate can provide their own implementation as well.
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,10 @@ use uuid::Uuid;
|
||||||
/// ## Tasks
|
/// ## Tasks
|
||||||
///
|
///
|
||||||
/// Tasks are uniquely identified by UUIDs.
|
/// Tasks are uniquely identified by UUIDs.
|
||||||
/// Most task modifications are performed via the [`crate::Task`] and [`crate::TaskMut`] types.
|
/// Most task modifications are performed via the [`Task`](crate::Task) and
|
||||||
|
/// [`TaskMut`](crate::TaskMut) types. Use of two types for tasks allows easy
|
||||||
|
/// read-only manipulation of lots of tasks, with exclusive access required only
|
||||||
|
/// for modifications.
|
||||||
///
|
///
|
||||||
/// ## Working Set
|
/// ## Working Set
|
||||||
///
|
///
|
||||||
|
|
|
@ -113,9 +113,11 @@ impl<'t> Txn<'t> {
|
||||||
fn get_next_working_set_number(&self) -> anyhow::Result<usize> {
|
fn get_next_working_set_number(&self) -> anyhow::Result<usize> {
|
||||||
let t = self.get_txn()?;
|
let t = self.get_txn()?;
|
||||||
let next_id: Option<usize> = t
|
let next_id: Option<usize> = t
|
||||||
.query_row("SELECT COALESCE(MAX(id), 0) + 1 FROM working_set", [], |r| {
|
.query_row(
|
||||||
r.get(0)
|
"SELECT COALESCE(MAX(id), 0) + 1 FROM working_set",
|
||||||
})
|
[],
|
||||||
|
|r| r.get(0),
|
||||||
|
)
|
||||||
.optional()
|
.optional()
|
||||||
.context("Getting highest working set ID")?;
|
.context("Getting highest working set ID")?;
|
||||||
|
|
||||||
|
@ -290,7 +292,10 @@ impl<'t> StorageTxn for Txn<'t> {
|
||||||
|
|
||||||
let rows: Vec<Result<(usize, Uuid), _>> = rows.collect();
|
let rows: Vec<Result<(usize, Uuid), _>> = rows.collect();
|
||||||
let mut res = Vec::with_capacity(rows.len());
|
let mut res = Vec::with_capacity(rows.len());
|
||||||
for _ in 0..self.get_next_working_set_number().context("Getting working set number")? {
|
for _ in 0..self
|
||||||
|
.get_next_working_set_number()
|
||||||
|
.context("Getting working set number")?
|
||||||
|
{
|
||||||
res.push(None);
|
res.push(None);
|
||||||
}
|
}
|
||||||
for r in rows {
|
for r in rows {
|
||||||
|
|
|
@ -10,7 +10,7 @@ mod task;
|
||||||
pub use annotation::Annotation;
|
pub use annotation::Annotation;
|
||||||
pub use priority::Priority;
|
pub use priority::Priority;
|
||||||
pub use status::Status;
|
pub use status::Status;
|
||||||
pub use tag::{Tag, INVALID_TAG_CHARACTERS};
|
pub use tag::Tag;
|
||||||
pub use task::{Task, TaskMut};
|
pub use task::{Task, TaskMut};
|
||||||
|
|
||||||
pub type Timestamp = DateTime<Utc>;
|
pub type Timestamp = DateTime<Utc>;
|
||||||
|
|
|
@ -5,7 +5,7 @@ use std::str::FromStr;
|
||||||
/// A Tag is a descriptor for a task, that is either present or absent, and can be used for
|
/// A Tag is a descriptor for a task, that is either present or absent, and can be used for
|
||||||
/// filtering. Tags composed of all uppercase letters are reserved for synthetic tags.
|
/// filtering. Tags composed of all uppercase letters are reserved for synthetic tags.
|
||||||
///
|
///
|
||||||
/// Valid tags must not contain whitespace or any of the characters in [`INVALID_TAG_CHARACTERS`].
|
/// Valid tags must not contain whitespace or any of the characters in `+-*/(<>^! %=~`.
|
||||||
/// The first characters additionally cannot be a digit, and subsequent characters cannot be `:`.
|
/// The first characters additionally cannot be a digit, and subsequent characters cannot be `:`.
|
||||||
/// This definition is based on [that of
|
/// This definition is based on [that of
|
||||||
/// TaskWarrior](https://github.com/GothenburgBitFactory/taskwarrior/blob/663c6575ceca5bd0135ae884879339dac89d3142/src/Lexer.cpp#L146-L164).
|
/// TaskWarrior](https://github.com/GothenburgBitFactory/taskwarrior/blob/663c6575ceca5bd0135ae884879339dac89d3142/src/Lexer.cpp#L146-L164).
|
||||||
|
@ -19,6 +19,7 @@ pub(super) enum TagInner {
|
||||||
Synthetic(SyntheticTag),
|
Synthetic(SyntheticTag),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// see doc comment for Tag, above
|
||||||
pub const INVALID_TAG_CHARACTERS: &str = "+-*/(<>^! %=~";
|
pub const INVALID_TAG_CHARACTERS: &str = "+-*/(<>^! %=~";
|
||||||
|
|
||||||
impl Tag {
|
impl Tag {
|
||||||
|
|
|
@ -8,6 +8,16 @@ use std::convert::AsRef;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
/* The Task and TaskMut classes wrap the underlying [`TaskMap`], which is a simple key/value map.
|
||||||
|
* They provide semantic meaning to that TaskMap according to the TaskChampion data model. For
|
||||||
|
* example, [`get_status`](Task::get_status) and [`set_status`](TaskMut::set_status) translate from
|
||||||
|
* strings in the TaskMap to [`Status`].
|
||||||
|
*
|
||||||
|
* The same approach applies for more complex data such as dependencies or annotations. Users of
|
||||||
|
* this API should only need the [`get_taskmap`](Task::get_taskmap) method for debugging purposes,
|
||||||
|
* and should never need to make changes to the TaskMap directly.
|
||||||
|
*/
|
||||||
|
|
||||||
/// A task, as publicly exposed by this crate.
|
/// A task, as publicly exposed by this crate.
|
||||||
///
|
///
|
||||||
/// Note that Task objects represent a snapshot of the task at a moment in time, and are not
|
/// Note that Task objects represent a snapshot of the task at a moment in time, and are not
|
||||||
|
@ -15,16 +25,21 @@ use uuid::Uuid;
|
||||||
/// but a Task that is cached for more than a few seconds may cause the user to see stale
|
/// but a Task that is cached for more than a few seconds may cause the user to see stale
|
||||||
/// data. Fetch, use, and drop Tasks quickly.
|
/// data. Fetch, use, and drop Tasks quickly.
|
||||||
///
|
///
|
||||||
/// This struct contains only getters for various values on the task. The `into_mut` method returns
|
/// This struct contains only getters for various values on the task. The
|
||||||
/// a TaskMut which can be used to modify the task.
|
/// [`into_mut`](Task::into_mut) method
|
||||||
|
/// returns a TaskMut which can be used to modify the task.
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Task {
|
pub struct Task {
|
||||||
uuid: Uuid,
|
uuid: Uuid,
|
||||||
taskmap: TaskMap,
|
taskmap: TaskMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A mutable task, with setter methods. Most methods are simple setters and not further
|
/// A mutable task, with setter methods.
|
||||||
/// described. Calling a setter will update the Replica, as well as the included Task.
|
///
|
||||||
|
/// Most methods are simple setters and not further described. Calling a setter will update the
|
||||||
|
/// referenced Replica, as well as the included Task, immediately.
|
||||||
|
///
|
||||||
|
/// The [`Task`] methods are available on [`TaskMut`] via [`Deref`](std::ops::Deref).
|
||||||
pub struct TaskMut<'r> {
|
pub struct TaskMut<'r> {
|
||||||
task: Task,
|
task: Task,
|
||||||
replica: &'r mut Replica,
|
replica: &'r mut Replica,
|
||||||
|
@ -150,8 +165,7 @@ impl Task {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'r> TaskMut<'r> {
|
impl<'r> TaskMut<'r> {
|
||||||
/// Get the immutable version of this object. Note that TaskMut [`std::ops::Deref`]s to
|
/// Get the immutable version of this object, ending the exclusive reference to the Replica.
|
||||||
/// [`crate::task::Task`], so all of that struct's getter methods can be used on TaskMut.
|
|
||||||
pub fn into_immut(self) -> Task {
|
pub fn into_immut(self) -> Task {
|
||||||
self.task
|
self.task
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue