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: "/"
|
directory: "/"
|
||||||
schedule:
|
schedule:
|
||||||
interval: "weekly"
|
interval: "weekly"
|
||||||
|
# Enable version updates for git submodules
|
||||||
|
- package-ecosystem: "gitsubmodule"
|
||||||
|
directory: "/"
|
||||||
|
schedule:
|
||||||
|
interval: "daily"
|
||||||
# Enable updates for Rust packages
|
# Enable updates for Rust packages
|
||||||
- package-ecosystem: "cargo"
|
- package-ecosystem: "cargo"
|
||||||
directory: "/" # Location of package manifests
|
directory: "/" # Location of package manifests
|
||||||
|
|
46
.github/workflows/checks.yml
vendored
46
.github/workflows/checks.yml
vendored
|
@ -15,25 +15,25 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Cache cargo registry
|
- uses: dtolnay/rust-toolchain@master
|
||||||
uses: actions/cache@v4
|
id: toolchain
|
||||||
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
|
|
||||||
with:
|
with:
|
||||||
# If this version is old enough to cause errors, or older than the
|
# 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 MSRV, bump it to the MSRV of the currently-required
|
||||||
# TaskChampion package; if necessary, bump that version as well.
|
# TaskChampion package; if necessary, bump that version as well.
|
||||||
toolchain: "1.81.0" # MSRV
|
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
|
- uses: actions-rs/cargo@v1.0.3
|
||||||
with:
|
with:
|
||||||
|
@ -53,12 +53,11 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: dtolnay/rust-toolchain@master
|
||||||
|
id: toolchain
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
toolchain: "stable"
|
||||||
components: rustfmt
|
components: "rustfmt"
|
||||||
toolchain: stable
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- uses: actions-rs/cargo@v1.0.3
|
- uses: actions-rs/cargo@v1.0.3
|
||||||
with:
|
with:
|
||||||
|
@ -71,12 +70,11 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: actions-rs/toolchain@v1
|
- uses: dtolnay/rust-toolchain@master
|
||||||
|
id: toolchain
|
||||||
with:
|
with:
|
||||||
profile: minimal
|
toolchain: "stable"
|
||||||
components: rustfmt
|
components: "rustfmt"
|
||||||
toolchain: stable
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: "Check metadata"
|
- name: "Check metadata"
|
||||||
run: ".github/workflows/metadata-check.sh"
|
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"
|
submodules: "recursive"
|
||||||
|
|
||||||
- name: Install cosign
|
- name: Install cosign
|
||||||
uses: sigstore/cosign-installer@v3.7.0
|
uses: sigstore/cosign-installer@v3.8.2
|
||||||
|
|
||||||
- name: Log into registry ${{ env.REGISTRY }}
|
- name: Log into registry ${{ env.REGISTRY }}
|
||||||
uses: docker/login-action@v3.3.0
|
uses: docker/login-action@v3.4.0
|
||||||
with:
|
with:
|
||||||
registry: ${{ env.REGISTRY }}
|
registry: ${{ env.REGISTRY }}
|
||||||
username: ${{ github.repository_owner }}
|
username: ${{ github.repository_owner }}
|
||||||
|
@ -44,7 +44,7 @@ jobs:
|
||||||
|
|
||||||
- name: Build and push Taskwarrior Docker image
|
- name: Build and push Taskwarrior Docker image
|
||||||
id: build-and-push
|
id: build-and-push
|
||||||
uses: docker/build-push-action@v6.11.0
|
uses: docker/build-push-action@v6.16.0
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
file: "./docker/task.dockerfile"
|
file: "./docker/task.dockerfile"
|
||||||
|
|
10
.github/workflows/release-check.yaml
vendored
10
.github/workflows/release-check.yaml
vendored
|
@ -6,16 +6,14 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
id: toolchain
|
||||||
|
|
||||||
- name: Cache cargo registry
|
- name: Cache cargo registry
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/registry
|
path: ~/.cargo/registry
|
||||||
key: ${{ runner.os }}-cargo-registry-${{ hashFiles('**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-registry-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
- uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: "stable"
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Install uuid-dev
|
- name: Install uuid-dev
|
||||||
run: sudo apt 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:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
id: toolchain
|
||||||
|
|
||||||
- name: Cache cargo registry
|
- name: Cache cargo registry
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/registry
|
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
|
- name: Cache cargo build
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: target
|
path: target
|
||||||
key: ${{ runner.os }}-stable-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-build-target-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
- uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: "stable"
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Test MacOS
|
- name: Test MacOS
|
||||||
run: bash test/scripts/test_macos.sh
|
run: bash test/scripts/test_macos.sh
|
||||||
|
@ -72,22 +70,20 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- uses: dtolnay/rust-toolchain@stable
|
||||||
|
id: toolchain
|
||||||
|
|
||||||
- name: Cache cargo registry
|
- name: Cache cargo registry
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/registry
|
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
|
- name: Cache cargo build
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: target
|
path: target
|
||||||
key: ${{ runner.os }}-stable-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-build-target-${{ steps.toolchain.outputs.cachekey }}-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
- uses: actions-rs/toolchain@v1
|
|
||||||
with:
|
|
||||||
toolchain: "stable"
|
|
||||||
override: true
|
|
||||||
|
|
||||||
- name: Test MacOS
|
- name: Test MacOS
|
||||||
run: bash test/scripts/test_macos.sh
|
run: bash test/scripts/test_macos.sh
|
||||||
|
@ -101,26 +97,25 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- 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
|
- name: Cache cargo registry
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: ~/.cargo/registry
|
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
|
- name: Cache cargo build
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: target
|
path: target
|
||||||
key: ${{ runner.os }}-cargo-build-target-${{ hashFiles('**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-build-target-${{ steps.toolchain.outputs.cachekey }}-${{ 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
|
|
||||||
|
|
||||||
- uses: actions-rs/cargo@v1.0.3
|
- uses: actions-rs/cargo@v1.0.3
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -9,11 +9,11 @@ repos:
|
||||||
- id: check-yaml
|
- id: check-yaml
|
||||||
- id: check-added-large-files
|
- id: check-added-large-files
|
||||||
- repo: https://github.com/pre-commit/mirrors-clang-format
|
- repo: https://github.com/pre-commit/mirrors-clang-format
|
||||||
rev: v19.1.6
|
rev: v20.1.3
|
||||||
hooks:
|
hooks:
|
||||||
- id: clang-format
|
- id: clang-format
|
||||||
types_or: [c++, c]
|
types_or: [c++, c]
|
||||||
- repo: https://github.com/psf/black
|
- repo: https://github.com/psf/black
|
||||||
rev: 24.10.0
|
rev: 25.1.0
|
||||||
hooks:
|
hooks:
|
||||||
- id: black
|
- id: black
|
||||||
|
|
|
@ -4,7 +4,7 @@ enable_testing()
|
||||||
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
set (CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||||
|
|
||||||
project (task
|
project (task
|
||||||
VERSION 3.3.0
|
VERSION 3.4.1
|
||||||
DESCRIPTION "Taskwarrior - a command-line TODO list manager"
|
DESCRIPTION "Taskwarrior - a command-line TODO list manager"
|
||||||
HOMEPAGE_URL https://taskwarrior.org/)
|
HOMEPAGE_URL https://taskwarrior.org/)
|
||||||
|
|
||||||
|
@ -162,6 +162,6 @@ endforeach (doc_FILE)
|
||||||
|
|
||||||
set (CPACK_SOURCE_GENERATOR "TGZ")
|
set (CPACK_SOURCE_GENERATOR "TGZ")
|
||||||
set (CPACK_SOURCE_PACKAGE_FILE_NAME ${PACKAGE_NAME}-${PACKAGE_VERSION})
|
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/")
|
"commit.h" "cmake.h$" "\\\\.gitmodules" "src/libshared/\\\\.git" ".github/" ".*\\\\.gitignore$" "docker-compose.yml" "\\\\.git/")
|
||||||
include (CPack)
|
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 ---------------------------
|
------ 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.
|
- Sync now supports AWS S3 as a backend.
|
||||||
- A new `task import-v2` command allows importing Taskwarrior-2.x
|
- A new `task import-v2` command allows importing Taskwarrior-2.x
|
||||||
data files directly.
|
data files directly.
|
||||||
|
|
||||||
3.3.0 -
|
|
||||||
|
|
||||||
Thanks to the following people for contributions to this release:
|
Thanks to the following people for contributions to this release:
|
||||||
|
|
||||||
- Chongyun Lee
|
- Chongyun Lee
|
||||||
|
@ -18,8 +43,6 @@ Thanks to the following people for contributions to this release:
|
||||||
- Scott Mcdermott
|
- Scott Mcdermott
|
||||||
- Thomas Lauf
|
- Thomas Lauf
|
||||||
|
|
||||||
------ old releases ------------------------------
|
|
||||||
|
|
||||||
3.2.0 -
|
3.2.0 -
|
||||||
|
|
||||||
- Support for the journal in `task info` has been restored (#3671) and the
|
- 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 -S . -B build -DCMAKE_BUILD_TYPE=Release . [3]
|
||||||
$ cmake --build build [4]
|
$ cmake --build build [4]
|
||||||
$ sudo cmake --install build [5]
|
$ 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:
|
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
|
To uninstall Taskwarrior, remove the files listed in the install_manifest.txt
|
||||||
file that was generated when you built Taskwarrior.
|
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
|
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`
|
- Add a new item in `content/news`
|
||||||
- Update `data/projects.json` with the latest version and a fake next version for "devel"
|
- 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 `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
|
## 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:
|
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
|
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
|
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
|
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
|
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:
|
that this:
|
||||||
|
|
||||||
.nf
|
.nf
|
||||||
task description.word:bar list
|
task description.word:foo list
|
||||||
.fi
|
.fi
|
||||||
|
|
||||||
Will match the description 'foo bar baz' but does not match 'dog food'.
|
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
|
.TP
|
||||||
.B gc=1
|
.B gc=1
|
||||||
Can be used to temporarily suspend rebuilding, so that task IDs don't change.
|
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
|
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
|
rc.gc=0 ...), and not permanently used in the .taskrc file, as this
|
||||||
significantly affects performance in the long term.
|
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.
|
is weeks, hours, minutes, money, or some other resource count.
|
||||||
|
|
||||||
.TP
|
.TP
|
||||||
.B uda.<name>.type=string|numeric|date|duration
|
.B uda.<name>.type=string|numeric|uuid|date|duration
|
||||||
.RS
|
.RS
|
||||||
Defines a UDA called '<name>', of the specified type.
|
Defines a UDA called '<name>', of the specified type.
|
||||||
.RE
|
.RE
|
||||||
|
|
|
@ -6,20 +6,20 @@ include_directories (${CMAKE_SOURCE_DIR}
|
||||||
${CMAKE_SOURCE_DIR}/src/libshared/src
|
${CMAKE_SOURCE_DIR}/src/libshared/src
|
||||||
${TASK_INCLUDE_DIRS})
|
${TASK_INCLUDE_DIRS})
|
||||||
|
|
||||||
add_library (task STATIC CLI2.cpp CLI2.h
|
add_library (task STATIC CLI2.cpp
|
||||||
Context.cpp Context.h
|
Context.cpp
|
||||||
DOM.cpp DOM.h
|
DOM.cpp
|
||||||
Eval.cpp Eval.h
|
Eval.cpp
|
||||||
Filter.cpp Filter.h
|
Filter.cpp
|
||||||
Hooks.cpp Hooks.h
|
Hooks.cpp
|
||||||
Lexer.cpp Lexer.h
|
Lexer.cpp
|
||||||
Operation.cpp Operation.h
|
Operation.cpp
|
||||||
TF2.cpp TF2.h
|
TF2.cpp
|
||||||
TDB2.cpp TDB2.h
|
TDB2.cpp
|
||||||
Task.cpp Task.h
|
Task.cpp
|
||||||
Variant.cpp Variant.h
|
Variant.cpp
|
||||||
Version.cpp Version.h
|
Version.cpp
|
||||||
ViewTask.cpp ViewTask.h
|
ViewTask.cpp
|
||||||
dependency.cpp
|
dependency.cpp
|
||||||
feedback.cpp
|
feedback.cpp
|
||||||
legacy.cpp
|
legacy.cpp
|
||||||
|
@ -27,26 +27,25 @@ add_library (task STATIC CLI2.cpp CLI2.h
|
||||||
recur.cpp
|
recur.cpp
|
||||||
rules.cpp
|
rules.cpp
|
||||||
sort.cpp
|
sort.cpp
|
||||||
util.cpp util.h)
|
util.cpp)
|
||||||
target_link_libraries(task taskchampion-cpp)
|
target_link_libraries(task taskchampion-cpp)
|
||||||
|
|
||||||
add_library (libshared STATIC libshared/src/Color.cpp libshared/src/Color.h
|
add_library (libshared STATIC libshared/src/Color.cpp
|
||||||
libshared/src/Configuration.cpp libshared/src/Configuration.h
|
libshared/src/Configuration.cpp
|
||||||
libshared/src/Datetime.cpp libshared/src/Datetime.h
|
libshared/src/Datetime.cpp
|
||||||
libshared/src/Duration.cpp libshared/src/Duration.h
|
libshared/src/Duration.cpp
|
||||||
libshared/src/FS.cpp libshared/src/FS.h
|
libshared/src/FS.cpp
|
||||||
libshared/src/JSON.cpp libshared/src/JSON.h
|
libshared/src/JSON.cpp
|
||||||
libshared/src/Msg.cpp libshared/src/Msg.h
|
libshared/src/Msg.cpp
|
||||||
libshared/src/Pig.cpp libshared/src/Pig.h
|
libshared/src/Pig.cpp
|
||||||
libshared/src/RX.cpp libshared/src/RX.h
|
libshared/src/RX.cpp
|
||||||
libshared/src/Table.cpp libshared/src/Table.h
|
libshared/src/Table.cpp
|
||||||
libshared/src/Timer.cpp libshared/src/Timer.h
|
libshared/src/Timer.cpp
|
||||||
libshared/src/format.cpp libshared/src/format.h
|
libshared/src/format.cpp
|
||||||
libshared/src/ip.cpp
|
libshared/src/ip.cpp
|
||||||
libshared/src/shared.cpp libshared/src/shared.h
|
libshared/src/shared.cpp
|
||||||
libshared/src/unicode.cpp libshared/src/unicode.h
|
libshared/src/unicode.cpp
|
||||||
libshared/src/utf8.cpp libshared/src/utf8.h
|
libshared/src/utf8.cpp)
|
||||||
libshared/src/wcwidth.h)
|
|
||||||
|
|
||||||
add_executable (task_executable main.cpp)
|
add_executable (task_executable main.cpp)
|
||||||
add_executable (calc_executable calc.cpp)
|
add_executable (calc_executable calc.cpp)
|
||||||
|
|
|
@ -36,16 +36,15 @@
|
||||||
#include <Version.h>
|
#include <Version.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <recur.h>
|
||||||
|
#include <rules.h>
|
||||||
#include <rust/cxx.h>
|
#include <rust/cxx.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <taskchampion-cpp/lib.h>
|
#include <taskchampion-cpp/lib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
@ -55,7 +54,6 @@
|
||||||
#include <commit.h>
|
#include <commit.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
#ifdef SOLARIS
|
#ifdef SOLARIS
|
||||||
|
@ -598,9 +596,6 @@ int Context::initialize(int argc, const char** argv) {
|
||||||
|
|
||||||
createDefaultConfig();
|
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.
|
// [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'.");
|
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.
|
// [8] Initialize hooks.
|
||||||
|
@ -869,7 +879,7 @@ int Context::dispatch(std::string& out) {
|
||||||
if (config.getBoolean("debug") && config.getInteger("debug.parser") == 1)
|
if (config.getBoolean("debug") && config.getInteger("debug.parser") == 1)
|
||||||
debug(cli2.dump("Parse Tree (before command-specifіc processing)"));
|
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();
|
handleUntil();
|
||||||
handleRecurrence();
|
handleRecurrence();
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include <Task.h>
|
#include <Task.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,6 @@
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Take an input set of tasks and filter into a subset.
|
// Take an input set of tasks and filter into a subset.
|
||||||
void Filter::subset(const std::vector<Task>& input, std::vector<Task>& output) {
|
void Filter::subset(const std::vector<Task>& input, std::vector<Task>& output) {
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <Task.h>
|
#include <Task.h>
|
||||||
#include <Variant.h>
|
#include <Variant.h>
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
class Filter {
|
class Filter {
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
#include <Variant.h>
|
#include <Variant.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
#include <unistd.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
|
// - all emitted non-JSON lines are considered feedback or error messages
|
||||||
// depending on the status code.
|
// 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;
|
if (!_enabled) return;
|
||||||
|
|
||||||
Timer timer;
|
Timer timer;
|
||||||
|
|
|
@ -40,7 +40,7 @@ class Hooks {
|
||||||
void onLaunch() const;
|
void onLaunch() const;
|
||||||
void onExit() const;
|
void onExit() const;
|
||||||
void onAdd(Task&) const;
|
void onAdd(Task&) const;
|
||||||
void onModify(const Task&, Task&) const;
|
void onModify(Task&, Task&) const;
|
||||||
std::vector<std::string> list() const;
|
std::vector<std::string> list() const;
|
||||||
|
|
||||||
private:
|
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
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
// of this software and associated documentation files (the "Software"), to deal
|
// of this software and associated documentation files (the "Software"), to deal
|
||||||
|
@ -24,8 +25,8 @@
|
||||||
//
|
//
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
#ifndef INCLUDED_OPERATIOn
|
#ifndef INCLUDED_OPERATION
|
||||||
#define INCLUDED_OPERATIOn
|
#define INCLUDED_OPERATION
|
||||||
|
|
||||||
#include <taskchampion-cpp/lib.h>
|
#include <taskchampion-cpp/lib.h>
|
||||||
|
|
||||||
|
|
26
src/TDB2.cpp
26
src/TDB2.cpp
|
@ -33,16 +33,11 @@
|
||||||
#include <TDB2.h>
|
#include <TDB2.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
|
||||||
#include <list>
|
|
||||||
#include <sstream>
|
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
@ -50,17 +45,16 @@ bool TDB2::debug_mode = false;
|
||||||
static void dependency_scan(std::vector<Task>&);
|
static void dependency_scan(std::vector<Task>&);
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void TDB2::open_replica(const std::string& location, bool 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);
|
_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.
|
// Add the new task to the replica.
|
||||||
void TDB2::add(Task& task) {
|
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.
|
// Ensure the task is consistent, and provide defaults if necessary.
|
||||||
// bool argument to validate() is "applyDefault", to apply default values for
|
// bool argument to validate() is "applyDefault", to apply default values for
|
||||||
// properties not otherwise given.
|
// properties not otherwise given.
|
||||||
|
@ -194,11 +188,8 @@ void TDB2::purge(Task& task) {
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
rust::Box<tc::Replica>& TDB2::replica() {
|
rust::Box<tc::Replica>& TDB2::replica() {
|
||||||
// Create a replica in-memory if `open_replica` has not been called. This
|
// One of the open_replica_ methods must be called before this one.
|
||||||
// occurs in tests.
|
assert(_replica);
|
||||||
if (!_replica) {
|
|
||||||
_replica = tc::new_replica_in_memory();
|
|
||||||
}
|
|
||||||
return _replica.value();
|
return _replica.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,8 +354,7 @@ bool TDB2::get(const std::string& uuid, Task& task) {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// Locate task by UUID, wherever it is.
|
// Locate task by UUID, wherever it is.
|
||||||
bool TDB2::has(const std::string& uuid) {
|
bool TDB2::has(const std::string& uuid) {
|
||||||
Task task;
|
return replica()->get_task_data(tc::uuid_from_string(uuid)).is_some();
|
||||||
return get(uuid, task);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -27,9 +27,7 @@
|
||||||
#ifndef INCLUDED_TDB2
|
#ifndef INCLUDED_TDB2
|
||||||
#define INCLUDED_TDB2
|
#define INCLUDED_TDB2
|
||||||
|
|
||||||
#include <FS.h>
|
|
||||||
#include <Task.h>
|
#include <Task.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <taskchampion-cpp/lib.h>
|
#include <taskchampion-cpp/lib.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -46,7 +44,8 @@ class TDB2 {
|
||||||
|
|
||||||
TDB2() = default;
|
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 add(Task &);
|
||||||
void modify(Task &);
|
void modify(Task &);
|
||||||
void purge(Task &);
|
void purge(Task &);
|
||||||
|
|
12
src/TF2.cpp
12
src/TF2.cpp
|
@ -31,18 +31,12 @@
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <cmake.h>
|
#include <cmake.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
|
#include <legacy.h>
|
||||||
|
#endif
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iostream>
|
|
||||||
#include <list>
|
|
||||||
#include <set>
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#define STRING_TDB2_REVERTED "Modified task reverted."
|
#define STRING_TDB2_REVERTED "Modified task reverted."
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -29,12 +29,9 @@
|
||||||
|
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <Task.h>
|
#include <Task.h>
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
// TF2 Class represents a single 2.x-style file in the task database.
|
// 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 <Eval.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Variant.h>
|
#include <Variant.h>
|
||||||
#include <main.h>
|
#include <dependency.h>
|
||||||
|
#include <feedback.h>
|
||||||
|
|
||||||
#define APPROACHING_INFINITY 1000 // Close enough. This isn't rocket surgery.
|
#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.
|
// Determines status of a date attribute.
|
||||||
Task::dateState Task::getDateState(const std::string& name) const {
|
Task::dateState Task::getDateState(const std::string& name) const {
|
||||||
std::string value = get(name);
|
time_t value = get_date(name);
|
||||||
if (value.length()) {
|
if (value > 0) {
|
||||||
Datetime reference(value);
|
Datetime reference(value);
|
||||||
Datetime now;
|
Datetime now;
|
||||||
Datetime today("today");
|
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;
|
std::stringstream out;
|
||||||
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 value is an empty string, do not ever output it
|
||||||
if (i.second == "") continue;
|
if (i.second == "") continue;
|
||||||
|
|
||||||
if (attributes_written) out << ',';
|
|
||||||
|
|
||||||
std::string type = Task::attributes[i.first];
|
std::string type = Task::attributes[i.first];
|
||||||
if (type == "") type = "string";
|
if (type == "") type = "string";
|
||||||
|
|
||||||
// Date fields are written as ISO 8601.
|
// Date fields are written as ISO 8601.
|
||||||
if (type == "date") {
|
if (type == "date") {
|
||||||
Datetime d(i.second);
|
time_t epoch = get_date(i.first);
|
||||||
out << '"' << (i.first == "modification" ? "modified" : i.first)
|
if (epoch != 0) {
|
||||||
<< "\":\""
|
Datetime d(i.second);
|
||||||
// Date was deleted, do not export parsed empty string
|
if (attributes_written) out << ',';
|
||||||
<< (i.second == "" ? "" : d.toISO()) << '"';
|
|
||||||
|
|
||||||
++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") {
|
else if (type == "numeric") {
|
||||||
|
if (attributes_written) out << ',';
|
||||||
|
|
||||||
out << '"' << i.first << "\":" << i.second;
|
out << '"' << i.first << "\":" << i.second;
|
||||||
|
|
||||||
++attributes_written;
|
++attributes_written;
|
||||||
|
@ -827,6 +833,8 @@ std::string Task::composeJSON(bool decorate /*= false*/) const {
|
||||||
|
|
||||||
// Everything else is a quoted value.
|
// Everything else is a quoted value.
|
||||||
else {
|
else {
|
||||||
|
if (attributes_written) out << ',';
|
||||||
|
|
||||||
out << '"' << i.first << "\":\"" << (type == "string" ? json::encode(i.second) : i.second)
|
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
|
#ifdef PRODUCT_TASKWARRIOR
|
||||||
// Include urgency.
|
// Include urgency.
|
||||||
if (decorate) out << ',' << "\"urgency\":" << urgency_c();
|
if (decorate) out << ',' << "\"urgency\":" << urgency();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
out << '}';
|
out << '}';
|
||||||
|
@ -920,7 +928,7 @@ void Task::addAnnotation(const std::string& description) {
|
||||||
++now;
|
++now;
|
||||||
} while (has(key));
|
} while (has(key));
|
||||||
|
|
||||||
data[key] = json::decode(description);
|
data[key] = description;
|
||||||
++annotation_count;
|
++annotation_count;
|
||||||
recalc_urgency = true;
|
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.
|
// Delegate modification to the column object or their base classes.
|
||||||
if (name == "depends" || name == "tags" || name == "recur" || column->type() == "date" ||
|
if (name == "depends" || name == "tags" || name == "recur" || column->type() == "date" ||
|
||||||
column->type() == "duration" || column->type() == "numeric" ||
|
column->type() == "duration" || column->type() == "numeric" ||
|
||||||
column->type() == "string") {
|
column->type() == "string" || column->type() == "uuid") {
|
||||||
column->modify(*this, value);
|
column->modify(*this, value);
|
||||||
mods = true;
|
mods = true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <Datetime.h>
|
#include <Datetime.h>
|
||||||
#include <JSON.h>
|
#include <JSON.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <stdio.h>
|
|
||||||
#include <taskchampion-cpp/lib.h>
|
#include <taskchampion-cpp/lib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
@ -69,7 +68,7 @@ class Task {
|
||||||
Task(rust::Box<tc::TaskData>);
|
Task(rust::Box<tc::TaskData>);
|
||||||
|
|
||||||
void parse(const std::string&);
|
void parse(const std::string&);
|
||||||
std::string composeJSON(bool decorate = false) const;
|
std::string composeJSON(bool decorate = false);
|
||||||
|
|
||||||
// Status values.
|
// Status values.
|
||||||
enum status { pending, completed, deleted, recurring, waiting };
|
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_BOOL "Cannot divide duration by Boolean"
|
||||||
#define STRING_VARIANT_DIV_DUR_STR "Cannot divide durations by strings"
|
#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_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_BOOL "Cannot modulo Booleans"
|
||||||
#define STRING_VARIANT_MOD_DATE "Cannot modulo date values"
|
#define STRING_VARIANT_MOD_DATE "Cannot modulo date values"
|
||||||
#define STRING_VARIANT_MOD_DUR "Cannot modulo duration 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);
|
throw std::string(STRING_VARIANT_DIV_DUR_DATE);
|
||||||
|
|
||||||
case type_duration:
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,9 +28,7 @@
|
||||||
#define INCLUDED_VARIANT
|
#define INCLUDED_VARIANT
|
||||||
|
|
||||||
#include <Task.h>
|
#include <Task.h>
|
||||||
#include <time.h>
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class Variant {
|
class Variant {
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <ViewTask.h>
|
#include <ViewTask.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <rules.h>
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
|
|
|
@ -30,13 +30,10 @@
|
||||||
#include <ColDepends.h>
|
#include <ColDepends.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <regex>
|
#include <regex>
|
||||||
|
|
||||||
#define STRING_COLUMN_LABEL_DEP "Depends"
|
#define STRING_COLUMN_LABEL_DEP "Depends"
|
||||||
|
|
|
@ -32,8 +32,8 @@
|
||||||
#include <Eval.h>
|
#include <Eval.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Variant.h>
|
#include <Variant.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
|
|
||||||
|
|
|
@ -56,11 +56,9 @@ void ColumnTypeDuration::modify(Task& task, const std::string& value) {
|
||||||
evaluatedValue = Variant(value);
|
evaluatedValue = Variant(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
// The duration is stored in raw form, but it must still be valid,
|
// The duration is first parsed, then stored inside the variant as a `time_t`
|
||||||
// and therefore is parsed first.
|
|
||||||
std::string label = " [1;37;43mMODIFICATION[0m ";
|
std::string label = " [1;37;43mMODIFICATION[0m ";
|
||||||
if (evaluatedValue.type() == Variant::type_duration) {
|
if (evaluatedValue.type() == Variant::type_duration) {
|
||||||
// Store the raw value, for 'recur'.
|
|
||||||
Context::getContext().debug(label + _name + " <-- " + (std::string)evaluatedValue + " <-- '" +
|
Context::getContext().debug(label + _name + " <-- " + (std::string)evaluatedValue + " <-- '" +
|
||||||
value + '\'');
|
value + '\'');
|
||||||
task.set(_name, evaluatedValue);
|
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 <ColTypeDuration.h>
|
||||||
#include <ColTypeNumeric.h>
|
#include <ColTypeNumeric.h>
|
||||||
#include <ColTypeString.h>
|
#include <ColTypeString.h>
|
||||||
|
#include <ColUUID.h>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
class ColumnUDAString : public ColumnTypeString {
|
class ColumnUDAString : public ColumnTypeString {
|
||||||
|
@ -83,5 +84,12 @@ class ColumnUDADuration : public ColumnTypeDuration {
|
||||||
std::vector<std::string> _values;
|
std::vector<std::string> _values;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
class ColumnUDAUUID : public ColumnUUID {
|
||||||
|
public:
|
||||||
|
ColumnUDAUUID();
|
||||||
|
bool validate(const std::string&) const;
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -246,9 +246,15 @@ Column* Column::uda(const std::string& name) {
|
||||||
c->_label = label;
|
c->_label = label;
|
||||||
if (values != "") c->_values = split(values, ',');
|
if (values != "") c->_values = split(values, ',');
|
||||||
return c;
|
return c;
|
||||||
|
} else if (type == "uuid") {
|
||||||
|
auto c = new ColumnUDAUUID();
|
||||||
|
c->_name = name;
|
||||||
|
c->_label = label;
|
||||||
|
return c;
|
||||||
} else if (type != "")
|
} else if (type != "")
|
||||||
throw std::string(
|
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;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
|
|
||||||
#include <CmdAdd.h>
|
#include <CmdAdd.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CmdAdd::CmdAdd() {
|
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
|
// the task is empty, but DOM references can refer to earlier parts of the
|
||||||
// command line, e.g., `task add due:20110101 wait:due`.
|
// command line, e.g., `task add due:20110101 wait:due`.
|
||||||
task.modify(Task::modReplace, true);
|
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);
|
Context::getContext().tdb2.add(task);
|
||||||
|
|
||||||
// Do not display ID 0, users cannot query by that
|
// Do not display ID 0, users cannot query by that
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#include <CmdAnnotate.h>
|
#include <CmdAnnotate.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#include <CmdAppend.h>
|
#include <CmdAppend.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <Duration.h>
|
#include <Duration.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <utf8.h>
|
#include <utf8.h>
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include <Color.h>
|
#include <Color.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <rules.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
|
@ -218,8 +218,8 @@ void CmdContext::defineContext(const std::vector<std::string>& words, std::strin
|
||||||
if (!valid_write_context) {
|
if (!valid_write_context) {
|
||||||
std::stringstream warning;
|
std::stringstream warning;
|
||||||
warning
|
warning
|
||||||
<< format("The filter '{1}' is not a valid modification string, because it contains {2}.",
|
<< format("The filter '{1}' is not a valid modification string, because it {2}.", value,
|
||||||
value, reason)
|
reason)
|
||||||
<< "\nAs such, value for the write context cannot be set (context will not apply on task "
|
<< "\nAs such, value for the write context cannot be set (context will not apply on task "
|
||||||
"add / task log).\n\n"
|
"add / task log).\n\n"
|
||||||
<< format(
|
<< format(
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <CmdCount.h>
|
#include <CmdCount.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CmdCount::CmdCount() {
|
CmdCount::CmdCount() {
|
||||||
|
|
|
@ -34,15 +34,15 @@
|
||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
#include <Version.h>
|
#include <Version.h>
|
||||||
#include <ViewTask.h>
|
#include <ViewTask.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <legacy.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <stdlib.h>
|
#include <sort.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <map>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,10 @@
|
||||||
#include <CmdDelete.h>
|
#include <CmdDelete.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <dependency.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <recur.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#include <CmdDenotate.h>
|
#include <CmdDenotate.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,11 @@
|
||||||
#include <CmdDone.h>
|
#include <CmdDone.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <dependency.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <nag.h>
|
||||||
|
#include <recur.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#include <CmdDuplicate.h>
|
#include <CmdDuplicate.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -36,7 +36,6 @@
|
||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
#include <Pig.h>
|
#include <Pig.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
@ -64,7 +63,7 @@ CmdEdit::CmdEdit() {
|
||||||
_read_only = false;
|
_read_only = false;
|
||||||
_displays_id = false;
|
_displays_id = false;
|
||||||
_needs_gc = false;
|
_needs_gc = false;
|
||||||
_needs_recur_update = false;
|
_needs_recur_update = true;
|
||||||
_uses_context = true;
|
_uses_context = true;
|
||||||
_accepts_filter = true;
|
_accepts_filter = true;
|
||||||
_accepts_modifications = false;
|
_accepts_modifications = false;
|
||||||
|
@ -78,8 +77,6 @@ CmdEdit::CmdEdit() {
|
||||||
// wrench. To be used sparingly.
|
// wrench. To be used sparingly.
|
||||||
int CmdEdit::execute(std::string&) {
|
int CmdEdit::execute(std::string&) {
|
||||||
// Filter the tasks.
|
// Filter the tasks.
|
||||||
handleUntil();
|
|
||||||
handleRecurrence();
|
|
||||||
Filter filter;
|
Filter filter;
|
||||||
std::vector<Task> filtered;
|
std::vector<Task> filtered;
|
||||||
filter.subset(filtered);
|
filter.subset(filtered);
|
||||||
|
|
|
@ -31,8 +31,9 @@
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <legacy.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
#include <sort.h>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CmdExport::CmdExport() {
|
CmdExport::CmdExport() {
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <DOM.h>
|
#include <DOM.h>
|
||||||
#include <Variant.h>
|
#include <Variant.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -55,7 +54,7 @@ CmdHistoryBase<HistoryStrategy>::CmdHistoryBase() {
|
||||||
_read_only = true;
|
_read_only = true;
|
||||||
_displays_id = false;
|
_displays_id = false;
|
||||||
_needs_gc = false;
|
_needs_gc = false;
|
||||||
_needs_recur_update = false;
|
_needs_recur_update = true;
|
||||||
_uses_context = true;
|
_uses_context = true;
|
||||||
_accepts_filter = true;
|
_accepts_filter = true;
|
||||||
_accepts_modifications = false;
|
_accepts_modifications = false;
|
||||||
|
@ -294,8 +293,6 @@ int CmdHistoryBase<HistoryStrategy>::execute(std::string& output) {
|
||||||
completedGroup.clear();
|
completedGroup.clear();
|
||||||
|
|
||||||
// Apply filter.
|
// Apply filter.
|
||||||
handleUntil();
|
|
||||||
handleRecurrence();
|
|
||||||
Filter filter;
|
Filter filter;
|
||||||
std::vector<Task> filtered;
|
std::vector<Task> filtered;
|
||||||
filter.subset(filtered);
|
filter.subset(filtered);
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
#include <CmdIDs.h>
|
#include <CmdIDs.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
@ -137,8 +136,6 @@ CmdCompletionIds::CmdCompletionIds() {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int CmdCompletionIds::execute(std::string& output) {
|
int CmdCompletionIds::execute(std::string& output) {
|
||||||
// Apply filter.
|
// Apply filter.
|
||||||
handleUntil();
|
|
||||||
handleRecurrence();
|
|
||||||
Filter filter;
|
Filter filter;
|
||||||
std::vector<Task> filtered;
|
std::vector<Task> filtered;
|
||||||
filter.subset(filtered);
|
filter.subset(filtered);
|
||||||
|
@ -174,8 +171,6 @@ CmdZshCompletionIds::CmdZshCompletionIds() {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int CmdZshCompletionIds::execute(std::string& output) {
|
int CmdZshCompletionIds::execute(std::string& output) {
|
||||||
// Apply filter.
|
// Apply filter.
|
||||||
handleUntil();
|
|
||||||
handleRecurrence();
|
|
||||||
Filter filter;
|
Filter filter;
|
||||||
std::vector<Task> filtered;
|
std::vector<Task> filtered;
|
||||||
filter.subset(filtered);
|
filter.subset(filtered);
|
||||||
|
@ -211,8 +206,6 @@ CmdUUIDs::CmdUUIDs() {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int CmdUUIDs::execute(std::string& output) {
|
int CmdUUIDs::execute(std::string& output) {
|
||||||
// Apply filter.
|
// Apply filter.
|
||||||
handleUntil();
|
|
||||||
handleRecurrence();
|
|
||||||
Filter filter;
|
Filter filter;
|
||||||
std::vector<Task> filtered;
|
std::vector<Task> filtered;
|
||||||
filter.subset(filtered);
|
filter.subset(filtered);
|
||||||
|
@ -247,8 +240,6 @@ CmdCompletionUuids::CmdCompletionUuids() {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int CmdCompletionUuids::execute(std::string& output) {
|
int CmdCompletionUuids::execute(std::string& output) {
|
||||||
// Apply filter.
|
// Apply filter.
|
||||||
handleUntil();
|
|
||||||
handleRecurrence();
|
|
||||||
Filter filter;
|
Filter filter;
|
||||||
std::vector<Task> filtered;
|
std::vector<Task> filtered;
|
||||||
filter.subset(filtered);
|
filter.subset(filtered);
|
||||||
|
@ -283,8 +274,6 @@ CmdZshCompletionUuids::CmdZshCompletionUuids() {
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
int CmdZshCompletionUuids::execute(std::string& output) {
|
int CmdZshCompletionUuids::execute(std::string& output) {
|
||||||
// Apply filter.
|
// Apply filter.
|
||||||
handleUntil();
|
|
||||||
handleRecurrence();
|
|
||||||
Filter filter;
|
Filter filter;
|
||||||
std::vector<Task> filtered;
|
std::vector<Task> filtered;
|
||||||
filter.subset(filtered);
|
filter.subset(filtered);
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include <JSON.h>
|
#include <JSON.h>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
|
||||||
|
|
||||||
class CmdImportV2 : public Command {
|
class CmdImportV2 : public Command {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -34,9 +34,9 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
#include <Operation.h>
|
#include <Operation.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <rules.h>
|
||||||
#include <math.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <taskchampion-cpp/lib.h>
|
#include <taskchampion-cpp/lib.h>
|
||||||
|
@ -120,9 +120,11 @@ int CmdInfo::execute(std::string& output) {
|
||||||
description += '\n' + std::string(indent, ' ') +
|
description += '\n' + std::string(indent, ' ') +
|
||||||
Datetime(anno.first.substr(11)).toString(dateformatanno) + ' ' + anno.second;
|
Datetime(anno.first.substr(11)).toString(dateformatanno) + ' ' + anno.second;
|
||||||
|
|
||||||
row = view.addRow();
|
if (task.has("description")) {
|
||||||
view.set(row, 0, "Description");
|
row = view.addRow();
|
||||||
view.set(row, 1, description, c);
|
view.set(row, 0, "Description");
|
||||||
|
view.set(row, 1, description, c);
|
||||||
|
}
|
||||||
|
|
||||||
// status
|
// status
|
||||||
row = view.addRow();
|
row = view.addRow();
|
||||||
|
@ -215,64 +217,76 @@ int CmdInfo::execute(std::string& output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// entry
|
// entry
|
||||||
row = view.addRow();
|
if (task.has("entry") && task.get_date("entry")) {
|
||||||
view.set(row, 0, "Entered");
|
row = view.addRow();
|
||||||
Datetime dt(task.get_date("entry"));
|
view.set(row, 0, "Entered");
|
||||||
std::string entry = dt.toString(dateformat);
|
Datetime dt(task.get_date("entry"));
|
||||||
|
std::string entry = dt.toString(dateformat);
|
||||||
|
|
||||||
std::string age;
|
std::string age;
|
||||||
auto created = task.get("entry");
|
auto created = task.get("entry");
|
||||||
if (created.length()) {
|
if (created.length()) {
|
||||||
Datetime dt(strtoll(created.c_str(), nullptr, 10));
|
Datetime dt(strtoll(created.c_str(), nullptr, 10));
|
||||||
age = Duration(now - dt).formatVague();
|
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
|
// wait
|
||||||
if (task.has("wait")) {
|
if (validDate("wait")) {
|
||||||
row = view.addRow();
|
row = view.addRow();
|
||||||
view.set(row, 0, "Waiting until");
|
view.set(row, 0, "Waiting until");
|
||||||
view.set(row, 1, Datetime(task.get_date("wait")).toString(dateformat));
|
view.set(row, 1, Datetime(task.get_date("wait")).toString(dateformat));
|
||||||
}
|
}
|
||||||
|
|
||||||
// scheduled
|
// scheduled
|
||||||
if (task.has("scheduled")) {
|
if (validDate("scheduled")) {
|
||||||
row = view.addRow();
|
row = view.addRow();
|
||||||
view.set(row, 0, "Scheduled");
|
view.set(row, 0, "Scheduled");
|
||||||
view.set(row, 1, Datetime(task.get_date("scheduled")).toString(dateformat));
|
view.set(row, 1, Datetime(task.get_date("scheduled")).toString(dateformat));
|
||||||
}
|
}
|
||||||
|
|
||||||
// start
|
// start
|
||||||
if (task.has("start")) {
|
if (validDate("start")) {
|
||||||
row = view.addRow();
|
row = view.addRow();
|
||||||
view.set(row, 0, "Start");
|
view.set(row, 0, "Start");
|
||||||
view.set(row, 1, Datetime(task.get_date("start")).toString(dateformat));
|
view.set(row, 1, Datetime(task.get_date("start")).toString(dateformat));
|
||||||
}
|
}
|
||||||
|
|
||||||
// due (colored)
|
// due (colored)
|
||||||
if (task.has("due")) {
|
if (validDate("due")) {
|
||||||
row = view.addRow();
|
row = view.addRow();
|
||||||
view.set(row, 0, "Due");
|
view.set(row, 0, "Due");
|
||||||
view.set(row, 1, Datetime(task.get_date("due")).toString(dateformat));
|
view.set(row, 1, Datetime(task.get_date("due")).toString(dateformat));
|
||||||
}
|
}
|
||||||
|
|
||||||
// end
|
// end
|
||||||
if (task.has("end")) {
|
if (validDate("end")) {
|
||||||
row = view.addRow();
|
row = view.addRow();
|
||||||
view.set(row, 0, "End");
|
view.set(row, 0, "End");
|
||||||
view.set(row, 1, Datetime(task.get_date("end")).toString(dateformat));
|
view.set(row, 1, Datetime(task.get_date("end")).toString(dateformat));
|
||||||
}
|
}
|
||||||
|
|
||||||
// until
|
// until
|
||||||
if (task.has("until")) {
|
if (validDate("until")) {
|
||||||
row = view.addRow();
|
row = view.addRow();
|
||||||
view.set(row, 0, "Until");
|
view.set(row, 0, "Until");
|
||||||
view.set(row, 1, Datetime(task.get_date("until")).toString(dateformat));
|
view.set(row, 1, Datetime(task.get_date("until")).toString(dateformat));
|
||||||
}
|
}
|
||||||
|
|
||||||
// modified
|
// modified
|
||||||
if (task.has("modified")) {
|
if (validDate("modified")) {
|
||||||
row = view.addRow();
|
row = view.addRow();
|
||||||
view.set(row, 0, "Last modified");
|
view.set(row, 0, "Last modified");
|
||||||
|
|
||||||
|
@ -632,7 +646,11 @@ std::optional<std::string> CmdInfo::formatForInfo(const std::vector<Operation>&
|
||||||
} else {
|
} else {
|
||||||
// Record the last start time for later duration calculation.
|
// Record the last start time for later duration calculation.
|
||||||
if (prop == "start") {
|
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),
|
out << format("{1} set to '{2}'.", Lexer::ucFirst(prop),
|
||||||
|
|
|
@ -29,8 +29,8 @@
|
||||||
|
|
||||||
#include <CmdLog.h>
|
#include <CmdLog.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CmdLog::CmdLog() {
|
CmdLog::CmdLog() {
|
||||||
|
|
|
@ -30,8 +30,9 @@
|
||||||
#include <CmdModify.h>
|
#include <CmdModify.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <recur.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
#include <iostream>
|
#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.");
|
throw std::string("You cannot remove the recurrence from a recurring task.");
|
||||||
|
|
||||||
if ((before.getStatus() == Task::pending) && (after.getStatus() == Task::pending) &&
|
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.",
|
throw format("Could not modify task {1}. You cannot set an end date on a pending task.",
|
||||||
before.identifier(true));
|
before.identifier(true));
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <Duration.h>
|
#include <Duration.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
|
@ -161,6 +160,7 @@ std::vector<NewsItem> NewsItem::all() {
|
||||||
version3_1_0(items);
|
version3_1_0(items);
|
||||||
version3_2_0(items);
|
version3_2_0(items);
|
||||||
version3_3_0(items);
|
version3_3_0(items);
|
||||||
|
version3_4_0(items);
|
||||||
return items;
|
return items;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -531,6 +531,21 @@ void NewsItem::version3_3_0(std::vector<NewsItem>& items) {
|
||||||
items.push_back(info);
|
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) {
|
int CmdNews::execute(std::string& output) {
|
||||||
auto words = Context::getContext().cli2.getWords();
|
auto words = Context::getContext().cli2.getWords();
|
||||||
|
@ -573,61 +588,10 @@ int CmdNews::execute(std::string& output) {
|
||||||
}
|
}
|
||||||
wait_for_enter();
|
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
|
// Set a mark in the config to remember which version's release notes were displayed
|
||||||
if (news_version < current_version) {
|
if (news_version < current_version) {
|
||||||
CmdConfig::setConfigVariable("news.version", std::string(current_version), false);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,6 +53,7 @@ class NewsItem {
|
||||||
static void version3_1_0(std::vector<NewsItem>&);
|
static void version3_1_0(std::vector<NewsItem>&);
|
||||||
static void version3_2_0(std::vector<NewsItem>&);
|
static void version3_2_0(std::vector<NewsItem>&);
|
||||||
static void version3_3_0(std::vector<NewsItem>&);
|
static void version3_3_0(std::vector<NewsItem>&);
|
||||||
|
static void version3_4_0(std::vector<NewsItem>&);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NewsItem(Version, const std::string&, const std::string& = "", const std::string& = "",
|
NewsItem(Version, const std::string&, const std::string& = "", const std::string& = "",
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#include <CmdPrepend.h>
|
#include <CmdPrepend.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -32,10 +32,9 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <sort.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#include <CmdPurge.h>
|
#include <CmdPurge.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -32,7 +32,7 @@
|
||||||
#include <FS.h>
|
#include <FS.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <legacy.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
|
@ -30,8 +30,11 @@
|
||||||
#include <CmdStart.h>
|
#include <CmdStart.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <dependency.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <nag.h>
|
||||||
|
#include <recur.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,10 @@
|
||||||
#include <CmdStop.h>
|
#include <CmdStop.h>
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
|
#include <dependency.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <recur.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
|
|
@ -33,11 +33,10 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <sort.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
|
@ -32,13 +32,11 @@
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <signal.h>
|
|
||||||
#include <taskchampion-cpp/lib.h>
|
#include <taskchampion-cpp/lib.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <regex>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -81,6 +79,10 @@ int CmdSync::execute(std::string& output) {
|
||||||
out << "sync.server.origin is deprecated. Use sync.server.url instead.\n";
|
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 (server_dir != "") {
|
||||||
if (verbose) {
|
if (verbose) {
|
||||||
out << format("Syncing with {1}", server_dir) << '\n';
|
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");
|
throw std::string("sync.server.client_id and sync.encryption_secret are required");
|
||||||
}
|
}
|
||||||
if (verbose) {
|
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,
|
replica->sync_to_remote(server_url, tc::uuid_from_string(client_id), encryption_secret,
|
||||||
avoid_snapshots);
|
avoid_snapshots);
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
|
@ -33,8 +33,7 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
#include <rules.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
|
@ -33,7 +33,6 @@
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <Task.h>
|
#include <Task.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
|
|
|
@ -31,12 +31,11 @@
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Operation.h>
|
#include <Operation.h>
|
||||||
#include <Task.h>
|
#include <Task.h>
|
||||||
|
#include <shared.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "shared.h"
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
CmdUndo::CmdUndo() {
|
CmdUndo::CmdUndo() {
|
||||||
_keyword = "undo";
|
_keyword = "undo";
|
||||||
|
|
|
@ -32,8 +32,6 @@
|
||||||
#include <Filter.h>
|
#include <Filter.h>
|
||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
#include <Datetime.h>
|
#include <Datetime.h>
|
||||||
#include <Table.h>
|
#include <Table.h>
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#ifdef HAVE_COMMIT
|
#ifdef HAVE_COMMIT
|
||||||
|
|
|
@ -50,9 +50,7 @@
|
||||||
#include <CmdEdit.h>
|
#include <CmdEdit.h>
|
||||||
#include <Command.h>
|
#include <Command.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
|
@ -31,7 +31,6 @@
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
class Command {
|
class Command {
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -28,13 +28,11 @@
|
||||||
// cmake.h include header must come first
|
// cmake.h include header must come first
|
||||||
|
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
|
#include <dependency.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
|
||||||
#define STRING_DEPEND_BLOCKED "Task {1} is blocked by:"
|
#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 <Datetime.h>
|
||||||
#include <Duration.h>
|
#include <Duration.h>
|
||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <main.h>
|
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#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()) {
|
if (Context::getContext().columns.find(name) != Context::getContext().columns.end()) {
|
||||||
Column* col = Context::getContext().columns[name];
|
Column* col = Context::getContext().columns[name];
|
||||||
if (col && col->type() == "date" && value != "") {
|
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"));
|
if (format == "") return d.toString(Context::getContext().config.get("dateformat"));
|
||||||
|
|
||||||
return d.toString(format);
|
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 <Context.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
|
|
||||||
#include <cstddef>
|
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#define STRING_LEGACY_PRIORITY "Legacy attribute found. Please change '{1}' to '{2}'."
|
#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 <cmake.h>
|
||||||
|
|
||||||
#include <algorithm>
|
|
||||||
// cmake.h include header must come first
|
// cmake.h include header must come first
|
||||||
|
|
||||||
#include <Context.h>
|
#include <Context.h>
|
||||||
|
|
||||||
#include <iterator>
|
|
||||||
#include <unordered_set>
|
|
||||||
#include <utility>
|
|
||||||
#include <vector>
|
#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 <Datetime.h>
|
||||||
#include <Duration.h>
|
#include <Duration.h>
|
||||||
#include <Lexer.h>
|
#include <Lexer.h>
|
||||||
|
#include <feedback.h>
|
||||||
#include <format.h>
|
#include <format.h>
|
||||||
#include <inttypes.h>
|
|
||||||
#include <main.h>
|
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <stdio.h>
|
#include <recur.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unicode.h>
|
#include <unicode.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <util.h>
|
#include <util.h>
|
||||||
|
|
||||||
#include <fstream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <iostream>
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
// Add a `time_t` delta to a Datetime, checking for and returning nullopt on integer overflow.
|
// 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) {
|
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') {
|
else if (unicodeLatinDigit(period[0]) && period[period.length() - 1] == 'q') {
|
||||||
int increment = strtol(period.substr(0, period.length() - 1).c_str(), nullptr, 10);
|
int increment = strtol(period.substr(0, period.length() - 1).c_str(), nullptr, 10);
|
||||||
|
|
||||||
if (increment <= 0)
|
if (increment <= 0) {
|
||||||
throw format("Recurrence period '{1}' is equivalent to {2} and hence invalid.", period,
|
Context::getContext().footnote(format(
|
||||||
increment);
|
"Recurrence period '{1}' is equivalent to {2} and hence invalid.", period, increment));
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
m += 3 * increment;
|
m += 3 * increment;
|
||||||
while (m > 12) {
|
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.
|
// Add the period to current, and we're done.
|
||||||
std::string::size_type idx = 0;
|
std::string::size_type idx = 0;
|
||||||
Duration p;
|
Duration p;
|
||||||
if (!p.parse(period, idx))
|
if (!p.parse(period, idx)) {
|
||||||
throw std::string(format("The recurrence value '{1}' is not valid.", period));
|
Context::getContext().footnote(
|
||||||
|
format("Warning: The recurrence value '{1}' is not valid.", period));
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
return checked_add_datetime(current, p.toTime_t());
|
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 <Context.h>
|
||||||
#include <Datetime.h>
|
#include <Datetime.h>
|
||||||
#include <main.h>
|
#include <rules.h>
|
||||||
#include <shared.h>
|
#include <shared.h>
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
static std::map<std::string, Color> gsColor;
|
static std::map<std::string, Color> gsColor;
|
||||||
static std::vector<std::string> gsPrecedence;
|
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>>;
|
fn new_replica_in_memory() -> Result<Box<Replica>>;
|
||||||
|
|
||||||
/// Create a new replica stored on-disk.
|
/// Create a new replica stored on-disk.
|
||||||
fn new_replica_on_disk(taskdb_dir: String, create_if_missing: bool)
|
fn new_replica_on_disk(
|
||||||
-> Result<Box<Replica>>;
|
taskdb_dir: String,
|
||||||
|
create_if_missing: bool,
|
||||||
|
read_write: bool,
|
||||||
|
) -> Result<Box<Replica>>;
|
||||||
|
|
||||||
/// Commit the given operations to the replica.
|
/// Commit the given operations to the replica.
|
||||||
fn commit_operations(&mut self, ops: Vec<Operation>) -> Result<()>;
|
fn commit_operations(&mut self, ops: Vec<Operation>) -> Result<()>;
|
||||||
|
@ -490,11 +493,14 @@ impl From<tc::Replica> for Replica {
|
||||||
fn new_replica_on_disk(
|
fn new_replica_on_disk(
|
||||||
taskdb_dir: String,
|
taskdb_dir: String,
|
||||||
create_if_missing: bool,
|
create_if_missing: bool,
|
||||||
|
read_write: bool,
|
||||||
) -> Result<Box<Replica>, CppError> {
|
) -> Result<Box<Replica>, CppError> {
|
||||||
|
use tc::storage::AccessMode::*;
|
||||||
|
let access_mode = if read_write { ReadWrite } else { ReadOnly };
|
||||||
let storage = tc::StorageConfig::OnDisk {
|
let storage = tc::StorageConfig::OnDisk {
|
||||||
taskdb_dir: PathBuf::from(taskdb_dir),
|
taskdb_dir: PathBuf::from(taskdb_dir),
|
||||||
create_if_missing,
|
create_if_missing,
|
||||||
access_mode: tc::storage::AccessMode::ReadWrite,
|
access_mode,
|
||||||
}
|
}
|
||||||
.into_storage()?;
|
.into_storage()?;
|
||||||
Ok(Box::new(tc::Replica::new(storage).into()))
|
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