diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
deleted file mode 100644
index 4660d0f..0000000
--- a/.github/workflows/build.yml
+++ /dev/null
@@ -1,75 +0,0 @@
-# What software is installed by default:
-# https://docs.github.com/en/actions/using-github-hosted-runners/using-github-hosted-runners/about-github-hosted-runners#supported-runners-and-hardware-resources
-
-name: build
-
-on:
- push:
- pull_request:
-
-defaults:
- run:
- shell: bash
-
-jobs:
- build:
- strategy:
- matrix:
- os:
- - ubuntu-22.04
- - windows-latest
- - macos-latest
- - macos-13
- runs-on: ${{ matrix.os }}
- steps:
- - name: Check out repo
- uses: actions/checkout@v4
-
- - name: Set up rust
- run: rustup update
-
- - name: Build
- run: cargo build --release
-
- - name: Test
- run: cargo test --release
-
- - name: Record target triple
- run: rustc -vV | awk '/^host/ { print $2 }' > target/release/host
-
- - name: Upload
- uses: actions/upload-artifact@v4
- with:
- name: cove-${{ matrix.os }}
- path: |
- target/release/cove
- target/release/cove.exe
- target/release/host
-
- release:
- runs-on: ubuntu-latest
- if: ${{ startsWith(github.ref, 'refs/tags/v') }}
- needs:
- - build
- permissions:
- contents: write
- steps:
- - name: Download artifacts
- uses: actions/download-artifact@v4
-
- - name: Zip artifacts
- run: |
- chmod +x cove-ubuntu-22.04/cove
- chmod +x cove-windows-latest/cove.exe
- chmod +x cove-macos-latest/cove
- chmod +x cove-macos-13/cove
- zip -jr "cove-$(cat cove-ubuntu-22.04/host).zip" cove-ubuntu-22.04/cove
- zip -jr "cove-$(cat cove-windows-latest/host).zip" cove-windows-latest/cove.exe
- zip -jr "cove-$(cat cove-macos-latest/host).zip" cove-macos-latest/cove
- zip -jr "cove-$(cat cove-macos-13/host).zip" cove-macos-13/cove
-
- - name: Create new release
- uses: softprops/action-gh-release@v2
- with:
- body: Automated release, see [CHANGELOG.md](CHANGELOG.md) for more details.
- files: "*.zip"
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 4e428aa..0000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,8 +0,0 @@
-{
- "files.insertFinalNewline": true,
- "rust-analyzer.cargo.features": "all",
- "rust-analyzer.imports.granularity.enforce": true,
- "rust-analyzer.imports.granularity.group": "crate",
- "rust-analyzer.imports.group.enable": true,
- "evenBetterToml.formatter.columnWidth": 100,
-}
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3f9ce8c..dfc25da 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,286 +4,28 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
Procedure when bumping the version number:
-
1. Update dependencies in a separate commit
2. Set version number in `Cargo.toml`
3. Add new section in this changelog
-4. Run `cargo run help-config > CONFIG.md`
-5. Commit with message `Bump version to X.Y.Z`
-6. Create tag named `vX.Y.Z`
-7. Push `master` and the new tag
+4. Commit with message `Bump version to X.Y.Z`
+5. Create tag named `vX.Y.Z`
+6. Fast-forward branch `latest`
+7. Push `master`, `latest` and the new tag
## Unreleased
-### Changed
-
-- Display emoji user id hashes in the nick list
-- Compile linux binary with older glibc version
-
-## v0.9.3 - 2025-05-31
-
-### Added
-
-- Key bindings for emoji-based user id hashing
-
-### Fixed
-
-- `keys.rooms.action.connect_autojoin` connecting to non-autojoin rooms
-
-## v0.9.2 - 2025-03-14
-
-### Added
-
-- `bell_on_mention` config option
-
-## v0.9.1 - 2025-03-01
-
-### Fixed
-
-- Rendering glitches with unicode-based width estimation
-
-## v0.9.0 - 2025-02-23
-
-### Added
-
-- Unicode-based grapheme width estimation method
- - `width_estimation_method` config option
- - `--width-estimation-method` option
-- Room links are now included in the `I` message links list
-
-### Changed
-
-- Updated documentation for `time_zone` config option
-- When connecting to a room using `n` in the room list, the cursor now moves to that room
-- Updated list of emoji names
-
-### Removed
-
-- Special handling of &rl2dev
-
-### Fixed
-
-- Nick color in rare edge cases
-- Message link list rendering bug
-
-## v0.8.3 - 2024-05-20
-
-### Changed
-
-- Updated list of emoji names
-
-## v0.8.2 - 2024-04-25
-
-### Changed
-
-- Renamed `json-stream` export format to `json-lines` (see )
-- Changed `json-lines` file extension from `.json` to `.jsonl`
-
-### Fixed
-
-- Crash when window is too small while empty message editor is visible
-- Mistakes in output and docs
-- Cove not cleaning up terminal state properly
-
-## v0.8.1 - 2024-01-11
-
-### Added
-
-- Support for setting window title
-- More information to room list heading
-- Key bindings for live caesar cipher de- and encoding
-
-### Removed
-
-- Key binding to open present page
-
-## v0.8.0 - 2024-01-04
-
-### Added
-
-- Support for multiple euph server domains
-- Support for `TZ` environment variable
-- `time_zone` config option
-- `--domain` option to `cove export` command
-- `--domain` option to `cove clear-cookies` command
-- Domain field to "connect to new room" popup
-- Welcome info box next to room list
-
-### Changed
-
-- The default euph domain is now https://euphoria.leet.nu/ everywhere
-- The config file format was changed to support multiple euph servers with different domains.
- Options previously located at `euph.rooms.*` should be reviewed and moved to `euph.servers."euphoria.leet.nu".rooms.*`.
-- Tweaked F1 popup
-- Tweaked chat message editor when nick list is foused
-- Reduced connection timeout from 30 seconds to 10 seconds
-
-### Fixed
-
-- Room deletion popup accepting any room name
-- Duplicated key presses on Windows
-
-## v0.7.1 - 2023-08-31
-
-### Changed
-
-- Updated dependencies
-
-## v0.7.0 - 2023-05-14
-
-### Added
-
-- Auto-generated config documentation
- - in [CONFIG.md](CONFIG.md)
- - via `help-config` CLI command
-- `keys.*` config options
-- `measure_widths` config option
-
-### Changed
-
-- Overhauled widget system and extracted generic widgets to [toss](https://github.com/Garmelon/toss)
-- Overhauled config system to support auto-generating documentation
-- Overhauled key binding system to make key bindings configurable
-- Redesigned F1 popup. It can now be toggled with F1 like the F12 log
-- The F12 log can now be closed with escape
-- Some more small UI fixes and adjustments to the new key binding system
-- Reduced tearing when redrawing screen
-- Split up project into sub-crates
-- Simplified flake dependencies
-
-## v0.6.1 - 2023-04-10
-
-### Changed
-
-- Improved JSON export performance
-- Always show rooms from config file in room list
-
-### Fixed
-
-- Rooms reconnecting instead of showing error popups
-
-## v0.6.0 - 2023-04-04
-
-### Added
-
-- Emoji support
-- `flake.nix`, making cove available as a nix flake
-- `json-stream` room export format
-- Option to export to stdout via `--out -`
-- `--verbose` flag
-
-### Changed
-
-- Non-export info is now printed to stderr instead of stdout
-- Recognizes links without scheme (e.g. `euphoria.io` instead of `https://euphoria.io`)
-- Rooms waiting for reconnect are no longer sorted to bottom in default sort order
-
-### Fixed
-
-- Mentions not being stopped by `>`
-
-## v0.5.2 - 2023-01-14
-
-### Added
-
-- Key binding to open present page
-
-### Changed
-
-- Always connect to &rl2dev in ephemeral mode
-- Reduce amount of messages per &rl2dev log request
-
-## v0.5.1 - 2022-11-27
-
-### Changed
-
-- Increase reconnect delay to one minute
-- Print errors that occurred while cove was running more compactly
-
-## v0.5.0 - 2022-09-26
-
-### Added
-
-- Key bindings to navigate nick list
-- Room deletion confirmation popup
-- Message inspection popup
-- Session inspection popup
-- Error popup when external editor fails
-- `rooms_sort_order` config option
-
-### Changed
-
-- Use nick changes to detect sessions for nick list
-- Support Unicode 15
-
-### Fixed
-
-- Cursor being visible through popups
-- Cursor in lists when highlighted item moves off-screen
-- User disappearing from nick list when only one of their sessions disconnects
-
-## v0.4.0 - 2022-09-01
-
-### Added
-
-- Config file and `--config` cli option
-- `data_dir` config option
-- `ephemeral` config option
-- `offline` config option and `--offline` cli flag
-- `euph.rooms..autojoin` config option
-- `euph.rooms..username` config option
-- `euph.rooms..force_username` config option
-- `euph.rooms..password` config option
-- Key binding to change rooms sort order
-- Key bindings to connect to/disconnect from all rooms
-- Key bindings to connect to autojoin rooms/disconnect from non-autojoin rooms
-- Key bindings to move to parent/root message
-- Key bindings to view and open links in a message
-
-### Changed
-
-- Some key bindings in the rooms list
-
-### Fixed
-
-- Rooms being stuck in "Connecting" state
-
-## v0.3.0 - 2022-08-22
-
-### Added
-
-- Account login and logout
-- Authentication dialog for password-protected rooms
-- Error popups in rooms when something goes wrong
-- `--ephemeral` flag that prevents cove from storing data permanently
-- Key binding to download more logs
-
-### Changed
-
-- Reduced amount of unnecessary redraws
-- Description of `export` CLI command
-
-### Fixed
-
-- Crash when connecting to nonexistent rooms
-- Crash when connecting to rooms that require authentication
-- Pasting multi-line strings into the editor
-
## v0.2.1 - 2022-08-11
### Added
-
- Support for modifiers on special keys via the [kitty keyboard protocol](https://sw.kovidgoyal.net/kitty/keyboard-protocol/)
### Fixed
-
- Joining new rooms no longer crashes cove
- Scrolling when exiting message editor
## v0.2.0 - 2022-08-10
### Added
-
- New messages are now marked as unseen
- Sub-trees can now be folded
- Support for pasting text into editors
@@ -296,12 +38,10 @@ Procedure when bumping the version number:
- Support for exporting multiple/all rooms at once
### Changed
-
- Reorganized export command
- Slowed down room history download speed
### Fixed
-
- Chat rendering when deleting and re-joining a room
- Spacing in some popups
diff --git a/CONFIG.md b/CONFIG.md
deleted file mode 100644
index 82a7242..0000000
--- a/CONFIG.md
+++ /dev/null
@@ -1,711 +0,0 @@
-# Config file format
-
-Cove's config file uses the [TOML](https://toml.io/) format.
-
-Here is an example config that changes a few different options:
-
-```toml
-measure_widths = true
-rooms_sort_order = "importance"
-
-[euph.servers."euphoria.leet.nu".rooms]
-welcome.autojoin = true
-test.username = "badingle"
-test.force_username = true
-private.password = "foobar"
-
-[keys]
-general.abort = ["esc", "ctrl+c"]
-general.exit = "ctrl+q"
-tree.action.fold_tree = "f"
-```
-
-## Key bindings
-
-Key bindings are specified as strings or lists of strings. Each string specifies
-a main key and zero or more modifier keys. The modifier keys (if any) are listed
-first, followed by the main key. They are separated by the `+` character and
-**no** whitespace.
-
-Examples of key bindings:
-- `"ctrl+c"`
-- `"X"` (not `"shift+x"`)
-- `"space"` or `" "` (both space bar)
-- `["g", "home"]`
-- `["K", "ctrl+up"]`
-- `["f1", "?"]`
-- `"ctrl+alt+f3"`
-- `["enter", "any+enter"]` (matches `enter` regardless of modifiers)
-
-Available main keys:
-- Any single character that can be typed
-- `esc`, `enter`, `space`, `tab`, `backtab`
-- `backspace`, `delete`, `insert`
-- `left`, `right`, `up`, `down`
-- `home`, `end`, `pageup`, `pagedown`
-- `f1`, `f2`, ...
-
-Available modifiers:
-- `shift` (must not be used with single characters)
-- `ctrl`
-- `alt`
-- `any` (matches as long as at least one modifier is pressed)
-
-## Available options
-
-### `bell_on_mention`
-
-**Required:** yes
-**Type:** boolean
-**Default:** `false`
-
-Ring the bell (character 0x07) when you are mentioned in a room.
-
-### `data_dir`
-
-**Required:** no
-**Type:** path
-**Default:** platform-dependent
-
-The directory that cove stores its data in when not running in ephemeral
-mode.
-
-Relative paths are interpreted relative to the user's home directory.
-
-See also the `--data-dir` command line option.
-
-### `ephemeral`
-
-**Required:** yes
-**Type:** boolean
-**Default:** `false`
-
-Whether to start in ephemeral mode.
-
-In ephemeral mode, cove doesn't store any data. It completely ignores
-any options related to the data dir.
-
-See also the `--ephemeral` command line option.
-
-### `euph.servers..rooms..autojoin`
-
-**Required:** yes
-**Type:** boolean
-**Default:** `false`
-
-Whether to automatically join this room on startup.
-
-### `euph.servers..rooms..force_username`
-
-**Required:** yes
-**Type:** boolean
-**Default:** `false`
-
-If `euph.servers..rooms..username` is set, this will force
-cove to set the username even if there is already a different username
-associated with the current session.
-
-### `euph.servers..rooms..password`
-
-**Required:** no
-**Type:** string
-
-If set, cove will try once to use this password to authenticate, should
-the room be password-protected.
-
-### `euph.servers..rooms..username`
-
-**Required:** no
-**Type:** string
-
-If set, cove will set this username upon joining if there is no username
-associated with the current session.
-
-### `keys.cursor.down`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["j", "down"]`
-
-Move down.
-
-### `keys.cursor.to_bottom`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["G", "end"]`
-
-Move to bottom.
-
-### `keys.cursor.to_top`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["g", "home"]`
-
-Move to top.
-
-### `keys.cursor.up`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["k", "up"]`
-
-Move up.
-
-### `keys.editor.action.backspace`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["ctrl+h", "backspace"]`
-
-Delete before cursor.
-
-### `keys.editor.action.clear`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"ctrl+l"`
-
-Clear editor contents.
-
-### `keys.editor.action.delete`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["ctrl+d", "delete"]`
-
-Delete after cursor.
-
-### `keys.editor.action.external`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["ctrl+x", "alt+e"]`
-
-Edit in external editor.
-
-### `keys.editor.cursor.down`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"down"`
-
-Move down.
-
-### `keys.editor.cursor.end`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["ctrl+e", "end"]`
-
-Move to end of line.
-
-### `keys.editor.cursor.left`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["ctrl+b", "left"]`
-
-Move left.
-
-### `keys.editor.cursor.left_word`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["alt+b", "ctrl+left"]`
-
-Move left a word.
-
-### `keys.editor.cursor.right`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["ctrl+f", "right"]`
-
-Move right.
-
-### `keys.editor.cursor.right_word`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["alt+f", "ctrl+right"]`
-
-Move right a word.
-
-### `keys.editor.cursor.start`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["ctrl+a", "home"]`
-
-Move to start of line.
-
-### `keys.editor.cursor.up`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"up"`
-
-Move up.
-
-### `keys.general.abort`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"esc"`
-
-Abort/close.
-
-### `keys.general.confirm`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"enter"`
-
-Confirm.
-
-### `keys.general.exit`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"ctrl+c"`
-
-Quit cove.
-
-### `keys.general.focus`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"tab"`
-
-Advance focus.
-
-### `keys.general.help`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"f1"`
-
-Show this help.
-
-### `keys.general.log`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"f12"`
-
-Show log.
-
-### `keys.room.action.account`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"A"`
-
-Manage account.
-
-### `keys.room.action.authenticate`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"a"`
-
-Authenticate.
-
-### `keys.room.action.more_messages`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"m"`
-
-Download more messages.
-
-### `keys.room.action.nick`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"n"`
-
-Change nick.
-
-### `keys.rooms.action.change_sort_order`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"s"`
-
-Change sort order.
-
-### `keys.rooms.action.connect`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"c"`
-
-Connect to selected room.
-
-### `keys.rooms.action.connect_all`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"C"`
-
-Connect to all rooms.
-
-### `keys.rooms.action.connect_autojoin`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"a"`
-
-Connect to all autojoin rooms.
-
-### `keys.rooms.action.delete`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"X"`
-
-Delete room.
-
-### `keys.rooms.action.disconnect`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"d"`
-
-Disconnect from selected room.
-
-### `keys.rooms.action.disconnect_all`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"D"`
-
-Disconnect from all rooms.
-
-### `keys.rooms.action.disconnect_non_autojoin`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"A"`
-
-Disconnect from all non-autojoin rooms.
-
-### `keys.rooms.action.new`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"n"`
-
-Connect to new room.
-
-### `keys.scroll.center_cursor`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"z"`
-
-Center cursor.
-
-### `keys.scroll.down_full`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["ctrl+f", "pagedown"]`
-
-Scroll down a full screen.
-
-### `keys.scroll.down_half`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"ctrl+d"`
-
-Scroll down half a screen.
-
-### `keys.scroll.down_line`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"ctrl+e"`
-
-Scroll down one line.
-
-### `keys.scroll.up_full`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["ctrl+b", "pageup"]`
-
-Scroll up a full screen.
-
-### `keys.scroll.up_half`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"ctrl+u"`
-
-Scroll up half a screen.
-
-### `keys.scroll.up_line`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"ctrl+y"`
-
-Scroll up one line.
-
-### `keys.tree.action.decrease_caesar`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"C"`
-
-Decrease caesar cipher rotation.
-
-### `keys.tree.action.fold_tree`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"space"`
-
-Fold current message's subtree.
-
-### `keys.tree.action.increase_caesar`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"c"`
-
-Increase caesar cipher rotation.
-
-### `keys.tree.action.inspect`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"i"`
-
-Inspect selected element.
-
-### `keys.tree.action.links`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"I"`
-
-List links found in message.
-
-### `keys.tree.action.mark_older_seen`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"ctrl+s"`
-
-Mark all older messages as seen.
-
-### `keys.tree.action.mark_visible_seen`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"S"`
-
-Mark all visible messages as seen.
-
-### `keys.tree.action.new_thread`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"t"`
-
-Start a new thread.
-
-### `keys.tree.action.reply`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"r"`
-
-Reply to message, inline if possible.
-
-### `keys.tree.action.reply_alternate`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"R"`
-
-Reply opposite to normal reply.
-
-### `keys.tree.action.toggle_nick_emoji`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"e"`
-
-Toggle agent id based nick emoji.
-
-### `keys.tree.action.toggle_seen`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"s"`
-
-Toggle current message's seen status.
-
-### `keys.tree.cursor.to_above_sibling`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["K", "ctrl+up"]`
-
-Move to above sibling.
-
-### `keys.tree.cursor.to_below_sibling`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["J", "ctrl+down"]`
-
-Move to below sibling.
-
-### `keys.tree.cursor.to_newer_message`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["l", "right"]`
-
-Move to newer message.
-
-### `keys.tree.cursor.to_newer_unseen_message`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["L", "ctrl+right"]`
-
-Move to newer unseen message.
-
-### `keys.tree.cursor.to_older_message`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["h", "left"]`
-
-Move to older message.
-
-### `keys.tree.cursor.to_older_unseen_message`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `["H", "ctrl+left"]`
-
-Move to older unseen message.
-
-### `keys.tree.cursor.to_parent`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"p"`
-
-Move to parent.
-
-### `keys.tree.cursor.to_root`
-
-**Required:** yes
-**Type:** key binding
-**Default:** `"P"`
-
-Move to root.
-
-### `measure_widths`
-
-**Required:** yes
-**Type:** boolean
-**Default:** `false`
-
-Whether to measure the width of graphemes (i.e. characters) as displayed
-by the terminal emulator instead of estimating the width.
-
-Enabling this makes rendering a bit slower but more accurate. The screen
-might also flash when encountering new graphemes.
-
-See also the `--measure-widths` command line option.
-
-### `offline`
-
-**Required:** yes
-**Type:** boolean
-**Default:** `false`
-
-Whether to start in offline mode.
-
-In offline mode, cove won't automatically join rooms marked via the
-`autojoin` option on startup. You can still join those rooms manually by
-pressing `a` in the rooms list.
-
-See also the `--offline` command line option.
-
-### `rooms_sort_order`
-
-**Required:** yes
-**Type:** string
-**Values:** `"alphabet"`, `"importance"`
-**Default:** `"alphabet"`
-
-Initial sort order of rooms list.
-
-`"alphabet"` sorts rooms in alphabetic order.
-
-`"importance"` sorts rooms by the following criteria (in descending
-order of priority):
-
-1. connected rooms before unconnected rooms
-2. rooms with unread messages before rooms without
-3. alphabetic order
-
-### `time_zone`
-
-**Required:** no
-**Type:** string
-**Default:** `$TZ` or local system time zone
-
-Time zone that chat timestamps should be displayed in.
-
-This option can either be the string `"localtime"`, a [POSIX TZ string],
-or a [tz identifier] from the [tz database].
-
-When not set or when set to `"localtime"`, cove attempts to use your
-system's configured time zone, falling back to UTC.
-
-When the string begins with a colon or doesn't match the a POSIX TZ
-string format, it is interpreted as a tz identifier and looked up in
-your system's tz database (or a bundled tz database on Windows).
-
-If the `TZ` environment variable exists, it overrides this option.
-
-[POSIX TZ string]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
-[tz identifier]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
-[tz database]: https://en.wikipedia.org/wiki/Tz_database
-
-### `width_estimation_method`
-
-**Required:** yes
-**Type:** string
-**Values:** `"legacy"`, `"unicode"`
-**Default:** `"legacy"`
-
-How to estimate the width of graphemes (i.e. characters) as displayed by
-the terminal emulator.
-
-`"legacy"`: Use a legacy method that should mostly work on most terminal
-emulators. This method will never be correct in all cases since every
-terminal emulator handles grapheme widths slightly differently. However,
-those cases are usually rare (unless you view a lot of emoji).
-
-`"unicode"`: Use the unicode standard in a best-effort manner to
-determine grapheme widths. Some terminals (e.g. ghostty) can make use of
-this.
-
-This method is used when `measure_widths` is set to `false`.
-
-See also the `--width-estimation-method` command line option.
diff --git a/Cargo.lock b/Cargo.lock
index 2f45a5a..65c261d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,226 +1,114 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
-version = 4
-
-[[package]]
-name = "addr2line"
-version = "0.24.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
-dependencies = [
- "gimli",
-]
-
-[[package]]
-name = "adler2"
-version = "2.0.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627"
+version = 3
[[package]]
name = "ahash"
-version = "0.8.11"
+version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011"
+checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47"
dependencies = [
- "cfg-if",
+ "getrandom",
"once_cell",
"version_check",
- "zerocopy 0.7.35",
]
[[package]]
name = "aho-corasick"
-version = "1.1.3"
+version = "0.7.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
+checksum = "1e37cfd5e7657ada45f742d6e99ca5788580b5c529dc78faf11ece6dc702656f"
dependencies = [
"memchr",
]
-[[package]]
-name = "anstream"
-version = "0.6.18"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b"
-dependencies = [
- "anstyle",
- "anstyle-parse",
- "anstyle-query",
- "anstyle-wincon",
- "colorchoice",
- "is_terminal_polyfill",
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle"
-version = "1.0.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9"
-
-[[package]]
-name = "anstyle-parse"
-version = "0.2.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9"
-dependencies = [
- "utf8parse",
-]
-
-[[package]]
-name = "anstyle-query"
-version = "1.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c"
-dependencies = [
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "anstyle-wincon"
-version = "3.0.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ca3534e77181a9cc07539ad51f2141fe32f6c3ffd4df76db8ad92346b003ae4e"
-dependencies = [
- "anstyle",
- "once_cell",
- "windows-sys 0.59.0",
-]
-
[[package]]
name = "anyhow"
-version = "1.0.97"
+version = "1.0.61"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f"
+checksum = "508b352bb5c066aac251f6daf6b36eccd03e8a88e8081cd44959ea277a3af9a8"
+
+[[package]]
+name = "approx"
+version = "0.5.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6"
+dependencies = [
+ "num-traits",
+]
[[package]]
name = "async-trait"
-version = "0.1.87"
+version = "0.1.57"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d556ec1359574147ec0c4fc5eb525f3f23263a592b1a9c07e0a75b427de55c97"
+checksum = "76464446b8bc32758d7e88ee1a804d9914cd9b1cb264c029899680b0be29826f"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
+[[package]]
+name = "atty"
+version = "0.2.14"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8"
+dependencies = [
+ "hermit-abi",
+ "libc",
+ "winapi",
+]
+
[[package]]
name = "autocfg"
-version = "1.4.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26"
+checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
-name = "aws-lc-rs"
-version = "1.12.6"
+name = "base64"
+version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dabb68eb3a7aa08b46fddfd59a3d55c978243557a90ab804769f7e20e67d2b01"
-dependencies = [
- "aws-lc-sys",
- "zeroize",
-]
-
-[[package]]
-name = "aws-lc-sys"
-version = "0.27.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6bbe221bbf523b625a4dd8585c7f38166e31167ec2ca98051dbcb4c3b6e825d2"
-dependencies = [
- "bindgen",
- "cc",
- "cmake",
- "dunce",
- "fs_extra",
-]
-
-[[package]]
-name = "backtrace"
-version = "0.3.74"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a"
-dependencies = [
- "addr2line",
- "cfg-if",
- "libc",
- "miniz_oxide",
- "object",
- "rustc-demangle",
- "windows-targets",
-]
-
-[[package]]
-name = "bindgen"
-version = "0.69.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271383c67ccabffb7381723dea0672a673f292304fcb45c01cc648c7a8d58088"
-dependencies = [
- "bitflags",
- "cexpr",
- "clang-sys",
- "itertools",
- "lazy_static",
- "lazycell",
- "log",
- "prettyplease",
- "proc-macro2",
- "quote",
- "regex",
- "rustc-hash",
- "shlex",
- "syn",
- "which",
-]
+checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd"
[[package]]
name = "bitflags"
-version = "2.9.0"
+version = "1.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "block-buffer"
-version = "0.10.4"
+version = "0.10.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
+checksum = "0bf7fe51849ea569fd452f37822f606a5cabb684dc918707a0193fd4664ff324"
dependencies = [
"generic-array",
]
[[package]]
-name = "bytes"
-version = "1.10.1"
+name = "bumpalo"
+version = "3.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
+checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3"
[[package]]
-name = "caseless"
-version = "0.2.2"
+name = "byteorder"
+version = "1.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8b6fd507454086c8edfd769ca6ada439193cdb209c7681712ef6275cccbfe5d8"
-dependencies = [
- "unicode-normalization",
-]
+checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610"
+
+[[package]]
+name = "bytes"
+version = "1.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ec8a7b6a70fde80372154c65702f00a0f56f3e1c36abbc6c440484be248856db"
[[package]]
name = "cc"
-version = "1.2.16"
+version = "1.0.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c"
-dependencies = [
- "jobserver",
- "libc",
- "shlex",
-]
-
-[[package]]
-name = "cexpr"
-version = "0.6.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
-dependencies = [
- "nom",
-]
+checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
[[package]]
name = "cfg-if"
@@ -228,46 +116,31 @@ version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
-[[package]]
-name = "clang-sys"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4"
-dependencies = [
- "glob",
- "libc",
- "libloading",
-]
-
[[package]]
name = "clap"
-version = "4.5.32"
+version = "3.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83"
+checksum = "a3dbbb6653e7c55cc8595ad3e1f7be8f32aba4eb7ff7f0fd1163d4f3d137c0a9"
dependencies = [
- "clap_builder",
+ "atty",
+ "bitflags",
"clap_derive",
-]
-
-[[package]]
-name = "clap_builder"
-version = "4.5.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8"
-dependencies = [
- "anstream",
- "anstyle",
"clap_lex",
+ "indexmap",
+ "once_cell",
"strsim",
+ "termcolor",
+ "textwrap",
]
[[package]]
name = "clap_derive"
-version = "4.5.32"
+version = "3.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09176aae279615badda0765c0c0b3f6ed53f4709118af73cf4655d85d1530cd7"
+checksum = "9ba52acd3b0a5c33aeada5cdaa3267cdc7c594a98731d4268cdc1532f4264cb4"
dependencies = [
"heck",
+ "proc-macro-error",
"proc-macro2",
"quote",
"syn",
@@ -275,30 +148,18 @@ dependencies = [
[[package]]
name = "clap_lex"
-version = "0.7.4"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
-
-[[package]]
-name = "cmake"
-version = "0.1.54"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e7caa3f9de89ddbe2c607f4101924c5abec803763ae9534e4f4d7d8f84aa81f0"
+checksum = "2850f2f5a82cbf437dd5af4d49848fbdfc27c157c3d010345776f952765261c5"
dependencies = [
- "cc",
+ "os_str_bytes",
]
-[[package]]
-name = "colorchoice"
-version = "1.0.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
-
[[package]]
name = "cookie"
-version = "0.18.1"
+version = "0.16.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
+checksum = "94d4706de1b0fa5b132270cddffa8585166037822e260a944fe161acd137ca05"
dependencies = [
"time",
"version_check",
@@ -306,9 +167,9 @@ dependencies = [
[[package]]
name = "core-foundation"
-version = "0.10.0"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63"
+checksum = "194a7a9e6de53fa55116934067c844d9d749312f75c6f6d0980e8c252f8c2146"
dependencies = [
"core-foundation-sys",
"libc",
@@ -316,92 +177,58 @@ dependencies = [
[[package]]
name = "core-foundation-sys"
-version = "0.8.7"
+version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
+checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "cove"
-version = "0.9.3"
+version = "0.2.1"
dependencies = [
"anyhow",
"async-trait",
"clap",
"cookie",
- "cove-config",
- "cove-input",
"crossterm",
"directories",
- "euphoxide",
- "jiff",
- "linkify",
+ "edit",
+ "futures",
"log",
- "open",
+ "palette",
"parking_lot",
+ "rand",
"rusqlite",
- "rustls",
+ "serde",
"serde_json",
"thiserror",
+ "time",
"tokio",
+ "tokio-tungstenite",
"toss",
+ "unicode-segmentation",
"unicode-width",
- "vault",
-]
-
-[[package]]
-name = "cove-config"
-version = "0.9.3"
-dependencies = [
- "cove-input",
- "cove-macro",
- "serde",
- "thiserror",
- "toml",
-]
-
-[[package]]
-name = "cove-input"
-version = "0.9.3"
-dependencies = [
- "cove-macro",
- "crossterm",
- "edit",
- "parking_lot",
- "serde",
- "serde_either",
- "thiserror",
- "toss",
-]
-
-[[package]]
-name = "cove-macro"
-version = "0.9.3"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
]
[[package]]
name = "cpufeatures"
-version = "0.2.17"
+version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
+checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b"
dependencies = [
"libc",
]
[[package]]
name = "crossterm"
-version = "0.28.1"
+version = "0.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
+checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67"
dependencies = [
"bitflags",
"crossterm_winapi",
+ "libc",
"mio",
"parking_lot",
- "rustix 0.38.44",
"signal-hook",
"signal-hook-mio",
"winapi",
@@ -409,9 +236,9 @@ dependencies = [
[[package]]
name = "crossterm_winapi"
-version = "0.9.1"
+version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b"
+checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c"
dependencies = [
"winapi",
]
@@ -426,26 +253,11 @@ dependencies = [
"typenum",
]
-[[package]]
-name = "data-encoding"
-version = "2.8.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "575f75dfd25738df5b91b8e43e14d44bda14637a58fae779fd2b064f8bf3e010"
-
-[[package]]
-name = "deranged"
-version = "0.3.11"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4"
-dependencies = [
- "powerfmt",
-]
-
[[package]]
name = "digest"
-version = "0.10.7"
+version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
+checksum = "f2fb860ca6fafa5552fb6d0e816a69c8e49f0908bf524e30a90d97c85892d506"
dependencies = [
"block-buffer",
"crypto-common",
@@ -453,36 +265,29 @@ dependencies = [
[[package]]
name = "directories"
-version = "6.0.0"
+version = "4.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "16f5094c54661b38d03bd7e50df373292118db60b585c08a411c6d840017fe7d"
+checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
dependencies = [
"dirs-sys",
]
[[package]]
name = "dirs-sys"
-version = "0.5.0"
+version = "0.3.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
dependencies = [
"libc",
- "option-ext",
"redox_users",
- "windows-sys 0.59.0",
+ "winapi",
]
-[[package]]
-name = "dunce"
-version = "1.0.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
-
[[package]]
name = "edit"
-version = "0.1.5"
+version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f364860e764787163c8c8f58231003839be31276e821e2ad2092ddf496b1aa09"
+checksum = "c562aa71f7bc691fde4c6bf5f93ae5a5298b617c2eb44c76c87832299a17fbb4"
dependencies = [
"tempfile",
"which",
@@ -490,51 +295,15 @@ dependencies = [
[[package]]
name = "either"
-version = "1.15.0"
+version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
-
-[[package]]
-name = "equivalent"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
-
-[[package]]
-name = "errno"
-version = "0.3.10"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d"
-dependencies = [
- "libc",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "euphoxide"
-version = "0.6.1"
-source = "git+https://github.com/Garmelon/euphoxide.git?tag=v0.6.1#7a292c429ad44aa6aa52fc381e3168841d6303b0"
-dependencies = [
- "async-trait",
- "caseless",
- "clap",
- "cookie",
- "futures-util",
- "jiff",
- "log",
- "serde",
- "serde_json",
- "tokio",
- "tokio-stream",
- "tokio-tungstenite",
- "unicode-normalization",
-]
+checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be"
[[package]]
name = "fallible-iterator"
-version = "0.3.0"
+version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649"
+checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7"
[[package]]
name = "fallible-streaming-iterator"
@@ -544,9 +313,21 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fastrand"
-version = "2.3.0"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be"
+checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
+dependencies = [
+ "instant",
+]
+
+[[package]]
+name = "find-crate"
+version = "0.6.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2"
+dependencies = [
+ "toml",
+]
[[package]]
name = "fnv"
@@ -555,38 +336,99 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]]
-name = "fs_extra"
-version = "1.3.0"
+name = "form_urlencoded"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c"
+checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191"
+dependencies = [
+ "matches",
+ "percent-encoding",
+]
[[package]]
-name = "futures-core"
-version = "0.3.31"
+name = "futures"
+version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
+checksum = "f73fe65f54d1e12b726f517d3e2135ca3125a437b6d998caf1962961f7172d9e"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-executor",
+ "futures-io",
+ "futures-sink",
+ "futures-task",
+ "futures-util",
+]
[[package]]
-name = "futures-sink"
-version = "0.3.31"
+name = "futures-channel"
+version = "0.3.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
-
-[[package]]
-name = "futures-task"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
-
-[[package]]
-name = "futures-util"
-version = "0.3.31"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
+checksum = "c3083ce4b914124575708913bca19bfe887522d6e2e6d0952943f5eac4a74010"
dependencies = [
"futures-core",
"futures-sink",
+]
+
+[[package]]
+name = "futures-core"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0c09fd04b7e4073ac7156a9539b57a484a8ea920f79c7c675d05d289ab6110d3"
+
+[[package]]
+name = "futures-executor"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9420b90cfa29e327d0429f19be13e7ddb68fa1cccb09d65e5706b8c7a749b8a6"
+dependencies = [
+ "futures-core",
"futures-task",
+ "futures-util",
+]
+
+[[package]]
+name = "futures-io"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fc4045962a5a5e935ee2fdedaa4e08284547402885ab326734432bed5d12966b"
+
+[[package]]
+name = "futures-macro"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "33c1e13800337f4d4d7a316bf45a567dbcb6ffe087f16424852d97e97a91f512"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "futures-sink"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "21163e139fa306126e6eedaf49ecdb4588f939600f0b1e770f4205ee4b7fa868"
+
+[[package]]
+name = "futures-task"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "57c66a976bf5909d801bbef33416c41372779507e7a6b3a5e25e4749c58f776a"
+
+[[package]]
+name = "futures-util"
+version = "0.3.21"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d8b7abd5d659d9b90c8cba917f6ec750a74e2dc23902ef9cd4cc8c8b22e6036a"
+dependencies = [
+ "futures-channel",
+ "futures-core",
+ "futures-io",
+ "futures-macro",
+ "futures-sink",
+ "futures-task",
+ "memchr",
"pin-project-lite",
"pin-utils",
"slab",
@@ -594,9 +436,9 @@ dependencies = [
[[package]]
name = "generic-array"
-version = "0.14.7"
+version = "0.14.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
+checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9"
dependencies = [
"typenum",
"version_check",
@@ -604,83 +446,53 @@ dependencies = [
[[package]]
name = "getrandom"
-version = "0.2.15"
+version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
+checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
- "wasi 0.11.0+wasi-snapshot-preview1",
+ "wasi",
]
-[[package]]
-name = "getrandom"
-version = "0.3.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8"
-dependencies = [
- "cfg-if",
- "libc",
- "wasi 0.13.3+wasi-0.2.2",
- "windows-targets",
-]
-
-[[package]]
-name = "gimli"
-version = "0.31.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
-
-[[package]]
-name = "glob"
-version = "0.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2"
-
[[package]]
name = "hashbrown"
-version = "0.14.5"
+version = "0.12.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
dependencies = [
"ahash",
]
-[[package]]
-name = "hashbrown"
-version = "0.15.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
-
[[package]]
name = "hashlink"
-version = "0.9.1"
+version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af"
+checksum = "d452c155cb93fecdfb02a73dd57b5d8e442c2063bd7aac72f1bc5e4263a43086"
dependencies = [
- "hashbrown 0.14.5",
+ "hashbrown",
]
[[package]]
name = "heck"
-version = "0.5.0"
+version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
-name = "home"
-version = "0.5.11"
+name = "hermit-abi"
+version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
+checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33"
dependencies = [
- "windows-sys 0.59.0",
+ "libc",
]
[[package]]
name = "http"
-version = "1.3.1"
+version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565"
+checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399"
dependencies = [
"bytes",
"fnv",
@@ -689,185 +501,83 @@ dependencies = [
[[package]]
name = "httparse"
-version = "1.10.1"
+version = "1.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
+checksum = "496ce29bb5a52785b44e0f7ca2847ae0bb839c9bd28f69acac9b99d461c0c04c"
+
+[[package]]
+name = "idna"
+version = "0.2.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8"
+dependencies = [
+ "matches",
+ "unicode-bidi",
+ "unicode-normalization",
+]
[[package]]
name = "indexmap"
-version = "2.8.0"
+version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058"
+checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e"
dependencies = [
- "equivalent",
- "hashbrown 0.15.2",
+ "autocfg",
+ "hashbrown",
]
[[package]]
-name = "is-docker"
-version = "0.2.0"
+name = "instant"
+version = "0.1.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "928bae27f42bc99b60d9ac7334e3a21d10ad8f1835a4e12ec3ec0464765ed1b3"
+checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c"
dependencies = [
- "once_cell",
-]
-
-[[package]]
-name = "is-wsl"
-version = "0.4.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "173609498df190136aa7dea1a91db051746d339e18476eed5ca40521f02d7aa5"
-dependencies = [
- "is-docker",
- "once_cell",
-]
-
-[[package]]
-name = "is_terminal_polyfill"
-version = "1.70.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
-
-[[package]]
-name = "itertools"
-version = "0.12.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569"
-dependencies = [
- "either",
+ "cfg-if",
]
[[package]]
name = "itoa"
-version = "1.0.15"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
+checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
[[package]]
-name = "jiff"
-version = "0.2.4"
+name = "js-sys"
+version = "0.3.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d699bc6dfc879fb1bf9bdff0d4c56f0884fc6f0d0eb0fba397a6d00cd9a6b85e"
+checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
dependencies = [
- "jiff-static",
- "jiff-tzdb-platform",
- "log",
- "portable-atomic",
- "portable-atomic-util",
- "serde",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "jiff-static"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8d16e75759ee0aa64c57a56acbf43916987b20c77373cb7e808979e02b93c9f9"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "jiff-tzdb"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "962e1dfe9b2d75a84536cf5bf5eaaa4319aa7906c7160134a22883ac316d5f31"
-
-[[package]]
-name = "jiff-tzdb-platform"
-version = "0.1.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a63c62e404e7b92979d2792352d885a7f8f83fd1d0d31eea582d77b2ceca697e"
-dependencies = [
- "jiff-tzdb",
-]
-
-[[package]]
-name = "jobserver"
-version = "0.1.32"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0"
-dependencies = [
- "libc",
+ "wasm-bindgen",
]
[[package]]
name = "lazy_static"
-version = "1.5.0"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
-
-[[package]]
-name = "lazycell"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
+checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
-version = "0.2.171"
+version = "0.2.129"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6"
-
-[[package]]
-name = "libloading"
-version = "0.8.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34"
-dependencies = [
- "cfg-if",
- "windows-targets",
-]
-
-[[package]]
-name = "libredox"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d"
-dependencies = [
- "bitflags",
- "libc",
-]
+checksum = "64de3cc433455c14174d42e554d4027ee631c4d046d43e3ecc6efc4636cdc7a7"
[[package]]
name = "libsqlite3-sys"
-version = "0.28.0"
+version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0c10584274047cb335c23d3e61bcef8e323adae7c5c8c760540f73610177fc3f"
+checksum = "9f0455f2c1bc9a7caa792907026e469c1d91761fb0ea37cbb16427c77280cf35"
dependencies = [
"cc",
"pkg-config",
"vcpkg",
]
-[[package]]
-name = "linkify"
-version = "0.10.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1dfa36d52c581e9ec783a7ce2a5e0143da6237be5811a0b3153fedfdbe9f780"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.4.15"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
-
-[[package]]
-name = "linux-raw-sys"
-version = "0.9.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413"
-
[[package]]
name = "lock_api"
-version = "0.4.12"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17"
+checksum = "327fa5b6a6940e4699ec49a9beae1ea4845c6bab9314e4f84ac68742139d8c53"
dependencies = [
"autocfg",
"scopeguard",
@@ -875,120 +585,111 @@ dependencies = [
[[package]]
name = "log"
-version = "0.4.26"
+version = "0.4.17"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e"
+checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "matches"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f"
[[package]]
name = "memchr"
-version = "2.7.4"
+version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
-
-[[package]]
-name = "minimal-lexical"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
-
-[[package]]
-name = "miniz_oxide"
-version = "0.8.5"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5"
-dependencies = [
- "adler2",
-]
+checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
[[package]]
name = "mio"
-version = "1.0.3"
+version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd"
+checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
dependencies = [
"libc",
"log",
- "wasi 0.11.0+wasi-snapshot-preview1",
- "windows-sys 0.52.0",
+ "wasi",
+ "windows-sys",
]
-[[package]]
-name = "nom"
-version = "7.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
-dependencies = [
- "memchr",
- "minimal-lexical",
-]
-
-[[package]]
-name = "num-conv"
-version = "0.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
-
[[package]]
name = "num-traits"
-version = "0.2.19"
+version = "0.2.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
+checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd"
dependencies = [
"autocfg",
]
[[package]]
-name = "object"
-version = "0.36.7"
+name = "num_cpus"
+version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
+checksum = "19e64526ebdee182341572e50e9ad03965aa510cd94427a4549448f285e957a1"
dependencies = [
- "memchr",
+ "hermit-abi",
+ "libc",
+]
+
+[[package]]
+name = "num_threads"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
+dependencies = [
+ "libc",
]
[[package]]
name = "once_cell"
-version = "1.21.1"
+version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
-
-[[package]]
-name = "open"
-version = "5.3.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e2483562e62ea94312f3576a7aca397306df7990b8d89033e18766744377ef95"
-dependencies = [
- "is-wsl",
- "libc",
- "pathdiff",
-]
+checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1"
[[package]]
name = "openssl-probe"
-version = "0.1.6"
+version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d05e27ee213611ffe7d6348b942e8f942b37114c00cc03cec254295a4a17852e"
+checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf"
[[package]]
-name = "option-ext"
-version = "0.2.0"
+name = "os_str_bytes"
+version = "6.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
+checksum = "648001efe5d5c0102d8cea768e348da85d90af8ba91f0bea908f157951493cd4"
[[package]]
-name = "ordered-float"
-version = "2.10.1"
+name = "palette"
+version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "68f19d67e5a2795c94e73e0bb1cc1a7edeb2e28efd39e2e1c9b7a40c1108b11c"
+checksum = "8f9cd68f7112581033f157e56c77ac4a5538ec5836a2e39284e65bd7d7275e49"
dependencies = [
+ "approx",
"num-traits",
+ "palette_derive",
+]
+
+[[package]]
+name = "palette_derive"
+version = "0.6.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "05eedf46a8e7c27f74af0c9cfcdb004ceca158cb1b918c6f68f8d7a549b3e427"
+dependencies = [
+ "find-crate",
+ "proc-macro2",
+ "quote",
+ "syn",
]
[[package]]
name = "parking_lot"
-version = "0.12.3"
+version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
+checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f"
dependencies = [
"lock_api",
"parking_lot_core",
@@ -996,28 +697,28 @@ dependencies = [
[[package]]
name = "parking_lot_core"
-version = "0.9.10"
+version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8"
+checksum = "09a279cbf25cb0757810394fbc1e359949b59e348145c643a939a525692e6929"
dependencies = [
"cfg-if",
"libc",
"redox_syscall",
"smallvec",
- "windows-targets",
+ "windows-sys",
]
[[package]]
-name = "pathdiff"
-version = "0.2.3"
+name = "percent-encoding"
+version = "2.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
+checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e"
[[package]]
name = "pin-project-lite"
-version = "0.2.16"
+version = "0.2.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
+checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116"
[[package]]
name = "pin-utils"
@@ -1027,84 +728,74 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
[[package]]
name = "pkg-config"
-version = "0.3.32"
+version = "0.3.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
-
-[[package]]
-name = "portable-atomic"
-version = "1.11.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "350e9b48cbc6b0e028b0473b114454c6316e57336ee184ceab6e53f72c178b3e"
-
-[[package]]
-name = "portable-atomic-util"
-version = "0.2.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d8a2f0d8d040d7848a709caf78912debcc3f33ee4b3cac47d73d1e1069e83507"
-dependencies = [
- "portable-atomic",
-]
-
-[[package]]
-name = "powerfmt"
-version = "0.2.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
+checksum = "1df8c4ec4b0627e53bdf214615ad287367e482558cf84b109250b37464dc03ae"
[[package]]
name = "ppv-lite86"
-version = "0.2.21"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
+checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
+
+[[package]]
+name = "proc-macro-error"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
- "zerocopy 0.8.23",
+ "proc-macro-error-attr",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "version_check",
]
[[package]]
-name = "prettyplease"
-version = "0.2.31"
+name = "proc-macro-error-attr"
+version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb"
+checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
- "syn",
+ "quote",
+ "version_check",
]
[[package]]
name = "proc-macro2"
-version = "1.0.94"
+version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84"
+checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
-version = "1.0.40"
+version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
+checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "rand"
-version = "0.9.0"
+version = "0.8.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94"
+checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
dependencies = [
+ "libc",
"rand_chacha",
"rand_core",
- "zerocopy 0.8.23",
]
[[package]]
name = "rand_chacha"
-version = "0.9.0"
+version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb"
+checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
dependencies = [
"ppv-lite86",
"rand_core",
@@ -1112,50 +803,38 @@ dependencies = [
[[package]]
name = "rand_core"
-version = "0.9.3"
+version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38"
+checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7"
dependencies = [
- "getrandom 0.3.1",
+ "getrandom",
]
[[package]]
name = "redox_syscall"
-version = "0.5.10"
+version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
-version = "0.5.0"
+version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
dependencies = [
- "getrandom 0.2.15",
- "libredox",
+ "getrandom",
+ "redox_syscall",
"thiserror",
]
[[package]]
name = "regex"
-version = "1.11.1"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191"
-dependencies = [
- "aho-corasick",
- "memchr",
- "regex-automata",
- "regex-syntax",
-]
-
-[[package]]
-name = "regex-automata"
-version = "0.4.9"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
+checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b"
dependencies = [
"aho-corasick",
"memchr",
@@ -1164,29 +843,39 @@ dependencies = [
[[package]]
name = "regex-syntax"
-version = "0.8.5"
+version = "0.6.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c"
+checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244"
+
+[[package]]
+name = "remove_dir_all"
+version = "0.5.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
+dependencies = [
+ "winapi",
+]
[[package]]
name = "ring"
-version = "0.17.14"
+version = "0.16.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7"
+checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc"
dependencies = [
"cc",
- "cfg-if",
- "getrandom 0.2.15",
"libc",
+ "once_cell",
+ "spin",
"untrusted",
- "windows-sys 0.52.0",
+ "web-sys",
+ "winapi",
]
[[package]]
name = "rusqlite"
-version = "0.31.0"
+version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b838eba278d213a8beaf485bd313fd580ca4505a00d5871caeb1457c55322cae"
+checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a"
dependencies = [
"bitflags",
"fallible-iterator",
@@ -1197,115 +886,76 @@ dependencies = [
"time",
]
-[[package]]
-name = "rustc-demangle"
-version = "0.1.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f"
-
-[[package]]
-name = "rustc-hash"
-version = "1.1.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
-
-[[package]]
-name = "rustix"
-version = "0.38.44"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
-dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys 0.4.15",
- "windows-sys 0.59.0",
-]
-
-[[package]]
-name = "rustix"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f7178faa4b75a30e269c71e61c353ce2748cf3d76f0c44c393f4e60abf49b825"
-dependencies = [
- "bitflags",
- "errno",
- "libc",
- "linux-raw-sys 0.9.3",
- "windows-sys 0.59.0",
-]
-
[[package]]
name = "rustls"
-version = "0.23.23"
+version = "0.20.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "47796c98c480fce5406ef69d1c76378375492c3b0a0de587be0c1d9feb12f395"
+checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033"
dependencies = [
- "aws-lc-rs",
"log",
- "once_cell",
- "rustls-pki-types",
- "rustls-webpki",
- "subtle",
- "zeroize",
+ "ring",
+ "sct",
+ "webpki",
]
[[package]]
name = "rustls-native-certs"
-version = "0.8.1"
+version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcff2dd52b58a8d98a70243663a0d234c4e2b79235637849d15913394a247d3"
+checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50"
dependencies = [
"openssl-probe",
- "rustls-pki-types",
+ "rustls-pemfile",
"schannel",
"security-framework",
]
[[package]]
-name = "rustls-pki-types"
-version = "1.11.0"
+name = "rustls-pemfile"
+version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
-
-[[package]]
-name = "rustls-webpki"
-version = "0.102.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9"
+checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55"
dependencies = [
- "aws-lc-rs",
- "ring",
- "rustls-pki-types",
- "untrusted",
+ "base64",
]
[[package]]
name = "ryu"
-version = "1.0.20"
+version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
+checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "schannel"
-version = "0.1.27"
+version = "0.1.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d"
+checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2"
dependencies = [
- "windows-sys 0.59.0",
+ "lazy_static",
+ "windows-sys",
]
[[package]]
name = "scopeguard"
-version = "1.2.0"
+version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
+checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
+
+[[package]]
+name = "sct"
+version = "0.7.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4"
+dependencies = [
+ "ring",
+ "untrusted",
+]
[[package]]
name = "security-framework"
-version = "3.2.0"
+version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "271720403f46ca04f7ba6f55d438f8bd878d6b8ca0a1046e8228c4145bcbb316"
+checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc"
dependencies = [
"bitflags",
"core-foundation",
@@ -1316,9 +966,9 @@ dependencies = [
[[package]]
name = "security-framework-sys"
-version = "2.14.0"
+version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "49db231d56a190491cb4aeda9527f1ad45345af50b0851622a7adb8c03b01c32"
+checksum = "0160a13a177a45bfb43ce71c01580998474f556ad854dcbca936dd2841a5c556"
dependencies = [
"core-foundation-sys",
"libc",
@@ -1326,87 +976,51 @@ dependencies = [
[[package]]
name = "serde"
-version = "1.0.219"
+version = "1.0.143"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
+checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553"
dependencies = [
"serde_derive",
]
-[[package]]
-name = "serde-value"
-version = "0.7.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f3a1a3341211875ef120e117ea7fd5228530ae7e7036a779fdc9117be6b3282c"
-dependencies = [
- "ordered-float",
- "serde",
-]
-
[[package]]
name = "serde_derive"
-version = "1.0.219"
+version = "1.0.143"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
+checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
-[[package]]
-name = "serde_either"
-version = "0.2.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "689643f4e7826ffcd227d2cc166bfdf5869750191ffe9fd593531e6ba351f2fb"
-dependencies = [
- "serde",
- "serde-value",
-]
-
[[package]]
name = "serde_json"
-version = "1.0.140"
+version = "1.0.83"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
+checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7"
dependencies = [
"itoa",
- "memchr",
"ryu",
"serde",
]
[[package]]
-name = "serde_spanned"
-version = "0.6.8"
+name = "sha-1"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "sha1"
-version = "0.10.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
+checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f"
dependencies = [
"cfg-if",
"cpufeatures",
"digest",
]
-[[package]]
-name = "shlex"
-version = "1.3.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
-
[[package]]
name = "signal-hook"
-version = "0.3.17"
+version = "0.3.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801"
+checksum = "a253b5e89e2698464fc26b545c9edceb338e18a89effeeecfea192c3025be29d"
dependencies = [
"libc",
"signal-hook-registry",
@@ -1414,9 +1028,9 @@ dependencies = [
[[package]]
name = "signal-hook-mio"
-version = "0.2.4"
+version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "34db1a06d485c9142248b7a054f034b349b212551f3dfd19c94d45a754a217cd"
+checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af"
dependencies = [
"libc",
"mio",
@@ -1425,55 +1039,55 @@ dependencies = [
[[package]]
name = "signal-hook-registry"
-version = "1.4.2"
+version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
+checksum = "e51e73328dc4ac0c7ccbda3a494dfa03df1de2f46018127f60c693f2648455b0"
dependencies = [
"libc",
]
[[package]]
name = "slab"
-version = "0.4.9"
+version = "0.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67"
+checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef"
dependencies = [
"autocfg",
]
[[package]]
name = "smallvec"
-version = "1.14.0"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd"
+checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
[[package]]
name = "socket2"
-version = "0.5.8"
+version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8"
+checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0"
dependencies = [
"libc",
- "windows-sys 0.52.0",
+ "winapi",
]
[[package]]
-name = "strsim"
-version = "0.11.1"
+name = "spin"
+version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
[[package]]
-name = "subtle"
-version = "2.6.1"
+name = "strsim"
+version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
+checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
-version = "2.0.100"
+version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0"
+checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
dependencies = [
"proc-macro2",
"quote",
@@ -1482,31 +1096,47 @@ dependencies = [
[[package]]
name = "tempfile"
-version = "3.19.0"
+version = "3.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "488960f40a3fd53d72c2a29a58722561dee8afdd175bd88e3db4677d7b2ba600"
+checksum = "5cdb1ef4eaeeaddc8fbd371e5017057064af0911902ef36b39801f67cc6d79e4"
dependencies = [
+ "cfg-if",
"fastrand",
- "getrandom 0.3.1",
- "once_cell",
- "rustix 1.0.2",
- "windows-sys 0.59.0",
+ "libc",
+ "redox_syscall",
+ "remove_dir_all",
+ "winapi",
]
[[package]]
-name = "thiserror"
-version = "2.0.12"
+name = "termcolor"
+version = "1.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
+checksum = "bab24d30b911b2376f3a13cc2cd443142f0c81dda04c118693e35b3835757755"
+dependencies = [
+ "winapi-util",
+]
+
+[[package]]
+name = "textwrap"
+version = "0.15.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b1141d4d61095b28419e22cb0bbf02755f5e54e0526f97f1e3d1d160e60885fb"
+
+[[package]]
+name = "thiserror"
+version = "1.0.32"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
-version = "2.0.12"
+version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
+checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21"
dependencies = [
"proc-macro2",
"quote",
@@ -1515,73 +1145,64 @@ dependencies = [
[[package]]
name = "time"
-version = "0.3.39"
+version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dad298b01a40a23aac4580b67e3dbedb7cc8402f3592d7f49469de2ea4aecdd8"
+checksum = "db76ff9fa4b1458b3c7f077f3ff9887394058460d21e634355b273aaf11eea45"
dependencies = [
- "deranged",
"itoa",
- "num-conv",
- "powerfmt",
+ "libc",
+ "num_threads",
"serde",
- "time-core",
"time-macros",
]
-[[package]]
-name = "time-core"
-version = "0.1.3"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "765c97a5b985b7c11d7bc27fa927dc4fe6af3a6dfb021d28deb60d3bf51e76ef"
-
[[package]]
name = "time-macros"
-version = "0.2.20"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "e8093bc3e81c3bc5f7879de09619d06c9a5a5e45ca44dfeeb7225bae38005c5c"
-dependencies = [
- "num-conv",
- "time-core",
-]
+checksum = "42657b1a6f4d817cda8e7a0ace261fe0cc946cf3a80314390b22cc61ae080792"
[[package]]
name = "tinyvec"
-version = "1.9.0"
+version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09b3661f17e86524eccd4371ab0429194e0d7c008abb45f7a7495b1719463c71"
+checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50"
dependencies = [
"tinyvec_macros",
]
[[package]]
name = "tinyvec_macros"
-version = "0.1.1"
+version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
+checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c"
[[package]]
name = "tokio"
-version = "1.44.1"
+version = "1.20.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f382da615b842244d4b8738c82ed1275e6c5dd90c459a30941cd07080b06c91a"
+checksum = "7a8325f63a7d4774dd041e363b2409ed1c5cbbd0f867795e661df066b2b0a581"
dependencies = [
- "backtrace",
+ "autocfg",
"bytes",
"libc",
+ "memchr",
"mio",
+ "num_cpus",
+ "once_cell",
"parking_lot",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
- "windows-sys 0.52.0",
+ "winapi",
]
[[package]]
name = "tokio-macros"
-version = "2.5.0"
+version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
+checksum = "9724f9a975fb987ef7a3cd9be0350edcbe130698af5b8f7a631e23d42d052484"
dependencies = [
"proc-macro2",
"quote",
@@ -1590,81 +1211,45 @@ dependencies = [
[[package]]
name = "tokio-rustls"
-version = "0.26.2"
+version = "0.23.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
+checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59"
dependencies = [
"rustls",
"tokio",
-]
-
-[[package]]
-name = "tokio-stream"
-version = "0.1.17"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
-dependencies = [
- "futures-core",
- "pin-project-lite",
- "tokio",
+ "webpki",
]
[[package]]
name = "tokio-tungstenite"
-version = "0.26.2"
+version = "0.17.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7a9daff607c6d2bf6c16fd681ccb7eecc83e4e2cdc1ca067ffaadfca5de7f084"
+checksum = "f714dd15bead90401d77e04243611caec13726c2408afd5b31901dfcdcb3b181"
dependencies = [
"futures-util",
"log",
"rustls",
"rustls-native-certs",
- "rustls-pki-types",
"tokio",
"tokio-rustls",
"tungstenite",
+ "webpki",
]
[[package]]
name = "toml"
-version = "0.8.20"
+version = "0.5.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cd87a5cdd6ffab733b2f74bc4fd7ee5fff6634124999ac278c35fc78c6120148"
+checksum = "8d82e1a7758622a465f8cee077614c73484dac5b836c02ff6a40d5d1010324d7"
dependencies = [
"serde",
- "serde_spanned",
- "toml_datetime",
- "toml_edit",
-]
-
-[[package]]
-name = "toml_datetime"
-version = "0.6.8"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41"
-dependencies = [
- "serde",
-]
-
-[[package]]
-name = "toml_edit"
-version = "0.22.24"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474"
-dependencies = [
- "indexmap",
- "serde",
- "serde_spanned",
- "toml_datetime",
- "winnow",
]
[[package]]
name = "toss"
-version = "0.3.4"
-source = "git+https://github.com/Garmelon/toss.git?tag=v0.3.4#57aa8c59308f6f0aa82bde415a42b56c3d6f7c4d"
+version = "0.1.0"
+source = "git+https://github.com/Garmelon/toss.git?rev=45ece466c235cce6e998bbd404f915cad3628c8c#45ece466c235cce6e998bbd404f915cad3628c8c"
dependencies = [
- "async-trait",
"crossterm",
"unicode-linebreak",
"unicode-segmentation",
@@ -1673,67 +1258,90 @@ dependencies = [
[[package]]
name = "tungstenite"
-version = "0.26.2"
+version = "0.17.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4793cb5e56680ecbb1d843515b23b6de9a75eb04b66643e256a396d43be33c13"
+checksum = "e27992fd6a8c29ee7eef28fc78349aa244134e10ad447ce3b9f0ac0ed0fa4ce0"
dependencies = [
+ "base64",
+ "byteorder",
"bytes",
- "data-encoding",
"http",
"httparse",
"log",
"rand",
"rustls",
- "rustls-pki-types",
- "sha1",
+ "sha-1",
"thiserror",
+ "url",
"utf-8",
+ "webpki",
]
[[package]]
name = "typenum"
-version = "1.18.0"
+version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
+checksum = "dcf81ac59edc17cc8697ff311e8f5ef2d99fcbd9817b34cec66f90b6c3dfd987"
+
+[[package]]
+name = "unicode-bidi"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992"
[[package]]
name = "unicode-ident"
-version = "1.0.18"
+version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
+checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
[[package]]
name = "unicode-linebreak"
-version = "0.1.5"
+version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
+checksum = "3a52dcaab0c48d931f7cc8ef826fa51690a08e1ea55117ef26f89864f532383f"
+dependencies = [
+ "regex",
+]
[[package]]
name = "unicode-normalization"
-version = "0.1.24"
+version = "0.1.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
+checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6"
dependencies = [
"tinyvec",
]
[[package]]
name = "unicode-segmentation"
-version = "1.12.0"
+version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
+checksum = "7e8820f5d777f6224dc4be3632222971ac30164d4a258d595640799554ebfd99"
[[package]]
name = "unicode-width"
-version = "0.2.0"
+version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd"
+checksum = "3ed742d4ea2bd1176e236172c8429aaf54486e7ac098db29ffe6529e0ce50973"
[[package]]
name = "untrusted"
-version = "0.9.0"
+version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
+checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
+
+[[package]]
+name = "url"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c"
+dependencies = [
+ "form_urlencoded",
+ "idna",
+ "matches",
+ "percent-encoding",
+]
[[package]]
name = "utf-8"
@@ -1741,21 +1349,6 @@ version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
-[[package]]
-name = "utf8parse"
-version = "0.2.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
-
-[[package]]
-name = "vault"
-version = "0.4.0"
-source = "git+https://github.com/Garmelon/vault.git?tag=v0.4.0#a53254d2e787d15fd2d00584fddf9b84e79572ee"
-dependencies = [
- "rusqlite",
- "tokio",
-]
-
[[package]]
name = "vcpkg"
version = "0.2.15"
@@ -1764,9 +1357,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
[[package]]
name = "version_check"
-version = "0.9.5"
+version = "0.9.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
+checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
[[package]]
name = "wasi"
@@ -1775,24 +1368,88 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
-name = "wasi"
-version = "0.13.3+wasi-0.2.2"
+name = "wasm-bindgen"
+version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2"
+checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
dependencies = [
- "wit-bindgen-rt",
+ "cfg-if",
+ "wasm-bindgen-macro",
+]
+
+[[package]]
+name = "wasm-bindgen-backend"
+version = "0.2.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
+dependencies = [
+ "bumpalo",
+ "log",
+ "once_cell",
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-macro"
+version = "0.2.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
+dependencies = [
+ "quote",
+ "wasm-bindgen-macro-support",
+]
+
+[[package]]
+name = "wasm-bindgen-macro-support"
+version = "0.2.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+ "wasm-bindgen-backend",
+ "wasm-bindgen-shared",
+]
+
+[[package]]
+name = "wasm-bindgen-shared"
+version = "0.2.82"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
+
+[[package]]
+name = "web-sys"
+version = "0.3.59"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ed055ab27f941423197eb86b2035720b1a3ce40504df082cac2ecc6ed73335a1"
+dependencies = [
+ "js-sys",
+ "wasm-bindgen",
+]
+
+[[package]]
+name = "webpki"
+version = "0.22.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd"
+dependencies = [
+ "ring",
+ "untrusted",
]
[[package]]
name = "which"
-version = "4.4.2"
+version = "4.2.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
+checksum = "5c4fb54e6113b6a8772ee41c3404fb0301ac79604489467e0a9ce1f3e97c24ae"
dependencies = [
"either",
- "home",
- "once_cell",
- "rustix 0.38.44",
+ "lazy_static",
+ "libc",
]
[[package]]
@@ -1811,6 +1468,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
+[[package]]
+name = "winapi-util"
+version = "0.1.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
+dependencies = [
+ "winapi",
+]
+
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
@@ -1819,146 +1485,43 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
-version = "0.52.0"
+version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
+checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-sys"
-version = "0.59.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
-dependencies = [
- "windows-targets",
-]
-
-[[package]]
-name = "windows-targets"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
-dependencies = [
- "windows_aarch64_gnullvm",
"windows_aarch64_msvc",
"windows_i686_gnu",
- "windows_i686_gnullvm",
"windows_i686_msvc",
"windows_x86_64_gnu",
- "windows_x86_64_gnullvm",
"windows_x86_64_msvc",
]
-[[package]]
-name = "windows_aarch64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
-
[[package]]
name = "windows_aarch64_msvc"
-version = "0.52.6"
+version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
+checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_i686_gnu"
-version = "0.52.6"
+version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
-
-[[package]]
-name = "windows_i686_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
+checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_msvc"
-version = "0.52.6"
+version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
+checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_x86_64_gnu"
-version = "0.52.6"
+version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
-
-[[package]]
-name = "windows_x86_64_gnullvm"
-version = "0.52.6"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
+checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_msvc"
-version = "0.52.6"
+version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
-
-[[package]]
-name = "winnow"
-version = "0.7.4"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "wit-bindgen-rt"
-version = "0.33.0"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c"
-dependencies = [
- "bitflags",
-]
-
-[[package]]
-name = "zerocopy"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
-dependencies = [
- "zerocopy-derive 0.7.35",
-]
-
-[[package]]
-name = "zerocopy"
-version = "0.8.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6"
-dependencies = [
- "zerocopy-derive 0.8.23",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.7.35"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "zerocopy-derive"
-version = "0.8.23"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154"
-dependencies = [
- "proc-macro2",
- "quote",
- "syn",
-]
-
-[[package]]
-name = "zeroize"
-version = "1.8.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
+checksum = "c811ca4a8c853ef420abd8592ba53ddbbac90410fab6903b3e79972a631f7680"
diff --git a/Cargo.toml b/Cargo.toml
index 33f245f..9a659cb 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,72 +1,40 @@
-[workspace]
-resolver = "3"
-members = ["cove", "cove-*"]
+[package]
+name = "cove"
+version = "0.2.1"
+edition = "2021"
-[workspace.package]
-version = "0.9.3"
-edition = "2024"
+[dependencies]
+anyhow = "1.0.61"
+async-trait = "0.1.57"
+clap = { version = "3.2.16", features = ["derive"] }
+cookie = "0.16.0"
+crossterm = "0.25.0"
+directories = "4.0.1"
+edit = "0.1.4"
+futures = "0.3.21"
+log = { version = "0.4.17", features = ["std"] }
+palette = { version = "0.6.1", default-features = false, features = ["std"] }
+parking_lot = "0.12.1"
+rand = "0.8.5"
+rusqlite = { version = "0.28.0", features = ["bundled", "time"] }
+serde = { version = "1.0.143", features = ["derive"] }
+serde_json = "1.0.83"
+thiserror = "1.0.32"
+tokio = { version = "1.20.1", features = ["full"] }
+unicode-segmentation = "1.9.0"
+unicode-width = "0.1.9"
-[workspace.dependencies]
-anyhow = "1.0.97"
-async-trait = "0.1.87"
-clap = { version = "4.5.32", features = ["derive", "deprecated"] }
-cookie = "0.18.1"
-crossterm = "0.28.1"
-directories = "6.0.0"
-edit = "0.1.5"
-jiff = "0.2.4"
-linkify = "0.10.0"
-log = { version = "0.4.26", features = ["std"] }
-open = "5.3.2"
-parking_lot = "0.12.3"
-proc-macro2 = "1.0.94"
-quote = "1.0.40"
-rusqlite = { version = "0.31.0", features = ["bundled", "time"] }
-rustls = "0.23.23"
-serde = { version = "1.0.219", features = ["derive"] }
-serde_either = "0.2.1"
-serde_json = "1.0.140"
-syn = "2.0.100"
-thiserror = "2.0.12"
-tokio = { version = "1.44.1", features = ["full"] }
-toml = "0.8.20"
-unicode-width = "0.2.0"
+[dependencies.time]
+version = "0.3.13"
+features = ["macros", "formatting", "parsing", "serde"]
-[workspace.dependencies.euphoxide]
-git = "https://github.com/Garmelon/euphoxide.git"
-tag = "v0.6.1"
-features = ["bot"]
+[dependencies.tokio-tungstenite]
+version = "0.17.2"
+features = ["rustls-tls-native-roots"]
-[workspace.dependencies.toss]
+[dependencies.toss]
git = "https://github.com/Garmelon/toss.git"
-tag = "v0.3.4"
+rev = "45ece466c235cce6e998bbd404f915cad3628c8c"
-[workspace.dependencies.vault]
-git = "https://github.com/Garmelon/vault.git"
-tag = "v0.4.0"
-features = ["tokio"]
-
-[workspace.lints]
-rust.unsafe_code = { level = "forbid", priority = 1 }
-# Lint groups
-rust.deprecated_safe = "warn"
-rust.future_incompatible = "warn"
-rust.keyword_idents = "warn"
-rust.rust_2018_idioms = "warn"
-rust.unused = "warn"
-# Individual lints
-rust.non_local_definitions = "warn"
-rust.redundant_imports = "warn"
-rust.redundant_lifetimes = "warn"
-rust.single_use_lifetimes = "warn"
-rust.unit_bindings = "warn"
-rust.unnameable_types = "warn"
-rust.unused_crate_dependencies = "warn"
-rust.unused_import_braces = "warn"
-rust.unused_lifetimes = "warn"
-rust.unused_qualifications = "warn"
-# Clippy
-clippy.use_self = "warn"
-
-[profile.dev.package."*"]
-opt-level = 3
+# [patch."https://github.com/Garmelon/toss.git"]
+# toss = { path = "../toss/" }
diff --git a/README.md b/README.md
index 22fef83..7cdfd17 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,62 @@
# cove
-Cove is a TUI client for [euphoria.leet.nu](https://euphoria.leet.nu/), a threaded
+Cove is a TUI client for [euphoria.io](https://euphoria.io/), a threaded
real-time chat platform.

-It runs on Linux, Windows, and macOS.
+It runs on Linux, Windows and macOS.
-## Installing cove
+## Manual installation
-Download a binary of your choice from the
-[latest release on GitHub](https://github.com/Garmelon/cove/releases/latest).
+This section contains instructions on how to install cove by compiling it yourself.
+It doesn't assume you know how to program, but it does assume basic familiarity with the command line on your platform of choice.
+Cove runs in the terminal, after all.
-## Using cove
+### Installing rustup
+
+Cove is written in Rust, so the first step is to install rustup. Either install
+it from your package manager of choice (if you have one) or use the
+[installer](https://rustup.rs/).
+
+Test your installation by running `rustup --version` and `cargo --version`. If
+rustup is installed correctly, both of these should show a version number.
+
+Cove is designed on the current version of the stable toolchain. If cove doesn't
+compile, you can try switching to the stable toolchain and updating it using the
+following commands:
+```bash
+$ rustup default stable
+$ rustup update
+```
+
+### Installing cove
+
+To install or update to the latest release of cove, run the following command:
+
+```bash
+$ cargo install --force --git https://github.com/Garmelon/cove --branch latest
+```
+
+If you like to live dangerously and want to install or update to the latest,
+bleeding-edge, possibly-broken commit from the repo's main branch, run the
+following command.
+
+**Warning:** This could corrupt your vault. Make sure to make a backup before
+running the command.
+
+```bash
+$ cargo install --force --git https://github.com/Garmelon/cove
+```
+
+To install a specific version of cove, run the following command and substitute
+in the full version you want to install:
+
+```bash
+$ cargo install --force --git https://github.com/Garmelon/cove --tag v0.1.0
+```
+
+### Using cove
To start cove, simply run `cove` in your terminal. For more info about the
available subcommands such as exporting room logs or resetting cookies, run
@@ -22,12 +66,3 @@ If you delete rooms, cove's vault (the database it stores messages and other
things in) won't automatically shrink. If it takes up too much space, try
running `cove gc` and waiting for it to finish. This isn't done automatically
because it can take quite a while.
-
-## Configuring cove
-
-A complete list of config options is available in the [CONFIG.md](CONFIG.md)
-file or via `cove help-config`.
-
-When launched, cove prints the location it is loading its config file from. To
-configure cove, create a config file at that location. This location can be
-changed via the `--config` command line option.
diff --git a/cove-config/CONFIG.md b/cove-config/CONFIG.md
deleted file mode 100644
index e69de29..0000000
diff --git a/cove-config/Cargo.toml b/cove-config/Cargo.toml
deleted file mode 100644
index 9102bfd..0000000
--- a/cove-config/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "cove-config"
-version.workspace = true
-edition.workspace = true
-
-[dependencies]
-cove-input = { path = "../cove-input" }
-cove-macro = { path = "../cove-macro" }
-
-serde.workspace = true
-thiserror.workspace = true
-toml.workspace = true
-
-[lints]
-workspace = true
diff --git a/cove-config/src/doc.rs b/cove-config/src/doc.rs
deleted file mode 100644
index 35f6074..0000000
--- a/cove-config/src/doc.rs
+++ /dev/null
@@ -1,267 +0,0 @@
-//! Auto-generate markdown documentation.
-
-use std::{collections::HashMap, path::PathBuf};
-
-use cove_input::KeyBinding;
-pub use cove_macro::Document;
-use serde::Serialize;
-
-const MARKDOWN_INTRODUCTION: &str = r#"# Config file format
-
-Cove's config file uses the [TOML](https://toml.io/) format.
-
-Here is an example config that changes a few different options:
-
-```toml
-measure_widths = true
-rooms_sort_order = "importance"
-
-[euph.servers."euphoria.leet.nu".rooms]
-welcome.autojoin = true
-test.username = "badingle"
-test.force_username = true
-private.password = "foobar"
-
-[keys]
-general.abort = ["esc", "ctrl+c"]
-general.exit = "ctrl+q"
-tree.action.fold_tree = "f"
-```
-
-## Key bindings
-
-Key bindings are specified as strings or lists of strings. Each string specifies
-a main key and zero or more modifier keys. The modifier keys (if any) are listed
-first, followed by the main key. They are separated by the `+` character and
-**no** whitespace.
-
-Examples of key bindings:
-- `"ctrl+c"`
-- `"X"` (not `"shift+x"`)
-- `"space"` or `" "` (both space bar)
-- `["g", "home"]`
-- `["K", "ctrl+up"]`
-- `["f1", "?"]`
-- `"ctrl+alt+f3"`
-- `["enter", "any+enter"]` (matches `enter` regardless of modifiers)
-
-Available main keys:
-- Any single character that can be typed
-- `esc`, `enter`, `space`, `tab`, `backtab`
-- `backspace`, `delete`, `insert`
-- `left`, `right`, `up`, `down`
-- `home`, `end`, `pageup`, `pagedown`
-- `f1`, `f2`, ...
-
-Available modifiers:
-- `shift` (must not be used with single characters)
-- `ctrl`
-- `alt`
-- `any` (matches as long as at least one modifier is pressed)
-
-## Available options
-"#;
-
-pub fn toml_value_as_markdown(value: &T) -> String {
- let mut result = String::new();
- value
- .serialize(toml::ser::ValueSerializer::new(&mut result))
- .expect("not a valid toml value");
- format!("`{result}`")
-}
-
-#[derive(Clone, Default)]
-pub struct ValueInfo {
- pub required: Option,
- pub r#type: Option,
- pub values: Option>,
- pub default: Option,
-}
-
-impl ValueInfo {
- fn as_markdown(&self) -> String {
- let mut lines = vec![];
-
- if let Some(required) = self.required {
- let yesno = if required { "yes" } else { "no" };
- lines.push(format!("**Required:** {yesno}"));
- }
-
- if let Some(r#type) = &self.r#type {
- lines.push(format!("**Type:** {type}"));
- }
-
- if let Some(values) = &self.values {
- let values = values.join(", ");
- lines.push(format!("**Values:** {values}"));
- }
-
- if let Some(default) = &self.default {
- lines.push(format!("**Default:** {default}"));
- }
-
- lines.join(" \n")
- }
-}
-
-#[derive(Clone, Default)]
-pub struct StructInfo {
- pub fields: HashMap>,
-}
-
-#[derive(Clone, Default)]
-pub struct WrapInfo {
- pub inner: Option>,
- pub metavar: Option,
-}
-
-#[derive(Clone, Default)]
-pub struct Doc {
- pub description: Option,
-
- pub value_info: ValueInfo,
- pub struct_info: StructInfo,
- pub wrap_info: WrapInfo,
-}
-
-struct Entry {
- path: String,
- description: String,
- value_info: ValueInfo,
-}
-
-impl Entry {
- fn new(description: String, value_info: ValueInfo) -> Self {
- Self {
- path: String::new(),
- description,
- value_info,
- }
- }
-
- fn with_parent(mut self, segment: String) -> Self {
- if self.path.is_empty() {
- self.path = segment;
- } else {
- self.path = format!("{segment}.{}", self.path);
- }
- self
- }
-}
-
-impl Doc {
- fn entries(&self) -> Vec {
- let mut entries = vec![];
-
- if let Some(description) = &self.description {
- entries.push(Entry::new(description.clone(), self.value_info.clone()));
- }
-
- for (segment, field) in &self.struct_info.fields {
- entries.extend(
- field
- .entries()
- .into_iter()
- .map(|entry| entry.with_parent(segment.clone())),
- );
- }
-
- if let Some(inner) = &self.wrap_info.inner {
- let segment = match &self.wrap_info.metavar {
- Some(metavar) => format!("<{metavar}>"),
- None => "<...>".to_string(),
- };
- entries.extend(
- inner
- .entries()
- .into_iter()
- .map(|entry| entry.with_parent(segment.clone())),
- );
- }
-
- entries
- }
-
- pub fn as_markdown(&self) -> String {
- // Print entries in alphabetical order to make generated documentation
- // format more stable.
- let mut entries = self.entries();
- entries.sort_unstable_by(|a, b| a.path.cmp(&b.path));
-
- let mut result = String::new();
-
- result.push_str(MARKDOWN_INTRODUCTION);
-
- for entry in entries {
- result.push_str(&format!("\n### `{}`\n", entry.path));
-
- let value_info = entry.value_info.as_markdown();
- if !value_info.is_empty() {
- result.push_str(&format!("\n{value_info}\n"));
- }
-
- if !entry.description.is_empty() {
- result.push_str(&format!("\n{}\n", entry.description));
- }
- }
-
- result
- }
-}
-
-pub trait Document {
- fn doc() -> Doc;
-}
-
-impl Document for String {
- fn doc() -> Doc {
- let mut doc = Doc::default();
- doc.value_info.required = Some(true);
- doc.value_info.r#type = Some("string".to_string());
- doc
- }
-}
-
-impl Document for bool {
- fn doc() -> Doc {
- let mut doc = Doc::default();
- doc.value_info.required = Some(true);
- doc.value_info.r#type = Some("boolean".to_string());
- doc
- }
-}
-
-impl Document for PathBuf {
- fn doc() -> Doc {
- let mut doc = Doc::default();
- doc.value_info.required = Some(true);
- doc.value_info.r#type = Some("path".to_string());
- doc
- }
-}
-
-impl Document for Option {
- fn doc() -> Doc {
- let mut doc = I::doc();
- assert_eq!(doc.value_info.required, Some(true));
- doc.value_info.required = Some(false);
- doc
- }
-}
-
-impl Document for HashMap {
- fn doc() -> Doc {
- let mut doc = Doc::default();
- doc.wrap_info.inner = Some(Box::new(I::doc()));
- doc
- }
-}
-
-impl Document for KeyBinding {
- fn doc() -> Doc {
- let mut doc = Doc::default();
- doc.value_info.required = Some(true);
- doc.value_info.r#type = Some("key binding".to_string());
- doc
- }
-}
diff --git a/cove-config/src/euph.rs b/cove-config/src/euph.rs
deleted file mode 100644
index 5ed0fb5..0000000
--- a/cove-config/src/euph.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use std::collections::HashMap;
-
-use serde::{Deserialize, Serialize};
-
-use crate::doc::Document;
-
-#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, Document)]
-#[serde(rename_all = "snake_case")]
-pub enum RoomsSortOrder {
- #[default]
- Alphabet,
- Importance,
-}
-
-// TODO Mark favourite rooms via printable ascii characters
-#[derive(Debug, Clone, Default, Deserialize, Document)]
-pub struct EuphRoom {
- /// Whether to automatically join this room on startup.
- #[serde(default)]
- pub autojoin: bool,
-
- /// If set, cove will set this username upon joining if there is no username
- /// associated with the current session.
- pub username: Option,
-
- /// If `euph.servers..rooms..username` is set, this will force
- /// cove to set the username even if there is already a different username
- /// associated with the current session.
- #[serde(default)]
- pub force_username: bool,
-
- /// If set, cove will try once to use this password to authenticate, should
- /// the room be password-protected.
- pub password: Option,
-}
-
-#[derive(Debug, Default, Deserialize, Document)]
-pub struct EuphServer {
- #[document(metavar = "room")]
- pub rooms: HashMap,
-}
-
-#[derive(Debug, Default, Deserialize, Document)]
-pub struct Euph {
- #[document(metavar = "domain")]
- pub servers: HashMap,
-}
diff --git a/cove-config/src/keys.rs b/cove-config/src/keys.rs
deleted file mode 100644
index 47c171c..0000000
--- a/cove-config/src/keys.rs
+++ /dev/null
@@ -1,427 +0,0 @@
-use cove_input::{KeyBinding, KeyGroup, KeyGroupInfo};
-use serde::Deserialize;
-
-use crate::doc::Document;
-
-macro_rules! default_bindings {
- ( $(
- pub mod $mod:ident { $(
- pub fn $name:ident => [ $($key:expr),* ];
- )* }
- )*) => {
- mod default { $(
- pub mod $mod { $(
- pub fn $name() -> ::cove_input::KeyBinding {
- ::cove_input::KeyBinding::new().with_keys([ $($key),* ]).unwrap()
- }
- )* }
- )* }
- };
-}
-
-default_bindings! {
- pub mod general {
- pub fn exit => ["ctrl+c"];
- pub fn abort => ["esc"];
- pub fn confirm => ["enter"];
- pub fn focus => ["tab"];
- pub fn help => ["f1"];
- pub fn log => ["f12"];
- }
-
- pub mod scroll {
- pub fn up_line => ["ctrl+y"];
- pub fn down_line => ["ctrl+e"];
- pub fn up_half => ["ctrl+u"];
- pub fn down_half => ["ctrl+d"];
- pub fn up_full => ["ctrl+b", "pageup"];
- pub fn down_full => ["ctrl+f", "pagedown"];
- pub fn center_cursor => ["z"];
- }
-
- pub mod cursor {
- pub fn up => ["k", "up"];
- pub fn down => ["j", "down"];
- pub fn to_top => ["g", "home"];
- pub fn to_bottom => ["G", "end"];
- }
-
- pub mod editor_cursor {
- pub fn left => ["ctrl+b","left"];
- pub fn right => ["ctrl+f", "right"];
- pub fn left_word => ["alt+b", "ctrl+left"];
- pub fn right_word => ["alt+f", "ctrl+right"];
- pub fn start => ["ctrl+a", "home"];
- pub fn end => ["ctrl+e", "end"];
- pub fn up => ["up"];
- pub fn down => ["down"];
- }
-
- pub mod editor_action {
- pub fn backspace => ["ctrl+h", "backspace"];
- pub fn delete => ["ctrl+d", "delete"];
- pub fn clear => ["ctrl+l"];
- pub fn external => ["ctrl+x", "alt+e"];
- }
-
- pub mod rooms_action {
- pub fn connect => ["c"];
- pub fn connect_all => ["C"];
- pub fn disconnect => ["d"];
- pub fn disconnect_all => ["D"];
- pub fn connect_autojoin => ["a"];
- pub fn disconnect_non_autojoin => ["A"];
- pub fn new => ["n"];
- pub fn delete => ["X"];
- pub fn change_sort_order => ["s"];
- }
-
- pub mod room_action {
- pub fn authenticate => ["a"];
- pub fn nick => ["n"];
- pub fn more_messages => ["m"];
- pub fn account => ["A"];
- }
-
- pub mod tree_cursor {
- pub fn to_above_sibling => ["K", "ctrl+up"];
- pub fn to_below_sibling => ["J", "ctrl+down"];
- pub fn to_parent => ["p"];
- pub fn to_root => ["P"];
- pub fn to_older_message => ["h", "left"];
- pub fn to_newer_message => ["l", "right"];
- pub fn to_older_unseen_message => ["H", "ctrl+left"];
- pub fn to_newer_unseen_message => ["L", "ctrl+right"];
- }
-
- pub mod tree_action {
- pub fn reply => ["r"];
- pub fn reply_alternate => ["R"];
- pub fn new_thread => ["t"];
- pub fn fold_tree => [" "];
- pub fn toggle_seen => ["s"];
- pub fn mark_visible_seen => ["S"];
- pub fn mark_older_seen => ["ctrl+s"];
- pub fn info => ["i"];
- pub fn links => ["I"];
- pub fn toggle_nick_emoji => ["e"];
- pub fn increase_caesar => ["c"];
- pub fn decrease_caesar => ["C"];
- }
-
-}
-
-#[derive(Debug, Deserialize, Document, KeyGroup)]
-/// General.
-pub struct General {
- /// Quit cove.
- #[serde(default = "default::general::exit")]
- pub exit: KeyBinding,
- /// Abort/close.
- #[serde(default = "default::general::abort")]
- pub abort: KeyBinding,
- /// Confirm.
- #[serde(default = "default::general::confirm")]
- pub confirm: KeyBinding,
- /// Advance focus.
- #[serde(default = "default::general::focus")]
- pub focus: KeyBinding,
- /// Show this help.
- #[serde(default = "default::general::help")]
- pub help: KeyBinding,
- /// Show log.
- #[serde(default = "default::general::log")]
- pub log: KeyBinding,
-}
-
-#[derive(Debug, Deserialize, Document, KeyGroup)]
-/// Scrolling.
-pub struct Scroll {
- /// Scroll up one line.
- #[serde(default = "default::scroll::up_line")]
- pub up_line: KeyBinding,
- /// Scroll down one line.
- #[serde(default = "default::scroll::down_line")]
- pub down_line: KeyBinding,
- /// Scroll up half a screen.
- #[serde(default = "default::scroll::up_half")]
- pub up_half: KeyBinding,
- /// Scroll down half a screen.
- #[serde(default = "default::scroll::down_half")]
- pub down_half: KeyBinding,
- /// Scroll up a full screen.
- #[serde(default = "default::scroll::up_full")]
- pub up_full: KeyBinding,
- /// Scroll down a full screen.
- #[serde(default = "default::scroll::down_full")]
- pub down_full: KeyBinding,
- /// Center cursor.
- #[serde(default = "default::scroll::center_cursor")]
- pub center_cursor: KeyBinding,
-}
-
-#[derive(Debug, Deserialize, Document, KeyGroup)]
-/// Cursor movement.
-pub struct Cursor {
- /// Move up.
- #[serde(default = "default::cursor::up")]
- pub up: KeyBinding,
- /// Move down.
- #[serde(default = "default::cursor::down")]
- pub down: KeyBinding,
- /// Move to top.
- #[serde(default = "default::cursor::to_top")]
- pub to_top: KeyBinding,
- /// Move to bottom.
- #[serde(default = "default::cursor::to_bottom")]
- pub to_bottom: KeyBinding,
-}
-
-#[derive(Debug, Deserialize, Document, KeyGroup)]
-/// Editor cursor movement.
-pub struct EditorCursor {
- /// Move left.
- #[serde(default = "default::editor_cursor::left")]
- pub left: KeyBinding,
- /// Move right.
- #[serde(default = "default::editor_cursor::right")]
- pub right: KeyBinding,
- /// Move left a word.
- #[serde(default = "default::editor_cursor::left_word")]
- pub left_word: KeyBinding,
- /// Move right a word.
- #[serde(default = "default::editor_cursor::right_word")]
- pub right_word: KeyBinding,
- /// Move to start of line.
- #[serde(default = "default::editor_cursor::start")]
- pub start: KeyBinding,
- /// Move to end of line.
- #[serde(default = "default::editor_cursor::end")]
- pub end: KeyBinding,
- /// Move up.
- #[serde(default = "default::editor_cursor::up")]
- pub up: KeyBinding,
- /// Move down.
- #[serde(default = "default::editor_cursor::down")]
- pub down: KeyBinding,
-}
-
-#[derive(Debug, Deserialize, Document, KeyGroup)]
-/// Editor actions.
-pub struct EditorAction {
- /// Delete before cursor.
- #[serde(default = "default::editor_action::backspace")]
- pub backspace: KeyBinding,
- /// Delete after cursor.
- #[serde(default = "default::editor_action::delete")]
- pub delete: KeyBinding,
- /// Clear editor contents.
- #[serde(default = "default::editor_action::clear")]
- pub clear: KeyBinding,
- /// Edit in external editor.
- #[serde(default = "default::editor_action::external")]
- pub external: KeyBinding,
-}
-
-#[derive(Debug, Default, Deserialize, Document)]
-pub struct Editor {
- #[serde(default)]
- #[document(no_default)]
- pub cursor: EditorCursor,
-
- #[serde(default)]
- #[document(no_default)]
- pub action: EditorAction,
-}
-
-#[derive(Debug, Deserialize, Document, KeyGroup)]
-/// Room list actions.
-pub struct RoomsAction {
- /// Connect to selected room.
- #[serde(default = "default::rooms_action::connect")]
- pub connect: KeyBinding,
- /// Connect to all rooms.
- #[serde(default = "default::rooms_action::connect_all")]
- pub connect_all: KeyBinding,
- /// Disconnect from selected room.
- #[serde(default = "default::rooms_action::disconnect")]
- pub disconnect: KeyBinding,
- /// Disconnect from all rooms.
- #[serde(default = "default::rooms_action::disconnect_all")]
- pub disconnect_all: KeyBinding,
- /// Connect to all autojoin rooms.
- #[serde(default = "default::rooms_action::connect_autojoin")]
- pub connect_autojoin: KeyBinding,
- /// Disconnect from all non-autojoin rooms.
- #[serde(default = "default::rooms_action::disconnect_non_autojoin")]
- pub disconnect_non_autojoin: KeyBinding,
- /// Connect to new room.
- #[serde(default = "default::rooms_action::new")]
- pub new: KeyBinding,
- /// Delete room.
- #[serde(default = "default::rooms_action::delete")]
- pub delete: KeyBinding,
- /// Change sort order.
- #[serde(default = "default::rooms_action::change_sort_order")]
- pub change_sort_order: KeyBinding,
-}
-
-#[derive(Debug, Default, Deserialize, Document)]
-pub struct Rooms {
- #[serde(default)]
- #[document(no_default)]
- pub action: RoomsAction,
-}
-
-#[derive(Debug, Deserialize, Document, KeyGroup)]
-/// Room actions.
-pub struct RoomAction {
- /// Authenticate.
- #[serde(default = "default::room_action::authenticate")]
- pub authenticate: KeyBinding,
- /// Change nick.
- #[serde(default = "default::room_action::nick")]
- pub nick: KeyBinding,
- /// Download more messages.
- #[serde(default = "default::room_action::more_messages")]
- pub more_messages: KeyBinding,
- /// Manage account.
- #[serde(default = "default::room_action::account")]
- pub account: KeyBinding,
-}
-
-#[derive(Debug, Default, Deserialize, Document)]
-pub struct Room {
- #[serde(default)]
- #[document(no_default)]
- pub action: RoomAction,
-}
-
-#[derive(Debug, Deserialize, Document, KeyGroup)]
-/// Tree cursor movement.
-pub struct TreeCursor {
- /// Move to above sibling.
- #[serde(default = "default::tree_cursor::to_above_sibling")]
- pub to_above_sibling: KeyBinding,
- /// Move to below sibling.
- #[serde(default = "default::tree_cursor::to_below_sibling")]
- pub to_below_sibling: KeyBinding,
- /// Move to parent.
- #[serde(default = "default::tree_cursor::to_parent")]
- pub to_parent: KeyBinding,
- /// Move to root.
- #[serde(default = "default::tree_cursor::to_root")]
- pub to_root: KeyBinding,
- /// Move to older message.
- #[serde(default = "default::tree_cursor::to_older_message")]
- pub to_older_message: KeyBinding,
- /// Move to newer message.
- #[serde(default = "default::tree_cursor::to_newer_message")]
- pub to_newer_message: KeyBinding,
- /// Move to older unseen message.
- #[serde(default = "default::tree_cursor::to_older_unseen_message")]
- pub to_older_unseen_message: KeyBinding,
- /// Move to newer unseen message.
- #[serde(default = "default::tree_cursor::to_newer_unseen_message")]
- pub to_newer_unseen_message: KeyBinding,
- // TODO Bindings inspired by vim's ()/[]/{} bindings?
-}
-
-#[derive(Debug, Deserialize, Document, KeyGroup)]
-/// Tree actions.
-pub struct TreeAction {
- /// Reply to message, inline if possible.
- #[serde(default = "default::tree_action::reply")]
- pub reply: KeyBinding,
- /// Reply opposite to normal reply.
- #[serde(default = "default::tree_action::reply_alternate")]
- pub reply_alternate: KeyBinding,
- /// Start a new thread.
- #[serde(default = "default::tree_action::new_thread")]
- pub new_thread: KeyBinding,
- /// Fold current message's subtree.
- #[serde(default = "default::tree_action::fold_tree")]
- pub fold_tree: KeyBinding,
- /// Toggle current message's seen status.
- #[serde(default = "default::tree_action::toggle_seen")]
- pub toggle_seen: KeyBinding,
- /// Mark all visible messages as seen.
- #[serde(default = "default::tree_action::mark_visible_seen")]
- pub mark_visible_seen: KeyBinding,
- /// Mark all older messages as seen.
- #[serde(default = "default::tree_action::mark_older_seen")]
- pub mark_older_seen: KeyBinding,
- /// Inspect selected element.
- #[serde(default = "default::tree_action::info")]
- pub inspect: KeyBinding,
- /// List links found in message.
- #[serde(default = "default::tree_action::links")]
- pub links: KeyBinding,
- /// Toggle agent id based nick emoji.
- #[serde(default = "default::tree_action::toggle_nick_emoji")]
- pub toggle_nick_emoji: KeyBinding,
- /// Increase caesar cipher rotation.
- #[serde(default = "default::tree_action::increase_caesar")]
- pub increase_caesar: KeyBinding,
- /// Decrease caesar cipher rotation.
- #[serde(default = "default::tree_action::decrease_caesar")]
- pub decrease_caesar: KeyBinding,
-}
-
-#[derive(Debug, Default, Deserialize, Document)]
-pub struct Tree {
- #[serde(default)]
- #[document(no_default)]
- pub cursor: TreeCursor,
-
- #[serde(default)]
- #[document(no_default)]
- pub action: TreeAction,
-}
-
-#[derive(Debug, Default, Deserialize, Document)]
-pub struct Keys {
- #[serde(default)]
- #[document(no_default)]
- pub general: General,
-
- #[serde(default)]
- #[document(no_default)]
- pub scroll: Scroll,
-
- #[serde(default)]
- #[document(no_default)]
- pub cursor: Cursor,
-
- #[serde(default)]
- #[document(no_default)]
- pub editor: Editor,
-
- #[serde(default)]
- #[document(no_default)]
- pub rooms: Rooms,
-
- #[serde(default)]
- #[document(no_default)]
- pub room: Room,
-
- #[serde(default)]
- #[document(no_default)]
- pub tree: Tree,
-}
-
-impl Keys {
- pub fn groups(&self) -> Vec> {
- vec![
- KeyGroupInfo::new("general", &self.general),
- KeyGroupInfo::new("scroll", &self.scroll),
- KeyGroupInfo::new("cursor", &self.cursor),
- KeyGroupInfo::new("editor.cursor", &self.editor.cursor),
- KeyGroupInfo::new("editor.action", &self.editor.action),
- KeyGroupInfo::new("rooms.action", &self.rooms.action),
- KeyGroupInfo::new("room.action", &self.room.action),
- KeyGroupInfo::new("tree.cursor", &self.tree.cursor),
- KeyGroupInfo::new("tree.action", &self.tree.action),
- ]
- }
-}
diff --git a/cove-config/src/lib.rs b/cove-config/src/lib.rs
deleted file mode 100644
index 0cb6cc7..0000000
--- a/cove-config/src/lib.rs
+++ /dev/null
@@ -1,158 +0,0 @@
-use std::{
- fs,
- io::{self, ErrorKind},
- path::{Path, PathBuf},
-};
-
-use doc::Document;
-use serde::{Deserialize, Serialize};
-
-pub use crate::{euph::*, keys::*};
-
-pub mod doc;
-mod euph;
-mod keys;
-
-#[derive(Debug, thiserror::Error)]
-pub enum Error {
- #[error("failed to read config file")]
- Io(#[from] io::Error),
- #[error("failed to parse config file")]
- Toml(#[from] toml::de::Error),
-}
-
-#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize, Document)]
-#[serde(rename_all = "snake_case")]
-pub enum WidthEstimationMethod {
- #[default]
- Legacy,
- Unicode,
-}
-
-#[derive(Debug, Default, Deserialize, Document)]
-pub struct Config {
- /// The directory that cove stores its data in when not running in ephemeral
- /// mode.
- ///
- /// Relative paths are interpreted relative to the user's home directory.
- ///
- /// See also the `--data-dir` command line option.
- #[document(default = "platform-dependent")]
- pub data_dir: Option,
-
- /// Whether to start in ephemeral mode.
- ///
- /// In ephemeral mode, cove doesn't store any data. It completely ignores
- /// any options related to the data dir.
- ///
- /// See also the `--ephemeral` command line option.
- #[serde(default)]
- pub ephemeral: bool,
-
- /// How to estimate the width of graphemes (i.e. characters) as displayed by
- /// the terminal emulator.
- ///
- /// `"legacy"`: Use a legacy method that should mostly work on most terminal
- /// emulators. This method will never be correct in all cases since every
- /// terminal emulator handles grapheme widths slightly differently. However,
- /// those cases are usually rare (unless you view a lot of emoji).
- ///
- /// `"unicode"`: Use the unicode standard in a best-effort manner to
- /// determine grapheme widths. Some terminals (e.g. ghostty) can make use of
- /// this.
- ///
- /// This method is used when `measure_widths` is set to `false`.
- ///
- /// See also the `--width-estimation-method` command line option.
- #[serde(default)]
- pub width_estimation_method: WidthEstimationMethod,
-
- /// Whether to measure the width of graphemes (i.e. characters) as displayed
- /// by the terminal emulator instead of estimating the width.
- ///
- /// Enabling this makes rendering a bit slower but more accurate. The screen
- /// might also flash when encountering new graphemes.
- ///
- /// See also the `--measure-widths` command line option.
- #[serde(default)]
- pub measure_widths: bool,
-
- /// Whether to start in offline mode.
- ///
- /// In offline mode, cove won't automatically join rooms marked via the
- /// `autojoin` option on startup. You can still join those rooms manually by
- /// pressing `a` in the rooms list.
- ///
- /// See also the `--offline` command line option.
- #[serde(default)]
- pub offline: bool,
-
- /// Initial sort order of rooms list.
- ///
- /// `"alphabet"` sorts rooms in alphabetic order.
- ///
- /// `"importance"` sorts rooms by the following criteria (in descending
- /// order of priority):
- ///
- /// 1. connected rooms before unconnected rooms
- /// 2. rooms with unread messages before rooms without
- /// 3. alphabetic order
- #[serde(default)]
- pub rooms_sort_order: RoomsSortOrder,
-
- /// Ring the bell (character 0x07) when you are mentioned in a room.
- #[serde(default)]
- pub bell_on_mention: bool,
-
- /// Time zone that chat timestamps should be displayed in.
- ///
- /// This option can either be the string `"localtime"`, a [POSIX TZ string],
- /// or a [tz identifier] from the [tz database].
- ///
- /// When not set or when set to `"localtime"`, cove attempts to use your
- /// system's configured time zone, falling back to UTC.
- ///
- /// When the string begins with a colon or doesn't match the a POSIX TZ
- /// string format, it is interpreted as a tz identifier and looked up in
- /// your system's tz database (or a bundled tz database on Windows).
- ///
- /// If the `TZ` environment variable exists, it overrides this option.
- ///
- /// [POSIX TZ string]: https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03
- /// [tz identifier]: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
- /// [tz database]: https://en.wikipedia.org/wiki/Tz_database
- #[serde(default)]
- #[document(default = "`$TZ` or local system time zone")]
- pub time_zone: Option,
-
- #[serde(default)]
- #[document(no_default)]
- pub euph: Euph,
-
- #[serde(default)]
- #[document(no_default)]
- pub keys: Keys,
-}
-
-impl Config {
- pub fn load(path: &Path) -> Result {
- Ok(match fs::read_to_string(path) {
- Ok(content) => toml::from_str(&content)?,
- Err(err) if err.kind() == ErrorKind::NotFound => Self::default(),
- Err(err) => Err(err)?,
- })
- }
-
- pub fn euph_room(&self, domain: &str, name: &str) -> EuphRoom {
- if let Some(server) = self.euph.servers.get(domain) {
- if let Some(room) = server.rooms.get(name) {
- return room.clone();
- }
- }
- EuphRoom::default()
- }
-
- pub fn time_zone_ref(&self) -> Option<&str> {
- self.time_zone.as_ref().map(|s| s as &str)
- }
-}
diff --git a/cove-input/Cargo.toml b/cove-input/Cargo.toml
deleted file mode 100644
index 5005be2..0000000
--- a/cove-input/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-name = "cove-input"
-version.workspace = true
-edition.workspace = true
-
-[dependencies]
-cove-macro = { path = "../cove-macro" }
-
-crossterm.workspace = true
-edit.workspace = true
-parking_lot.workspace = true
-serde.workspace = true
-serde_either.workspace = true
-thiserror.workspace = true
-toss.workspace = true
-
-[lints]
-workspace = true
diff --git a/cove-input/src/keys.rs b/cove-input/src/keys.rs
deleted file mode 100644
index 8d2fdf1..0000000
--- a/cove-input/src/keys.rs
+++ /dev/null
@@ -1,252 +0,0 @@
-use std::{fmt, num::ParseIntError, str::FromStr};
-
-use crossterm::event::{KeyCode, KeyEvent, KeyModifiers};
-use serde::{Deserialize, Deserializer, Serialize, Serializer, de::Error};
-use serde_either::SingleOrVec;
-
-#[derive(Debug, thiserror::Error)]
-pub enum ParseKeysError {
- #[error("no key code specified")]
- NoKeyCode,
- #[error("unknown key code: {0:?}")]
- UnknownKeyCode(String),
- #[error("invalid function key number: {0}")]
- InvalidFNumber(#[from] ParseIntError),
- #[error("unknown modifier: {0:?}")]
- UnknownModifier(String),
- #[error("modifier {0} conflicts with previous modifier")]
- ConflictingModifier(String),
-}
-
-fn conflicts_with_shift(code: KeyCode) -> bool {
- match code {
- KeyCode::Char(' ') => false,
- KeyCode::Char(_) => true,
- _ => false,
- }
-}
-
-#[derive(Debug, Clone, Copy, PartialEq, Eq)]
-pub struct KeyPress {
- pub code: KeyCode,
- pub shift: bool,
- pub ctrl: bool,
- pub alt: bool,
- pub any: bool,
-}
-
-impl KeyPress {
- fn parse_key_code(code: &str) -> Result {
- let code = match code {
- "esc" => KeyCode::Esc,
- "enter" => KeyCode::Enter,
- "space" => KeyCode::Char(' '),
- "tab" => KeyCode::Tab,
- "backtab" => KeyCode::BackTab,
-
- "backspace" => KeyCode::Backspace,
- "delete" => KeyCode::Delete,
- "insert" => KeyCode::Insert,
-
- "left" => KeyCode::Left,
- "right" => KeyCode::Right,
- "up" => KeyCode::Up,
- "down" => KeyCode::Down,
-
- "home" => KeyCode::Home,
- "end" => KeyCode::End,
- "pageup" => KeyCode::PageUp,
- "pagedown" => KeyCode::PageDown,
-
- c if c.chars().count() == 1 => KeyCode::Char(c.chars().next().unwrap()),
- c if c.starts_with('f') => KeyCode::F(c.strip_prefix('f').unwrap().parse()?),
-
- "" => return Err(ParseKeysError::NoKeyCode),
- c => return Err(ParseKeysError::UnknownKeyCode(c.to_string())),
- };
- Ok(Self {
- code,
- shift: false,
- ctrl: false,
- alt: false,
- any: false,
- })
- }
-
- fn display_key_code(code: KeyCode) -> String {
- match code {
- KeyCode::Esc => "esc".to_string(),
- KeyCode::Enter => "enter".to_string(),
- KeyCode::Char(' ') => "space".to_string(),
- KeyCode::Tab => "tab".to_string(),
- KeyCode::BackTab => "backtab".to_string(),
-
- KeyCode::Backspace => "backspace".to_string(),
- KeyCode::Delete => "delete".to_string(),
- KeyCode::Insert => "insert".to_string(),
-
- KeyCode::Left => "left".to_string(),
- KeyCode::Right => "right".to_string(),
- KeyCode::Up => "up".to_string(),
- KeyCode::Down => "down".to_string(),
-
- KeyCode::Home => "home".to_string(),
- KeyCode::End => "end".to_string(),
- KeyCode::PageUp => "pageup".to_string(),
- KeyCode::PageDown => "pagedown".to_string(),
-
- KeyCode::Char(c) => c.to_string(),
- KeyCode::F(n) => format!("f{n}"),
-
- _ => "unknown".to_string(),
- }
- }
-
- fn parse_modifier(
- &mut self,
- modifier: &str,
- shift_allowed: bool,
- ) -> Result<(), ParseKeysError> {
- match modifier {
- m if self.any => return Err(ParseKeysError::ConflictingModifier(m.to_string())),
- "shift" if shift_allowed && !self.shift => self.shift = true,
- "ctrl" if !self.ctrl => self.ctrl = true,
- "alt" if !self.alt => self.alt = true,
- "any" if !self.shift && !self.ctrl && !self.alt => self.any = true,
- m @ ("shift" | "ctrl" | "alt" | "any") => {
- return Err(ParseKeysError::ConflictingModifier(m.to_string()));
- }
- m => return Err(ParseKeysError::UnknownModifier(m.to_string())),
- }
- Ok(())
- }
-
- pub fn matches(&self, event: KeyEvent) -> bool {
- if event.code != self.code {
- return false;
- }
-
- if self.any && !event.modifiers.is_empty() {
- return true;
- }
-
- let ctrl = event.modifiers.contains(KeyModifiers::CONTROL) == self.ctrl;
- let alt = event.modifiers.contains(KeyModifiers::ALT) == self.alt;
- if conflicts_with_shift(self.code) {
- ctrl && alt
- } else {
- let shift = event.modifiers.contains(KeyModifiers::SHIFT) == self.shift;
- shift && ctrl && alt
- }
- }
-}
-
-impl FromStr for KeyPress {
- type Err = ParseKeysError;
-
- fn from_str(s: &str) -> Result {
- let mut parts = s.split('+');
- let code = parts.next_back().ok_or(ParseKeysError::NoKeyCode)?;
-
- let mut keys = Self::parse_key_code(code)?;
- let shift_allowed = !conflicts_with_shift(keys.code);
- for modifier in parts {
- keys.parse_modifier(modifier, shift_allowed)?;
- }
-
- Ok(keys)
- }
-}
-
-impl fmt::Display for KeyPress {
- fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
- let code = Self::display_key_code(self.code);
-
- let mut segments = vec![];
- if self.shift {
- segments.push("shift");
- }
- if self.ctrl {
- segments.push("ctrl");
- }
- if self.alt {
- segments.push("alt");
- }
- if self.any {
- segments.push("any");
- }
- segments.push(&code);
-
- segments.join("+").fmt(f)
- }
-}
-
-impl Serialize for KeyPress {
- fn serialize(&self, serializer: S) -> Result {
- format!("{self}").serialize(serializer)
- }
-}
-
-impl<'de> Deserialize<'de> for KeyPress {
- fn deserialize>(deserializer: D) -> Result {
- String::deserialize(deserializer)?
- .parse()
- .map_err(|e| D::Error::custom(format!("{e}")))
- }
-}
-
-#[derive(Debug, Clone)]
-pub struct KeyBinding(Vec);
-
-impl KeyBinding {
- pub fn new() -> Self {
- Self(vec![])
- }
-
- pub fn keys(&self) -> &[KeyPress] {
- &self.0
- }
-
- pub fn with_key(self, key: &str) -> Result {
- self.with_keys([key])
- }
-
- pub fn with_keys<'a, I>(mut self, keys: I) -> Result
- where
- I: IntoIterator- ,
- {
- for key in keys {
- self.0.push(key.parse()?);
- }
- Ok(self)
- }
-
- pub fn matches(&self, event: KeyEvent) -> bool {
- self.0.iter().any(|kp| kp.matches(event))
- }
-}
-
-impl Default for KeyBinding {
- fn default() -> Self {
- Self::new()
- }
-}
-
-impl Serialize for KeyBinding {
- fn serialize(&self, serializer: S) -> Result {
- if self.0.len() == 1 {
- self.0[0].serialize(serializer)
- } else {
- self.0.serialize(serializer)
- }
- }
-}
-
-impl<'de> Deserialize<'de> for KeyBinding {
- fn deserialize>(deserializer: D) -> Result {
- Ok(match SingleOrVec::::deserialize(deserializer)? {
- SingleOrVec::Single(key) => Self(vec![key]),
- SingleOrVec::Vec(keys) => Self(keys),
- })
- }
-}
diff --git a/cove-input/src/lib.rs b/cove-input/src/lib.rs
deleted file mode 100644
index f6b2e92..0000000
--- a/cove-input/src/lib.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-use std::{io, sync::Arc};
-
-pub use cove_macro::KeyGroup;
-use crossterm::event::{Event, KeyEvent, KeyEventKind};
-use parking_lot::FairMutex;
-use toss::{Frame, Terminal, WidthDb};
-
-pub use crate::keys::*;
-
-mod keys;
-
-pub struct KeyBindingInfo<'a> {
- pub name: &'static str,
- pub binding: &'a KeyBinding,
- pub description: &'static str,
-}
-
-/// A group of related key bindings.
-pub trait KeyGroup {
- const DESCRIPTION: &'static str;
-
- fn bindings(&self) -> Vec>;
-}
-
-pub struct KeyGroupInfo<'a> {
- pub name: &'static str,
- pub description: &'static str,
- pub bindings: Vec>,
-}
-
-impl<'a> KeyGroupInfo<'a> {
- pub fn new(name: &'static str, group: &'a G) -> Self {
- Self {
- name,
- description: G::DESCRIPTION,
- bindings: group.bindings(),
- }
- }
-}
-
-pub struct InputEvent<'a> {
- event: Event,
- terminal: &'a mut Terminal,
- crossterm_lock: Arc>,
-}
-
-impl<'a> InputEvent<'a> {
- pub fn new(
- event: Event,
- terminal: &'a mut Terminal,
- crossterm_lock: Arc>,
- ) -> Self {
- Self {
- event,
- terminal,
- crossterm_lock,
- }
- }
-
- /// If the current event represents a key press, returns the [`KeyEvent`]
- /// associated with that key press.
- pub fn key_event(&self) -> Option {
- if let Event::Key(event) = &self.event {
- if matches!(event.kind, KeyEventKind::Press | KeyEventKind::Repeat) {
- return Some(*event);
- }
- }
- None
- }
-
- pub fn paste_event(&self) -> Option<&str> {
- match &self.event {
- Event::Paste(string) => Some(string),
- _ => None,
- }
- }
-
- pub fn matches(&self, binding: &KeyBinding) -> bool {
- match self.key_event() {
- Some(event) => binding.matches(event),
- None => false,
- }
- }
-
- pub fn frame(&mut self) -> &mut Frame {
- self.terminal.frame()
- }
-
- pub fn widthdb(&mut self) -> &mut WidthDb {
- self.terminal.widthdb()
- }
-
- pub fn prompt(&mut self, initial_text: &str) -> io::Result {
- let guard = self.crossterm_lock.lock();
- self.terminal.suspend().expect("failed to suspend");
- let content = edit::edit(initial_text);
- self.terminal.unsuspend().expect("fauled to unsuspend");
- drop(guard);
-
- content
- }
-}
diff --git a/cove-macro/Cargo.toml b/cove-macro/Cargo.toml
deleted file mode 100644
index 6c01b7d..0000000
--- a/cove-macro/Cargo.toml
+++ /dev/null
@@ -1,15 +0,0 @@
-[package]
-name = "cove-macro"
-version.workspace = true
-edition.workspace = true
-
-[dependencies]
-proc-macro2.workspace = true
-quote.workspace = true
-syn.workspace = true
-
-[lib]
-proc-macro = true
-
-[lints]
-workspace = true
diff --git a/cove-macro/src/document.rs b/cove-macro/src/document.rs
deleted file mode 100644
index afec84d..0000000
--- a/cove-macro/src/document.rs
+++ /dev/null
@@ -1,152 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::quote;
-use syn::{Data, DataEnum, DataStruct, DeriveInput, Field, Ident, LitStr, spanned::Spanned};
-
-use crate::util::{self, SerdeDefault};
-
-#[derive(Default)]
-struct FieldInfo {
- description: Option,
- metavar: Option,
- default: Option,
- serde_default: Option,
- no_default: bool,
-}
-
-impl FieldInfo {
- fn initialize_from_field(&mut self, field: &Field) -> syn::Result<()> {
- let docstring = util::docstring(&field.attrs)?;
- if !docstring.is_empty() {
- self.description = Some(docstring);
- }
-
- for arg in util::attribute_arguments(&field.attrs, "document")? {
- if arg.path.is_ident("metavar") {
- // Parse `#[document(metavar = "bla")]`
- if let Some(metavar) = arg.value.and_then(util::into_litstr) {
- self.metavar = Some(metavar);
- } else {
- util::bail(arg.path.span(), "must be of the form `key = \"value\"`")?;
- }
- } else if arg.path.is_ident("default") {
- // Parse `#[document(default = "bla")]`
- if let Some(value) = arg.value.and_then(util::into_litstr) {
- self.default = Some(value);
- } else {
- util::bail(arg.path.span(), "must be of the form `key = \"value\"`")?;
- }
- } else if arg.path.is_ident("no_default") {
- // Parse #[document(no_default)]
- if arg.value.is_some() {
- util::bail(arg.path.span(), "must not have a value")?;
- }
- self.no_default = true;
- } else {
- util::bail(arg.path.span(), "unknown argument name")?;
- }
- }
-
- // Find `#[serde(default)]` or `#[serde(default = "bla")]`.
- self.serde_default = util::serde_default(field)?;
-
- Ok(())
- }
-
- fn from_field(field: &Field) -> syn::Result {
- let mut result = Self::default();
- result.initialize_from_field(field)?;
- Ok(result)
- }
-}
-
-fn from_struct(ident: Ident, data: DataStruct) -> syn::Result {
- let mut fields = vec![];
- for field in data.fields {
- let Some(ident) = field.ident.as_ref() else {
- return util::bail(field.span(), "must not be a tuple struct");
- };
- let ident = ident.to_string();
-
- let info = FieldInfo::from_field(&field)?;
-
- let mut setters = vec![];
- if let Some(description) = info.description {
- setters.push(quote! {
- doc.description = Some(#description.to_string());
- });
- }
- if let Some(metavar) = info.metavar {
- setters.push(quote! {
- doc.wrap_info.metavar = Some(#metavar.to_string());
- });
- }
- if info.no_default {
- } else if let Some(default) = info.default {
- setters.push(quote! {
- doc.value_info.default = Some(#default.to_string());
- });
- } else if let Some(serde_default) = info.serde_default {
- let value = serde_default.value();
- setters.push(quote! {
- doc.value_info.default = Some(crate::doc::toml_value_as_markdown(value));
- });
- }
-
- let ty = field.ty;
- fields.push(quote! {
- fields.insert(
- #ident.to_string(),
- {
- let mut doc = <#ty as crate::doc::Document>::doc();
- #( #setters )*
- ::std::boxed::Box::new(doc)
- }
- );
- });
- }
-
- let tokens = quote!(
- impl crate::doc::Document for #ident {
- fn doc() -> crate::doc::Doc {
- let mut fields = ::std::collections::HashMap::new();
- #( #fields )*
-
- let mut doc = crate::doc::Doc::default();
- doc.struct_info.fields = fields;
- doc
- }
- }
- );
-
- Ok(tokens)
-}
-
-fn from_enum(ident: Ident, data: DataEnum) -> syn::Result {
- let mut values = vec![];
- for variant in data.variants {
- let ident = variant.ident;
- values.push(quote! {
- crate::doc::toml_value_as_markdown(&Self::#ident)
- });
- }
-
- let tokens = quote!(
- impl crate::doc::Document for #ident {
- fn doc() -> crate::doc::Doc {
- let mut doc = ::doc();
- doc.value_info.values = Some(vec![ #( #values ),* ]);
- doc
- }
- }
- );
-
- Ok(tokens)
-}
-
-pub fn derive_impl(input: DeriveInput) -> syn::Result {
- match input.data {
- Data::Struct(data) => from_struct(input.ident, data),
- Data::Enum(data) => from_enum(input.ident, data),
- Data::Union(_) => util::bail(input.span(), "must be an enum or a struct"),
- }
-}
diff --git a/cove-macro/src/key_group.rs b/cove-macro/src/key_group.rs
deleted file mode 100644
index 832bfd3..0000000
--- a/cove-macro/src/key_group.rs
+++ /dev/null
@@ -1,74 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::quote;
-use syn::{Data, DeriveInput, spanned::Spanned};
-
-use crate::util;
-
-fn decapitalize(s: &str) -> String {
- let mut chars = s.chars();
- if let Some(char) = chars.next() {
- char.to_lowercase().chain(chars).collect()
- } else {
- String::new()
- }
-}
-
-pub fn derive_impl(input: DeriveInput) -> syn::Result {
- let Data::Struct(data) = input.data else {
- return util::bail(input.span(), "must be a struct");
- };
-
- let docstring = util::docstring(&input.attrs)?;
- let description = docstring.strip_suffix('.').unwrap_or(&docstring);
-
- let mut bindings = vec![];
- let mut defaults = vec![];
- for field in &data.fields {
- if let Some(field_ident) = &field.ident {
- let field_name = field_ident.to_string();
-
- let docstring = util::docstring(&field.attrs)?;
- let description = decapitalize(&docstring);
- let description = description.strip_suffix('.').unwrap_or(&description);
-
- let default = util::serde_default(field)?;
- let Some(default) = default else {
- return util::bail(field_ident.span(), "must have serde default");
- };
- let default_value = default.value();
-
- bindings.push(quote! {
- ::cove_input::KeyBindingInfo {
- name: #field_name,
- binding: &self.#field_ident,
- description: #description
- }
- });
-
- defaults.push(quote! {
- #field_ident: #default_value,
- });
- }
- }
-
- let ident = input.ident;
- Ok(quote! {
- impl ::cove_input::KeyGroup for #ident {
- const DESCRIPTION: &'static str = #description;
-
- fn bindings(&self) -> Vec<::cove_input::KeyBindingInfo<'_>> {
- vec![
- #( #bindings, )*
- ]
- }
- }
-
- impl Default for #ident {
- fn default() -> Self {
- Self {
- #( #defaults )*
- }
- }
- }
- })
-}
diff --git a/cove-macro/src/lib.rs b/cove-macro/src/lib.rs
deleted file mode 100644
index c655f2a..0000000
--- a/cove-macro/src/lib.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use syn::{DeriveInput, parse_macro_input};
-
-mod document;
-mod key_group;
-mod util;
-
-#[proc_macro_derive(Document, attributes(document))]
-pub fn derive_document(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- let input = parse_macro_input!(input as DeriveInput);
- match document::derive_impl(input) {
- Ok(tokens) => tokens.into(),
- Err(err) => err.into_compile_error().into(),
- }
-}
-
-#[proc_macro_derive(KeyGroup)]
-pub fn derive_group(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- let input = parse_macro_input!(input as DeriveInput);
- match key_group::derive_impl(input) {
- Ok(tokens) => tokens.into(),
- Err(err) => err.into_compile_error().into(),
- }
-}
diff --git a/cove-macro/src/util.rs b/cove-macro/src/util.rs
deleted file mode 100644
index d73b7ca..0000000
--- a/cove-macro/src/util.rs
+++ /dev/null
@@ -1,117 +0,0 @@
-use proc_macro2::{Span, TokenStream};
-use quote::quote;
-use syn::{
- Attribute, Expr, ExprLit, ExprPath, Field, Lit, LitStr, Path, Token, Type, parse::Parse,
- punctuated::Punctuated,
-};
-
-pub fn bail(span: Span, message: &str) -> syn::Result {
- Err(syn::Error::new(span, message))
-}
-
-pub fn litstr(expr: &Expr) -> Option<&LitStr> {
- match expr {
- Expr::Lit(ExprLit {
- lit: Lit::Str(lit), ..
- }) => Some(lit),
- _ => None,
- }
-}
-
-pub fn into_litstr(expr: Expr) -> Option {
- match expr {
- Expr::Lit(ExprLit {
- lit: Lit::Str(lit), ..
- }) => Some(lit),
- _ => None,
- }
-}
-
-/// Given a struct field, this finds all attributes like `#[doc = "bla"]`,
-/// unindents, concatenates and returns them.
-pub fn docstring(attributes: &[Attribute]) -> syn::Result {
- let mut lines = vec![];
-
- for attr in attributes.iter().filter(|attr| attr.path().is_ident("doc")) {
- if let Some(lit) = litstr(&attr.meta.require_name_value()?.value) {
- let value = lit.value();
- let value = value
- .strip_prefix(' ')
- .map(|value| value.to_string())
- .unwrap_or(value);
- lines.push(value);
- }
- }
-
- Ok(lines.join("\n"))
-}
-
-pub struct AttributeArgument {
- pub path: Path,
- pub value: Option,
-}
-
-impl Parse for AttributeArgument {
- fn parse(input: syn::parse::ParseStream<'_>) -> syn::Result {
- let path = Path::parse(input)?;
- let value = if input.peek(Token![=]) {
- input.parse::()?;
- Some(Expr::parse(input)?)
- } else {
- None
- };
- Ok(Self { path, value })
- }
-}
-
-/// Given a struct field, this finds all arguments of the form `#[path(key)]`
-/// and `#[path(key = value)]`. Multiple arguments may be specified in a single
-/// annotation, e.g. `#[foo(bar, baz = true)]`.
-pub fn attribute_arguments(
- attributes: &[Attribute],
- path: &str,
-) -> syn::Result> {
- let mut attr_args = vec![];
-
- for attr in attributes.iter().filter(|attr| attr.path().is_ident(path)) {
- let args =
- attr.parse_args_with(Punctuated::::parse_terminated)?;
- attr_args.extend(args);
- }
-
- Ok(attr_args)
-}
-
-pub enum SerdeDefault {
- Default(Type),
- Path(ExprPath),
-}
-
-impl SerdeDefault {
- pub fn value(&self) -> TokenStream {
- match self {
- Self::Default(ty) => quote! {
- <#ty as Default>::default()
- },
- Self::Path(path) => quote! {
- #path()
- },
- }
- }
-}
-
-/// Find `#[serde(default)]` or `#[serde(default = "bla")]`.
-pub fn serde_default(field: &Field) -> syn::Result