From 458433ef3474a52d3c0343b9515fe5dbed152c4a Mon Sep 17 00:00:00 2001 From: Bojin Li Date: Thu, 5 Dec 2024 02:40:58 +0800 Subject: [PATCH] Bump version to v0.14 (#8) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add Sixel support Fixes #910 * Implementation of the XTSMGRAPHICS sequence. * Don't clear cells after the right side of the graphic. * Don’t erase text behind a sixel image; the image might be transparent We still add a reference to the graphic in the first cell of every line under the image, but we don’t erase any of the text in any of the cells. * remove an unncessary variable from insert_graphic * Avoid unnecessary clone when set graphic data. * Define MAX_GRAPHIC_DIMENSIONS as a 2-elements array. * support DECSET/DECRST (CSI ? Pm h) to change where the cursor ends up after printing a sixel image. The default is for the cursor to be moved to the first column of the line after the image. When we receive CSI ? 8452 h, we will instead leave the cursor on the last line of the image, on the next column past the end of the image. * put the TermMode back to just u32; I had miscounted the bits * move_forward takes a relative column count, not an absolute column number * Interprets mode 80 as Sixel Display Mode. This is reverse of the *sixel scrolling* option, which should match the actual behaviour of DEC terminals. For reference: https://github.com/alacritty/alacritty/pull/4763#issuecomment-925374707 * Fill all cells under a graphic with the template. With the template we can create hyperlinks attached to the graphic. To avoid reflow issues when a row is shrank, wrapped rows that only contain graphic cells are discarded. With this approach we loss some info, like the hyperlink, but the image is always properly positioned in the grid. * Allow hue values up to 360 in the Sixel parser. * Allow replacing part of a graphic with text. When text is added to a cell with a reference to a graphic, an operation is sent to the OpenGL thread to replace a subregion of the cell with a transparent area. If the OpenGL driver supports the GL_ARB_clear_texture extension, the region is updated with glClearTexSubImage. If the extension is not available, the texture is updated with glTexSubImage2D. * Highlight graphics to show hints. Similar to the underline line rendered when the cursor is over an hyperlink, for graphics we now render a border around the graphic. * Allow overlapping graphics. If a graphic is added over another one, the implementation now checks if new graphic has transparent pixels in every cell. If so, the graphic is appended to the cell, instead of replacing the previous one. SmallVec is used to prevent heap allocation when the cell only contains a single graphic. This should be the most common scenario. The GPU will store up to 100 textures. If another texture is added when there are 100, the oldest one is deleted. * Optimize graphics replacement. A simple optimization for inserting graphics is to detect when a new graphic is replacing completely an existing one. If both graphics have the same size, and the new one is opaque, we can assume that the previous graphic will not be displayed anymore, so it is not considered when update the graphics list in a single cell. This commit also adds serde implementation for GraphicsCell. This was used to debug the new logic. * Fix clippy warnings. * Use hls_to_rgb implementation from libsixel. * Changes in sixel module to be compatible with oldstable. - Reimplement abs_diff(). - Use positional arguments to format the error message in assert_color!(). * Initialize cell dimensions when create a Graphics instance. This fixes a bug that crashes the terminal when a graphic is added before resizing the window. * Support GLES2 Renderer in sixel * Set graphics limit per cell. The limit per grid is increased to `1000`, and a new limit per cell is added, set to `20`. * Add Eq derive to ClearSubregion. Suggested by clippy. * CSI XTSMGRAPHICS Pi=2, Pa=1 should return dimensions that fit in text area * Remove entry about Sixel support in the changelog. * Update damage when a graphics is inserted. * Apply rustfmt to term/mod.rs. * Apply rustfmt and clippy to the current branch. * Serialize/Deserialize only if the `serde` feature is set. * Apply clippy suggestions. * Include Sixel support in Device Attributes response. The response for `\e[c` (Send Device Attributes) now returns level 2 with the Sixel extension. The other extensions are 6 (Selectively Erasable Characters) and 22 (Color Text). The values are documented in page 04-19 of DEC-STD-070. * Upgrade vte fork. With `$ cargo update vte`. * Use the published vte-graphics crate, instead of a Git repository. * Fix sixels position when padding>0 * Bump MSRV to 1.74.0 * Bump dependencies Update winit and clap to latest versions. * Document options which are not working everywhere yet This includes `window.position` and `window.resize_increments`. * Restart config monitor on import change This patch checks the hash of the import paths on every config change and restarts the config monitor whenever the current monitor's hash diverges from the updated config's list of imports. Closes #7981. * Unify string formatting * Fix description in alacritty-bindings(5) Man pages use the man page name as the first word in description. This also aligns with other man pages we have. * Make `ConPty` creation fallible * Remove duplicate clip-path from logo * Update checkout CI action * Improve TermMode bitflags initialization * Make alacritty(1) config paths resemble alacritty(5) This also fixes the escaping in alacritty(5) page. * Ignore cursor color request with default colors Currently when the cursor colors are requested for the default cursor color, Alacritty always responds with #000000. Since this is most likely incorrect, this response is misleading. Realistically there's very little reason why any application would need to know the color of the (often dynamically changing) default cursor. So instead of always reporting an incorrect black value, this patch just stops reporting values unless the cursor color was explicitly changed. Closes #8169. * Fix fullwidth semantic escape characters Semantic escape characters occupying two two grid cells were always skipped over, making it impossible to have functional fullwidth characters as part of semantic escape characters. This patch fixes this by only skipping over fullwidth spacer cells, rather than skipping those cells entirely. Closes #8188. * Fix app icon in alt+tab view on Windows * Move root config fields to `[general]` section Some users struggle with TOML, since root options must always be at the top of the file, since they're otherwise associated with the last table. To avoid misunderstandings, all root-level fields have been removed. A new `general` section was added to allow housing configuration options that do not fit into any more specific groups. Closes #7906. * Add migration support for TOML config changes This patch allows running `alacritty migrate` to automatically apply configuration changes made to the TOML format, like moving `ipc_socket` to `general.ipc_socket`. This should reduce the friction of moving around individual options significantly, while also persisting the format of the existing TOML file thanks to `toml_edit`. The YAML migration has been simplified significantly to only switch the format of the file from YAML to TOML. The new TOML features are used for everything else. * Restructure message bar log message The first line is not really useful for the user, so move it to the bottom. * Remove startup notify variables only for shell This will prevent issues when `setup_env` from `alacritty_terminal` will remove potentially useful variables for users of the library. Fixes #8202. * Remove unused `Clone` requirements * Fix highlight invalidation on grid scroll This fixes an issue where hints highlighted by vi or mouse cursor would produce an underline on the incorrect line since the highlights only store the initial match boundaries without accounting for new content scrolling the terminal. To accurately invalidate the hint highlights, we use existing damage information of the current frame. The existing logic to damage hints for the next frame to account for removal has been changed, since the hints would otherwise be cleared immediately. Instead we now mark the terminal as fully damaged for the upcoming frame whenever the hints are cleared. Closes #7737. * Change ctrl+shift+u to ctrl+shift+o Avoid collisions with IMEs by using ctrl+shift+o. ctrl+shift+u is bound to open unicode input in a lot of IMEs by default meaning that users won't ever see the url hints UI. * Add unicode 16 support This fixes issues in width calculation for symbols added in Unicode version 16. Since the upstream unicode-width crate has not been updated yet, this makes use of the temporary unicode-width-16 version to support Unicode 16 with Alacritty 0.14.0. * Fix panic on missing general config section Fixes #8230. * Alacritty version 0.14.0-rc1 * Implement multi-char cursor highlight Use `end` of the cursor to draw a `HollowBlock` from `start` to `end`. When cursor covers only a single character, use `Beam` cursor instead of `HollowBlock`. Fixes #8238. Fixes #7849. * Add IME support to inline search This changes the behavior of inline search from only accepting direct key inputs, to also accepting IME and paste. The additional characters are still being discarded, matching the existing behavior. This also fixes an issue where inline search wouldn't work for characters requiring modifiers, since the modifier press was interpreted as the search target instead. Closes #8208. * Add headless mode This patch adds a daemon mode to Alacritty which allows starting the Alacritty process without spawning an initial window. While this does not provide any significant advantage over the existing behavior of always spawning a window, it does integrate nicer with some setups and is a pretty trivial addition. * Remove dbg! in migration command * Alacritty version 0.14.0-rc2 * Fix pipe FD leak on X11 The pipe was not using O_CLOEXEC, so it was leaked into the child. Fixes #8249. * Revert "Add unicode 16 support" This reverts commit 5dca7a85e7d8e98f8e770c17af8efb442c2277d0. * Do not pull serde without serde feature alacritty_terminal was pulling `serde` via vte even though serde feature was disabled. * Alacritty version 0.14.0 * Use the GitHub CLI client to upload release assets. The binary for Linux is also added to the release. The `contents: write` permission is needed to create releases and upload the assets. * Clear compiler warnings * Add missed token for asset upload script --------- Co-authored-by: Ayose Co-authored-by: Daniel Brooks Co-authored-by: kumattau Co-authored-by: Manuel de Prada <6536835+manueldeprada@users.noreply.github.com> Co-authored-by: Kirill Chibisov Co-authored-by: Christian Duerr Co-authored-by: Hamir Mahal Co-authored-by: 张小白 <364772080@qq.com> Co-authored-by: philomathic_life <15947783+zacknewman@users.noreply.github.com> Co-authored-by: Dimitri Sabadie Co-authored-by: Neil Stewart <40719351+madcdevelop@users.noreply.github.com> Co-authored-by: Nathan Lilienthal Co-authored-by: YizhePKU --- .github/workflows/ci.yml | 4 +- .github/workflows/release.yml | 14 +- .github/workflows/upload_asset.sh | 87 +-- CHANGELOG.md | 21 +- Cargo.lock | 603 ++++++++++-------- alacritty/Cargo.toml | 16 +- alacritty/src/cli.rs | 16 +- alacritty/src/config/bindings.rs | 11 +- alacritty/src/config/general.rs | 39 ++ alacritty/src/config/mod.rs | 50 +- alacritty/src/config/monitor.rs | 37 +- alacritty/src/config/terminal.rs | 6 +- alacritty/src/config/ui_config.rs | 131 ++-- alacritty/src/daemon.rs | 2 +- alacritty/src/display/content.rs | 31 +- alacritty/src/display/cursor.rs | 4 +- alacritty/src/display/damage.rs | 9 + alacritty/src/display/hint.rs | 2 +- alacritty/src/display/mod.rs | 248 +++---- alacritty/src/display/window.rs | 7 +- alacritty/src/event.rs | 115 +++- alacritty/src/input/keyboard.rs | 17 +- alacritty/src/input/mod.rs | 35 +- alacritty/src/ipc.rs | 11 +- alacritty/src/logging.rs | 8 +- alacritty/src/main.rs | 16 +- alacritty/src/migrate.rs | 267 -------- alacritty/src/migrate/mod.rs | 326 ++++++++++ alacritty/src/migrate/yaml.rs | 87 +++ alacritty/src/renderer/mod.rs | 8 +- alacritty/src/renderer/shader.rs | 6 +- alacritty/src/string.rs | 1 + alacritty/src/window_context.rs | 17 +- alacritty/windows/wix/alacritty.wxs | 2 +- alacritty_config/Cargo.toml | 6 +- alacritty_config_derive/Cargo.toml | 6 +- .../src/config_deserialize/de_struct.rs | 1 + alacritty_config_derive/src/serde_replace.rs | 4 +- alacritty_config_derive/tests/config.rs | 19 +- alacritty_terminal/CHANGELOG.md | 14 +- alacritty_terminal/Cargo.toml | 4 +- alacritty_terminal/src/grid/mod.rs | 6 +- alacritty_terminal/src/grid/resize.rs | 2 +- alacritty_terminal/src/grid/row.rs | 2 +- alacritty_terminal/src/grid/storage.rs | 6 +- alacritty_terminal/src/term/cell.rs | 2 - alacritty_terminal/src/term/mod.rs | 48 +- alacritty_terminal/src/term/search.rs | 29 +- alacritty_terminal/src/tty/mod.rs | 11 +- alacritty_terminal/src/tty/unix.rs | 4 + alacritty_terminal/src/tty/windows/conpty.rs | 25 +- alacritty_terminal/src/tty/windows/mod.rs | 3 +- extra/completions/_alacritty | 125 ++-- extra/completions/alacritty.bash | 96 ++- extra/completions/alacritty.fish | 121 ++-- extra/logo/alacritty-term.svg | 3 +- extra/man/alacritty-bindings.5.scd | 2 +- extra/man/alacritty.1.scd | 12 +- extra/man/alacritty.5.scd | 48 +- extra/osx/Alacritty.app/Contents/Info.plist | 2 +- 60 files changed, 1632 insertions(+), 1223 deletions(-) create mode 100644 alacritty/src/config/general.rs delete mode 100644 alacritty/src/migrate.rs create mode 100644 alacritty/src/migrate/mod.rs create mode 100644 alacritty/src/migrate/yaml.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fe8dd2cd0b..c65e7f82ee9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,7 +14,7 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Stable run: cargo test - name: Stable (no default features) @@ -30,7 +30,7 @@ jobs: check-macos-x86_64: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install target run: rustup update && rustup target add x86_64-apple-darwin - name: Build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 8c5d756ea44..6efa44221ad 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,9 @@ on: push: tags: ["v[0-9]+.[0-9]+.[0-9]+*"] +permissions: + contents: write + env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} CARGO_TERM_COLOR: always @@ -98,7 +101,7 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Test run: cargo test --release - name: Build @@ -124,13 +127,15 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install dependencies run: | sudo apt-get install cmake pkg-config libfreetype6-dev libfontconfig1-dev \ libxcb-xfixes0-dev libxkbcommon-dev python3 scdoc - name: Test run: cargo test --release + - name: Build + run: cargo build --release - name: Generate manpages run: | scdoc < extra/man/alacritty.1.scd | gzip -c > "./alacritty.1.gz" @@ -139,7 +144,12 @@ jobs: scdoc < extra/man/alacritty-bindings.5.scd | gzip -c > "./alacritty-bindings.5.gz" - name: Upload Assets run: | + binpath="alacritty-linux-$(uname -m).gz" + gzip -9 --stdout target/release/alacritty > "$binpath" + mv ./extra/logo/alacritty-term.svg ./Alacritty.svg + + ./.github/workflows/upload_asset.sh "$binpath" $GITHUB_TOKEN ./.github/workflows/upload_asset.sh ./Alacritty.svg $GITHUB_TOKEN ./.github/workflows/upload_asset.sh ./alacritty.1.gz $GITHUB_TOKEN ./.github/workflows/upload_asset.sh ./alacritty-msg.1.gz $GITHUB_TOKEN diff --git a/.github/workflows/upload_asset.sh b/.github/workflows/upload_asset.sh index 5f57d934f7d..1503cb161ca 100755 --- a/.github/workflows/upload_asset.sh +++ b/.github/workflows/upload_asset.sh @@ -8,89 +8,12 @@ fi repo="xxxbrian/alacritty" file_path=$1 -bearer=$2 -echo "Starting asset upload from $file_path to $repo." +tag=$(git describe --tags --abbrev=0) -# Get the release for this tag. -tag="$(git describe --tags --abbrev=0)" - -# Make sure the git tag could be determined. -if [ -z "$tag" ]; then - printf "\e[31mError: Unable to find git tag\e[0m\n" - exit 1 -fi - -echo "Git tag: $tag" - -# Get the upload URL for the current tag. -# -# Since this might be a draft release, we can't just use the /releases/tags/:tag -# endpoint which only shows published releases. -echo "Checking for existing release..." -upload_url=$(\ - curl \ - --http1.1 \ - -H "Authorization: Bearer $bearer" \ - "https://api.github.com/repos/$repo/releases" \ - 2> /dev/null \ - | grep -E "(upload_url|tag_name)" \ - | paste - - \ - | grep -e "tag_name\": \"$tag\"" \ - | head -n 1 \ - | sed 's/.*\(https.*assets\).*/\1/' \ -) - -# Create a new release if we didn't find one for this tag. -if [ -z "$upload_url" ]; then - echo "No release found." - echo "Creating new release..." - - # Create new release. - response=$( - curl -f \ - --http1.1 \ - -X POST \ - -H "Authorization: Bearer $bearer" \ - -d "{\"tag_name\":\"$tag\",\"draft\":true}" \ - "https://api.github.com/repos/$repo/releases" \ - 2> /dev/null\ - ) - - # Abort if the release could not be created. - if [ $? -ne 0 ]; then - printf "\e[31mError: Unable to create new release.\e[0m\n" - exit 1; - fi - - # Extract upload URL from new release. - upload_url=$(\ - echo "$response" \ - | grep "upload_url" \ - | sed 's/.*: "\(.*\){.*/\1/' \ - ) +if ! gh release view "$tag" +then + gh release create --draft "$tag" fi -# Propagate error if no URL for asset upload could be found. -if [ -z "$upload_url" ]; then - printf "\e[31mError: Unable to find release upload url.\e[0m\n" - exit 2 -fi - -# Upload the file to the tag's release. -file_name=${file_path##*/} -echo "Uploading asset $file_name to $upload_url..." -curl -f \ - --http1.1 \ - -X POST \ - -H "Authorization: Bearer $bearer" \ - -H "Content-Type: application/octet-stream" \ - --data-binary @"$file_path" \ - "$upload_url?name=$file_name" \ - &> /dev/null \ -|| { \ - printf "\e[31mError: Unable to upload asset.\e[0m\n" \ - && exit 3; \ -} - -printf "\e[32mSuccess\e[0m\n" +gh release upload "$tag" "$file_path" diff --git a/CHANGELOG.md b/CHANGELOG.md index 8442355ae5c..2b3d2b46b97 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,17 +8,28 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). Notable changes to the `alacritty_terminal` crate are documented in its [CHANGELOG](./alacritty_terminal/CHANGELOG.md). -## 0.14.0-dev +## 0.14.0 + +### Packaging + +- Minimum Rust version has been bumped to 1.74.0 ### Added - Support relative path imports from config files +- `alacritty migrate` support for TOML configuration changes +- Headless mode using `alacritty --daemon` ### Changed - Pressing `Alt` with unicode input will now add `ESC` like for ASCII input - Decorations use opaque style and system window background on macOS - No longer source `~/.zshenv` on macOS +- Moved config options `import`, `working_directory`, `live_config_reload`, and `ipc_socket` + to the new `general` section +- Moved config option `shell` to `terminal.shell` +- `ctrl+shift+u` binding to open links to `ctrl+shift+o` to avoid collisions with IMEs +- Use `Beam` cursor for single char cursor inside the IME preview ### Fixed @@ -32,6 +43,14 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Config emitting errors for nonexistent import paths - Kitty keyboard protocol reporting shifted key codes - Broken search with words broken across line boundary on the first character +- Config import changes not being live reloaded +- Cursor color requests with default cursor colors +- Fullwidth semantic escape characters +- Windows app icon now displays properly in old alt+tab on Windows +- Alacritty not being properly activated with startup notify +- Invalid URL highlights after terminal scrolling +- Hollow block cursor not spanning multiple chars being edited inside the IME preview +- Vi inline search only working for direct key input without modifiers ## 0.13.2 diff --git a/Cargo.lock b/Cargo.lock index 91e64d06f85..4c79f0e7761 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,22 +23,22 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "alacritty" -version = "0.14.0-dev" +version = "0.14.0" dependencies = [ "ahash", "alacritty_config", "alacritty_config_derive", "alacritty_terminal", - "bitflags 2.5.0", + "bitflags 2.6.0", "clap", "clap_complete", "cocoa", @@ -60,7 +60,9 @@ dependencies = [ "serde_json", "serde_yaml", "smallvec", + "tempfile", "toml", + "toml_edit 0.22.21", "unicode-width", "windows-sys 0.52.0", "winit", @@ -69,7 +71,7 @@ dependencies = [ [[package]] name = "alacritty_config" -version = "0.2.1-dev" +version = "0.2.2" dependencies = [ "alacritty_config_derive", "log", @@ -79,7 +81,7 @@ dependencies = [ [[package]] name = "alacritty_config_derive" -version = "0.2.3-dev" +version = "0.2.4" dependencies = [ "alacritty_config", "log", @@ -92,10 +94,10 @@ dependencies = [ [[package]] name = "alacritty_terminal" -version = "0.24.1-dev" +version = "0.24.1" dependencies = [ "base64", - "bitflags 2.5.0", + "bitflags 2.6.0", "home", "libc", "log", @@ -121,7 +123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.5.0", + "bitflags 2.6.0", "cc", "cesu8", "jni", @@ -143,50 +145,51 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "anstream" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" +checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" dependencies = [ "anstyle", "anstyle-parse", "anstyle-query", "anstyle-wincon", "colorchoice", + "is_terminal_polyfill", "utf8parse", ] [[package]] name = "anstyle" -version = "1.0.6" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" +checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -215,15 +218,15 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.1.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "base64" -version = "0.22.0" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" @@ -233,9 +236,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -257,29 +260,29 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.15.4" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.15.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "bytes" -version = "1.5.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "calloop" -version = "0.12.4" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "log", "polling", "rustix", @@ -289,9 +292,9 @@ dependencies = [ [[package]] name = "calloop-wayland-source" -version = "0.2.0" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0ea9b9476c7fad82841a8dbb380e2eae480c21910feba80725b46931ed8f02" +checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" dependencies = [ "calloop", "rustix", @@ -301,9 +304,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.90" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" +checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" dependencies = [ "jobserver", "libc", @@ -338,9 +341,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.4.11" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", "clap_derive", @@ -348,9 +351,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.11" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstream", "anstyle", @@ -360,18 +363,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.4" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" +checksum = "5b4be9c4c4b1f30b78d8a750e0822b6a6102d97e62061c583a6c1dea2dfb33ae" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck", "proc-macro2", @@ -381,9 +384,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" [[package]] name = "clipboard-win" @@ -427,15 +430,15 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" [[package]] name = "combine" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", "memchr", @@ -443,9 +446,9 @@ dependencies = [ [[package]] name = "concurrent-queue" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d16048cd947b08fa32c24458a22f5dc5e835264f689f4f5653210c69fd107363" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" dependencies = [ "crossbeam-utils", ] @@ -482,9 +485,9 @@ checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" [[package]] name = "core-graphics" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "970a29baf4110c26fedbc7f82107d42c23f7e88e404c4577ed73fe99ff85a212" +checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", "core-foundation", @@ -518,27 +521,27 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.4.0" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.12" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[package]] name = "crossfont" @@ -620,9 +623,9 @@ dependencies = [ [[package]] name = "downcast-rs" -version = "1.2.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" [[package]] name = "dpi" @@ -669,19 +672,19 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "fastrand" -version = "2.0.1" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "fdeflate" @@ -694,21 +697,21 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "redox_syscall 0.4.1", + "windows-sys 0.52.0", ] [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" dependencies = [ "crc32fast", "miniz_oxide", @@ -747,7 +750,7 @@ version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5442dee36ca09604133580dc0553780e867936bb3cbef3275859e889026d2b17" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "freetype-sys", "libc", ] @@ -790,9 +793,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.12" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -816,7 +819,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2491aa3090f682ddd920b184491844440fdd14379c7eef8f5bc10ef7fb3242fd" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg_aliases", "cgl", "core-foundation", @@ -866,30 +869,36 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "heck" -version = "0.4.1" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc" [[package]] name = "home" -version = "0.5.5" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "indexmap" -version = "2.2.5" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -915,11 +924,17 @@ dependencies = [ "libc", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" + [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" [[package]] name = "jni" @@ -945,9 +960,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.28" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" +checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" dependencies = [ "libc", ] @@ -995,59 +1010,58 @@ checksum = "10257499f089cd156ad82d0a9cd57d9501fa2c989068992a97eb3c27836f206b" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.153" +version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" +checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] name = "libredox" -version = "0.0.1" +version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", "redox_syscall 0.4.1", ] [[package]] name = "libredox" -version = "0.0.2" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "libc", - "redox_syscall 0.4.1", ] [[package]] name = "linux-raw-sys" -version = "0.4.13" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "lock_api" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" dependencies = [ "autocfg", "scopeguard", @@ -1055,9 +1069,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" dependencies = [ "serde", ] @@ -1073,9 +1087,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.1" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" @@ -1097,9 +1111,9 @@ dependencies = [ [[package]] name = "miniz_oxide" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "simd-adler32", @@ -1132,7 +1146,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "jni-sys", "log", "ndk-sys", @@ -1162,7 +1176,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -1238,7 +1252,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "libc", "objc2", @@ -1254,7 +1268,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "objc2", "objc2-core-location", @@ -1278,7 +1292,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "objc2", "objc2-foundation", @@ -1320,7 +1334,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "dispatch", "libc", @@ -1345,7 +1359,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "objc2", "objc2-foundation", @@ -1357,7 +1371,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "objc2", "objc2-foundation", @@ -1380,7 +1394,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "objc2", "objc2-cloud-kit", @@ -1412,7 +1426,7 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "objc2", "objc2-core-location", @@ -1451,9 +1465,9 @@ dependencies = [ [[package]] name = "parking_lot" -version = "0.12.1" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ "lock_api", "parking_lot_core", @@ -1461,15 +1475,15 @@ dependencies = [ [[package]] name = "parking_lot_core" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -1500,15 +1514,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" dependencies = [ "atomic-waker", "fastrand", @@ -1536,16 +1550,17 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.0" +version = "3.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi", "pin-project-lite", "rustix", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1559,27 +1574,27 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.79" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.34.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "6f24d770aeca0eacb81ac29dfbc55ebcc09312fdd1f8bbecdc7e4a84e000e3b4" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.35" +version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] @@ -1592,38 +1607,38 @@ checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.4.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" dependencies = [ "getrandom", - "libredox 0.0.1", + "libredox 0.1.3", "thiserror", ] [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", @@ -1632,9 +1647,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "rustc_version" @@ -1647,16 +1662,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.25" +version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "itoa", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -1672,9 +1687,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.17" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -1699,9 +1714,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.9.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de61fa7334ee8ee1f5c3c58dcc414fb9361e7e8f5bff9d45f4d69eeb89a7169" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" dependencies = [ "crossfont", "log", @@ -1711,24 +1726,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.22" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" +checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.197" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.197" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -1737,9 +1752,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.114" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "itoa", "ryu", @@ -1748,18 +1763,18 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] [[package]] name = "serde_yaml" -version = "0.9.33" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ "indexmap", "itoa", @@ -1780,9 +1795,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.1" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" dependencies = [ "libc", ] @@ -1804,20 +1819,20 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.13.1" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" dependencies = [ "serde", ] [[package]] name = "smithay-client-toolkit" -version = "0.18.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "calloop", "calloop-wayland-source", "cursor-icon", @@ -1838,9 +1853,9 @@ dependencies = [ [[package]] name = "smithay-clipboard" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c091e7354ea8059d6ad99eace06dd13ddeedbb0ac72d40a9a6e7ff790525882d" +checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846" dependencies = [ "libc", "smithay-client-toolkit", @@ -1849,9 +1864,9 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ "serde", ] @@ -1864,35 +1879,48 @@ checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" [[package]] name = "strsim" -version = "0.10.0" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.53" +version = "2.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" +checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +dependencies = [ + "cfg-if", + "fastrand", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "thiserror" -version = "1.0.58" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.58" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" dependencies = [ "proc-macro2", "quote", @@ -1926,21 +1954,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.11" +version = "0.8.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" +checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.7", + "toml_edit 0.22.21", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -1958,15 +1986,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.7" +version = "0.22.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" +checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.18", ] [[package]] @@ -1999,9 +2027,9 @@ checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unsafe-libyaml" @@ -2011,9 +2039,9 @@ checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" @@ -2047,7 +2075,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2864755f49461b8296184ac43e06516a4bc47dab4d4d06396b8c852f3e7c1593" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cursor-icon", "log", "serde", @@ -2057,9 +2085,9 @@ dependencies = [ [[package]] name = "vte_generate_state_changes" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d257817081c7dffcdbab24b9e62d2def62e2ff7d00b1c20062551e6cccc145ff" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" dependencies = [ "proc-macro2", "quote", @@ -2149,9 +2177,9 @@ checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wayland-backend" -version = "0.3.3" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40" +checksum = "f90e11ce2ca99c97b940ee83edbae9da2d56a08f9ea8158550fd77fa31722993" dependencies = [ "cc", "downcast-rs", @@ -2163,11 +2191,11 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.2" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" +checksum = "7e321577a0a165911bdcfb39cf029302479d7527b517ee58ab0f6ad09edf0943" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "rustix", "wayland-backend", "wayland-scanner", @@ -2179,16 +2207,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.1" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba" +checksum = "6ef9489a8df197ebf3a8ce8a7a7f0a2320035c3743f3c1bd0bdbccf07ce64f95" dependencies = [ "rustix", "wayland-client", @@ -2197,11 +2225,11 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.31.2" +version = "0.32.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +checksum = "62989625a776e827cc0f15d41444a3cea5205b963c3a25be48ae1b52d6b4daaa" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -2209,11 +2237,11 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +checksum = "f79f2d57c7fcc6ab4d602adba364bf59a5c24de57bd194486bf9b8360e06bfc4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2222,11 +2250,11 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.2.0" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +checksum = "fd993de54a40a40fbe5601d9f1fbcaef0aebcc5fda447d7dc8f6dcbaae4f8953" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2235,9 +2263,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.1" +version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283" +checksum = "d7b56f89937f1cf2ee1f1259cf2936a17a1f45d8f0aa1019fae6d470d304cfa6" dependencies = [ "proc-macro2", "quick-xml", @@ -2246,9 +2274,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.1" +version = "0.31.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" +checksum = "43676fe2daf68754ecf1d72026e4e6c15483198b5d24e888b74d3f22f887a148" dependencies = [ "dlib", "log", @@ -2294,11 +2322,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" dependencies = [ - "winapi", + "windows-sys 0.52.0", ] [[package]] @@ -2331,7 +2359,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets 0.52.6", ] [[package]] @@ -2366,18 +2403,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -2394,9 +2431,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -2412,9 +2449,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -2430,15 +2467,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -2454,9 +2491,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -2472,9 +2509,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -2490,9 +2527,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -2508,20 +2545,20 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.30.3" +version = "0.30.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f45a7b7e2de6af35448d7718dab6d95acec466eb3bb7a56f4d31d1af754004" +checksum = "4225ddd8ab67b8b59a2fee4b34889ebf13c0460c1c3fa297c58e21eb87801b33" dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.5.0", + "bitflags 2.6.0", "block2", "bytemuck", "calloop", @@ -2576,9 +2613,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -2604,9 +2641,9 @@ dependencies = [ [[package]] name = "x11-clipboard" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98785a09322d7446e28a13203d2cae1059a0dd3dfb32cb06d0a225f023d8286" +checksum = "662d74b3d77e396b8e5beb00b9cad6a9eccf40b2ef68cc858784b14c41d535a3" dependencies = [ "libc", "x11rb", @@ -2625,9 +2662,9 @@ dependencies = [ [[package]] name = "x11rb" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" dependencies = [ "as-raw-xcb-connection", "gethostname", @@ -2640,9 +2677,9 @@ dependencies = [ [[package]] name = "x11rb-protocol" -version = "0.13.0" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e63e71c4b8bd9ffec2c963173a4dc4cbde9ee96961d4fcb4429db9929b606c34" +checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xcursor" @@ -2662,7 +2699,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "dlib", "log", "once_cell", @@ -2671,15 +2708,15 @@ dependencies = [ [[package]] name = "xkeysym" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "054a8e68b76250b253f671d1268cb7f1ae089ec35e195b2efb2a4e9a836d0621" +checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.19" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" [[package]] name = "yeslogic-fontconfig-sys" @@ -2695,18 +2732,18 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.32" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 062a443d85d..453ac70c7ce 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alacritty" -version = "0.14.0-dev" +version = "0.14.0" authors = ["Christian Duerr ", "Joe Wilm "] license = "Apache-2.0" description = "A fast, cross-platform, OpenGL terminal emulator" @@ -8,19 +8,19 @@ readme = "README.md" homepage = "https://alacritty.org" repository = "https://github.com/alacritty/alacritty" edition = "2021" -rust-version = "1.70.0" +rust-version = "1.74.0" [dependencies.alacritty_terminal] path = "../alacritty_terminal" -version = "0.24.1-dev" +version = "0.24.1" [dependencies.alacritty_config_derive] path = "../alacritty_config_derive" -version = "0.2.3-dev" +version = "0.2.4" [dependencies.alacritty_config] path = "../alacritty_config" -version = "0.2.1-dev" +version = "0.2.2" [dependencies] ahash = { version = "0.8.6", features = ["no-rng"] } @@ -35,13 +35,15 @@ log = { version = "0.4", features = ["std", "serde"] } memoffset = "0.9.0" notify = "6.1.1" parking_lot = "0.12.0" -serde = { version = "1", features = ["derive"] } serde_json = "1" +serde = { version = "1", features = ["derive"] } serde_yaml = "0.9.25" smallvec = { version = "1.13.1", features = ["serde"] } +tempfile = "3.12.0" toml = "0.8.2" +toml_edit = "0.22.21" unicode-width = "0.1" -winit = { version = "0.30.3", default-features = false, features = ["rwh_06", "serde"] } +winit = { version = "0.30.4", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] gl_generator = "0.14.0" diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index e7f2d3efd7e..bb0a24f4bd7 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -26,7 +26,7 @@ pub struct Options { pub print_events: bool, /// Generates ref test. - #[clap(long)] + #[clap(long, conflicts_with("daemon"))] pub ref_test: bool, /// X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix). @@ -62,6 +62,10 @@ pub struct Options { #[clap(short, conflicts_with("quiet"), action = ArgAction::Count)] verbose: u8, + /// Do not spawn an initial window. + #[clap(long)] + pub daemon: bool, + /// CLI options for config overrides. #[clap(skip)] pub config_options: ParsedOptions, @@ -88,8 +92,8 @@ impl Options { /// Override configuration file with options from the CLI. pub fn override_config(&mut self, config: &mut UiConfig) { #[cfg(unix)] - { - config.ipc_socket |= self.socket.is_some(); + if self.socket.is_some() { + config.ipc_socket = Some(true); } config.window.embed = self.embed.as_ref().and_then(|embed| parse_hex_or_decimal(embed)); @@ -216,10 +220,10 @@ impl WindowIdentity { /// Override the [`WindowIdentity`]'s fields with the [`WindowOptions`]. pub fn override_identity_config(&self, identity: &mut Identity) { if let Some(title) = &self.title { - identity.title = title.clone(); + identity.title.clone_from(title); } if let Some(class) = &self.class { - identity.class = class.clone(); + identity.class.clone_from(class); } } } @@ -524,7 +528,7 @@ mod tests { let generated = String::from_utf8_lossy(&generated); let mut completion = String::new(); - let mut file = File::open(format!("../extra/completions/{}", file)).unwrap(); + let mut file = File::open(format!("../extra/completions/{file}")).unwrap(); file.read_to_string(&mut completion).unwrap(); assert_eq!(generated, completion); diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs index 62ca03a0b7f..dfe31853bc0 100644 --- a/alacritty/src/config/bindings.rs +++ b/alacritty/src/config/bindings.rs @@ -287,7 +287,7 @@ impl Display for Action { Action::ViMotion(motion) => motion.fmt(f), Action::Vi(action) => action.fmt(f), Action::Mouse(action) => action.fmt(f), - _ => write!(f, "{:?}", self), + _ => write!(f, "{self:?}"), } } } @@ -1024,8 +1024,7 @@ impl<'a> Deserialize<'a> for RawBinding { }, Err(_) => { return Err(::custom(format!( - "Invalid key binding, scancode is too big: {}", - scancode + "Invalid key binding, scancode is too big: {scancode}" ))); }, }, @@ -1080,8 +1079,7 @@ impl<'a> Deserialize<'a> for RawBinding { _ => return Err(err), }; return Err(V::Error::custom(format!( - "unknown keyboard action `{}`", - value + "unknown keyboard action `{value}`" ))); }, } @@ -1122,8 +1120,7 @@ impl<'a> Deserialize<'a> for RawBinding { (Some(action @ Action::Mouse(_)), None, None) => { if mouse.is_none() { return Err(V::Error::custom(format!( - "action `{}` is only available for mouse bindings", - action, + "action `{action}` is only available for mouse bindings", ))); } action diff --git a/alacritty/src/config/general.rs b/alacritty/src/config/general.rs new file mode 100644 index 00000000000..ba559262bb7 --- /dev/null +++ b/alacritty/src/config/general.rs @@ -0,0 +1,39 @@ +//! Miscellaneous configuration options. + +use std::path::PathBuf; + +use alacritty_config_derive::ConfigDeserialize; + +/// General config section. +/// +/// This section is for fields which can not be easily categorized, +/// to avoid common TOML issues with root-level fields. +#[derive(ConfigDeserialize, Clone, PartialEq, Debug)] +pub struct General { + /// Configuration file imports. + /// + /// This is never read since the field is directly accessed through the config's + /// [`toml::Value`], but still present to prevent unused field warnings. + pub import: Vec, + + /// Shell startup directory. + pub working_directory: Option, + + /// Live config reload. + pub live_config_reload: bool, + + /// Offer IPC through a unix socket. + #[allow(unused)] + pub ipc_socket: bool, +} + +impl Default for General { + fn default() -> Self { + Self { + live_config_reload: true, + ipc_socket: true, + working_directory: Default::default(), + import: Default::default(), + } + } +} diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs index 488ef537769..ba9d674deb9 100644 --- a/alacritty/src/config/mod.rs +++ b/alacritty/src/config/mod.rs @@ -15,6 +15,7 @@ pub mod color; pub mod cursor; pub mod debug; pub mod font; +pub mod general; pub mod monitor; pub mod scrolling; pub mod selection; @@ -76,12 +77,12 @@ impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { Error::ReadingEnvHome(err) => { - write!(f, "Unable to read $HOME environment variable: {}", err) + write!(f, "Unable to read $HOME environment variable: {err}") }, - Error::Io(err) => write!(f, "Error reading config file: {}", err), - Error::Toml(err) => write!(f, "Config error: {}", err), - Error::TomlSe(err) => write!(f, "Yaml conversion error: {}", err), - Error::Yaml(err) => write!(f, "Config error: {}", err), + Error::Io(err) => write!(f, "Error reading config file: {err}"), + Error::Toml(err) => write!(f, "Config error: {err}"), + Error::TomlSe(err) => write!(f, "Yaml conversion error: {err}"), + Error::Yaml(err) => write!(f, "Config error: {err}"), } } } @@ -278,15 +279,15 @@ fn load_imports( merged } -// TODO: Merge back with `load_imports` once `alacritty migrate` is dropped. -// /// Get all import paths for a configuration. pub fn imports( config: &Value, base_path: &Path, recursion_limit: usize, ) -> StdResult>, String> { - let imports = match config.get("import") { + let imports = + config.get("import").or_else(|| config.get("general").and_then(|g| g.get("import"))); + let imports = match imports { Some(Value::Array(imports)) => imports, Some(_) => return Err("Invalid import type: expected a sequence".into()), None => return Ok(Vec::new()), @@ -300,7 +301,7 @@ pub fn imports( let mut import_paths = Vec::new(); for import in imports { - let mut path = match import { + let path = match import { Value::String(path) => PathBuf::from(path), _ => { import_paths.push(Err("Invalid import element type: expected path string".into())); @@ -308,23 +309,32 @@ pub fn imports( }, }; - // Resolve paths relative to user's home directory. - if let (Ok(stripped), Some(home_dir)) = (path.strip_prefix("~/"), home::home_dir()) { - path = home_dir.join(stripped); - } - - if path.is_relative() { - if let Some(base_path) = base_path.parent() { - path = base_path.join(path) - } - } + let normalized = normalize_import(base_path, path); - import_paths.push(Ok(path)); + import_paths.push(Ok(normalized)); } Ok(import_paths) } +/// Normalize import paths. +pub fn normalize_import(base_config_path: &Path, import_path: impl Into) -> PathBuf { + let mut import_path = import_path.into(); + + // Resolve paths relative to user's home directory. + if let (Ok(stripped), Some(home_dir)) = (import_path.strip_prefix("~/"), home::home_dir()) { + import_path = home_dir.join(stripped); + } + + if import_path.is_relative() { + if let Some(base_config_dir) = base_config_path.parent() { + import_path = base_config_dir.join(import_path) + } + } + + import_path +} + /// Prune the nulls from the YAML to ensure TOML compatibility. fn prune_yaml_nulls(value: &mut serde_yaml::Value, warn_pruned: bool) { fn walk(value: &mut serde_yaml::Value, warn_pruned: bool) -> bool { diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs index 53cff1c90c2..3f73f120101 100644 --- a/alacritty/src/config/monitor.rs +++ b/alacritty/src/config/monitor.rs @@ -1,3 +1,5 @@ +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; use std::path::PathBuf; use std::sync::mpsc::{self, RecvTimeoutError, Sender}; use std::thread::JoinHandle; @@ -23,6 +25,7 @@ const FALLBACK_POLLING_TIMEOUT: Duration = Duration::from_secs(1); pub struct ConfigMonitor { thread: JoinHandle<()>, shutdown_tx: Sender>, + watched_hash: Option, } impl ConfigMonitor { @@ -32,6 +35,9 @@ impl ConfigMonitor { return None; } + // Calculate the hash for the unmodified list of paths. + let watched_hash = Self::hash_paths(&paths); + // Exclude char devices like `/dev/null`, sockets, and so on, by checking that file type is // a regular file. paths.retain(|path| { @@ -139,7 +145,7 @@ impl ConfigMonitor { } }); - Some(Self { thread: join_handle, shutdown_tx: tx }) + Some(Self { watched_hash, thread: join_handle, shutdown_tx: tx }) } /// Synchronously shut down the monitor. @@ -154,4 +160,33 @@ impl ConfigMonitor { warn!("config monitor shutdown failed: {err:?}"); } } + + /// Check if the config monitor needs to be restarted. + /// + /// This checks the supplied list of files against the monitored files to determine if a + /// restart is necessary. + pub fn needs_restart(&self, files: &[PathBuf]) -> bool { + Self::hash_paths(files).map_or(true, |hash| Some(hash) == self.watched_hash) + } + + /// Generate the hash for a list of paths. + fn hash_paths(files: &[PathBuf]) -> Option { + // Use file count limit to avoid allocations. + const MAX_PATHS: usize = 1024; + if files.len() > MAX_PATHS { + return None; + } + + // Sort files to avoid restart on order change. + let mut sorted_files = [None; MAX_PATHS]; + for (i, file) in files.iter().enumerate() { + sorted_files[i] = Some(file); + } + sorted_files.sort_unstable(); + + // Calculate hash for the paths, regardless of order. + let mut hasher = DefaultHasher::new(); + Hash::hash_slice(&sorted_files, &mut hasher); + Some(hasher.finish()) + } } diff --git a/alacritty/src/config/terminal.rs b/alacritty/src/config/terminal.rs index b41af5db640..d0c0d9da49d 100644 --- a/alacritty/src/config/terminal.rs +++ b/alacritty/src/config/terminal.rs @@ -4,12 +4,14 @@ use toml::Value; use alacritty_config_derive::{ConfigDeserialize, SerdeReplace}; use alacritty_terminal::term::Osc52; -use crate::config::ui_config::StringVisitor; +use crate::config::ui_config::{Program, StringVisitor}; -#[derive(ConfigDeserialize, Default, Copy, Clone, Debug, PartialEq)] +#[derive(ConfigDeserialize, Default, Clone, Debug, PartialEq)] pub struct Terminal { /// OSC52 support mode. pub osc52: SerdeOsc52, + /// Path to a shell program to run on startup. + pub shell: Option, } #[derive(SerdeReplace, Default, Copy, Clone, Debug, PartialEq)] diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index c736517b026..04b577c88e3 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -26,7 +26,8 @@ use crate::config::color::Colors; use crate::config::cursor::Cursor; use crate::config::debug::Debug; use crate::config::font::Font; -use crate::config::mouse::{Mouse, MouseBindings}; +use crate::config::general::General; +use crate::config::mouse::Mouse; use crate::config::scrolling::Scrolling; use crate::config::selection::Selection; use crate::config::terminal::Terminal; @@ -38,8 +39,11 @@ use crate::config::LOG_TARGET_CONFIG; const URL_REGEX: &str = "(ipfs:|ipns:|magnet:|mailto:|gemini://|gopher://|https://|http://|news:|file:|git://|ssh:|ftp://)\ [^\u{0000}-\u{001F}\u{007F}-\u{009F}<>\"\\s{-}\\^⟨⟩`]+"; -#[derive(ConfigDeserialize, Clone, Debug, PartialEq)] +#[derive(ConfigDeserialize, Default, Clone, Debug, PartialEq)] pub struct UiConfig { + /// Miscellaneous configuration options. + pub general: General, + /// Extra environment variables. pub env: HashMap, @@ -64,14 +68,6 @@ pub struct UiConfig { /// Debug options. pub debug: Debug, - /// Send escape sequences using the alt key. - #[config(removed = "It's now always set to 'true'. If you're on macOS use \ - 'window.option_as_alt' to alter behavior of Option")] - pub alt_send_esc: Option, - - /// Live config reload. - pub live_config_reload: bool, - /// Bell configuration. pub bell: BellConfig, @@ -85,70 +81,35 @@ pub struct UiConfig { /// Regex hints for interacting with terminal content. pub hints: Hints, - /// Offer IPC through a unix socket. - #[cfg(unix)] - pub ipc_socket: bool, - /// Config for the alacritty_terminal itself. pub terminal: Terminal, - /// Path to a shell program to run on startup. - pub shell: Option, - - /// Shell startup directory. - pub working_directory: Option, - /// Keyboard configuration. keyboard: Keyboard, - /// Should draw bold text with brighter colors instead of bold font. - #[config(deprecated = "use colors.draw_bold_text_with_bright_colors instead")] - draw_bold_text_with_bright_colors: bool, - - /// Keybindings. - #[config(deprecated = "use keyboard.bindings instead")] - key_bindings: Option, - - /// Bindings for the mouse. - #[config(deprecated = "use mouse.bindings instead")] - mouse_bindings: Option, + /// Path to a shell program to run on startup. + #[config(deprecated = "use terminal.shell instead")] + shell: Option, /// Configuration file imports. /// /// This is never read since the field is directly accessed through the config's /// [`toml::Value`], but still present to prevent unused field warnings. - import: Vec, -} + #[config(deprecated = "use general.import instead")] + import: Option>, -impl Default for UiConfig { - fn default() -> Self { - Self { - live_config_reload: true, - #[cfg(unix)] - ipc_socket: true, - draw_bold_text_with_bright_colors: Default::default(), - working_directory: Default::default(), - mouse_bindings: Default::default(), - config_paths: Default::default(), - key_bindings: Default::default(), - alt_send_esc: Default::default(), - scrolling: Default::default(), - selection: Default::default(), - keyboard: Default::default(), - terminal: Default::default(), - import: Default::default(), - cursor: Default::default(), - window: Default::default(), - colors: Default::default(), - shell: Default::default(), - mouse: Default::default(), - debug: Default::default(), - hints: Default::default(), - font: Default::default(), - bell: Default::default(), - env: Default::default(), - } - } + /// Shell startup directory. + #[config(deprecated = "use general.working_directory instead")] + working_directory: Option, + + /// Live config reload. + #[config(deprecated = "use general.live_config_reload instead")] + live_config_reload: Option, + + /// Offer IPC through a unix socket. + #[cfg(unix)] + #[config(deprecated = "use general.ipc_socket instead")] + pub ipc_socket: Option, } impl UiConfig { @@ -166,26 +127,14 @@ impl UiConfig { /// Derive [`PtyOptions`] from the config. pub fn pty_config(&self) -> PtyOptions { - let shell = self.shell.clone().map(Into::into); - PtyOptions { - shell, - working_directory: self.working_directory.clone(), - hold: false, - env: HashMap::new(), - } + let shell = self.terminal.shell.clone().or_else(|| self.shell.clone()).map(Into::into); + let working_directory = + self.working_directory.clone().or_else(|| self.general.working_directory.clone()); + PtyOptions { working_directory, shell, hold: false, env: HashMap::new() } } /// Generate key bindings for all keyboard hints. pub fn generate_hint_bindings(&mut self) { - // Check which key bindings is most likely to be the user's configuration. - // - // Both will be non-empty due to the presence of the default keybindings. - let key_bindings = if let Some(key_bindings) = self.key_bindings.as_mut() { - &mut key_bindings.0 - } else { - &mut self.keyboard.bindings.0 - }; - for hint in &self.hints.enabled { let binding = match &hint.binding { Some(binding) => binding, @@ -200,7 +149,7 @@ impl UiConfig { action: Action::Hint(hint.clone()), }; - key_bindings.push(binding); + self.keyboard.bindings.0.push(binding); } } @@ -211,25 +160,23 @@ impl UiConfig { #[inline] pub fn key_bindings(&self) -> &[KeyBinding] { - if let Some(key_bindings) = self.key_bindings.as_ref() { - &key_bindings.0 - } else { - &self.keyboard.bindings.0 - } + &self.keyboard.bindings.0 } #[inline] pub fn mouse_bindings(&self) -> &[MouseBinding] { - if let Some(mouse_bindings) = self.mouse_bindings.as_ref() { - &mouse_bindings.0 - } else { - &self.mouse.bindings.0 - } + &self.mouse.bindings.0 } #[inline] - pub fn draw_bold_text_with_bright_colors(&self) -> bool { - self.colors.draw_bold_text_with_bright_colors || self.draw_bold_text_with_bright_colors + pub fn live_config_reload(&self) -> bool { + self.live_config_reload.unwrap_or(self.general.live_config_reload) + } + + #[cfg(unix)] + #[inline] + pub fn ipc_socket(&self) -> bool { + self.ipc_socket.unwrap_or(self.general.ipc_socket) } } @@ -362,7 +309,7 @@ impl Default for Hints { mouse: Some(HintMouse { enabled: true, mods: Default::default() }), binding: Some(HintBinding { key: BindingKey::Keycode { - key: Key::Character("u".into()), + key: Key::Character("o".into()), location: KeyLocation::Standard, }, mods: ModsWrapper(ModifiersState::SHIFT | ModifiersState::CONTROL), diff --git a/alacritty/src/daemon.rs b/alacritty/src/daemon.rs index df66646ae3d..c8fb88d1df0 100644 --- a/alacritty/src/daemon.rs +++ b/alacritty/src/daemon.rs @@ -94,7 +94,7 @@ pub fn foreground_process_path( } #[cfg(not(any(target_os = "macos", target_os = "freebsd")))] - let link_path = format!("/proc/{}/cwd", pid); + let link_path = format!("/proc/{pid}/cwd"); #[cfg(target_os = "freebsd")] let link_path = format!("/compat/linux/proc/{}/cwd", pid); diff --git a/alacritty/src/display/content.rs b/alacritty/src/display/content.rs index f36f71b59c2..02ac50e3773 100644 --- a/alacritty/src/display/content.rs +++ b/alacritty/src/display/content.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::num::NonZeroU32; use std::ops::Deref; use std::{cmp, mem}; @@ -137,8 +138,13 @@ impl<'a> RenderableContent<'a> { text_color = self.config.colors.primary.background; } + let width = if cell.flags.contains(Flags::WIDE_CHAR) { + NonZeroU32::new(2).unwrap() + } else { + NonZeroU32::new(1).unwrap() + }; RenderableCursor { - is_wide: cell.flags.contains(Flags::WIDE_CHAR), + width, shape: self.cursor_shape, point: self.cursor_point, cursor_color, @@ -357,7 +363,7 @@ impl RenderableCell { _ => rgb.into(), }, Color::Named(ansi) => { - match (config.draw_bold_text_with_bright_colors(), flags & Flags::DIM_BOLD) { + match (config.colors.draw_bold_text_with_bright_colors, flags & Flags::DIM_BOLD) { // If no bright foreground is set, treat it like the BOLD flag doesn't exist. (_, Flags::DIM_BOLD) if ansi == NamedColor::Foreground @@ -377,7 +383,7 @@ impl RenderableCell { }, Color::Indexed(idx) => { let idx = match ( - config.draw_bold_text_with_bright_colors(), + config.colors.draw_bold_text_with_bright_colors, flags & Flags::DIM_BOLD, idx, ) { @@ -425,7 +431,7 @@ pub struct RenderableCursor { shape: CursorShape, cursor_color: Rgb, text_color: Rgb, - is_wide: bool, + width: NonZeroU32, point: Point, } @@ -434,15 +440,20 @@ impl RenderableCursor { let shape = CursorShape::Hidden; let cursor_color = Rgb::default(); let text_color = Rgb::default(); - let is_wide = false; + let width = NonZeroU32::new(1).unwrap(); let point = Point::default(); - Self { shape, cursor_color, text_color, is_wide, point } + Self { shape, cursor_color, text_color, width, point } } } impl RenderableCursor { - pub fn new(point: Point, shape: CursorShape, cursor_color: Rgb, is_wide: bool) -> Self { - Self { shape, cursor_color, text_color: cursor_color, is_wide, point } + pub fn new( + point: Point, + shape: CursorShape, + cursor_color: Rgb, + width: NonZeroU32, + ) -> Self { + Self { shape, cursor_color, text_color: cursor_color, width, point } } pub fn color(&self) -> Rgb { @@ -453,8 +464,8 @@ impl RenderableCursor { self.shape } - pub fn is_wide(&self) -> bool { - self.is_wide + pub fn width(&self) -> NonZeroU32 { + self.width } pub fn point(&self) -> Point { diff --git a/alacritty/src/display/cursor.rs b/alacritty/src/display/cursor.rs index ee9d51f21be..ebbf7afb477 100644 --- a/alacritty/src/display/cursor.rs +++ b/alacritty/src/display/cursor.rs @@ -24,9 +24,7 @@ impl IntoRects for RenderableCursor { let thickness = (thickness * width).round().max(1.); - if self.is_wide() { - width *= 2.; - } + width *= self.width().get() as f32; match self.shape() { CursorShape::Beam => beam(x, y, height, thickness, self.color()), diff --git a/alacritty/src/display/damage.rs b/alacritty/src/display/damage.rs index f70cd2f5b1b..62c2f35f833 100644 --- a/alacritty/src/display/damage.rs +++ b/alacritty/src/display/damage.rs @@ -189,6 +189,15 @@ impl FrameDamage { self.lines.push(LineDamageBounds::undamaged(line, num_cols)); } } + + /// Check if a range is damaged. + #[inline] + pub fn intersects(&self, start: Point, end: Point) -> bool { + self.full + || self.lines[start.line].left <= start.column + || self.lines[end.line].right >= end.column + || (start.line + 1..end.line).any(|line| self.lines[line].is_damaged()) + } } /// Convert viewport `y` coordinate to [`Rect`] damage coordinate. diff --git a/alacritty/src/display/hint.rs b/alacritty/src/display/hint.rs index f118dbe090f..a01a1d03cf9 100644 --- a/alacritty/src/display/hint.rs +++ b/alacritty/src/display/hint.rs @@ -183,7 +183,7 @@ impl HintState { /// Update the alphabet used for hint labels. pub fn update_alphabet(&mut self, alphabet: &str) { if self.alphabet != alphabet { - self.alphabet = alphabet.to_owned(); + alphabet.clone_into(&mut self.alphabet); self.keys.clear(); } } diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index 1be84e16d2a..288bfa9c2f7 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -29,8 +29,7 @@ use alacritty_terminal::index::{Column, Direction, Line, Point}; use alacritty_terminal::selection::Selection; use alacritty_terminal::term::cell::Flags; use alacritty_terminal::term::{ - self, point_to_viewport, LineDamageBounds, Term, TermDamage, TermMode, MIN_COLUMNS, - MIN_SCREEN_LINES, + self, LineDamageBounds, Term, TermDamage, TermMode, MIN_COLUMNS, MIN_SCREEN_LINES, }; use alacritty_terminal::vte::ansi::{CursorShape, NamedColor}; @@ -270,10 +269,10 @@ impl SizeInfo { padding_right: f32, padding_top: f32, padding_bottom: f32, - dynamic_padding: bool, + _dynamic_padding: bool, ) -> SizeInfo { - let mut padding_x = (padding_left + padding_right) / 2.; - let mut padding_y = (padding_top + padding_bottom) / 2.; + let padding_x = (padding_left + padding_right) / 2.; // TODO: Reintroduce dynamic padding. + let padding_y = (padding_top + padding_bottom) / 2.; // TODO: Reintroduce dynamic padding. // TODO: Reintroduce dynamic padding. // if dynamic_padding { @@ -321,7 +320,7 @@ impl SizeInfo { /// Calculate padding to spread it evenly around the terminal content. #[inline] - fn dynamic_padding(padding: f32, dimension: f32, cell_dimension: f32) -> f32 { + fn _dynamic_padding(padding: f32, dimension: f32, cell_dimension: f32) -> f32 { // TODO: Reintroduce dynamic padding. padding + ((dimension - 2. * padding) % cell_dimension) / 2. } } @@ -806,41 +805,39 @@ impl Display { let vi_cursor_point = if vi_mode { Some(terminal.vi_mode_cursor.point) } else { None }; // Add damage from the terminal. - if self.collect_damage() { - match terminal.damage() { - TermDamage::Full => self.damage_tracker.frame().mark_fully_damaged(), - TermDamage::Partial(damaged_lines) => { - for damage in damaged_lines { - self.damage_tracker.frame().damage_line(damage); - } - }, - } - terminal.reset_damage(); + match terminal.damage() { + TermDamage::Full => self.damage_tracker.frame().mark_fully_damaged(), + TermDamage::Partial(damaged_lines) => { + for damage in damaged_lines { + self.damage_tracker.frame().damage_line(damage); + } + }, } + terminal.reset_damage(); let graphics_queues = terminal.graphics_take_queues(); // Drop terminal as early as possible to free lock. drop(terminal); - // Add damage from alacritty's UI elements overlapping terminal. - if self.collect_damage() { - let requires_full_damage = self.visual_bell.intensity() != 0. - || self.hint_state.active() - || search_state.regex().is_some(); + // Invalidate highlighted hints if grid has changed. + self.validate_hints(display_offset); - if requires_full_damage { - self.damage_tracker.frame().mark_fully_damaged(); - self.damage_tracker.next_frame().mark_fully_damaged(); - } - - let vi_cursor_viewport_point = - vi_cursor_point.and_then(|cursor| point_to_viewport(display_offset, cursor)); + // Add damage from alacritty's UI elements overlapping terminal. - self.damage_tracker.damage_vi_cursor(vi_cursor_viewport_point); - self.damage_tracker.damage_selection(selection_range, display_offset); + let requires_full_damage = self.visual_bell.intensity() != 0. + || self.hint_state.active() + || search_state.regex().is_some(); + if requires_full_damage { + self.damage_tracker.frame().mark_fully_damaged(); + self.damage_tracker.next_frame().mark_fully_damaged(); } + let vi_cursor_viewport_point = + vi_cursor_point.and_then(|cursor| term::point_to_viewport(display_offset, cursor)); + self.damage_tracker.damage_vi_cursor(vi_cursor_viewport_point); + self.damage_tracker.damage_selection(selection_range, display_offset); + // Make sure this window's OpenGL context is active. self.make_current(); @@ -869,42 +866,33 @@ impl Display { let vi_highlighted_hint = &self.vi_highlighted_hint; let damage_tracker = &mut self.damage_tracker; - self.renderer.draw_cells( - &size_info, - glyph_cache, - grid_cells.into_iter().map(|mut cell| { - // Underline hints hovered by mouse or vi mode cursor. - let point = term::viewport_to_point(display_offset, cell.point); + let cells = grid_cells.into_iter().map(|mut cell| { + let mut show_hint = false; - let mut show_hint = false; - - if has_highlighted_hint { - let hyperlink = - cell.extra.as_ref().and_then(|extra| extra.hyperlink.as_ref()); - if highlighted_hint - .as_ref() - .map_or(false, |hint| hint.should_highlight(point, hyperlink)) - || vi_highlighted_hint - .as_ref() - .map_or(false, |hint| hint.should_highlight(point, hyperlink)) - { - show_hint = true; - cell.flags.insert(Flags::UNDERLINE); - // Damage hints for the current and next frames. - damage_tracker.frame().damage_point(cell.point); - damage_tracker.next_frame().damage_point(cell.point); - } + // Underline hints hovered by mouse or vi mode cursor. + if has_highlighted_hint { + let point = term::viewport_to_point(display_offset, cell.point); + let hyperlink = cell.extra.as_ref().and_then(|extra| extra.hyperlink.as_ref()); + + let should_highlight = |hint: &Option| { + hint.as_ref().map_or(false, |hint| hint.should_highlight(point, hyperlink)) + }; + if should_highlight(highlighted_hint) || should_highlight(vi_highlighted_hint) { + show_hint = true; + damage_tracker.frame().damage_point(cell.point); + cell.flags.insert(Flags::UNDERLINE); } + } - // Update underline/strikeout. - lines.update(&cell); + // Update underline/strikeout. + lines.update(&cell); - // Track any graphic present in the cell. - graphics_list.update(&cell, show_hint); + // Track any graphic present in the cell. + graphics_list.update(&cell, show_hint); - cell - }), - ); + cell + }); + self.renderer.draw_cells(&size_info, glyph_cache, cells); } let mut rects = lines.rects(&metrics, &size_info); @@ -961,7 +949,9 @@ impl Display { if self.ime.preedit().is_none() { let fg = config.colors.footer_bar_foreground(); let shape = CursorShape::Underline; - let cursor = RenderableCursor::new(Point::new(line, column), shape, fg, false); + let cursor_width = NonZeroU32::new(1).unwrap(); + let cursor = + RenderableCursor::new(Point::new(line, column), shape, fg, cursor_width); rects.extend(cursor.rects(&size_info, config.cursor.thickness())); } @@ -969,8 +959,11 @@ impl Display { }, None => { let num_lines = self.size_info.screen_lines(); - term::point_to_viewport(display_offset, cursor_point) - .filter(|point| point.line < num_lines) + match vi_cursor_viewport_point { + None => term::point_to_viewport(display_offset, cursor_point) + .filter(|point| point.line < num_lines), + point => point, + } }, }; @@ -1100,10 +1093,17 @@ impl Display { let mut dirty = vi_highlighted_hint != self.vi_highlighted_hint; self.vi_highlighted_hint = vi_highlighted_hint; + // Force full redraw if the vi mode highlight was cleared. + if dirty && self.vi_highlighted_hint.is_none() { + self.damage_tracker.frame().mark_fully_damaged(); + } + // Abort if mouse highlighting conditions are not met. if !mouse.inside_text_area || !term.selection.as_ref().map_or(true, Selection::is_empty) { - dirty |= self.highlighted_hint.is_some(); - self.highlighted_hint = None; + if self.highlighted_hint.take().is_some() { + self.damage_tracker.frame().mark_fully_damaged(); + dirty = true; + } return dirty; } @@ -1127,9 +1127,15 @@ impl Display { } } - dirty |= self.highlighted_hint != highlighted_hint; + let mouse_highlight_dirty = self.highlighted_hint != highlighted_hint; + dirty |= mouse_highlight_dirty; self.highlighted_hint = highlighted_hint; + // Force full redraw if the mouse cursor highlight was cleared. + if mouse_highlight_dirty && self.highlighted_hint.is_none() { + self.damage_tracker.frame().mark_fully_damaged(); + } + dirty } @@ -1155,8 +1161,8 @@ impl Display { // Get the visible preedit. let visible_text: String = match (preedit.cursor_byte_offset, preedit.cursor_end_offset) { - (Some(byte_offset), Some(end_offset)) if end_offset > num_cols => StrShortener::new( - &preedit.text[byte_offset..], + (Some(byte_offset), Some(end_offset)) if end_offset.0 > num_cols => StrShortener::new( + &preedit.text[byte_offset.0..], num_cols, ShortenDirection::Right, Some(SHORTENER), @@ -1188,7 +1194,7 @@ impl Display { ); // Damage preedit inside the terminal viewport. - if self.collect_damage() && point.line < self.size_info.screen_lines() { + if point.line < self.size_info.screen_lines() { let damage = LineDamageBounds::new(start.line, 0, num_cols); self.damage_tracker.frame().damage_line(damage); self.damage_tracker.next_frame().damage_line(damage); @@ -1199,19 +1205,21 @@ impl Display { rects.extend(underline.rects(Flags::UNDERLINE, &metrics, &self.size_info)); let ime_popup_point = match preedit.cursor_end_offset { - Some(cursor_end_offset) if cursor_end_offset != 0 => { - let is_wide = preedit.text[preedit.cursor_byte_offset.unwrap_or_default()..] - .chars() - .next() - .map(|ch| ch.width() == Some(2)) - .unwrap_or_default(); + Some(cursor_end_offset) => { + // Use hollow block when multiple characters are changed at once. + let (shape, width) = if let Some(width) = + NonZeroU32::new((cursor_end_offset.0 - cursor_end_offset.1) as u32) + { + (CursorShape::HollowBlock, width) + } else { + (CursorShape::Beam, NonZeroU32::new(1).unwrap()) + }; let cursor_column = Column( - (end.column.0 as isize - cursor_end_offset as isize + 1).max(0) as usize, + (end.column.0 as isize - cursor_end_offset.0 as isize + 1).max(0) as usize, ); let cursor_point = Point::new(point.line, cursor_column); - let cursor = - RenderableCursor::new(cursor_point, CursorShape::HollowBlock, fg, is_wide); + let cursor = RenderableCursor::new(cursor_point, shape, fg, width); rects.extend(cursor.rects(&self.size_info, config.cursor.thickness())); cursor_point }, @@ -1299,13 +1307,11 @@ impl Display { let bg = config.colors.footer_bar_background(); for (uri, point) in uris.into_iter().zip(uri_lines) { // Damage the uri preview. - if self.collect_damage() { - let damage = LineDamageBounds::new(point.line, point.column.0, num_cols); - self.damage_tracker.frame().damage_line(damage); + let damage = LineDamageBounds::new(point.line, point.column.0, num_cols); + self.damage_tracker.frame().damage_line(damage); - // Damage the uri preview for the next frame as well. - self.damage_tracker.next_frame().damage_line(damage); - } + // Damage the uri preview for the next frame as well. + self.damage_tracker.next_frame().damage_line(damage); self.renderer.draw_string(point, fg, bg, uri, &self.size_info, &mut self.glyph_cache); } @@ -1316,7 +1322,7 @@ impl Display { fn draw_search(&mut self, config: &UiConfig, text: &str) { // Assure text length is at least num_cols. let num_cols = self.size_info.columns(); - let text = format!("{:<1$}", text, num_cols); + let text = format!("{text: bool { - matches!(self.raw_window_handle, RawWindowHandle::Wayland(_)) || self.damage_tracker.debug - } - /// Highlight damaged rects. /// /// This function is for debug purposes only. @@ -1409,6 +1405,34 @@ impl Display { } } + /// Check whether a hint highlight needs to be cleared. + fn validate_hints(&mut self, display_offset: usize) { + let frame = self.damage_tracker.frame(); + for (hint, reset_mouse) in + [(&mut self.highlighted_hint, true), (&mut self.vi_highlighted_hint, false)] + { + let (start, end) = match hint { + Some(hint) => (*hint.bounds().start(), *hint.bounds().end()), + None => return, + }; + + // Convert hint bounds to viewport coordinates. + let start = term::point_to_viewport(display_offset, start).unwrap_or_default(); + let end = term::point_to_viewport(display_offset, end).unwrap_or_else(|| { + Point::new(self.size_info.screen_lines() - 1, self.size_info.last_column()) + }); + + // Clear invalidated hints. + if frame.intersects(start, end) { + if reset_mouse { + self.window.set_mouse_cursor(CursorIcon::Default); + } + frame.mark_fully_damaged(); + *hint = None; + } + } + } + /// Request a new frame for a window on Wayland. fn request_frame(&mut self, scheduler: &mut Scheduler) { // Mark that we've used a frame. @@ -1494,20 +1518,22 @@ pub struct Preedit { /// Byte offset for cursor start into the preedit text. /// /// `None` means that the cursor is invisible. - cursor_byte_offset: Option, + cursor_byte_offset: Option<(usize, usize)>, - /// The cursor offset from the end of the preedit in char width. - cursor_end_offset: Option, + /// The cursor offset from the end of the start of the preedit in char width. + cursor_end_offset: Option<(usize, usize)>, } impl Preedit { - pub fn new(text: String, cursor_byte_offset: Option) -> Self { + pub fn new(text: String, cursor_byte_offset: Option<(usize, usize)>) -> Self { let cursor_end_offset = if let Some(byte_offset) = cursor_byte_offset { // Convert byte offset into char offset. - let cursor_end_offset = - text[byte_offset..].chars().fold(0, |acc, ch| acc + ch.width().unwrap_or(1)); + let start_to_end_offset = + text[byte_offset.0..].chars().fold(0, |acc, ch| acc + ch.width().unwrap_or(1)); + let end_to_end_offset = + text[byte_offset.1..].chars().fold(0, |acc, ch| acc + ch.width().unwrap_or(1)); - Some(cursor_end_offset) + Some((start_to_end_offset, end_to_end_offset)) } else { None }; diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index da5d85bcaac..1427dc75dc4 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -30,7 +30,7 @@ use winit::dpi::{PhysicalPosition, PhysicalSize}; use winit::event_loop::ActiveEventLoop; use winit::monitor::MonitorHandle; #[cfg(windows)] -use winit::platform::windows::IconExtWindows; +use winit::platform::windows::{IconExtWindows, WindowAttributesExtWindows}; use winit::raw_window_handle::{HasWindowHandle, RawWindowHandle}; use winit::window::{ CursorIcon, Fullscreen, ImePurpose, Theme, UserAttentionType, Window as WinitWindow, @@ -76,7 +76,7 @@ impl std::error::Error for Error { impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - Error::WindowCreation(err) => write!(f, "Error creating GL context; {}", err), + Error::WindowCreation(err) => write!(f, "Error creating GL context; {err}"), Error::Font(err) => err.fmt(f), } } @@ -302,7 +302,8 @@ impl Window { WinitWindow::default_attributes() .with_decorations(window_config.decorations != Decorations::None) - .with_window_icon(icon.ok()) + .with_window_icon(icon.as_ref().ok().cloned()) + .with_taskbar_icon(icon.ok()) } #[cfg(target_os = "macos")] diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index f2d615d0040..b391c95cf04 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1,5 +1,7 @@ //! Process window events. +use crate::ConfigMonitor; +use glutin::config::GetGlConfig; use std::borrow::Cow; use std::cmp::min; use std::collections::{HashMap, HashSet, VecDeque}; @@ -15,7 +17,8 @@ use std::{env, f32, mem}; use ahash::RandomState; use crossfont::Size as FontSize; -use glutin::display::{Display as GlutinDisplay, GetGlDisplay}; +use glutin::config::Config as GlutinConfig; +use glutin::display::GetGlDisplay; use log::{debug, error, info, warn}; use winit::application::ApplicationHandler; use winit::event::{ @@ -33,6 +36,7 @@ use alacritty_terminal::index::{Boundary, Column, Direction, Line, Point, Side}; use alacritty_terminal::selection::{Selection, SelectionType}; use alacritty_terminal::term::search::{Match, RegexSearch}; use alacritty_terminal::term::{self, ClipboardType, Term, TermMode}; +use alacritty_terminal::vte::ansi::NamedColor; #[cfg(unix)] use crate::cli::{IpcConfig, ParsedOptions}; @@ -70,13 +74,15 @@ const TOUCH_ZOOM_FACTOR: f32 = 0.01; /// Stores some state from received events and dispatches actions when they are /// triggered. pub struct Processor { + pub config_monitor: Option, + clipboard: Clipboard, scheduler: Scheduler, initial_window_options: Option, initial_window_error: Option>, windows: HashMap, proxy: EventLoopProxy, - gl_display: Option, + gl_config: Option, #[cfg(unix)] global_ipc_options: ParsedOptions, cli_options: CliOptions, @@ -101,18 +107,29 @@ impl Processor { // which is done in `loop_exiting`. let clipboard = unsafe { Clipboard::new(event_loop.display_handle().unwrap().as_raw()) }; + // Create a config monitor. + // + // The monitor watches the config file for changes and reloads it. Pending + // config changes are processed in the main loop. + let mut config_monitor = None; + if config.live_config_reload() { + config_monitor = + ConfigMonitor::new(config.config_paths.clone(), event_loop.create_proxy()); + } + Processor { initial_window_options, initial_window_error: None, cli_options, proxy, scheduler, - gl_display: None, + gl_config: None, config: Rc::new(config), clipboard, windows: Default::default(), #[cfg(unix)] global_ipc_options: Default::default(), + config_monitor, } } @@ -123,12 +140,16 @@ impl Processor { pub fn create_initial_window( &mut self, event_loop: &ActiveEventLoop, - options: WindowOptions, ) -> Result<(), Box> { + let options = match self.initial_window_options.take() { + Some(options) => options, + None => return Ok(()), + }; + let window_context = WindowContext::initial(event_loop, self.proxy.clone(), self.config.clone(), options)?; - self.gl_display = Some(window_context.display.gl_context().display()); + self.gl_config = Some(window_context.display.gl_context().config()); self.windows.insert(window_context.id(), window_context); Ok(()) @@ -140,7 +161,7 @@ impl Processor { event_loop: &ActiveEventLoop, options: WindowOptions, ) -> Result<(), Box> { - let window = self.windows.iter().next().as_ref().unwrap().1; + let gl_config = self.gl_config.as_ref().unwrap(); // Override config with CLI/IPC options. let mut config_overrides = options.config_overrides(); @@ -149,9 +170,14 @@ impl Processor { let mut config = self.config.clone(); config = config_overrides.override_config_rc(config); - #[allow(unused_mut)] - let mut window_context = - window.additional(event_loop, self.proxy.clone(), config, options, config_overrides)?; + let window_context = WindowContext::additional( + gl_config, + event_loop, + self.proxy.clone(), + config, + options, + config_overrides, + )?; self.windows.insert(window_context.id(), window_context); Ok(()) @@ -160,8 +186,8 @@ impl Processor { /// Run the event loop. /// /// The result is exit code generate from the loop. - pub fn run(mut self, event_loop: EventLoop) -> Result<(), Box> { - let result = event_loop.run_app(&mut self); + pub fn run(&mut self, event_loop: EventLoop) -> Result<(), Box> { + let result = event_loop.run_app(self); if let Some(initial_window_error) = self.initial_window_error.take() { Err(initial_window_error) } else { @@ -195,16 +221,11 @@ impl ApplicationHandler for Processor { fn resumed(&mut self, _event_loop: &ActiveEventLoop) {} fn new_events(&mut self, event_loop: &ActiveEventLoop, cause: StartCause) { - if cause != StartCause::Init { + if cause != StartCause::Init || self.cli_options.daemon { return; } - let initial_window_options = match self.initial_window_options.take() { - Some(initial_window_options) => initial_window_options, - None => return, - }; - - if let Err(err) = self.create_initial_window(event_loop, initial_window_options) { + if let Err(err) = self.create_initial_window(event_loop) { self.initial_window_error = Some(err); event_loop.exit(); return; @@ -297,6 +318,17 @@ impl ApplicationHandler for Processor { if let Ok(config) = config::reload(path, &mut self.cli_options) { self.config = Rc::new(config); + // Restart config monitor if imports changed. + if let Some(monitor) = self.config_monitor.take() { + let paths = &self.config.config_paths; + self.config_monitor = if monitor.needs_restart(paths) { + monitor.shutdown(); + ConfigMonitor::new(paths.clone(), self.proxy.clone()) + } else { + Some(monitor) + }; + } + for window_context in self.windows.values_mut() { window_context.update_config(self.config.clone()); } @@ -312,7 +344,13 @@ impl ApplicationHandler for Processor { window_context.display.make_not_current(); } - if let Err(err) = self.create_window(event_loop, options.clone()) { + if self.gl_config.is_none() { + // Handle initial window creation in daemon mode. + if let Err(err) = self.create_initial_window(event_loop) { + self.initial_window_error = Some(err); + event_loop.exit(); + } + } else if let Err(err) = self.create_window(event_loop, options.clone()) { error!("Could not open window: {:?}", err); } }, @@ -349,7 +387,7 @@ impl ApplicationHandler for Processor { self.scheduler.unschedule_window(window_context.id()); // Shutdown if no more terminals are open. - if self.windows.is_empty() { + if self.windows.is_empty() && !self.cli_options.daemon { // Write ref tests of last window to disk. if self.config.debug.ref_test { window_context.write_ref_test_results(); @@ -413,7 +451,7 @@ impl ApplicationHandler for Processor { info!("Exiting the event loop"); } - match self.gl_display.take() { + match self.gl_config.take().map(|config| config.display()) { #[cfg(not(target_os = "macos"))] Some(glutin::display::Display::Egl(display)) => { // Ensure that all the windows are dropped, so the destructors for @@ -1192,6 +1230,8 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon for c in text.chars() { self.search_input(c); } + } else if self.inline_search_state.char_pending { + self.inline_search_input(text); } else if bracketed && self.terminal().mode().contains(TermMode::BRACKETED_PASTE) { self.on_terminal_input_start(); @@ -1265,6 +1305,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon self.inline_search_state.stop_short = stop_short; self.inline_search_state.direction = direction; self.inline_search_state.char_pending = true; + self.inline_search_state.character = None; } /// Jump to the next matching character in the line. @@ -1279,6 +1320,22 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon self.inline_search(direction); } + /// Process input during inline search. + fn inline_search_input(&mut self, text: &str) { + // Ignore input with empty text, like modifier keys. + let c = match text.chars().next() { + Some(c) => c, + None => return, + }; + + self.inline_search_state.char_pending = false; + self.inline_search_state.character = Some(c); + self.window().set_ime_allowed(false); + + // Immediately move to the captured character. + self.inline_search_next(); + } + fn message(&self) -> Option<&Message> { self.message_buffer.message() } @@ -1712,9 +1769,12 @@ impl input::Processor> { } }, TerminalEvent::ColorRequest(index, format) => { - let color = self.ctx.terminal().colors()[index] - .map(Rgb) - .unwrap_or(self.ctx.display.colors[index]); + let color = match self.ctx.terminal().colors()[index] { + Some(color) => Rgb(color), + // Ignore cursor color requests unless it was changed. + None if index == NamedColor::Cursor as usize => return, + None => self.ctx.display.colors[index], + }; self.ctx.write_to_pty(format(color.0).into_bytes()); }, TerminalEvent::TextAreaSizeRequest(format) => { @@ -1814,11 +1874,8 @@ impl input::Processor> { self.ctx.update_cursor_blinking(); }, Ime::Preedit(text, cursor_offset) => { - let preedit = if text.is_empty() { - None - } else { - Some(Preedit::new(text, cursor_offset.map(|offset| offset.0))) - }; + let preedit = + (!text.is_empty()).then(|| Preedit::new(text, cursor_offset)); if self.ctx.display.ime.preedit() != preedit.as_ref() { self.ctx.display.ime.set_preedit(preedit); diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index d63da9f2bd0..147555940bd 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -1,5 +1,4 @@ use std::borrow::Cow; -use std::mem; use winit::event::{ElementState, KeyEvent}; #[cfg(target_os = "macos")] @@ -29,6 +28,9 @@ impl> Processor { let mods = self.ctx.modifiers().state(); if key.state == ElementState::Released { + if self.ctx.inline_search_state().char_pending { + self.ctx.window().set_ime_allowed(true); + } self.key_release(key, mode, mods); return; } @@ -45,15 +47,8 @@ impl> Processor { // First key after inline search is captured. let inline_state = self.ctx.inline_search_state(); - if mem::take(&mut inline_state.char_pending) { - if let Some(c) = text.chars().next() { - inline_state.character = Some(c); - - // Immediately move to the captured character. - self.ctx.inline_search_next(); - } - - // Ignore all other characters in `text`. + if inline_state.char_pending { + self.ctx.inline_search_input(text); return; } @@ -294,7 +289,7 @@ fn build_sequence(key: KeyEvent, mods: ModifiersState, mode: TermMode) -> Vec return Vec::new(), }; - let mut payload = format!("\x1b[{}", payload); + let mut payload = format!("\x1b[{payload}"); // Add modifiers information. if kitty_event_type || !modifiers.is_empty() || associated_text.is_some() { diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index 8019ee6d433..11eb30fd51c 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -127,6 +127,7 @@ pub trait ActionContext { fn inline_search_state(&mut self) -> &mut InlineSearchState; fn start_inline_search(&mut self, _direction: Direction, _stop_short: bool) {} fn inline_search_next(&mut self) {} + fn inline_search_input(&mut self, _text: &str) {} fn inline_search_previous(&mut self) {} fn hint_input(&mut self, _character: char) {} fn trigger_hint(&mut self, _hint: &HintMatch) {} @@ -809,7 +810,7 @@ impl> Processor { if self.ctx.terminal().mode().contains(TermMode::FOCUS_IN_OUT) { let chr = if is_focused { "I" } else { "O" }; - let msg = format!("\x1b[{}", chr); + let msg = format!("\x1b[{chr}"); self.ctx.write_to_pty(msg.into_bytes()); } } @@ -1329,9 +1330,9 @@ mod tests { event: WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, - device_id: unsafe { DeviceId::dummy() }, + device_id: DeviceId::dummy(), }, - window_id: unsafe { WindowId::dummy() }, + window_id: WindowId::dummy(), }, end_state: ClickState::Click, input_delay: Duration::ZERO, @@ -1345,9 +1346,9 @@ mod tests { event: WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Right, - device_id: unsafe { DeviceId::dummy() }, + device_id: DeviceId::dummy(), }, - window_id: unsafe { WindowId::dummy() }, + window_id: WindowId::dummy(), }, end_state: ClickState::Click, input_delay: Duration::ZERO, @@ -1361,9 +1362,9 @@ mod tests { event: WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Middle, - device_id: unsafe { DeviceId::dummy() }, + device_id: DeviceId::dummy(), }, - window_id: unsafe { WindowId::dummy() }, + window_id: WindowId::dummy(), }, end_state: ClickState::Click, input_delay: Duration::ZERO, @@ -1377,9 +1378,9 @@ mod tests { event: WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, - device_id: unsafe { DeviceId::dummy() }, + device_id: DeviceId::dummy(), }, - window_id: unsafe { WindowId::dummy() }, + window_id: WindowId::dummy(), }, end_state: ClickState::DoubleClick, input_delay: Duration::ZERO, @@ -1393,9 +1394,9 @@ mod tests { event: WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, - device_id: unsafe { DeviceId::dummy() }, + device_id: DeviceId::dummy(), }, - window_id: unsafe { WindowId::dummy() }, + window_id: WindowId::dummy(), }, end_state: ClickState::Click, input_delay: CLICK_THRESHOLD, @@ -1409,9 +1410,9 @@ mod tests { event: WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, - device_id: unsafe { DeviceId::dummy() }, + device_id: DeviceId::dummy(), }, - window_id: unsafe { WindowId::dummy() }, + window_id: WindowId::dummy(), }, end_state: ClickState::TripleClick, input_delay: Duration::ZERO, @@ -1425,9 +1426,9 @@ mod tests { event: WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Left, - device_id: unsafe { DeviceId::dummy() }, + device_id: DeviceId::dummy(), }, - window_id: unsafe { WindowId::dummy() }, + window_id: WindowId::dummy(), }, end_state: ClickState::Click, input_delay: CLICK_THRESHOLD, @@ -1441,9 +1442,9 @@ mod tests { event: WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Right, - device_id: unsafe { DeviceId::dummy() }, + device_id: DeviceId::dummy(), }, - window_id: unsafe { WindowId::dummy() }, + window_id: WindowId::dummy(), }, end_state: ClickState::Click, input_delay: Duration::ZERO, diff --git a/alacritty/src/ipc.rs b/alacritty/src/ipc.rs index 1cb7a1c8378..3d14c4cea52 100644 --- a/alacritty/src/ipc.rs +++ b/alacritty/src/ipc.rs @@ -20,13 +20,13 @@ const ALACRITTY_SOCKET_ENV: &str = "ALACRITTY_SOCKET"; /// Create an IPC socket. pub fn spawn_ipc_socket(options: &Options, event_proxy: EventLoopProxy) -> Option { - // Create the IPC socket and export its path as env variable if necessary. + // Create the IPC socket and export its path as env. + let socket_path = options.socket.clone().unwrap_or_else(|| { let mut path = socket_dir(); path.push(format!("{}-{}.sock", socket_prefix(), process::id())); path }); - env::set_var(ALACRITTY_SOCKET_ENV, socket_path.as_os_str()); let listener = match UnixListener::bind(&socket_path) { Ok(listener) => listener, @@ -36,6 +36,11 @@ pub fn spawn_ipc_socket(options: &Options, event_proxy: EventLoopProxy) - }, }; + env::set_var(ALACRITTY_SOCKET_ENV, socket_path.as_os_str()); + if options.daemon { + println!("ALACRITTY_SOCKET={}; export ALACRITTY_SOCKET", socket_path.display()); + } + // Spawn a thread to listen on the IPC socket. thread::spawn_named("socket listener", move || { let mut data = String::new(); @@ -111,7 +116,7 @@ fn find_socket(socket_path: Option) -> IoResult { if let Some(socket_path) = socket_path { // Ensure we inform the user about an invalid path. return UnixStream::connect(&socket_path).map_err(|err| { - let message = format!("invalid socket path {:?}", socket_path); + let message = format!("invalid socket path {socket_path:?}"); IoError::new(err.kind(), message) }); } diff --git a/alacritty/src/logging.rs b/alacritty/src/logging.rs index 59303649b0a..67cad63e46d 100644 --- a/alacritty/src/logging.rs +++ b/alacritty/src/logging.rs @@ -108,16 +108,16 @@ impl Logger { }; #[cfg(not(windows))] - let env_var = format!("${}", ALACRITTY_LOG_ENV); + let env_var = format!("${ALACRITTY_LOG_ENV}"); #[cfg(windows)] let env_var = format!("%{}%", ALACRITTY_LOG_ENV); let message = format!( - "[{}] See log at {} ({}):\n{}", + "[{}] {}\nSee log at {} ({})", record.level(), + record.args(), logfile_path, env_var, - record.args(), ); let mut message = Message::new(message, message_type); @@ -227,7 +227,7 @@ impl OnDemandLogFile { writeln!(io::stdout(), "Created log file at \"{}\"", self.path.display()); }, Err(e) => { - let _ = writeln!(io::stdout(), "Unable to create log file: {}", e); + let _ = writeln!(io::stdout(), "Unable to create log file: {e}"); return Err(e); }, } diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 6219dd78e1c..6bbf8dfd5d3 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -172,19 +172,9 @@ fn alacritty(mut options: Options) -> Result<(), Box> { #[cfg(target_os = "macos")] locale::set_locale_environment(); - // Create a config monitor when config was loaded from path. - // - // The monitor watches the config file for changes and reloads it. Pending - // config changes are processed in the main loop. - let mut config_monitor = None; - if config.live_config_reload { - config_monitor = - ConfigMonitor::new(config.config_paths.clone(), window_event_loop.create_proxy()); - } - // Create the IPC socket listener. #[cfg(unix)] - let socket_path = if config.ipc_socket { + let socket_path = if config.ipc_socket() { ipc::spawn_ipc_socket(&options, window_event_loop.create_proxy()) } else { None @@ -199,7 +189,7 @@ fn alacritty(mut options: Options) -> Result<(), Box> { }; // Event processor. - let processor = Processor::new(config, options, &window_event_loop); + let mut processor = Processor::new(config, options, &window_event_loop); // Start event loop and block until shutdown. let result = processor.run(window_event_loop); @@ -219,7 +209,7 @@ fn alacritty(mut options: Options) -> Result<(), Box> { // FIXME: Change PTY API to enforce the correct drop order with the typesystem. // Terminate the config monitor. - if let Some(config_monitor) = config_monitor.take() { + if let Some(config_monitor) = processor.config_monitor.take() { config_monitor.shutdown(); } diff --git a/alacritty/src/migrate.rs b/alacritty/src/migrate.rs deleted file mode 100644 index 6d116858b06..00000000000 --- a/alacritty/src/migrate.rs +++ /dev/null @@ -1,267 +0,0 @@ -//! Configuration file migration. - -use std::fs; -use std::path::Path; - -use toml::map::Entry; -use toml::{Table, Value}; - -use crate::cli::MigrateOptions; -use crate::config; - -/// Handle migration. -pub fn migrate(options: MigrateOptions) { - // Find configuration file path. - let config_path = options - .config_file - .clone() - .or_else(|| config::installed_config("toml")) - .or_else(|| config::installed_config("yml")); - - // Abort if system has no installed configuration. - let config_path = match config_path { - Some(config_path) => config_path, - None => { - eprintln!("No configuration file found"); - std::process::exit(1); - }, - }; - - // If we're doing a wet run, perform a dry run first for safety. - if !options.dry_run { - #[allow(clippy::redundant_clone)] - let mut options = options.clone(); - options.silent = true; - options.dry_run = true; - if let Err(err) = migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) { - eprintln!("Configuration file migration failed:"); - eprintln!(" {config_path:?}: {err}"); - std::process::exit(1); - } - } - - // Migrate the root config. - match migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) { - Ok(new_path) => { - if !options.silent { - println!("Successfully migrated {config_path:?} to {new_path:?}"); - } - }, - Err(err) => { - eprintln!("Configuration file migration failed:"); - eprintln!(" {config_path:?}: {err}"); - std::process::exit(1); - }, - } -} - -/// Migrate a specific configuration file. -fn migrate_config( - options: &MigrateOptions, - path: &Path, - recursion_limit: usize, -) -> Result { - // Ensure configuration file has an extension. - let path_str = path.to_string_lossy(); - let (prefix, suffix) = match path_str.rsplit_once('.') { - Some((prefix, suffix)) => (prefix, suffix), - None => return Err("missing file extension".to_string()), - }; - - // Abort if config is already toml. - if suffix == "toml" { - return Err("already in TOML format".to_string()); - } - - // Try to parse the configuration file. - let mut config = match config::deserialize_config(path, !options.dry_run) { - Ok(config) => config, - Err(err) => return Err(format!("parsing error: {err}")), - }; - - // Migrate config imports. - if !options.skip_imports { - migrate_imports(options, &mut config, path, recursion_limit)?; - } - - // Migrate deprecated field names to their new location. - if !options.skip_renames { - migrate_renames(&mut config)?; - } - - // Convert to TOML format. - let toml = toml::to_string(&config).map_err(|err| format!("conversion error: {err}"))?; - let new_path = format!("{prefix}.toml"); - - if options.dry_run && !options.silent { - // Output new content to STDOUT. - println!( - "\nv-----Start TOML for {path:?}-----v\n\n{toml}\n^-----End TOML for {path:?}-----^\n" - ); - } else if !options.dry_run { - // Write the new toml configuration. - fs::write(&new_path, toml).map_err(|err| format!("filesystem error: {err}"))?; - } - - Ok(new_path) -} - -/// Migrate the imports of a config. -fn migrate_imports( - options: &MigrateOptions, - config: &mut Value, - base_path: &Path, - recursion_limit: usize, -) -> Result<(), String> { - let imports = match config::imports(config, base_path, recursion_limit) { - Ok(imports) => imports, - Err(err) => return Err(format!("import error: {err}")), - }; - - // Migrate the individual imports. - let mut new_imports = Vec::new(); - for import in imports { - let import = match import { - Ok(import) => import, - Err(err) => return Err(format!("import error: {err}")), - }; - - // Keep yaml import if path does not exist. - if !import.exists() { - if options.dry_run { - eprintln!("Keeping yaml config for nonexistent import: {import:?}"); - } - new_imports.push(Value::String(import.to_string_lossy().into())); - continue; - } - - let new_path = migrate_config(options, &import, recursion_limit - 1)?; - - // Print new import path. - if options.dry_run { - println!("Successfully migrated import {import:?} to {new_path:?}"); - } - - new_imports.push(Value::String(new_path)); - } - - // Update the imports field. - if let Some(import) = config.get_mut("import") { - *import = Value::Array(new_imports); - } - - Ok(()) -} - -/// Migrate deprecated fields. -fn migrate_renames(config: &mut Value) -> Result<(), String> { - let config_table = match config.as_table_mut() { - Some(config_table) => config_table, - None => return Ok(()), - }; - - // draw_bold_text_with_bright_colors -> colors.draw_bold_text_with_bright_colors - move_value(config_table, &["draw_bold_text_with_bright_colors"], &[ - "colors", - "draw_bold_text_with_bright_colors", - ])?; - - // key_bindings -> keyboard.bindings - move_value(config_table, &["key_bindings"], &["keyboard", "bindings"])?; - - // mouse_bindings -> mouse.bindings - move_value(config_table, &["mouse_bindings"], &["mouse", "bindings"])?; - - Ok(()) -} - -/// Move a toml value from one map to another. -fn move_value(config_table: &mut Table, origin: &[&str], target: &[&str]) -> Result<(), String> { - if let Some(value) = remove_node(config_table, origin)? { - if !insert_node_if_empty(config_table, target, value)? { - return Err(format!( - "conflict: both `{}` and `{}` are set", - origin.join("."), - target.join(".") - )); - } - } - - Ok(()) -} - -/// Remove a node from a tree of tables. -fn remove_node(table: &mut Table, path: &[&str]) -> Result, String> { - if path.len() == 1 { - Ok(table.remove(path[0])) - } else { - let next_table_value = match table.get_mut(path[0]) { - Some(next_table_value) => next_table_value, - None => return Ok(None), - }; - - let next_table = match next_table_value.as_table_mut() { - Some(next_table) => next_table, - None => return Err(format!("invalid `{}` table", path[0])), - }; - - remove_node(next_table, &path[1..]) - } -} - -/// Try to insert a node into a tree of tables. -/// -/// Returns `false` if the node already exists. -fn insert_node_if_empty(table: &mut Table, path: &[&str], node: Value) -> Result { - if path.len() == 1 { - match table.entry(path[0]) { - Entry::Vacant(vacant_entry) => { - vacant_entry.insert(node); - Ok(true) - }, - Entry::Occupied(_) => Ok(false), - } - } else { - let next_table_value = table.entry(path[0]).or_insert_with(|| Value::Table(Table::new())); - - let next_table = match next_table_value.as_table_mut() { - Some(next_table) => next_table, - None => return Err(format!("invalid `{}` table", path[0])), - }; - - insert_node_if_empty(next_table, &path[1..], node) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn move_values() { - let input = r#" -root_value = 3 - -[table] -table_value = 5 - -[preexisting] -not_moved = 9 - "#; - - let mut value: Value = toml::from_str(input).unwrap(); - let table = value.as_table_mut().unwrap(); - - move_value(table, &["root_value"], &["new_table", "root_value"]).unwrap(); - move_value(table, &["table", "table_value"], &["preexisting", "subtable", "new_name"]) - .unwrap(); - - let output = toml::to_string(table).unwrap(); - - assert_eq!( - output, - "[new_table]\nroot_value = 3\n\n[preexisting]\nnot_moved = \ - 9\n\n[preexisting.subtable]\nnew_name = 5\n\n[table]\n" - ); - } -} diff --git a/alacritty/src/migrate/mod.rs b/alacritty/src/migrate/mod.rs new file mode 100644 index 00000000000..2f806d361a1 --- /dev/null +++ b/alacritty/src/migrate/mod.rs @@ -0,0 +1,326 @@ +//! Configuration file migration. + +use std::fmt::Debug; +use std::path::Path; +use std::{fs, mem}; + +use tempfile::NamedTempFile; +use toml_edit::{DocumentMut, Item}; + +use crate::cli::MigrateOptions; +use crate::config; + +mod yaml; + +/// Handle migration. +pub fn migrate(options: MigrateOptions) { + // Find configuration file path. + let config_path = options + .config_file + .clone() + .or_else(|| config::installed_config("toml")) + .or_else(|| config::installed_config("yml")); + + // Abort if system has no installed configuration. + let config_path = match config_path { + Some(config_path) => config_path, + None => { + eprintln!("No configuration file found"); + std::process::exit(1); + }, + }; + + // If we're doing a wet run, perform a dry run first for safety. + if !options.dry_run { + #[allow(clippy::redundant_clone)] + let mut options = options.clone(); + options.silent = true; + options.dry_run = true; + if let Err(err) = migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) { + eprintln!("Configuration file migration failed:"); + eprintln!(" {config_path:?}: {err}"); + std::process::exit(1); + } + } + + // Migrate the root config. + match migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) { + Ok(migration) => { + if !options.silent { + println!("{}", migration.success_message(false)); + } + }, + Err(err) => { + eprintln!("Configuration file migration failed:"); + eprintln!(" {config_path:?}: {err}"); + std::process::exit(1); + }, + } +} + +/// Migrate a specific configuration file. +fn migrate_config<'a>( + options: &MigrateOptions, + path: &'a Path, + recursion_limit: usize, +) -> Result, String> { + // Ensure configuration file has an extension. + let path_str = path.to_string_lossy(); + let (prefix, suffix) = match path_str.rsplit_once('.') { + Some((prefix, suffix)) => (prefix, suffix), + None => return Err("missing file extension".to_string()), + }; + + // Handle legacy YAML files. + if suffix == "yml" { + let new_path = yaml::migrate(options, path, recursion_limit, prefix)?; + return Ok(Migration::Yaml((path, new_path))); + } + + // TOML only does renames, so return early if they are disabled. + if options.skip_renames { + if options.dry_run { + eprintln!("Ignoring TOML file {path:?} since `--skip-renames` was supplied"); + } + return Ok(Migration::Toml(path)); + } + + // Read TOML file and perform all in-file migrations. + let toml = fs::read_to_string(path).map_err(|err| format!("{err}"))?; + let mut migrated = migrate_toml(toml)?; + + // Recursively migrate imports. + migrate_imports(options, path, &mut migrated, recursion_limit)?; + + // Write migrated TOML file. + write_results(options, path, &migrated.to_string())?; + + Ok(Migration::Toml(path)) +} + +/// Migrate TOML config to the latest version. +fn migrate_toml(toml: String) -> Result { + // Parse TOML file. + let mut document = match toml.parse::() { + Ok(document) => document, + Err(err) => return Err(format!("TOML parsing error: {err}")), + }; + + // Move `draw_bold_text_with_bright_colors` to its own section. + move_value(&mut document, &["draw_bold_text_with_bright_colors"], &[ + "colors", + "draw_bold_text_with_bright_colors", + ])?; + + // Move bindings to their own section. + move_value(&mut document, &["key_bindings"], &["keyboard", "bindings"])?; + move_value(&mut document, &["mouse_bindings"], &["mouse", "bindings"])?; + + // Avoid warnings due to introduction of the new `general` section. + move_value(&mut document, &["live_config_reload"], &["general", "live_config_reload"])?; + move_value(&mut document, &["working_directory"], &["general", "working_directory"])?; + move_value(&mut document, &["ipc_socket"], &["general", "ipc_socket"])?; + move_value(&mut document, &["import"], &["general", "import"])?; + move_value(&mut document, &["shell"], &["terminal", "shell"])?; + + Ok(document) +} + +/// Migrate TOML imports to the latest version. +fn migrate_imports( + options: &MigrateOptions, + path: &Path, + document: &mut DocumentMut, + recursion_limit: usize, +) -> Result<(), String> { + // Check if any imports need to be processed. + let imports = match document + .get("general") + .and_then(|general| general.get("import")) + .and_then(|import| import.as_array()) + { + Some(array) if !array.is_empty() => array, + _ => return Ok(()), + }; + + // Abort once recursion limit is exceeded. + if recursion_limit == 0 { + return Err("Exceeded maximum configuration import depth".into()); + } + + // Migrate each import. + for import in imports.into_iter().filter_map(|item| item.as_str()) { + let normalized_path = config::normalize_import(path, import); + let migration = migrate_config(options, &normalized_path, recursion_limit)?; + if options.dry_run { + println!("{}", migration.success_message(true)); + } + } + + Ok(()) +} + +/// Move a TOML value from one map to another. +fn move_value(document: &mut DocumentMut, origin: &[&str], target: &[&str]) -> Result<(), String> { + // Find and remove the original item. + let (mut origin_key, mut origin_item) = (None, document.as_item_mut()); + for element in origin { + let table = match origin_item.as_table_like_mut() { + Some(table) => table, + None => panic!("Moving from unsupported TOML structure"), + }; + + let (key, item) = match table.get_key_value_mut(element) { + Some((key, item)) => (key, item), + None => return Ok(()), + }; + + origin_key = Some(key); + origin_item = item; + + // Ensure no empty tables are left behind. + if let Some(table) = origin_item.as_table_mut() { + table.set_implicit(true) + } + } + + let origin_key_decor = + origin_key.map(|key| (key.leaf_decor().clone(), key.dotted_decor().clone())); + let origin_item = mem::replace(origin_item, Item::None); + + // Create all dependencies for the new location. + let mut target_item = document.as_item_mut(); + for (i, element) in target.iter().enumerate() { + let table = match target_item.as_table_like_mut() { + Some(table) => table, + None => panic!("Moving into unsupported TOML structure"), + }; + + if i + 1 == target.len() { + table.insert(element, origin_item); + // Move original key decorations. + if let Some((leaf, dotted)) = origin_key_decor { + let mut key = table.key_mut(element).unwrap(); + *key.leaf_decor_mut() = leaf; + *key.dotted_decor_mut() = dotted; + } + + break; + } else { + // Create missing parent tables. + target_item = target_item[element].or_insert(toml_edit::table()); + } + } + + Ok(()) +} + +/// Write migrated TOML to its target location. +fn write_results

(options: &MigrateOptions, path: P, toml: &str) -> Result<(), String> +where + P: AsRef + Debug, +{ + let path = path.as_ref(); + if options.dry_run && !options.silent { + // Output new content to STDOUT. + println!( + "\nv-----Start TOML for {path:?}-----v\n\n{toml}\n^-----End TOML for {path:?}-----^\n" + ); + } else if !options.dry_run { + // Atomically replace the configuration file. + let tmp = NamedTempFile::new_in(path.parent().unwrap()) + .map_err(|err| format!("could not create temporary file: {err}"))?; + fs::write(tmp.path(), toml).map_err(|err| format!("filesystem error: {err}"))?; + tmp.persist(path).map_err(|err| format!("atomic replacement failed: {err}"))?; + } + Ok(()) +} + +/// Performed migration mode. +enum Migration<'a> { + /// In-place TOML migration. + Toml(&'a Path), + /// YAML to TOML migration. + Yaml((&'a Path, String)), +} + +impl<'a> Migration<'a> { + /// Get the success message for this migration. + fn success_message(&self, import: bool) -> String { + match self { + Self::Yaml((original_path, new_path)) if import => { + format!("Successfully migrated import {original_path:?} to {new_path:?}") + }, + Self::Yaml((original_path, new_path)) => { + format!("Successfully migrated {original_path:?} to {new_path:?}") + }, + Self::Toml(original_path) if import => { + format!("Successfully migrated import {original_path:?}") + }, + Self::Toml(original_path) => format!("Successfully migrated {original_path:?}"), + } + } + + /// Get the file path after migration. + fn new_path(&self) -> String { + match self { + Self::Toml(path) => path.to_string_lossy().into(), + Self::Yaml((_, path)) => path.into(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn move_values() { + let input = r#" +# This is a root_value. +# +# Use it with care. +root_value = 3 + +[table] +table_value = 5 + +[preexisting] +not_moved = 9 + "#; + + let mut document = input.parse::().unwrap(); + + move_value(&mut document, &["root_value"], &["new_table", "root_value"]).unwrap(); + move_value(&mut document, &["table", "table_value"], &[ + "preexisting", + "subtable", + "new_name", + ]) + .unwrap(); + + let output = document.to_string(); + + let expected = r#" +[preexisting] +not_moved = 9 + +[preexisting.subtable] +new_name = 5 + +[new_table] + +# This is a root_value. +# +# Use it with care. +root_value = 3 + "#; + + assert_eq!(output, expected); + } + + #[test] + fn migrate_empty() { + assert!(migrate_toml(String::new()).unwrap().to_string().is_empty()); + } +} diff --git a/alacritty/src/migrate/yaml.rs b/alacritty/src/migrate/yaml.rs new file mode 100644 index 00000000000..9607e95e463 --- /dev/null +++ b/alacritty/src/migrate/yaml.rs @@ -0,0 +1,87 @@ +//! Migration of legacy YAML files to TOML. + +use std::path::Path; + +use toml::Value; + +use crate::cli::MigrateOptions; +use crate::config; +use crate::migrate::{migrate_config, migrate_toml, write_results}; + +/// Migrate a legacy YAML config to TOML. +pub fn migrate( + options: &MigrateOptions, + path: &Path, + recursion_limit: usize, + prefix: &str, +) -> Result { + // Try to parse the configuration file. + let mut config = match config::deserialize_config(path, !options.dry_run) { + Ok(config) => config, + Err(err) => return Err(format!("YAML parsing error: {err}")), + }; + + // Migrate config imports. + if !options.skip_imports { + migrate_imports(options, &mut config, path, recursion_limit)?; + } + + // Convert to TOML format. + let mut toml = toml::to_string(&config).map_err(|err| format!("conversion error: {err}"))?; + let new_path = format!("{prefix}.toml"); + + // Apply TOML migration, without recursing through imports. + toml = migrate_toml(toml)?.to_string(); + + // Write migrated TOML config. + write_results(options, &new_path, &toml)?; + + Ok(new_path) +} + +/// Migrate the imports of a config. +fn migrate_imports( + options: &MigrateOptions, + config: &mut Value, + base_path: &Path, + recursion_limit: usize, +) -> Result<(), String> { + let imports = match config::imports(config, base_path, recursion_limit) { + Ok(imports) => imports, + Err(err) => return Err(format!("import error: {err}")), + }; + + // Migrate the individual imports. + let mut new_imports = Vec::new(); + for import in imports { + let import = match import { + Ok(import) => import, + Err(err) => return Err(format!("import error: {err}")), + }; + + // Keep yaml import if path does not exist. + if !import.exists() { + if options.dry_run { + eprintln!("Keeping yaml config for nonexistent import: {import:?}"); + } + new_imports.push(Value::String(import.to_string_lossy().into())); + continue; + } + + let migration = migrate_config(options, &import, recursion_limit - 1)?; + + // Print success message. + if options.dry_run { + println!("{}", migration.success_message(true)); + } + + new_imports.push(Value::String(migration.new_path())); + } + + // Update the imports field. + if let Some(import) = config.get_mut("import") { + *import = Value::Array(new_imports); + } + + Ok(()) +} diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index 98285a02bc6..71dcd96d6ec 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -69,10 +69,10 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { Error::Shader(err) => { - write!(f, "There was an error initializing the shaders: {}", err) + write!(f, "There was an error initializing the shaders: {err}") }, Error::Other(err) => { - write!(f, "{}", err) + write!(f, "{err}") }, } } @@ -115,9 +115,9 @@ fn gl_get_string( Ok(CStr::from_ptr(string_ptr as *const _).to_string_lossy()) }, gl::INVALID_ENUM => { - Err(format!("OpenGL error requesting {}: invalid enum", description).into()) + Err(format!("OpenGL error requesting {description}: invalid enum").into()) }, - error_id => Err(format!("OpenGL error {} requesting {}", error_id, description).into()), + error_id => Err(format!("OpenGL error {error_id} requesting {description}").into()), } } } diff --git a/alacritty/src/renderer/shader.rs b/alacritty/src/renderer/shader.rs index e3baab9e768..86938e4526c 100644 --- a/alacritty/src/renderer/shader.rs +++ b/alacritty/src/renderer/shader.rs @@ -196,9 +196,9 @@ impl std::error::Error for ShaderError {} impl fmt::Display for ShaderError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - Self::Compile(reason) => write!(f, "Failed compiling shader: {}", reason), - Self::Link(reason) => write!(f, "Failed linking shader: {}", reason), - Self::Uniform(name) => write!(f, "Failed to get uniform location of {:?}", name), + Self::Compile(reason) => write!(f, "Failed compiling shader: {reason}"), + Self::Link(reason) => write!(f, "Failed linking shader: {reason}"), + Self::Uniform(name) => write!(f, "Failed to get uniform location of {name:?}"), } } } diff --git a/alacritty/src/string.rs b/alacritty/src/string.rs index e41b078578d..a7af439465d 100644 --- a/alacritty/src/string.rs +++ b/alacritty/src/string.rs @@ -51,6 +51,7 @@ impl<'a> StrShortener<'a> { if direction == ShortenDirection::Right { return Self { + #[allow(clippy::iter_skip_zero)] chars: text.chars().skip(0), accumulated_len: 0, text_action: TextAction::Char, diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index 062f9ef0cd7..cfc3cd9645d 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -9,7 +9,7 @@ use std::os::unix::io::{AsRawFd, RawFd}; use std::rc::Rc; use std::sync::Arc; -use glutin::config::GetGlConfig; +use glutin::config::Config as GlutinConfig; use glutin::display::GetGlDisplay; #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] use glutin::platform::x11::X11GlConfigExt; @@ -119,18 +119,14 @@ impl WindowContext { /// Create additional context with the graphics platform other windows are using. pub fn additional( - &self, + gl_config: &GlutinConfig, event_loop: &ActiveEventLoop, proxy: EventLoopProxy, config: Rc, options: WindowOptions, config_overrides: ParsedOptions, ) -> Result> { - // Get any window and take its GL config and display to build a new context. - let (gl_display, gl_config) = { - let gl_context = self.display.gl_context(); - (gl_context.display(), gl_context.config()) - }; + let gl_display = gl_config.display(); let mut identity = config.window.identity.clone(); options.window_identity.override_identity_config(&mut identity); @@ -147,11 +143,8 @@ impl WindowContext { // Create context. let raw_window_handle = window.raw_window_handle(); - let gl_context = renderer::platform::create_gl_context( - &gl_display, - &gl_config, - Some(raw_window_handle), - )?; + let gl_context = + renderer::platform::create_gl_context(&gl_display, gl_config, Some(raw_window_handle))?; // Check if new window will be opened as a tab. #[cfg(target_os = "macos")] diff --git a/alacritty/windows/wix/alacritty.wxs b/alacritty/windows/wix/alacritty.wxs index cd64ec7ba3e..cd00bda0bcd 100644 --- a/alacritty/windows/wix/alacritty.wxs +++ b/alacritty/windows/wix/alacritty.wxs @@ -1,5 +1,5 @@ - + diff --git a/alacritty_config/Cargo.toml b/alacritty_config/Cargo.toml index c09a05e2b7b..862c6eb875f 100644 --- a/alacritty_config/Cargo.toml +++ b/alacritty_config/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "alacritty_config" -version = "0.2.1-dev" +version = "0.2.2" authors = ["Christian Duerr "] license = "MIT OR Apache-2.0" description = "Alacritty configuration abstractions" homepage = "https://alacritty.org" repository = "https://github.com/alacritty/alacritty" edition = "2021" -rust-version = "1.70.0" +rust-version = "1.74.0" [dependencies] log = { version = "0.4.17", features = ["serde"] } @@ -15,5 +15,5 @@ serde = "1.0.163" toml = "0.8.2" [dev-dependencies] -alacritty_config_derive = { version = "0.2.3-dev", path = "../alacritty_config_derive" } +alacritty_config_derive = { version = "0.2.4", path = "../alacritty_config_derive" } serde = { version = "1.0.163", features = ["derive"] } diff --git a/alacritty_config_derive/Cargo.toml b/alacritty_config_derive/Cargo.toml index dce132379b8..bf439ce75d1 100644 --- a/alacritty_config_derive/Cargo.toml +++ b/alacritty_config_derive/Cargo.toml @@ -1,13 +1,13 @@ [package] name = "alacritty_config_derive" -version = "0.2.3-dev" +version = "0.2.4" authors = ["Christian Duerr "] license = "MIT OR Apache-2.0" description = "Failure resistant deserialization derive" homepage = "https://alacritty.org" repository = "https://github.com/alacritty/alacritty" edition = "2021" -rust-version = "1.70.0" +rust-version = "1.74.0" [lib] proc-macro = true @@ -19,7 +19,7 @@ syn = { version = "2.0.16", features = ["derive", "parsing", "proc-macro", "prin [dev-dependencies.alacritty_config] path = "../alacritty_config" -version = "0.2.1-dev" +version = "0.2.2" [dev-dependencies] log = "0.4.11" diff --git a/alacritty_config_derive/src/config_deserialize/de_struct.rs b/alacritty_config_derive/src/config_deserialize/de_struct.rs index d2a7dd82af4..ad38863ed4c 100644 --- a/alacritty_config_derive/src/config_deserialize/de_struct.rs +++ b/alacritty_config_derive/src/config_deserialize/de_struct.rs @@ -155,6 +155,7 @@ fn field_deserializer(field_streams: &mut FieldStreams, field: &Field) -> Result if let Some(warning) = parsed.param { message = format!("{}; {}", message, warning.value()); } + message.push_str("\nUse `alacritty migrate` to automatically resolve it"); // Append stream to log deprecation/removal warning. match_assignment_stream.extend(quote! { diff --git a/alacritty_config_derive/src/serde_replace.rs b/alacritty_config_derive/src/serde_replace.rs index ddd0cf75767..cd56b3bcc95 100644 --- a/alacritty_config_derive/src/serde_replace.rs +++ b/alacritty_config_derive/src/serde_replace.rs @@ -112,11 +112,11 @@ fn match_arms(fields: &Punctuated) -> Result = OnceLock::new(); + let logger = LOGGER.get_or_init(Logger::default); log::set_logger(logger).unwrap(); log::set_max_level(log::LevelFilter::Warn); @@ -134,15 +132,16 @@ fn config_deserialize() { ]); let warn_logs = logger.warn_logs.lock().unwrap(); assert_eq!(warn_logs.as_slice(), [ - "Config warning: field1 has been deprecated; use field2 instead", - "Config warning: enom_error has been deprecated", - "Config warning: gone has been removed; it's gone", + "Config warning: field1 has been deprecated; use field2 instead\nUse `alacritty migrate` \ + to automatically resolve it", + "Config warning: enom_error has been deprecated\nUse `alacritty migrate` to automatically \ + resolve it", + "Config warning: gone has been removed; it's gone\nUse `alacritty migrate` to \ + automatically resolve it", "Unused config key: field3", ]); } -static mut LOGGER: Option = None; - /// Logger storing all messages for later validation. #[derive(Default)] struct Logger { diff --git a/alacritty_terminal/CHANGELOG.md b/alacritty_terminal/CHANGELOG.md index 82636168706..e612e7498ec 100644 --- a/alacritty_terminal/CHANGELOG.md +++ b/alacritty_terminal/CHANGELOG.md @@ -8,7 +8,19 @@ sections should follow the order `Added`, `Changed`, `Deprecated`, `Fixed` and The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). -## 0.24.1-dev +## 0.24.1 + +### Changed + +- Shell RCs are no longer sourced on macOs + +### Fixed + +- Semantic search handling of fullwidth characters +- Inline search ignoring line wrapping flag +- Clearing of `XDG_ACTIVATION_TOKEN` and `DESKTOP_STARTUP_ID` in the main process +- FD leaks when closing PTYs on Unix +- Crash when ConPTY creation failed ## 0.24.0 diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index 98c641710e1..b8c0db4c2b2 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alacritty_terminal" -version = "0.24.1-dev" +version = "0.24.1" authors = ["Christian Duerr ", "Joe Wilm "] license = "Apache-2.0" description = "Library for writing terminal emulators" @@ -8,7 +8,7 @@ readme = "../README.md" homepage = "https://alacritty.org" repository = "https://github.com/alacritty/alacritty" edition = "2021" -rust-version = "1.70.0" +rust-version = "1.74.0" [features] default = ["serde"] diff --git a/alacritty_terminal/src/grid/mod.rs b/alacritty_terminal/src/grid/mod.rs index 43302354b41..8c913de83c8 100644 --- a/alacritty_terminal/src/grid/mod.rs +++ b/alacritty_terminal/src/grid/mod.rs @@ -137,7 +137,7 @@ pub struct Grid { max_scroll_limit: usize, } -impl Grid { +impl Grid { pub fn new(lines: usize, columns: usize, max_scroll_limit: usize) -> Grid { Grid { raw: Storage::with_capacity(lines, columns), @@ -356,7 +356,7 @@ impl Grid { /// Reset a visible region within the grid. pub fn reset_region>(&mut self, bounds: R) where - T: ResetDiscriminant + GridCell + Clone + Default, + T: ResetDiscriminant + GridCell + Default, D: PartialEq, { let start = match bounds.start_bound() { @@ -392,7 +392,7 @@ impl Grid { #[inline] pub fn initialize_all(&mut self) where - T: GridCell + Clone + Default, + T: GridCell + Default, { // Remove all cached lines to clear them of any content. self.truncate(); diff --git a/alacritty_terminal/src/grid/resize.rs b/alacritty_terminal/src/grid/resize.rs index 92ee55d77db..751abae1b82 100644 --- a/alacritty_terminal/src/grid/resize.rs +++ b/alacritty_terminal/src/grid/resize.rs @@ -9,7 +9,7 @@ use crate::term::cell::{Flags, ResetDiscriminant}; use crate::grid::row::Row; use crate::grid::{Dimensions, Grid, GridCell}; -impl Grid { +impl Grid { /// Resize the grid's width and/or height. pub fn resize(&mut self, reflow: bool, lines: usize, columns: usize) where diff --git a/alacritty_terminal/src/grid/row.rs b/alacritty_terminal/src/grid/row.rs index 72f386ae282..9a7f81fb388 100644 --- a/alacritty_terminal/src/grid/row.rs +++ b/alacritty_terminal/src/grid/row.rs @@ -30,7 +30,7 @@ impl PartialEq for Row { } } -impl Row { +impl Row { /// Create a new terminal row. /// /// Ideally the `template` should be `Copy` in all performance sensitive scenarios. diff --git a/alacritty_terminal/src/grid/storage.rs b/alacritty_terminal/src/grid/storage.rs index 0a2be43b71a..abf5710347e 100644 --- a/alacritty_terminal/src/grid/storage.rs +++ b/alacritty_terminal/src/grid/storage.rs @@ -66,7 +66,7 @@ impl Storage { #[inline] pub fn with_capacity(visible_lines: usize, columns: usize) -> Storage where - T: Clone + Default, + T: Default, { // Initialize visible lines; the scrollback buffer is initialized dynamically. let mut inner = Vec::with_capacity(visible_lines); @@ -79,7 +79,7 @@ impl Storage { #[inline] pub fn grow_visible_lines(&mut self, next: usize) where - T: Clone + Default, + T: Default, { // Number of lines the buffer needs to grow. let additional_lines = next - self.visible_lines; @@ -125,7 +125,7 @@ impl Storage { #[inline] pub fn initialize(&mut self, additional_rows: usize, columns: usize) where - T: Clone + Default, + T: Default, { if self.len + additional_rows > self.inner.len() { self.rezero(); diff --git a/alacritty_terminal/src/term/cell.rs b/alacritty_terminal/src/term/cell.rs index 6b32c781abe..c91ef2f1f38 100644 --- a/alacritty_terminal/src/term/cell.rs +++ b/alacritty_terminal/src/term/cell.rs @@ -126,9 +126,7 @@ impl ResetDiscriminant for Cell { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct CellExtra { zerowidth: Vec, - underline_color: Option, - hyperlink: Option, #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))] diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 706bbe3244d..6b0ccccdf98 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -57,30 +57,30 @@ bitflags! { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TermMode: u32 { const NONE = 0; - const SHOW_CURSOR = 0b0000_0000_0000_0000_0000_0001; - const APP_CURSOR = 0b0000_0000_0000_0000_0000_0010; - const APP_KEYPAD = 0b0000_0000_0000_0000_0000_0100; - const MOUSE_REPORT_CLICK = 0b0000_0000_0000_0000_0000_1000; - const BRACKETED_PASTE = 0b0000_0000_0000_0000_0001_0000; - const SGR_MOUSE = 0b0000_0000_0000_0000_0010_0000; - const MOUSE_MOTION = 0b0000_0000_0000_0000_0100_0000; - const LINE_WRAP = 0b0000_0000_0000_0000_1000_0000; - const LINE_FEED_NEW_LINE = 0b0000_0000_0000_0001_0000_0000; - const ORIGIN = 0b0000_0000_0000_0010_0000_0000; - const INSERT = 0b0000_0000_0000_0100_0000_0000; - const FOCUS_IN_OUT = 0b0000_0000_0000_1000_0000_0000; - const ALT_SCREEN = 0b0000_0000_0001_0000_0000_0000; - const MOUSE_DRAG = 0b0000_0000_0010_0000_0000_0000; - const MOUSE_MODE = 0b0000_0000_0010_0000_0100_1000; - const UTF8_MOUSE = 0b0000_0000_0100_0000_0000_0000; - const ALTERNATE_SCROLL = 0b0000_0000_1000_0000_0000_0000; - const VI = 0b0000_0001_0000_0000_0000_0000; - const URGENCY_HINTS = 0b0000_0010_0000_0000_0000_0000; - const DISAMBIGUATE_ESC_CODES = 0b0000_0100_0000_0000_0000_0000; - const REPORT_EVENT_TYPES = 0b0000_1000_0000_0000_0000_0000; - const REPORT_ALTERNATE_KEYS = 0b0001_0000_0000_0000_0000_0000; - const REPORT_ALL_KEYS_AS_ESC = 0b0010_0000_0000_0000_0000_0000; - const REPORT_ASSOCIATED_TEXT = 0b0100_0000_0000_0000_0000_0000; + const SHOW_CURSOR = 1; + const APP_CURSOR = 1 << 1; + const APP_KEYPAD = 1 << 2; + const MOUSE_REPORT_CLICK = 1 << 3; + const BRACKETED_PASTE = 1 << 4; + const SGR_MOUSE = 1 << 5; + const MOUSE_MOTION = 1 << 6; + const LINE_WRAP = 1 << 7; + const LINE_FEED_NEW_LINE = 1 << 8; + const ORIGIN = 1 << 9; + const INSERT = 1 << 10; + const FOCUS_IN_OUT = 1 << 11; + const ALT_SCREEN = 1 << 12; + const MOUSE_DRAG = 1 << 13; + const UTF8_MOUSE = 1 << 14; + const ALTERNATE_SCROLL = 1 << 15; + const VI = 1 << 16; + const URGENCY_HINTS = 1 << 17; + const DISAMBIGUATE_ESC_CODES = 1 << 18; + const REPORT_EVENT_TYPES = 1 << 19; + const REPORT_ALTERNATE_KEYS = 1 << 20; + const REPORT_ALL_KEYS_AS_ESC = 1 << 21; + const REPORT_ASSOCIATED_TEXT = 1 << 22; + const MOUSE_MODE = Self::MOUSE_REPORT_CLICK.bits() | Self::MOUSE_MOTION.bits() | Self::MOUSE_DRAG.bits(); const KITTY_KEYBOARD_PROTOCOL = Self::DISAMBIGUATE_ESC_CODES.bits() | Self::REPORT_EVENT_TYPES.bits() | Self::REPORT_ALTERNATE_KEYS.bits() diff --git a/alacritty_terminal/src/term/search.rs b/alacritty_terminal/src/term/search.rs index a5ae9337a96..33f6ee056b5 100644 --- a/alacritty_terminal/src/term/search.rs +++ b/alacritty_terminal/src/term/search.rs @@ -516,7 +516,14 @@ impl Term { #[must_use] pub fn semantic_search_left(&self, point: Point) -> Point { match self.inline_search_left(point, self.semantic_escape_chars()) { - Ok(point) => self.grid.iter_from(point).next().map_or(point, |cell| cell.point), + // If we found a match, reverse for at least one cell, skipping over wide cell spacers. + Ok(point) => { + let wide_spacer = Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; + self.grid + .iter_from(point) + .find(|cell| !cell.flags.intersects(wide_spacer)) + .map_or(point, |cell| cell.point) + }, Err(point) => point, } } @@ -538,7 +545,7 @@ impl Term { let mut iter = self.grid.iter_from(point); let last_column = self.columns() - 1; - let wide = Flags::WIDE_CHAR | Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; + let wide_spacer = Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; while let Some(cell) = iter.prev() { if cell.point.column == last_column && !cell.flags.contains(Flags::WRAPLINE) { break; @@ -546,7 +553,7 @@ impl Term { point = cell.point; - if !cell.flags.intersects(wide) && needles.contains(cell.c) { + if !cell.flags.intersects(wide_spacer) && needles.contains(cell.c) { return Ok(point); } } @@ -559,7 +566,7 @@ impl Term { // Limit the starting point to the last line in the history point.line = max(point.line, self.topmost_line()); - let wide = Flags::WIDE_CHAR | Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; + let wide_spacer = Flags::WIDE_CHAR_SPACER | Flags::LEADING_WIDE_CHAR_SPACER; let last_column = self.columns() - 1; // Immediately stop if start point in on line break. @@ -570,7 +577,7 @@ impl Term { for cell in self.grid.iter_from(point) { point = cell.point; - if !cell.flags.intersects(wide) && needles.contains(cell.c) { + if !cell.flags.intersects(wide_spacer) && needles.contains(cell.c) { return Ok(point); } @@ -1171,4 +1178,16 @@ mod tests { let match_end = Point::new(Line(1), Column(2)); assert_eq!(term.regex_search_left(&mut regex, start, end), Some(match_start..=match_end)); } + + #[test] + fn fullwidth_semantic() { + #[rustfmt::skip] + let mut term = mock_term("test-x-test"); + term.config.semantic_escape_chars = "-".into(); + + let start = term.semantic_search_left(Point::new(Line(0), Column(6))); + let end = term.semantic_search_right(Point::new(Line(0), Column(6))); + assert_eq!(start, Point::new(Line(0), Column(6))); + assert_eq!(end, Point::new(Line(0), Column(6))); + } } diff --git a/alacritty_terminal/src/tty/mod.rs b/alacritty_terminal/src/tty/mod.rs index 55d263ca5b1..eed2a76dc28 100644 --- a/alacritty_terminal/src/tty/mod.rs +++ b/alacritty_terminal/src/tty/mod.rs @@ -50,9 +50,10 @@ impl Shell { } } -/// This trait defines the behaviour needed to read and/or write to a stream. -/// It defines an abstraction over polling's interface in order to allow either one -/// read/write object or a separate read and write object. +/// Stream read and/or write behavior. +/// +/// This defines an abstraction over polling's interface in order to allow either +/// one read/write object or a separate read and write object. pub trait EventedReadWrite { type Reader: io::Read; type Writer: io::Write; @@ -97,10 +98,6 @@ pub fn setup_env() { // Advertise 24-bit color support. env::set_var("COLORTERM", "truecolor"); - - // Prevent child processes from inheriting startup notification env. - env::remove_var("DESKTOP_STARTUP_ID"); - env::remove_var("XDG_ACTIVATION_TOKEN"); } /// Check if a terminfo entry exists on the system. diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 8084a753b23..6565f20b8d9 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -227,6 +227,10 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd builder.env(key, value); } + // Prevent child processes from inheriting linux-specific startup notification env. + builder.env_remove("XDG_ACTIVATION_TOKEN"); + builder.env_remove("DESKTOP_STARTUP_ID"); + unsafe { builder.pre_exec(move || { // Create a new process group. diff --git a/alacritty_terminal/src/tty/windows/conpty.rs b/alacritty_terminal/src/tty/windows/conpty.rs index 244681e7c9f..28289f90e11 100644 --- a/alacritty_terminal/src/tty/windows/conpty.rs +++ b/alacritty_terminal/src/tty/windows/conpty.rs @@ -1,7 +1,7 @@ use log::{info, warn}; use std::collections::{HashMap, HashSet}; use std::ffi::OsStr; -use std::io::Error; +use std::io::{Error, Result}; use std::os::windows::ffi::OsStrExt; use std::os::windows::io::IntoRawHandle; use std::{mem, ptr}; @@ -107,7 +107,7 @@ impl Drop for Conpty { // The ConPTY handle can be sent between threads. unsafe impl Send for Conpty {} -pub fn new(config: &Options, window_size: WindowSize) -> Option { +pub fn new(config: &Options, window_size: WindowSize) -> Result { let api = ConptyApi::new(); let mut pty_handle: HPCON = 0; @@ -115,8 +115,8 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { // size to be used. There may be small performance and memory advantages // to be gained by tuning this in the future, but it's likely a reasonable // start point. - let (conout, conout_pty_handle) = miow::pipe::anonymous(0).unwrap(); - let (conin_pty_handle, conin) = miow::pipe::anonymous(0).unwrap(); + let (conout, conout_pty_handle) = miow::pipe::anonymous(0)?; + let (conin_pty_handle, conin) = miow::pipe::anonymous(0)?; // Create the Pseudo Console, using the pipes. let result = unsafe { @@ -154,7 +154,7 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { // This call was expected to return false. if failure { - panic_shell_spawn(); + return Err(Error::last_os_error()); } } @@ -180,7 +180,7 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { ) > 0; if !success { - panic_shell_spawn(); + return Err(Error::last_os_error()); } } @@ -197,7 +197,7 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { ) > 0; if !success { - panic_shell_spawn(); + return Err(Error::last_os_error()); } } @@ -230,17 +230,17 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { ) > 0; if !success { - panic_shell_spawn(); + return Err(Error::last_os_error()); } } let conin = UnblockedWriter::new(conin, PIPE_CAPACITY); let conout = UnblockedReader::new(conout, PIPE_CAPACITY); - let child_watcher = ChildExitWatcher::new(proc_info.hProcess).unwrap(); + let child_watcher = ChildExitWatcher::new(proc_info.hProcess)?; let conpty = Conpty { handle: pty_handle as HPCON, api }; - Some(Pty::new(conpty, conout, conin, child_watcher)) + Ok(Pty::new(conpty, conout, conin, child_watcher)) } // Windows environment variables are case-insensitive, and the caller is responsible for @@ -300,11 +300,6 @@ fn add_windows_env_key_value_to_block(block: &mut Vec, key: &OsStr, value: block.push(0); } -// Panic with the last os error as message. -fn panic_shell_spawn() { - panic!("Unable to spawn shell: {}", Error::last_os_error()); -} - impl OnResize for Conpty { fn on_resize(&mut self, window_size: WindowSize) { let result = unsafe { (self.api.resize)(self.handle, window_size.into()) }; diff --git a/alacritty_terminal/src/tty/windows/mod.rs b/alacritty_terminal/src/tty/windows/mod.rs index 6af162c83df..32e24677013 100644 --- a/alacritty_terminal/src/tty/windows/mod.rs +++ b/alacritty_terminal/src/tty/windows/mod.rs @@ -1,5 +1,5 @@ use std::ffi::OsStr; -use std::io::{self, Error, ErrorKind, Result}; +use std::io::{self, Result}; use std::iter::once; use std::os::windows::ffi::OsStrExt; use std::sync::mpsc::TryRecvError; @@ -35,7 +35,6 @@ pub struct Pty { pub fn new(config: &Options, window_size: WindowSize, _window_id: u64) -> Result { conpty::new(config, window_size) - .ok_or_else(|| Error::new(ErrorKind::Other, "failed to spawn conpty")) } impl Pty { diff --git a/extra/completions/_alacritty b/extra/completions/_alacritty index a510fb15f6f..0ccce66fbc0 100644 --- a/extra/completions/_alacritty +++ b/extra/completions/_alacritty @@ -14,7 +14,7 @@ _alacritty() { fi local context curcontext="$curcontext" state line - _arguments "${_arguments_options[@]}" \ + _arguments "${_arguments_options[@]}" : \ '--embed=[X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix)]:EMBED: ' \ '--config-file=[Specify alternative configuration file \[default\: \$XDG_CONFIG_HOME/alacritty/alacritty.toml\]]:CONFIG_FILE:_files' \ '--socket=[Path for IPC socket creation]:SOCKET:_files' \ @@ -27,9 +27,10 @@ _alacritty() { '*-o+[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION: ' \ '*--option=[Override configuration file options \[example\: '\''cursor.style="Beam"'\''\]]:OPTION: ' \ '--print-events[Print all events to STDOUT]' \ -'--ref-test[Generates ref test]' \ +'(--daemon)--ref-test[Generates ref test]' \ '(-v)*-q[Reduces the level of verbosity (the min level is -qq)]' \ '(-q)*-v[Increases the level of verbosity (the max level is -vvv)]' \ +'--daemon[Do not spawn an initial window]' \ '--hold[Remain open after child process exit]' \ '-h[Print help]' \ '--help[Print help]' \ @@ -45,7 +46,7 @@ _alacritty() { curcontext="${curcontext%:*:*}:alacritty-command-$line[1]:" case $line[1] in (msg) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '-s+[IPC socket connection path override]:SOCKET:_files' \ '--socket=[IPC socket connection path override]:SOCKET:_files' \ '-h[Print help]' \ @@ -61,7 +62,7 @@ _arguments "${_arguments_options[@]}" \ curcontext="${curcontext%:*:*}:alacritty-msg-command-$line[1]:" case $line[1] in (create-window) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '--working-directory=[Start the shell in the specified working directory]:WORKING_DIRECTORY:_files' \ '*-e+[Command and args to execute (must be last argument)]:COMMAND: ' \ '*--command=[Command and args to execute (must be last argument)]:COMMAND: ' \ @@ -76,7 +77,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (config) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '-w+[Window ID for the new config]:WINDOW_ID: ' \ '--window-id=[Window ID for the new config]:WINDOW_ID: ' \ '()-r[Clear all runtime configuration changes]' \ @@ -87,7 +88,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (help) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ ":: :_alacritty__msg__help_commands" \ "*::: :->help" \ && ret=0 @@ -99,15 +100,15 @@ _arguments "${_arguments_options[@]}" \ curcontext="${curcontext%:*:*}:alacritty-msg-help-command-$line[1]:" case $line[1] in (create-window) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ && ret=0 ;; (config) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ && ret=0 ;; (help) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ && ret=0 ;; esac @@ -119,7 +120,7 @@ esac esac ;; (migrate) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ '-c+[Path to the configuration file]:CONFIG_FILE:_files' \ '--config-file=[Path to the configuration file]:CONFIG_FILE:_files' \ '-d[Only output TOML config to STDOUT]' \ @@ -134,7 +135,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (help) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ ":: :_alacritty__help_commands" \ "*::: :->help" \ && ret=0 @@ -146,7 +147,7 @@ _arguments "${_arguments_options[@]}" \ curcontext="${curcontext%:*:*}:alacritty-help-command-$line[1]:" case $line[1] in (msg) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ ":: :_alacritty__help__msg_commands" \ "*::: :->msg" \ && ret=0 @@ -158,11 +159,11 @@ _arguments "${_arguments_options[@]}" \ curcontext="${curcontext%:*:*}:alacritty-help-msg-command-$line[1]:" case $line[1] in (create-window) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ && ret=0 ;; (config) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ && ret=0 ;; esac @@ -170,11 +171,11 @@ _arguments "${_arguments_options[@]}" \ esac ;; (migrate) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ && ret=0 ;; (help) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ && ret=0 ;; esac @@ -195,36 +196,6 @@ _alacritty_commands() { ) _describe -t commands 'alacritty commands' commands "$@" } -(( $+functions[_alacritty__help__msg__config_commands] )) || -_alacritty__help__msg__config_commands() { - local commands; commands=() - _describe -t commands 'alacritty help msg config commands' commands "$@" -} -(( $+functions[_alacritty__msg__config_commands] )) || -_alacritty__msg__config_commands() { - local commands; commands=() - _describe -t commands 'alacritty msg config commands' commands "$@" -} -(( $+functions[_alacritty__msg__help__config_commands] )) || -_alacritty__msg__help__config_commands() { - local commands; commands=() - _describe -t commands 'alacritty msg help config commands' commands "$@" -} -(( $+functions[_alacritty__help__msg__create-window_commands] )) || -_alacritty__help__msg__create-window_commands() { - local commands; commands=() - _describe -t commands 'alacritty help msg create-window commands' commands "$@" -} -(( $+functions[_alacritty__msg__create-window_commands] )) || -_alacritty__msg__create-window_commands() { - local commands; commands=() - _describe -t commands 'alacritty msg create-window commands' commands "$@" -} -(( $+functions[_alacritty__msg__help__create-window_commands] )) || -_alacritty__msg__help__create-window_commands() { - local commands; commands=() - _describe -t commands 'alacritty msg help create-window commands' commands "$@" -} (( $+functions[_alacritty__help_commands] )) || _alacritty__help_commands() { local commands; commands=( @@ -239,46 +210,76 @@ _alacritty__help__help_commands() { local commands; commands=() _describe -t commands 'alacritty help help commands' commands "$@" } -(( $+functions[_alacritty__msg__help_commands] )) || -_alacritty__msg__help_commands() { +(( $+functions[_alacritty__help__migrate_commands] )) || +_alacritty__help__migrate_commands() { + local commands; commands=() + _describe -t commands 'alacritty help migrate commands' commands "$@" +} +(( $+functions[_alacritty__help__msg_commands] )) || +_alacritty__help__msg_commands() { local commands; commands=( 'create-window:Create a new window in the same Alacritty process' \ 'config:Update the Alacritty configuration' \ -'help:Print this message or the help of the given subcommand(s)' \ ) - _describe -t commands 'alacritty msg help commands' commands "$@" + _describe -t commands 'alacritty help msg commands' commands "$@" } -(( $+functions[_alacritty__msg__help__help_commands] )) || -_alacritty__msg__help__help_commands() { +(( $+functions[_alacritty__help__msg__config_commands] )) || +_alacritty__help__msg__config_commands() { local commands; commands=() - _describe -t commands 'alacritty msg help help commands' commands "$@" + _describe -t commands 'alacritty help msg config commands' commands "$@" } -(( $+functions[_alacritty__help__migrate_commands] )) || -_alacritty__help__migrate_commands() { +(( $+functions[_alacritty__help__msg__create-window_commands] )) || +_alacritty__help__msg__create-window_commands() { local commands; commands=() - _describe -t commands 'alacritty help migrate commands' commands "$@" + _describe -t commands 'alacritty help msg create-window commands' commands "$@" } (( $+functions[_alacritty__migrate_commands] )) || _alacritty__migrate_commands() { local commands; commands=() _describe -t commands 'alacritty migrate commands' commands "$@" } -(( $+functions[_alacritty__help__msg_commands] )) || -_alacritty__help__msg_commands() { +(( $+functions[_alacritty__msg_commands] )) || +_alacritty__msg_commands() { local commands; commands=( 'create-window:Create a new window in the same Alacritty process' \ 'config:Update the Alacritty configuration' \ +'help:Print this message or the help of the given subcommand(s)' \ ) - _describe -t commands 'alacritty help msg commands' commands "$@" + _describe -t commands 'alacritty msg commands' commands "$@" } -(( $+functions[_alacritty__msg_commands] )) || -_alacritty__msg_commands() { +(( $+functions[_alacritty__msg__config_commands] )) || +_alacritty__msg__config_commands() { + local commands; commands=() + _describe -t commands 'alacritty msg config commands' commands "$@" +} +(( $+functions[_alacritty__msg__create-window_commands] )) || +_alacritty__msg__create-window_commands() { + local commands; commands=() + _describe -t commands 'alacritty msg create-window commands' commands "$@" +} +(( $+functions[_alacritty__msg__help_commands] )) || +_alacritty__msg__help_commands() { local commands; commands=( 'create-window:Create a new window in the same Alacritty process' \ 'config:Update the Alacritty configuration' \ 'help:Print this message or the help of the given subcommand(s)' \ ) - _describe -t commands 'alacritty msg commands' commands "$@" + _describe -t commands 'alacritty msg help commands' commands "$@" +} +(( $+functions[_alacritty__msg__help__config_commands] )) || +_alacritty__msg__help__config_commands() { + local commands; commands=() + _describe -t commands 'alacritty msg help config commands' commands "$@" +} +(( $+functions[_alacritty__msg__help__create-window_commands] )) || +_alacritty__msg__help__create-window_commands() { + local commands; commands=() + _describe -t commands 'alacritty msg help create-window commands' commands "$@" +} +(( $+functions[_alacritty__msg__help__help_commands] )) || +_alacritty__msg__help__help_commands() { + local commands; commands=() + _describe -t commands 'alacritty msg help help commands' commands "$@" } if [ "$funcstack[1]" = "_alacritty" ]; then diff --git a/extra/completions/alacritty.bash b/extra/completions/alacritty.bash index c1546f500a9..e2213b75799 100644 --- a/extra/completions/alacritty.bash +++ b/extra/completions/alacritty.bash @@ -61,7 +61,7 @@ _alacritty() { case "${cmd}" in alacritty) - opts="-q -v -e -T -o -h -V --print-events --ref-test --embed --config-file --socket --working-directory --hold --command --title --class --option --help --version msg migrate help" + opts="-q -v -e -T -o -h -V --print-events --ref-test --embed --config-file --socket --daemon --working-directory --hold --command --title --class --option --help --version msg migrate help" if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -72,15 +72,48 @@ _alacritty() { return 0 ;; --config-file) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --socket) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --working-directory) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --command) @@ -210,11 +243,33 @@ _alacritty() { fi case "${prev}" in --config-file) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; -c) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; *) @@ -232,11 +287,33 @@ _alacritty() { fi case "${prev}" in --socket) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; -s) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; *) @@ -276,7 +353,18 @@ _alacritty() { fi case "${prev}" in --working-directory) + local oldifs + if [ -n "${IFS+x}" ]; then + oldifs="$IFS" + fi + IFS=$'\n' COMPREPLY=($(compgen -f "${cur}")) + if [ -n "${oldifs+x}" ]; then + IFS="$oldifs" + fi + if [[ "${BASH_VERSINFO[0]}" -ge 4 ]]; then + compopt -o filenames + fi return 0 ;; --command) @@ -373,4 +461,8 @@ _alacritty() { esac } -complete -F _alacritty -o nosort -o bashdefault -o default alacritty +if [[ "${BASH_VERSINFO[0]}" -eq 4 && "${BASH_VERSINFO[1]}" -ge 4 || "${BASH_VERSINFO[0]}" -gt 4 ]]; then + complete -F _alacritty -o nosort -o bashdefault -o default alacritty +else + complete -F _alacritty -o bashdefault -o default alacritty +fi diff --git a/extra/completions/alacritty.fish b/extra/completions/alacritty.fish index 72609f70ad6..7cfc333767b 100644 --- a/extra/completions/alacritty.fish +++ b/extra/completions/alacritty.fish @@ -1,47 +1,74 @@ -complete -c alacritty -n "__fish_use_subcommand" -l embed -d 'X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix)' -r -complete -c alacritty -n "__fish_use_subcommand" -l config-file -d 'Specify alternative configuration file [default: $XDG_CONFIG_HOME/alacritty/alacritty.toml]' -r -F -complete -c alacritty -n "__fish_use_subcommand" -l socket -d 'Path for IPC socket creation' -r -F -complete -c alacritty -n "__fish_use_subcommand" -l working-directory -d 'Start the shell in the specified working directory' -r -F -complete -c alacritty -n "__fish_use_subcommand" -s e -l command -d 'Command and args to execute (must be last argument)' -r -complete -c alacritty -n "__fish_use_subcommand" -s T -l title -d 'Defines the window title [default: Alacritty]' -r -complete -c alacritty -n "__fish_use_subcommand" -l class -d 'Defines window class/app_id on X11/Wayland [default: Alacritty]' -r -complete -c alacritty -n "__fish_use_subcommand" -s o -l option -d 'Override configuration file options [example: \'cursor.style="Beam"\']' -r -complete -c alacritty -n "__fish_use_subcommand" -l print-events -d 'Print all events to STDOUT' -complete -c alacritty -n "__fish_use_subcommand" -l ref-test -d 'Generates ref test' -complete -c alacritty -n "__fish_use_subcommand" -s q -d 'Reduces the level of verbosity (the min level is -qq)' -complete -c alacritty -n "__fish_use_subcommand" -s v -d 'Increases the level of verbosity (the max level is -vvv)' -complete -c alacritty -n "__fish_use_subcommand" -l hold -d 'Remain open after child process exit' -complete -c alacritty -n "__fish_use_subcommand" -s h -l help -d 'Print help' -complete -c alacritty -n "__fish_use_subcommand" -s V -l version -d 'Print version' -complete -c alacritty -n "__fish_use_subcommand" -f -a "msg" -d 'Send a message to the Alacritty socket' -complete -c alacritty -n "__fish_use_subcommand" -f -a "migrate" -d 'Migrate the configuration file' -complete -c alacritty -n "__fish_use_subcommand" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -s s -l socket -d 'IPC socket connection path override' -r -F -complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -s h -l help -d 'Print help' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "create-window" -d 'Create a new window in the same Alacritty process' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "config" -d 'Update the Alacritty configuration' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -l working-directory -d 'Start the shell in the specified working directory' -r -F -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -s e -l command -d 'Command and args to execute (must be last argument)' -r -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -s T -l title -d 'Defines the window title [default: Alacritty]' -r -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -l class -d 'Defines window class/app_id on X11/Wayland [default: Alacritty]' -r -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -s o -l option -d 'Override configuration file options [example: \'cursor.style="Beam"\']' -r -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -l hold -d 'Remain open after child process exit' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from create-window" -s h -l help -d 'Print help' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from config" -s w -l window-id -d 'Window ID for the new config' -r -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from config" -s r -l reset -d 'Clear all runtime configuration changes' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from config" -s h -l help -d 'Print help (see more with \'--help\')' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "create-window" -d 'Create a new window in the same Alacritty process' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "config" -d 'Update the Alacritty configuration' -complete -c alacritty -n "__fish_seen_subcommand_from msg; and __fish_seen_subcommand_from help; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' -complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s c -l config-file -d 'Path to the configuration file' -r -F -complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s d -l dry-run -d 'Only output TOML config to STDOUT' -complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s i -l skip-imports -d 'Do not recurse over imports' -complete -c alacritty -n "__fish_seen_subcommand_from migrate" -l skip-renames -d 'Do not move renamed fields to their new location' -complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s s -l silent -d 'Do not output to STDOUT' -complete -c alacritty -n "__fish_seen_subcommand_from migrate" -s h -l help -d 'Print help' -complete -c alacritty -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from migrate; and not __fish_seen_subcommand_from help" -f -a "msg" -d 'Send a message to the Alacritty socket' -complete -c alacritty -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from migrate; and not __fish_seen_subcommand_from help" -f -a "migrate" -d 'Migrate the configuration file' -complete -c alacritty -n "__fish_seen_subcommand_from help; and not __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from migrate; and not __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' -complete -c alacritty -n "__fish_seen_subcommand_from help; and __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config" -f -a "create-window" -d 'Create a new window in the same Alacritty process' -complete -c alacritty -n "__fish_seen_subcommand_from help; and __fish_seen_subcommand_from msg; and not __fish_seen_subcommand_from create-window; and not __fish_seen_subcommand_from config" -f -a "config" -d 'Update the Alacritty configuration' +# Print an optspec for argparse to handle cmd's options that are independent of any subcommand. +function __fish_alacritty_global_optspecs + string join \n print-events ref-test embed= config-file= socket= q v daemon working-directory= hold e/command= T/title= class= o/option= h/help V/version +end + +function __fish_alacritty_needs_command + # Figure out if the current invocation already has a command. + set -l cmd (commandline -opc) + set -e cmd[1] + argparse -s (__fish_alacritty_global_optspecs) -- $cmd 2>/dev/null + or return + if set -q argv[1] + # Also print the command, so this can be used to figure out what it is. + echo $argv[1] + return 1 + end + return 0 +end + +function __fish_alacritty_using_subcommand + set -l cmd (__fish_alacritty_needs_command) + test -z "$cmd" + and return 1 + contains -- $cmd[1] $argv +end + +complete -c alacritty -n "__fish_alacritty_needs_command" -l embed -d 'X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix)' -r +complete -c alacritty -n "__fish_alacritty_needs_command" -l config-file -d 'Specify alternative configuration file [default: $XDG_CONFIG_HOME/alacritty/alacritty.toml]' -r -F +complete -c alacritty -n "__fish_alacritty_needs_command" -l socket -d 'Path for IPC socket creation' -r -F +complete -c alacritty -n "__fish_alacritty_needs_command" -l working-directory -d 'Start the shell in the specified working directory' -r -F +complete -c alacritty -n "__fish_alacritty_needs_command" -s e -l command -d 'Command and args to execute (must be last argument)' -r +complete -c alacritty -n "__fish_alacritty_needs_command" -s T -l title -d 'Defines the window title [default: Alacritty]' -r +complete -c alacritty -n "__fish_alacritty_needs_command" -l class -d 'Defines window class/app_id on X11/Wayland [default: Alacritty]' -r +complete -c alacritty -n "__fish_alacritty_needs_command" -s o -l option -d 'Override configuration file options [example: \'cursor.style="Beam"\']' -r +complete -c alacritty -n "__fish_alacritty_needs_command" -l print-events -d 'Print all events to STDOUT' +complete -c alacritty -n "__fish_alacritty_needs_command" -l ref-test -d 'Generates ref test' +complete -c alacritty -n "__fish_alacritty_needs_command" -s q -d 'Reduces the level of verbosity (the min level is -qq)' +complete -c alacritty -n "__fish_alacritty_needs_command" -s v -d 'Increases the level of verbosity (the max level is -vvv)' +complete -c alacritty -n "__fish_alacritty_needs_command" -l daemon -d 'Do not spawn an initial window' +complete -c alacritty -n "__fish_alacritty_needs_command" -l hold -d 'Remain open after child process exit' +complete -c alacritty -n "__fish_alacritty_needs_command" -s h -l help -d 'Print help' +complete -c alacritty -n "__fish_alacritty_needs_command" -s V -l version -d 'Print version' +complete -c alacritty -n "__fish_alacritty_needs_command" -f -a "msg" -d 'Send a message to the Alacritty socket' +complete -c alacritty -n "__fish_alacritty_needs_command" -f -a "migrate" -d 'Migrate the configuration file' +complete -c alacritty -n "__fish_alacritty_needs_command" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and not __fish_seen_subcommand_from create-window config help" -s s -l socket -d 'IPC socket connection path override' -r -F +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and not __fish_seen_subcommand_from create-window config help" -s h -l help -d 'Print help' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and not __fish_seen_subcommand_from create-window config help" -f -a "create-window" -d 'Create a new window in the same Alacritty process' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and not __fish_seen_subcommand_from create-window config help" -f -a "config" -d 'Update the Alacritty configuration' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and not __fish_seen_subcommand_from create-window config help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from create-window" -l working-directory -d 'Start the shell in the specified working directory' -r -F +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from create-window" -s e -l command -d 'Command and args to execute (must be last argument)' -r +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from create-window" -s T -l title -d 'Defines the window title [default: Alacritty]' -r +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from create-window" -l class -d 'Defines window class/app_id on X11/Wayland [default: Alacritty]' -r +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from create-window" -s o -l option -d 'Override configuration file options [example: \'cursor.style="Beam"\']' -r +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from create-window" -l hold -d 'Remain open after child process exit' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from create-window" -s h -l help -d 'Print help' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from config" -s w -l window-id -d 'Window ID for the new config' -r +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from config" -s r -l reset -d 'Clear all runtime configuration changes' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from config" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from help" -f -a "create-window" -d 'Create a new window in the same Alacritty process' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from help" -f -a "config" -d 'Update the Alacritty configuration' +complete -c alacritty -n "__fish_alacritty_using_subcommand msg; and __fish_seen_subcommand_from help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' +complete -c alacritty -n "__fish_alacritty_using_subcommand migrate" -s c -l config-file -d 'Path to the configuration file' -r -F +complete -c alacritty -n "__fish_alacritty_using_subcommand migrate" -s d -l dry-run -d 'Only output TOML config to STDOUT' +complete -c alacritty -n "__fish_alacritty_using_subcommand migrate" -s i -l skip-imports -d 'Do not recurse over imports' +complete -c alacritty -n "__fish_alacritty_using_subcommand migrate" -l skip-renames -d 'Do not move renamed fields to their new location' +complete -c alacritty -n "__fish_alacritty_using_subcommand migrate" -s s -l silent -d 'Do not output to STDOUT' +complete -c alacritty -n "__fish_alacritty_using_subcommand migrate" -s h -l help -d 'Print help' +complete -c alacritty -n "__fish_alacritty_using_subcommand help; and not __fish_seen_subcommand_from msg migrate help" -f -a "msg" -d 'Send a message to the Alacritty socket' +complete -c alacritty -n "__fish_alacritty_using_subcommand help; and not __fish_seen_subcommand_from msg migrate help" -f -a "migrate" -d 'Migrate the configuration file' +complete -c alacritty -n "__fish_alacritty_using_subcommand help; and not __fish_seen_subcommand_from msg migrate help" -f -a "help" -d 'Print this message or the help of the given subcommand(s)' +complete -c alacritty -n "__fish_alacritty_using_subcommand help; and __fish_seen_subcommand_from msg" -f -a "create-window" -d 'Create a new window in the same Alacritty process' +complete -c alacritty -n "__fish_alacritty_using_subcommand help; and __fish_seen_subcommand_from msg" -f -a "config" -d 'Update the Alacritty configuration' diff --git a/extra/logo/alacritty-term.svg b/extra/logo/alacritty-term.svg index 065df5387c8..9798a3df9ec 100644 --- a/extra/logo/alacritty-term.svg +++ b/extra/logo/alacritty-term.svg @@ -423,7 +423,6 @@ transform="translate(-16,35.820639)" sodipodi:insensitive="true"> \ No newline at end of file + sodipodi:nodetypes="cccc" /> diff --git a/extra/man/alacritty-bindings.5.scd b/extra/man/alacritty-bindings.5.scd index 3de2986ee89..7f0bdf34ea3 100644 --- a/extra/man/alacritty-bindings.5.scd +++ b/extra/man/alacritty-bindings.5.scd @@ -2,7 +2,7 @@ ALACRITTY-BINDINGS(5) # NAME -Alacritty Bindings - Default configuration file bindings. +alacritty-bindings - Default configuration file bindings. # SYNOPSIS diff --git a/extra/man/alacritty.1.scd b/extra/man/alacritty.1.scd index b82ba08e326..86630a65306 100644 --- a/extra/man/alacritty.1.scd +++ b/extra/man/alacritty.1.scd @@ -21,6 +21,10 @@ set of features with high performance. Remain open after child process exits. +*--daemon* + + Do not spawn an initial window. + *--print-events* Print all events to STDOUT. @@ -61,13 +65,17 @@ set of features with high performance. Specify alternative configuration file. - Alacritty looks for the configuration file at the following paths: + Alacritty doesn't create the config file for you, but it looks for one in the + following locations on UNIX systems: + . _$XDG_CONFIG_HOME/alacritty/alacritty.toml_ . _$XDG_CONFIG_HOME/alacritty.toml_ . _$HOME/.config/alacritty/alacritty.toml_ . _$HOME/.alacritty.toml_ - On Windows, the configuration file is located at _%APPDATA%\\alacritty\\alacritty.toml_. + On Windows, the config file will be looked for in: + + . _%APPDATA%\\alacritty\\alacritty.toml_ *--embed* __ diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index 15bc2127690..8e92734ad89 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -14,18 +14,18 @@ can be found at _https://toml.io/en/v1.0.0_. Alacritty doesn't create the config file for you, but it looks for one in the following locations on UNIX systems: -. `$XDG_CONFIG_HOME/alacritty/alacritty.toml` -. `$XDG_CONFIG_HOME/alacritty.toml` -. `$HOME/.config/alacritty/alacritty.toml` -. `$HOME/.alacritty.toml` +. _$XDG_CONFIG_HOME/alacritty/alacritty.toml_ +. _$XDG_CONFIG_HOME/alacritty.toml_ +. _$HOME/.config/alacritty/alacritty.toml_ +. _$HOME/.alacritty.toml_ On Windows, the config file will be looked for in: -. `%APPDATA%\alacritty\alacritty.toml` +. _%APPDATA%\\alacritty\\alacritty.toml_ # GENERAL -This section documents the root level of the configuration file. +This section documents the *[general]* table of the configuration file. *import* = [_""_,] @@ -46,20 +46,6 @@ This section documents the root level of the configuration file. _"alacritty-theme/themes/gruvbox_dark.toml"_,++ ] -*shell* = _""_ | { program = _""_, args = [_""_,] } - - You can set _shell.program_ to the path of your favorite shell, e.g. - _/bin/zsh_. Entries in _shell.args_ are passed as arguments to the shell. - - Default: - Linux/BSD/macOS: _$SHELL_ or the user's login shell, if _$SHELL_ is unset++ -Windows: _"powershell"_ - - Example: - *[shell]*++ -program = _"/bin/zsh"_++ -args = [_"-l"_] - *working_directory* = _""_ | _"None"_ Directory the shell is started in. When this is unset, or _"None"_, the @@ -104,7 +90,7 @@ This section documents the *[window]* table of the configuration file. Default: { columns = _0_, lines = _0_ } -*position* = _"None"_ | { x = __, y = __ } +*position* = _"None"_ | { x = __, y = __ } # _(has no effect on Wayland)_ Window startup position. @@ -197,13 +183,13 @@ This section documents the *[window]* table of the configuration file. Default: _"None"_ -*resize_increments* = _true_ | _false_ +*resize_increments* = _true_ | _false_ # _(works on macOS/X11)_ Prefer resizing window by discrete steps equal to cell dimensions. Default: _false_ -*option_as_alt* = _"OnlyLeft"_ | _"OnlyRight"_ | _"Both"_ | _"None"_ # _(macos only)_ +*option_as_alt* = _"OnlyLeft"_ | _"OnlyRight"_ | _"Both"_ | _"None"_ # _(macOS only)_ Make _Option_ key behave as _Alt_. @@ -605,6 +591,20 @@ This section documents the *[cursor]* table of the configuration file. This section documents the *[terminal]* table of the configuration file. +*shell* = _""_ | { program = _""_, args = [_""_,] } + + You can set _shell.program_ to the path of your favorite shell, e.g. + _/bin/zsh_. Entries in _shell.args_ are passed as arguments to the shell. + + Default: + Linux/BSD/macOS: _$SHELL_ or the user's login shell, if _$SHELL_ is unset++ +Windows: _"powershell"_ + + Example: + *[shell]*++ +program = _"/bin/zsh"_++ +args = [_"-l"_] + *osc52* = _"Disabled"_ | _"OnlyCopy"_ | _"OnlyPaste"_ | _"CopyPaste"_ Controls the ability to write to the system clipboard with the _OSC 52_ @@ -730,7 +730,7 @@ hyperlinks = _true_++ post_processing = _true_++ persist = _false_++ mouse.enabled = _true_++ -binding = { key = _"U"_, mods = _"Control|Shift"_ }++ +binding = { key = _"O"_, mods = _"Control|Shift"_ }++ regex = _"(ipfs:|ipns:|magnet:|mailto:|gemini://|gopher://|https://|http://|news:|file:|git://|ssh:|ftp://)[^\\u0000-\\u001F\\u007F-\\u009F<>\\"\\\\s{-}\\\\^⟨⟩`]+"_ # KEYBOARD diff --git a/extra/osx/Alacritty.app/Contents/Info.plist b/extra/osx/Alacritty.app/Contents/Info.plist index 9d7ca942d39..dd551e0fc36 100644 --- a/extra/osx/Alacritty.app/Contents/Info.plist +++ b/extra/osx/Alacritty.app/Contents/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.14.0-dev + 0.14.0 CFBundleSupportedPlatforms MacOSX