mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-09-03 16:17:19 +02:00
Merge branch 'develop' into feature/sync-feedback
This commit is contained in:
commit
e2305e703d
117 changed files with 1995 additions and 861 deletions
1
.dockerignore
Normal file
1
.dockerignore
Normal file
|
@ -0,0 +1 @@
|
|||
target
|
5
.github/dependabot.yml
vendored
5
.github/dependabot.yml
vendored
|
@ -5,6 +5,11 @@ updates:
|
|||
directory: "/"
|
||||
schedule:
|
||||
interval: "weekly"
|
||||
# Enable version updates for git submodules
|
||||
- package-ecosystem: "gitsubmodule"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
# Enable updates for Rust packages
|
||||
- package-ecosystem: "cargo"
|
||||
directory: "/" # Location of package manifests
|
||||
|
|
46
.github/workflows/checks.yml
vendored
46
.github/workflows/checks.yml
vendored
|
@ -15,25 +15,25 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
id: toolchain
|
||||
with:
|
||||
# If this version is old enough to cause errors, or older than the
|
||||
# TaskChampion MSRV, bump it to the MSRV of the currently-required
|
||||
# TaskChampion package; if necessary, bump that version as well.
|
||||
toolchain: "1.81.0" # MSRV
|
||||
override: true
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
|
@ -53,12 +53,11 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
id: toolchain
|
||||
with:
|
||||
profile: minimal
|
||||
components: rustfmt
|
||||
toolchain: stable
|
||||
override: true
|
||||
toolchain: "stable"
|
||||
components: "rustfmt"
|
||||
|
||||
- uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
|
@ -71,12 +70,11 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
id: toolchain
|
||||
with:
|
||||
profile: minimal
|
||||
components: rustfmt
|
||||
toolchain: stable
|
||||
override: true
|
||||
toolchain: "stable"
|
||||
components: "rustfmt"
|
||||
|
||||
- name: "Check metadata"
|
||||
run: ".github/workflows/metadata-check.sh"
|
||||
|
|
6
.github/workflows/docker-image.yaml
vendored
6
.github/workflows/docker-image.yaml
vendored
|
@ -33,10 +33,10 @@ jobs:
|
|||
submodules: "recursive"
|
||||
|
||||
- name: Install cosign
|
||||
uses: sigstore/cosign-installer@v3.7.0
|
||||
uses: sigstore/cosign-installer@v3.8.2
|
||||
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
uses: docker/login-action@v3.3.0
|
||||
uses: docker/login-action@v3.4.0
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.repository_owner }}
|
||||
|
@ -44,7 +44,7 @@ jobs:
|
|||
|
||||
- name: Build and push Taskwarrior Docker image
|
||||
id: build-and-push
|
||||
uses: docker/build-push-action@v6.11.0
|
||||
uses: docker/build-push-action@v6.16.0
|
||||
with:
|
||||
context: .
|
||||
file: "./docker/task.dockerfile"
|
||||
|
|
10
.github/workflows/release-check.yaml
vendored
10
.github/workflows/release-check.yaml
vendored
|
@ -6,16 +6,14 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
id: toolchain
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: "stable"
|
||||
override: true
|
||||
key: ${{ runner.os }}-cargo-registry-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Install uuid-dev
|
||||
run: sudo apt install uuid-dev
|
||||
|
|
45
.github/workflows/tests.yaml
vendored
45
.github/workflows/tests.yaml
vendored
|
@ -43,22 +43,20 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
id: toolchain
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-stable-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: ${{ runner.os }}-cargo-registry-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-stable-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: "stable"
|
||||
override: true
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Test MacOS
|
||||
run: bash test/scripts/test_macos.sh
|
||||
|
@ -72,22 +70,20 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
id: toolchain
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-stable-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: ${{ runner.os }}-cargo-registry-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-stable-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: "stable"
|
||||
override: true
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Test MacOS
|
||||
run: bash test/scripts/test_macos.sh
|
||||
|
@ -101,26 +97,25 @@ jobs:
|
|||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: dtolnay/rust-toolchain@master
|
||||
id: toolchain
|
||||
with:
|
||||
# If this version is old enough to cause errors, or older than the
|
||||
# TaskChampion MSRV, bump it to the MSRV of the currently-required
|
||||
# TaskChampion package; if necessary, bump that version as well.
|
||||
toolchain: "1.81.0" # MSRV
|
||||
|
||||
- name: Cache cargo registry
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.cargo/registry
|
||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
|
||||
key: ${{ runner.os }}-cargo-registry-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- name: Cache cargo build
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: target
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
# If this version is old enough to cause errors, or older than the
|
||||
# TaskChampion MSRV, bump it to the MSRV of the currently-required
|
||||
# TaskChampion package; if necessary, bump that version as well.
|
||||
# This should match the MSRV in `src/taskchampion-cpp/Cargo.toml`.
|
||||
toolchain: "1.81.0" # MSRV
|
||||
override: true
|
||||
key: ${{ runner.os }}-cargo-build-target-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||
|
||||
- uses: actions-rs/cargo@v1.0.3
|
||||
with:
|
||||
|
|
|
@ -9,11 +9,11 @@ repos:
|
|||
- id: check-yaml
|
||||
- id: check-added-large-files
|
||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||
rev: v19.1.6
|
||||
rev: v20.1.3
|
||||
hooks:
|
||||
- id: clang-format
|
||||
types_or: [c++, c]
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 24.10.0
|
||||
rev: 25.1.0
|
||||
hooks:
|
||||
- id: black
|
||||
|
|
|
@ -4,7 +4,7 @@ enable_testing()
|
|||
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
project (task
|
||||
VERSION 3.3.0
|
||||
VERSION 3.4.1
|
||||
DESCRIPTION "Taskwarrior - a command-line TODO list manager"
|
||||
HOMEPAGE_URL https://taskwarrior.org/)
|
||||
|
||||
|
@ -162,6 +162,6 @@ endforeach (doc_FILE)
|
|||
|
||||
set (CPACK_SOURCE_GENERATOR "TGZ")
|
||||
set (CPACK_SOURCE_PACKAGE_FILE_NAME ${PACKAGE_NAME}-${PACKAGE_VERSION})
|
||||
set (CPACK_SOURCE_IGNORE_FILES "build" "test" "misc/*" "performance" "swp$" "src/lex$" "task-.*.tar.gz"
|
||||
set (CPACK_SOURCE_IGNORE_FILES "build" "target" "test" "misc/*" "performance" "swp$" "src/lex$" "task-.*.tar.gz"
|
||||
"commit.h" "cmake.h$" "\\\\.gitmodules" "src/libshared/\\\\.git" ".github/" ".*\\\\.gitignore$" "docker-compose.yml" "\\\\.git/")
|
||||
include (CPack)
|
||||
|
|
1
CONTRIBUTING.md
Symbolic link
1
CONTRIBUTING.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
doc/devel/contrib/development.md
|
1161
Cargo.lock
generated
1161
Cargo.lock
generated
File diff suppressed because it is too large
Load diff
31
ChangeLog
31
ChangeLog
|
@ -1,11 +1,36 @@
|
|||
------ current release ---------------------------
|
||||
|
||||
3.4.1 -
|
||||
|
||||
- The nagging to read `task news` has been fixed.
|
||||
|
||||
------ old releases ------------------------------
|
||||
|
||||
3.4.0 -
|
||||
|
||||
- Where possible, the task DB is now opened in read-only mode, which improves
|
||||
performance. This is the case for reports (task lists) only when the `gc`
|
||||
config is false.
|
||||
- An updated version of corrosion fixes build errors trying to find the Rust
|
||||
toolchain.
|
||||
|
||||
Thanks to the following people for contributions to this release:
|
||||
|
||||
- Dustin J. Mitchell
|
||||
- Kalle Kietäväinen
|
||||
- Karl
|
||||
- Matthew
|
||||
- Tejada-Omar
|
||||
- Tobias Predel
|
||||
- Yong Li
|
||||
- jrmarino
|
||||
|
||||
3.3.0 -
|
||||
|
||||
- Sync now supports AWS S3 as a backend.
|
||||
- A new `task import-v2` command allows importing Taskwarrior-2.x
|
||||
data files directly.
|
||||
|
||||
3.3.0 -
|
||||
|
||||
Thanks to the following people for contributions to this release:
|
||||
|
||||
- Chongyun Lee
|
||||
|
@ -18,8 +43,6 @@ Thanks to the following people for contributions to this release:
|
|||
- Scott Mcdermott
|
||||
- Thomas Lauf
|
||||
|
||||
------ old releases ------------------------------
|
||||
|
||||
3.2.0 -
|
||||
|
||||
- Support for the journal in `task info` has been restored (#3671) and the
|
||||
|
|
9
INSTALL
9
INSTALL
|
@ -34,7 +34,7 @@ Briefly, these shell commands will unpack, build and install Taskwarrior:
|
|||
$ cmake -S . -B build -DCMAKE_BUILD_TYPE=Release . [3]
|
||||
$ cmake --build build [4]
|
||||
$ sudo cmake --install build [5]
|
||||
$ cd .. ; rm -r task-X.Y.Z [6]
|
||||
$ cd .. ; rm -r task-X.Y.Z [6] (see: Uninstallation)
|
||||
|
||||
These commands are explained below:
|
||||
|
||||
|
@ -103,6 +103,13 @@ There is no uninstall option in CMake makefiles. This is a manual process.
|
|||
To uninstall Taskwarrior, remove the files listed in the install_manifest.txt
|
||||
file that was generated when you built Taskwarrior.
|
||||
|
||||
```sh
|
||||
cd task-X.Y.Z
|
||||
sudo xargs rm < build/install_manifest.txt
|
||||
```
|
||||
|
||||
If you want to uninstall this way, you will need to omit step [6] above and
|
||||
retain the source folder after installation.
|
||||
|
||||
Taskwarrior Build Notes
|
||||
-----------------------
|
||||
|
|
1
RELEASING.md
Symbolic link
1
RELEASING.md
Symbolic link
|
@ -0,0 +1 @@
|
|||
doc/devel/contrib/releasing.md
|
|
@ -24,3 +24,6 @@ To release Taskwarrior, follow this process:
|
|||
- Add a new item in `content/news`
|
||||
- Update `data/projects.json` with the latest version and a fake next version for "devel"
|
||||
- Update `data/releases.json` with the new version, and copy the tarball into `content/download`.
|
||||
- Update various things, in a new PR:
|
||||
- `cargo update`
|
||||
- `git submodule update --remote --merge`
|
||||
|
|
|
@ -25,7 +25,7 @@ In brief: "MUST" (or "REQUIRED") means that the item is an absolute requirement
|
|||
|
||||
## General Format
|
||||
|
||||
The format is JSON, specifically a JSON object as a single line of text, terminated by a newline (U+000D).
|
||||
The format is JSON, specifically a JSON object as a single line of text, terminated by a line feed (U+000A).
|
||||
|
||||
The JSON looks like this:
|
||||
|
||||
|
|
|
@ -143,7 +143,9 @@ Then configure Taskwarrior with:
|
|||
|
||||
To synchronize your tasks to AWS, select a region near you and use the AWS
|
||||
console to create a new S3 bucket. The default settings for the bucket are
|
||||
adequate.
|
||||
adequate. In particular, ensure that no lifecycle policies are enabled, as they
|
||||
may automatically delete or transition objects, potentially impacting data
|
||||
availability.
|
||||
|
||||
You will also need an AWS IAM user with the following policy, where BUCKETNAME
|
||||
is the name of the bucket. The same user can be configured for multiple
|
||||
|
|
|
@ -1037,7 +1037,7 @@ modifier requires that the attribute contain the whole word specified, such
|
|||
that this:
|
||||
|
||||
.nf
|
||||
task description.word:bar list
|
||||
task description.word:foo list
|
||||
.fi
|
||||
|
||||
Will match the description 'foo bar baz' but does not match 'dog food'.
|
||||
|
|
|
@ -212,6 +212,9 @@ This is a path to the hook scripts directory. By default it is ~/.task/hooks.
|
|||
.TP
|
||||
.B gc=1
|
||||
Can be used to temporarily suspend rebuilding, so that task IDs don't change.
|
||||
Rebuilding requires read/write access to the database, so disabling `gc` may
|
||||
result in better performance.
|
||||
|
||||
Note that this should be used in the form of a command line override (task
|
||||
rc.gc=0 ...), and not permanently used in the .taskrc file, as this
|
||||
significantly affects performance in the long term.
|
||||
|
@ -1381,7 +1384,7 @@ if you define a UDA named 'estimate', Taskwarrior will not know that this value
|
|||
is weeks, hours, minutes, money, or some other resource count.
|
||||
|
||||
.TP
|
||||
.B uda.<name>.type=string|numeric|date|duration
|
||||
.B uda.<name>.type=string|numeric|uuid|date|duration
|
||||
.RS
|
||||
Defines a UDA called '<name>', of the specified type.
|
||||
.RE
|
||||
|
|
|
@ -6,20 +6,20 @@ include_directories (${CMAKE_SOURCE_DIR}
|
|||
${CMAKE_SOURCE_DIR}/src/libshared/src
|
||||
${TASK_INCLUDE_DIRS})
|
||||
|
||||
add_library (task STATIC CLI2.cpp CLI2.h
|
||||
Context.cpp Context.h
|
||||
DOM.cpp DOM.h
|
||||
Eval.cpp Eval.h
|
||||
Filter.cpp Filter.h
|
||||
Hooks.cpp Hooks.h
|
||||
Lexer.cpp Lexer.h
|
||||
Operation.cpp Operation.h
|
||||
TF2.cpp TF2.h
|
||||
TDB2.cpp TDB2.h
|
||||
Task.cpp Task.h
|
||||
Variant.cpp Variant.h
|
||||
Version.cpp Version.h
|
||||
ViewTask.cpp ViewTask.h
|
||||
add_library (task STATIC CLI2.cpp
|
||||
Context.cpp
|
||||
DOM.cpp
|
||||
Eval.cpp
|
||||
Filter.cpp
|
||||
Hooks.cpp
|
||||
Lexer.cpp
|
||||
Operation.cpp
|
||||
TF2.cpp
|
||||
TDB2.cpp
|
||||
Task.cpp
|
||||
Variant.cpp
|
||||
Version.cpp
|
||||
ViewTask.cpp
|
||||
dependency.cpp
|
||||
feedback.cpp
|
||||
legacy.cpp
|
||||
|
@ -27,26 +27,25 @@ add_library (task STATIC CLI2.cpp CLI2.h
|
|||
recur.cpp
|
||||
rules.cpp
|
||||
sort.cpp
|
||||
util.cpp util.h)
|
||||
util.cpp)
|
||||
target_link_libraries(task taskchampion-cpp)
|
||||
|
||||
add_library (libshared STATIC libshared/src/Color.cpp libshared/src/Color.h
|
||||
libshared/src/Configuration.cpp libshared/src/Configuration.h
|
||||
libshared/src/Datetime.cpp libshared/src/Datetime.h
|
||||
libshared/src/Duration.cpp libshared/src/Duration.h
|
||||
libshared/src/FS.cpp libshared/src/FS.h
|
||||
libshared/src/JSON.cpp libshared/src/JSON.h
|
||||
libshared/src/Msg.cpp libshared/src/Msg.h
|
||||
libshared/src/Pig.cpp libshared/src/Pig.h
|
||||
libshared/src/RX.cpp libshared/src/RX.h
|
||||
libshared/src/Table.cpp libshared/src/Table.h
|
||||
libshared/src/Timer.cpp libshared/src/Timer.h
|
||||
libshared/src/format.cpp libshared/src/format.h
|
||||
add_library (libshared STATIC libshared/src/Color.cpp
|
||||
libshared/src/Configuration.cpp
|
||||
libshared/src/Datetime.cpp
|
||||
libshared/src/Duration.cpp
|
||||
libshared/src/FS.cpp
|
||||
libshared/src/JSON.cpp
|
||||
libshared/src/Msg.cpp
|
||||
libshared/src/Pig.cpp
|
||||
libshared/src/RX.cpp
|
||||
libshared/src/Table.cpp
|
||||
libshared/src/Timer.cpp
|
||||
libshared/src/format.cpp
|
||||
libshared/src/ip.cpp
|
||||
libshared/src/shared.cpp libshared/src/shared.h
|
||||
libshared/src/unicode.cpp libshared/src/unicode.h
|
||||
libshared/src/utf8.cpp libshared/src/utf8.h
|
||||
libshared/src/wcwidth.h)
|
||||
libshared/src/shared.cpp
|
||||
libshared/src/unicode.cpp
|
||||
libshared/src/utf8.cpp)
|
||||
|
||||
add_executable (task_executable main.cpp)
|
||||
add_executable (calc_executable calc.cpp)
|
||||
|
|
|
@ -36,16 +36,15 @@
|
|||
#include <Version.h>
|
||||
#include <assert.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <recur.h>
|
||||
#include <rules.h>
|
||||
#include <rust/cxx.h>
|
||||
#include <shared.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <taskchampion-cpp/lib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
|
@ -55,7 +54,6 @@
|
|||
#include <commit.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#ifdef SOLARIS
|
||||
|
@ -598,9 +596,6 @@ int Context::initialize(int argc, const char** argv) {
|
|||
|
||||
createDefaultConfig();
|
||||
|
||||
bool create_if_missing = !config.getBoolean("exit.on.missing.db");
|
||||
tdb2.open_replica(data_dir, create_if_missing);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [3] Instantiate Command objects and capture command entities.
|
||||
|
@ -674,6 +669,21 @@ int Context::initialize(int argc, const char** argv) {
|
|||
if (foundAssumed) header("No command specified - assuming 'information'.");
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [7.5] Open the Replica.
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool create_if_missing = !config.getBoolean("exit.on.missing.db");
|
||||
Command* c = commands[cli2.getCommand()];
|
||||
|
||||
// We must allow writes if either 'gc' is enabled and the command performs GC, or the command
|
||||
// itself is read-write.
|
||||
bool read_write =
|
||||
(config.getBoolean("gc") && (c->needs_gc() || c->needs_recur_update())) || !c->read_only();
|
||||
tdb2.open_replica(data_dir, create_if_missing, read_write);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// [8] Initialize hooks.
|
||||
|
@ -869,7 +879,7 @@ int Context::dispatch(std::string& out) {
|
|||
if (config.getBoolean("debug") && config.getInteger("debug.parser") == 1)
|
||||
debug(cli2.dump("Parse Tree (before command-specifіc processing)"));
|
||||
|
||||
if (c->needs_recur_update()) {
|
||||
if (c->needs_recur_update() && Context::getContext().config.getBoolean("gc")) {
|
||||
handleUntil();
|
||||
handleRecurrence();
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <Task.h>
|
||||
#include <format.h>
|
||||
#include <shared.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <map>
|
||||
|
||||
|
|
|
@ -36,8 +36,6 @@
|
|||
#include <format.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Take an input set of tasks and filter into a subset.
|
||||
void Filter::subset(const std::vector<Task>& input, std::vector<Task>& output) {
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <Task.h>
|
||||
#include <Variant.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Filter {
|
||||
|
|
|
@ -44,7 +44,6 @@
|
|||
#include <Variant.h>
|
||||
#include <format.h>
|
||||
#include <shared.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
@ -276,7 +275,7 @@ void Hooks::onAdd(Task& task) const {
|
|||
// - all emitted non-JSON lines are considered feedback or error messages
|
||||
// depending on the status code.
|
||||
//
|
||||
void Hooks::onModify(const Task& before, Task& after) const {
|
||||
void Hooks::onModify(Task& before, Task& after) const {
|
||||
if (!_enabled) return;
|
||||
|
||||
Timer timer;
|
||||
|
|
|
@ -40,7 +40,7 @@ class Hooks {
|
|||
void onLaunch() const;
|
||||
void onExit() const;
|
||||
void onAdd(Task&) const;
|
||||
void onModify(const Task&, Task&) const;
|
||||
void onModify(Task&, Task&) const;
|
||||
std::vector<std::string> list() const;
|
||||
|
||||
private:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2024, Tomas Babej, Paul Beckingham, Federico Hernandez.
|
||||
// Copyright 2006 - 2025, Tomas Babej, Paul Beckingham, Federico Hernandez,
|
||||
// Tobias Predel.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
|
@ -24,8 +25,8 @@
|
|||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_OPERATIOn
|
||||
#define INCLUDED_OPERATIOn
|
||||
#ifndef INCLUDED_OPERATION
|
||||
#define INCLUDED_OPERATION
|
||||
|
||||
#include <taskchampion-cpp/lib.h>
|
||||
|
||||
|
|
26
src/TDB2.cpp
26
src/TDB2.cpp
|
@ -33,16 +33,11 @@
|
|||
#include <TDB2.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
|
@ -50,17 +45,16 @@ bool TDB2::debug_mode = false;
|
|||
static void dependency_scan(std::vector<Task>&);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB2::open_replica(const std::string& location, bool create_if_missing) {
|
||||
_replica = tc::new_replica_on_disk(location, create_if_missing);
|
||||
void TDB2::open_replica(const std::string& location, bool create_if_missing, bool read_write) {
|
||||
_replica = tc::new_replica_on_disk(location, create_if_missing, read_write);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void TDB2::open_replica_in_memory() { _replica = tc::new_replica_in_memory(); }
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Add the new task to the replica.
|
||||
void TDB2::add(Task& task) {
|
||||
// Validate a task for addition. This is stricter than `task.validate`, as any
|
||||
// inconsistency is probably user error.
|
||||
task.validate_add();
|
||||
|
||||
// Ensure the task is consistent, and provide defaults if necessary.
|
||||
// bool argument to validate() is "applyDefault", to apply default values for
|
||||
// properties not otherwise given.
|
||||
|
@ -194,11 +188,8 @@ void TDB2::purge(Task& task) {
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
rust::Box<tc::Replica>& TDB2::replica() {
|
||||
// Create a replica in-memory if `open_replica` has not been called. This
|
||||
// occurs in tests.
|
||||
if (!_replica) {
|
||||
_replica = tc::new_replica_in_memory();
|
||||
}
|
||||
// One of the open_replica_ methods must be called before this one.
|
||||
assert(_replica);
|
||||
return _replica.value();
|
||||
}
|
||||
|
||||
|
@ -363,8 +354,7 @@ bool TDB2::get(const std::string& uuid, Task& task) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Locate task by UUID, wherever it is.
|
||||
bool TDB2::has(const std::string& uuid) {
|
||||
Task task;
|
||||
return get(uuid, task);
|
||||
return replica()->get_task_data(tc::uuid_from_string(uuid)).is_some();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -27,9 +27,7 @@
|
|||
#ifndef INCLUDED_TDB2
|
||||
#define INCLUDED_TDB2
|
||||
|
||||
#include <FS.h>
|
||||
#include <Task.h>
|
||||
#include <stdio.h>
|
||||
#include <taskchampion-cpp/lib.h>
|
||||
|
||||
#include <map>
|
||||
|
@ -46,7 +44,8 @@ class TDB2 {
|
|||
|
||||
TDB2() = default;
|
||||
|
||||
void open_replica(const std::string &, bool create_if_missing);
|
||||
void open_replica(const std::string &, bool create_if_missing, bool read_write);
|
||||
void open_replica_in_memory();
|
||||
void add(Task &);
|
||||
void modify(Task &);
|
||||
void purge(Task &);
|
||||
|
|
12
src/TF2.cpp
12
src/TF2.cpp
|
@ -31,18 +31,12 @@
|
|||
#include <Table.h>
|
||||
#include <cmake.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#ifdef PRODUCT_TASKWARRIOR
|
||||
#include <legacy.h>
|
||||
#endif
|
||||
#include <shared.h>
|
||||
#include <signal.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <sstream>
|
||||
|
||||
#define STRING_TDB2_REVERTED "Modified task reverted."
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -29,12 +29,9 @@
|
|||
|
||||
#include <FS.h>
|
||||
#include <Task.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
// TF2 Class represents a single 2.x-style file in the task database.
|
||||
|
|
38
src/Task.cpp
38
src/Task.cpp
|
@ -58,7 +58,8 @@
|
|||
#include <Eval.h>
|
||||
#include <Filter.h>
|
||||
#include <Variant.h>
|
||||
#include <main.h>
|
||||
#include <dependency.h>
|
||||
#include <feedback.h>
|
||||
|
||||
#define APPROACHING_INFINITY 1000 // Close enough. This isn't rocket surgery.
|
||||
|
||||
|
@ -321,8 +322,8 @@ void Task::setStatus(Task::status status) {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Determines status of a date attribute.
|
||||
Task::dateState Task::getDateState(const std::string& name) const {
|
||||
std::string value = get(name);
|
||||
if (value.length()) {
|
||||
time_t value = get_date(name);
|
||||
if (value > 0) {
|
||||
Datetime reference(value);
|
||||
Datetime now;
|
||||
Datetime today("today");
|
||||
|
@ -776,7 +777,7 @@ void Task::parseLegacy(const std::string& line) {
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string Task::composeJSON(bool decorate /*= false*/) const {
|
||||
std::string Task::composeJSON(bool decorate /*= false*/) {
|
||||
std::stringstream out;
|
||||
out << '{';
|
||||
|
||||
|
@ -797,20 +798,23 @@ std::string Task::composeJSON(bool decorate /*= false*/) const {
|
|||
// If value is an empty string, do not ever output it
|
||||
if (i.second == "") continue;
|
||||
|
||||
if (attributes_written) out << ',';
|
||||
|
||||
std::string type = Task::attributes[i.first];
|
||||
if (type == "") type = "string";
|
||||
|
||||
// Date fields are written as ISO 8601.
|
||||
if (type == "date") {
|
||||
Datetime d(i.second);
|
||||
out << '"' << (i.first == "modification" ? "modified" : i.first)
|
||||
<< "\":\""
|
||||
// Date was deleted, do not export parsed empty string
|
||||
<< (i.second == "" ? "" : d.toISO()) << '"';
|
||||
time_t epoch = get_date(i.first);
|
||||
if (epoch != 0) {
|
||||
Datetime d(i.second);
|
||||
if (attributes_written) out << ',';
|
||||
|
||||
++attributes_written;
|
||||
out << '"' << (i.first == "modification" ? "modified" : i.first)
|
||||
<< "\":\""
|
||||
// Date was deleted, do not export parsed empty string
|
||||
<< (i.second == "" ? "" : d.toISO()) << '"';
|
||||
|
||||
++attributes_written;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -820,6 +824,8 @@ std::string Task::composeJSON(bool decorate /*= false*/) const {
|
|||
}
|
||||
*/
|
||||
else if (type == "numeric") {
|
||||
if (attributes_written) out << ',';
|
||||
|
||||
out << '"' << i.first << "\":" << i.second;
|
||||
|
||||
++attributes_written;
|
||||
|
@ -827,6 +833,8 @@ std::string Task::composeJSON(bool decorate /*= false*/) const {
|
|||
|
||||
// Everything else is a quoted value.
|
||||
else {
|
||||
if (attributes_written) out << ',';
|
||||
|
||||
out << '"' << i.first << "\":\"" << (type == "string" ? json::encode(i.second) : i.second)
|
||||
<< '"';
|
||||
|
||||
|
@ -886,7 +894,7 @@ std::string Task::composeJSON(bool decorate /*= false*/) const {
|
|||
|
||||
#ifdef PRODUCT_TASKWARRIOR
|
||||
// Include urgency.
|
||||
if (decorate) out << ',' << "\"urgency\":" << urgency_c();
|
||||
if (decorate) out << ',' << "\"urgency\":" << urgency();
|
||||
#endif
|
||||
|
||||
out << '}';
|
||||
|
@ -920,7 +928,7 @@ void Task::addAnnotation(const std::string& description) {
|
|||
++now;
|
||||
} while (has(key));
|
||||
|
||||
data[key] = json::decode(description);
|
||||
data[key] = description;
|
||||
++annotation_count;
|
||||
recalc_urgency = true;
|
||||
}
|
||||
|
@ -1991,7 +1999,7 @@ void Task::modify(modType type, bool text_required /* = false */) {
|
|||
// Delegate modification to the column object or their base classes.
|
||||
if (name == "depends" || name == "tags" || name == "recur" || column->type() == "date" ||
|
||||
column->type() == "duration" || column->type() == "numeric" ||
|
||||
column->type() == "string") {
|
||||
column->type() == "string" || column->type() == "uuid") {
|
||||
column->modify(*this, value);
|
||||
mods = true;
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <Datetime.h>
|
||||
#include <JSON.h>
|
||||
#include <Table.h>
|
||||
#include <stdio.h>
|
||||
#include <taskchampion-cpp/lib.h>
|
||||
#include <time.h>
|
||||
|
||||
|
@ -69,7 +68,7 @@ class Task {
|
|||
Task(rust::Box<tc::TaskData>);
|
||||
|
||||
void parse(const std::string&);
|
||||
std::string composeJSON(bool decorate = false) const;
|
||||
std::string composeJSON(bool decorate = false);
|
||||
|
||||
// Status values.
|
||||
enum status { pending, completed, deleted, recurring, waiting };
|
||||
|
|
|
@ -75,7 +75,6 @@
|
|||
#define STRING_VARIANT_DIV_DUR_BOOL "Cannot divide duration by Boolean"
|
||||
#define STRING_VARIANT_DIV_DUR_STR "Cannot divide durations by strings"
|
||||
#define STRING_VARIANT_DIV_DUR_DATE "Cannot divide durations by dates"
|
||||
#define STRING_VARIANT_DIV_DUR_DUR "Cannot divide durations by durations"
|
||||
#define STRING_VARIANT_MOD_BOOL "Cannot modulo Booleans"
|
||||
#define STRING_VARIANT_MOD_DATE "Cannot modulo date values"
|
||||
#define STRING_VARIANT_MOD_DUR "Cannot modulo duration values"
|
||||
|
@ -1760,7 +1759,9 @@ Variant& Variant::operator/=(const Variant& other) {
|
|||
throw std::string(STRING_VARIANT_DIV_DUR_DATE);
|
||||
|
||||
case type_duration:
|
||||
throw std::string(STRING_VARIANT_DIV_DUR_DUR);
|
||||
_type = type_real;
|
||||
_real = static_cast<double>(_duration) / static_cast<double>(right._duration);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@
|
|||
#define INCLUDED_VARIANT
|
||||
|
||||
#include <Task.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
class Variant {
|
||||
|
|
|
@ -30,7 +30,7 @@
|
|||
#include <Context.h>
|
||||
#include <ViewTask.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <rules.h>
|
||||
#include <utf8.h>
|
||||
#include <util.h>
|
||||
|
||||
|
|
|
@ -30,13 +30,10 @@
|
|||
#include <ColDepends.h>
|
||||
#include <Context.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <stdlib.h>
|
||||
#include <utf8.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <regex>
|
||||
|
||||
#define STRING_COLUMN_LABEL_DEP "Depends"
|
||||
|
|
|
@ -32,8 +32,8 @@
|
|||
#include <Eval.h>
|
||||
#include <Filter.h>
|
||||
#include <Variant.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <utf8.h>
|
||||
|
||||
|
|
|
@ -56,11 +56,9 @@ void ColumnTypeDuration::modify(Task& task, const std::string& value) {
|
|||
evaluatedValue = Variant(value);
|
||||
}
|
||||
|
||||
// The duration is stored in raw form, but it must still be valid,
|
||||
// and therefore is parsed first.
|
||||
// The duration is first parsed, then stored inside the variant as a `time_t`
|
||||
std::string label = " [1;37;43mMODIFICATION[0m ";
|
||||
if (evaluatedValue.type() == Variant::type_duration) {
|
||||
// Store the raw value, for 'recur'.
|
||||
Context::getContext().debug(label + _name + " <-- " + (std::string)evaluatedValue + " <-- '" +
|
||||
value + '\'');
|
||||
task.set(_name, evaluatedValue);
|
||||
|
|
|
@ -297,3 +297,23 @@ void ColumnUDADuration::render(std::vector<std::string>& lines, Task& task, int
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
ColumnUDAUUID::ColumnUDAUUID() {
|
||||
_name = "<uda>";
|
||||
_type = "uuid";
|
||||
_style = "long";
|
||||
_label = "";
|
||||
_modifiable = true;
|
||||
_uda = true;
|
||||
_styles = {"long", "short"};
|
||||
_examples = {"f30cb9c3-3fc0-483f-bfb2-3bf134f00694", "f30cb9c3"};
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
bool ColumnUDAUUID::validate(const std::string& input) const {
|
||||
Lexer lex(input);
|
||||
std::string token;
|
||||
Lexer::Type type;
|
||||
return lex.isUUID(token, type, true);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <ColTypeDuration.h>
|
||||
#include <ColTypeNumeric.h>
|
||||
#include <ColTypeString.h>
|
||||
#include <ColUUID.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class ColumnUDAString : public ColumnTypeString {
|
||||
|
@ -83,5 +84,12 @@ class ColumnUDADuration : public ColumnTypeDuration {
|
|||
std::vector<std::string> _values;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
class ColumnUDAUUID : public ColumnUUID {
|
||||
public:
|
||||
ColumnUDAUUID();
|
||||
bool validate(const std::string&) const;
|
||||
};
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -246,9 +246,15 @@ Column* Column::uda(const std::string& name) {
|
|||
c->_label = label;
|
||||
if (values != "") c->_values = split(values, ',');
|
||||
return c;
|
||||
} else if (type == "uuid") {
|
||||
auto c = new ColumnUDAUUID();
|
||||
c->_name = name;
|
||||
c->_label = label;
|
||||
return c;
|
||||
} else if (type != "")
|
||||
throw std::string(
|
||||
"User defined attributes may only be of type 'string', 'date', 'duration' or 'numeric'.");
|
||||
"User defined attributes may only be of type 'string', 'uuid', date', 'duration' or "
|
||||
"'numeric'.");
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
|
||||
#include <CmdAdd.h>
|
||||
#include <Context.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CmdAdd::CmdAdd() {
|
||||
|
@ -56,6 +56,11 @@ int CmdAdd::execute(std::string& output) {
|
|||
// the task is empty, but DOM references can refer to earlier parts of the
|
||||
// command line, e.g., `task add due:20110101 wait:due`.
|
||||
task.modify(Task::modReplace, true);
|
||||
|
||||
// Validate a task for addition. This is stricter than `task.validate`, as any
|
||||
// inconsistency is probably user error.
|
||||
task.validate_add();
|
||||
|
||||
Context::getContext().tdb2.add(task);
|
||||
|
||||
// Do not display ID 0, users cannot query by that
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#include <CmdAnnotate.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#include <CmdAppend.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <Duration.h>
|
||||
#include <Filter.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <math.h>
|
||||
#include <shared.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <Lexer.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <stdlib.h>
|
||||
#include <utf8.h>
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <Context.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <Color.h>
|
||||
#include <Context.h>
|
||||
#include <Table.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <util.h>
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
#include <Filter.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <rules.h>
|
||||
#include <shared.h>
|
||||
#include <util.h>
|
||||
|
||||
|
@ -218,8 +218,8 @@ void CmdContext::defineContext(const std::vector<std::string>& words, std::strin
|
|||
if (!valid_write_context) {
|
||||
std::stringstream warning;
|
||||
warning
|
||||
<< format("The filter '{1}' is not a valid modification string, because it contains {2}.",
|
||||
value, reason)
|
||||
<< format("The filter '{1}' is not a valid modification string, because it {2}.", value,
|
||||
reason)
|
||||
<< "\nAs such, value for the write context cannot be set (context will not apply on task "
|
||||
"add / task log).\n\n"
|
||||
<< format(
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <CmdCount.h>
|
||||
#include <Filter.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CmdCount::CmdCount() {
|
||||
|
|
|
@ -34,15 +34,15 @@
|
|||
#include <Lexer.h>
|
||||
#include <Version.h>
|
||||
#include <ViewTask.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <legacy.h>
|
||||
#include <shared.h>
|
||||
#include <stdlib.h>
|
||||
#include <sort.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
|
|
|
@ -30,8 +30,10 @@
|
|||
#include <CmdDelete.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <dependency.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <recur.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#include <CmdDenotate.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <util.h>
|
||||
|
||||
|
|
|
@ -30,8 +30,11 @@
|
|||
#include <CmdDone.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <dependency.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <nag.h>
|
||||
#include <recur.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#include <CmdDuplicate.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
#include <Lexer.h>
|
||||
#include <Pig.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
@ -64,7 +63,7 @@ CmdEdit::CmdEdit() {
|
|||
_read_only = false;
|
||||
_displays_id = false;
|
||||
_needs_gc = false;
|
||||
_needs_recur_update = false;
|
||||
_needs_recur_update = true;
|
||||
_uses_context = true;
|
||||
_accepts_filter = true;
|
||||
_accepts_modifications = false;
|
||||
|
@ -78,8 +77,6 @@ CmdEdit::CmdEdit() {
|
|||
// wrench. To be used sparingly.
|
||||
int CmdEdit::execute(std::string&) {
|
||||
// Filter the tasks.
|
||||
handleUntil();
|
||||
handleRecurrence();
|
||||
Filter filter;
|
||||
std::vector<Task> filtered;
|
||||
filter.subset(filtered);
|
||||
|
|
|
@ -31,8 +31,9 @@
|
|||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <legacy.h>
|
||||
#include <shared.h>
|
||||
#include <sort.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CmdExport::CmdExport() {
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <DOM.h>
|
||||
#include <Variant.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <Filter.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <sstream>
|
||||
|
@ -55,7 +54,7 @@ CmdHistoryBase<HistoryStrategy>::CmdHistoryBase() {
|
|||
_read_only = true;
|
||||
_displays_id = false;
|
||||
_needs_gc = false;
|
||||
_needs_recur_update = false;
|
||||
_needs_recur_update = true;
|
||||
_uses_context = true;
|
||||
_accepts_filter = true;
|
||||
_accepts_modifications = false;
|
||||
|
@ -294,8 +293,6 @@ int CmdHistoryBase<HistoryStrategy>::execute(std::string& output) {
|
|||
completedGroup.clear();
|
||||
|
||||
// Apply filter.
|
||||
handleUntil();
|
||||
handleRecurrence();
|
||||
Filter filter;
|
||||
std::vector<Task> filtered;
|
||||
filter.subset(filtered);
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
#include <CmdIDs.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
@ -137,8 +136,6 @@ CmdCompletionIds::CmdCompletionIds() {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdCompletionIds::execute(std::string& output) {
|
||||
// Apply filter.
|
||||
handleUntil();
|
||||
handleRecurrence();
|
||||
Filter filter;
|
||||
std::vector<Task> filtered;
|
||||
filter.subset(filtered);
|
||||
|
@ -174,8 +171,6 @@ CmdZshCompletionIds::CmdZshCompletionIds() {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdZshCompletionIds::execute(std::string& output) {
|
||||
// Apply filter.
|
||||
handleUntil();
|
||||
handleRecurrence();
|
||||
Filter filter;
|
||||
std::vector<Task> filtered;
|
||||
filter.subset(filtered);
|
||||
|
@ -211,8 +206,6 @@ CmdUUIDs::CmdUUIDs() {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdUUIDs::execute(std::string& output) {
|
||||
// Apply filter.
|
||||
handleUntil();
|
||||
handleRecurrence();
|
||||
Filter filter;
|
||||
std::vector<Task> filtered;
|
||||
filter.subset(filtered);
|
||||
|
@ -247,8 +240,6 @@ CmdCompletionUuids::CmdCompletionUuids() {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdCompletionUuids::execute(std::string& output) {
|
||||
// Apply filter.
|
||||
handleUntil();
|
||||
handleRecurrence();
|
||||
Filter filter;
|
||||
std::vector<Task> filtered;
|
||||
filter.subset(filtered);
|
||||
|
@ -283,8 +274,6 @@ CmdZshCompletionUuids::CmdZshCompletionUuids() {
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdZshCompletionUuids::execute(std::string& output) {
|
||||
// Apply filter.
|
||||
handleUntil();
|
||||
handleRecurrence();
|
||||
Filter filter;
|
||||
std::vector<Task> filtered;
|
||||
filter.subset(filtered);
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <JSON.h>
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class CmdImportV2 : public Command {
|
||||
public:
|
||||
|
|
|
@ -34,9 +34,9 @@
|
|||
#include <Filter.h>
|
||||
#include <Lexer.h>
|
||||
#include <Operation.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <math.h>
|
||||
#include <rules.h>
|
||||
#include <shared.h>
|
||||
#include <stdlib.h>
|
||||
#include <taskchampion-cpp/lib.h>
|
||||
|
@ -120,9 +120,11 @@ int CmdInfo::execute(std::string& output) {
|
|||
description += '\n' + std::string(indent, ' ') +
|
||||
Datetime(anno.first.substr(11)).toString(dateformatanno) + ' ' + anno.second;
|
||||
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Description");
|
||||
view.set(row, 1, description, c);
|
||||
if (task.has("description")) {
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Description");
|
||||
view.set(row, 1, description, c);
|
||||
}
|
||||
|
||||
// status
|
||||
row = view.addRow();
|
||||
|
@ -215,64 +217,76 @@ int CmdInfo::execute(std::string& output) {
|
|||
}
|
||||
|
||||
// entry
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Entered");
|
||||
Datetime dt(task.get_date("entry"));
|
||||
std::string entry = dt.toString(dateformat);
|
||||
if (task.has("entry") && task.get_date("entry")) {
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Entered");
|
||||
Datetime dt(task.get_date("entry"));
|
||||
std::string entry = dt.toString(dateformat);
|
||||
|
||||
std::string age;
|
||||
auto created = task.get("entry");
|
||||
if (created.length()) {
|
||||
Datetime dt(strtoll(created.c_str(), nullptr, 10));
|
||||
age = Duration(now - dt).formatVague();
|
||||
std::string age;
|
||||
auto created = task.get("entry");
|
||||
if (created.length()) {
|
||||
Datetime dt(strtoll(created.c_str(), nullptr, 10));
|
||||
age = Duration(now - dt).formatVague();
|
||||
}
|
||||
|
||||
view.set(row, 1, entry + " (" + age + ')');
|
||||
}
|
||||
|
||||
view.set(row, 1, entry + " (" + age + ')');
|
||||
auto validDate = [&](const char* prop) {
|
||||
if (!task.has(prop)) {
|
||||
return false;
|
||||
}
|
||||
if (task.get_date(prop) == 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// wait
|
||||
if (task.has("wait")) {
|
||||
if (validDate("wait")) {
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Waiting until");
|
||||
view.set(row, 1, Datetime(task.get_date("wait")).toString(dateformat));
|
||||
}
|
||||
|
||||
// scheduled
|
||||
if (task.has("scheduled")) {
|
||||
if (validDate("scheduled")) {
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Scheduled");
|
||||
view.set(row, 1, Datetime(task.get_date("scheduled")).toString(dateformat));
|
||||
}
|
||||
|
||||
// start
|
||||
if (task.has("start")) {
|
||||
if (validDate("start")) {
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Start");
|
||||
view.set(row, 1, Datetime(task.get_date("start")).toString(dateformat));
|
||||
}
|
||||
|
||||
// due (colored)
|
||||
if (task.has("due")) {
|
||||
if (validDate("due")) {
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Due");
|
||||
view.set(row, 1, Datetime(task.get_date("due")).toString(dateformat));
|
||||
}
|
||||
|
||||
// end
|
||||
if (task.has("end")) {
|
||||
if (validDate("end")) {
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "End");
|
||||
view.set(row, 1, Datetime(task.get_date("end")).toString(dateformat));
|
||||
}
|
||||
|
||||
// until
|
||||
if (task.has("until")) {
|
||||
if (validDate("until")) {
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Until");
|
||||
view.set(row, 1, Datetime(task.get_date("until")).toString(dateformat));
|
||||
}
|
||||
|
||||
// modified
|
||||
if (task.has("modified")) {
|
||||
if (validDate("modified")) {
|
||||
row = view.addRow();
|
||||
view.set(row, 0, "Last modified");
|
||||
|
||||
|
@ -632,7 +646,11 @@ std::optional<std::string> CmdInfo::formatForInfo(const std::vector<Operation>&
|
|||
} else {
|
||||
// Record the last start time for later duration calculation.
|
||||
if (prop == "start") {
|
||||
last_start = Datetime(value.value()).toEpoch();
|
||||
try {
|
||||
last_start = Datetime(value.value()).toEpoch();
|
||||
} catch (std::string) {
|
||||
// ignore invalid dates
|
||||
}
|
||||
}
|
||||
|
||||
out << format("{1} set to '{2}'.", Lexer::ucFirst(prop),
|
||||
|
|
|
@ -29,8 +29,8 @@
|
|||
|
||||
#include <CmdLog.h>
|
||||
#include <Context.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CmdLog::CmdLog() {
|
||||
|
|
|
@ -30,8 +30,9 @@
|
|||
#include <CmdModify.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <recur.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <iostream>
|
||||
|
@ -119,7 +120,7 @@ void CmdModify::checkConsistency(Task &before, Task &after) {
|
|||
throw std::string("You cannot remove the recurrence from a recurring task.");
|
||||
|
||||
if ((before.getStatus() == Task::pending) && (after.getStatus() == Task::pending) &&
|
||||
(after.get("end") != ""))
|
||||
(before.get("end") == "") && (after.get("end") != ""))
|
||||
throw format("Could not modify task {1}. You cannot set an end date on a pending task.",
|
||||
before.identifier(true));
|
||||
}
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <Duration.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <util.h>
|
||||
|
||||
|
@ -161,6 +160,7 @@ std::vector<NewsItem> NewsItem::all() {
|
|||
version3_1_0(items);
|
||||
version3_2_0(items);
|
||||
version3_3_0(items);
|
||||
version3_4_0(items);
|
||||
return items;
|
||||
}
|
||||
|
||||
|
@ -531,6 +531,21 @@ void NewsItem::version3_3_0(std::vector<NewsItem>& items) {
|
|||
items.push_back(info);
|
||||
}
|
||||
|
||||
void NewsItem::version3_4_0(std::vector<NewsItem>& items) {
|
||||
Version version("3.4.0");
|
||||
NewsItem info{version,
|
||||
/*title=*/"Read-Only Access",
|
||||
/*bg_title=*/"",
|
||||
/*background=*/"",
|
||||
/*punchline=*/"Some Taskwarrior commands operate faster in read-only mode",
|
||||
/*update=*/
|
||||
"Some commands do not need to write to the DB, so can open it in read-only\n"
|
||||
"mode and thus more quickly. This does not include reports (task lists),\n"
|
||||
"unless the `gc` config is false. Use `rc.gc=0` in command-lines to allow\n"
|
||||
"read-only access.\n\n"};
|
||||
items.push_back(info);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
int CmdNews::execute(std::string& output) {
|
||||
auto words = Context::getContext().cli2.getWords();
|
||||
|
@ -573,61 +588,10 @@ int CmdNews::execute(std::string& output) {
|
|||
}
|
||||
wait_for_enter();
|
||||
|
||||
// Display outro
|
||||
Datetime now;
|
||||
Datetime beginning(2006, 11, 29);
|
||||
Duration development_time = Duration(now - beginning);
|
||||
|
||||
Color underline = Color("underline");
|
||||
|
||||
std::stringstream outro;
|
||||
outro << underline.colorize(bold.colorize("Taskwarrior crowdfunding\n"));
|
||||
outro << format(
|
||||
"Taskwarrior has been in development for {1} years but its survival\n"
|
||||
"depends on your support!\n\n"
|
||||
"Please consider joining our {2} fundraiser to help us fund maintenance\n"
|
||||
"and development of new features:\n\n",
|
||||
std::lround(static_cast<float>(development_time.days()) / 365.25), now.year());
|
||||
outro << bold.colorize(" https://github.com/sponsors/GothenburgBitFactory/\n\n");
|
||||
outro << "Perks are available for our sponsors.\n";
|
||||
|
||||
std::cout << outro.str();
|
||||
|
||||
// Set a mark in the config to remember which version's release notes were displayed
|
||||
if (news_version < current_version) {
|
||||
CmdConfig::setConfigVariable("news.version", std::string(current_version), false);
|
||||
|
||||
// Revert back to default signal handling after displaying the outro
|
||||
signal(SIGINT, SIG_DFL);
|
||||
|
||||
std::string question = format(
|
||||
"\nWould you like to open Taskwarrior {1} fundraising campaign to read more?", now.year());
|
||||
|
||||
std::vector<std::string> options{"yes", "no"};
|
||||
std::vector<std::string> matches;
|
||||
|
||||
std::cout << question << " (YES/no) ";
|
||||
|
||||
std::string answer;
|
||||
std::getline(std::cin, answer);
|
||||
|
||||
if (std::cin.eof() || trim(answer).empty())
|
||||
answer = "yes";
|
||||
else
|
||||
lowerCase(trim(answer));
|
||||
|
||||
autoComplete(answer, options, matches, 1); // Hard-coded 1.
|
||||
|
||||
if (matches.size() == 1 && matches[0] == "yes")
|
||||
#if defined(DARWIN)
|
||||
system("open 'https://github.com/sponsors/GothenburgBitFactory/'");
|
||||
#else
|
||||
system("xdg-open 'https://github.com/sponsors/GothenburgBitFactory/'");
|
||||
#endif
|
||||
|
||||
std::cout << std::endl;
|
||||
} else
|
||||
wait_for_enter(); // Do not display the outro and footnote at once
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@ class NewsItem {
|
|||
static void version3_1_0(std::vector<NewsItem>&);
|
||||
static void version3_2_0(std::vector<NewsItem>&);
|
||||
static void version3_3_0(std::vector<NewsItem>&);
|
||||
static void version3_4_0(std::vector<NewsItem>&);
|
||||
|
||||
private:
|
||||
NewsItem(Version, const std::string&, const std::string& = "", const std::string& = "",
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#include <CmdPrepend.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
|
@ -32,10 +32,9 @@
|
|||
#include <Filter.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <sort.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
#include <CmdPurge.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -32,7 +32,7 @@
|
|||
#include <FS.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <legacy.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
|
|
@ -30,8 +30,11 @@
|
|||
#include <CmdStart.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <dependency.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <nag.h>
|
||||
#include <recur.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <Filter.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h>
|
||||
|
||||
|
|
|
@ -30,8 +30,10 @@
|
|||
#include <CmdStop.h>
|
||||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <dependency.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <recur.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
|
|
@ -33,11 +33,10 @@
|
|||
#include <Filter.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <sort.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <sstream>
|
||||
|
||||
|
|
|
@ -32,13 +32,11 @@
|
|||
#include <Context.h>
|
||||
#include <Filter.h>
|
||||
#include <format.h>
|
||||
#include <inttypes.h>
|
||||
#include <shared.h>
|
||||
#include <signal.h>
|
||||
#include <taskchampion-cpp/lib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <regex>
|
||||
#include <sstream>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -81,6 +79,10 @@ int CmdSync::execute(std::string& output) {
|
|||
out << "sync.server.origin is deprecated. Use sync.server.url instead.\n";
|
||||
}
|
||||
|
||||
// redact credentials from `server_url`, if present
|
||||
std::regex remove_creds_regex("^(https?://.+):(.+)@(.+)");
|
||||
std::string safe_server_url = std::regex_replace(server_url, remove_creds_regex, "$1:****@$3");
|
||||
|
||||
if (server_dir != "") {
|
||||
if (verbose) {
|
||||
out << format("Syncing with {1}", server_dir) << '\n';
|
||||
|
@ -149,7 +151,7 @@ int CmdSync::execute(std::string& output) {
|
|||
throw std::string("sync.server.client_id and sync.encryption_secret are required");
|
||||
}
|
||||
if (verbose) {
|
||||
out << format("Syncing with sync server at {1}", server_url) << '\n';
|
||||
out << format("Syncing with sync server at {1}", safe_server_url) << '\n';
|
||||
}
|
||||
replica->sync_to_remote(server_url, tc::uuid_from_string(client_id), encryption_secret,
|
||||
avoid_snapshots);
|
||||
|
|
|
@ -32,7 +32,6 @@
|
|||
#include <Filter.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <sstream>
|
||||
|
|
|
@ -33,8 +33,7 @@
|
|||
#include <Filter.h>
|
||||
#include <Table.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <stdlib.h>
|
||||
#include <rules.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
#include <Table.h>
|
||||
#include <Task.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <util.h>
|
||||
|
||||
|
|
|
@ -31,12 +31,11 @@
|
|||
#include <Context.h>
|
||||
#include <Operation.h>
|
||||
#include <Task.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
#include "shared.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
CmdUndo::CmdUndo() {
|
||||
_keyword = "undo";
|
||||
|
|
|
@ -32,8 +32,6 @@
|
|||
#include <Filter.h>
|
||||
#include <Lexer.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sstream>
|
||||
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
#include <Context.h>
|
||||
#include <Datetime.h>
|
||||
#include <Table.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <sstream>
|
||||
#ifdef HAVE_COMMIT
|
||||
|
|
|
@ -50,9 +50,7 @@
|
|||
#include <CmdEdit.h>
|
||||
#include <Command.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <stdlib.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <iostream>
|
||||
|
|
|
@ -31,7 +31,6 @@
|
|||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class Command {
|
||||
public:
|
||||
|
|
|
@ -28,13 +28,11 @@
|
|||
// cmake.h include header must come first
|
||||
|
||||
#include <Context.h>
|
||||
#include <dependency.h>
|
||||
#include <format.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <stack>
|
||||
|
||||
#define STRING_DEPEND_BLOCKED "Task {1} is blocked by:"
|
||||
|
|
43
src/dependency.h
Normal file
43
src/dependency.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2025, Tomas Babej, Paul Beckingham, Federico Hernandez,
|
||||
// Tobias Predel.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// https://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_DEPENDENCY
|
||||
#define INCLUDED_DEPENDENCY
|
||||
|
||||
#include <cmake.h>
|
||||
// cmake.h include header must come first
|
||||
|
||||
#include <Task.h>
|
||||
|
||||
#define STRING_DEPEND_BLOCKED "Task {1} is blocked by:"
|
||||
bool dependencyIsCircular(const Task& task);
|
||||
void dependencyChainOnComplete(Task& task);
|
||||
void dependencyChainOnStart(Task& task);
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -31,13 +31,11 @@
|
|||
#include <Datetime.h>
|
||||
#include <Duration.h>
|
||||
#include <Lexer.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <inttypes.h>
|
||||
#include <main.h>
|
||||
#include <shared.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <string>
|
||||
|
@ -51,7 +49,12 @@ std::string renderAttribute(const std::string& name, const std::string& value,
|
|||
if (Context::getContext().columns.find(name) != Context::getContext().columns.end()) {
|
||||
Column* col = Context::getContext().columns[name];
|
||||
if (col && col->type() == "date" && value != "") {
|
||||
Datetime d((time_t)strtoll(value.c_str(), nullptr, 10));
|
||||
int64_t epoch = strtoll(value.c_str(), nullptr, 10);
|
||||
// Do not try to render an un-parseable value.
|
||||
if (epoch == 0) {
|
||||
return value;
|
||||
}
|
||||
Datetime d((time_t)epoch);
|
||||
if (format == "") return d.toString(Context::getContext().config.get("dateformat"));
|
||||
|
||||
return d.toString(format);
|
||||
|
|
54
src/feedback.h
Normal file
54
src/feedback.h
Normal file
|
@ -0,0 +1,54 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2025, Tomas Babej, Paul Beckingham, Federico Hernandez,
|
||||
// Tobias Predel.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// https://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_FEEDBACK
|
||||
#define INCLUDED_FEEDBACK
|
||||
|
||||
#include <cmake.h>
|
||||
// cmake.h include header must come first
|
||||
|
||||
#include <Task.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
std::string renderAttribute(const std::string& name, const std::string& value,
|
||||
const std::string& format = "");
|
||||
void feedback_affected(const std::string& effect);
|
||||
void feedback_affected(const std::string& effect, int quantity);
|
||||
void feedback_affected(const std::string& effect, const Task& task);
|
||||
void feedback_reserved_tags(const std::string& tag);
|
||||
void feedback_special_tags(const Task& task, const std::string& tag);
|
||||
void feedback_unblocked(const Task& task);
|
||||
void feedback_backlog();
|
||||
std::string onProjectChange(Task& task, bool scope = true);
|
||||
std::string onProjectChange(Task& task1, Task& task2);
|
||||
std::string onExpiration(Task& task);
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -30,7 +30,6 @@
|
|||
#include <Context.h>
|
||||
#include <format.h>
|
||||
|
||||
#include <cstddef>
|
||||
#include <sstream>
|
||||
|
||||
#define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'."
|
||||
|
|
44
src/legacy.h
Normal file
44
src/legacy.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2025, Tomas Babej, Paul Beckingham, Federico Hernandez,
|
||||
// Tobias Predel.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// https://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_LEGACY
|
||||
#define INCLUDED_LEGACY
|
||||
|
||||
#include <cmake.h>
|
||||
// cmake.h include header must come first
|
||||
|
||||
#include <string>
|
||||
|
||||
void legacyColumnMap(std::string& name);
|
||||
void legacySortColumnMap(std::string& name);
|
||||
std::string legacyCheckForDeprecatedVariables();
|
||||
std::string legacyCheckForDeprecatedColumns();
|
||||
void legacyAttributeMap(std::string& name);
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -1 +1 @@
|
|||
Subproject commit 1a06cb4caebdae3c5e58fe83e2fd2211d2959815
|
||||
Subproject commit 8ad3646209c8d2e7820c3cd59319a2be3b3d221e
|
94
src/main.h
94
src/main.h
|
@ -1,94 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2021, Tomas Babej, Paul Beckingham, Federico Hernandez.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// https://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_MAIN
|
||||
#define INCLUDED_MAIN
|
||||
|
||||
#include <Color.h>
|
||||
#include <Context.h>
|
||||
#include <Datetime.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
// recur.cpp
|
||||
void handleRecurrence();
|
||||
void handleUntil();
|
||||
std::optional<Datetime> checked_add_datetime(Datetime& base, time_t delta);
|
||||
std::optional<Datetime> getNextRecurrence(Datetime&, std::string&);
|
||||
bool generateDueDates(Task&, std::vector<Datetime>&);
|
||||
void updateRecurrenceMask(Task&);
|
||||
|
||||
// nag.cpp
|
||||
void nag(std::vector<Task>&);
|
||||
|
||||
// rules.cpp
|
||||
void initializeColorRules();
|
||||
void autoColorize(Task&, Color&);
|
||||
std::string colorizeHeader(const std::string&);
|
||||
std::string colorizeFootnote(const std::string&);
|
||||
std::string colorizeError(const std::string&);
|
||||
std::string colorizeDebug(const std::string&);
|
||||
|
||||
// dependency.cpp
|
||||
bool dependencyIsCircular(const Task&);
|
||||
void dependencyChainOnComplete(Task&);
|
||||
void dependencyChainOnStart(Task&);
|
||||
|
||||
// feedback.cpp
|
||||
std::string renderAttribute(const std::string&, const std::string&, const std::string& format = "");
|
||||
void feedback_affected(const std::string&);
|
||||
void feedback_affected(const std::string&, int);
|
||||
void feedback_affected(const std::string&, const Task&);
|
||||
void feedback_reserved_tags(const std::string&);
|
||||
void feedback_special_tags(const Task&, const std::string&);
|
||||
void feedback_unblocked(const Task&);
|
||||
void feedback_backlog();
|
||||
std::string onProjectChange(Task&, bool scope = true);
|
||||
std::string onProjectChange(Task&, Task&);
|
||||
std::string onExpiration(Task&);
|
||||
|
||||
// sort.cpp
|
||||
void sort_tasks(std::vector<Task>&, std::vector<int>&, const std::string&);
|
||||
void sort_projects(std::list<std::pair<std::string, int>>& sorted,
|
||||
std::map<std::string, int>& allProjects);
|
||||
void sort_projects(std::list<std::pair<std::string, int>>& sorted,
|
||||
std::map<std::string, bool>& allProjects);
|
||||
|
||||
// legacy.cpp
|
||||
void legacyColumnMap(std::string&);
|
||||
void legacySortColumnMap(std::string&);
|
||||
std::string legacyCheckForDeprecatedVariables();
|
||||
std::string legacyCheckForDeprecatedColumns();
|
||||
void legacyAttributeMap(std::string&);
|
||||
|
||||
#endif
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -25,15 +25,9 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <cmake.h>
|
||||
|
||||
#include <algorithm>
|
||||
// cmake.h include header must come first
|
||||
|
||||
#include <Context.h>
|
||||
|
||||
#include <iterator>
|
||||
#include <unordered_set>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
43
src/nag.h
Normal file
43
src/nag.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2025, Tomas Babej, Paul Beckingham, Federico Hernandez,
|
||||
// Tobias Predel.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// https://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_NAG
|
||||
#define INCLUDED_NAG
|
||||
|
||||
#include <cmake.h>
|
||||
// cmake.h include header must come first
|
||||
#include <Task.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Generates a nag message when there are READY tasks of a higher urgency.
|
||||
void nag(std::vector<Task>& tasks);
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -31,25 +31,19 @@
|
|||
#include <Datetime.h>
|
||||
#include <Duration.h>
|
||||
#include <Lexer.h>
|
||||
#include <feedback.h>
|
||||
#include <format.h>
|
||||
#include <inttypes.h>
|
||||
#include <main.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <recur.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unicode.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
#include <optional>
|
||||
#include <sstream>
|
||||
|
||||
// Add a `time_t` delta to a Datetime, checking for and returning nullopt on integer overflow.
|
||||
std::optional<Datetime> checked_add_datetime(Datetime& base, time_t delta) {
|
||||
|
@ -288,9 +282,11 @@ std::optional<Datetime> getNextRecurrence(Datetime& current, std::string& period
|
|||
else if (unicodeLatinDigit(period[0]) && period[period.length() - 1] == 'q') {
|
||||
int increment = strtol(period.substr(0, period.length() - 1).c_str(), nullptr, 10);
|
||||
|
||||
if (increment <= 0)
|
||||
throw format("Recurrence period '{1}' is equivalent to {2} and hence invalid.", period,
|
||||
increment);
|
||||
if (increment <= 0) {
|
||||
Context::getContext().footnote(format(
|
||||
"Recurrence period '{1}' is equivalent to {2} and hence invalid.", period, increment));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
m += 3 * increment;
|
||||
while (m > 12) {
|
||||
|
@ -346,8 +342,11 @@ std::optional<Datetime> getNextRecurrence(Datetime& current, std::string& period
|
|||
// Add the period to current, and we're done.
|
||||
std::string::size_type idx = 0;
|
||||
Duration p;
|
||||
if (!p.parse(period, idx))
|
||||
throw std::string(format("The recurrence value '{1}' is not valid.", period));
|
||||
if (!p.parse(period, idx)) {
|
||||
Context::getContext().footnote(
|
||||
format("Warning: The recurrence value '{1}' is not valid.", period));
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return checked_add_datetime(current, p.toTime_t());
|
||||
}
|
||||
|
|
57
src/recur.h
Normal file
57
src/recur.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2025, Tomas Babej, Paul Beckingham, Federico Hernandez,
|
||||
// Tobias Predel.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// https://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_RECUR
|
||||
#define INCLUDED_RECUR
|
||||
|
||||
#include <cmake.h>
|
||||
// cmake.h include header must come first
|
||||
|
||||
#include <Context.h>
|
||||
#include <Datetime.h>
|
||||
#include <Duration.h>
|
||||
#include <Lexer.h>
|
||||
#include <format.h>
|
||||
#include <pwd.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <unicode.h>
|
||||
#include <unistd.h>
|
||||
#include <util.h>
|
||||
|
||||
#include <optional>
|
||||
|
||||
std::optional<Datetime> checked_add_datetime(Datetime& base, time_t delta);
|
||||
void handleRecurrence();
|
||||
bool generateDueDates(Task& parent, std::vector<Datetime>& allDue);
|
||||
std::optional<Datetime> getNextRecurrence(Datetime& current, std::string& period);
|
||||
void updateRecurrenceMask(Task& task);
|
||||
void handleUntil();
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -29,9 +29,8 @@
|
|||
|
||||
#include <Context.h>
|
||||
#include <Datetime.h>
|
||||
#include <main.h>
|
||||
#include <rules.h>
|
||||
#include <shared.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
static std::map<std::string, Color> gsColor;
|
||||
static std::vector<std::string> gsPrecedence;
|
||||
|
|
47
src/rules.h
Normal file
47
src/rules.h
Normal file
|
@ -0,0 +1,47 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2025, Tomas Babej, Paul Beckingham, Federico Hernandez,
|
||||
// Tobias Predel.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// https://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_RULES
|
||||
#define INCLUDED_RULES
|
||||
|
||||
#include <cmake.h>
|
||||
// cmake.h include header must come first
|
||||
|
||||
#include <Context.h>
|
||||
#include <Datetime.h>
|
||||
#include <shared.h>
|
||||
|
||||
void initializeColorRules();
|
||||
void autoColorize(Task& task, Color& c);
|
||||
std::string colorizeHeader(const std::string& input);
|
||||
std::string colorizeFootnote(const std::string& input);
|
||||
std::string colorizeError(const std::string& input);
|
||||
std::string colorizeDebug(const std::string& input);
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
51
src/sort.h
Normal file
51
src/sort.h
Normal file
|
@ -0,0 +1,51 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Copyright 2006 - 2025, Tomas Babej, Paul Beckingham, Federico Hernandez,
|
||||
// Tobias Predel.
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included
|
||||
// in all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
//
|
||||
// https://www.opensource.org/licenses/mit-license.php
|
||||
//
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifndef INCLUDED_SORT
|
||||
#define INCLUDED_SORT
|
||||
|
||||
#include <cmake.h>
|
||||
// cmake.h include header must come first
|
||||
|
||||
#include <Task.h>
|
||||
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
void sort_tasks(std::vector<Task>& data, std::vector<int>& order, const std::string& keys);
|
||||
|
||||
void sort_projects(std::list<std::pair<std::string, int>>& sorted,
|
||||
std::map<std::string, int>& allProjects);
|
||||
|
||||
void sort_projects(std::list<std::pair<std::string, int>>& sorted,
|
||||
std::map<std::string, bool>& allProjects);
|
||||
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
|
@ -1 +1 @@
|
|||
Subproject commit 64289b1d79d6d19cd2e241db515381a086bb8407
|
||||
Subproject commit 715c235daef4b8ee67278f12256334ad3dd4c4ae
|
|
@ -104,8 +104,11 @@ mod ffi {
|
|||
fn new_replica_in_memory() -> Result<Box<Replica>>;
|
||||
|
||||
/// Create a new replica stored on-disk.
|
||||
fn new_replica_on_disk(taskdb_dir: String, create_if_missing: bool)
|
||||
-> Result<Box<Replica>>;
|
||||
fn new_replica_on_disk(
|
||||
taskdb_dir: String,
|
||||
create_if_missing: bool,
|
||||
read_write: bool,
|
||||
) -> Result<Box<Replica>>;
|
||||
|
||||
/// Commit the given operations to the replica.
|
||||
fn commit_operations(&mut self, ops: Vec<Operation>) -> Result<()>;
|
||||
|
@ -490,11 +493,14 @@ impl From<tc::Replica> for Replica {
|
|||
fn new_replica_on_disk(
|
||||
taskdb_dir: String,
|
||||
create_if_missing: bool,
|
||||
read_write: bool,
|
||||
) -> Result<Box<Replica>, CppError> {
|
||||
use tc::storage::AccessMode::*;
|
||||
let access_mode = if read_write { ReadWrite } else { ReadOnly };
|
||||
let storage = tc::StorageConfig::OnDisk {
|
||||
taskdb_dir: PathBuf::from(taskdb_dir),
|
||||
create_if_missing,
|
||||
access_mode: tc::storage::AccessMode::ReadWrite,
|
||||
access_mode,
|
||||
}
|
||||
.into_storage()?;
|
||||
Ok(Box::new(tc::Replica::new(storage).into()))
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue