Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec18da0664 | ||
|
|
59c99f4f5c | ||
|
|
6d2bf5ac09 | ||
|
|
b1efb1eb62 |
3
.github/workflows/ci.yml
vendored
3
.github/workflows/ci.yml
vendored
@@ -12,7 +12,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: DeterminateSystems/nix-installer-action@main
|
- uses: DeterminateSystems/nix-installer-action@main
|
||||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
|
||||||
- name: Check formatting
|
- name: Check formatting
|
||||||
run: nix develop --command cargo fmt --all -- --check
|
run: nix develop --command cargo fmt --all -- --check
|
||||||
- name: Run clippy
|
- name: Run clippy
|
||||||
@@ -25,7 +24,6 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: DeterminateSystems/nix-installer-action@main
|
- uses: DeterminateSystems/nix-installer-action@main
|
||||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: nix develop --command cargo test
|
run: nix develop --command cargo test
|
||||||
|
|
||||||
@@ -34,6 +32,5 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: DeterminateSystems/nix-installer-action@main
|
- uses: DeterminateSystems/nix-installer-action@main
|
||||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
|
||||||
- name: Build project
|
- name: Build project
|
||||||
run: nix build .#timr
|
run: nix build .#timr
|
||||||
|
|||||||
11
.github/workflows/release.yml
vendored
11
.github/workflows/release.yml
vendored
@@ -31,7 +31,7 @@ jobs:
|
|||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
os_target: linux
|
os_target: linux
|
||||||
binary_name: timr-tui
|
binary_name: timr-tui
|
||||||
arch: x86_64 # `x86_64` by default
|
arch: x86_64 # based on target 'x86_64-unknown-linux-musl' defined by `CARGO_BUILD_TARGET` in flake.nix
|
||||||
- os: ubuntu-latest
|
- os: ubuntu-latest
|
||||||
os_target: windows
|
os_target: windows
|
||||||
binary_name: timr-tui.exe
|
binary_name: timr-tui.exe
|
||||||
@@ -43,14 +43,17 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: DeterminateSystems/nix-installer-action@main
|
- uses: DeterminateSystems/nix-installer-action@main
|
||||||
- uses: DeterminateSystems/magic-nix-cache-action@main
|
|
||||||
|
|
||||||
- name: Build (windows)
|
- name: Build (windows)
|
||||||
if: matrix.os_target == 'windows'
|
if: matrix.os_target == 'windows'
|
||||||
run: nix build .#windows
|
run: nix build .#windows
|
||||||
|
|
||||||
- name: Build (linux/macos)
|
- name: Build (linux)
|
||||||
if: matrix.os_target != 'windows'
|
if: matrix.os_target == 'linux'
|
||||||
|
run: nix build .#linuxStatic
|
||||||
|
|
||||||
|
- name: Build (macos)
|
||||||
|
if: matrix.os_target == 'macos'
|
||||||
run: nix build
|
run: nix build
|
||||||
|
|
||||||
- name: Copy artifact
|
- name: Copy artifact
|
||||||
|
|||||||
296
Cargo.lock
generated
296
Cargo.lock
generated
@@ -28,9 +28,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "allocator-api2"
|
name = "allocator-api2"
|
||||||
version = "0.2.20"
|
version = "0.2.21"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9"
|
checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "anstream"
|
name = "anstream"
|
||||||
@@ -104,9 +104,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
version = "2.6.0"
|
version = "2.7.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
checksum = "1be3f42a67d6d345ecd59f675f3f012d6974981560836e938c22b424b85ce1be"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
@@ -134,9 +134,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cc"
|
name = "cc"
|
||||||
version = "1.2.1"
|
version = "1.2.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
|
checksum = "ad0cf6e91fde44c773c6ee7ec6bba798504641a8bc2eb7e37a04ffbf4dfaa55a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"shlex",
|
"shlex",
|
||||||
]
|
]
|
||||||
@@ -149,9 +149,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.5.23"
|
version = "4.5.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84"
|
checksum = "a8eb5e908ef3a6efbe1ed62520fb7287959888c88485abe072543190ecc66783"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
@@ -159,9 +159,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.5.23"
|
version = "4.5.26"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838"
|
checksum = "96b01801b5fc6a0a232407abc821660c9c6d25a1cafc0d4f85f29fb8d9afc121"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
@@ -171,9 +171,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_derive"
|
name = "clap_derive"
|
||||||
version = "4.5.18"
|
version = "4.5.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
|
checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@@ -222,9 +222,9 @@ checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "compact_str"
|
name = "compact_str"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6050c3a16ddab2e412160b31f2c871015704239bca62f72f6e5f0be631d3f644"
|
checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"castaway",
|
"castaway",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
@@ -305,12 +305,6 @@ dependencies = [
|
|||||||
"powerfmt",
|
"powerfmt",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "diff"
|
|
||||||
version = "0.1.13"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "directories"
|
name = "directories"
|
||||||
version = "5.0.1"
|
version = "5.0.1"
|
||||||
@@ -345,13 +339,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "errno"
|
name = "erased-serde"
|
||||||
version = "0.3.9"
|
version = "0.4.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba"
|
checksum = "24e2389d65ab4fab27dc2a5de7b191e1f6617d1f1c8855c0dc569c94a4cbb18d"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"typeid",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "errno"
|
||||||
|
version = "0.3.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"libc",
|
"libc",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -372,9 +376,9 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "foldhash"
|
name = "foldhash"
|
||||||
version = "0.1.3"
|
version = "0.1.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2"
|
checksum = "a0d2fde1f7b3d48b8395d5f2de76c18a528bd6a9cdde438df747bfcba3e05d6f"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
@@ -499,12 +503,6 @@ version = "0.5.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "hermit-abi"
|
|
||||||
version = "0.3.9"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ident_case"
|
name = "ident_case"
|
||||||
version = "1.0.1"
|
version = "1.0.1"
|
||||||
@@ -525,13 +523,12 @@ checksum = "b248f5224d1d606005e02c97f5aa4e88eeb230488bcc03bc9ca4d7991399f2b5"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "instability"
|
name = "instability"
|
||||||
version = "0.3.3"
|
version = "0.3.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b829f37dead9dc39df40c2d3376c179fdfd2ac771f53f55d3c30dc096a3c0c6e"
|
checksum = "0bf9fed6d91cfb734e7476a06bde8300a1b94e217e1b523b6f0cd1a01998c71d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"indoc",
|
"indoc",
|
||||||
"pretty_assertions",
|
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"syn",
|
"syn",
|
||||||
@@ -566,9 +563,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.166"
|
version = "0.2.169"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c2ccc108bbc0b1331bd061864e7cd823c0cab660bbe6970e66e2c0614decde36"
|
checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libredox"
|
name = "libredox"
|
||||||
@@ -582,9 +579,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.4.15"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89"
|
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lock_api"
|
name = "lock_api"
|
||||||
@@ -598,9 +595,12 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.22"
|
version = "0.4.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
checksum = "3d6ea2a48c204030ee31a7d7fc72c93294c92fe87ecb1789881c9543516e1a0d"
|
||||||
|
dependencies = [
|
||||||
|
"value-bag",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "lru"
|
name = "lru"
|
||||||
@@ -637,11 +637,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio"
|
name = "mio"
|
||||||
version = "1.0.2"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec"
|
checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"hermit-abi",
|
|
||||||
"libc",
|
"libc",
|
||||||
"log",
|
"log",
|
||||||
"wasi",
|
"wasi",
|
||||||
@@ -737,9 +736,9 @@ checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-project-lite"
|
name = "pin-project-lite"
|
||||||
version = "0.2.15"
|
version = "0.2.16"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff"
|
checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pin-utils"
|
name = "pin-utils"
|
||||||
@@ -753,30 +752,20 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "pretty_assertions"
|
|
||||||
version = "1.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3ae130e2f271fbc2ac3a40fb1d07180839cdbbe443c7a27e1e3c13c5cac0116d"
|
|
||||||
dependencies = [
|
|
||||||
"diff",
|
|
||||||
"yansi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.92"
|
version = "1.0.93"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0"
|
checksum = "60946a68e5f9d28b0dc1c21bb8a97ee7d018a8b322fa57838ba31cc878e22d99"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.37"
|
version = "1.0.38"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af"
|
checksum = "0e4dccaaaf89514f546c693ddc140f729f958c247918a13380cccc6078391acc"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
]
|
]
|
||||||
@@ -804,9 +793,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "redox_syscall"
|
name = "redox_syscall"
|
||||||
version = "0.5.7"
|
version = "0.5.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f"
|
checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
]
|
]
|
||||||
@@ -874,22 +863,22 @@ checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustix"
|
name = "rustix"
|
||||||
version = "0.38.41"
|
version = "0.38.43"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6"
|
checksum = "a78891ee6bf2340288408954ac787aa063d8e8817e9f53abb37c695c6d834ef6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bitflags",
|
"bitflags",
|
||||||
"errno",
|
"errno",
|
||||||
"libc",
|
"libc",
|
||||||
"linux-raw-sys",
|
"linux-raw-sys",
|
||||||
"windows-sys 0.52.0",
|
"windows-sys 0.59.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustversion"
|
name = "rustversion"
|
||||||
version = "1.0.18"
|
version = "1.0.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248"
|
checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ryu"
|
name = "ryu"
|
||||||
@@ -905,18 +894,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.215"
|
version = "1.0.217"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
checksum = "02fc4265df13d6fa1d00ecff087228cc0a2b5f3c0e87e258d8b94a156e984c70"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.215"
|
version = "1.0.217"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
checksum = "5a9bf7cf98d04a2b28aead066b7496853d4779c9cc183c440dbac457641e19a0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -924,10 +913,19 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_json"
|
name = "serde_fmt"
|
||||||
version = "1.0.134"
|
version = "1.0.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d00f4175c42ee48b15416f6193a959ba3a0d67fc699a0db9ad12df9f83991c7d"
|
checksum = "e1d4ddca14104cd60529e8c7f7ba71a2c8acd8f7f5cfcdc2faf97eeb7c3010a4"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serde_json"
|
||||||
|
version = "1.0.135"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2b0d7ba2887406110130a978386c4e1befb98c674b4fba677954e4db976630d9"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa",
|
"itoa",
|
||||||
"memchr",
|
"memchr",
|
||||||
@@ -1040,10 +1038,88 @@ dependencies = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "syn"
|
name = "sval"
|
||||||
version = "2.0.89"
|
version = "2.13.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e"
|
checksum = "f6dc0f9830c49db20e73273ffae9b5240f63c42e515af1da1fceefb69fceafd8"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sval_buffer"
|
||||||
|
version = "2.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "429922f7ad43c0ef8fd7309e14d750e38899e32eb7e8da656ea169dd28ee212f"
|
||||||
|
dependencies = [
|
||||||
|
"sval",
|
||||||
|
"sval_ref",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sval_dynamic"
|
||||||
|
version = "2.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "68f16ff5d839396c11a30019b659b0976348f3803db0626f736764c473b50ff4"
|
||||||
|
dependencies = [
|
||||||
|
"sval",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sval_fmt"
|
||||||
|
version = "2.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c01c27a80b6151b0557f9ccbe89c11db571dc5f68113690c1e028d7e974bae94"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"sval",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sval_json"
|
||||||
|
version = "2.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0deef63c70da622b2a8069d8600cf4b05396459e665862e7bdb290fd6cf3f155"
|
||||||
|
dependencies = [
|
||||||
|
"itoa",
|
||||||
|
"ryu",
|
||||||
|
"sval",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sval_nested"
|
||||||
|
version = "2.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a39ce5976ae1feb814c35d290cf7cf8cd4f045782fe1548d6bc32e21f6156e9f"
|
||||||
|
dependencies = [
|
||||||
|
"sval",
|
||||||
|
"sval_buffer",
|
||||||
|
"sval_ref",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sval_ref"
|
||||||
|
version = "2.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bb7c6ee3751795a728bc9316a092023529ffea1783499afbc5c66f5fabebb1fa"
|
||||||
|
dependencies = [
|
||||||
|
"sval",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sval_serde"
|
||||||
|
version = "2.13.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2a5572d0321b68109a343634e3a5d576bf131b82180c6c442dee06349dfc652a"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
"sval",
|
||||||
|
"sval_nested",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "2.0.96"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1115,7 +1191,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "timr-tui"
|
name = "timr-tui"
|
||||||
version = "1.0.0"
|
version = "1.1.0-alpha"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap",
|
"clap",
|
||||||
"color-eyre",
|
"color-eyre",
|
||||||
@@ -1136,9 +1212,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio"
|
name = "tokio"
|
||||||
version = "1.41.1"
|
version = "1.43.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33"
|
checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"backtrace",
|
"backtrace",
|
||||||
"bytes",
|
"bytes",
|
||||||
@@ -1154,9 +1230,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-macros"
|
name = "tokio-macros"
|
||||||
version = "2.4.0"
|
version = "2.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@@ -1165,9 +1241,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-stream"
|
name = "tokio-stream"
|
||||||
version = "0.1.16"
|
version = "0.1.17"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1"
|
checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures-core",
|
"futures-core",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
@@ -1176,9 +1252,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-util"
|
name = "tokio-util"
|
||||||
version = "0.7.12"
|
version = "0.7.13"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a"
|
checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"futures-core",
|
"futures-core",
|
||||||
@@ -1258,6 +1334,12 @@ dependencies = [
|
|||||||
"tracing-log",
|
"tracing-log",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "typeid"
|
||||||
|
version = "1.0.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0e13db2e0ccd5e14a544e8a246ba2312cd25223f616442d7f2cb0e3db614236e"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-ident"
|
name = "unicode-ident"
|
||||||
version = "1.0.14"
|
version = "1.0.14"
|
||||||
@@ -1305,6 +1387,42 @@ version = "0.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "value-bag"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "3ef4c4aa54d5d05a279399bfa921ec387b7aba77caf7a682ae8d86785b8fdad2"
|
||||||
|
dependencies = [
|
||||||
|
"value-bag-serde1",
|
||||||
|
"value-bag-sval2",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "value-bag-serde1"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "4bb773bd36fd59c7ca6e336c94454d9c66386416734817927ac93d81cb3c5b0b"
|
||||||
|
dependencies = [
|
||||||
|
"erased-serde",
|
||||||
|
"serde",
|
||||||
|
"serde_fmt",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "value-bag-sval2"
|
||||||
|
version = "1.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "53a916a702cac43a88694c97657d449775667bcd14b70419441d05b7fea4a83a"
|
||||||
|
dependencies = [
|
||||||
|
"sval",
|
||||||
|
"sval_buffer",
|
||||||
|
"sval_dynamic",
|
||||||
|
"sval_fmt",
|
||||||
|
"sval_json",
|
||||||
|
"sval_ref",
|
||||||
|
"sval_serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "wasi"
|
name = "wasi"
|
||||||
version = "0.11.0+wasi-snapshot-preview1"
|
version = "0.11.0+wasi-snapshot-preview1"
|
||||||
@@ -1480,9 +1598,3 @@ name = "windows_x86_64_msvc"
|
|||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "yansi"
|
|
||||||
version = "1.0.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "timr-tui"
|
name = "timr-tui"
|
||||||
version = "1.0.0"
|
version = "1.1.0-alpha"
|
||||||
description = "TUI to organize your time: Pomodoro, Countdown, Timer."
|
description = "TUI to organize your time: Pomodoro, Countdown, Timer."
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
rust-version = "1.82.0"
|
rust-version = "1.84.0"
|
||||||
homepage = "https://github.com/sectore/timr-tui"
|
homepage = "https://github.com/sectore/timr-tui"
|
||||||
repository = "https://github.com/sectore/timr-tui"
|
repository = "https://github.com/sectore/timr-tui"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|||||||
24
flake.lock
generated
24
flake.lock
generated
@@ -2,11 +2,11 @@
|
|||||||
"nodes": {
|
"nodes": {
|
||||||
"crane": {
|
"crane": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1733286231,
|
"lastModified": 1736566337,
|
||||||
"narHash": "sha256-mlIDSv1/jqWnH8JTiOV7GMUNPCXL25+6jmD+7hdxx5o=",
|
"narHash": "sha256-SC0eDcZPqISVt6R0UfGPyQLrI0+BppjjtQ3wcSlk0oI=",
|
||||||
"owner": "ipetkov",
|
"owner": "ipetkov",
|
||||||
"repo": "crane",
|
"repo": "crane",
|
||||||
"rev": "af1556ecda8bcf305820f68ec2f9d77b41d9cc80",
|
"rev": "9172acc1ee6c7e1cbafc3044ff850c568c75a5a3",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -23,11 +23,11 @@
|
|||||||
"rust-analyzer-src": "rust-analyzer-src"
|
"rust-analyzer-src": "rust-analyzer-src"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1732689334,
|
"lastModified": 1736577158,
|
||||||
"narHash": "sha256-yKI1KiZ0+bvDvfPTQ1ZT3oP/nIu3jPYm4dnbRd6hYg4=",
|
"narHash": "sha256-ngnAENZ+vmzOFgnj0EDtHj22nuH7MQB+EqzUmdbvaqA=",
|
||||||
"owner": "nix-community",
|
"owner": "nix-community",
|
||||||
"repo": "fenix",
|
"repo": "fenix",
|
||||||
"rev": "a8a983027ca02b363dfc82fbe3f7d9548a8d3dce",
|
"rev": "05dcdb02ea657f81b13d99bd0ca36b09d25f4c43",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -56,11 +56,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1733212471,
|
"lastModified": 1736344531,
|
||||||
"narHash": "sha256-M1+uCoV5igihRfcUKrr1riygbe73/dzNnzPsmaLCmpo=",
|
"narHash": "sha256-8YVQ9ZbSfuUk2bUf2KRj60NRraLPKPS0Q4QFTbc+c2c=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "55d15ad12a74eb7d4646254e13638ad0c4128776",
|
"rev": "bffc22eb12172e6db3c5dde9e3e5628f8e3e7912",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -81,11 +81,11 @@
|
|||||||
"rust-analyzer-src": {
|
"rust-analyzer-src": {
|
||||||
"flake": false,
|
"flake": false,
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1732633904,
|
"lastModified": 1736517563,
|
||||||
"narHash": "sha256-7VKcoLug9nbAN2txqVksWHHJplqK9Ou8dXjIZAIYSGc=",
|
"narHash": "sha256-YJ5ajpMsyXITc91ZfnI0Mdocd+tmCFkZ3BLozUkB44M=",
|
||||||
"owner": "rust-lang",
|
"owner": "rust-lang",
|
||||||
"repo": "rust-analyzer",
|
"repo": "rust-analyzer",
|
||||||
"rev": "8d5e91c94f80c257ce6dbdfba7bd63a5e8a03fa6",
|
"rev": "4f35021ca9a8e7f9ed4344139b9eaf770a2e5725",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
22
flake.nix
22
flake.nix
@@ -1,7 +1,5 @@
|
|||||||
{
|
{
|
||||||
inputs = {
|
inputs = {
|
||||||
# Disable `nixos-unstable` for now, it introduced some `VScode` related errors:
|
|
||||||
# error: function 'buildVscodeExtension' called without required argument 'pname'
|
|
||||||
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
flake-utils.url = "github:numtide/flake-utils";
|
flake-utils.url = "github:numtide/flake-utils";
|
||||||
crane.url = "github:ipetkov/crane";
|
crane.url = "github:ipetkov/crane";
|
||||||
@@ -20,12 +18,12 @@
|
|||||||
}:
|
}:
|
||||||
flake-utils.lib.eachDefaultSystem (system: let
|
flake-utils.lib.eachDefaultSystem (system: let
|
||||||
pkgs = nixpkgs.legacyPackages.${system};
|
pkgs = nixpkgs.legacyPackages.${system};
|
||||||
# Using stable toolchain as base
|
|
||||||
toolchain = with fenix.packages.${system};
|
toolchain = with fenix.packages.${system};
|
||||||
combine [
|
combine [
|
||||||
minimal.rustc
|
minimal.rustc
|
||||||
minimal.cargo
|
minimal.cargo
|
||||||
targets.x86_64-pc-windows-gnu.latest.rust-std
|
targets.x86_64-pc-windows-gnu.latest.rust-std
|
||||||
|
targets.x86_64-unknown-linux-musl.latest.rust-std
|
||||||
];
|
];
|
||||||
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
|
craneLib = (crane.mkLib pkgs).overrideToolchain toolchain;
|
||||||
|
|
||||||
@@ -35,19 +33,24 @@
|
|||||||
cargoArtifacts = craneLib.buildDepsOnly {
|
cargoArtifacts = craneLib.buildDepsOnly {
|
||||||
src = craneLib.cleanCargoSource ./.;
|
src = craneLib.cleanCargoSource ./.;
|
||||||
};
|
};
|
||||||
|
strictDeps = true;
|
||||||
doCheck = false; # skip tests during nix build
|
doCheck = false; # skip tests during nix build
|
||||||
};
|
};
|
||||||
|
|
||||||
# Native build
|
# Native build
|
||||||
timr = craneLib.buildPackage commonArgs;
|
timr = craneLib.buildPackage commonArgs;
|
||||||
|
|
||||||
|
# Linux build w/ statically linked binaries
|
||||||
|
staticLinuxBuild = craneLib.buildPackage (commonArgs
|
||||||
|
// {
|
||||||
|
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
|
||||||
|
CARGO_BUILD_RUSTFLAGS = "-C target-feature=+crt-static";
|
||||||
|
});
|
||||||
|
|
||||||
# Windows cross-compilation build
|
# Windows cross-compilation build
|
||||||
# @see https://crane.dev/examples/cross-windows.html
|
# @see https://crane.dev/examples/cross-windows.html
|
||||||
crossBuild = craneLib.buildPackage {
|
windowsBuild = craneLib.buildPackage {
|
||||||
src = craneLib.cleanCargoSource ./.;
|
inherit (commonArgs) src strictDeps doCheck;
|
||||||
|
|
||||||
strictDeps = true;
|
|
||||||
doCheck = false;
|
|
||||||
|
|
||||||
CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu";
|
CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu";
|
||||||
|
|
||||||
@@ -68,7 +71,8 @@
|
|||||||
packages = {
|
packages = {
|
||||||
inherit timr;
|
inherit timr;
|
||||||
default = timr;
|
default = timr;
|
||||||
windows = crossBuild;
|
linuxStatic = staticLinuxBuild;
|
||||||
|
windows = windowsBuild;
|
||||||
};
|
};
|
||||||
|
|
||||||
# Development shell with all necessary tools
|
# Development shell with all necessary tools
|
||||||
|
|||||||
38
src/app.rs
38
src/app.rs
@@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
args::Args,
|
args::Args,
|
||||||
common::{AppTime, AppTimeFormat, Content, Style},
|
common::{AppEditMode, AppTime, AppTimeFormat, Content, Style},
|
||||||
constants::TICK_VALUE_MS,
|
constants::TICK_VALUE_MS,
|
||||||
events::{Event, EventHandler, Events},
|
events::{Event, EventHandler, Events},
|
||||||
storage::AppStorage,
|
storage::AppStorage,
|
||||||
@@ -112,10 +112,11 @@ impl App {
|
|||||||
with_decis,
|
with_decis,
|
||||||
pomodoro_mode,
|
pomodoro_mode,
|
||||||
} = args;
|
} = args;
|
||||||
|
let app_time = get_app_time();
|
||||||
Self {
|
Self {
|
||||||
mode: Mode::Running,
|
mode: Mode::Running,
|
||||||
content,
|
content,
|
||||||
app_time: get_app_time(),
|
app_time,
|
||||||
style,
|
style,
|
||||||
with_decis,
|
with_decis,
|
||||||
countdown: CountdownState::new(
|
countdown: CountdownState::new(
|
||||||
@@ -126,6 +127,7 @@ impl App {
|
|||||||
with_decis,
|
with_decis,
|
||||||
}),
|
}),
|
||||||
elapsed_value_countdown,
|
elapsed_value_countdown,
|
||||||
|
app_time,
|
||||||
),
|
),
|
||||||
timer: TimerState::new(ClockState::<clock::Timer>::new(ClockStateArgs {
|
timer: TimerState::new(ClockState::<clock::Timer>::new(ClockStateArgs {
|
||||||
initial_value: Duration::ZERO,
|
initial_value: Duration::ZERO,
|
||||||
@@ -150,6 +152,7 @@ impl App {
|
|||||||
if let Some(event) = events.next().await {
|
if let Some(event) = events.next().await {
|
||||||
if matches!(event, Event::Tick) {
|
if matches!(event, Event::Tick) {
|
||||||
self.app_time = get_app_time();
|
self.app_time = get_app_time();
|
||||||
|
self.countdown.set_app_time(self.app_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pipe events into subviews and handle only 'unhandled' events afterwards
|
// Pipe events into subviews and handle only 'unhandled' events afterwards
|
||||||
@@ -175,11 +178,32 @@ impl App {
|
|||||||
self.mode != Mode::Quit
|
self.mode != Mode::Quit
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_edit_mode(&self) -> bool {
|
fn get_edit_mode(&self) -> AppEditMode {
|
||||||
match self.content {
|
match self.content {
|
||||||
Content::Countdown => self.countdown.get_clock().is_edit_mode(),
|
Content::Countdown => {
|
||||||
Content::Timer => self.timer.get_clock().is_edit_mode(),
|
if self.countdown.is_clock_edit_mode() {
|
||||||
Content::Pomodoro => self.pomodoro.get_clock().is_edit_mode(),
|
AppEditMode::Clock
|
||||||
|
} else if self.countdown.is_time_edit_mode() {
|
||||||
|
AppEditMode::Time
|
||||||
|
} else {
|
||||||
|
AppEditMode::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Content::Timer => {
|
||||||
|
if self.timer.get_clock().is_edit_mode() {
|
||||||
|
AppEditMode::Clock
|
||||||
|
} else {
|
||||||
|
AppEditMode::None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Content::Pomodoro => {
|
||||||
|
if self.pomodoro.get_clock().is_edit_mode() {
|
||||||
|
AppEditMode::Clock
|
||||||
|
} else {
|
||||||
|
AppEditMode::None
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,7 +322,7 @@ impl StatefulWidget for AppWidget {
|
|||||||
Footer {
|
Footer {
|
||||||
running_clock: state.clock_is_running(),
|
running_clock: state.clock_is_running(),
|
||||||
selected_content: state.content,
|
selected_content: state.content,
|
||||||
edit_mode: state.is_edit_mode(),
|
app_edit_mode: state.get_edit_mode(),
|
||||||
app_time: state.app_time,
|
app_time: state.app_time,
|
||||||
}
|
}
|
||||||
.render(v2, buf, &mut state.footer);
|
.render(v2, buf, &mut state.footer);
|
||||||
|
|||||||
@@ -128,6 +128,13 @@ impl AppTime {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub enum AppEditMode {
|
||||||
|
None,
|
||||||
|
Clock,
|
||||||
|
Time,
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,10 @@ pub const MINS_PER_HOUR: u64 = 60;
|
|||||||
// https://doc.rust-lang.org/src/core/time.rs.html#36
|
// https://doc.rust-lang.org/src/core/time.rs.html#36
|
||||||
const HOURS_PER_DAY: u64 = 24;
|
const HOURS_PER_DAY: u64 = 24;
|
||||||
|
|
||||||
|
// max. 99:59:59
|
||||||
|
pub const MAX_DURATION: Duration =
|
||||||
|
Duration::from_secs(100 * MINS_PER_HOUR * SECS_PER_MINUTE).saturating_sub(ONE_SECOND);
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialOrd)]
|
#[derive(Debug, Clone, Copy, PartialOrd)]
|
||||||
pub struct DurationEx {
|
pub struct DurationEx {
|
||||||
inner: Duration,
|
inner: Duration,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ pub mod clock_elements_test;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
pub mod clock_test;
|
pub mod clock_test;
|
||||||
pub mod countdown;
|
pub mod countdown;
|
||||||
|
pub mod edit_time;
|
||||||
pub mod footer;
|
pub mod footer;
|
||||||
pub mod header;
|
pub mod header;
|
||||||
pub mod pomodoro;
|
pub mod pomodoro;
|
||||||
|
|||||||
@@ -11,20 +11,13 @@ use ratatui::{
|
|||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
common::Style,
|
common::Style,
|
||||||
duration::{
|
duration::{DurationEx, MAX_DURATION, ONE_DECI_SECOND, ONE_HOUR, ONE_MINUTE, ONE_SECOND},
|
||||||
DurationEx, MINS_PER_HOUR, ONE_DECI_SECOND, ONE_HOUR, ONE_MINUTE, ONE_SECOND,
|
|
||||||
SECS_PER_MINUTE,
|
|
||||||
},
|
|
||||||
utils::center_horizontal,
|
utils::center_horizontal,
|
||||||
widgets::clock_elements::{
|
widgets::clock_elements::{
|
||||||
Colon, Digit, Dot, COLON_WIDTH, DIGIT_HEIGHT, DIGIT_WIDTH, DOT_WIDTH,
|
Colon, Digit, Dot, COLON_WIDTH, DIGIT_HEIGHT, DIGIT_SPACE_WIDTH, DIGIT_WIDTH, DOT_WIDTH,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
// max. 99:59:59
|
|
||||||
const MAX_DURATION: Duration =
|
|
||||||
Duration::from_secs(100 * MINS_PER_HOUR * SECS_PER_MINUTE).saturating_sub(ONE_SECOND);
|
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone, Display, PartialEq, Eq)]
|
#[derive(Debug, Copy, Clone, Display, PartialEq, Eq)]
|
||||||
pub enum Time {
|
pub enum Time {
|
||||||
Decis,
|
Decis,
|
||||||
@@ -128,6 +121,11 @@ impl<T> ClockState<T> {
|
|||||||
&self.current_value
|
&self.current_value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_current_value(&mut self, duration: DurationEx) {
|
||||||
|
self.current_value = duration;
|
||||||
|
self.update_format();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn toggle_edit(&mut self) {
|
pub fn toggle_edit(&mut self) {
|
||||||
self.mode = match self.mode.clone() {
|
self.mode = match self.mode.clone() {
|
||||||
Mode::Editable(_, prev) => {
|
Mode::Editable(_, prev) => {
|
||||||
@@ -463,8 +461,6 @@ impl ClockState<Timer> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const SPACE_WIDTH: u16 = 1;
|
|
||||||
|
|
||||||
pub struct ClockWidget<T>
|
pub struct ClockWidget<T>
|
||||||
where
|
where
|
||||||
T: std::fmt::Debug,
|
T: std::fmt::Debug,
|
||||||
@@ -499,15 +495,15 @@ where
|
|||||||
Format::HhMmSs => add_decis(
|
Format::HhMmSs => add_decis(
|
||||||
vec![
|
vec![
|
||||||
DIGIT_WIDTH, // h
|
DIGIT_WIDTH, // h
|
||||||
SPACE_WIDTH, // (space)
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
DIGIT_WIDTH, // h
|
DIGIT_WIDTH, // h
|
||||||
COLON_WIDTH, // :
|
COLON_WIDTH, // :
|
||||||
DIGIT_WIDTH, // m
|
DIGIT_WIDTH, // m
|
||||||
SPACE_WIDTH, // (space)
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
DIGIT_WIDTH, // m
|
DIGIT_WIDTH, // m
|
||||||
COLON_WIDTH, // :
|
COLON_WIDTH, // :
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
SPACE_WIDTH, // (space)
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
],
|
],
|
||||||
with_decis,
|
with_decis,
|
||||||
@@ -517,11 +513,11 @@ where
|
|||||||
DIGIT_WIDTH, // h
|
DIGIT_WIDTH, // h
|
||||||
COLON_WIDTH, // :
|
COLON_WIDTH, // :
|
||||||
DIGIT_WIDTH, // m
|
DIGIT_WIDTH, // m
|
||||||
SPACE_WIDTH, // (space)
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
DIGIT_WIDTH, // m
|
DIGIT_WIDTH, // m
|
||||||
COLON_WIDTH, // :
|
COLON_WIDTH, // :
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
SPACE_WIDTH, // (space)
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
],
|
],
|
||||||
with_decis,
|
with_decis,
|
||||||
@@ -529,11 +525,11 @@ where
|
|||||||
Format::MmSs => add_decis(
|
Format::MmSs => add_decis(
|
||||||
vec![
|
vec![
|
||||||
DIGIT_WIDTH, // m
|
DIGIT_WIDTH, // m
|
||||||
SPACE_WIDTH, // (space)
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
DIGIT_WIDTH, // m
|
DIGIT_WIDTH, // m
|
||||||
COLON_WIDTH, // :
|
COLON_WIDTH, // :
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
SPACE_WIDTH, // (space)
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
],
|
],
|
||||||
with_decis,
|
with_decis,
|
||||||
@@ -543,7 +539,7 @@ where
|
|||||||
DIGIT_WIDTH, // m
|
DIGIT_WIDTH, // m
|
||||||
COLON_WIDTH, // :
|
COLON_WIDTH, // :
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
SPACE_WIDTH, // (space)
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
],
|
],
|
||||||
with_decis,
|
with_decis,
|
||||||
@@ -551,7 +547,7 @@ where
|
|||||||
Format::Ss => add_decis(
|
Format::Ss => add_decis(
|
||||||
vec![
|
vec![
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
SPACE_WIDTH, // (space)
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
DIGIT_WIDTH, // s
|
DIGIT_WIDTH, // s
|
||||||
],
|
],
|
||||||
with_decis,
|
with_decis,
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ pub const DIGIT_WIDTH: u16 = DIGIT_SIZE as u16;
|
|||||||
pub const DIGIT_HEIGHT: u16 = DIGIT_SIZE as u16 + 1 /* border height */;
|
pub const DIGIT_HEIGHT: u16 = DIGIT_SIZE as u16 + 1 /* border height */;
|
||||||
pub const COLON_WIDTH: u16 = 4; // incl. padding left + padding right
|
pub const COLON_WIDTH: u16 = 4; // incl. padding left + padding right
|
||||||
pub const DOT_WIDTH: u16 = 4; // incl. padding left + padding right
|
pub const DOT_WIDTH: u16 = 4; // incl. padding left + padding right
|
||||||
|
pub const DIGIT_SPACE_WIDTH: u16 = 1; // space between digits
|
||||||
|
|
||||||
#[rustfmt::skip]
|
#[rustfmt::skip]
|
||||||
const DIGIT_0: [u8; DIGIT_SIZE * DIGIT_SIZE] = [
|
const DIGIT_0: [u8; DIGIT_SIZE * DIGIT_SIZE] = [
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
use crate::{
|
||||||
|
common::{AppTime, Style},
|
||||||
|
constants::TICK_VALUE_MS,
|
||||||
|
duration::{DurationEx, MAX_DURATION},
|
||||||
|
events::{Event, EventHandler},
|
||||||
|
utils::center,
|
||||||
|
widgets::{
|
||||||
|
clock::{self, ClockState, ClockStateArgs, ClockWidget, Mode as ClockMode},
|
||||||
|
edit_time::EditTimeState,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use crossterm::event::KeyModifiers;
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
crossterm::event::KeyCode,
|
crossterm::event::KeyCode,
|
||||||
@@ -5,16 +17,12 @@ use ratatui::{
|
|||||||
text::Line,
|
text::Line,
|
||||||
widgets::{StatefulWidget, Widget},
|
widgets::{StatefulWidget, Widget},
|
||||||
};
|
};
|
||||||
use std::{cmp::max, time::Duration};
|
|
||||||
|
|
||||||
use crate::{
|
use std::ops::Sub;
|
||||||
common::Style,
|
use std::{cmp::max, time::Duration};
|
||||||
constants::TICK_VALUE_MS,
|
use time::OffsetDateTime;
|
||||||
duration::DurationEx,
|
|
||||||
events::{Event, EventHandler},
|
use super::edit_time::{EditTimeStateArgs, EditTimeWidget};
|
||||||
utils::center,
|
|
||||||
widgets::clock::{self, ClockState, ClockStateArgs, ClockWidget, Mode as ClockMode},
|
|
||||||
};
|
|
||||||
|
|
||||||
/// State for Countdown Widget
|
/// State for Countdown Widget
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
@@ -23,10 +31,17 @@ pub struct CountdownState {
|
|||||||
clock: ClockState<clock::Countdown>,
|
clock: ClockState<clock::Countdown>,
|
||||||
/// clock to count time after `DONE` - similar to Mission Elapsed Time (MET)
|
/// clock to count time after `DONE` - similar to Mission Elapsed Time (MET)
|
||||||
elapsed_clock: ClockState<clock::Timer>,
|
elapsed_clock: ClockState<clock::Timer>,
|
||||||
|
app_time: AppTime,
|
||||||
|
/// Edit by local time
|
||||||
|
edit_time: Option<EditTimeState>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CountdownState {
|
impl CountdownState {
|
||||||
pub fn new(clock: ClockState<clock::Countdown>, elapsed_value: Duration) -> Self {
|
pub fn new(
|
||||||
|
clock: ClockState<clock::Countdown>,
|
||||||
|
elapsed_value: Duration,
|
||||||
|
app_time: AppTime,
|
||||||
|
) -> Self {
|
||||||
Self {
|
Self {
|
||||||
clock,
|
clock,
|
||||||
elapsed_clock: ClockState::<clock::Timer>::new(ClockStateArgs {
|
elapsed_clock: ClockState::<clock::Timer>::new(ClockStateArgs {
|
||||||
@@ -43,6 +58,8 @@ impl CountdownState {
|
|||||||
} else {
|
} else {
|
||||||
ClockMode::Initial
|
ClockMode::Initial
|
||||||
}),
|
}),
|
||||||
|
app_time,
|
||||||
|
edit_time: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,11 +79,55 @@ impl CountdownState {
|
|||||||
pub fn get_elapsed_value(&self) -> &DurationEx {
|
pub fn get_elapsed_value(&self) -> &DurationEx {
|
||||||
self.elapsed_clock.get_current_value()
|
self.elapsed_clock.get_current_value()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_app_time(&mut self, app_time: AppTime) {
|
||||||
|
self.app_time = app_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn time_to_edit(&self) -> OffsetDateTime {
|
||||||
|
// get current value
|
||||||
|
let d: Duration = (*self.clock.get_current_value()).into();
|
||||||
|
// transform
|
||||||
|
let dd = time::Duration::try_from(d).unwrap_or(time::Duration::ZERO);
|
||||||
|
// substract from `app_time`
|
||||||
|
OffsetDateTime::from(self.app_time).saturating_add(dd)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn min_time_to_edit(&self) -> OffsetDateTime {
|
||||||
|
OffsetDateTime::from(self.app_time)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn max_time_to_edit(&self) -> OffsetDateTime {
|
||||||
|
OffsetDateTime::from(self.app_time)
|
||||||
|
.saturating_add(time::Duration::try_from(MAX_DURATION).unwrap_or(time::Duration::ZERO))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn edit_time_done(&mut self, edit_time: &mut EditTimeState) {
|
||||||
|
// get diff
|
||||||
|
let d: time::Duration = edit_time
|
||||||
|
.get_time()
|
||||||
|
.sub(OffsetDateTime::from(self.app_time));
|
||||||
|
// transfrom
|
||||||
|
let dx: DurationEx = Duration::try_from(d).unwrap_or(Duration::ZERO).into();
|
||||||
|
// update clock
|
||||||
|
self.clock.set_current_value(dx);
|
||||||
|
// remove `edit_time`
|
||||||
|
self.edit_time = None;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_clock_edit_mode(&self) -> bool {
|
||||||
|
self.clock.is_edit_mode()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_time_edit_mode(&self) -> bool {
|
||||||
|
self.edit_time.is_some()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EventHandler for CountdownState {
|
impl EventHandler for CountdownState {
|
||||||
fn update(&mut self, event: Event) -> Option<Event> {
|
fn update(&mut self, event: Event) -> Option<Event> {
|
||||||
let edit_mode = self.clock.is_edit_mode();
|
let is_edit_clock = self.clock.is_edit_mode();
|
||||||
|
let is_edit_time = self.edit_time.is_some();
|
||||||
match event {
|
match event {
|
||||||
Event::Tick => {
|
Event::Tick => {
|
||||||
if !self.clock.is_done() {
|
if !self.clock.is_done() {
|
||||||
@@ -77,12 +138,24 @@ impl EventHandler for CountdownState {
|
|||||||
self.elapsed_clock.run();
|
self.elapsed_clock.run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
let min_time = self.min_time_to_edit();
|
||||||
|
let max_time = self.max_time_to_edit();
|
||||||
|
if let Some(edit_time) = &mut self.edit_time {
|
||||||
|
edit_time.set_min_time(min_time);
|
||||||
|
edit_time.set_max_time(max_time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Event::Key(key) => match key.code {
|
Event::Key(key) => match key.code {
|
||||||
KeyCode::Char('r') => {
|
KeyCode::Char('r') => {
|
||||||
// reset both clocks
|
// reset both clocks to use intial values
|
||||||
self.clock.reset();
|
self.clock.reset();
|
||||||
self.elapsed_clock.reset();
|
self.elapsed_clock.reset();
|
||||||
|
|
||||||
|
// reset `edit_time` back initial value
|
||||||
|
let time = self.time_to_edit();
|
||||||
|
if let Some(edit_time) = &mut self.edit_time {
|
||||||
|
edit_time.set_time(time);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
KeyCode::Char('s') => {
|
KeyCode::Char('s') => {
|
||||||
// toggle pause status depending on which clock is running
|
// toggle pause status depending on which clock is running
|
||||||
@@ -91,30 +164,92 @@ impl EventHandler for CountdownState {
|
|||||||
} else {
|
} else {
|
||||||
self.elapsed_clock.toggle_pause();
|
self.elapsed_clock.toggle_pause();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// finish `edit_time` and continue for using `clock`
|
||||||
|
if let Some(edit_time) = &mut self.edit_time.clone() {
|
||||||
|
self.edit_time_done(edit_time);
|
||||||
}
|
}
|
||||||
KeyCode::Char('e') => {
|
}
|
||||||
|
// STRG + e => toggle edit time
|
||||||
|
KeyCode::Char('e') if key.modifiers.contains(KeyModifiers::CONTROL) => {
|
||||||
|
// stop editing clock
|
||||||
|
if self.clock.is_edit_mode() {
|
||||||
|
// toggle edit mode
|
||||||
self.clock.toggle_edit();
|
self.clock.toggle_edit();
|
||||||
// stop + reset timer entering `edit` mode
|
}
|
||||||
|
|
||||||
|
if let Some(edit_time) = &mut self.edit_time.clone() {
|
||||||
|
self.edit_time_done(edit_time)
|
||||||
|
} else {
|
||||||
|
// update `edit_time`
|
||||||
|
self.edit_time = Some(EditTimeState::new(EditTimeStateArgs {
|
||||||
|
time: self.time_to_edit(),
|
||||||
|
min: self.min_time_to_edit(),
|
||||||
|
max: self.max_time_to_edit(),
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop `clock`
|
||||||
|
if self.clock.is_running() {
|
||||||
|
self.clock.toggle_pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
// stop `elapsed_clock`
|
||||||
if self.elapsed_clock.is_running() {
|
if self.elapsed_clock.is_running() {
|
||||||
self.elapsed_clock.toggle_pause();
|
self.elapsed_clock.toggle_pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
KeyCode::Left if edit_mode => {
|
// STRG + e => toggle edit clock
|
||||||
|
KeyCode::Char('e') => {
|
||||||
|
// toggle edit mode
|
||||||
|
self.clock.toggle_edit();
|
||||||
|
|
||||||
|
// stop `elapsed_clock`
|
||||||
|
if self.elapsed_clock.is_running() {
|
||||||
|
self.elapsed_clock.toggle_pause();
|
||||||
|
}
|
||||||
|
|
||||||
|
// finish `edit_time` and continue for using `clock`
|
||||||
|
if let Some(edit_time) = &mut self.edit_time.clone() {
|
||||||
|
self.edit_time_done(edit_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
KeyCode::Left if is_edit_clock => {
|
||||||
self.clock.edit_next();
|
self.clock.edit_next();
|
||||||
}
|
}
|
||||||
KeyCode::Right if edit_mode => {
|
KeyCode::Left if is_edit_time => {
|
||||||
|
// safe unwrap because of previous check in `is_edit_time`
|
||||||
|
self.edit_time.as_mut().unwrap().next();
|
||||||
|
}
|
||||||
|
KeyCode::Right if is_edit_clock => {
|
||||||
self.clock.edit_prev();
|
self.clock.edit_prev();
|
||||||
}
|
}
|
||||||
KeyCode::Up if edit_mode => {
|
KeyCode::Right if is_edit_time => {
|
||||||
|
// safe unwrap because of previous check in `is_edit_time`
|
||||||
|
self.edit_time.as_mut().unwrap().prev();
|
||||||
|
}
|
||||||
|
KeyCode::Up if is_edit_clock => {
|
||||||
self.clock.edit_up();
|
self.clock.edit_up();
|
||||||
// whenever `clock`'s value is changed, reset `elapsed_clock`
|
// whenever `clock`'s value is changed, reset `elapsed_clock`
|
||||||
self.elapsed_clock.reset();
|
self.elapsed_clock.reset();
|
||||||
}
|
}
|
||||||
KeyCode::Down if edit_mode => {
|
KeyCode::Up if is_edit_time => {
|
||||||
|
// safe unwrap because of previous check in `is_edit_time`
|
||||||
|
self.edit_time.as_mut().unwrap().up();
|
||||||
|
// whenever `clock`'s value is changed, reset `elapsed_clock`
|
||||||
|
self.elapsed_clock.reset();
|
||||||
|
}
|
||||||
|
KeyCode::Down if is_edit_clock => {
|
||||||
self.clock.edit_down();
|
self.clock.edit_down();
|
||||||
// whenever clock value is changed, reset timer
|
// whenever clock value is changed, reset timer
|
||||||
self.elapsed_clock.reset();
|
self.elapsed_clock.reset();
|
||||||
}
|
}
|
||||||
|
KeyCode::Down if is_edit_time => {
|
||||||
|
// safe unwrap because of previous check in `is_edit_time`
|
||||||
|
self.edit_time.as_mut().unwrap().down();
|
||||||
|
// whenever clock value is changed, reset timer
|
||||||
|
self.elapsed_clock.reset();
|
||||||
|
}
|
||||||
_ => return Some(event),
|
_ => return Some(event),
|
||||||
},
|
},
|
||||||
_ => return Some(event),
|
_ => return Some(event),
|
||||||
@@ -127,11 +262,40 @@ pub struct Countdown {
|
|||||||
pub style: Style,
|
pub style: Style,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn human_days_diff(a: &OffsetDateTime, b: &OffsetDateTime) -> String {
|
||||||
|
let days_diff = (a.date() - b.date()).whole_days();
|
||||||
|
match days_diff {
|
||||||
|
0 => "today".to_owned(),
|
||||||
|
1 => "tomorrow".to_owned(),
|
||||||
|
n => format!("+{}days", n),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl StatefulWidget for Countdown {
|
impl StatefulWidget for Countdown {
|
||||||
type State = CountdownState;
|
type State = CountdownState;
|
||||||
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||||
let clock = ClockWidget::new(self.style);
|
// render `edit_time` OR `clock`
|
||||||
|
if let Some(edit_time) = &mut state.edit_time {
|
||||||
|
let label = Line::raw(
|
||||||
|
format!(
|
||||||
|
"Countdown {} {}",
|
||||||
|
edit_time.get_selected().clone(),
|
||||||
|
human_days_diff(edit_time.get_time(), &state.app_time.into())
|
||||||
|
)
|
||||||
|
.to_uppercase(),
|
||||||
|
);
|
||||||
|
let widget = EditTimeWidget::new(self.style);
|
||||||
|
let area = center(
|
||||||
|
area,
|
||||||
|
Constraint::Length(max(widget.get_width(), label.width() as u16)),
|
||||||
|
Constraint::Length(widget.get_height() + 1 /* height of label */),
|
||||||
|
);
|
||||||
|
let [v1, v2] =
|
||||||
|
Layout::vertical(Constraint::from_lengths([widget.get_height(), 1])).areas(area);
|
||||||
|
|
||||||
|
widget.render(v1, buf, edit_time);
|
||||||
|
label.centered().render(v2, buf);
|
||||||
|
} else {
|
||||||
let label = Line::raw(
|
let label = Line::raw(
|
||||||
if state.clock.is_done() {
|
if state.clock.is_done() {
|
||||||
if state.clock.with_decis {
|
if state.clock.with_decis {
|
||||||
@@ -155,19 +319,20 @@ impl StatefulWidget for Countdown {
|
|||||||
}
|
}
|
||||||
.to_uppercase(),
|
.to_uppercase(),
|
||||||
);
|
);
|
||||||
|
let widget = ClockWidget::new(self.style);
|
||||||
let area = center(
|
let area = center(
|
||||||
area,
|
area,
|
||||||
Constraint::Length(max(
|
Constraint::Length(max(
|
||||||
clock.get_width(&state.clock.get_format(), state.clock.with_decis),
|
widget.get_width(&state.clock.get_format(), state.clock.with_decis),
|
||||||
label.width() as u16,
|
label.width() as u16,
|
||||||
)),
|
)),
|
||||||
Constraint::Length(clock.get_height() + 1 /* height of label */),
|
Constraint::Length(widget.get_height() + 1 /* height of label */),
|
||||||
);
|
);
|
||||||
let [v1, v2] =
|
let [v1, v2] =
|
||||||
Layout::vertical(Constraint::from_lengths([clock.get_height(), 1])).areas(area);
|
Layout::vertical(Constraint::from_lengths([widget.get_height(), 1])).areas(area);
|
||||||
|
|
||||||
clock.render(v1, buf, &mut state.clock);
|
widget.render(v1, buf, &mut state.clock);
|
||||||
label.centered().render(v2, buf);
|
label.centered().render(v2, buf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|||||||
231
src/widgets/edit_time.rs
Normal file
231
src/widgets/edit_time.rs
Normal file
@@ -0,0 +1,231 @@
|
|||||||
|
use std::fmt;
|
||||||
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
|
use ratatui::{
|
||||||
|
buffer::Buffer,
|
||||||
|
layout::{Constraint, Layout, Rect},
|
||||||
|
widgets::{StatefulWidget, Widget},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
common::Style,
|
||||||
|
widgets::clock_elements::{Colon, Digit, COLON_WIDTH, DIGIT_SPACE_WIDTH, DIGIT_WIDTH},
|
||||||
|
};
|
||||||
|
|
||||||
|
use super::clock_elements::DIGIT_HEIGHT;
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum Selected {
|
||||||
|
Seconds,
|
||||||
|
Minutes,
|
||||||
|
Hours,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Selected {
|
||||||
|
pub fn next(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Selected::Seconds => Selected::Minutes,
|
||||||
|
Selected::Minutes => Selected::Hours,
|
||||||
|
Selected::Hours => Selected::Seconds,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prev(&self) -> Self {
|
||||||
|
match self {
|
||||||
|
Selected::Seconds => Selected::Hours,
|
||||||
|
Selected::Minutes => Selected::Seconds,
|
||||||
|
Selected::Hours => Selected::Minutes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for Selected {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
match self {
|
||||||
|
Selected::Seconds => write!(f, "[edit seconds]"),
|
||||||
|
Selected::Minutes => write!(f, "[edit minutes]"),
|
||||||
|
Selected::Hours => write!(f, "[edit hours]"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EditTimeState {
|
||||||
|
selected: Selected,
|
||||||
|
time: OffsetDateTime,
|
||||||
|
min: OffsetDateTime,
|
||||||
|
max: OffsetDateTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EditTimeStateArgs {
|
||||||
|
pub time: OffsetDateTime,
|
||||||
|
pub min: OffsetDateTime,
|
||||||
|
pub max: OffsetDateTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EditTimeState {
|
||||||
|
pub fn new(args: EditTimeStateArgs) -> Self {
|
||||||
|
EditTimeState {
|
||||||
|
time: args.time,
|
||||||
|
min: args.min,
|
||||||
|
max: args.max,
|
||||||
|
selected: Selected::Minutes,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_time(&mut self, time: OffsetDateTime) {
|
||||||
|
self.time = time;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_min_time(&mut self, min: OffsetDateTime) {
|
||||||
|
self.min = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn set_max_time(&mut self, min: OffsetDateTime) {
|
||||||
|
self.max = min;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_time(&mut self) -> &OffsetDateTime {
|
||||||
|
&self.time
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_selected(&mut self) -> &Selected {
|
||||||
|
&self.selected
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn next(&mut self) {
|
||||||
|
self.selected = self.selected.next();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn prev(&mut self) {
|
||||||
|
self.selected = self.selected.prev();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn up(&mut self) {
|
||||||
|
self.time = match self.selected {
|
||||||
|
Selected::Seconds => {
|
||||||
|
if self
|
||||||
|
.time
|
||||||
|
.lt(&self.max.saturating_sub(time::Duration::new(1, 0)))
|
||||||
|
{
|
||||||
|
self.time.saturating_add(time::Duration::new(1, 0))
|
||||||
|
} else {
|
||||||
|
self.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Selected::Minutes => {
|
||||||
|
if self
|
||||||
|
.time
|
||||||
|
.lt(&self.max.saturating_sub(time::Duration::new(60, 0)))
|
||||||
|
{
|
||||||
|
self.time.saturating_add(time::Duration::new(60, 0))
|
||||||
|
} else {
|
||||||
|
self.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Selected::Hours => {
|
||||||
|
if self
|
||||||
|
.time
|
||||||
|
.lt(&self.max.saturating_sub(time::Duration::new(60 * 60, 0)))
|
||||||
|
{
|
||||||
|
self.time.saturating_add(time::Duration::new(60 * 60, 0))
|
||||||
|
} else {
|
||||||
|
self.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn down(&mut self) {
|
||||||
|
self.time = match self.selected {
|
||||||
|
Selected::Seconds => {
|
||||||
|
if self
|
||||||
|
.time
|
||||||
|
.ge(&self.min.saturating_add(time::Duration::new(1, 0)))
|
||||||
|
{
|
||||||
|
self.time.saturating_sub(time::Duration::new(1, 0))
|
||||||
|
} else {
|
||||||
|
self.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Selected::Minutes => {
|
||||||
|
if self
|
||||||
|
.time
|
||||||
|
.ge(&self.min.saturating_add(time::Duration::new(60, 0)))
|
||||||
|
{
|
||||||
|
self.time.saturating_sub(time::Duration::new(60, 0))
|
||||||
|
} else {
|
||||||
|
self.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Selected::Hours => {
|
||||||
|
if self
|
||||||
|
.time
|
||||||
|
.ge(&self.min.saturating_add(time::Duration::new(60 * 60, 0)))
|
||||||
|
{
|
||||||
|
self.time.saturating_sub(time::Duration::new(60 * 60, 0))
|
||||||
|
} else {
|
||||||
|
self.time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct EditTimeWidget {
|
||||||
|
style: Style,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EditTimeWidget {
|
||||||
|
pub fn new(style: Style) -> Self {
|
||||||
|
Self { style }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_horizontal_lengths(&self) -> Vec<u16> {
|
||||||
|
vec![
|
||||||
|
DIGIT_WIDTH, // h
|
||||||
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
|
DIGIT_WIDTH, // h
|
||||||
|
COLON_WIDTH, // :
|
||||||
|
DIGIT_WIDTH, // m
|
||||||
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
|
DIGIT_WIDTH, // m
|
||||||
|
COLON_WIDTH, // :
|
||||||
|
DIGIT_WIDTH, // s
|
||||||
|
DIGIT_SPACE_WIDTH, // (space)
|
||||||
|
DIGIT_WIDTH, // s
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_width(&self) -> u16 {
|
||||||
|
self.get_horizontal_lengths().iter().sum()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_height(&self) -> u16 {
|
||||||
|
DIGIT_HEIGHT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StatefulWidget for EditTimeWidget {
|
||||||
|
type State = EditTimeState;
|
||||||
|
fn render(self, area: Rect, buf: &mut Buffer, state: &mut Self::State) {
|
||||||
|
let symbol = self.style.get_digit_symbol();
|
||||||
|
let edit_hours = matches!(state.selected, Selected::Hours);
|
||||||
|
let edit_minutes = matches!(state.selected, Selected::Minutes);
|
||||||
|
let edit_secs = matches!(state.selected, Selected::Seconds);
|
||||||
|
|
||||||
|
let [hh, _, h, c_hm, mm, _, m, c_ms, ss, _, s] =
|
||||||
|
Layout::horizontal(Constraint::from_lengths(self.get_horizontal_lengths())).areas(area);
|
||||||
|
|
||||||
|
Digit::new((state.time.hour() as u64) / 10, edit_hours, symbol).render(hh, buf);
|
||||||
|
Digit::new((state.time.hour() as u64) % 10, edit_hours, symbol).render(h, buf);
|
||||||
|
Colon::new(symbol).render(c_hm, buf);
|
||||||
|
Digit::new((state.time.minute() as u64) / 10, edit_minutes, symbol).render(mm, buf);
|
||||||
|
Digit::new((state.time.minute() as u64) % 10, edit_minutes, symbol).render(m, buf);
|
||||||
|
Colon::new(symbol).render(c_ms, buf);
|
||||||
|
Digit::new((state.time.second() as u64) / 10, edit_secs, symbol).render(ss, buf);
|
||||||
|
Digit::new((state.time.second() as u64) % 10, edit_secs, symbol).render(s, buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
|
|
||||||
use crate::common::{AppTime, AppTimeFormat, Content};
|
use crate::common::{AppEditMode, AppTime, AppTimeFormat, Content};
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
buffer::Buffer,
|
buffer::Buffer,
|
||||||
layout::{Constraint, Layout, Rect},
|
layout::{Constraint, Layout, Rect},
|
||||||
@@ -45,7 +45,7 @@ impl FooterState {
|
|||||||
pub struct Footer {
|
pub struct Footer {
|
||||||
pub running_clock: bool,
|
pub running_clock: bool,
|
||||||
pub selected_content: Content,
|
pub selected_content: Content,
|
||||||
pub edit_mode: bool,
|
pub app_edit_mode: AppEditMode,
|
||||||
pub app_time: AppTime,
|
pub app_time: AppTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -139,21 +139,8 @@ impl StatefulWidget for Footer {
|
|||||||
Style::default().add_modifier(Modifier::BOLD),
|
Style::default().add_modifier(Modifier::BOLD),
|
||||||
)),
|
)),
|
||||||
Cell::from(Line::from({
|
Cell::from(Line::from({
|
||||||
if self.edit_mode {
|
match self.app_edit_mode {
|
||||||
vec![
|
AppEditMode::None => {
|
||||||
Span::from("[e]dit done"),
|
|
||||||
Span::from(SPACE),
|
|
||||||
Span::from(format!(
|
|
||||||
"[{} {}]edit selection",
|
|
||||||
scrollbar::HORIZONTAL.begin,
|
|
||||||
scrollbar::HORIZONTAL.end
|
|
||||||
)), // ← →,
|
|
||||||
Span::from(SPACE),
|
|
||||||
Span::from(format!("[{}]edit up", scrollbar::VERTICAL.begin)), // ↑
|
|
||||||
Span::from(SPACE),
|
|
||||||
Span::from(format!("[{}]edit up", scrollbar::VERTICAL.end)), // ↓,
|
|
||||||
]
|
|
||||||
} else {
|
|
||||||
let mut spans = vec![
|
let mut spans = vec![
|
||||||
Span::from(if self.running_clock {
|
Span::from(if self.running_clock {
|
||||||
"[s]top"
|
"[s]top"
|
||||||
@@ -165,6 +152,12 @@ impl StatefulWidget for Footer {
|
|||||||
Span::from(SPACE),
|
Span::from(SPACE),
|
||||||
Span::from("[e]dit"),
|
Span::from("[e]dit"),
|
||||||
];
|
];
|
||||||
|
if self.selected_content == Content::Countdown {
|
||||||
|
spans.extend_from_slice(&[
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from("[ctrl+e]dit by local time"),
|
||||||
|
]);
|
||||||
|
}
|
||||||
if self.selected_content == Content::Pomodoro {
|
if self.selected_content == Content::Pomodoro {
|
||||||
spans.extend_from_slice(&[
|
spans.extend_from_slice(&[
|
||||||
Span::from(SPACE),
|
Span::from(SPACE),
|
||||||
@@ -173,6 +166,24 @@ impl StatefulWidget for Footer {
|
|||||||
}
|
}
|
||||||
spans
|
spans
|
||||||
}
|
}
|
||||||
|
others => vec![
|
||||||
|
Span::from(match others {
|
||||||
|
AppEditMode::Clock => "[e]dit done",
|
||||||
|
AppEditMode::Time => "[ctrl+e]dit done",
|
||||||
|
_ => "",
|
||||||
|
}),
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from(format!(
|
||||||
|
"[{} {}]edit selection",
|
||||||
|
scrollbar::HORIZONTAL.begin,
|
||||||
|
scrollbar::HORIZONTAL.end
|
||||||
|
)), // ← →,
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from(format!("[{}]edit up", scrollbar::VERTICAL.begin)), // ↑
|
||||||
|
Span::from(SPACE),
|
||||||
|
Span::from(format!("[{}]edit up", scrollbar::VERTICAL.end)), // ↓,
|
||||||
|
],
|
||||||
|
}
|
||||||
})),
|
})),
|
||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
|
|||||||
Reference in New Issue
Block a user