Merge pull request #288 from taskchampion/docs-update

Docs update
This commit is contained in:
Dustin J. Mitchell 2021-10-01 22:08:40 -04:00 committed by GitHub
commit d923dc7bae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 71 additions and 26 deletions

View file

@ -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)))

View file

@ -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.

View file

@ -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
/// ///

View file

@ -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 {

View file

@ -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>;

View file

@ -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 {

View file

@ -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
} }