From 5c4469ffa7727b7a8d82f3f8261613a30591b4de Mon Sep 17 00:00:00 2001 From: Alexandru Placinta Date: Sun, 11 Feb 2024 23:53:57 +0100 Subject: [PATCH 001/102] Fix row indexing with inclusive ranges --- alacritty_terminal/src/grid/row.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alacritty_terminal/src/grid/row.rs b/alacritty_terminal/src/grid/row.rs index 951ef093..4e22e50b 100644 --- a/alacritty_terminal/src/grid/row.rs +++ b/alacritty_terminal/src/grid/row.rs @@ -291,7 +291,7 @@ impl Index> for Row { impl IndexMut> for Row { #[inline] fn index_mut(&mut self, index: RangeToInclusive) -> &mut [T] { - self.occ = max(self.occ, *index.end); + self.occ = max(self.occ, *index.end + 1); &mut self.inner[..=(index.end.0)] } } From 1645a70168ca012bcf6f2cab42271dd51ae682a2 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Mon, 12 Feb 2024 21:01:20 +0100 Subject: [PATCH 002/102] Use dynamic MSRV for oldstable CI Instead of manually specifying the oldstable version in all our CI scripts, it is now pulled from the `Cargo.toml` which simplifies the update process. The contributing guide has also been updated to not include the explicit version and its wording has been loosened a bit to correctly represent current maintenance practices. --- .builds/freebsd.yml | 5 +++-- .builds/linux.yml | 5 +++-- .github/workflows/ci.yml | 2 +- CONTRIBUTING.md | 5 +++-- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 4c9860b5..5e5021c6 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -24,8 +24,9 @@ tasks: cargo test - oldstable: | cd alacritty - rustup toolchain install --profile minimal 1.70.0 - rustup default 1.70.0 + oldstable=$(cat alacritty/Cargo.toml | grep "rust-version" | sed 's/.*"\(.*\)".*/\1/') + rustup toolchain install --profile minimal $oldstable + rustup default $oldstable cargo test - clippy: | cd alacritty diff --git a/.builds/linux.yml b/.builds/linux.yml index f2e9038a..e036261b 100644 --- a/.builds/linux.yml +++ b/.builds/linux.yml @@ -34,8 +34,9 @@ tasks: cargo test - oldstable: | cd alacritty - rustup toolchain install --profile minimal 1.70.0 - rustup default 1.70.0 + oldstable=$(cat alacritty/Cargo.toml | grep "rust-version" | sed 's/.*"\(.*\)".*/\1/') + rustup toolchain install --profile minimal $oldstable + rustup default $oldstable cargo test - clippy: | cd alacritty diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0a0b5f6f..573c4e0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: run: cargo test -p alacritty_terminal --no-default-features - name: Oldstable run: | - rustup default 1.70.0 + rustup default $(cat alacritty/Cargo.toml | grep "rust-version" | sed 's/.*"\(.*\)".*/\1/') cargo test - name: Clippy run: | diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 334a3e76..b07c02ef 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -42,8 +42,9 @@ and [easy](https://github.com/alacritty/alacritty/issues?q=is%3Aopen+is%3Aissue+label%3A%22D+-+easy%22) issues. -Please note that the minimum supported version of Alacritty is Rust 1.70.0. All patches are expected -to work with the minimum supported version. +You can find the minimum supported Rust version in Alacritty's manifest file +(`cat alacritty/Cargo.toml | grep "rust-version"`). Alacritty **must** always +build with the MSRV and bumping it should be avoided if possible. Since `alacritty_terminal`'s version always tracks the next release, make sure that the version is bumped according to semver when necessary. From 7d22310a4aa5d0beb3da93ee35c4504b9f839293 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Mon, 12 Feb 2024 21:09:22 +0100 Subject: [PATCH 003/102] Bump MSRV to 1.72.0 --- CHANGELOG.md | 4 ++++ Cargo.lock | 4 ++-- alacritty/Cargo.toml | 2 +- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d0bc36f..cdbf3392 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## 0.14.0-dev +### Packaging + +- Minimum Rust version has been bumped to 1.72.0 + ### Added - Default `Home`/`End` bindings in Vi mode mapped to `First`/`Last` respectively diff --git a/Cargo.lock b/Cargo.lock index df9900be..e56c3216 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.6" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff" dependencies = [ "cfg-if", "getrandom", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index c39473bf..37412f90 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -7,7 +7,7 @@ description = "A fast, cross-platform, OpenGL terminal emulator" readme = "README.md" homepage = "https://github.com/alacritty/alacritty" edition = "2021" -rust-version = "1.70.0" +rust-version = "1.72.0" [dependencies.alacritty_terminal] path = "../alacritty_terminal" From de12f03812e04c1b7cd58e8aa86d50e55de92f33 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Tue, 13 Feb 2024 22:08:33 +0100 Subject: [PATCH 004/102] Fix clippy warnings --- alacritty/src/event.rs | 1 + alacritty/src/input/mod.rs | 3 +++ 2 files changed, 4 insertions(+) diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index ff08557b..e1ee20f8 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -917,6 +917,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon self.config } + #[cfg(target_os = "macos")] fn event_loop(&self) -> &EventLoopWindowTarget { self.event_loop } diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index 5bc95bdf..9a96b45b 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -19,6 +19,7 @@ use winit::dpi::PhysicalPosition; use winit::event::{ ElementState, Modifiers, MouseButton, MouseScrollDelta, Touch as TouchEvent, TouchPhase, }; +#[cfg(target_os = "macos")] use winit::event_loop::EventLoopWindowTarget; use winit::keyboard::ModifiersState; #[cfg(target_os = "macos")] @@ -103,6 +104,7 @@ pub trait ActionContext { fn pop_message(&mut self) {} fn message(&self) -> Option<&Message>; fn config(&self) -> &UiConfig; + #[cfg(target_os = "macos")] fn event_loop(&self) -> &EventLoopWindowTarget; fn mouse_mode(&self) -> bool; fn clipboard_mut(&mut self) -> &mut Clipboard; @@ -1216,6 +1218,7 @@ mod tests { self.clipboard } + #[cfg(target_os = "macos")] fn event_loop(&self) -> &EventLoopWindowTarget { unimplemented!(); } From f1853a031d52f6964bbf368d2975767449fc4814 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Wed, 14 Feb 2024 01:59:56 +0100 Subject: [PATCH 005/102] Fix regional scrolling leaking into history This fixes an issue where a scrolling region that does not start at the top of the screen would still rotate lines into history when scrolling the content "upwards". --- CHANGELOG.md | 1 + alacritty_terminal/src/grid/mod.rs | 52 ++++++----- alacritty_terminal/tests/ref.rs | 1 + .../alacritty.recording | 91 +++++++++++++++++++ .../config.json | 1 + .../grid.json | 1 + .../size.json | 1 + 7 files changed, 126 insertions(+), 22 deletions(-) create mode 100644 alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/alacritty.recording create mode 100644 alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/config.json create mode 100644 alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/grid.json create mode 100644 alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/size.json diff --git a/CHANGELOG.md b/CHANGELOG.md index cdbf3392..ad36fbbb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - C0 and C1 codes being emitted in associated text when using kitty keyboard - Occasional hang on startup with some Wayland compositors - Missing key for `NumpadDecimal` in key bindings +- Scrolling content upwards moving lines into history when it shouldn't ### Changed diff --git a/alacritty_terminal/src/grid/mod.rs b/alacritty_terminal/src/grid/mod.rs index 8fdde0a4..59769883 100644 --- a/alacritty_terminal/src/grid/mod.rs +++ b/alacritty_terminal/src/grid/mod.rs @@ -268,33 +268,41 @@ impl Grid { self.display_offset = min(self.display_offset + positions, self.max_scroll_limit); } - // Create scrollback for the new lines. - self.increase_scroll_limit(positions); + // Only rotate the entire history if the active region starts at the top. + if region.start == 0 { + // Create scrollback for the new lines. + self.increase_scroll_limit(positions); - // Swap the lines fixed at the top to their target positions after rotation. - // - // Since we've made sure that the rotation will never rotate away the entire region, we - // know that the position of the fixed lines before the rotation must already be - // visible. - // - // We need to start from the bottom, to make sure the fixed lines aren't swapped with each - // other. - for i in (0..region.start.0).rev().map(Line::from) { - self.raw.swap(i, i + positions); - } + // Swap the lines fixed at the top to their target positions after rotation. + // + // Since we've made sure that the rotation will never rotate away the entire region, we + // know that the position of the fixed lines before the rotation must already be + // visible. + // + // We need to start from the bottom, to make sure the fixed lines aren't swapped with + // each other. + for i in (0..region.start.0).rev().map(Line::from) { + self.raw.swap(i, i + positions); + } - // Rotate the entire line buffer upward. - self.raw.rotate(-(positions as isize)); + // Rotate the entire line buffer upward. + self.raw.rotate(-(positions as isize)); - // Ensure all new lines are fully cleared. - let screen_lines = self.screen_lines(); - for i in ((screen_lines - positions)..screen_lines).map(Line::from) { - self.raw[i].reset(&self.cursor.template); + // Swap the fixed lines at the bottom back into position. + let screen_lines = self.screen_lines() as i32; + for i in (region.end.0..screen_lines).rev().map(Line::from) { + self.raw.swap(i, i - positions); + } + } else { + // Rotate lines without moving anything into history. + for i in (region.start.0..region.end.0 - positions as i32).map(Line::from) { + self.raw.swap(i, i + positions); + } } - // Swap the fixed lines at the bottom back into position. - for i in (region.end.0..(screen_lines as i32)).rev().map(Line::from) { - self.raw.swap(i, i - positions); + // Ensure all new lines are fully cleared. + for i in (region.end.0 - positions as i32..region.end.0).map(Line::from) { + self.raw[i].reset(&self.cursor.template); } } diff --git a/alacritty_terminal/tests/ref.rs b/alacritty_terminal/tests/ref.rs index 587d2d3e..1f992941 100644 --- a/alacritty_terminal/tests/ref.rs +++ b/alacritty_terminal/tests/ref.rs @@ -71,6 +71,7 @@ ref_tests! { zerowidth zsh_tab_completion erase_in_line + scroll_in_region_up_preserves_history } fn read_u8

(path: P) -> Vec diff --git a/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/alacritty.recording b/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/alacritty.recording new file mode 100644 index 00000000..80e989b4 --- /dev/null +++ b/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/alacritty.recording @@ -0,0 +1,91 @@ +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls -lah +[?2004l total 464K +drwxr-xr-x 13 undeadleech undeadleech 4.0K Feb 12 20:50 . +drwxr-xr-x 15 undeadleech undeadleech 4.0K Dec 9 18:42 .. +drwxr-xr-x 5 undeadleech undeadleech 4.0K Feb 10 09:04 alacritty +drwxr-xr-x 3 undeadleech undeadleech 4.0K Feb 10 09:04 alacritty_config +drwxr-xr-x 4 undeadleech undeadleech 4.0K Feb 10 09:04 alacritty_config_derive +-rw-r--r-- 1 undeadleech undeadleech 115 Feb 12 20:51 alacritty.recording +drwxr-xr-x 4 undeadleech undeadleech 4.0K Feb 10 09:04 alacritty_terminal +drwxr-xr-x 2 undeadleech undeadleech 4.0K Jan 8 23:30 .builds +-rw-r--r-- 1 undeadleech undeadleech 62K Feb 12 18:19 Cargo.lock +-rw-r--r-- 1 undeadleech undeadleech 201 Jan 8 23:29 Cargo.toml +-rw-r--r-- 1 undeadleech undeadleech 56K Feb 10 09:04 CHANGELOG.md +-rw-r--r-- 1 undeadleech undeadleech 18 Feb 12 20:50 config.json +-rw-r--r-- 1 undeadleech undeadleech 7.9K Feb 10 09:04 CONTRIBUTING.md +drwxr-xr-x 2 undeadleech undeadleech 4.0K Feb 10 09:04 docs +-rw-r--r-- 1 undeadleech undeadleech 240 Jan 8 23:29 .editorconfig +drwxr-xr-x 8 undeadleech undeadleech 4.0K Feb 10 09:04 extra +drwxr-xr-x 8 undeadleech undeadleech 4.0K Feb 12 20:50 .git +drwxr-xr-x 3 undeadleech undeadleech 4.0K Oct 14 2022 .github +-rw-r--r-- 1 undeadleech undeadleech 7 Oct 14 2022 .gitignore +-rw-r--r-- 1 undeadleech undeadleech 212K Feb 12 20:50 grid.json +-rw-r--r-- 1 undeadleech undeadleech 11K Jan 8 23:29 INSTALL.md +-rw-r--r-- 1 undeadleech undeadleech 11K Sep 1 2022 LICENSE-APACHE +-rw-r--r-- 1 undeadleech undeadleech 1023 Jan 15 2023 LICENSE-MIT +-rw-r--r-- 1 undeadleech undeadleech 3.2K Jan 8 23:29 Makefile +-rw-r--r-- 1 undeadleech undeadleech 4.2K Feb 10 09:04 README.md +-rw-r--r-- 1 undeadleech undeadleech 421 Oct 14 2022 rustfmt.toml +drwxr-xr-x 2 undeadleech undeadleech 4.0K Sep 1 2022 scripts +-rw-r--r-- 1 undeadleech undeadleech 32 Feb 12 20:50 size.json +drwxr-xr-x 6 undeadleech undeadleech 4.0K Feb 12 18:19 target +-rw-r--r-- 1 undeadleech undeadleech 27 Apr 9 2023 TODO +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ echo -e "\e[12r" +[?2004l  +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls +[?2004l alacritty Cargo.toml grid.json rustfmt.toml +alacritty_config CHANGELOG.md INSTALL.md scripts +alacritty_config_derive config.json LICENSE-APACHE size.json +alacritty.recording CONTRIBUTING.md LICENSE-MIT target +alacritty_terminal docs Makefile TODO +Cargo.lock extra README.md +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls +[?2004l alacritty Cargo.toml grid.json rustfmt.toml +alacritty_config CHANGELOG.md INSTALL.md scripts +alacritty_config_derive config.json LICENSE-APACHE size.json +alacritty.recording CONTRIBUTING.md LICENSE-MIT target +alacritty_terminal docs Makefile TODO +Cargo.lock extra README.md +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls +[?2004l alacritty Cargo.toml grid.json rustfmt.toml +alacritty_config CHANGELOG.md INSTALL.md scripts +alacritty_config_derive config.json LICENSE-APACHE size.json +alacritty.recording CONTRIBUTING.md LICENSE-MIT target +alacritty_terminal docs Makefile TODO +Cargo.lock extra README.md +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls +[?2004l alacritty Cargo.toml grid.json rustfmt.toml +alacritty_config CHANGELOG.md INSTALL.md scripts +alacritty_config_derive config.json LICENSE-APACHE size.json +alacritty.recording CONTRIBUTING.md LICENSE-MIT target +alacritty_terminal docs Makefile TODO +Cargo.lock extra README.md +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls +[?2004l alacritty Cargo.toml grid.json rustfmt.toml +alacritty_config CHANGELOG.md INSTALL.md scripts +alacritty_config_derive config.json LICENSE-APACHE size.json +alacritty.recording CONTRIBUTING.md LICENSE-MIT target +alacritty_terminal docs Makefile TODO +Cargo.lock extra README.md +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls +[?2004l alacritty Cargo.toml grid.json rustfmt.toml +alacritty_config CHANGELOG.md INSTALL.md scripts +alacritty_config_derive config.json LICENSE-APACHE size.json +alacritty.recording CONTRIBUTING.md LICENSE-MIT target +alacritty_terminal docs Makefile TODO +Cargo.lock extra README.md +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls +[?2004l alacritty Cargo.toml grid.json rustfmt.toml +alacritty_config CHANGELOG.md INSTALL.md scripts +alacritty_config_derive config.json LICENSE-APACHE size.json +alacritty.recording CONTRIBUTING.md LICENSE-MIT target +alacritty_terminal docs Makefile TODO +Cargo.lock extra README.md +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ ls +[?2004l alacritty Cargo.toml grid.json rustfmt.toml +alacritty_config CHANGELOG.md INSTALL.md scripts +alacritty_config_derive config.json LICENSE-APACHE size.json +alacritty.recording CONTRIBUTING.md LICENSE-MIT target +alacritty_terminal docs Makefile TODO +Cargo.lock extra README.md +]0;undeadleech@archhq:~/programming/alacritty/alacritty[?2004h[undeadleech@archhq alacritty]$ \ No newline at end of file diff --git a/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/config.json b/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/config.json new file mode 100644 index 00000000..4e3fa126 --- /dev/null +++ b/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/config.json @@ -0,0 +1 @@ +{"history_size":10} \ No newline at end of file diff --git a/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/grid.json b/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/grid.json new file mode 100644 index 00000000..3c1f52a8 --- /dev/null +++ b/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/grid.json @@ -0,0 +1 @@ +{"raw":{"inner":[{"inner":[{"c":"[","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"@","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"q","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"]","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"$","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":32},{"inner":[{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"k","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"R","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"D","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":51},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"k","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"D","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":62},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"R","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"B","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"U","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":64},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"v","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"P","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"H","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"z","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":67},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"H","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"p","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":65},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":70},{"inner":[{"c":"[","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"@","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"q","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"]","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"$","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":34},{"inner":[{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"k","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"R","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"D","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":51},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"k","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"D","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":62},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"R","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"B","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"U","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":64},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"v","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"P","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"H","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"z","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":67},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"H","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"p","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":65},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":70},{"inner":[{"c":"[","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"@","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"q","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"]","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"$","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":34},{"inner":[{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"k","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"R","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"D","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":51},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"k","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"D","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":62},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"R","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"B","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"U","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":64},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"v","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"P","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"H","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"z","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":67},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"H","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"p","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":65},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":70},{"inner":[{"c":"[","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"@","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"q","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"]","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"$","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":34},{"inner":[{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"k","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"R","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"D","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":51},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"k","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"D","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":62},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"R","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"B","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"U","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"M","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":64},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"v","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"P","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"H","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"z","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":67},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"_","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"H","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"E","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"O","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"G","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"I","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"N","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"S","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"T","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"A","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"L","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"p","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":65},{"inner":[{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"C","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"g","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"j","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"\t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"f","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"m","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":70},{"inner":[{"c":"[","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"@","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"q","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"]","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"$","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":34},{"inner":[{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"w","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"5","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"4","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"0","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"K","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"F","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"b","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"1","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"0","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"0","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"9","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":":","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"0","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"4","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":65},{"inner":[{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"w","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"1","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"5","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"4","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"0","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"K","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"D","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"9","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"1","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"8","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":":","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"4","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"2","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":58},{"inner":[{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"w","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"x","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"1","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"3","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"4","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"0","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"K","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"F","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"b","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"1","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"2","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"2","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"0","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":":","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"5","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"0","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":".","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":57},{"inner":[{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"o","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"4","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"6","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"4","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"K","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":10},{"inner":[{"c":"[","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"u","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"n","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"d","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"e","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"@","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"q","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"c","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"r","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"i","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"t","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"y","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"]","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"$","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"s","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"-","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"l","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"a","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":"h","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":39},{"inner":[{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":0},{"inner":[{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":0},{"inner":[{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":0},{"inner":[{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":0},{"inner":[{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":0},{"inner":[{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null},{"c":" ","fg":{"Named":"Foreground"},"bg":{"Named":"Background"},"flags":"","extra":null}],"occ":0}],"zero":0,"visible_lines":30,"len":40},"columns":80,"lines":30,"display_offset":0,"max_scroll_limit":10} \ No newline at end of file diff --git a/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/size.json b/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/size.json new file mode 100644 index 00000000..6593a642 --- /dev/null +++ b/alacritty_terminal/tests/ref/scroll_in_region_up_preserves_history/size.json @@ -0,0 +1 @@ +{"columns":80,"screen_lines":30} \ No newline at end of file From cb3a79dbf6472740daca8440d5166c1d4af5029e Mon Sep 17 00:00:00 2001 From: Yadi Abdalhalim <36752216+Ydot19@users.noreply.github.com> Date: Mon, 19 Feb 2024 02:18:07 -0800 Subject: [PATCH 006/102] Fix typo in config docs --- extra/man/alacritty.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index f42b74e3..81637f3e 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -890,7 +890,7 @@ _https://docs.rs/winit/latest/winit/keyboard/enum.Key.html#variant.Dead_ Centers the screen around the vi mode cursor. *InlineSearchForward* Search forward within the current line. - *InlineSearchBcakward* + *InlineSearchBackward* Search backward within the current line. *InlineSearchForwardShort* Search forward within the current line, stopping just short of the character. From 37349c4566a1431b5becbb649dec536ecbe18e71 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 27 Feb 2024 08:57:36 +0400 Subject: [PATCH 007/102] Bump winit to 0.29.11 Fixes #7633. Fixes #7613. Fixes #7607. Fixes #7571. Fixes #7549. --- CHANGELOG.md | 4 ++ Cargo.lock | 95 ++++++++------------------------------------ alacritty/Cargo.toml | 4 +- 3 files changed, 23 insertions(+), 80 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad36fbbb..a0fd391d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Occasional hang on startup with some Wayland compositors - Missing key for `NumpadDecimal` in key bindings - Scrolling content upwards moving lines into history when it shouldn't +- Sticky keys not working sometimes on X11 +- Modifiers occasionally getting desynced on X11 +- Autokey no longer working with alacritty on X11 +- Freeze when moving window between monitors on Xfwm ### Changed diff --git a/Cargo.lock b/Cargo.lock index e56c3216..cb92ca75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -469,9 +469,9 @@ dependencies = [ [[package]] name = "copypasta" -version = "0.10.0" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d35364349bf9e9e1c3a035ddcb00d188d23a3c40c50244c03c27a99fc6a65ae" +checksum = "deb85422867ca93da58b7f95fb5c0c10f6183ed6e1ef8841568968a896d3a858" dependencies = [ "clipboard-win", "objc", @@ -789,16 +789,6 @@ version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" -[[package]] -name = "gethostname" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb65d4ba3173c56a500b555b532f72c42e8d1fe64962b518897f8959fae2c177" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "gethostname" version = "0.4.3" @@ -1032,9 +1022,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" [[package]] name = "libc" -version = "0.2.151" +version = "0.2.153" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" @@ -1117,15 +1107,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de893c32cde5f383baa4c04c5d6dbdd735cfd4a794b0debdb2bb1b421da5ff4" -dependencies = [ - "autocfg", -] - [[package]] name = "miniz_oxide" version = "0.7.1" @@ -1187,18 +1168,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "nix" -version = "0.26.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" -dependencies = [ - "bitflags 1.3.2", - "cfg-if", - "libc", - "memoffset", -] - [[package]] name = "notify" version = "6.1.1" @@ -1698,9 +1667,9 @@ dependencies = [ [[package]] name = "smithay-clipboard" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb62b280ce5a5cba847669933a0948d00904cf83845c944eae96a4738cea1a6" +checksum = "c091e7354ea8059d6ad99eace06dd13ddeedbb0ac72d40a9a6e7ff790525882d" dependencies = [ "libc", "smithay-client-toolkit", @@ -2161,15 +2130,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" -dependencies = [ - "winapi", -] - [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -2310,9 +2270,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winit" -version = "0.29.9" +version = "0.29.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2376dab13e09c01ad8b679f0dbc7038af4ec43d9a91344338e37bd686481550" +checksum = "272be407f804517512fdf408f0fe6c067bf24659a913c61af97af176bfd5aa92" dependencies = [ "ahash", "android-activity", @@ -2353,7 +2313,7 @@ dependencies = [ "web-time", "windows-sys 0.48.0", "x11-dl", - "x11rb 0.13.0", + "x11rb", "xkbcommon-dl", ] @@ -2387,11 +2347,12 @@ dependencies = [ [[package]] name = "x11-clipboard" -version = "0.8.1" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41aca1115b1f195f21c541c5efb423470848d48143127d0f07f8b90c27440df" +checksum = "613c2be3e772af2bbb57c5a94413675f5ec668bac00a71ada2ced28c420ef087" dependencies = [ - "x11rb 0.12.0", + "libc", + "x11rb", ] [[package]] @@ -2405,19 +2366,6 @@ dependencies = [ "pkg-config", ] -[[package]] -name = "x11rb" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1641b26d4dec61337c35a1b1aaf9e3cba8f46f0b43636c609ab0291a648040a" -dependencies = [ - "gethostname 0.3.0", - "nix", - "winapi", - "winapi-wsapoll", - "x11rb-protocol 0.12.0", -] - [[package]] name = "x11rb" version = "0.13.0" @@ -2425,21 +2373,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" dependencies = [ "as-raw-xcb-connection", - "gethostname 0.4.3", + "gethostname", "libc", "libloading", "once_cell", "rustix", - "x11rb-protocol 0.13.0", -] - -[[package]] -name = "x11rb-protocol" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d6c3f9a0fb6701fab8f6cea9b0c0bd5d6876f1f89f7fada07e558077c344bc" -dependencies = [ - "nix", + "x11rb-protocol", ] [[package]] @@ -2462,9 +2401,9 @@ checksum = "213b7324336b53d2414b2db8537e56544d981803139155afa84f76eeebb7a546" [[package]] name = "xkbcommon-dl" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6924668544c48c0133152e7eec86d644a056ca3d09275eb8d5cdb9855f9d8699" +checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ "bitflags 2.4.1", "dlib", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 37412f90..db6894f5 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -25,7 +25,7 @@ version = "0.2.1-dev" ahash = { version = "0.8.6", features = ["no-rng"] } bitflags = "2.2.1" clap = { version = "4.2.7", features = ["derive", "env"] } -copypasta = { version = "0.10.0", default-features = false } +copypasta = { version = "0.10.1", default-features = false } crossfont = { version = "0.7.0", features = ["force_system_fontconfig"] } glutin = { version = "0.31.1", default-features = false, features = ["egl", "wgl"] } home = "0.5.5" @@ -39,7 +39,7 @@ serde_json = "1" serde_yaml = "0.9.25" toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.29.9", default-features = false, features = ["rwh_05", "serde"] } +winit = { version = "0.29.11", default-features = false, features = ["rwh_05", "serde"] } [build-dependencies] gl_generator = "0.14.0" From 93e3de7c31ba48945d0bafca6cb6523b32abe0bc Mon Sep 17 00:00:00 2001 From: Dimitris Apostolou Date: Wed, 28 Feb 2024 20:09:07 +0200 Subject: [PATCH 008/102] Fix feature = "cargo-clippy" deprecation --- alacritty/src/main.rs | 2 +- alacritty_config_derive/src/lib.rs | 2 +- alacritty_terminal/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 91d99cbe..2a60961a 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -2,7 +2,7 @@ #![warn(rust_2018_idioms, future_incompatible)] #![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use)] -#![cfg_attr(feature = "cargo-clippy", deny(warnings))] +#![cfg_attr(clippy, deny(warnings))] // With the default subsystem, 'console', windows creates an additional console // window for the program. // This is silently ignored on non-windows systems. diff --git a/alacritty_config_derive/src/lib.rs b/alacritty_config_derive/src/lib.rs index a7850529..324bce2a 100644 --- a/alacritty_config_derive/src/lib.rs +++ b/alacritty_config_derive/src/lib.rs @@ -1,5 +1,5 @@ #![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use)] -#![cfg_attr(feature = "cargo-clippy", deny(warnings))] +#![cfg_attr(clippy, deny(warnings))] use proc_macro::TokenStream; use proc_macro2::TokenStream as TokenStream2; diff --git a/alacritty_terminal/src/lib.rs b/alacritty_terminal/src/lib.rs index 7e4e68b1..7324473c 100644 --- a/alacritty_terminal/src/lib.rs +++ b/alacritty_terminal/src/lib.rs @@ -2,7 +2,7 @@ #![warn(rust_2018_idioms, future_incompatible)] #![deny(clippy::all, clippy::if_not_else, clippy::enum_glob_use)] -#![cfg_attr(feature = "cargo-clippy", deny(warnings))] +#![cfg_attr(clippy, deny(warnings))] pub mod event; pub mod event_loop; From c354f58f421c267cc1472414eaaa9f738509ede0 Mon Sep 17 00:00:00 2001 From: Friz64 Date: Thu, 29 Feb 2024 17:38:55 +0100 Subject: [PATCH 009/102] Check alternative cursor icon names on Wayland --- CHANGELOG.md | 1 + Cargo.lock | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a0fd391d..e28eadf0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Modifiers occasionally getting desynced on X11 - Autokey no longer working with alacritty on X11 - Freeze when moving window between monitors on Xfwm +- Mouse cursor not changing on Wayland when cursor theme uses legacy cursor icon names ### Changed diff --git a/Cargo.lock b/Cargo.lock index cb92ca75..ebc787ff 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1642,9 +1642,9 @@ checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "smithay-client-toolkit" -version = "0.18.0" +version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e3d9941fa3bacf7c2bf4b065304faa14164151254cd16ce1b1bc8fc381600f" +checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" dependencies = [ "bitflags 2.4.1", "calloop", From 876bbc50beaf53f83134630a4aaec4c8ddc5d2ec Mon Sep 17 00:00:00 2001 From: Alexandru Placinta Date: Fri, 1 Mar 2024 01:31:19 +0100 Subject: [PATCH 010/102] Add alias support to `SerdeReplace` --- CHANGELOG.md | 1 + alacritty_config_derive/src/serde_replace.rs | 38 +++++++++++++--- alacritty_config_derive/tests/config.rs | 46 +++++++++++++++++++- 3 files changed, 78 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e28eadf0..58ce9764 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Autokey no longer working with alacritty on X11 - Freeze when moving window between monitors on Xfwm - Mouse cursor not changing on Wayland when cursor theme uses legacy cursor icon names +- Config keys are available under proper names ### Changed diff --git a/alacritty_config_derive/src/serde_replace.rs b/alacritty_config_derive/src/serde_replace.rs index 0a703b4c..ddd0cf75 100644 --- a/alacritty_config_derive/src/serde_replace.rs +++ b/alacritty_config_derive/src/serde_replace.rs @@ -44,7 +44,10 @@ pub fn derive_recursive( ) -> TokenStream2 { let GenericsStreams { unconstrained, constrained, .. } = crate::generics_streams(&generics.params); - let replace_arms = match_arms(&fields); + let replace_arms = match match_arms(&fields) { + Err(e) => return e.to_compile_error(), + Ok(replace_arms) => replace_arms, + }; quote! { #[allow(clippy::extra_unused_lifetimes)] @@ -75,7 +78,7 @@ pub fn derive_recursive( } /// Create SerdeReplace recursive match arms. -fn match_arms(fields: &Punctuated) -> TokenStream2 { +fn match_arms(fields: &Punctuated) -> Result { let mut stream = TokenStream2::default(); let mut flattened_arm = None; @@ -88,19 +91,42 @@ fn match_arms(fields: &Punctuated) -> TokenStream2 { let flatten = field .attrs .iter() + .filter(|attr| (*attr).path().is_ident("config")) .filter_map(|attr| attr.parse_args::().ok()) .any(|parsed| parsed.ident.as_str() == "flatten"); if flatten && flattened_arm.is_some() { - return Error::new(ident.span(), MULTIPLE_FLATTEN_ERROR).to_compile_error(); + return Err(Error::new(ident.span(), MULTIPLE_FLATTEN_ERROR)); } else if flatten { flattened_arm = Some(quote! { _ => alacritty_config::SerdeReplace::replace(&mut self.#ident, value)?, }); } else { + // Extract all `#[config(alias = "...")]` attribute values. + let aliases = field + .attrs + .iter() + .filter(|attr| (*attr).path().is_ident("config")) + .filter_map(|attr| attr.parse_args::().ok()) + .filter(|parsed| parsed.ident.as_str() == "alias") + .map(|parsed| { + let value = parsed + .param + .ok_or_else(|| format!("Field \"{}\" has no alias value", ident))? + .value(); + + if value.trim().is_empty() { + return Err(format!("Field \"{}\" has an empty alias value", ident)); + } + + Ok(value) + }) + .collect::, String>>() + .map_err(|msg| Error::new(ident.span(), msg))?; + stream.extend(quote! { - #literal => alacritty_config::SerdeReplace::replace(&mut self.#ident, next_value)?, - }); + #(#aliases)|* | #literal => alacritty_config::SerdeReplace::replace(&mut + self.#ident, next_value)?, }); } } @@ -109,5 +135,5 @@ fn match_arms(fields: &Punctuated) -> TokenStream2 { stream.extend(flattened_arm); } - stream + Ok(stream) } diff --git a/alacritty_config_derive/tests/config.rs b/alacritty_config_derive/tests/config.rs index 3130bcda..27a968ed 100644 --- a/alacritty_config_derive/tests/config.rs +++ b/alacritty_config_derive/tests/config.rs @@ -23,7 +23,7 @@ impl Default for TestEnum { #[derive(ConfigDeserialize)] struct Test { - #[config(alias = "noalias")] + #[config(alias = "field1_alias")] #[config(deprecated = "use field2 instead")] field1: usize, #[config(deprecated = "shouldn't be hit")] @@ -39,6 +39,9 @@ struct Test { enom_error: TestEnum, #[config(removed = "it's gone")] gone: bool, + #[config(alias = "multiple_alias1")] + #[config(alias = "multiple_alias2")] + multiple_alias_field: usize, } impl Default for Test { @@ -53,6 +56,7 @@ impl Default for Test { enom_big: TestEnum::default(), enom_error: TestEnum::default(), gone: false, + multiple_alias_field: 0, } } } @@ -70,6 +74,7 @@ struct Test2 { #[derive(ConfigDeserialize, Default)] struct Test3 { + #[config(alias = "flatty_alias")] flatty: usize, } @@ -189,6 +194,33 @@ fn replace_derive() { assert_eq!(test.nesting.newtype, NewType(9)); } +#[test] +fn replace_derive_using_alias() { + let mut test = Test::default(); + + assert_ne!(test.field1, 9); + + let value = toml::from_str("field1_alias=9").unwrap(); + test.replace(value).unwrap(); + + assert_eq!(test.field1, 9); +} + +#[test] +fn replace_derive_using_multiple_aliases() { + let mut test = Test::default(); + + let toml_value = toml::from_str("multiple_alias1=6").unwrap(); + test.replace(toml_value).unwrap(); + + assert_eq!(test.multiple_alias_field, 6); + + let toml_value = toml::from_str("multiple_alias1=7").unwrap(); + test.replace(toml_value).unwrap(); + + assert_eq!(test.multiple_alias_field, 7); +} + #[test] fn replace_flatten() { let mut test = Test::default(); @@ -198,3 +230,15 @@ fn replace_flatten() { assert_eq!(test.flatten.flatty, 7); } + +#[test] +fn replace_flatten_using_alias() { + let mut test = Test::default(); + + assert_ne!(test.flatten.flatty, 7); + + let value = toml::from_str("flatty_alias=7").unwrap(); + test.replace(value).unwrap(); + + assert_eq!(test.flatten.flatty, 7); +} From 63e94fd32409b8654a7ec9e6a3c1d1365544ff6c Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Fri, 1 Mar 2024 14:36:56 +0400 Subject: [PATCH 011/102] Bump winit to 0.29.12 The 0.29.11 was yanked. --- Cargo.lock | 4 ++-- alacritty/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ebc787ff..566794b6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2270,9 +2270,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winit" -version = "0.29.11" +version = "0.29.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "272be407f804517512fdf408f0fe6c067bf24659a913c61af97af176bfd5aa92" +checksum = "b042fd2f023ddd9713f02f8f89c62f5a32c18d104ac182b480a0e3e6cb8d37f7" dependencies = [ "ahash", "android-activity", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index db6894f5..84e5273d 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -39,7 +39,7 @@ serde_json = "1" serde_yaml = "0.9.25" toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.29.11", default-features = false, features = ["rwh_05", "serde"] } +winit = { version = "0.29.12", default-features = false, features = ["rwh_05", "serde"] } [build-dependencies] gl_generator = "0.14.0" From f7811548ae9cabb1122f43b42fec4d660318bc96 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 3 Mar 2024 11:41:01 +0400 Subject: [PATCH 012/102] Fix build failure on NetBSD x11-clipboard was unconditionally using eventfd which is not present on NetBSD. Links: https://github.com/quininer/x11-clipboard/issues/48 --- CHANGELOG.md | 1 + Cargo.lock | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 58ce9764..0f19c399 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Freeze when moving window between monitors on Xfwm - Mouse cursor not changing on Wayland when cursor theme uses legacy cursor icon names - Config keys are available under proper names +- Build failure when compiling with x11 feature on NetBSD ### Changed diff --git a/Cargo.lock b/Cargo.lock index 566794b6..69367f31 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2347,9 +2347,9 @@ dependencies = [ [[package]] name = "x11-clipboard" -version = "0.9.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613c2be3e772af2bbb57c5a94413675f5ec668bac00a71ada2ced28c420ef087" +checksum = "b98785a09322d7446e28a13203d2cae1059a0dd3dfb32cb06d0a225f023d8286" dependencies = [ "libc", "x11rb", From 6dbb3ff9002d3d6b6776370013cab36a78c3eb50 Mon Sep 17 00:00:00 2001 From: huajin tong <137764712+thirdkeyword@users.noreply.github.com> Date: Thu, 7 Mar 2024 06:55:41 +0800 Subject: [PATCH 013/102] Fix log typos --- CHANGELOG.md | 2 +- alacritty_terminal/src/term/mod.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f19c399..f5361861 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -487,7 +487,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Performance of scrolling regions with offset from the bottom - Extra mouse buttons are no longer ignored on Wayland - Numpad arrow keys are now properly recognized on Wayland -- Compilation when targetting aarch64-apple-darwin +- Compilation when targeting aarch64-apple-darwin - Window not being completely opaque on Windows - Window being always on top during alt-tab on Windows - Cursor position not reported to apps when mouse is moved with button held outside of window diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index ec79886c..2ed6d7c9 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -1305,7 +1305,7 @@ impl Handler for Term { return; } - trace!("Attemting to pop {to_pop} keyboard modes from the stack"); + trace!("Attempting to pop {to_pop} keyboard modes from the stack"); let new_len = self.keyboard_mode_stack.len().saturating_sub(to_pop as usize); self.keyboard_mode_stack.truncate(new_len); From 55b36cebc474152c8d69d4b478bbd4b250b233bf Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 7 Mar 2024 12:21:17 +0400 Subject: [PATCH 014/102] Bump winit to 0.29.14 Fixes #7806. --- Cargo.lock | 8 ++++---- alacritty/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 69367f31..07ee4cef 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1119,9 +1119,9 @@ dependencies = [ [[package]] name = "mio" -version = "0.8.10" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f3d0b296e374a4e6f3c7b0a1f5a51d748a0d34c85e7dc48fc3fa9a87657fe09" +checksum = "a4a650543ca06a924e8b371db273b2756685faae30f8487da1b56505a8f78b0c" dependencies = [ "libc", "log", @@ -2270,9 +2270,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winit" -version = "0.29.12" +version = "0.29.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b042fd2f023ddd9713f02f8f89c62f5a32c18d104ac182b480a0e3e6cb8d37f7" +checksum = "a7a3db69ffbe53a9babec7804da7a90f21020fcce1f2f5e5291e2311245b993d" dependencies = [ "ahash", "android-activity", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 84e5273d..313dfed2 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -39,7 +39,7 @@ serde_json = "1" serde_yaml = "0.9.25" toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.29.12", default-features = false, features = ["rwh_05", "serde"] } +winit = { version = "0.29.14", default-features = false, features = ["rwh_05", "serde"] } [build-dependencies] gl_generator = "0.14.0" From 992011a4cd9a35f197acc0a0bd430d89a0d01013 Mon Sep 17 00:00:00 2001 From: Small White <364772080@qq.com> Date: Thu, 7 Mar 2024 16:56:21 +0800 Subject: [PATCH 015/102] Expose more process info on Windows --- alacritty_terminal/src/tty/windows/child.rs | 25 ++++++++++++++++++++- alacritty_terminal/src/tty/windows/mod.rs | 4 ++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/alacritty_terminal/src/tty/windows/child.rs b/alacritty_terminal/src/tty/windows/child.rs index 6bc9ed20..7de6563f 100644 --- a/alacritty_terminal/src/tty/windows/child.rs +++ b/alacritty_terminal/src/tty/windows/child.rs @@ -1,5 +1,6 @@ use std::ffi::c_void; use std::io::Error; +use std::num::NonZeroU32; use std::sync::atomic::{AtomicPtr, Ordering}; use std::sync::{mpsc, Arc, Mutex}; @@ -8,7 +9,7 @@ use polling::{Event, Poller}; use windows_sys::Win32::Foundation::{BOOLEAN, HANDLE}; use windows_sys::Win32::System::Threading::{ - RegisterWaitForSingleObject, UnregisterWait, INFINITE, WT_EXECUTEINWAITTHREAD, + GetProcessId, RegisterWaitForSingleObject, UnregisterWait, INFINITE, WT_EXECUTEINWAITTHREAD, WT_EXECUTEONLYONCE, }; @@ -42,6 +43,8 @@ pub struct ChildExitWatcher { wait_handle: AtomicPtr, event_rx: mpsc::Receiver, interest: Arc>>, + child_handle: HANDLE, + pid: Option, } impl ChildExitWatcher { @@ -66,10 +69,13 @@ impl ChildExitWatcher { if success == 0 { Err(Error::last_os_error()) } else { + let pid = unsafe { NonZeroU32::new(GetProcessId(child_handle)) }; Ok(ChildExitWatcher { wait_handle: AtomicPtr::from(wait_handle as *mut c_void), event_rx, interest, + child_handle, + pid, }) } } @@ -85,6 +91,23 @@ impl ChildExitWatcher { pub fn deregister(&self) { *self.interest.lock().unwrap() = None; } + + /// Retrieve the process handle of the underlying child process. + /// + /// This function does **not** pass ownership of the raw handle to you, + /// and the handle is only guaranteed to be valid while the hosted application + /// has not yet been destroyed. + /// + /// If you terminate the process using this handle, the terminal will get a + /// timeout error, and the child watcher will emit an `Exited` event. + pub fn raw_handle(&self) -> HANDLE { + self.child_handle + } + + /// Retrieve the Process ID associated to the underlying child process. + pub fn pid(&self) -> Option { + self.pid + } } impl Drop for ChildExitWatcher { diff --git a/alacritty_terminal/src/tty/windows/mod.rs b/alacritty_terminal/src/tty/windows/mod.rs index cbd803f1..e42e2b6c 100644 --- a/alacritty_terminal/src/tty/windows/mod.rs +++ b/alacritty_terminal/src/tty/windows/mod.rs @@ -47,6 +47,10 @@ impl Pty { ) -> Self { Self { backend: backend.into(), conout: conout.into(), conin: conin.into(), child_watcher } } + + pub fn child_watcher(&self) -> &ChildExitWatcher { + &self.child_watcher + } } fn with_key(mut event: Event, key: usize) -> Event { From f5646ba352c809f78c55a9e1f6a5212aea787899 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Sat, 9 Mar 2024 13:32:32 +0200 Subject: [PATCH 016/102] Send exit code events on child process exit Fixes #7753. --- alacritty/src/event.rs | 2 +- alacritty_terminal/src/event.rs | 4 ++++ alacritty_terminal/src/event_loop.rs | 7 +++++-- alacritty_terminal/src/tty/mod.rs | 4 ++-- alacritty_terminal/src/tty/unix.rs | 2 +- alacritty_terminal/src/tty/windows/child.rs | 23 +++++++++++++++------ alacritty_terminal/src/tty/windows/mod.rs | 2 +- 7 files changed, 31 insertions(+), 13 deletions(-) diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index e1ee20f8..4fa397ad 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1356,7 +1356,7 @@ impl input::Processor> { TerminalEvent::PtyWrite(text) => self.ctx.write_to_pty(text.into_bytes()), TerminalEvent::MouseCursorDirty => self.reset_mouse_cursor(), TerminalEvent::CursorBlinkingChange => self.ctx.update_cursor_blinking(), - TerminalEvent::Exit | TerminalEvent::Wakeup => (), + TerminalEvent::Exit | TerminalEvent::ChildExit(_) | TerminalEvent::Wakeup => (), }, #[cfg(unix)] EventType::IpcConfig(_) => (), diff --git a/alacritty_terminal/src/event.rs b/alacritty_terminal/src/event.rs index caa1e9d6..e17d41ea 100644 --- a/alacritty_terminal/src/event.rs +++ b/alacritty_terminal/src/event.rs @@ -52,6 +52,9 @@ pub enum Event { /// Shutdown request. Exit, + + /// Child process exited with an error code. + ChildExit(i32), } impl Debug for Event { @@ -69,6 +72,7 @@ impl Debug for Event { Event::Wakeup => write!(f, "Wakeup"), Event::Bell => write!(f, "Bell"), Event::Exit => write!(f, "Exit"), + Event::ChildExit(code) => write!(f, "ChildExit({code})"), } } } diff --git a/alacritty_terminal/src/event_loop.rs b/alacritty_terminal/src/event_loop.rs index 42025b00..929c642d 100644 --- a/alacritty_terminal/src/event_loop.rs +++ b/alacritty_terminal/src/event_loop.rs @@ -259,7 +259,11 @@ where for event in events.iter() { match event.key { tty::PTY_CHILD_EVENT_TOKEN => { - if let Some(tty::ChildEvent::Exited) = self.pty.next_child_event() { + if let Some(tty::ChildEvent::Exited(code)) = self.pty.next_child_event() + { + if let Some(code) = code { + self.event_proxy.send_event(Event::ChildExit(code)); + } if self.hold { // With hold enabled, make sure the PTY is drained. let _ = self.pty_read(&mut state, &mut buf, pipe.as_mut()); @@ -267,7 +271,6 @@ where // Without hold, shutdown the terminal. self.terminal.lock().exit(); } - self.event_proxy.send_event(Event::Wakeup); break 'event_loop; } diff --git a/alacritty_terminal/src/tty/mod.rs b/alacritty_terminal/src/tty/mod.rs index d1bb023c..35d227b8 100644 --- a/alacritty_terminal/src/tty/mod.rs +++ b/alacritty_terminal/src/tty/mod.rs @@ -67,8 +67,8 @@ pub trait EventedReadWrite { /// Events concerning TTY child processes. #[derive(Debug, PartialEq, Eq)] pub enum ChildEvent { - /// Indicates the child has exited. - Exited, + /// Indicates the child has exited, with an error code if available. + Exited(Option), } /// A pseudoterminal (or PTY). diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 2c06d54f..1034c5a9 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -381,7 +381,7 @@ impl EventedPty for Pty { None }, Ok(None) => None, - Ok(_) => Some(ChildEvent::Exited), + Ok(exit_status) => Some(ChildEvent::Exited(exit_status.and_then(|s| s.code()))), } } } diff --git a/alacritty_terminal/src/tty/windows/child.rs b/alacritty_terminal/src/tty/windows/child.rs index 7de6563f..dc6b992c 100644 --- a/alacritty_terminal/src/tty/windows/child.rs +++ b/alacritty_terminal/src/tty/windows/child.rs @@ -7,10 +7,10 @@ use std::sync::{mpsc, Arc, Mutex}; use polling::os::iocp::{CompletionPacket, PollerIocpExt}; use polling::{Event, Poller}; -use windows_sys::Win32::Foundation::{BOOLEAN, HANDLE}; +use windows_sys::Win32::Foundation::{BOOLEAN, FALSE, HANDLE}; use windows_sys::Win32::System::Threading::{ - GetProcessId, RegisterWaitForSingleObject, UnregisterWait, INFINITE, WT_EXECUTEINWAITTHREAD, - WT_EXECUTEONLYONCE, + GetExitCodeProcess, GetProcessId, RegisterWaitForSingleObject, UnregisterWait, INFINITE, + WT_EXECUTEINWAITTHREAD, WT_EXECUTEONLYONCE, }; use crate::tty::ChildEvent; @@ -23,6 +23,7 @@ struct Interest { struct ChildExitSender { sender: mpsc::Sender, interest: Arc>>, + child_handle: AtomicPtr, } /// WinAPI callback to run when child process exits. @@ -32,7 +33,13 @@ extern "system" fn child_exit_callback(ctx: *mut c_void, timed_out: BOOLEAN) { } let event_tx: Box<_> = unsafe { Box::from_raw(ctx as *mut ChildExitSender) }; - let _ = event_tx.sender.send(ChildEvent::Exited); + + let mut exit_code = 0_u32; + let child_handle = event_tx.child_handle.load(Ordering::Relaxed) as HANDLE; + let status = unsafe { GetExitCodeProcess(child_handle, &mut exit_code) }; + let exit_code = if status == FALSE { None } else { Some(exit_code as i32) }; + event_tx.sender.send(ChildEvent::Exited(exit_code)).ok(); + let interest = event_tx.interest.lock().unwrap(); if let Some(interest) = interest.as_ref() { interest.poller.post(CompletionPacket::new(interest.event)).ok(); @@ -53,7 +60,11 @@ impl ChildExitWatcher { let mut wait_handle: HANDLE = 0; let interest = Arc::new(Mutex::new(None)); - let sender_ref = Box::new(ChildExitSender { sender: event_tx, interest: interest.clone() }); + let sender_ref = Box::new(ChildExitSender { + sender: event_tx, + interest: interest.clone(), + child_handle: AtomicPtr::from(child_handle as *mut c_void), + }); let success = unsafe { RegisterWaitForSingleObject( @@ -145,6 +156,6 @@ mod tests { poller.wait(&mut events, Some(WAIT_TIMEOUT)).unwrap(); assert_eq!(events.iter().next().unwrap().key, PTY_CHILD_EVENT_TOKEN); // Verify that at least one `ChildEvent::Exited` was received. - assert_eq!(child_exit_watcher.event_rx().try_recv(), Ok(ChildEvent::Exited)); + assert_eq!(child_exit_watcher.event_rx().try_recv(), Ok(ChildEvent::Exited(Some(1)))); } } diff --git a/alacritty_terminal/src/tty/windows/mod.rs b/alacritty_terminal/src/tty/windows/mod.rs index e42e2b6c..6af162c8 100644 --- a/alacritty_terminal/src/tty/windows/mod.rs +++ b/alacritty_terminal/src/tty/windows/mod.rs @@ -115,7 +115,7 @@ impl EventedPty for Pty { match self.child_watcher.event_rx().try_recv() { Ok(ev) => Some(ev), Err(TryRecvError::Empty) => None, - Err(TryRecvError::Disconnected) => Some(ChildEvent::Exited), + Err(TryRecvError::Disconnected) => Some(ChildEvent::Exited(None)), } } } From 41d2f1df4509148a6f1ffb3de59c2389a3a93283 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 10 Mar 2024 01:58:12 +0400 Subject: [PATCH 017/102] Set PTY's pixel size on startup 117719b3 removed the extra call for TIOCSWINSZ, however the initial `openpty` call itself did not set the pixel size, which caused issues with some clients. --- alacritty_terminal/src/tty/unix.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 1034c5a9..8ce04191 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -4,7 +4,6 @@ use std::ffi::CStr; use std::fs::File; use std::io::{Error, ErrorKind, Read, Result}; use std::mem::MaybeUninit; -use std::os::fd::OwnedFd; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::net::UnixStream; use std::os::unix::process::CommandExt; @@ -38,17 +37,6 @@ macro_rules! die { }} } -/// Get raw fds for master/slave ends of a new PTY. -fn make_pty(size: Winsize) -> Result<(OwnedFd, OwnedFd)> { - let mut window_size = size; - window_size.ws_xpixel = 0; - window_size.ws_ypixel = 0; - - let ends = openpty(None, Some(&window_size))?; - - Ok((ends.controller, ends.user)) -} - /// Really only needed on BSD, but should be fine elsewhere. fn set_controlling_terminal(fd: c_int) { let res = unsafe { @@ -194,7 +182,8 @@ fn default_shell_command(shell: &str, user: &str) -> Command { /// Create a new TTY and return a handle to interact with it. pub fn new(config: &Options, window_size: WindowSize, window_id: u64) -> Result { - let (master, slave) = make_pty(window_size.to_winsize())?; + let pty = openpty(None, Some(&window_size.to_winsize()))?; + let (master, slave) = (pty.controller, pty.user); let master_fd = master.as_raw_fd(); let slave_fd = slave.as_raw_fd(); From 275726f78499698f82eafff761fb497b29ddc2b8 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Tue, 12 Mar 2024 12:15:00 +0100 Subject: [PATCH 018/102] Fix hint `Select` action for hyperlink escape This fixes an issue where the `Select` action for hyperlink escape text would select the entire line, instead of selecting only the hyperlink itself. It also changes the way hyperlinks with the same ID are highlighted, removing the restriction of being on consecutive lines and instead highlighting all visible cells that correspond to the matching hyperlink. Closes #7766. --- CHANGELOG.md | 1 + alacritty/src/cli.rs | 2 +- alacritty/src/config/ui_config.rs | 2 +- alacritty/src/display/hint.rs | 48 ++++++++------------------ alacritty/src/display/mod.rs | 2 +- alacritty/src/logging.rs | 2 +- alacritty_terminal/src/event_loop.rs | 1 - alacritty_terminal/src/grid/storage.rs | 2 +- alacritty_terminal/src/term/mod.rs | 2 -- alacritty_terminal/src/tty/unix.rs | 2 +- 10 files changed, 22 insertions(+), 42 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f5361861..63f2fe96 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -30,6 +30,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Mouse cursor not changing on Wayland when cursor theme uses legacy cursor icon names - Config keys are available under proper names - Build failure when compiling with x11 feature on NetBSD +- Hint `Select` action selecting the entire line for URL escapes ### Changed diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index fee2680f..d5e24b4a 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -5,7 +5,7 @@ use std::rc::Rc; use alacritty_config::SerdeReplace; use clap::{ArgAction, Args, Parser, Subcommand, ValueHint}; -use log::{self, error, LevelFilter}; +use log::{error, LevelFilter}; use serde::{Deserialize, Serialize}; use toml::Value; diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index 21059734..a4b6c2c5 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -10,7 +10,7 @@ use alacritty_terminal::term::Config as TermConfig; use alacritty_terminal::tty::{Options as PtyOptions, Shell}; use log::{error, warn}; use serde::de::{Error as SerdeError, MapAccess, Visitor}; -use serde::{self, Deserialize, Deserializer}; +use serde::{Deserialize, Deserializer}; use unicode_width::UnicodeWidthChar; use winit::keyboard::{Key, ModifiersState}; diff --git a/alacritty/src/display/hint.rs b/alacritty/src/display/hint.rs index bd09a881..f118dbe0 100644 --- a/alacritty/src/display/hint.rs +++ b/alacritty/src/display/hint.rs @@ -204,7 +204,8 @@ pub struct HintMatch { impl HintMatch { #[inline] pub fn should_highlight(&self, point: Point, pointed_hyperlink: Option<&Hyperlink>) -> bool { - self.bounds.contains(&point) && self.hyperlink.as_ref() == pointed_hyperlink + self.hyperlink.as_ref() == pointed_hyperlink + && (self.hyperlink.is_some() || self.bounds.contains(&point)) } #[inline] @@ -400,49 +401,30 @@ pub fn highlighted_at( } /// Retrieve the hyperlink with its range, if there is one at the specified point. +/// +/// This will only return contiguous cells, even if another hyperlink with the same ID exists. fn hyperlink_at(term: &Term, point: Point) -> Option<(Hyperlink, Match)> { let hyperlink = term.grid()[point].hyperlink()?; - let viewport_start = Line(-(term.grid().display_offset() as i32)); - let viewport_end = viewport_start + term.bottommost_line(); - - let mut match_start = Point::new(point.line, Column(0)); - let mut match_end = Point::new(point.line, Column(term.columns() - 1)); let grid = term.grid(); - // Find adjacent lines that have the same `hyperlink`. The end purpose to highlight hyperlinks - // that span across multiple lines or not directly attached to each other. - - // Find the closest to the viewport start adjacent line. - while match_start.line > viewport_start { - let next_line = match_start.line - 1i32; - // Iterate over all the cells in the grid's line and check if any of those cells contains - // the hyperlink we've found at original `point`. - let line_contains_hyperlink = grid[next_line] - .into_iter() - .any(|cell| cell.hyperlink().map_or(false, |h| h == hyperlink)); - - // There's no hyperlink on the next line, break. - if !line_contains_hyperlink { + let mut match_end = point; + for cell in grid.iter_from(point) { + if cell.hyperlink().map_or(false, |link| link == hyperlink) { + match_end = cell.point; + } else { break; } - - match_start.line = next_line; } - // Ditto for the end. - while match_end.line < viewport_end { - let next_line = match_end.line + 1i32; - - let line_contains_hyperlink = grid[next_line] - .into_iter() - .any(|cell| cell.hyperlink().map_or(false, |h| h == hyperlink)); - - if !line_contains_hyperlink { + let mut match_start = point; + let mut iter = grid.iter_from(point); + while let Some(cell) = iter.prev() { + if cell.hyperlink().map_or(false, |link| link == hyperlink) { + match_start = cell.point; + } else { break; } - - match_end.line = next_line; } Some((hyperlink, match_start..=match_end)) diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index dc37794d..4dafa80f 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -20,7 +20,7 @@ use winit::dpi::PhysicalSize; use winit::keyboard::ModifiersState; use winit::window::CursorIcon; -use crossfont::{self, Rasterize, Rasterizer, Size as FontSize}; +use crossfont::{Rasterize, Rasterizer, Size as FontSize}; use unicode_width::UnicodeWidthChar; use alacritty_terminal::event::{EventListener, OnResize, WindowSize}; diff --git a/alacritty/src/logging.rs b/alacritty/src/logging.rs index 42f1536e..a3833a5b 100644 --- a/alacritty/src/logging.rs +++ b/alacritty/src/logging.rs @@ -12,7 +12,7 @@ use std::sync::{Arc, Mutex, OnceLock}; use std::time::Instant; use std::{env, process}; -use log::{self, Level, LevelFilter}; +use log::{Level, LevelFilter}; use winit::event_loop::EventLoopProxy; use crate::cli::Options; diff --git a/alacritty_terminal/src/event_loop.rs b/alacritty_terminal/src/event_loop.rs index 929c642d..62dd7440 100644 --- a/alacritty_terminal/src/event_loop.rs +++ b/alacritty_terminal/src/event_loop.rs @@ -5,7 +5,6 @@ use std::collections::VecDeque; use std::fmt::{self, Display, Formatter}; use std::fs::File; use std::io::{self, ErrorKind, Read, Write}; -use std::marker::Send; use std::num::NonZeroUsize; use std::sync::mpsc::{self, Receiver, Sender, TryRecvError}; use std::sync::Arc; diff --git a/alacritty_terminal/src/grid/storage.rs b/alacritty_terminal/src/grid/storage.rs index d5709d14..0a2be43b 100644 --- a/alacritty_terminal/src/grid/storage.rs +++ b/alacritty_terminal/src/grid/storage.rs @@ -1,4 +1,4 @@ -use std::cmp::{max, PartialEq}; +use std::cmp::max; use std::mem; use std::mem::MaybeUninit; use std::ops::{Index, IndexMut}; diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 2ed6d7c9..f17f7462 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -2389,10 +2389,8 @@ pub mod test { #[cfg(feature = "serde")] use serde::{Deserialize, Serialize}; - use unicode_width::UnicodeWidthChar; use crate::event::VoidListener; - use crate::index::Column; #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct TermSize { diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 8ce04191..455abbd2 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -11,7 +11,7 @@ use std::process::{Child, Command, Stdio}; use std::sync::Arc; use std::{env, ptr}; -use libc::{self, c_int, TIOCSCTTY}; +use libc::{c_int, TIOCSCTTY}; use log::error; use polling::{Event, PollMode, Poller}; use rustix_openpty::openpty; From 1a73fe5fd2735bed5c8ec34b4f92c52f67ecfad9 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 14 Mar 2024 05:01:21 +0400 Subject: [PATCH 019/102] Bump winit to 0.29.15 --- Cargo.lock | 4 ++-- alacritty/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 07ee4cef..cdbdf0a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2270,9 +2270,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winit" -version = "0.29.14" +version = "0.29.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7a3db69ffbe53a9babec7804da7a90f21020fcce1f2f5e5291e2311245b993d" +checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" dependencies = [ "ahash", "android-activity", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 313dfed2..0baf323a 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -39,7 +39,7 @@ serde_json = "1" serde_yaml = "0.9.25" toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.29.14", default-features = false, features = ["rwh_05", "serde"] } +winit = { version = "0.29.15", default-features = false, features = ["rwh_05", "serde"] } [build-dependencies] gl_generator = "0.14.0" From 5b4e9c9a09df156aefdefed2075d9ff0d8e7ac74 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Fri, 15 Mar 2024 23:00:18 +0100 Subject: [PATCH 020/102] Bump dependencies This bumps all dependencies that can be updated without introducing a build failure. --- Cargo.lock | 314 +++++++++++++++++----------------- alacritty_terminal/Cargo.toml | 2 +- 2 files changed, 161 insertions(+), 155 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cdbdf0a5..73a02188 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -10,9 +10,9 @@ checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] name = "ahash" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cd52102d3df161c77a887b608d7a4897d7cc112886a9537b738a887a03aaff" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", "getrandom", @@ -38,7 +38,7 @@ dependencies = [ "alacritty_config", "alacritty_config_derive", "alacritty_terminal", - "bitflags 2.4.1", + "bitflags 2.4.2", "clap", "clap_complete", "cocoa", @@ -94,7 +94,7 @@ name = "alacritty_terminal" version = "0.22.1-dev" dependencies = [ "base64", - "bitflags 2.4.1", + "bitflags 2.4.2", "home", "libc", "log", @@ -114,12 +114,12 @@ dependencies = [ [[package]] name = "android-activity" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39b801912a977c3fd52d80511fe1c0c8480c6f957f21ae2ce1b92ffe970cf4b9" +checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" dependencies = [ "android-properties", - "bitflags 2.4.1", + "bitflags 2.4.2", "cc", "cesu8", "jni", @@ -141,9 +141,9 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "anstream" -version = "0.6.5" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d664a92ecae85fd0a7392615844904654d1d5f5514837f471ddef4a057aba1b6" +checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb" dependencies = [ "anstyle", "anstyle-parse", @@ -155,9 +155,9 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc" [[package]] name = "anstyle-parse" @@ -219,9 +219,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "base64" -version = "0.21.5" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9475866fec1451be56a3c2400fd081ff546538961565ccb5b7142cbd22bc7a51" [[package]] name = "bitflags" @@ -231,9 +231,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" dependencies = [ "serde", ] @@ -246,9 +246,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block-sys" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dd7cf50912cddc06dc5ea7c08c5e81c1b2c842a70d19def1848d54c586fed92" +checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" dependencies = [ "objc-sys", ] @@ -265,15 +265,15 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "7ff69b9dd49fd426c69a0db9fc04dd934cdb6645ff000864d98f7e2af8830eaa" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "5d6d68c57235a3a081186990eca2867354726650f42f7516ca50c28d6281fd15" [[package]] name = "bytes" @@ -283,11 +283,11 @@ checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "calloop" -version = "0.12.3" +version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50b5a44d59a98c55a9eeb518f39bf7499ba19fd98ee7d22618687f3f10adbf" +checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "log", "polling", "rustix", @@ -309,9 +309,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "8cd6604a82acf3039f1144f54b8eb34e91ffba622051189e71b781822d5ee1f5" dependencies = [ "jobserver", "libc", @@ -535,31 +535,27 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "b3855a8a784b474f333699ef2bbca9db2c4a1f6d9088a90a2d25b1eb53111eaa" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.10" +version = "0.5.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2" +checksum = "ab3db02a9c5b5121e1e42fbdb1aeb65f5e02624cc58c43f2884c6ccac0b82f95" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.18" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] +checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossfont" @@ -651,11 +647,12 @@ dependencies = [ [[package]] name = "embed-resource" -version = "2.4.0" +version = "2.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54cc3e827ee1c3812239a9a41dede7b4d7d5d5464faa32d71bd7cba28ce2cb2" +checksum = "c6985554d0688b687c5cb73898a34fbe3ad6c24c58c238a4d91d5e840670ee9d" dependencies = [ "cc", + "memchr", "rustc_version", "toml", "vswhom", @@ -696,9 +693,9 @@ checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fdeflate" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209098dd6dfc4445aa6111f0e98653ac323eaa4dfd212c9ca3931bf9955c31bd" +checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" dependencies = [ "simd-adler32", ] @@ -801,9 +798,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "190092ea657667030ac6a35e305e62fc4dd69fd98ac98631e5d3a2b1575a12b5" dependencies = [ "cfg-if", "libc", @@ -823,11 +820,11 @@ dependencies = [ [[package]] name = "glutin" -version = "0.31.2" +version = "0.31.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "005459a22af86adc706522d78d360101118e2638ec21df3852fcc626e0dbb212" +checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cfg_aliases", "cgl", "core-foundation", @@ -908,9 +905,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.1.0" +version = "2.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" dependencies = [ "equivalent", "hashbrown", @@ -966,18 +963,18 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "ab46a6e9526ddef3ae7f787c06f0f2600639ba80ea3eade3d8e670a2230f51d6" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" dependencies = [ "wasm-bindgen", ] @@ -1028,12 +1025,12 @@ checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd" [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.48.5", ] [[package]] @@ -1042,7 +1039,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall 0.4.1", ] @@ -1053,16 +1050,16 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "libc", "redox_syscall 0.4.1", ] [[package]] name = "linux-raw-sys" -version = "0.4.12" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "01cda141df6706de531b6c46c3a33ecca755538219bd484262fa09410c13539c" [[package]] name = "lock_api" @@ -1076,9 +1073,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" dependencies = [ "serde", ] @@ -1094,24 +1091,24 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45fd3a57831bf88bc63f8cebc0cf956116276e97fef3966103e96416209f7c92" +checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" dependencies = [ "libc", ] [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "9d811f3e15f28568be3407c8e7fdb6514c1cda3cb30683f15b6a1a1dc4ea14a7" dependencies = [ "adler", "simd-adler32", @@ -1144,7 +1141,7 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "jni-sys", "log", "ndk-sys", @@ -1174,7 +1171,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "crossbeam-channel", "filetime", "fsevent-sys", @@ -1189,18 +1186,18 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1328,15 +1325,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "png" -version = "0.17.10" +version = "0.17.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1361,18 +1358,18 @@ dependencies = [ [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" dependencies = [ - "toml_edit 0.20.7", + "toml_edit 0.21.1", ] [[package]] name = "proc-macro2" -version = "1.0.71" +version = "1.0.79" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +checksum = "e835ff2298f5721608eb1a980ecaee1aef2c132bf95ecc026a11b7bf3c01c02e" dependencies = [ "unicode-ident", ] @@ -1388,9 +1385,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.33" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" dependencies = [ "proc-macro2", ] @@ -1432,9 +1429,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" dependencies = [ "aho-corasick", "memchr", @@ -1462,7 +1459,7 @@ version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "errno", "itoa", "libc", @@ -1483,9 +1480,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1" [[package]] name = "same-file" @@ -1522,24 +1519,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "92d43fe69e652f3df9bdc2b85b2854a0825b86e4fb76bc44d945137d053639ca" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "3fb1c873e1b9b056a4dc4c0c198b24c3ffa059243875552b2bd0933b1aee4ce2" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.197" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "7eb0b34b42edc17f6b7cac84a52a1c5f0e1bb2227e997ca9011ea3dd34e8610b" dependencies = [ "proc-macro2", "quote", @@ -1548,9 +1545,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.114" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c5f09b1bd632ef549eaa9f60a1f8de742bdbc698e6cee2095fc84dde5f549ae0" dependencies = [ "itoa", "ryu", @@ -1568,9 +1565,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.29" +version = "0.9.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" +checksum = "a0623d197252096520c6f2a5e1171ee436e5af99a5d7caa2891e55e61950e6d9" dependencies = [ "indexmap", "itoa", @@ -1636,9 +1633,9 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "e6ecd384b10a64542d77071bd64bd7b231f4ed5940fba55e98c3de13824cf3d7" [[package]] name = "smithay-client-toolkit" @@ -1646,7 +1643,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "calloop", "calloop-wayland-source", "cursor-icon", @@ -1678,9 +1675,9 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" dependencies = [ "serde", ] @@ -1699,9 +1696,9 @@ checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" [[package]] name = "syn" -version = "2.0.43" +version = "2.0.53" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "7383cd0e49fff4b6b90ca5670bfd3e9d6a733b3f90c686605aa7eec8c4996032" dependencies = [ "proc-macro2", "quote", @@ -1710,18 +1707,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.52" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.52" +version = "1.0.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7" dependencies = [ "proc-macro2", "quote", @@ -1730,9 +1727,9 @@ dependencies = [ [[package]] name = "tiny-skia" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6a067b809476893fce6a254cf285850ff69c847e6cfbade6a20b655b6c7e80d" +checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" dependencies = [ "arrayref", "arrayvec", @@ -1744,9 +1741,9 @@ dependencies = [ [[package]] name = "tiny-skia-path" -version = "0.11.3" +version = "0.11.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5de35e8a90052baaaf61f171680ac2f8e925a1e43ea9d2e3a00514772250e541" +checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" dependencies = [ "arrayref", "bytemuck", @@ -1755,14 +1752,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.8" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "af06656561d28735e9c1cd63dfd57132c8155426aa6af24f36a00a351f88c48e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit 0.22.7", ] [[package]] @@ -1776,26 +1773,26 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.20.7" +version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" +checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ "indexmap", "toml_datetime", - "winnow", + "winnow 0.5.40", ] [[package]] name = "toml_edit" -version = "0.21.0" +version = "0.22.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow", + "winnow 0.6.5", ] [[package]] @@ -1822,9 +1819,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] name = "unicode-width" @@ -1834,9 +1831,9 @@ checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unsafe-libyaml" -version = "0.2.10" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab4c90930b95a82d00dc9e9ac071b4991924390d46cbd0dfe566148667605e4b" +checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" [[package]] name = "utf8parse" @@ -1876,7 +1873,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40eb22ae96f050e0c0d6f7ce43feeae26c348fc4dea56928ca81537cfaa6188b" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cursor-icon", "log", "serde", @@ -1896,9 +1893,9 @@ dependencies = [ [[package]] name = "walkdir" -version = "2.4.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" dependencies = [ "same-file", "winapi-util", @@ -1912,9 +1909,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1922,9 +1919,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" dependencies = [ "bumpalo", "log", @@ -1937,9 +1934,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" dependencies = [ "cfg-if", "js-sys", @@ -1949,9 +1946,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1959,9 +1956,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", @@ -1972,9 +1969,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" [[package]] name = "wayland-backend" @@ -1996,7 +1993,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "rustix", "wayland-backend", "wayland-scanner", @@ -2008,7 +2005,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "cursor-icon", "wayland-backend", ] @@ -2030,7 +2027,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "wayland-backend", "wayland-client", "wayland-scanner", @@ -2042,7 +2039,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2055,7 +2052,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2087,9 +2084,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" dependencies = [ "js-sys", "wasm-bindgen", @@ -2277,7 +2274,7 @@ dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.4.1", + "bitflags 2.4.2", "bytemuck", "calloop", "cfg_aliases", @@ -2319,18 +2316,27 @@ dependencies = [ [[package]] name = "winnow" -version = "0.5.30" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "winnow" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" dependencies = [ "memchr", ] [[package]] name = "winreg" -version = "0.51.0" +version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "937f3df7948156640f46aacef17a70db0de5917bda9c92b0f751f3a955b588fc" +checksum = "a277a57398d4bfa075df44f501a17cfdf8542d224f0d36095a2adc7aee4ef0a5" dependencies = [ "cfg-if", "windows-sys 0.48.0", @@ -2405,7 +2411,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.4.2", "dlib", "log", "once_cell", diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index 18ccdf11..bd7f02a1 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -14,7 +14,7 @@ default = ["serde"] serde = ["dep:serde", "bitflags/serde", "vte/serde"] [dependencies] -base64 = "0.21.3" +base64 = "0.22.0" bitflags = "2.4.1" home = "0.5.5" libc = "0.2" From 14b53f18dbae3f434a5011a9fb49b52574caedaf Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Mon, 18 Mar 2024 01:15:04 +0100 Subject: [PATCH 021/102] Drop MSRV to 1.70.0 --- CHANGELOG.md | 4 ---- alacritty/Cargo.toml | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 63f2fe96..7dadf41c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,10 +7,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## 0.14.0-dev -### Packaging - -- Minimum Rust version has been bumped to 1.72.0 - ### Added - Default `Home`/`End` bindings in Vi mode mapped to `First`/`Last` respectively diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 0baf323a..36156bf1 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -7,7 +7,7 @@ description = "A fast, cross-platform, OpenGL terminal emulator" readme = "README.md" homepage = "https://github.com/alacritty/alacritty" edition = "2021" -rust-version = "1.72.0" +rust-version = "1.70.0" [dependencies.alacritty_terminal] path = "../alacritty_terminal" From fe88aaa0855283d689dc41d531db916404ef9c51 Mon Sep 17 00:00:00 2001 From: Kirill Bulatov Date: Mon, 18 Mar 2024 03:15:39 +0200 Subject: [PATCH 022/102] Allow setting terminal env vars via PTY options Closes #7778. --- alacritty/src/cli.rs | 2 + alacritty/src/config/ui_config.rs | 7 +- alacritty_terminal/src/tty/mod.rs | 4 + alacritty_terminal/src/tty/unix.rs | 4 +- alacritty_terminal/src/tty/windows/conpty.rs | 80 ++++++++++++++++++-- 5 files changed, 90 insertions(+), 7 deletions(-) diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index d5e24b4a..91ba2fd6 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -1,4 +1,5 @@ use std::cmp::max; +use std::collections::HashMap; use std::ops::{Deref, DerefMut}; use std::path::PathBuf; use std::rc::Rc; @@ -195,6 +196,7 @@ impl From for PtyOptions { working_directory: options.working_directory.take(), shell: options.command().map(Into::into), hold: options.hold, + env: HashMap::new(), } } } diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index a4b6c2c5..580a3dad 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -167,7 +167,12 @@ 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 } + PtyOptions { + shell, + working_directory: self.working_directory.clone(), + hold: false, + env: HashMap::new(), + } } /// Generate key bindings for all keyboard hints. diff --git a/alacritty_terminal/src/tty/mod.rs b/alacritty_terminal/src/tty/mod.rs index 35d227b8..55d263ca 100644 --- a/alacritty_terminal/src/tty/mod.rs +++ b/alacritty_terminal/src/tty/mod.rs @@ -1,5 +1,6 @@ //! TTY related functionality. +use std::collections::HashMap; use std::path::PathBuf; use std::sync::Arc; use std::{env, io}; @@ -29,6 +30,9 @@ pub struct Options { /// Remain open after child process exits. pub hold: bool, + + /// Extra environment variables. + pub env: HashMap, } /// Shell options. diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 455abbd2..a4b07b74 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -217,9 +217,11 @@ pub fn new(config: &Options, window_size: WindowSize, window_id: u64) -> Result< builder.env("ALACRITTY_WINDOW_ID", &window_id); builder.env("USER", user.user); builder.env("HOME", user.home); - // Set Window ID for clients relying on X11 hacks. builder.env("WINDOWID", window_id); + for (key, value) in &config.env { + builder.env(key, value); + } unsafe { builder.pre_exec(move || { diff --git a/alacritty_terminal/src/tty/windows/conpty.rs b/alacritty_terminal/src/tty/windows/conpty.rs index 9731b4f0..244681e7 100644 --- a/alacritty_terminal/src/tty/windows/conpty.rs +++ b/alacritty_terminal/src/tty/windows/conpty.rs @@ -1,5 +1,8 @@ -use log::info; +use log::{info, warn}; +use std::collections::{HashMap, HashSet}; +use std::ffi::OsStr; use std::io::Error; +use std::os::windows::ffi::OsStrExt; use std::os::windows::io::IntoRawHandle; use std::{mem, ptr}; @@ -13,8 +16,8 @@ use windows_sys::{s, w}; use windows_sys::Win32::System::Threading::{ CreateProcessW, InitializeProcThreadAttributeList, UpdateProcThreadAttribute, - EXTENDED_STARTUPINFO_PRESENT, PROCESS_INFORMATION, PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, - STARTF_USESTDHANDLES, STARTUPINFOEXW, STARTUPINFOW, + CREATE_UNICODE_ENVIRONMENT, EXTENDED_STARTUPINFO_PRESENT, PROCESS_INFORMATION, + PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE, STARTF_USESTDHANDLES, STARTUPINFOEXW, STARTUPINFOW, }; use crate::event::{OnResize, WindowSize}; @@ -198,8 +201,18 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { } } + // Prepare child process creation arguments. let cmdline = win32_string(&cmdline(config)); let cwd = config.working_directory.as_ref().map(win32_string); + let mut creation_flags = EXTENDED_STARTUPINFO_PRESENT; + let custom_env_block = convert_custom_env(&config.env); + let custom_env_block_pointer = match &custom_env_block { + Some(custom_env_block) => { + creation_flags |= CREATE_UNICODE_ENVIRONMENT; + custom_env_block.as_ptr() as *mut std::ffi::c_void + }, + None => ptr::null_mut(), + }; let mut proc_info: PROCESS_INFORMATION = unsafe { mem::zeroed() }; unsafe { @@ -209,8 +222,8 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { ptr::null_mut(), ptr::null_mut(), false as i32, - EXTENDED_STARTUPINFO_PRESENT, - ptr::null_mut(), + creation_flags, + custom_env_block_pointer, cwd.as_ref().map_or_else(ptr::null, |s| s.as_ptr()), &mut startup_info_ex.StartupInfo as *mut STARTUPINFOW, &mut proc_info as *mut PROCESS_INFORMATION, @@ -230,6 +243,63 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { Some(Pty::new(conpty, conout, conin, child_watcher)) } +// Windows environment variables are case-insensitive, and the caller is responsible for +// deduplicating environment variables, so do that here while converting. +// +// https://learn.microsoft.com/en-us/previous-versions/troubleshoot/windows/win32/createprocess-cannot-eliminate-duplicate-variables#environment-variables +fn convert_custom_env(custom_env: &HashMap) -> Option> { + // Windows inherits parent's env when no `lpEnvironment` parameter is specified. + if custom_env.is_empty() { + return None; + } + + let mut converted_block = Vec::new(); + let mut all_env_keys = HashSet::new(); + for (custom_key, custom_value) in custom_env { + let custom_key_os = OsStr::new(custom_key); + if all_env_keys.insert(custom_key_os.to_ascii_uppercase()) { + add_windows_env_key_value_to_block( + &mut converted_block, + custom_key_os, + OsStr::new(&custom_value), + ); + } else { + warn!( + "Omitting environment variable pair with duplicate key: \ + '{custom_key}={custom_value}'" + ); + } + } + + // Pull the current process environment after, to avoid overwriting the user provided one. + for (inherited_key, inherited_value) in std::env::vars_os() { + if all_env_keys.insert(inherited_key.to_ascii_uppercase()) { + add_windows_env_key_value_to_block( + &mut converted_block, + &inherited_key, + &inherited_value, + ); + } + } + + converted_block.push(0); + Some(converted_block) +} + +// According to the `lpEnvironment` parameter description: +// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa#parameters +// +// > An environment block consists of a null-terminated block of null-terminated strings. Each +// string is in the following form: +// > +// > name=value\0 +fn add_windows_env_key_value_to_block(block: &mut Vec, key: &OsStr, value: &OsStr) { + block.extend(key.encode_wide()); + block.push('=' as u16); + block.extend(value.encode_wide()); + block.push(0); +} + // Panic with the last os error as message. fn panic_shell_spawn() { panic!("Unable to spawn shell: {}", Error::last_os_error()); From fd1a3cc79192d1d03839f0fd8c72e1f8d0fce42e Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 21 Mar 2024 08:00:06 +0400 Subject: [PATCH 023/102] Fix kitty encoding used for char input without text On Windows some key combinations for regular text input, like Ctrl+1 don't have any text attached, so they were generating the kitty escape sequence even when they shouldn't. --- CHANGELOG.md | 1 + alacritty/src/input/keyboard.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dadf41c..cbbd4bb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Config keys are available under proper names - Build failure when compiling with x11 feature on NetBSD - Hint `Select` action selecting the entire line for URL escapes +- Kitty encoding used for regular keys when they don't carry text ### Changed diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index b7635bd9..afb23eb5 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -347,7 +347,7 @@ impl SequenceBuilder { associated_text: Option<&str>, ) -> Option { let character = match key.logical_key.as_ref() { - Key::Character(character) => character, + Key::Character(character) if self.kitty_seq => character, _ => return None, }; From cef95324c9e2572a50e2d2334cbe2ba3641a12a8 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sun, 24 Mar 2024 05:00:41 +0100 Subject: [PATCH 024/102] Fix msi installer build This works around an issue where wix was pulling pre-release extensions and thus breaking compatibility with our used wix version. --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 17b2d1af..3918a540 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -48,10 +48,10 @@ jobs: ./.github/workflows/upload_asset.sh \ ./Alacritty-${GITHUB_REF##*/}-portable.exe $GITHUB_TOKEN - name: Install WiX - run: dotnet tool install --global wix --version 4.0.1 - - name: Crate msi installer + run: dotnet tool install --global wix --version 4.0.5 + - name: Create msi installer run: | - wix extension add WixToolset.UI.wixext WixToolset.Util.wixext + wix extension add WixToolset.UI.wixext/4.0.5 WixToolset.Util.wixext/4.0.5 wix build -arch "x64" -ext WixToolset.UI.wixext -ext WixToolset.Util.wixext \ -out "./Alacritty-${GITHUB_REF##*/}-installer.msi" "alacritty/windows/wix/alacritty.wxs" - name: Upload msi installer From a3be505f24c8412504468daf8d375a9ad81adbc1 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 24 Mar 2024 19:07:20 +0400 Subject: [PATCH 025/102] Send ESC with Alt for unicode input Make `Alt` send `ESC` for unicode input the way it's done for ASCII. Previously it was disabled because of macOS, however on macOS we're using the `option_as_alt` setting, which solves the original issue. The `Alt` prefixing is still disabled for the unicode strings, like when they come from the compose input. Fixes #7852. --- CHANGELOG.md | 1 + alacritty/src/input/keyboard.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index cbbd4bb8..d61e0e9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed +- Pressing `Alt` with unicode input will now add `ESC` like for ASCII input - No unused-key warnings will be emitted for OS-specific config keys - Use built-in font for sextant symbols from `U+1FB00` to `U+1FB3B` - Kitty encoding is not used anymore for uncommon keys unless the protocol enabled diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index afb23eb5..b4c35741 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -126,7 +126,7 @@ impl> Processor { self.ctx.modifiers().state().alt_key() } }, - _ => text.len() == 1 && alt_send_esc, + _ => alt_send_esc && text.chars().count() == 1, } } From 9af7eb1b31dde67d7b1bc1824e7a375a54e9c79a Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Tue, 26 Mar 2024 10:14:52 +0100 Subject: [PATCH 026/102] Add version 0.13.2 to CHANGELOG This is only an update to the development version and does not represent a stable release. --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d61e0e9e..fa9f0d65 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## 0.14.0-dev +### Changed + +- Pressing `Alt` with unicode input will now add `ESC` like for ASCII input + +## 0.13.2 + ### Added - Default `Home`/`End` bindings in Vi mode mapped to `First`/`Last` respectively @@ -31,7 +37,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### Changed -- Pressing `Alt` with unicode input will now add `ESC` like for ASCII input - No unused-key warnings will be emitted for OS-specific config keys - Use built-in font for sextant symbols from `U+1FB00` to `U+1FB3B` - Kitty encoding is not used anymore for uncommon keys unless the protocol enabled From 6585d60408be1d6c275a41e4c94da092482a1ea7 Mon Sep 17 00:00:00 2001 From: ZhiZe-ZG <75554862+ZhiZe-ZG@users.noreply.github.com> Date: Thu, 28 Mar 2024 23:17:41 +0800 Subject: [PATCH 027/102] Fix "Open Alacritty Here" on Windows --- alacritty/windows/wix/alacritty.wxs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alacritty/windows/wix/alacritty.wxs b/alacritty/windows/wix/alacritty.wxs index 0ef66ec3..cd64ec7b 100644 --- a/alacritty/windows/wix/alacritty.wxs +++ b/alacritty/windows/wix/alacritty.wxs @@ -41,7 +41,7 @@ - + From d4f2f8577f763df059653dfab733dfe6ddc06913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Foorack=20/=20Max=20Fax=C3=A4lv?= Date: Sun, 31 Mar 2024 03:57:09 +0200 Subject: [PATCH 028/102] Update homepage and repository in Cargo manifests --- alacritty/Cargo.toml | 3 ++- alacritty_config/Cargo.toml | 3 ++- alacritty_config_derive/Cargo.toml | 3 ++- alacritty_terminal/Cargo.toml | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 36156bf1..cbdd2b00 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -5,7 +5,8 @@ authors = ["Christian Duerr ", "Joe Wilm "] license = "MIT OR Apache-2.0" description = "Alacritty configuration abstractions" -homepage = "https://github.com/alacritty/alacritty" +homepage = "https://alacritty.org" +repository = "https://github.com/alacritty/alacritty" edition = "2021" rust-version = "1.70.0" diff --git a/alacritty_config_derive/Cargo.toml b/alacritty_config_derive/Cargo.toml index 655cde3c..dce13237 100644 --- a/alacritty_config_derive/Cargo.toml +++ b/alacritty_config_derive/Cargo.toml @@ -4,7 +4,8 @@ version = "0.2.3-dev" authors = ["Christian Duerr "] license = "MIT OR Apache-2.0" description = "Failure resistant deserialization derive" -homepage = "https://github.com/alacritty/alacritty" +homepage = "https://alacritty.org" +repository = "https://github.com/alacritty/alacritty" edition = "2021" rust-version = "1.70.0" diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index bd7f02a1..3c761b63 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -5,7 +5,8 @@ authors = ["Christian Duerr ", "Joe Wilm Date: Thu, 18 Apr 2024 22:58:15 +0400 Subject: [PATCH 029/102] Fix window being focused by default Winit explicitly states that the window is not focused by default and the `Focused` event will deliver the state later on. Also start adding notable changes to alacritty_terminal in its own CHANGELOG. Closes #7866. --- CHANGELOG.md | 7 +++++++ CONTRIBUTING.md | 9 +++++---- Cargo.lock | 2 +- alacritty/Cargo.toml | 2 +- alacritty_terminal/CHANGELOG.md | 15 ++++++++++++++ alacritty_terminal/Cargo.toml | 2 +- alacritty_terminal/src/term/mod.rs | 32 +++++++++++++++--------------- 7 files changed, 46 insertions(+), 23 deletions(-) create mode 100644 alacritty_terminal/CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md index fa9f0d65..b6e47476 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,8 +5,15 @@ The sections should follow the order `Packaging`, `Added`, `Changed`, `Fixed` an 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 +### Fixed + +- New window being treated as focused when it's not on Wayland + ### Changed - Pressing `Alt` with unicode input will now add `ESC` like for ASCII input diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b07c02ef..fe7b2a71 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -91,10 +91,11 @@ If any change has been made to the `config.rs` file, it should also be documente Changes compared to the latest Alacritty release which have a direct effect on the user (opposed to things like code refactorings or documentation/tests) additionally need to be documented in the -`CHANGELOG.md`. The existing entries should be used as a style guideline. The change log should be -used to document changes from a user-perspective, instead of explaining the technical background -(like commit messages). More information about Alacritty's change log format can be found -[here](https://keepachangelog.com). +`CHANGELOG.md`. When a notable change is made to `alacritty_terminal`, it should be documented in +`alacritty_terminal/CHANGELOG.md` as well. The existing entries should be used as a style guideline. +The change log should be used to document changes from a user-perspective, instead of explaining the +technical background (like commit messages) More information about Alacritty's change log format can +be found [here](https://keepachangelog.com). ### Style diff --git a/Cargo.lock b/Cargo.lock index 73a02188..89a12c08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,7 +91,7 @@ dependencies = [ [[package]] name = "alacritty_terminal" -version = "0.22.1-dev" +version = "0.23.0-dev" dependencies = [ "base64", "bitflags 2.4.2", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index cbdd2b00..b305197e 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -12,7 +12,7 @@ rust-version = "1.70.0" [dependencies.alacritty_terminal] path = "../alacritty_terminal" -version = "0.22.1-dev" +version = "0.23.0-dev" [dependencies.alacritty_config_derive] path = "../alacritty_config_derive" diff --git a/alacritty_terminal/CHANGELOG.md b/alacritty_terminal/CHANGELOG.md new file mode 100644 index 00000000..b8dd33e8 --- /dev/null +++ b/alacritty_terminal/CHANGELOG.md @@ -0,0 +1,15 @@ +# Changelog + +All notable changes to alacritty_terminal are documented in this file. The +sections should follow the order `Added`, `Changed`, `Deprecated`, `Fixed` and +`Removed`. + +**Breaking changes are written in bold style.** + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). + +## 0.23.0-dev + +### Changed + +- **`Term` is not focused by default anymore** diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index 3c761b63..92731db7 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alacritty_terminal" -version = "0.22.1-dev" +version = "0.23.0-dev" authors = ["Christian Duerr ", "Joe Wilm "] license = "Apache-2.0" description = "Library for writing terminal emulators" diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index f17f7462..54b64a73 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -407,13 +407,13 @@ impl Term { } } - pub fn new(options: Config, dimensions: &D, event_proxy: T) -> Term { + pub fn new(config: Config, dimensions: &D, event_proxy: T) -> Term { let num_cols = dimensions.columns(); let num_lines = dimensions.screen_lines(); - let history_size = options.scrolling_history; + let history_size = config.scrolling_history; let grid = Grid::new(num_lines, num_cols, history_size); - let alt = Grid::new(num_lines, num_cols, 0); + let inactive_grid = Grid::new(num_lines, num_cols, 0); let tabs = TabStops::new(grid.columns()); @@ -423,24 +423,24 @@ impl Term { let damage = TermDamageState::new(num_cols, num_lines); Term { + inactive_grid, + scroll_region, + event_proxy, + damage, + config, grid, - inactive_grid: alt, + tabs, + inactive_keyboard_mode_stack: Default::default(), + keyboard_mode_stack: Default::default(), active_charset: Default::default(), vi_mode_cursor: Default::default(), - tabs, - mode: Default::default(), - scroll_region, + cursor_style: Default::default(), colors: color::Colors::default(), - cursor_style: None, - event_proxy, - is_focused: true, - title: None, title_stack: Default::default(), - keyboard_mode_stack: Default::default(), - inactive_keyboard_mode_stack: Default::default(), - selection: None, - damage, - config: options, + is_focused: Default::default(), + selection: Default::default(), + title: Default::default(), + mode: Default::default(), } } From 18fff6a12b2d20ae76fc3152db01daaa71a96aba Mon Sep 17 00:00:00 2001 From: William Viktorsson Date: Sun, 21 Apr 2024 01:11:46 +0200 Subject: [PATCH 030/102] Fix crash when trying to open a new tab on macOS This fixes an issue where Alacritty would crash when trying to open a new tab on macOS while having decorations disabled. Co-authored-by: Christian Duerr --- CHANGELOG.md | 1 + alacritty/src/input/mod.rs | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b6e47476..e6b301e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,6 +12,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its ### Fixed +- Crash when trying to create a new tab without decorations enabled - New window being treated as focused when it's not on Wayland ### Changed diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index 9a96b45b..365717c3 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -36,6 +36,8 @@ use alacritty_terminal::vi_mode::ViMotion; use alacritty_terminal::vte::ansi::{ClearMode, Handler}; use crate::clipboard::Clipboard; +#[cfg(target_os = "macos")] +use crate::config::window::Decorations; use crate::config::{Action, BindingMode, MouseAction, SearchAction, UiConfig, ViAction}; use crate::display::hint::HintMatch; use crate::display::window::Window; @@ -385,8 +387,11 @@ impl Execute for Action { Action::CreateNewWindow => ctx.create_new_window(None), #[cfg(target_os = "macos")] Action::CreateNewTab => { - let tabbing_id = Some(ctx.window().tabbing_id()); - ctx.create_new_window(tabbing_id); + // Tabs on macOS are not possible without decorations. + if ctx.config().window.decorations != Decorations::None { + let tabbing_id = Some(ctx.window().tabbing_id()); + ctx.create_new_window(tabbing_id); + } }, #[cfg(target_os = "macos")] Action::SelectNextTab => ctx.window().select_next_tab(), From 44dc9e19f4bbf89d1789502953683ca201668fe4 Mon Sep 17 00:00:00 2001 From: Matt Fellenz Date: Sun, 21 Apr 2024 04:12:55 -0700 Subject: [PATCH 031/102] Fix missing config import warning --- alacritty/src/config/mod.rs | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs index a77ed770..4ae3b67d 100644 --- a/alacritty/src/config/mod.rs +++ b/alacritty/src/config/mod.rs @@ -263,13 +263,12 @@ fn load_imports(config: &Value, config_paths: &mut Vec, recursion_limit }, }; - if !path.exists() { - info!(target: LOG_TARGET_CONFIG, "Config import not found:\n {:?}", path.display()); - continue; - } - match parse_config(&path, config_paths, recursion_limit - 1) { Ok(config) => merged = serde_utils::merge(merged, config), + Err(Error::Io(io)) if io.kind() == io::ErrorKind::NotFound => { + info!(target: LOG_TARGET_CONFIG, "Config import not found:\n {:?}", path.display()); + continue; + }, Err(err) => { error!(target: LOG_TARGET_CONFIG, "Unable to import config {:?}: {}", path, err) }, From 90054614c241375839571d4dd2145edcb65257a6 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 21 Apr 2024 15:23:10 +0400 Subject: [PATCH 032/102] Fix IME preview overlapping text Fix incorrect usage of the `flags` when drawing the preedit resulting in setting the `flags`, but not actually reading the value back. The logic to skip things was also used incorrectly, because the renderer does that already based on the `WIDE_CHAR` flag on the cell. Fixes: 67a433ceed (Skip whitespaces for wide chars in preedit) --- CHANGELOG.md | 9 +++++---- alacritty/src/renderer/mod.rs | 31 +++++++++++++++---------------- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6b301e2..b41ed24f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,14 +10,15 @@ Notable changes to the `alacritty_terminal` crate are documented in its ## 0.14.0-dev +### Changed + +- Pressing `Alt` with unicode input will now add `ESC` like for ASCII input + ### Fixed - Crash when trying to create a new tab without decorations enabled - New window being treated as focused when it's not on Wayland - -### Changed - -- Pressing `Alt` with unicode input will now add `ESC` like for ASCII input +- IME preview blending into text below it ## 0.13.2 diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index 02bfd762..f4f1397f 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -205,30 +205,29 @@ impl Renderer { size_info: &SizeInfo, glyph_cache: &mut GlyphCache, ) { - let mut skip_next = false; - let cells = string_chars.enumerate().filter_map(|(i, character)| { - if skip_next { - skip_next = false; - return None; - } - - let mut flags = Flags::empty(); - if character.width() == Some(2) { - flags.insert(Flags::WIDE_CHAR); - // Wide character is always followed by a spacer, so skip it. - skip_next = true; - } + let mut wide_char_spacer = false; + let cells = string_chars.enumerate().map(|(i, character)| { + let flags = if wide_char_spacer { + wide_char_spacer = false; + Flags::WIDE_CHAR_SPACER + } else if character.width() == Some(2) { + // The spacer is always following the wide char. + wide_char_spacer = true; + Flags::WIDE_CHAR + } else { + Flags::empty() + }; - Some(RenderableCell { + RenderableCell { point: Point::new(point.line, point.column + i), character, extra: None, - flags: Flags::empty(), + flags, bg_alpha: 1.0, fg, bg, underline: fg, - }) + } }); self.draw_cells(size_info, glyph_cache, cells); From ce800bfde2a2121a830c2b0854749875b3aebf79 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Tue, 23 Apr 2024 17:42:16 +0200 Subject: [PATCH 033/102] Fix dynamic title override for multiple windows This fixes an issue where Windows spawned after the initial one through IPC or bindings would not update their title due to the initial window having its title set through the CLI. Title changes are still inhibited for additional windows when they are spawned through `alacritty msg create-window` with the `--title` CLI option added. Closes #6836. --- CHANGELOG.md | 1 + alacritty/src/cli.rs | 14 -------------- alacritty/src/event.rs | 9 ++++++--- alacritty/src/window_context.rs | 3 ++- 4 files changed, 9 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b41ed24f..959ae73e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Crash when trying to create a new tab without decorations enabled - New window being treated as focused when it's not on Wayland - IME preview blending into text below it +- Dynamic title disabled for new windows when initial one has title as CLI option ## 0.13.2 diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index 91ba2fd6..e7f2d3ef 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -92,7 +92,6 @@ impl Options { config.ipc_socket |= self.socket.is_some(); } - config.window.dynamic_title &= self.window_options.window_identity.title.is_none(); config.window.embed = self.embed.as_ref().and_then(|embed| parse_hex_or_decimal(embed)); config.debug.print_events |= self.print_events; config.debug.log_level = max(config.debug.log_level, self.log_level()); @@ -425,19 +424,6 @@ mod tests { assert_eq!(old_dynamic_title, config.window.dynamic_title); } - #[test] - fn dynamic_title_overridden_by_options() { - let mut config = UiConfig::default(); - - let title = Some(String::from("foo")); - let window_identity = WindowIdentity { title, ..WindowIdentity::default() }; - let new_window_options = WindowOptions { window_identity, ..WindowOptions::default() }; - let mut options = Options { window_options: new_window_options, ..Options::default() }; - options.override_config(&mut config); - - assert!(!config.window.dynamic_title); - } - #[test] fn dynamic_title_not_overridden_by_config() { let mut config = UiConfig::default(); diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 4fa397ad..5276776a 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -217,6 +217,7 @@ pub struct ActionContext<'a, N, T> { pub message_buffer: &'a mut MessageBuffer, pub config: &'a UiConfig, pub cursor_blink_timed_out: &'a mut bool, + #[cfg(target_os = "macos")] pub event_loop: &'a EventLoopWindowTarget, pub event_proxy: &'a EventLoopProxy, pub scheduler: &'a mut Scheduler, @@ -1213,7 +1214,6 @@ pub struct Mouse { pub click_state: ClickState, pub accumulated_scroll: AccumulatedScroll, pub cell_side: Side, - pub lines_scrolled: f32, pub block_hint_launcher: bool, pub hint_highlight_dirty: bool, pub inside_text_area: bool, @@ -1234,7 +1234,6 @@ impl Default for Mouse { hint_highlight_dirty: Default::default(), block_hint_launcher: Default::default(), inside_text_area: Default::default(), - lines_scrolled: Default::default(), accumulated_scroll: Default::default(), x: Default::default(), y: Default::default(), @@ -1313,7 +1312,7 @@ impl input::Processor> { }, TerminalEvent::ResetTitle => { let window_config = &self.ctx.config.window; - if window_config.dynamic_title { + if !self.ctx.preserve_title && window_config.dynamic_title { self.ctx.display.window.set_title(window_config.identity.title.clone()); } }, @@ -1694,6 +1693,7 @@ impl Processor { }; window_context.handle_event( + #[cfg(target_os = "macos")] event_loop, &proxy, &mut clipboard, @@ -1708,6 +1708,7 @@ impl Processor { // Dispatch event to all windows. for window_context in self.windows.values_mut() { window_context.handle_event( + #[cfg(target_os = "macos")] event_loop, &proxy, &mut clipboard, @@ -1794,6 +1795,7 @@ impl Processor { WinitEvent::UserEvent(event @ Event { window_id: None, .. }) => { for window_context in self.windows.values_mut() { window_context.handle_event( + #[cfg(target_os = "macos")] event_loop, &proxy, &mut clipboard, @@ -1807,6 +1809,7 @@ impl Processor { | WinitEvent::UserEvent(Event { window_id: Some(window_id), .. }) => { if let Some(window_context) = self.windows.get_mut(&window_id) { window_context.handle_event( + #[cfg(target_os = "macos")] event_loop, &proxy, &mut clipboard, diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index 891551bb..f0f24fe8 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -399,7 +399,7 @@ impl WindowContext { /// Process events for this terminal window. pub fn handle_event( &mut self, - event_loop: &EventLoopWindowTarget, + #[cfg(target_os = "macos")] event_loop: &EventLoopWindowTarget, event_proxy: &EventLoopProxy, clipboard: &mut Clipboard, scheduler: &mut Scheduler, @@ -445,6 +445,7 @@ impl WindowContext { preserve_title: self.preserve_title, config: &self.config, event_proxy, + #[cfg(target_os = "macos")] event_loop, clipboard, scheduler, From ed3fac8a033acf10293712339185920849d45a0a Mon Sep 17 00:00:00 2001 From: Owen Law <81528246+someone13574@users.noreply.github.com> Date: Wed, 1 May 2024 01:27:54 -0400 Subject: [PATCH 034/102] Add `from_file_descriptors()` to `tty::unix` --- alacritty_terminal/CHANGELOG.md | 4 ++++ alacritty_terminal/src/tty/unix.rs | 6 ++++++ 2 files changed, 10 insertions(+) diff --git a/alacritty_terminal/CHANGELOG.md b/alacritty_terminal/CHANGELOG.md index b8dd33e8..8f416235 100644 --- a/alacritty_terminal/CHANGELOG.md +++ b/alacritty_terminal/CHANGELOG.md @@ -10,6 +10,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## 0.23.0-dev +### Added + +- `tty::unix::from_fd()` to create a TTY from a pre-opened PTY's file-descriptors + ### Changed - **`Term` is not focused by default anymore** diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index a4b07b74..54118a58 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -4,6 +4,7 @@ use std::ffi::CStr; use std::fs::File; use std::io::{Error, ErrorKind, Read, Result}; use std::mem::MaybeUninit; +use std::os::fd::OwnedFd; use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::net::UnixStream; use std::os::unix::process::CommandExt; @@ -184,6 +185,11 @@ fn default_shell_command(shell: &str, user: &str) -> Command { pub fn new(config: &Options, window_size: WindowSize, window_id: u64) -> Result { let pty = openpty(None, Some(&window_size.to_winsize()))?; let (master, slave) = (pty.controller, pty.user); + from_fd(config, window_id, master, slave) +} + +/// Create a new TTY from a PTY's file descriptors. +pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd) -> Result { let master_fd = master.as_raw_fd(); let slave_fd = slave.as_raw_fd(); From 26ed8e1b9dfe2e4c5d23dc80043554197113d83f Mon Sep 17 00:00:00 2001 From: Aarni Koskela Date: Fri, 3 May 2024 20:44:17 +0300 Subject: [PATCH 035/102] Add config file locations into alacritty(5) --- README.md | 6 ++---- extra/man/alacritty.5.scd | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index af678ff8..d00520b4 100644 --- a/README.md +++ b/README.md @@ -69,11 +69,9 @@ following locations: 3. `$HOME/.config/alacritty/alacritty.toml` 4. `$HOME/.alacritty.toml` -### Windows +On Windows, the config file will be looked for in: -On Windows, the config file should be located at: - -`%APPDATA%\alacritty\alacritty.toml` +* `%APPDATA%\alacritty\alacritty.toml` ## Contributing diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index 81637f3e..a26b3d96 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -9,6 +9,20 @@ Alacritty - TOML configuration file format. Alacritty's configuration file uses the TOML format. The format's specification can be found at _https://toml.io/en/v1.0.0_. +# LOCATION + +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 config file will be looked for in: + +. `%APPDATA%\alacritty\alacritty.toml` + # GENERAL This section documents the root level of the configuration file. From 82f41ed65ce0d3207d56d6877fd0ed898d7dce0c Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Fri, 3 May 2024 21:47:41 +0200 Subject: [PATCH 036/102] Bump alacritty_terminal to 0.24.1-dev This is only an update to the development version and does not represent a stable release. --- Cargo.lock | 2 +- alacritty/Cargo.toml | 2 +- alacritty_terminal/CHANGELOG.md | 4 +++- alacritty_terminal/Cargo.toml | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89a12c08..c4197c3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,7 +91,7 @@ dependencies = [ [[package]] name = "alacritty_terminal" -version = "0.23.0-dev" +version = "0.24.1-dev" dependencies = [ "base64", "bitflags 2.4.2", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index b305197e..7fcbb13a 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -12,7 +12,7 @@ rust-version = "1.70.0" [dependencies.alacritty_terminal] path = "../alacritty_terminal" -version = "0.23.0-dev" +version = "0.24.1-dev" [dependencies.alacritty_config_derive] path = "../alacritty_config_derive" diff --git a/alacritty_terminal/CHANGELOG.md b/alacritty_terminal/CHANGELOG.md index 8f416235..82636168 100644 --- a/alacritty_terminal/CHANGELOG.md +++ b/alacritty_terminal/CHANGELOG.md @@ -8,7 +8,9 @@ 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.23.0-dev +## 0.24.1-dev + +## 0.24.0 ### Added diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index 92731db7..ed36cc36 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alacritty_terminal" -version = "0.23.0-dev" +version = "0.24.1-dev" authors = ["Christian Duerr ", "Joe Wilm "] license = "Apache-2.0" description = "Library for writing terminal emulators" From a77f77c48fca298caab3a4834b2d7ab1a98cae88 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Fri, 3 May 2024 22:20:45 +0200 Subject: [PATCH 037/102] Fix shutdown of config monitor This implements a coordinated shutdown of the config monitor by sending an event to its thread and waiting for the thread to terminate. --- alacritty/src/config/monitor.rs | 240 ++++++++++++++++++-------------- alacritty/src/main.rs | 13 +- 2 files changed, 143 insertions(+), 110 deletions(-) diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs index f4b39a22..53cff1c9 100644 --- a/alacritty/src/config/monitor.rs +++ b/alacritty/src/config/monitor.rs @@ -1,9 +1,13 @@ use std::path::PathBuf; -use std::sync::mpsc::{self, RecvTimeoutError}; +use std::sync::mpsc::{self, RecvTimeoutError, Sender}; +use std::thread::JoinHandle; use std::time::{Duration, Instant}; -use log::{debug, error}; -use notify::{Config, EventKind, RecommendedWatcher, RecursiveMode, Watcher}; +use log::{debug, error, warn}; +use notify::{ + Config, Error as NotifyError, Event as NotifyEvent, EventKind, RecommendedWatcher, + RecursiveMode, Watcher, +}; use winit::event_loop::EventLoopProxy; use alacritty_terminal::thread; @@ -15,115 +19,139 @@ const DEBOUNCE_DELAY: Duration = Duration::from_millis(10); /// The fallback for `RecommendedWatcher` polling. const FALLBACK_POLLING_TIMEOUT: Duration = Duration::from_secs(1); -pub fn watch(mut paths: Vec, event_proxy: EventLoopProxy) { - // Don't monitor config if there is no path to watch. - if paths.is_empty() { - return; - } +/// Config file update monitor. +pub struct ConfigMonitor { + thread: JoinHandle<()>, + shutdown_tx: Sender>, +} - // Exclude char devices like `/dev/null`, sockets, and so on, by checking that file type is a - // regular file. - paths.retain(|path| { - // Call `metadata` to resolve symbolic links. - path.metadata().map_or(false, |metadata| metadata.file_type().is_file()) - }); - - // Canonicalize paths, keeping the base paths for symlinks. - for i in 0..paths.len() { - if let Ok(canonical_path) = paths[i].canonicalize() { - match paths[i].symlink_metadata() { - Ok(metadata) if metadata.file_type().is_symlink() => paths.push(canonical_path), - _ => paths[i] = canonical_path, - } +impl ConfigMonitor { + pub fn new(mut paths: Vec, event_proxy: EventLoopProxy) -> Option { + // Don't monitor config if there is no path to watch. + if paths.is_empty() { + return None; } - } - // The Duration argument is a debouncing period. - let (tx, rx) = mpsc::channel(); - let mut watcher = match RecommendedWatcher::new( - tx, - Config::default().with_poll_interval(FALLBACK_POLLING_TIMEOUT), - ) { - Ok(watcher) => watcher, - Err(err) => { - error!("Unable to watch config file: {}", err); - return; - }, - }; - - thread::spawn_named("config watcher", move || { - // Get all unique parent directories. - let mut parents = paths - .iter() - .map(|path| { - let mut path = path.clone(); - path.pop(); - path - }) - .collect::>(); - parents.sort_unstable(); - parents.dedup(); - - // Watch all configuration file directories. - for parent in &parents { - if let Err(err) = watcher.watch(parent, RecursiveMode::NonRecursive) { - debug!("Unable to watch config directory {:?}: {}", parent, err); + // Exclude char devices like `/dev/null`, sockets, and so on, by checking that file type is + // a regular file. + paths.retain(|path| { + // Call `metadata` to resolve symbolic links. + path.metadata().map_or(false, |metadata| metadata.file_type().is_file()) + }); + + // Canonicalize paths, keeping the base paths for symlinks. + for i in 0..paths.len() { + if let Ok(canonical_path) = paths[i].canonicalize() { + match paths[i].symlink_metadata() { + Ok(metadata) if metadata.file_type().is_symlink() => paths.push(canonical_path), + _ => paths[i] = canonical_path, + } } } - // The current debouncing time. - let mut debouncing_deadline: Option = None; - - // The events accumulated during the debounce period. - let mut received_events = Vec::new(); - - loop { - // We use `recv_timeout` to debounce the events coming from the watcher and reduce - // the amount of config reloads. - let event = match debouncing_deadline.as_ref() { - Some(debouncing_deadline) => { - rx.recv_timeout(debouncing_deadline.saturating_duration_since(Instant::now())) - }, - None => { - let event = rx.recv().map_err(Into::into); - // Set the debouncing deadline after receiving the event. - debouncing_deadline = Some(Instant::now() + DEBOUNCE_DELAY); - event - }, - }; - - match event { - Ok(Ok(event)) => match event.kind { - EventKind::Any - | EventKind::Create(_) - | EventKind::Modify(_) - | EventKind::Other => { - received_events.push(event); + // The Duration argument is a debouncing period. + let (tx, rx) = mpsc::channel(); + let mut watcher = match RecommendedWatcher::new( + tx.clone(), + Config::default().with_poll_interval(FALLBACK_POLLING_TIMEOUT), + ) { + Ok(watcher) => watcher, + Err(err) => { + error!("Unable to watch config file: {}", err); + return None; + }, + }; + + let join_handle = thread::spawn_named("config watcher", move || { + // Get all unique parent directories. + let mut parents = paths + .iter() + .map(|path| { + let mut path = path.clone(); + path.pop(); + path + }) + .collect::>(); + parents.sort_unstable(); + parents.dedup(); + + // Watch all configuration file directories. + for parent in &parents { + if let Err(err) = watcher.watch(parent, RecursiveMode::NonRecursive) { + debug!("Unable to watch config directory {:?}: {}", parent, err); + } + } + + // The current debouncing time. + let mut debouncing_deadline: Option = None; + + // The events accumulated during the debounce period. + let mut received_events = Vec::new(); + + loop { + // We use `recv_timeout` to debounce the events coming from the watcher and reduce + // the amount of config reloads. + let event = match debouncing_deadline.as_ref() { + Some(debouncing_deadline) => rx.recv_timeout( + debouncing_deadline.saturating_duration_since(Instant::now()), + ), + None => { + let event = rx.recv().map_err(Into::into); + // Set the debouncing deadline after receiving the event. + debouncing_deadline = Some(Instant::now() + DEBOUNCE_DELAY); + event + }, + }; + + match event { + Ok(Ok(event)) => match event.kind { + EventKind::Other if event.info() == Some("shutdown") => break, + EventKind::Any + | EventKind::Create(_) + | EventKind::Modify(_) + | EventKind::Other => { + received_events.push(event); + }, + _ => (), + }, + Err(RecvTimeoutError::Timeout) => { + // Go back to polling the events. + debouncing_deadline = None; + + if received_events + .drain(..) + .flat_map(|event| event.paths.into_iter()) + .any(|path| paths.contains(&path)) + { + // Always reload the primary configuration file. + let event = Event::new(EventType::ConfigReload(paths[0].clone()), None); + let _ = event_proxy.send_event(event); + } }, - _ => (), - }, - Err(RecvTimeoutError::Timeout) => { - // Go back to polling the events. - debouncing_deadline = None; - - if received_events - .drain(..) - .flat_map(|event| event.paths.into_iter()) - .any(|path| paths.contains(&path)) - { - // Always reload the primary configuration file. - let event = Event::new(EventType::ConfigReload(paths[0].clone()), None); - let _ = event_proxy.send_event(event); - } - }, - Ok(Err(err)) => { - debug!("Config watcher errors: {:?}", err); - }, - Err(err) => { - debug!("Config watcher channel dropped unexpectedly: {}", err); - break; - }, - }; + Ok(Err(err)) => { + debug!("Config watcher errors: {:?}", err); + }, + Err(err) => { + debug!("Config watcher channel dropped unexpectedly: {}", err); + break; + }, + }; + } + }); + + Some(Self { thread: join_handle, shutdown_tx: tx }) + } + + /// Synchronously shut down the monitor. + pub fn shutdown(self) { + // Request shutdown. + let mut event = NotifyEvent::new(EventKind::Other); + event = event.set_info("shutdown"); + let _ = self.shutdown_tx.send(Ok(event)); + + // Wait for thread to terminate. + if let Err(err) = self.thread.join() { + warn!("config monitor shutdown failed: {err:?}"); } - }); + } } diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 2a60961a..f9301767 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -56,7 +56,8 @@ mod gl { #[cfg(unix)] use crate::cli::MessageOptions; use crate::cli::{Options, Subcommands}; -use crate::config::{monitor, UiConfig}; +use crate::config::monitor::ConfigMonitor; +use crate::config::UiConfig; use crate::event::{Event, Processor}; #[cfg(target_os = "macos")] use crate::macos::locale; @@ -165,8 +166,10 @@ fn alacritty(mut options: Options) -> Result<(), Box> { // // 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 { - monitor::watch(config.config_paths.clone(), window_event_loop.create_proxy()); + config_monitor = + ConfigMonitor::new(config.config_paths.clone(), window_event_loop.create_proxy()); } // Create the IPC socket listener. @@ -205,8 +208,10 @@ fn alacritty(mut options: Options) -> Result<(), Box> { // FIXME: Change PTY API to enforce the correct drop order with the typesystem. drop(processor); - // FIXME patch notify library to have a shutdown method. - // config_reloader.join().ok(); + // Terminate the config monitor. + if let Some(config_monitor) = config_monitor.take() { + config_monitor.shutdown(); + } // Without explicitly detaching the console cmd won't redraw it's prompt. #[cfg(windows)] From 48c088a50c977dfaf2a5a7052a5ddd39071e6063 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 4 May 2024 20:51:56 +0400 Subject: [PATCH 038/102] Bump winit to 0.30.0 --- CHANGELOG.md | 1 + Cargo.lock | 309 +++++++++---- alacritty/Cargo.toml | 6 +- alacritty/src/clipboard.rs | 6 +- alacritty/src/display/window.rs | 48 ++- alacritty/src/event.rs | 741 ++++++++++++++++---------------- alacritty/src/input/mod.rs | 8 +- alacritty/src/logging.rs | 4 + alacritty/src/main.rs | 29 +- alacritty/src/window_context.rs | 8 +- alacritty_terminal/Cargo.toml | 2 +- 11 files changed, 667 insertions(+), 495 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 959ae73e..5ae7ffb8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its ### Changed - Pressing `Alt` with unicode input will now add `ESC` like for ASCII input +- Decorations use opaque style and system window background on macOS ### Fixed diff --git a/Cargo.lock b/Cargo.lock index c4197c3c..f73c36a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,7 +61,7 @@ dependencies = [ "serde_yaml", "toml", "unicode-width", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "winit", "xdg", ] @@ -109,14 +109,14 @@ dependencies = [ "signal-hook", "unicode-width", "vte", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "android-activity" -version = "0.5.2" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee91c0c2905bae44f84bfa4e044536541df26b7703fd0888deeb9060fcc44289" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", "bitflags 2.4.2", @@ -260,7 +260,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" dependencies = [ "block-sys", - "objc2", + "objc2 0.4.1", +] + +[[package]] +name = "block2" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43ff7d91d3c1d568065b06c899777d1e48dcf76103a672a0adbc238a7f247f1e" +dependencies = [ + "objc2 0.5.1", ] [[package]] @@ -335,6 +344,12 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +[[package]] +name = "cfg_aliases" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f" + [[package]] name = "cgl" version = "0.3.2" @@ -403,15 +418,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "cmake" -version = "0.1.50" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" -dependencies = [ - "cc", -] - [[package]] name = "cocoa" version = "0.25.0" @@ -559,9 +565,9 @@ checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345" [[package]] name = "crossfont" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e89c65306ecd118368d875f48d69394b5c3ff6bb7c57ae6deb638782735a093c" +checksum = "c44e28d120f3c9254800ea53349b09cbb45ac1f15f09215011a16241ae0289bc" dependencies = [ "cocoa", "core-foundation", @@ -576,8 +582,18 @@ dependencies = [ "objc", "once_cell", "pkg-config", - "servo-fontconfig", "winapi", + "yeslogic-fontconfig-sys", +] + +[[package]] +name = "cstr" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68523903c8ae5aacfa32a0d9ae60cadeb764e1da14ee0d26b1f3089f13a54636" +dependencies = [ + "proc-macro2", + "quote", ] [[package]] @@ -631,6 +647,15 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +[[package]] +name = "dpi" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +dependencies = [ + "serde", +] + [[package]] name = "dwrote" version = "0.11.0" @@ -675,16 +700,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "expat-sys" -version = "2.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "658f19728920138342f68408b7cf7644d90d4784353d8ebc32e7e8663dbe45fa" -dependencies = [ - "cmake", - "pkg-config", -] - [[package]] name = "fastrand" version = "2.0.1" @@ -751,22 +766,22 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" [[package]] name = "freetype-rs" -version = "0.26.0" +version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74eadec9d0a5c28c54bb9882e54787275152a4e36ce206b45d7451384e5bf5fb" +checksum = "5442dee36ca09604133580dc0553780e867936bb3cbef3275859e889026d2b17" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.2", "freetype-sys", "libc", ] [[package]] name = "freetype-sys" -version = "0.13.1" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a37d4011c0cc628dfa766fcc195454f4b068d7afdc2adfd28861191d866e731a" +checksum = "0e7edc5b9669349acfda99533e9e0bcf26a51862ab43b08ee7745c55d28eb134" dependencies = [ - "cmake", + "cc", "libc", "pkg-config", ] @@ -825,7 +840,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" dependencies = [ "bitflags 2.4.2", - "cfg_aliases", + "cfg_aliases 0.1.1", "cgl", "core-foundation", "dispatch", @@ -834,7 +849,7 @@ dependencies = [ "glutin_wgl_sys", "icrate", "libloading", - "objc2", + "objc2 0.4.1", "once_cell", "raw-window-handle", "wayland-sys", @@ -898,9 +913,9 @@ version = "0.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" dependencies = [ - "block2", + "block2 0.3.0", "dispatch", - "objc2", + "objc2 0.4.1", ] [[package]] @@ -1137,9 +1152,9 @@ dependencies = [ [[package]] name = "ndk" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ "bitflags 2.4.2", "jni-sys", @@ -1158,9 +1173,9 @@ checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" [[package]] name = "ndk-sys" -version = "0.5.0+25.2.9519653" +version = "0.6.0+11769913" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +checksum = "ee6cda3051665f1fb8d9e08fc35c96d5a244fb1be711a03b71118828afc9a873" dependencies = [ "jni-sys", ] @@ -1227,9 +1242,9 @@ dependencies = [ [[package]] name = "objc-sys" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c71324e4180d0899963fc83d9d241ac39e699609fc1025a850aadac8257459" +checksum = "da284c198fb9b7b0603f8635185e85fbd5b64ee154b1ed406d489077de2d6d60" [[package]] name = "objc2" @@ -1238,7 +1253,40 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" dependencies = [ "objc-sys", - "objc2-encode", + "objc2-encode 3.0.0", +] + +[[package]] +name = "objc2" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4b25e1034d0e636cd84707ccdaa9f81243d399196b8a773946dcffec0401659" +dependencies = [ + "objc-sys", + "objc2-encode 4.0.1", +] + +[[package]] +name = "objc2-app-kit" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb79768a710a9a1798848179edb186d1af7e8a8679f369e4b8d201dd2a034047" +dependencies = [ + "block2 0.5.0", + "objc2 0.5.1", + "objc2-core-data", + "objc2-foundation", +] + +[[package]] +name = "objc2-core-data" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e092bc42eaf30a08844e6a076938c60751225ec81431ab89f5d1ccd9f958d6c" +dependencies = [ + "block2 0.5.0", + "objc2 0.5.1", + "objc2-foundation", ] [[package]] @@ -1247,6 +1295,23 @@ version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +[[package]] +name = "objc2-encode" +version = "4.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88658da63e4cc2c8adb1262902cd6af51094df0488b760d6fd27194269c0950a" + +[[package]] +name = "objc2-foundation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfaefe14254871ea16c7d88968c0ff14ba554712a20d76421eec52f0a7fb8904" +dependencies = [ + "block2 0.5.0", + "dispatch", + "objc2 0.5.1", +] + [[package]] name = "objc_id" version = "0.1.1" @@ -1306,6 +1371,26 @@ version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -1507,9 +1592,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.1" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +checksum = "7de61fa7334ee8ee1f5c3c58dcc414fb9361e7e8f5bff9d45f4d69eeb89a7169" dependencies = [ "crossfont", "log", @@ -1576,27 +1661,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "servo-fontconfig" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7e3e22fe5fd73d04ebf0daa049d3efe3eae55369ce38ab16d07ddd9ac5c217c" -dependencies = [ - "libc", - "servo-fontconfig-sys", -] - -[[package]] -name = "servo-fontconfig-sys" -version = "5.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" -dependencies = [ - "expat-sys", - "freetype-sys", - "pkg-config", -] - [[package]] name = "signal-hook" version = "0.3.17" @@ -2094,9 +2158,9 @@ dependencies = [ [[package]] name = "web-time" -version = "0.2.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa30049b1c872b72c89866d458eae9f20380ab280ffd1b1e18df2d3e2d98cfe0" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ "js-sys", "wasm-bindgen", @@ -2151,6 +2215,15 @@ dependencies = [ "windows-targets 0.48.5", ] +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.5", +] + [[package]] name = "windows-targets" version = "0.42.2" @@ -2181,6 +2254,22 @@ dependencies = [ "windows_x86_64_msvc 0.48.5", ] +[[package]] +name = "windows-targets" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +dependencies = [ + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "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", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.42.2" @@ -2193,6 +2282,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" + [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -2205,6 +2300,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" + [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -2217,6 +2318,18 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" +[[package]] +name = "windows_i686_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" + [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -2229,6 +2342,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" +[[package]] +name = "windows_i686_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" + [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -2241,6 +2360,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" + [[package]] name = "windows_x86_64_gnullvm" version = "0.42.2" @@ -2253,6 +2378,12 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" + [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -2265,11 +2396,17 @@ version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" + [[package]] name = "winit" -version = "0.29.15" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d59ad965a635657faf09c8f062badd885748428933dad8e8bdd64064d92e5ca" +checksum = "ea9e6d5d66cbf702e0dd820302144f51b69a95acdc495dd98ca280ff206562b1" dependencies = [ "ahash", "android-activity", @@ -2277,28 +2414,30 @@ dependencies = [ "bitflags 2.4.2", "bytemuck", "calloop", - "cfg_aliases", + "cfg_aliases 0.2.0", + "concurrent-queue", "core-foundation", "core-graphics", "cursor-icon", - "icrate", + "dpi", "js-sys", "libc", - "log", "memmap2", "ndk", - "ndk-sys", - "objc2", - "once_cell", + "objc2 0.5.1", + "objc2-app-kit", + "objc2-foundation", "orbclient", "percent-encoding", + "pin-project", "raw-window-handle", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", "sctk-adwaita", "serde", "smithay-client-toolkit", "smol_str", + "tracing", "unicode-segmentation", "wasm-bindgen", "wasm-bindgen-futures", @@ -2308,7 +2447,7 @@ dependencies = [ "wayland-protocols-plasma", "web-sys", "web-time", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "x11-dl", "x11rb", "xkbcommon-dl", @@ -2430,6 +2569,18 @@ version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +[[package]] +name = "yeslogic-fontconfig-sys" +version = "5.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb6b23999a8b1a997bf47c7bb4d19ad4029c3327bb3386ebe0a5ff584b33c7a" +dependencies = [ + "cstr", + "dlib", + "once_cell", + "pkg-config", +] + [[package]] name = "zerocopy" version = "0.7.32" diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 7fcbb13a..10ee1aee 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -27,7 +27,7 @@ ahash = { version = "0.8.6", features = ["no-rng"] } bitflags = "2.2.1" clap = { version = "4.2.7", features = ["derive", "env"] } copypasta = { version = "0.10.1", default-features = false } -crossfont = { version = "0.7.0", features = ["force_system_fontconfig"] } +crossfont = "0.8.0" glutin = { version = "0.31.1", default-features = false, features = ["egl", "wgl"] } home = "0.5.5" libc = "0.2" @@ -40,7 +40,7 @@ serde_json = "1" serde_yaml = "0.9.25" toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.29.15", default-features = false, features = ["rwh_05", "serde"] } +winit = { version = "0.30.0", default-features = false, features = ["rwh_05", "serde"] } [build-dependencies] gl_generator = "0.14.0" @@ -60,7 +60,7 @@ objc = "0.2.2" [target.'cfg(windows)'.dependencies] dirs = "5.0.1" -windows-sys = { version = "0.48", features = [ +windows-sys = { version = "0.52", features = [ "Win32_UI_WindowsAndMessaging", "Win32_System_Threading", "Win32_System_Console", diff --git a/alacritty/src/clipboard.rs b/alacritty/src/clipboard.rs index b3818c75..bb90a13d 100644 --- a/alacritty/src/clipboard.rs +++ b/alacritty/src/clipboard.rs @@ -3,7 +3,6 @@ use raw_window_handle::RawDisplayHandle; use alacritty_terminal::term::ClipboardType; -#[cfg(any(test, not(any(feature = "x11", target_os = "macos", windows))))] use copypasta::nop_clipboard::NopClipboardContext; #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] use copypasta::wayland_clipboard; @@ -31,9 +30,8 @@ impl Clipboard { } } - /// Used for tests and to handle missing clipboard provider when built without the `x11` - /// feature. - #[cfg(any(test, not(any(feature = "x11", target_os = "macos", windows))))] + /// Used for tests, to handle missing clipboard provider when built without the `x11` + /// feature, and as default clipboard value. pub fn new_nop() -> Self { Self { clipboard: Box::new(NopClipboardContext::new().unwrap()), selection: None } } diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index e4bfa2cb..09793fa0 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -1,16 +1,16 @@ #[cfg(not(any(target_os = "macos", windows)))] use winit::platform::startup_notify::{ - self, EventLoopExtStartupNotify, WindowBuilderExtStartupNotify, + self, EventLoopExtStartupNotify, WindowAttributesExtStartupNotify, }; #[cfg(all(not(feature = "x11"), not(any(target_os = "macos", windows))))] -use winit::platform::wayland::WindowBuilderExtWayland; +use winit::platform::wayland::WindowAttributesExtWayland; #[rustfmt::skip] #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] use { std::io::Cursor, - winit::platform::x11::{WindowBuilderExtX11, EventLoopWindowTargetExtX11}, + winit::platform::x11::{WindowAttributesExtX11, ActiveEventLoopExtX11}, glutin::platform::x11::X11VisualInfo, winit::window::Icon, png::Decoder, @@ -23,18 +23,18 @@ use { cocoa::appkit::NSColorSpace, cocoa::base::{id, nil, NO, YES}, objc::{msg_send, sel, sel_impl}, - winit::platform::macos::{OptionAsAlt, WindowBuilderExtMacOS, WindowExtMacOS}, + winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS}, }; use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use winit::dpi::{PhysicalPosition, PhysicalSize}; -use winit::event_loop::EventLoopWindowTarget; +use winit::event_loop::ActiveEventLoop; use winit::monitor::MonitorHandle; #[cfg(windows)] use winit::platform::windows::IconExtWindows; use winit::window::{ CursorIcon, Fullscreen, ImePurpose, Theme, UserAttentionType, Window as WinitWindow, - WindowBuilder, WindowId, + WindowAttributes, WindowId, }; use alacritty_terminal::index::Point; @@ -121,8 +121,8 @@ impl Window { /// Create a new window. /// /// This creates a window and fully initializes a window. - pub fn new( - event_loop: &EventLoopWindowTarget, + pub fn new( + event_loop: &ActiveEventLoop, config: &UiConfig, identity: &Identity, #[rustfmt::skip] @@ -133,7 +133,7 @@ impl Window { x11_visual: Option, ) -> Result { let identity = identity.clone(); - let mut window_builder = Window::get_platform_window( + let mut window_attributes = Window::get_platform_window( &identity, &config.window, #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] @@ -143,14 +143,14 @@ impl Window { ); if let Some(position) = config.window.position { - window_builder = window_builder + window_attributes = window_attributes .with_position(PhysicalPosition::::from((position.x, position.y))); } #[cfg(not(any(target_os = "macos", windows)))] if let Some(token) = event_loop.read_token_from_env() { log::debug!("Activating window with token: {token:?}"); - window_builder = window_builder.with_activation_token(token); + window_attributes = window_attributes.with_activation_token(token); // Remove the token from the env. startup_notify::reset_activation_token_env(); @@ -160,22 +160,23 @@ impl Window { #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] if let Some(parent_window_id) = event_loop.is_x11().then_some(config.window.embed).flatten() { - window_builder = window_builder.with_embed_parent_window(parent_window_id); + window_attributes = window_attributes.with_embed_parent_window(parent_window_id); } - let window = window_builder + window_attributes = window_attributes .with_title(&identity.title) .with_theme(config.window.theme()) .with_visible(false) .with_transparent(true) .with_blur(config.window.blur) .with_maximized(config.window.maximized()) - .with_fullscreen(config.window.fullscreen()) - .build(event_loop)?; + .with_fullscreen(config.window.fullscreen()); + + let window = event_loop.create_window(window_attributes)?; // Text cursor. let current_mouse_cursor = CursorIcon::Text; - window.set_cursor_icon(current_mouse_cursor); + window.set_cursor(current_mouse_cursor); // Enable IME. window.set_ime_allowed(true); @@ -248,7 +249,7 @@ impl Window { pub fn set_mouse_cursor(&mut self, cursor: CursorIcon) { if cursor != self.current_mouse_cursor { self.current_mouse_cursor = cursor; - self.window.set_cursor_icon(cursor); + self.window.set_cursor(cursor); } } @@ -267,7 +268,7 @@ impl Window { #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] x11_visual: Option< X11VisualInfo, >, - ) -> WindowBuilder { + ) -> WindowAttributes { #[cfg(feature = "x11")] let icon = { let mut decoder = Decoder::new(Cursor::new(WINDOW_ICON)); @@ -279,7 +280,7 @@ impl Window { .expect("invalid embedded icon format") }; - let builder = WindowBuilder::new() + let builder = WinitWindow::default_attributes() .with_name(&identity.class.general, &identity.class.instance) .with_decorations(window_config.decorations != Decorations::None); @@ -296,10 +297,10 @@ impl Window { } #[cfg(windows)] - pub fn get_platform_window(_: &Identity, window_config: &WindowConfig) -> WindowBuilder { + pub fn get_platform_window(_: &Identity, window_config: &WindowConfig) -> WindowAttributes { let icon = winit::window::Icon::from_resource(IDI_ICON, None); - WindowBuilder::new() + WinitWindow::default_attributes() .with_decorations(window_config.decorations != Decorations::None) .with_window_icon(icon.ok()) } @@ -309,8 +310,9 @@ impl Window { _: &Identity, window_config: &WindowConfig, tabbing_id: &Option, - ) -> WindowBuilder { - let mut window = WindowBuilder::new().with_option_as_alt(window_config.option_as_alt()); + ) -> WindowAttributes { + let mut window = + WinitWindow::default_attributes().with_option_as_alt(window_config.option_as_alt()); if let Some(tabbing_id) = tabbing_id { window = window.with_tabbing_identifier(tabbing_id); diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 5276776a..ac8474be 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -18,13 +18,12 @@ use crossfont::Size as FontSize; use glutin::display::{Display as GlutinDisplay, GetGlDisplay}; use log::{debug, error, info, warn}; use raw_window_handle::HasRawDisplayHandle; +use winit::application::ApplicationHandler; use winit::event::{ ElementState, Event as WinitEvent, Ime, Modifiers, MouseButton, StartCause, Touch as TouchEvent, WindowEvent, }; -use winit::event_loop::{ - ControlFlow, DeviceEvents, EventLoop, EventLoopProxy, EventLoopWindowTarget, -}; +use winit::event_loop::{ActiveEventLoop, ControlFlow, DeviceEvents, EventLoop, EventLoopProxy}; use winit::window::WindowId; use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify}; @@ -49,7 +48,7 @@ use crate::display::hint::HintMatch; use crate::display::window::Window; use crate::display::{Display, Preedit, SizeInfo}; use crate::input::{self, ActionContext as _, FONT_SIZE_STEP}; -use crate::logging::LOG_TARGET_CONFIG; +use crate::logging::{LOG_TARGET_CONFIG, LOG_TARGET_WINIT}; use crate::message_bar::{Message, MessageBuffer}; use crate::scheduler::{Scheduler, TimerId, Topic}; use crate::window_context::WindowContext; @@ -66,6 +65,372 @@ const MAX_SEARCH_HISTORY_SIZE: usize = 255; /// Touch zoom speed. const TOUCH_ZOOM_FACTOR: f32 = 0.01; +/// The event processor. +/// +/// Stores some state from received events and dispatches actions when they are +/// triggered. +pub struct Processor { + clipboard: Clipboard, + scheduler: Scheduler, + initial_window_options: Option, + initial_window_error: Option>, + windows: HashMap, + proxy: EventLoopProxy, + gl_display: Option, + #[cfg(unix)] + global_ipc_options: ParsedOptions, + cli_options: CliOptions, + config: Rc, +} + +impl Processor { + /// Create a new event processor. + pub fn new( + config: UiConfig, + cli_options: CliOptions, + event_loop: &EventLoop, + ) -> Processor { + let proxy = event_loop.create_proxy(); + let scheduler = Scheduler::new(proxy.clone()); + let initial_window_options = Some(cli_options.window_options.clone()); + + // Disable all device events, since we don't care about them. + event_loop.listen_device_events(DeviceEvents::Never); + + // SAFETY: Since this takes a pointer to the winit event loop, it MUST be dropped first, + // which is done in `loop_exiting`. + let clipboard = unsafe { Clipboard::new(event_loop.raw_display_handle()) }; + + Processor { + initial_window_options, + initial_window_error: None, + cli_options, + proxy, + scheduler, + gl_display: None, + config: Rc::new(config), + clipboard, + windows: Default::default(), + #[cfg(unix)] + global_ipc_options: Default::default(), + } + } + + /// Create initial window and load GL platform. + /// + /// This will initialize the OpenGL Api and pick a config that + /// will be used for the rest of the windows. + pub fn create_initial_window( + &mut self, + event_loop: &ActiveEventLoop, + options: WindowOptions, + ) -> Result<(), Box> { + 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.windows.insert(window_context.id(), window_context); + + Ok(()) + } + + /// Create a new terminal window. + pub fn create_window( + &mut self, + event_loop: &ActiveEventLoop, + options: WindowOptions, + ) -> Result<(), Box> { + let window = self.windows.iter().next().as_ref().unwrap().1; + + // Overide config with CLI/IPC options. + let mut config_overrides = options.config_overrides(); + #[cfg(unix)] + config_overrides.extend_from_slice(&self.global_ipc_options); + 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)?; + + self.windows.insert(window_context.id(), window_context); + Ok(()) + } + + /// 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); + if let Some(initial_window_error) = self.initial_window_error.take() { + Err(initial_window_error) + } else { + result.map_err(Into::into) + } + } + + /// Check if an event is irrelevant and can be skipped. + fn skip_window_event(event: &WindowEvent) -> bool { + matches!( + event, + WindowEvent::KeyboardInput { is_synthetic: true, .. } + | WindowEvent::ActivationTokenDone { .. } + | WindowEvent::DoubleTapGesture { .. } + | WindowEvent::TouchpadPressure { .. } + | WindowEvent::RotationGesture { .. } + | WindowEvent::CursorEntered { .. } + | WindowEvent::PinchGesture { .. } + | WindowEvent::AxisMotion { .. } + | WindowEvent::PanGesture { .. } + | WindowEvent::HoveredFileCancelled + | WindowEvent::Destroyed + | WindowEvent::ThemeChanged(_) + | WindowEvent::HoveredFile(_) + | WindowEvent::Moved(_) + ) + } +} + +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 { + 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) { + self.initial_window_error = Some(err); + event_loop.exit(); + return; + } + + info!("Initialisation complete"); + } + + fn window_event( + &mut self, + _event_loop: &ActiveEventLoop, + window_id: WindowId, + event: WindowEvent, + ) { + if self.config.debug.print_events { + info!(target: LOG_TARGET_WINIT, "{event:?}"); + } + + // Ignore all events we do not care about. + if Self::skip_window_event(&event) { + return; + } + + let window_context = match self.windows.get_mut(&window_id) { + Some(window_context) => window_context, + None => return, + }; + + let is_redraw = matches!(event, WindowEvent::RedrawRequested); + + window_context.handle_event( + #[cfg(target_os = "macos")] + _event_loop, + &self.proxy, + &mut self.clipboard, + &mut self.scheduler, + WinitEvent::WindowEvent { window_id, event }, + ); + + if is_redraw { + window_context.draw(&mut self.scheduler); + } + } + + fn user_event(&mut self, event_loop: &ActiveEventLoop, event: Event) { + if self.config.debug.print_events { + info!(target: LOG_TARGET_WINIT, "{event:?}"); + } + + // Handle events which don't mandate the WindowId. + match &event.payload { + // Process IPC config update. + #[cfg(unix)] + EventType::IpcConfig(ipc_config) => { + // Try and parse options as toml. + let mut options = ParsedOptions::from_options(&ipc_config.options); + + // Override IPC config for each window with matching ID. + for (_, window_context) in self + .windows + .iter_mut() + .filter(|(id, _)| event.window_id.is_none() || event.window_id == Some(**id)) + { + if ipc_config.reset { + window_context.reset_window_config(self.config.clone()); + } else { + window_context.add_window_config(self.config.clone(), &options); + } + } + + // Persist global options for future windows. + if event.window_id.is_none() { + if ipc_config.reset { + self.global_ipc_options.clear(); + } else { + self.global_ipc_options.append(&mut options); + } + } + }, + EventType::ConfigReload(path) => { + // Clear config logs from message bar for all terminals. + for window_context in self.windows.values_mut() { + if !window_context.message_buffer.is_empty() { + window_context.message_buffer.remove_target(LOG_TARGET_CONFIG); + window_context.display.pending_update.dirty = true; + } + } + + // Load config and update each terminal. + if let Ok(config) = config::reload(path, &mut self.cli_options) { + self.config = Rc::new(config); + + for window_context in self.windows.values_mut() { + window_context.update_config(self.config.clone()); + } + } + }, + // Create a new terminal window. + EventType::CreateWindow(options) => { + // XXX Ensure that no context is current when creating a new window, + // otherwise it may lock the backing buffer of the + // surface of current context when asking + // e.g. EGL on Wayland to create a new context. + for window_context in self.windows.values_mut() { + window_context.display.make_not_current(); + } + + if let Err(err) = self.create_window(event_loop, options.clone()) { + error!("Could not open window: {:?}", err); + } + }, + _ => (), + }; + + let window_id = match event.window_id { + Some(window_id) => window_id, + None => return, + }; + + // Handle the rest of events which require WindowId. + match event.payload { + EventType::Terminal(TerminalEvent::Wakeup) => { + if let Some(window_context) = self.windows.get_mut(&window_id) { + window_context.dirty = true; + if window_context.display.window.has_frame { + window_context.display.window.request_redraw(); + } + } + }, + EventType::Terminal(TerminalEvent::Exit) => { + // Remove the closed terminal. + let window_context = match self.windows.remove(&window_id) { + Some(window_context) => window_context, + None => return, + }; + + // Unschedule pending events. + self.scheduler.unschedule_window(window_context.id()); + + // Shutdown if no more terminals are open. + if self.windows.is_empty() { + // Write ref tests of last window to disk. + if self.config.debug.ref_test { + window_context.write_ref_test_results(); + } + + event_loop.exit(); + } + }, + // NOTE: This event bypasses batching to minimize input latency. + EventType::Frame => { + if let Some(window_context) = self.windows.get_mut(&window_id) { + window_context.display.window.has_frame = true; + if window_context.dirty { + window_context.display.window.request_redraw(); + } + } + }, + _ => { + if let Some(window_context) = self.windows.get_mut(&window_id) { + window_context.handle_event( + #[cfg(target_os = "macos")] + event_loop, + &self.proxy, + &mut self.clipboard, + &mut self.scheduler, + WinitEvent::UserEvent(event), + ); + } + }, + } + } + + fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { + if self.config.debug.print_events { + info!(target: LOG_TARGET_WINIT, "About to wait"); + } + + // Dispatch event to all windows. + for window_context in self.windows.values_mut() { + window_context.handle_event( + #[cfg(target_os = "macos")] + event_loop, + &self.proxy, + &mut self.clipboard, + &mut self.scheduler, + WinitEvent::AboutToWait, + ); + } + + // Update the scheduler after event processing to ensure + // the event loop deadline is as accurate as possible. + let control_flow = match self.scheduler.update() { + Some(instant) => ControlFlow::WaitUntil(instant), + None => ControlFlow::Wait, + }; + event_loop.set_control_flow(control_flow); + } + + fn exiting(&mut self, _event_loop: &ActiveEventLoop) { + if self.config.debug.print_events { + info!("Exiting the event loop"); + } + + match self.gl_display.take() { + #[cfg(not(target_os = "macos"))] + Some(glutin::display::Display::Egl(display)) => { + // Ensure that all the windows are dropped, so the destructors for + // Renderer and contexts ran. + self.windows.clear(); + + // SAFETY: the display is being destroyed after destroying all the + // windows, thus no attempt to access the EGL state will be made. + unsafe { + display.terminate(); + } + }, + _ => (), + } + + // SAFETY: The clipboard must be dropped before the event loop, so use the nop clipboard + // as a safe placeholder. + mem::swap(&mut self.clipboard, &mut Clipboard::new_nop()); + } +} + /// Alacritty events. #[derive(Debug, Clone)] pub struct Event { @@ -218,7 +583,7 @@ pub struct ActionContext<'a, N, T> { pub config: &'a UiConfig, pub cursor_blink_timed_out: &'a mut bool, #[cfg(target_os = "macos")] - pub event_loop: &'a EventLoopWindowTarget, + pub event_loop: &'a ActiveEventLoop, pub event_proxy: &'a EventLoopProxy, pub scheduler: &'a mut Scheduler, pub search_state: &'a mut SearchState, @@ -919,7 +1284,7 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon } #[cfg(target_os = "macos")] - fn event_loop(&self) -> &EventLoopWindowTarget { + fn event_loop(&self) -> &ActiveEventLoop { self.event_loop } @@ -1468,12 +1833,13 @@ impl input::Processor> { }, WindowEvent::KeyboardInput { is_synthetic: true, .. } | WindowEvent::ActivationTokenDone { .. } + | WindowEvent::DoubleTapGesture { .. } | WindowEvent::TouchpadPressure { .. } - | WindowEvent::TouchpadMagnify { .. } - | WindowEvent::TouchpadRotate { .. } - | WindowEvent::SmartMagnify { .. } + | WindowEvent::RotationGesture { .. } | WindowEvent::CursorEntered { .. } + | WindowEvent::PinchGesture { .. } | WindowEvent::AxisMotion { .. } + | WindowEvent::PanGesture { .. } | WindowEvent::HoveredFileCancelled | WindowEvent::Destroyed | WindowEvent::ThemeChanged(_) @@ -1493,363 +1859,6 @@ impl input::Processor> { } } -/// The event processor. -/// -/// Stores some state from received events and dispatches actions when they are -/// triggered. -pub struct Processor { - windows: HashMap, - gl_display: Option, - #[cfg(unix)] - global_ipc_options: ParsedOptions, - cli_options: CliOptions, - config: Rc, -} - -impl Processor { - /// Create a new event processor. - /// - /// Takes a writer which is expected to be hooked up to the write end of a PTY. - pub fn new( - config: UiConfig, - cli_options: CliOptions, - _event_loop: &EventLoop, - ) -> Processor { - Processor { - cli_options, - gl_display: None, - config: Rc::new(config), - windows: Default::default(), - #[cfg(unix)] - global_ipc_options: Default::default(), - } - } - - /// Create initial window and load GL platform. - /// - /// This will initialize the OpenGL Api and pick a config that - /// will be used for the rest of the windows. - pub fn create_initial_window( - &mut self, - event_loop: &EventLoopWindowTarget, - proxy: EventLoopProxy, - options: WindowOptions, - ) -> Result<(), Box> { - let window_context = - WindowContext::initial(event_loop, proxy, self.config.clone(), options)?; - - self.gl_display = Some(window_context.display.gl_context().display()); - self.windows.insert(window_context.id(), window_context); - - Ok(()) - } - - /// Create a new terminal window. - pub fn create_window( - &mut self, - event_loop: &EventLoopWindowTarget, - proxy: EventLoopProxy, - options: WindowOptions, - ) -> Result<(), Box> { - let window = self.windows.iter().next().as_ref().unwrap().1; - - // Overide config with CLI/IPC options. - let mut config_overrides = options.config_overrides(); - #[cfg(unix)] - config_overrides.extend_from_slice(&self.global_ipc_options); - let mut config = self.config.clone(); - config = config_overrides.override_config_rc(config); - - #[allow(unused_mut)] - let mut window_context = - window.additional(event_loop, proxy, config, options, config_overrides)?; - - self.windows.insert(window_context.id(), window_context); - Ok(()) - } - - /// Run the event loop. - /// - /// The result is exit code generate from the loop. - pub fn run( - &mut self, - event_loop: EventLoop, - initial_window_options: WindowOptions, - ) -> Result<(), Box> { - let proxy = event_loop.create_proxy(); - let mut scheduler = Scheduler::new(proxy.clone()); - let mut initial_window_options = Some(initial_window_options); - - // Disable all device events, since we don't care about them. - event_loop.listen_device_events(DeviceEvents::Never); - - let mut initial_window_error = Ok(()); - let initial_window_error_loop = &mut initial_window_error; - // SAFETY: Since this takes a pointer to the winit event loop, it MUST be dropped first, - // which is done by `move` into event loop. - let mut clipboard = unsafe { Clipboard::new(event_loop.raw_display_handle()) }; - let result = event_loop.run(move |event, event_loop| { - if self.config.debug.print_events { - info!("winit event: {:?}", event); - } - - // Ignore all events we do not care about. - if Self::skip_event(&event) { - return; - } - - match event { - // The event loop just got initialized. Create a window. - WinitEvent::Resumed => { - // Creating window inside event loop is required for platforms like macOS to - // properly initialize state, like tab management. Otherwise the first - // window won't handle tabs. - let initial_window_options = match initial_window_options.take() { - Some(initial_window_options) => initial_window_options, - None => return, - }; - - if let Err(err) = self.create_initial_window( - event_loop, - proxy.clone(), - initial_window_options, - ) { - *initial_window_error_loop = Err(err); - event_loop.exit(); - return; - } - - info!("Initialisation complete"); - }, - WinitEvent::LoopExiting => { - match self.gl_display.take() { - #[cfg(not(target_os = "macos"))] - Some(glutin::display::Display::Egl(display)) => { - // Ensure that all the windows are dropped, so the destructors for - // Renderer and contexts ran. - self.windows.clear(); - - // SAFETY: the display is being destroyed after destroying all the - // windows, thus no attempt to access the EGL state will be made. - unsafe { - display.terminate(); - } - }, - _ => (), - } - }, - // NOTE: This event bypasses batching to minimize input latency. - WinitEvent::UserEvent(Event { - window_id: Some(window_id), - payload: EventType::Terminal(TerminalEvent::Wakeup), - }) => { - if let Some(window_context) = self.windows.get_mut(&window_id) { - window_context.dirty = true; - if window_context.display.window.has_frame { - window_context.display.window.request_redraw(); - } - } - }, - // NOTE: This event bypasses batching to minimize input latency. - WinitEvent::UserEvent(Event { - window_id: Some(window_id), - payload: EventType::Frame, - }) => { - if let Some(window_context) = self.windows.get_mut(&window_id) { - window_context.display.window.has_frame = true; - if window_context.dirty { - window_context.display.window.request_redraw(); - } - } - }, - // Check for shutdown. - WinitEvent::UserEvent(Event { - window_id: Some(window_id), - payload: EventType::Terminal(TerminalEvent::Exit), - }) => { - // Remove the closed terminal. - let window_context = match self.windows.remove(&window_id) { - Some(window_context) => window_context, - None => return, - }; - - // Unschedule pending events. - scheduler.unschedule_window(window_context.id()); - - // Shutdown if no more terminals are open. - if self.windows.is_empty() { - // Write ref tests of last window to disk. - if self.config.debug.ref_test { - window_context.write_ref_test_results(); - } - - event_loop.exit(); - } - }, - WinitEvent::WindowEvent { window_id, event: WindowEvent::RedrawRequested } => { - let window_context = match self.windows.get_mut(&window_id) { - Some(window_context) => window_context, - None => return, - }; - - window_context.handle_event( - #[cfg(target_os = "macos")] - event_loop, - &proxy, - &mut clipboard, - &mut scheduler, - event, - ); - - window_context.draw(&mut scheduler); - }, - // Process all pending events. - WinitEvent::AboutToWait => { - // Dispatch event to all windows. - for window_context in self.windows.values_mut() { - window_context.handle_event( - #[cfg(target_os = "macos")] - event_loop, - &proxy, - &mut clipboard, - &mut scheduler, - WinitEvent::AboutToWait, - ); - } - - // Update the scheduler after event processing to ensure - // the event loop deadline is as accurate as possible. - let control_flow = match scheduler.update() { - Some(instant) => ControlFlow::WaitUntil(instant), - None => ControlFlow::Wait, - }; - event_loop.set_control_flow(control_flow); - }, - // Process config update. - WinitEvent::UserEvent(Event { payload: EventType::ConfigReload(path), .. }) => { - // Clear config logs from message bar for all terminals. - for window_context in self.windows.values_mut() { - if !window_context.message_buffer.is_empty() { - window_context.message_buffer.remove_target(LOG_TARGET_CONFIG); - window_context.display.pending_update.dirty = true; - } - } - - // Load config and update each terminal. - if let Ok(config) = config::reload(&path, &mut self.cli_options) { - self.config = Rc::new(config); - - for window_context in self.windows.values_mut() { - window_context.update_config(self.config.clone()); - } - } - }, - // Process IPC config update. - #[cfg(unix)] - WinitEvent::UserEvent(Event { - payload: EventType::IpcConfig(ipc_config), - window_id, - }) => { - // Try and parse options as toml. - let mut options = ParsedOptions::from_options(&ipc_config.options); - - // Override IPC config for each window with matching ID. - for (_, window_context) in self - .windows - .iter_mut() - .filter(|(id, _)| window_id.is_none() || window_id == Some(**id)) - { - if ipc_config.reset { - window_context.reset_window_config(self.config.clone()); - } else { - window_context.add_window_config(self.config.clone(), &options); - } - } - - // Persist global options for future windows. - if window_id.is_none() { - if ipc_config.reset { - self.global_ipc_options.clear(); - } else { - self.global_ipc_options.append(&mut options); - } - } - }, - // Create a new terminal window. - WinitEvent::UserEvent(Event { - payload: EventType::CreateWindow(options), .. - }) => { - // XXX Ensure that no context is current when creating a new window, - // otherwise it may lock the backing buffer of the - // surface of current context when asking - // e.g. EGL on Wayland to create a new context. - for window_context in self.windows.values_mut() { - window_context.display.make_not_current(); - } - - if let Err(err) = self.create_window(event_loop, proxy.clone(), options) { - error!("Could not open window: {:?}", err); - } - }, - // Process events affecting all windows. - WinitEvent::UserEvent(event @ Event { window_id: None, .. }) => { - for window_context in self.windows.values_mut() { - window_context.handle_event( - #[cfg(target_os = "macos")] - event_loop, - &proxy, - &mut clipboard, - &mut scheduler, - event.clone().into(), - ); - } - }, - // Process window-specific events. - WinitEvent::WindowEvent { window_id, .. } - | WinitEvent::UserEvent(Event { window_id: Some(window_id), .. }) => { - if let Some(window_context) = self.windows.get_mut(&window_id) { - window_context.handle_event( - #[cfg(target_os = "macos")] - event_loop, - &proxy, - &mut clipboard, - &mut scheduler, - event, - ); - } - }, - _ => (), - } - }); - - if initial_window_error.is_err() { - initial_window_error - } else { - result.map_err(Into::into) - } - } - - /// Check if an event is irrelevant and can be skipped. - fn skip_event(event: &WinitEvent) -> bool { - match event { - WinitEvent::NewEvents(StartCause::Init) => false, - WinitEvent::WindowEvent { event, .. } => matches!( - event, - WindowEvent::KeyboardInput { is_synthetic: true, .. } - | WindowEvent::TouchpadPressure { .. } - | WindowEvent::CursorEntered { .. } - | WindowEvent::AxisMotion { .. } - | WindowEvent::HoveredFileCancelled - | WindowEvent::Destroyed - | WindowEvent::HoveredFile(_) - | WindowEvent::Moved(_) - ), - WinitEvent::Suspended { .. } | WinitEvent::NewEvents { .. } => true, - _ => false, - } - } -} - #[derive(Debug, Clone)] pub struct EventProxy { proxy: EventLoopProxy, diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index 365717c3..095e8737 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -20,10 +20,10 @@ use winit::event::{ ElementState, Modifiers, MouseButton, MouseScrollDelta, Touch as TouchEvent, TouchPhase, }; #[cfg(target_os = "macos")] -use winit::event_loop::EventLoopWindowTarget; +use winit::event_loop::ActiveEventLoop; use winit::keyboard::ModifiersState; #[cfg(target_os = "macos")] -use winit::platform::macos::EventLoopWindowTargetExtMacOS; +use winit::platform::macos::ActiveEventLoopExtMacOS; use winit::window::CursorIcon; use alacritty_terminal::event::EventListener; @@ -107,7 +107,7 @@ pub trait ActionContext { fn message(&self) -> Option<&Message>; fn config(&self) -> &UiConfig; #[cfg(target_os = "macos")] - fn event_loop(&self) -> &EventLoopWindowTarget; + fn event_loop(&self) -> &ActiveEventLoop; fn mouse_mode(&self) -> bool; fn clipboard_mut(&mut self) -> &mut Clipboard; fn scheduler_mut(&mut self) -> &mut Scheduler; @@ -1224,7 +1224,7 @@ mod tests { } #[cfg(target_os = "macos")] - fn event_loop(&self) -> &EventLoopWindowTarget { + fn event_loop(&self) -> &ActiveEventLoop { unimplemented!(); } diff --git a/alacritty/src/logging.rs b/alacritty/src/logging.rs index a3833a5b..59303649 100644 --- a/alacritty/src/logging.rs +++ b/alacritty/src/logging.rs @@ -28,6 +28,9 @@ const ALACRITTY_LOG_ENV: &str = "ALACRITTY_LOG"; /// Logging target for config error messages. pub const LOG_TARGET_CONFIG: &str = "alacritty_config_derive"; +/// Logging target for winit events. +pub const LOG_TARGET_WINIT: &str = "alacritty_winit_event"; + /// Name for the environment variable containing extra logging targets. /// /// The targets are semicolon separated. @@ -47,6 +50,7 @@ fn extra_log_targets() -> &'static [String] { const ALLOWED_TARGETS: &[&str] = &[ LOG_TARGET_IPC_CONFIG, LOG_TARGET_CONFIG, + LOG_TARGET_WINIT, "alacritty_config_derive", "alacritty_terminal", "alacritty", diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index f9301767..2951c224 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -19,11 +19,11 @@ use std::path::PathBuf; use std::{env, fs}; use log::info; +#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] +use raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle}; #[cfg(windows)] use windows_sys::Win32::System::Console::{AttachConsole, FreeConsole, ATTACH_PARENT_PROCESS}; -use winit::event_loop::EventLoopBuilder as WinitEventLoopBuilder; -#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] -use winit::platform::x11::EventLoopWindowTargetExtX11; +use winit::event_loop::EventLoop; use alacritty_terminal::tty; @@ -125,7 +125,7 @@ impl Drop for TemporaryFiles { /// config change monitor, and runs the main display loop. fn alacritty(mut options: Options) -> Result<(), Box> { // Setup winit event loop. - let window_event_loop = WinitEventLoopBuilder::::with_user_event().build()?; + let window_event_loop = EventLoop::::with_user_event().build()?; // Initialize the logger as soon as possible as to capture output from other subsystems. let log_file = logging::initialize(&options, window_event_loop.create_proxy()) @@ -135,7 +135,14 @@ fn alacritty(mut options: Options) -> Result<(), Box> { info!("Version {}", env!("VERSION")); #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] - info!("Running on {}", if window_event_loop.is_x11() { "X11" } else { "Wayland" }); + info!( + "Running on {}", + if matches!(window_event_loop.raw_display_handle(), RawDisplayHandle::Wayland(_)) { + "Wayland" + } else { + "X11" + } + ); #[cfg(not(any(feature = "x11", target_os = "macos", windows)))] info!("Running on Wayland"); @@ -189,13 +196,14 @@ fn alacritty(mut options: Options) -> Result<(), Box> { }; // Event processor. - let window_options = options.window_options.clone(); - let mut processor = Processor::new(config, options, &window_event_loop); + let processor = Processor::new(config, options, &window_event_loop); // Start event loop and block until shutdown. - let result = processor.run(window_event_loop, window_options); + let result = processor.run(window_event_loop); - // This explicit drop is needed for Windows, ConPTY backend. Otherwise a deadlock can occur. + // `Processor` must be dropped before calling `FreeConsole`. + // + // This is needed for ConPTY backend. Otherwise a deadlock can occur. // The cause: // - Drop for ConPTY will deadlock if the conout pipe has already been dropped // - ConPTY is dropped when the last of processor and window context are dropped, because both @@ -206,7 +214,6 @@ fn alacritty(mut options: Options) -> Result<(), Box> { // order. // // FIXME: Change PTY API to enforce the correct drop order with the typesystem. - drop(processor); // Terminate the config monitor. if let Some(config_monitor) = config_monitor.take() { @@ -234,5 +241,5 @@ fn log_config_path(config: &UiConfig) { let _ = write!(msg, "\n {:?}", path.display()); } - info!("{}", msg); + info!("{msg}"); } diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index f0f24fe8..f5fb5cc5 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -17,7 +17,7 @@ use log::info; use raw_window_handle::HasRawDisplayHandle; use serde_json as json; use winit::event::{Event as WinitEvent, Modifiers, WindowEvent}; -use winit::event_loop::{EventLoopProxy, EventLoopWindowTarget}; +use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; use winit::window::WindowId; use alacritty_terminal::event::Event as TerminalEvent; @@ -70,7 +70,7 @@ pub struct WindowContext { impl WindowContext { /// Create initial window context that does bootstrapping the graphics API we're going to use. pub fn initial( - event_loop: &EventLoopWindowTarget, + event_loop: &ActiveEventLoop, proxy: EventLoopProxy, config: Rc, options: WindowOptions, @@ -120,7 +120,7 @@ impl WindowContext { /// Create additional context with the graphics platform other windows are using. pub fn additional( &self, - event_loop: &EventLoopWindowTarget, + event_loop: &ActiveEventLoop, proxy: EventLoopProxy, config: Rc, options: WindowOptions, @@ -399,7 +399,7 @@ impl WindowContext { /// Process events for this terminal window. pub fn handle_event( &mut self, - #[cfg(target_os = "macos")] event_loop: &EventLoopWindowTarget, + #[cfg(target_os = "macos")] event_loop: &ActiveEventLoop, event_proxy: &EventLoopProxy, clipboard: &mut Clipboard, scheduler: &mut Scheduler, diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index ed36cc36..79e7c05b 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -34,7 +34,7 @@ signal-hook = "0.3.10" [target.'cfg(windows)'.dependencies] piper = "0.2.1" miow = "0.6.0" -windows-sys = { version = "0.48.0", features = [ +windows-sys = { version = "0.52.0", features = [ "Win32_System_Console", "Win32_Foundation", "Win32_Security", From a21adf1a5073329501cca7dccd8a9f7d7baecc88 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 7 May 2024 20:23:21 +0400 Subject: [PATCH 039/102] Fix user events for all windows not handled The user events for all cases were not handled. Fixes: 48c088a5 (Bump winit to 0.30.0) Fixes: #7957. --- alacritty/src/event.rs | 54 +++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index ac8474be..9505e1a3 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -255,10 +255,10 @@ impl ApplicationHandler for Processor { } // Handle events which don't mandate the WindowId. - match &event.payload { + match (&event.payload, event.window_id.as_ref()) { // Process IPC config update. #[cfg(unix)] - EventType::IpcConfig(ipc_config) => { + (EventType::IpcConfig(ipc_config), window_id) => { // Try and parse options as toml. let mut options = ParsedOptions::from_options(&ipc_config.options); @@ -266,7 +266,7 @@ impl ApplicationHandler for Processor { for (_, window_context) in self .windows .iter_mut() - .filter(|(id, _)| event.window_id.is_none() || event.window_id == Some(**id)) + .filter(|(id, _)| window_id.is_none() || window_id == Some(*id)) { if ipc_config.reset { window_context.reset_window_config(self.config.clone()); @@ -276,7 +276,7 @@ impl ApplicationHandler for Processor { } // Persist global options for future windows. - if event.window_id.is_none() { + if window_id.is_none() { if ipc_config.reset { self.global_ipc_options.clear(); } else { @@ -284,7 +284,7 @@ impl ApplicationHandler for Processor { } } }, - EventType::ConfigReload(path) => { + (EventType::ConfigReload(path), _) => { // Clear config logs from message bar for all terminals. for window_context in self.windows.values_mut() { if !window_context.message_buffer.is_empty() { @@ -303,7 +303,7 @@ impl ApplicationHandler for Processor { } }, // Create a new terminal window. - EventType::CreateWindow(options) => { + (EventType::CreateWindow(options), _) => { // XXX Ensure that no context is current when creating a new window, // otherwise it may lock the backing buffer of the // surface of current context when asking @@ -316,27 +316,31 @@ impl ApplicationHandler for Processor { error!("Could not open window: {:?}", err); } }, - _ => (), - }; - - let window_id = match event.window_id { - Some(window_id) => window_id, - None => return, - }; - - // Handle the rest of events which require WindowId. - match event.payload { - EventType::Terminal(TerminalEvent::Wakeup) => { - if let Some(window_context) = self.windows.get_mut(&window_id) { + // Process events affecting all windows. + (_, None) => { + let event = WinitEvent::UserEvent(event); + for window_context in self.windows.values_mut() { + window_context.handle_event( + #[cfg(target_os = "macos")] + event_loop, + &self.proxy, + &mut self.clipboard, + &mut self.scheduler, + event.clone(), + ); + } + }, + (EventType::Terminal(TerminalEvent::Wakeup), Some(window_id)) => { + if let Some(window_context) = self.windows.get_mut(window_id) { window_context.dirty = true; if window_context.display.window.has_frame { window_context.display.window.request_redraw(); } } }, - EventType::Terminal(TerminalEvent::Exit) => { + (EventType::Terminal(TerminalEvent::Exit), Some(window_id)) => { // Remove the closed terminal. - let window_context = match self.windows.remove(&window_id) { + let window_context = match self.windows.remove(window_id) { Some(window_context) => window_context, None => return, }; @@ -355,16 +359,16 @@ impl ApplicationHandler for Processor { } }, // NOTE: This event bypasses batching to minimize input latency. - EventType::Frame => { - if let Some(window_context) = self.windows.get_mut(&window_id) { + (EventType::Frame, Some(window_id)) => { + if let Some(window_context) = self.windows.get_mut(window_id) { window_context.display.window.has_frame = true; if window_context.dirty { window_context.display.window.request_redraw(); } } }, - _ => { - if let Some(window_context) = self.windows.get_mut(&window_id) { + (_, Some(window_id)) => { + if let Some(window_context) = self.windows.get_mut(window_id) { window_context.handle_event( #[cfg(target_os = "macos")] event_loop, @@ -375,7 +379,7 @@ impl ApplicationHandler for Processor { ); } }, - } + }; } fn about_to_wait(&mut self, event_loop: &ActiveEventLoop) { From 7077a5f4cb5d23ce91a0509f7fae423458698170 Mon Sep 17 00:00:00 2001 From: Giacomo Battaglia <66565007+g-battaglia@users.noreply.github.com> Date: Tue, 7 May 2024 19:18:33 +0200 Subject: [PATCH 040/102] Allow requesting Bluetooth permission on macOS --- extra/osx/Alacritty.app/Contents/Info.plist | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extra/osx/Alacritty.app/Contents/Info.plist b/extra/osx/Alacritty.app/Contents/Info.plist index e7afebcb..e402e372 100644 --- a/extra/osx/Alacritty.app/Contents/Info.plist +++ b/extra/osx/Alacritty.app/Contents/Info.plist @@ -54,5 +54,7 @@ An application in Alacritty would like to access your reminders. NSSystemAdministrationUsageDescription An application in Alacritty requires elevated permissions. + NSBluetoothAlwaysUsageDescription + An application in Alacritty wants to use Bluetooth. From 3a7f21b00c50748016bc4aa2916b13b5a2e27b76 Mon Sep 17 00:00:00 2001 From: Travis Finkenauer Date: Sun, 12 May 2024 13:01:41 -0700 Subject: [PATCH 041/102] Add missing comma to alacritty(5) manpage --- extra/man/alacritty.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index a26b3d96..1b56210b 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -661,7 +661,7 @@ terminal and pipe it to other applications. Default: _"jfkdls;ahgurieowpq"_ -*enabled* = [{ **, **, **, **, **, ** **, ** },] +*enabled* = [{ **, **, **, **, **, **, **, ** },] Array with all available hints. From 3cd35dfe7efe894853ac9251891b37baee440002 Mon Sep 17 00:00:00 2001 From: Nathan Lilienthal Date: Wed, 15 May 2024 18:38:13 -0400 Subject: [PATCH 042/102] Ignore shell RCs for macOS zsh wrapper Closes #7886. --- CHANGELOG.md | 1 + alacritty_terminal/src/tty/unix.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ae7ffb8..a30d6196 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 ### Fixed diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 54118a58..1336fd04 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -177,7 +177,7 @@ fn default_shell_command(shell: &str, user: &str) -> Command { // -p: Preserves the environment. // // XXX: we use zsh here over sh due to `exec -a`. - login_command.args(["-flp", user, "/bin/zsh", "-c", &exec]); + login_command.args(["-flp", user, "/bin/zsh", "-fc", &exec]); login_command } From 38fed9a7c233e11e5f62433298235281fc3de885 Mon Sep 17 00:00:00 2001 From: EBADBEEF Date: Thu, 16 May 2024 14:15:20 -0700 Subject: [PATCH 043/102] Fix mouse mode bindings with multiple actions The following config was broken: ``` [mouse] bindings = [ { mouse = "Right", mods = "Shift", action = "Copy" }, { mouse = "Right", mods = "Shift", action = "ClearSelection" }, ] ``` Only the first action was applied. Change to allow more than one exact match in mouse mode with shift held, but keep the logic to not allow fallback search if any exact match was found. Regression was introduced in 1a143d11. --- CHANGELOG.md | 2 ++ alacritty/src/input/mod.rs | 9 +++++---- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a30d6196..b4947c03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,8 @@ Notable changes to the `alacritty_terminal` crate are documented in its - New window being treated as focused when it's not on Wayland - IME preview blending into text below it - Dynamic title disabled for new windows when initial one has title as CLI option +- While terminal in mouse mode, mouse bindings that used the shift modifier and + had multiple actions only performed the first action ## 0.13.2 diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index 095e8737..4900e26f 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -1004,17 +1004,18 @@ impl> Processor { let mouse_bindings = self.ctx.config().mouse_bindings().to_owned(); // If mouse mode is active, also look for bindings without shift. - let mut check_fallback = mouse_mode && mods.contains(ModifiersState::SHIFT); + let fallback_allowed = mouse_mode && mods.contains(ModifiersState::SHIFT); + let mut exact_match_found = false; for binding in &mouse_bindings { // Don't trigger normal bindings in mouse mode unless Shift is pressed. - if binding.is_triggered_by(mode, mods, &button) && (check_fallback || !mouse_mode) { + if binding.is_triggered_by(mode, mods, &button) && (fallback_allowed || !mouse_mode) { binding.action.execute(&mut self.ctx); - check_fallback = false; + exact_match_found = true; } } - if check_fallback { + if fallback_allowed && !exact_match_found { let fallback_mods = mods & !ModifiersState::SHIFT; for binding in &mouse_bindings { if binding.is_triggered_by(mode, fallback_mods, &button) { From f04b16161bc542075fdb8e5946a8eed976f26b0b Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Wed, 22 May 2024 14:25:50 +0200 Subject: [PATCH 044/102] Fix FD leak after closing child windows This patch fixes an issue with signal handling where Alacritty would permanently create one signal handling FD for each alacritty window created by an instance. This FD was never released, causing a leak of the FD. Closes #7983. --- CHANGELOG.md | 1 + alacritty_terminal/src/tty/unix.rs | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b4947c03..0c6aafe3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Dynamic title disabled for new windows when initial one has title as CLI option - While terminal in mouse mode, mouse bindings that used the shift modifier and had multiple actions only performed the first action +- Leaking FDs when closing windows on Unix systems ## 0.13.2 diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 1336fd04..1a2104c6 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -19,8 +19,8 @@ use rustix_openpty::openpty; use rustix_openpty::rustix::termios::Winsize; #[cfg(any(target_os = "linux", target_os = "macos"))] use rustix_openpty::rustix::termios::{self, InputModes, OptionalActions}; -use signal_hook::consts as sigconsts; -use signal_hook::low_level::pipe as signal_pipe; +use signal_hook::low_level::{pipe as signal_pipe, unregister as unregister_signal}; +use signal_hook::{consts as sigconsts, SigId}; use crate::event::{OnResize, WindowSize}; use crate::tty::{ChildEvent, EventedPty, EventedReadWrite, Options}; @@ -102,6 +102,7 @@ pub struct Pty { child: Child, file: File, signals: UnixStream, + sig_id: SigId, } impl Pty { @@ -260,13 +261,13 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd } // Prepare signal handling before spawning child. - let signals = { + let (signals, sig_id) = { let (sender, recv) = UnixStream::pair()?; // Register the recv end of the pipe for SIGCHLD. - signal_pipe::register(sigconsts::SIGCHLD, sender)?; + let sig_id = signal_pipe::register(sigconsts::SIGCHLD, sender)?; recv.set_nonblocking(true)?; - recv + (recv, sig_id) }; match builder.spawn() { @@ -277,7 +278,7 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd set_nonblocking(master_fd); } - Ok(Pty { child, file: File::from(master), signals }) + Ok(Pty { child, file: File::from(master), signals, sig_id }) }, Err(err) => Err(Error::new( err.kind(), @@ -296,6 +297,10 @@ impl Drop for Pty { unsafe { libc::kill(self.child.id() as i32, libc::SIGHUP); } + + // Clear signal-hook handler. + unregister_signal(self.sig_id); + let _ = self.child.wait(); } } From e9d4ac2a6ba5347998bd5d9eff1656b0c82e22e3 Mon Sep 17 00:00:00 2001 From: Jakob Hellermann Date: Thu, 23 May 2024 16:03:28 +0200 Subject: [PATCH 045/102] Fix IO safety violation from consequent dropping `OwnedFd` This was not a _real_ violation and was _expected_, though for rust to not complain clone FD properly... --- alacritty_terminal/src/tty/unix.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 1a2104c6..8f335500 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -5,10 +5,10 @@ use std::fs::File; use std::io::{Error, ErrorKind, Read, Result}; use std::mem::MaybeUninit; use std::os::fd::OwnedFd; -use std::os::unix::io::{AsRawFd, FromRawFd}; +use std::os::unix::io::AsRawFd; use std::os::unix::net::UnixStream; use std::os::unix::process::CommandExt; -use std::process::{Child, Command, Stdio}; +use std::process::{Child, Command}; use std::sync::Arc; use std::{env, ptr}; @@ -212,12 +212,9 @@ pub fn from_fd(config: &Options, window_id: u64, master: OwnedFd, slave: OwnedFd }; // Setup child stdin/stdout/stderr as slave fd of PTY. - // Ownership of fd is transferred to the Stdio structs and will be closed by them at the end of - // this scope. (It is not an issue that the fd is closed three times since File::drop ignores - // error on libc::close.). - builder.stdin(unsafe { Stdio::from_raw_fd(slave_fd) }); - builder.stderr(unsafe { Stdio::from_raw_fd(slave_fd) }); - builder.stdout(unsafe { Stdio::from_raw_fd(slave_fd) }); + builder.stdin(slave.try_clone()?); + builder.stderr(slave.try_clone()?); + builder.stdout(slave); // Setup shell environment. let window_id = window_id.to_string(); From 8dc27cebce277392bda3ef27671750990e1bde4f Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Thu, 23 May 2024 16:16:34 +0200 Subject: [PATCH 046/102] Fix error with missing imports This fixes a regression, likely introduced in 5d173f6df, which changed the severity of missing imports from `info` back to `error`. The cause of this issue was a more complicated error handling mechanism, which explicitly translated IO errors to a separate enum variant without accounting for it in all scenarios. While retrospectively this seems completely unnecessary to me, it did mean shorter error messages in case the main config file was not found. To preserve the benefits of both approaches, explicit handling for the `NotFound` IO error has been added when loading the main configuration file. --- CHANGELOG.md | 1 + alacritty/src/config/mod.rs | 15 +++++---------- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c6aafe3..91536648 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - While terminal in mouse mode, mouse bindings that used the shift modifier and had multiple actions only performed the first action - Leaking FDs when closing windows on Unix systems +- Config emitting errors for non-existent import paths ## 0.13.2 diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs index 4ae3b67d..f043d73b 100644 --- a/alacritty/src/config/mod.rs +++ b/alacritty/src/config/mod.rs @@ -44,9 +44,6 @@ pub type Result = std::result::Result; /// Errors occurring during config loading. #[derive(Debug)] pub enum Error { - /// Config file not found. - NotFound, - /// Couldn't read $HOME environment variable. ReadingEnvHome(env::VarError), @@ -66,7 +63,6 @@ pub enum Error { impl std::error::Error for Error { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { - Error::NotFound => None, Error::ReadingEnvHome(err) => err.source(), Error::Io(err) => err.source(), Error::Toml(err) => err.source(), @@ -79,7 +75,6 @@ impl std::error::Error for Error { impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - Error::NotFound => write!(f, "Unable to locate config file"), Error::ReadingEnvHome(err) => { write!(f, "Unable to read $HOME environment variable: {}", err) }, @@ -99,11 +94,7 @@ impl From for Error { impl From for Error { fn from(val: io::Error) -> Self { - if val.kind() == io::ErrorKind::NotFound { - Error::NotFound - } else { - Error::Io(val) - } + Error::Io(val) } } @@ -179,6 +170,10 @@ fn after_loading(config: &mut UiConfig, options: &mut Options) { fn load_from(path: &Path) -> Result { match read_config(path) { Ok(config) => Ok(config), + Err(Error::Io(io)) if io.kind() == io::ErrorKind::NotFound => { + error!(target: LOG_TARGET_CONFIG, "Unable to load config {:?}: File not found", path); + Err(Error::Io(io)) + }, Err(err) => { error!(target: LOG_TARGET_CONFIG, "Unable to load config {:?}: {}", path, err); Err(err) From a89d4f50dc6ac0256d6d52371c3711107de8c7d2 Mon Sep 17 00:00:00 2001 From: jadedpasta <86900272+jadedpasta@users.noreply.github.com> Date: Thu, 23 May 2024 13:36:14 -0500 Subject: [PATCH 047/102] Fix Kitty protocol reporting shifted keycodes The [kitty keyboard protocol][1] explicitly requires that the *un-shifted* version of the pressed key is used to report the primary code point in `CSI code-point;modifiers u` sequences. > Note that the codepoint used is always the lower-case (or more > technically, un-shifted) version of the key. If the user presses, for > example, ctrl+shift+a the escape code would be CSI 97;modifiers u. It > must not be CSI 65; modifiers u. Alacritty's current behavior is to report the shifted version when shift is pressed, and the un-shifted version otherwise: ```console # Note that you'll have to kill Alacritty after running this to get # control back! $ echo -ne '\x1b[>1u'; cat ^[[97;5u^[[65;6u ``` The above was generated by pressing `CTRL`+`a` followed by `CTRL`+`SHIFT`+`a` after running the command. Here `97` and `65` are the codepoints for `a` and `A` respectively. This change makes Alacritty match the protocol (and Kitty's) behavior. With this change applied, `97` is reported for both `CTRL`+`a` and `CTRL`+`SHIFT`+`a`. [1]: https://sw.kovidgoyal.net/kitty/keyboard-protocol/#key-codes --- CHANGELOG.md | 1 + alacritty/src/input/keyboard.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91536648..0c49c81d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its had multiple actions only performed the first action - Leaking FDs when closing windows on Unix systems - Config emitting errors for non-existent import paths +- Kitty keyboard protocol reporting shifted key codes ## 0.13.2 diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index b4c35741..fce5efbf 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -373,7 +373,7 @@ impl SequenceBuilder { { format!("{unicode_key_code}:{alternate_key_code}") } else { - alternate_key_code.to_string() + unicode_key_code.to_string() }; Some(SequenceBase::new(payload.into(), SequenceTerminator::Kitty)) From cacdb5bb3b72bad2c729227537979d95af75978f Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Fri, 24 May 2024 13:32:11 -0400 Subject: [PATCH 048/102] Fix spelling errors --- CHANGELOG.md | 12 ++++++------ CONTRIBUTING.md | 2 +- alacritty/src/config/ui_config.rs | 2 +- alacritty/src/event.rs | 4 ++-- alacritty/src/input/keyboard.rs | 2 +- alacritty_terminal/src/term/mod.rs | 2 +- alacritty_terminal/src/tty/unix.rs | 2 +- docs/features.md | 4 ++-- scripts/create-flamegraph.sh | 2 +- 9 files changed, 16 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c49c81d..3d1bd0c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - While terminal in mouse mode, mouse bindings that used the shift modifier and had multiple actions only performed the first action - Leaking FDs when closing windows on Unix systems -- Config emitting errors for non-existent import paths +- Config emitting errors for nonexistent import paths - Kitty keyboard protocol reporting shifted key codes ## 0.13.2 @@ -318,7 +318,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Terminal not exiting sometimes after closing all windows on macOS - CPU usage spikes due to mouse movements for unfocused windows on X11/Windows - First window on macOS not tabbed with system prefer tabs setting -- Window being treaten as focused by default on Wayland +- Window being treated as focused by default on Wayland ### Removed @@ -342,7 +342,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - OSC 104 not clearing colors when second parameter is empty - Builtin font lines not contiguous when `font.offset` is used - `font.glyph_offset` is no longer applied on builtin font -- Buili-in font arcs alignment +- Built-in font arcs alignment - Repeated permission prompts on M1 macs - Colors being slightly off when using `colors.transparent_background_colors` @@ -674,7 +674,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Reflow of cursor during resize - Cursor color escape ignored when its color is set to inverted in the config - Fontconfig's `autohint` and `hinting` options being ignored -- Ingoring of default FreeType properties +- Ignoring of default FreeType properties - Alacritty crashing at startup when the configured font does not exist - Font size rounding error - Opening URLs while search is active @@ -882,7 +882,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Block URL highlight while a selection is active - Bindings for Alt + F1-F12 - Discard scrolling region escape with bottom above top -- Opacity always applying to cells with their background color matching the teriminal background +- Opacity always applying to cells with their background color matching the terminal background - Allow semicolons when setting titles using an OSC - Background always opaque on X11 - Skipping redraws on PTY update @@ -952,7 +952,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its ### Fixed -- Double-width characters in URLs only being highlit on the left half +- Double-width characters in URLs only being highlighted on the left half - PTY size not getting updated when message bar is shown - Text Cursor disappearing - Incorrect positioning of zero-width characters over double-width characters diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fe7b2a71..52674cc4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -34,7 +34,7 @@ introduced the regression helps out a lot. ## Patches / Pull Requests -All patches have to be sent on Github as [pull requests](https://github.com/alacritty/alacritty/pulls). +All patches have to be sent on GitHub as [pull requests](https://github.com/alacritty/alacritty/pulls). If you are looking for a place to start contributing to Alacritty, take a look at the [help wanted](https://github.com/alacritty/alacritty/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22) diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index 580a3dad..a40dcaf8 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -499,7 +499,7 @@ impl<'de> Deserialize<'de> for HintContent { // Require at least one of hyperlinks or regex trigger hint matches. if content.regex.is_none() && !content.hyperlinks { return Err(M::Error::custom( - "Config error: At least on of the hint's regex or hint's hyperlinks must \ + "Config error: At least one of the hint's regex or hint's hyperlinks must \ be set", )); } diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 9505e1a3..b9bf3030 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -142,7 +142,7 @@ impl Processor { ) -> Result<(), Box> { let window = self.windows.iter().next().as_ref().unwrap().1; - // Overide config with CLI/IPC options. + // Override config with CLI/IPC options. let mut config_overrides = options.config_overrides(); #[cfg(unix)] config_overrides.extend_from_slice(&self.global_ipc_options); @@ -1439,7 +1439,7 @@ impl<'a, N: Notify + 'a, T: EventListener> ActionContext<'a, N, T> { self.scheduler.unschedule(TimerId::new(Topic::BlinkCursor, window_id)); self.scheduler.unschedule(TimerId::new(Topic::BlinkTimeout, window_id)); - // Reset blinkinig timeout. + // Reset blinking timeout. *self.cursor_blink_timed_out = false; if blinking && self.terminal.is_focused { diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index fce5efbf..d63da9f2 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -230,7 +230,7 @@ impl> Processor { _ if mode.contains(TermMode::REPORT_ALL_KEYS_AS_ESC) => { build_sequence(key, mods, mode).into() }, - // Winit uses different keys for `Backspace` so we expliictly specify the + // Winit uses different keys for `Backspace` so we explicitly specify the // values, instead of using what was passed to us from it. Key::Named(NamedKey::Tab) => [b'\t'].as_slice().into(), Key::Named(NamedKey::Enter) => [b'\r'].as_slice().into(), diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 54b64a73..4113ed9c 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -2082,7 +2082,7 @@ impl Handler for Term { let mode = match mode { ansi::Mode::Named(mode) => mode, ansi::Mode::Unknown(mode) => { - debug!("Ignorning unknown mode {} in unset_mode", mode); + debug!("Ignoring unknown mode {} in unset_mode", mode); return; }, }; diff --git a/alacritty_terminal/src/tty/unix.rs b/alacritty_terminal/src/tty/unix.rs index 8f335500..8084a753 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -124,7 +124,7 @@ struct ShellUser { impl ShellUser { /// look for shell, username, longname, and home dir in the respective environment variables - /// before falling back on looking in to `passwd`. + /// before falling back on looking into `passwd`. fn from_env() -> Result { let mut buf = [0; 1024]; let pw = get_pw_entry(&mut buf); diff --git a/docs/features.md b/docs/features.md index 29ff7ee8..43a29309 100644 --- a/docs/features.md +++ b/docs/features.md @@ -30,8 +30,8 @@ active. ## Search Search allows you to find anything in Alacritty's scrollback buffer. You can -search forward using Ctrl Shift f (Command f on MacOS) and -backward using Ctrl Shift b (Command b on MacOS). +search forward using Ctrl Shift f (Command f on macOS) and +backward using Ctrl Shift b (Command b on macOS). ### Vi Search diff --git a/scripts/create-flamegraph.sh b/scripts/create-flamegraph.sh index 921cee8a..ddfee813 100755 --- a/scripts/create-flamegraph.sh +++ b/scripts/create-flamegraph.sh @@ -21,7 +21,7 @@ fi # Create flamegraph cargo flamegraph --bin=alacritty -- $@ -# Unintall cargo-flamegraph if it has been installed with this script +# Uninstall cargo-flamegraph if it has been installed with this script if [ $installed_flamegraph == 1 ]; then read -p "Would you like to uninstall cargo-flamegraph? [Y/n] " -n 1 -r echo From 64ba0b8e915ad167b6d5cb4395da018e436385d6 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 8 Jun 2024 15:28:51 +0300 Subject: [PATCH 049/102] Bump glutin to 0.32.0 --- Cargo.lock | 110 ++++++++--------------------- alacritty/Cargo.toml | 5 +- alacritty/src/clipboard.rs | 4 +- alacritty/src/display/mod.rs | 2 +- alacritty/src/display/window.rs | 20 +++--- alacritty/src/event.rs | 4 +- alacritty/src/main.rs | 9 ++- alacritty/src/renderer/platform.rs | 2 +- alacritty/src/window_context.rs | 4 +- 9 files changed, 56 insertions(+), 104 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index f73c36a9..713a3080 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -55,7 +55,6 @@ dependencies = [ "objc", "parking_lot", "png", - "raw-window-handle", "serde", "serde_json", "serde_yaml", @@ -244,32 +243,13 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae85a0696e7ea3b835a453750bf002770776609115e6d25c6d2ff28a8200f7e7" -dependencies = [ - "objc-sys", -] - -[[package]] -name = "block2" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" -dependencies = [ - "block-sys", - "objc2 0.4.1", -] - [[package]] name = "block2" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "43ff7d91d3c1d568065b06c899777d1e48dcf76103a672a0adbc238a7f247f1e" dependencies = [ - "objc2 0.5.1", + "objc2", ] [[package]] @@ -340,15 +320,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - -[[package]] -name = "cfg_aliases" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77e53693616d3075149f4ead59bdeecd204ac6b8192d8969757601b74bddf00f" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "cgl" @@ -835,43 +809,44 @@ dependencies = [ [[package]] name = "glutin" -version = "0.31.3" +version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fcd4ae4e86d991ad1300b8f57166e5be0c95ef1f63f3f5b827f8a164548746" +checksum = "2491aa3090f682ddd920b184491844440fdd14379c7eef8f5bc10ef7fb3242fd" dependencies = [ "bitflags 2.4.2", - "cfg_aliases 0.1.1", + "cfg_aliases", "cgl", "core-foundation", "dispatch", "glutin_egl_sys", "glutin_glx_sys", "glutin_wgl_sys", - "icrate", "libloading", - "objc2 0.4.1", + "objc2", + "objc2-app-kit", + "objc2-foundation", "once_cell", "raw-window-handle", "wayland-sys", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "x11-dl", ] [[package]] name = "glutin_egl_sys" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77cc5623f5309ef433c3dd4ca1223195347fe62c413da8e2fdd0eb76db2d9bcd" +checksum = "cae99fff4d2850dbe6fb8c1fa8e4fead5525bab715beaacfccf3fb994e01c827" dependencies = [ "gl_generator", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "glutin_glx_sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a165fd686c10dcc2d45380b35796e577eacfd43d4660ee741ec8ebe2201b3b4f" +checksum = "9c2b2d3918e76e18e08796b55eb64e8fe6ec67d5a6b2e2a7e2edce224ad24c63" dependencies = [ "gl_generator", "x11-dl", @@ -879,9 +854,9 @@ dependencies = [ [[package]] name = "glutin_wgl_sys" -version = "0.5.0" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8098adac955faa2d31079b65dc48841251f69efd3ac25477903fc424362ead" +checksum = "0a4e1951bbd9434a81aa496fe59ccc2235af3820d27b85f9314e279609211e2c" dependencies = [ "gl_generator", ] @@ -907,17 +882,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "icrate" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" -dependencies = [ - "block2 0.3.0", - "dispatch", - "objc2 0.4.1", -] - [[package]] name = "indexmap" version = "2.2.5" @@ -1045,7 +1009,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] [[package]] @@ -1246,16 +1210,6 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da284c198fb9b7b0603f8635185e85fbd5b64ee154b1ed406d489077de2d6d60" -[[package]] -name = "objc2" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" -dependencies = [ - "objc-sys", - "objc2-encode 3.0.0", -] - [[package]] name = "objc2" version = "0.5.1" @@ -1263,7 +1217,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4b25e1034d0e636cd84707ccdaa9f81243d399196b8a773946dcffec0401659" dependencies = [ "objc-sys", - "objc2-encode 4.0.1", + "objc2-encode", ] [[package]] @@ -1272,8 +1226,8 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb79768a710a9a1798848179edb186d1af7e8a8679f369e4b8d201dd2a034047" dependencies = [ - "block2 0.5.0", - "objc2 0.5.1", + "block2", + "objc2", "objc2-core-data", "objc2-foundation", ] @@ -1284,17 +1238,11 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e092bc42eaf30a08844e6a076938c60751225ec81431ab89f5d1ccd9f958d6c" dependencies = [ - "block2 0.5.0", - "objc2 0.5.1", + "block2", + "objc2", "objc2-foundation", ] -[[package]] -name = "objc2-encode" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" - [[package]] name = "objc2-encode" version = "4.0.1" @@ -1307,9 +1255,9 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cfaefe14254871ea16c7d88968c0ff14ba554712a20d76421eec52f0a7fb8904" dependencies = [ - "block2 0.5.0", + "block2", "dispatch", - "objc2 0.5.1", + "objc2", ] [[package]] @@ -1479,9 +1427,9 @@ dependencies = [ [[package]] name = "raw-window-handle" -version = "0.5.2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +checksum = "20675572f6f24e9e76ef639bc5552774ed45f1c30e2951e1e99c59888861c539" [[package]] name = "redox_syscall" @@ -2414,7 +2362,7 @@ dependencies = [ "bitflags 2.4.2", "bytemuck", "calloop", - "cfg_aliases 0.2.0", + "cfg_aliases", "concurrent-queue", "core-foundation", "core-graphics", @@ -2424,7 +2372,7 @@ dependencies = [ "libc", "memmap2", "ndk", - "objc2 0.5.1", + "objc2", "objc2-app-kit", "objc2-foundation", "orbclient", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 10ee1aee..947f3ea1 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -28,19 +28,18 @@ bitflags = "2.2.1" clap = { version = "4.2.7", features = ["derive", "env"] } copypasta = { version = "0.10.1", default-features = false } crossfont = "0.8.0" -glutin = { version = "0.31.1", default-features = false, features = ["egl", "wgl"] } +glutin = { version = "0.32.0", default-features = false, features = ["egl", "wgl"] } home = "0.5.5" libc = "0.2" log = { version = "0.4", features = ["std", "serde"] } notify = "6.1.1" parking_lot = "0.12.0" -raw-window-handle = "0.5" serde = { version = "1", features = ["derive"] } serde_json = "1" serde_yaml = "0.9.25" toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.30.0", default-features = false, features = ["rwh_05", "serde"] } +winit = { version = "0.30.0", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] gl_generator = "0.14.0" diff --git a/alacritty/src/clipboard.rs b/alacritty/src/clipboard.rs index bb90a13d..7853de47 100644 --- a/alacritty/src/clipboard.rs +++ b/alacritty/src/clipboard.rs @@ -1,5 +1,5 @@ use log::{debug, warn}; -use raw_window_handle::RawDisplayHandle; +use winit::raw_window_handle::RawDisplayHandle; use alacritty_terminal::term::ClipboardType; @@ -23,7 +23,7 @@ impl Clipboard { #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))] RawDisplayHandle::Wayland(display) => { let (selection, clipboard) = - wayland_clipboard::create_clipboards_from_external(display.display); + wayland_clipboard::create_clipboards_from_external(display.display.as_ptr()); Self { clipboard: Box::new(clipboard), selection: Some(Box::new(selection)) } }, _ => Self::default(), diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index 4dafa80f..1841b167 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -14,10 +14,10 @@ use glutin::surface::{Surface, SwapInterval, WindowSurface}; use log::{debug, info}; use parking_lot::MutexGuard; -use raw_window_handle::RawWindowHandle; use serde::{Deserialize, Serialize}; use winit::dpi::PhysicalSize; use winit::keyboard::ModifiersState; +use winit::raw_window_handle::RawWindowHandle; use winit::window::CursorIcon; use crossfont::{Rasterize, Rasterizer, Size as FontSize}; diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 09793fa0..da5d85bc 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -26,12 +26,12 @@ use { winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS}, }; -use raw_window_handle::{HasRawWindowHandle, RawWindowHandle}; use winit::dpi::{PhysicalPosition, PhysicalSize}; use winit::event_loop::ActiveEventLoop; use winit::monitor::MonitorHandle; #[cfg(windows)] use winit::platform::windows::IconExtWindows; +use winit::raw_window_handle::{HasWindowHandle, RawWindowHandle}; use winit::window::{ CursorIcon, Fullscreen, ImePurpose, Theme, UserAttentionType, Window as WinitWindow, WindowAttributes, WindowId, @@ -190,7 +190,7 @@ impl Window { let scale_factor = window.scale_factor(); log::info!("Window scale factor: {}", scale_factor); - let is_x11 = matches!(window.raw_window_handle(), RawWindowHandle::Xlib(_)); + let is_x11 = matches!(window.window_handle().unwrap().as_raw(), RawWindowHandle::Xlib(_)); Ok(Self { requested_redraw: false, @@ -206,7 +206,7 @@ impl Window { #[inline] pub fn raw_window_handle(&self) -> RawWindowHandle { - self.window.raw_window_handle() + self.window.window_handle().unwrap().as_raw() } #[inline] @@ -444,14 +444,15 @@ impl Window { /// This prevents rendering artifacts from showing up when the window is transparent. #[cfg(target_os = "macos")] pub fn set_has_shadow(&self, has_shadows: bool) { - let raw_window = match self.raw_window_handle() { - RawWindowHandle::AppKit(handle) => handle.ns_window as id, + let ns_view = match self.raw_window_handle() { + RawWindowHandle::AppKit(handle) => handle.ns_view.as_ptr() as id, _ => return, }; let value = if has_shadows { YES } else { NO }; unsafe { - let _: id = msg_send![raw_window, setHasShadow: value]; + let ns_window: id = msg_send![ns_view, window]; + let _: id = msg_send![ns_window, setHasShadow: value]; } } @@ -487,12 +488,13 @@ impl Window { #[cfg(target_os = "macos")] fn use_srgb_color_space(window: &WinitWindow) { - let raw_window = match window.raw_window_handle() { - RawWindowHandle::AppKit(handle) => handle.ns_window as id, + let ns_view = match window.window_handle().unwrap().as_raw() { + RawWindowHandle::AppKit(handle) => handle.ns_view.as_ptr() as id, _ => return, }; unsafe { - let _: () = msg_send![raw_window, setColorSpace: NSColorSpace::sRGBColorSpace(nil)]; + let ns_window: id = msg_send![ns_view, window]; + let _: () = msg_send![ns_window, setColorSpace: NSColorSpace::sRGBColorSpace(nil)]; } } diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index b9bf3030..8da758df 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -17,13 +17,13 @@ use ahash::RandomState; use crossfont::Size as FontSize; use glutin::display::{Display as GlutinDisplay, GetGlDisplay}; use log::{debug, error, info, warn}; -use raw_window_handle::HasRawDisplayHandle; use winit::application::ApplicationHandler; use winit::event::{ ElementState, Event as WinitEvent, Ime, Modifiers, MouseButton, StartCause, Touch as TouchEvent, WindowEvent, }; use winit::event_loop::{ActiveEventLoop, ControlFlow, DeviceEvents, EventLoop, EventLoopProxy}; +use winit::raw_window_handle::HasDisplayHandle; use winit::window::WindowId; use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify}; @@ -99,7 +99,7 @@ impl Processor { // SAFETY: Since this takes a pointer to the winit event loop, it MUST be dropped first, // which is done in `loop_exiting`. - let clipboard = unsafe { Clipboard::new(event_loop.raw_display_handle()) }; + let clipboard = unsafe { Clipboard::new(event_loop.display_handle().unwrap().as_raw()) }; Processor { initial_window_options, diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 2951c224..6219dd78 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -19,11 +19,11 @@ use std::path::PathBuf; use std::{env, fs}; use log::info; -#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] -use raw_window_handle::{HasRawDisplayHandle, RawDisplayHandle}; #[cfg(windows)] use windows_sys::Win32::System::Console::{AttachConsole, FreeConsole, ATTACH_PARENT_PROCESS}; use winit::event_loop::EventLoop; +#[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] +use winit::raw_window_handle::{HasDisplayHandle, RawDisplayHandle}; use alacritty_terminal::tty; @@ -137,7 +137,10 @@ fn alacritty(mut options: Options) -> Result<(), Box> { #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] info!( "Running on {}", - if matches!(window_event_loop.raw_display_handle(), RawDisplayHandle::Wayland(_)) { + if matches!( + window_event_loop.display_handle().unwrap().as_raw(), + RawDisplayHandle::Wayland(_) + ) { "Wayland" } else { "X11" diff --git a/alacritty/src/renderer/platform.rs b/alacritty/src/renderer/platform.rs index 3568bd20..87ed29c2 100644 --- a/alacritty/src/renderer/platform.rs +++ b/alacritty/src/renderer/platform.rs @@ -12,10 +12,10 @@ use glutin::prelude::*; use glutin::surface::{Surface, SurfaceAttributesBuilder, WindowSurface}; use log::{debug, LevelFilter}; -use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use winit::dpi::PhysicalSize; #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] use winit::platform::x11; +use winit::raw_window_handle::{RawDisplayHandle, RawWindowHandle}; /// Create the GL display. pub fn create_gl_display( diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index f5fb5cc5..062f9ef0 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -14,10 +14,10 @@ use glutin::display::GetGlDisplay; #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] use glutin::platform::x11::X11GlConfigExt; use log::info; -use raw_window_handle::HasRawDisplayHandle; use serde_json as json; use winit::event::{Event as WinitEvent, Modifiers, WindowEvent}; use winit::event_loop::{ActiveEventLoop, EventLoopProxy}; +use winit::raw_window_handle::HasDisplayHandle; use winit::window::WindowId; use alacritty_terminal::event::Event as TerminalEvent; @@ -75,7 +75,7 @@ impl WindowContext { config: Rc, options: WindowOptions, ) -> Result> { - let raw_display_handle = event_loop.raw_display_handle(); + let raw_display_handle = event_loop.display_handle().unwrap().as_raw(); let mut identity = config.window.identity.clone(); options.window_identity.override_identity_config(&mut identity); From 0d4ab7bca43213d96ddfe40048fc0f922543c6f8 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 16 Jun 2024 10:37:33 +0300 Subject: [PATCH 050/102] Bump winit to 0.30.2 Fixes #7969. --- Cargo.lock | 225 +++++++++++++++++++++++++++++++++++-------- alacritty/Cargo.toml | 2 +- 2 files changed, 188 insertions(+), 39 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 713a3080..34cf72bc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -38,7 +38,7 @@ dependencies = [ "alacritty_config", "alacritty_config_derive", "alacritty_terminal", - "bitflags 2.4.2", + "bitflags 2.5.0", "clap", "clap_complete", "cocoa", @@ -93,7 +93,7 @@ name = "alacritty_terminal" version = "0.24.1-dev" dependencies = [ "base64", - "bitflags 2.4.2", + "bitflags 2.5.0", "home", "libc", "log", @@ -118,7 +118,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.4.2", + "bitflags 2.5.0", "cc", "cesu8", "jni", @@ -230,9 +230,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" +checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" dependencies = [ "serde", ] @@ -245,9 +245,9 @@ checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] name = "block2" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43ff7d91d3c1d568065b06c899777d1e48dcf76103a672a0adbc238a7f247f1e" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ "objc2", ] @@ -276,7 +276,7 @@ version = "0.12.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fba7adb4dd5aa98e5553510223000e7148f621165ec5f9acd7113f6ca4995298" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "log", "polling", "rustix", @@ -744,7 +744,7 @@ version = "0.36.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5442dee36ca09604133580dc0553780e867936bb3cbef3275859e889026d2b17" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "freetype-sys", "libc", ] @@ -813,7 +813,7 @@ version = "0.32.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2491aa3090f682ddd920b184491844440fdd14379c7eef8f5bc10ef7fb3242fd" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cfg_aliases", "cgl", "core-foundation", @@ -1018,7 +1018,7 @@ version = "0.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "redox_syscall 0.4.1", ] @@ -1029,7 +1029,7 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "libc", "redox_syscall 0.4.1", ] @@ -1120,7 +1120,7 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3f42e7bbe13d351b6bead8286a43aac9534b82bd3cc43e47037f012ebfd62d4" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "jni-sys", "log", "ndk-sys", @@ -1150,7 +1150,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -1206,15 +1206,15 @@ dependencies = [ [[package]] name = "objc-sys" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da284c198fb9b7b0603f8635185e85fbd5b64ee154b1ed406d489077de2d6d60" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" [[package]] name = "objc2" -version = "0.5.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b25e1034d0e636cd84707ccdaa9f81243d399196b8a773946dcffec0401659" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" dependencies = [ "objc-sys", "objc2-encode", @@ -1222,44 +1222,191 @@ dependencies = [ [[package]] name = "objc2-app-kit" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb79768a710a9a1798848179edb186d1af7e8a8679f369e4b8d201dd2a034047" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" dependencies = [ + "bitflags 2.5.0", "block2", + "libc", "objc2", "objc2-core-data", + "objc2-core-image", + "objc2-foundation", + "objc2-quartz-core", +] + +[[package]] +name = "objc2-cloud-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" +dependencies = [ + "bitflags 2.5.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + +[[package]] +name = "objc2-contacts" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" +dependencies = [ + "block2", + "objc2", "objc2-foundation", ] [[package]] name = "objc2-core-data" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e092bc42eaf30a08844e6a076938c60751225ec81431ab89f5d1ccd9f958d6c" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" dependencies = [ + "bitflags 2.5.0", "block2", "objc2", "objc2-foundation", ] +[[package]] +name = "objc2-core-image" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-core-location" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" +dependencies = [ + "block2", + "objc2", + "objc2-contacts", + "objc2-foundation", +] + [[package]] name = "objc2-encode" -version = "4.0.1" +version = "4.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88658da63e4cc2c8adb1262902cd6af51094df0488b760d6fd27194269c0950a" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" [[package]] name = "objc2-foundation" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfaefe14254871ea16c7d88968c0ff14ba554712a20d76421eec52f0a7fb8904" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" dependencies = [ + "bitflags 2.5.0", "block2", "dispatch", + "libc", "objc2", ] +[[package]] +name = "objc2-link-presentation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" +dependencies = [ + "block2", + "objc2", + "objc2-app-kit", + "objc2-foundation", +] + +[[package]] +name = "objc2-metal" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +dependencies = [ + "bitflags 2.5.0", + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-quartz-core" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +dependencies = [ + "bitflags 2.5.0", + "block2", + "objc2", + "objc2-foundation", + "objc2-metal", +] + +[[package]] +name = "objc2-symbols" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +dependencies = [ + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-ui-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" +dependencies = [ + "bitflags 2.5.0", + "block2", + "objc2", + "objc2-cloud-kit", + "objc2-core-data", + "objc2-core-image", + "objc2-core-location", + "objc2-foundation", + "objc2-link-presentation", + "objc2-quartz-core", + "objc2-symbols", + "objc2-uniform-type-identifiers", + "objc2-user-notifications", +] + +[[package]] +name = "objc2-uniform-type-identifiers" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +dependencies = [ + "block2", + "objc2", + "objc2-foundation", +] + +[[package]] +name = "objc2-user-notifications" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.5.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] + [[package]] name = "objc_id" version = "0.1.1" @@ -1492,7 +1639,7 @@ version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "errno", "itoa", "libc", @@ -1655,7 +1802,7 @@ version = "0.18.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "922fd3eeab3bd820d76537ce8f582b1cf951eceb5475c28500c7457d9d17f53a" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "calloop", "calloop-wayland-source", "cursor-icon", @@ -1885,7 +2032,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40eb22ae96f050e0c0d6f7ce43feeae26c348fc4dea56928ca81537cfaa6188b" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cursor-icon", "log", "serde", @@ -2005,7 +2152,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "rustix", "wayland-backend", "wayland-scanner", @@ -2017,7 +2164,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "cursor-icon", "wayland-backend", ] @@ -2039,7 +2186,7 @@ version = "0.31.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -2051,7 +2198,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2064,7 +2211,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -2352,14 +2499,15 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winit" -version = "0.30.0" +version = "0.30.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea9e6d5d66cbf702e0dd820302144f51b69a95acdc495dd98ca280ff206562b1" +checksum = "1dc930d6cfbf53c4fe0b95689cdc2e17b8658c3f4214b9953298ccb5a1a15c90" dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.4.2", + "bitflags 2.5.0", + "block2", "bytemuck", "calloop", "cfg_aliases", @@ -2375,6 +2523,7 @@ dependencies = [ "objc2", "objc2-app-kit", "objc2-foundation", + "objc2-ui-kit", "orbclient", "percent-encoding", "pin-project", @@ -2498,7 +2647,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" dependencies = [ - "bitflags 2.4.2", + "bitflags 2.5.0", "dlib", "log", "once_cell", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 947f3ea1..1abf4912 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -39,7 +39,7 @@ serde_json = "1" serde_yaml = "0.9.25" toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.30.0", default-features = false, features = ["rwh_06", "serde"] } +winit = { version = "0.30.2", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] gl_generator = "0.14.0" From da554e41f3a91ed6cc5db66b23bf65c58529db83 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 23 Jun 2024 17:56:19 +0300 Subject: [PATCH 051/102] Bump winit to 0.30.3 Fixes #8046. --- Cargo.lock | 4 ++-- alacritty/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 34cf72bc..92fe281f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2499,9 +2499,9 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winit" -version = "0.30.2" +version = "0.30.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dc930d6cfbf53c4fe0b95689cdc2e17b8658c3f4214b9953298ccb5a1a15c90" +checksum = "49f45a7b7e2de6af35448d7718dab6d95acec466eb3bb7a56f4d31d1af754004" dependencies = [ "ahash", "android-activity", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 1abf4912..a2fd0433 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -39,7 +39,7 @@ serde_json = "1" serde_yaml = "0.9.25" toml = "0.8.2" unicode-width = "0.1" -winit = { version = "0.30.2", default-features = false, features = ["rwh_06", "serde"] } +winit = { version = "0.30.3", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] gl_generator = "0.14.0" From 138ac426bfeb73db4f00d13a9126527d02c1e867 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 2 Jul 2024 19:55:26 +0300 Subject: [PATCH 052/102] Use latest macOS image on CI (#8072) Old macOS images are deprecated resulting in often failures, thus use latest macOS images available. Also given that macOS is arm64 by default check x86_64 as extra job and not arm64. --- .github/workflows/ci.yml | 8 ++++---- .github/workflows/release.yml | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 573c4e0f..2fe8dd2c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,11 +27,11 @@ jobs: run: | rustup component add clippy cargo clippy --all-targets - check-macos-arm: - runs-on: macos-11 + check-macos-x86_64: + runs-on: macos-latest steps: - uses: actions/checkout@v3 - name: Install target - run: rustup update && rustup target add aarch64-apple-darwin + run: rustup update && rustup target add x86_64-apple-darwin - name: Build - run: cargo build --target=aarch64-apple-darwin + run: cargo build --target=x86_64-apple-darwin diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3918a540..e161816c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,16 +10,16 @@ env: jobs: macos: - runs-on: macos-11 + runs-on: macos-latest steps: - uses: actions/checkout@v3 - name: Install dependencies run: brew install scdoc - name: Install ARM target - run: rustup update && rustup target add aarch64-apple-darwin + run: rustup update && rustup target add aarch64-apple-darwin && rustup target add x86_64-apple-darwin - name: Test - run: cargo test --release + run: cargo test --release --target=x86_64-apple-darwin - name: Build ARM run: cargo build --release --target=aarch64-apple-darwin - name: Make DMG From 5e6b92db85b3ea7ffd06a7a5ae0d2d62ad5946a6 Mon Sep 17 00:00:00 2001 From: Joshua Cao Date: Tue, 2 Jul 2024 12:14:25 -0700 Subject: [PATCH 053/102] Support relative imports in config file Co-authored-by: Christian Duerr --- CHANGELOG.md | 4 ++++ alacritty/src/config/mod.rs | 18 +++++++++++++++--- alacritty/src/migrate.rs | 5 +++-- extra/man/alacritty.5.scd | 6 ++++-- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d1bd0c8..97d3de84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ Notable changes to the `alacritty_terminal` crate are documented in its ## 0.14.0-dev +### Added + +- Support relative path imports from config files + ### Changed - Pressing `Alt` with unicode input will now add `ESC` like for ASCII input diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs index f043d73b..488ef537 100644 --- a/alacritty/src/config/mod.rs +++ b/alacritty/src/config/mod.rs @@ -205,7 +205,7 @@ fn parse_config( let config = deserialize_config(path, false)?; // Merge config with imports. - let imports = load_imports(&config, config_paths, recursion_limit); + let imports = load_imports(&config, path, config_paths, recursion_limit); Ok(serde_utils::merge(imports, config)) } @@ -237,9 +237,14 @@ pub fn deserialize_config(path: &Path, warn_pruned: bool) -> Result { } /// Load all referenced configuration files. -fn load_imports(config: &Value, config_paths: &mut Vec, recursion_limit: usize) -> Value { +fn load_imports( + config: &Value, + base_path: &Path, + config_paths: &mut Vec, + recursion_limit: usize, +) -> Value { // Get paths for all imports. - let import_paths = match imports(config, recursion_limit) { + let import_paths = match imports(config, base_path, recursion_limit) { Ok(import_paths) => import_paths, Err(err) => { error!(target: LOG_TARGET_CONFIG, "{err}"); @@ -278,6 +283,7 @@ fn load_imports(config: &Value, config_paths: &mut Vec, recursion_limit /// 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") { @@ -307,6 +313,12 @@ pub fn imports( path = home_dir.join(stripped); } + if path.is_relative() { + if let Some(base_path) = base_path.parent() { + path = base_path.join(path) + } + } + import_paths.push(Ok(path)); } diff --git a/alacritty/src/migrate.rs b/alacritty/src/migrate.rs index dbcfb2ae..6d116858 100644 --- a/alacritty/src/migrate.rs +++ b/alacritty/src/migrate.rs @@ -81,7 +81,7 @@ fn migrate_config( // Migrate config imports. if !options.skip_imports { - migrate_imports(options, &mut config, recursion_limit)?; + migrate_imports(options, &mut config, path, recursion_limit)?; } // Migrate deprecated field names to their new location. @@ -110,9 +110,10 @@ fn migrate_config( fn migrate_imports( options: &MigrateOptions, config: &mut Value, + base_path: &Path, recursion_limit: usize, ) -> Result<(), String> { - let imports = match config::imports(config, recursion_limit) { + let imports = match config::imports(config, base_path, recursion_limit) { Ok(imports) => imports, Err(err) => return Err(format!("import error: {err}")), }; diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index 1b56210b..15bc2127 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -35,13 +35,15 @@ This section documents the root level of the configuration file. file being loaded last. If a field is already present in a previous import, it will be replaced. - All imports must either be absolute paths starting with _/_, or paths - relative to the user's home directory starting with _~/_. + All imports must either be absolute paths starting with _/_, paths relative + to the user's home directory starting with _~/_, or paths relative from the + current config file. Example: import = [++ _"~/.config/alacritty/base16-dark.toml"_,++ _"~/.config/alacritty/keybindings.toml"_,++ + _"alacritty-theme/themes/gruvbox_dark.toml"_,++ ] *shell* = _""_ | { program = _""_, args = [_""_,] } From b3f0f68184b0d6b6221a5955acfcc4e33c01b766 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Fri, 5 Jul 2024 12:12:15 +0200 Subject: [PATCH 054/102] Fix search bug with wrapline on first character This fixes an issue where an inline search in the left direction would incorrectly assume that the first cell searched would not contain the `WRAPLINE` flag, causing the second search for the match end to terminate prematurely. Fixes #8060. --- CHANGELOG.md | 1 + alacritty/src/renderer/text/glyph_cache.rs | 13 ++++--------- alacritty_terminal/src/term/mod.rs | 12 ++++++------ alacritty_terminal/src/term/search.rs | 18 +++++++++++++++++- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 97d3de84..8442355a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -31,6 +31,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Leaking FDs when closing windows on Unix systems - 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 ## 0.13.2 diff --git a/alacritty/src/renderer/text/glyph_cache.rs b/alacritty/src/renderer/text/glyph_cache.rs index 957cde1a..6acc3189 100644 --- a/alacritty/src/renderer/text/glyph_cache.rs +++ b/alacritty/src/renderer/text/glyph_cache.rs @@ -187,14 +187,9 @@ impl GlyphCache { /// /// This will fail when the glyph could not be rasterized. Usually this is due to the glyph /// not being present in any font. - pub fn get( - &mut self, - glyph_key: GlyphKey, - loader: &mut L, - show_missing: bool, - ) -> Glyph + pub fn get(&mut self, glyph_key: GlyphKey, loader: &mut L, show_missing: bool) -> Glyph where - L: LoadGlyph, + L: LoadGlyph + ?Sized, { // Try to load glyph from cache. if let Some(glyph) = self.cache.get(&glyph_key) { @@ -242,9 +237,9 @@ impl GlyphCache { /// Load glyph into the atlas. /// /// This will apply all transforms defined for the glyph cache to the rasterized glyph before - pub fn load_glyph(&self, loader: &mut L, mut glyph: RasterizedGlyph) -> Glyph + pub fn load_glyph(&self, loader: &mut L, mut glyph: RasterizedGlyph) -> Glyph where - L: LoadGlyph, + L: LoadGlyph + ?Sized, { glyph.left += i32::from(self.glyph_offset.x); glyph.top += i32::from(self.glyph_offset.y); diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 4113ed9c..5dfd880c 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -1445,15 +1445,15 @@ impl Handler for Term { /// edition, in LINE FEED mode, /// /// > The execution of the formatter functions LINE FEED (LF), FORM FEED - /// (FF), LINE TABULATION (VT) cause only movement of the active position in - /// the direction of the line progression. + /// > (FF), LINE TABULATION (VT) cause only movement of the active position in + /// > the direction of the line progression. /// /// In NEW LINE mode, /// /// > The execution of the formatter functions LINE FEED (LF), FORM FEED - /// (FF), LINE TABULATION (VT) cause movement to the line home position on - /// the following line, the following form, etc. In the case of LF this is - /// referred to as the New Line (NL) option. + /// > (FF), LINE TABULATION (VT) cause movement to the line home position on + /// > the following line, the following form, etc. In the case of LF this is + /// > referred to as the New Line (NL) option. /// /// Additionally, ECMA-48 4th edition says that this option is deprecated. /// ECMA-48 5th edition only mentions this option (without explanation) @@ -2187,7 +2187,7 @@ impl Handler for Term { fn set_title(&mut self, title: Option) { trace!("Setting title to '{:?}'", title); - self.title = title.clone(); + self.title.clone_from(&title); let title_event = match title { Some(title) => Event::Title(title), diff --git a/alacritty_terminal/src/term/search.rs b/alacritty_terminal/src/term/search.rs index 585e191c..a5ae9337 100644 --- a/alacritty_terminal/src/term/search.rs +++ b/alacritty_terminal/src/term/search.rs @@ -293,12 +293,12 @@ impl Term { let mut state = regex.dfa.start_state_forward(&mut regex.cache, &input).unwrap(); let mut iter = self.grid.iter_from(start); - let mut last_wrapped = false; let mut regex_match = None; let mut done = false; let mut cell = iter.cell(); self.skip_fullwidth(&mut iter, &mut cell, regex.direction); + let mut last_wrapped = cell.flags.contains(Flags::WRAPLINE); let mut c = cell.c; let mut point = iter.point(); @@ -1155,4 +1155,20 @@ mod tests { assert_eq!(start, Point::new(Line(1), Column(0))); assert_eq!(end, Point::new(Line(1), Column(2))); } + + #[test] + fn inline_word_search() { + #[rustfmt::skip] + let term = mock_term("\ + word word word word w\n\ + ord word word word\ + "); + + let mut regex = RegexSearch::new("word").unwrap(); + let start = Point::new(Line(1), Column(4)); + let end = Point::new(Line(0), Column(0)); + let match_start = Point::new(Line(0), Column(20)); + let match_end = Point::new(Line(1), Column(2)); + assert_eq!(term.regex_search_left(&mut regex, start, end), Some(match_start..=match_end)); + } } From 3504246c3f57769ca0528fe397e866a13c49f039 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Wed, 17 Jul 2024 05:07:32 +0300 Subject: [PATCH 055/102] Bump MSRV to 1.74.0 --- CHANGELOG.md | 4 ++++ alacritty/Cargo.toml | 2 +- alacritty/src/string.rs | 1 + alacritty_config/Cargo.toml | 2 +- alacritty_config_derive/Cargo.toml | 2 +- alacritty_terminal/Cargo.toml | 2 +- 6 files changed, 9 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8442355a..203624fe 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ Notable changes to the `alacritty_terminal` crate are documented in its ## 0.14.0-dev +### Packaging + +- Minimum Rust version has been bumped to 1.74.0 + ### Added - Support relative path imports from config files diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index a2fd0433..1bc8f0fe 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -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" [dependencies.alacritty_terminal] path = "../alacritty_terminal" diff --git a/alacritty/src/string.rs b/alacritty/src/string.rs index e41b0785..a7af4394 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_config/Cargo.toml b/alacritty_config/Cargo.toml index c09a05e2..4ca631af 100644 --- a/alacritty_config/Cargo.toml +++ b/alacritty_config/Cargo.toml @@ -7,7 +7,7 @@ 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"] } diff --git a/alacritty_config_derive/Cargo.toml b/alacritty_config_derive/Cargo.toml index dce13237..f74a7cba 100644 --- a/alacritty_config_derive/Cargo.toml +++ b/alacritty_config_derive/Cargo.toml @@ -7,7 +7,7 @@ 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 diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index 79e7c05b..e643e081 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -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"] From f5e02862ffdcc579264ce85f11aed96732b257ff Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Wed, 17 Jul 2024 04:47:13 +0300 Subject: [PATCH 056/102] Bump dependencies Update winit and clap to latest versions. --- Cargo.lock | 567 ++++++++++++++++--------------- alacritty/Cargo.toml | 2 +- alacritty/src/cli.rs | 4 +- alacritty/src/display/hint.rs | 2 +- alacritty/src/input/mod.rs | 32 +- extra/completions/_alacritty | 122 +++---- extra/completions/alacritty.bash | 94 ++++- extra/completions/alacritty.fish | 120 ++++--- 8 files changed, 537 insertions(+), 406 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 92fe281f..566dbc08 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,9 +23,9 @@ 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", ] @@ -38,7 +38,7 @@ dependencies = [ "alacritty_config", "alacritty_config_derive", "alacritty_terminal", - "bitflags 2.5.0", + "bitflags 2.6.0", "clap", "clap_complete", "cocoa", @@ -93,7 +93,7 @@ name = "alacritty_terminal" version = "0.24.1-dev" dependencies = [ "base64", - "bitflags 2.5.0", + "bitflags 2.6.0", "home", "libc", "log", @@ -118,7 +118,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", @@ -140,50 +140,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]] @@ -212,15 +213,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" @@ -230,9 +231,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", ] @@ -254,29 +255,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", @@ -286,9 +287,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", @@ -298,9 +299,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", @@ -335,9 +336,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", @@ -345,9 +346,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", @@ -357,18 +358,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", @@ -378,9 +379,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" @@ -424,15 +425,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", @@ -440,9 +441,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", ] @@ -479,9 +480,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", @@ -515,27 +516,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" @@ -617,9 +618,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" @@ -666,19 +667,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" @@ -691,21 +692,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", @@ -744,7 +745,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", ] @@ -787,9 +788,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", @@ -813,7 +814,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", @@ -863,30 +864,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 = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + +[[package]] +name = "hermit-abi" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" +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.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b0b929d511467233429c45a44ac1dcaa21ba0f5ba11e4879e6ed28ddb4f9df4" +checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", "hashbrown", @@ -912,11 +919,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" @@ -942,9 +955,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", ] @@ -992,59 +1005,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", @@ -1052,9 +1064,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", ] @@ -1070,9 +1082,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" @@ -1085,9 +1097,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", @@ -1120,7 +1132,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", @@ -1150,7 +1162,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", @@ -1226,7 +1238,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", @@ -1242,7 +1254,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", @@ -1266,7 +1278,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", @@ -1308,7 +1320,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", @@ -1333,7 +1345,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", @@ -1345,7 +1357,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", @@ -1368,7 +1380,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", @@ -1400,7 +1412,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", @@ -1439,9 +1451,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", @@ -1449,15 +1461,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]] @@ -1488,15 +1500,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", @@ -1524,16 +1536,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]] @@ -1547,27 +1560,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", ] @@ -1580,38 +1593,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", @@ -1620,9 +1633,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" @@ -1635,16 +1648,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]] @@ -1660,9 +1673,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" @@ -1687,9 +1700,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", @@ -1699,24 +1712,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", @@ -1725,9 +1738,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", @@ -1736,18 +1749,18 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" 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", @@ -1768,9 +1781,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", ] @@ -1792,17 +1805,17 @@ 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" [[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", @@ -1823,9 +1836,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", @@ -1834,9 +1847,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", ] @@ -1849,15 +1862,15 @@ 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", @@ -1866,18 +1879,18 @@ dependencies = [ [[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", @@ -1911,21 +1924,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.15", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" dependencies = [ "serde", ] @@ -1943,15 +1956,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.7" +version = "0.22.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18769cd1cec395d70860ceb4d932812a0b4d06b1a4bb336745a4d21b9496e992" +checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.5", + "winnow 0.6.13", ] [[package]] @@ -1984,9 +1997,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" @@ -1996,9 +2009,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" @@ -2032,7 +2045,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40eb22ae96f050e0c0d6f7ce43feeae26c348fc4dea56928ca81537cfaa6188b" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cursor-icon", "log", "serde", @@ -2042,9 +2055,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", @@ -2134,9 +2147,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", @@ -2148,11 +2161,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", @@ -2164,16 +2177,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", @@ -2182,11 +2195,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", @@ -2194,11 +2207,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", @@ -2207,11 +2220,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", @@ -2220,9 +2233,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", @@ -2231,9 +2244,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", @@ -2279,11 +2292,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]] @@ -2316,7 +2329,7 @@ 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]] @@ -2351,18 +2364,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]] @@ -2379,9 +2392,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" @@ -2397,9 +2410,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" @@ -2415,15 +2428,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" @@ -2439,9 +2452,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" @@ -2457,9 +2470,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" @@ -2475,9 +2488,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" @@ -2493,20 +2506,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", @@ -2561,9 +2574,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.5" +version = "0.6.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dffa400e67ed5a4dd237983829e66475f0a4a26938c4b04c21baede6262215b8" +checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" dependencies = [ "memchr", ] @@ -2610,9 +2623,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", @@ -2625,9 +2638,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" @@ -2647,7 +2660,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", @@ -2656,15 +2669,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" @@ -2680,18 +2693,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 1bc8f0fe..e8739049 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -39,7 +39,7 @@ serde_json = "1" serde_yaml = "0.9.25" toml = "0.8.2" 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 e7f2d3ef..803c1f8c 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -216,10 +216,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); } } } diff --git a/alacritty/src/display/hint.rs b/alacritty/src/display/hint.rs index f118dbe0..a01a1d03 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/input/mod.rs b/alacritty/src/input/mod.rs index 4900e26f..9f7074f4 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -1327,9 +1327,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, @@ -1343,9 +1343,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, @@ -1359,9 +1359,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, @@ -1375,9 +1375,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, @@ -1391,9 +1391,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, @@ -1407,9 +1407,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, @@ -1423,9 +1423,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, @@ -1439,9 +1439,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/extra/completions/_alacritty b/extra/completions/_alacritty index a510fb15..a9260d5c 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' \ @@ -45,7 +45,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 +61,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 +76,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 +87,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (help) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ ":: :_alacritty__msg__help_commands" \ "*::: :->help" \ && ret=0 @@ -99,15 +99,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 +119,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 +134,7 @@ _arguments "${_arguments_options[@]}" \ && ret=0 ;; (help) -_arguments "${_arguments_options[@]}" \ +_arguments "${_arguments_options[@]}" : \ ":: :_alacritty__help_commands" \ "*::: :->help" \ && ret=0 @@ -146,7 +146,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 +158,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 +170,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 +195,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 +209,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 c1546f50..2c10d47c 100644 --- a/extra/completions/alacritty.bash +++ b/extra/completions/alacritty.bash @@ -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 72609f70..b7fa8ce6 100644 --- a/extra/completions/alacritty.fish +++ b/extra/completions/alacritty.fish @@ -1,47 +1,73 @@ -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 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 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' From c3075f189c2d8148c70a82f176565ea8e420b49f Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 18 Jul 2024 21:52:18 +0300 Subject: [PATCH 057/102] Document options which are not working everywhere yet This includes `window.position` and `window.resize_increments`. --- extra/man/alacritty.5.scd | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index 15bc2127..718abfa3 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -104,7 +104,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 +197,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_. From 6bd1674bd80e73df0d41e4342ad4e34bb7d04f84 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sun, 21 Jul 2024 10:49:47 +0200 Subject: [PATCH 058/102] 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. --- CHANGELOG.md | 1 + alacritty/src/config/monitor.rs | 37 ++++++++++++++++++++++++++++++++- alacritty/src/event.rs | 29 ++++++++++++++++++++++++-- alacritty/src/main.rs | 14 ++----------- 4 files changed, 66 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 203624fe..20df64f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -36,6 +36,7 @@ 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 ## 0.13.2 diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs index 53cff1c9..3f73f120 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/event.rs b/alacritty/src/event.rs index 8da758df..72009d88 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1,5 +1,6 @@ //! Process window events. +use crate::ConfigMonitor; use std::borrow::Cow; use std::cmp::min; use std::collections::{HashMap, HashSet, VecDeque}; @@ -70,6 +71,8 @@ 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, @@ -101,6 +104,16 @@ 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, @@ -113,6 +126,7 @@ impl Processor { windows: Default::default(), #[cfg(unix)] global_ipc_options: Default::default(), + config_monitor, } } @@ -160,8 +174,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 { @@ -297,6 +311,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()); } diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 6219dd78..da50c3e4 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -172,16 +172,6 @@ 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 { @@ -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(); } From d021a7b6f871f4078073848cf8744881561eb254 Mon Sep 17 00:00:00 2001 From: Hamir Mahal Date: Tue, 23 Jul 2024 18:37:35 -0700 Subject: [PATCH 059/102] Unify string formatting --- alacritty/src/cli.rs | 2 +- alacritty/src/config/bindings.rs | 11 ++++------- alacritty/src/config/mod.rs | 10 +++++----- alacritty/src/daemon.rs | 2 +- alacritty/src/display/mod.rs | 2 +- alacritty/src/display/window.rs | 2 +- alacritty/src/input/keyboard.rs | 2 +- alacritty/src/input/mod.rs | 2 +- alacritty/src/ipc.rs | 2 +- alacritty/src/logging.rs | 4 ++-- alacritty/src/renderer/mod.rs | 8 ++++---- alacritty/src/renderer/shader.rs | 6 +++--- alacritty_config_derive/src/serde_replace.rs | 4 ++-- 13 files changed, 27 insertions(+), 30 deletions(-) diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index 803c1f8c..f0c9be7e 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -524,7 +524,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 62ca03a0..dfe31853 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/mod.rs b/alacritty/src/config/mod.rs index 488ef537..f8fccb13 100644 --- a/alacritty/src/config/mod.rs +++ b/alacritty/src/config/mod.rs @@ -76,12 +76,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}"), } } } diff --git a/alacritty/src/daemon.rs b/alacritty/src/daemon.rs index df66646a..c8fb88d1 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/mod.rs b/alacritty/src/display/mod.rs index 1841b167..7809c824 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -1241,7 +1241,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:) -> 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), } } diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index d63da9f2..4bc3ffee 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -294,7 +294,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 9f7074f4..c10777f2 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -809,7 +809,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()); } } diff --git a/alacritty/src/ipc.rs b/alacritty/src/ipc.rs index 1cb7a1c8..d06d395e 100644 --- a/alacritty/src/ipc.rs +++ b/alacritty/src/ipc.rs @@ -111,7 +111,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 59303649..08e79469 100644 --- a/alacritty/src/logging.rs +++ b/alacritty/src/logging.rs @@ -108,7 +108,7 @@ 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); @@ -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/renderer/mod.rs b/alacritty/src/renderer/mod.rs index f4f1397f..16885b31 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -66,10 +66,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}") }, } } @@ -111,9 +111,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 e3baab9e..86938e45 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_config_derive/src/serde_replace.rs b/alacritty_config_derive/src/serde_replace.rs index ddd0cf75..cd56b3bc 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 Date: Sun, 11 Aug 2024 17:56:52 +0300 Subject: [PATCH 060/102] 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. --- extra/man/alacritty-bindings.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extra/man/alacritty-bindings.5.scd b/extra/man/alacritty-bindings.5.scd index 3de2986e..7f0bdf34 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 From 91d034ff8b53867143c005acfaa14609147c9a2c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=BC=A0=E5=B0=8F=E7=99=BD?= <364772080@qq.com> Date: Sat, 17 Aug 2024 01:37:34 +0800 Subject: [PATCH 061/102] Make `ConPty` creation fallible --- alacritty_terminal/src/tty/windows/conpty.rs | 25 ++++++++------------ alacritty_terminal/src/tty/windows/mod.rs | 3 +-- 2 files changed, 11 insertions(+), 17 deletions(-) diff --git a/alacritty_terminal/src/tty/windows/conpty.rs b/alacritty_terminal/src/tty/windows/conpty.rs index 244681e7..28289f90 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 6af162c8..32e24677 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 { From 5abb4b73937b17fe501b9ca20b602950f1218b96 Mon Sep 17 00:00:00 2001 From: philomathic_life <15947783+zacknewman@users.noreply.github.com> Date: Sun, 18 Aug 2024 02:10:55 +0000 Subject: [PATCH 062/102] Remove duplicate clip-path from logo --- extra/logo/alacritty-term.svg | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/extra/logo/alacritty-term.svg b/extra/logo/alacritty-term.svg index 065df538..9798a3df 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" /> From b125b99dd3886a3517f8ecf91dc6cae1ca5378fb Mon Sep 17 00:00:00 2001 From: Hamir Mahal Date: Sat, 31 Aug 2024 01:35:48 -0700 Subject: [PATCH 063/102] Update checkout CI action --- .github/workflows/ci.yml | 4 ++-- .github/workflows/release.yml | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2fe8dd2c..c65e7f82 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 e161816c..81d46970 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: runs-on: macos-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Install dependencies run: brew install scdoc - name: Install ARM target @@ -37,7 +37,7 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Test run: cargo test --release - name: Build @@ -63,7 +63,7 @@ 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 \ From 68f04024a3cbd5bdff68974eb54d1f999a292676 Mon Sep 17 00:00:00 2001 From: Dimitri Sabadie Date: Sat, 7 Sep 2024 02:25:56 +0200 Subject: [PATCH 064/102] Improve TermMode bitflags initialization --- alacritty_terminal/src/term/mod.rs | 48 +++++++++++++++--------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 5dfd880c..8a0410dc 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -54,30 +54,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() From 8dfd2e56ad7aaeaf09aaf9f680420cc5988155b0 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 10 Sep 2024 17:13:37 +0300 Subject: [PATCH 065/102] Make alacritty(1) config paths resemble alacritty(5) This also fixes the escaping in alacritty(5) page. --- extra/man/alacritty.1.scd | 8 ++++++-- extra/man/alacritty.5.scd | 10 +++++----- 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/extra/man/alacritty.1.scd b/extra/man/alacritty.1.scd index b82ba08e..c8a67bb8 100644 --- a/extra/man/alacritty.1.scd +++ b/extra/man/alacritty.1.scd @@ -61,13 +61,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 718abfa3..f1efc781 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -14,14 +14,14 @@ 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 From c74b5fa857a133298f0207c499c47cb95b27c78c Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sun, 22 Sep 2024 16:34:14 +0200 Subject: [PATCH 066/102] 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. --- CHANGELOG.md | 1 + alacritty/src/event.rs | 10 +++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20df64f0..38584ca5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,6 +37,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 ## 0.13.2 diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 72009d88..f10346af 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -34,6 +34,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}; @@ -1737,9 +1738,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) => { From 4a7728bf7fac06a35f27f6c4f31e0d9214e5152b Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sun, 22 Sep 2024 16:58:16 +0200 Subject: [PATCH 067/102] 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. --- CHANGELOG.md | 1 + alacritty_terminal/src/term/search.rs | 29 ++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38584ca5..946f48ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 ## 0.13.2 diff --git a/alacritty_terminal/src/term/search.rs b/alacritty_terminal/src/term/search.rs index a5ae9337..33f6ee05 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))); + } } From c899208e15c8987480912794d66358ea2581fc39 Mon Sep 17 00:00:00 2001 From: Neil Stewart <40719351+madcdevelop@users.noreply.github.com> Date: Mon, 30 Sep 2024 12:07:12 -0700 Subject: [PATCH 068/102] Fix app icon in alt+tab view on Windows --- CHANGELOG.md | 1 + alacritty/src/display/window.rs | 5 +++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 946f48ea..4d64bdf6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 ## 0.13.2 diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 2bb59b2c..1427dc75 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, @@ -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")] From 51089cfeed1adfd741d8dcbe6c9cb9376f88a576 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sun, 22 Sep 2024 00:10:48 +0200 Subject: [PATCH 069/102] 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. --- CHANGELOG.md | 3 + alacritty/src/cli.rs | 4 +- alacritty/src/config/general.rs | 39 +++++++++ alacritty/src/config/mod.rs | 7 +- alacritty/src/config/terminal.rs | 6 +- alacritty/src/config/ui_config.rs | 129 +++++++++--------------------- alacritty/src/display/content.rs | 4 +- alacritty/src/event.rs | 2 +- alacritty/src/main.rs | 2 +- alacritty/src/migrate.rs | 7 ++ alacritty_terminal/src/tty/mod.rs | 7 +- extra/man/alacritty.5.scd | 30 +++---- 12 files changed, 120 insertions(+), 120 deletions(-) create mode 100644 alacritty/src/config/general.rs diff --git a/CHANGELOG.md b/CHANGELOG.md index 4d64bdf6..4b767eef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,9 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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` ### Fixed diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index f0c9be7e..2b4afa02 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -88,8 +88,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)); diff --git a/alacritty/src/config/general.rs b/alacritty/src/config/general.rs new file mode 100644 index 00000000..ba559262 --- /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 f8fccb13..9ee5215c 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; @@ -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()), diff --git a/alacritty/src/config/terminal.rs b/alacritty/src/config/terminal.rs index b41af5db..d0c0d9da 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 a40dcaf8..a6155b8a 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) } } diff --git a/alacritty/src/display/content.rs b/alacritty/src/display/content.rs index 30439fc0..0e06b3ca 100644 --- a/alacritty/src/display/content.rs +++ b/alacritty/src/display/content.rs @@ -328,7 +328,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 @@ -348,7 +348,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, ) { diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index f10346af..b4600ae3 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -110,7 +110,7 @@ impl Processor { // 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 { + if config.live_config_reload() { config_monitor = ConfigMonitor::new(config.config_paths.clone(), event_loop.create_proxy()); } diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index da50c3e4..6bbf8dfd 100644 --- a/alacritty/src/main.rs +++ b/alacritty/src/main.rs @@ -174,7 +174,7 @@ fn alacritty(mut options: Options) -> Result<(), Box> { // 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 diff --git a/alacritty/src/migrate.rs b/alacritty/src/migrate.rs index 6d116858..39779ba2 100644 --- a/alacritty/src/migrate.rs +++ b/alacritty/src/migrate.rs @@ -172,6 +172,13 @@ fn migrate_renames(config: &mut Value) -> Result<(), String> { // mouse_bindings -> mouse.bindings move_value(config_table, &["mouse_bindings"], &["mouse", "bindings"])?; + // Avoid warnings due to introduction of the new `general` section. + move_value(config_table, &["live_config_reload"], &["general", "live_config_reload"])?; + move_value(config_table, &["working_directory"], &["general", "working_directory"])?; + move_value(config_table, &["ipc_socket"], &["general", "ipc_socket"])?; + move_value(config_table, &["import"], &["general", "import"])?; + move_value(config_table, &["shell"], &["terminal", "shell"])?; + Ok(()) } diff --git a/alacritty_terminal/src/tty/mod.rs b/alacritty_terminal/src/tty/mod.rs index 55d263ca..2bcc5da9 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; diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index f1efc781..1c0aa1d1 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -25,7 +25,7 @@ On Windows, the config file will be looked for in: # 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 @@ -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_ From 3db09595f31bd9f2f211d43d96f0acb887a68991 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Mon, 23 Sep 2024 02:15:52 +0200 Subject: [PATCH 070/102] 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. --- CHANGELOG.md | 1 + Cargo.lock | 48 ++- alacritty/Cargo.toml | 4 +- alacritty/src/config/mod.rs | 33 +- alacritty/src/migrate.rs | 274 --------------- alacritty/src/migrate/mod.rs | 318 ++++++++++++++++++ alacritty/src/migrate/yaml.rs | 87 +++++ .../src/config_deserialize/de_struct.rs | 1 + alacritty_config_derive/tests/config.rs | 19 +- 9 files changed, 476 insertions(+), 309 deletions(-) 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/CHANGELOG.md b/CHANGELOG.md index 4b767eef..dc858911 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its ### Added - Support relative path imports from config files +- `alacritty migrate` support for TOML configuration changes ### Changed diff --git a/Cargo.lock b/Cargo.lock index 566dbc08..39a672fd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -58,7 +58,9 @@ dependencies = [ "serde", "serde_json", "serde_yaml", + "tempfile", "toml", + "toml_edit 0.22.21", "unicode-width", "windows-sys 0.52.0", "winit", @@ -891,9 +893,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -1749,9 +1751,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -1877,6 +1879,19 @@ dependencies = [ "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.62" @@ -1931,14 +1946,14 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.15", + "toml_edit 0.22.21", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -1956,15 +1971,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.15" +version = "0.22.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59a3a72298453f564e2b111fa896f8d07fabb36f51f06d7e875fc5e0b5a3ef1" +checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.13", + "winnow 0.6.18", ] [[package]] @@ -2332,6 +2347,15 @@ dependencies = [ "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]] name = "windows-targets" version = "0.42.2" @@ -2574,9 +2598,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index e8739049..ab44b046 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -34,10 +34,12 @@ libc = "0.2" log = { version = "0.4", features = ["std", "serde"] } 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" +tempfile = "3.12.0" toml = "0.8.2" +toml_edit = "0.22.21" unicode-width = "0.1" winit = { version = "0.30.4", default-features = false, features = ["rwh_06", "serde"] } diff --git a/alacritty/src/config/mod.rs b/alacritty/src/config/mod.rs index 9ee5215c..ba9d674d 100644 --- a/alacritty/src/config/mod.rs +++ b/alacritty/src/config/mod.rs @@ -301,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())); @@ -309,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/migrate.rs b/alacritty/src/migrate.rs deleted file mode 100644 index 39779ba2..00000000 --- a/alacritty/src/migrate.rs +++ /dev/null @@ -1,274 +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"])?; - - // Avoid warnings due to introduction of the new `general` section. - move_value(config_table, &["live_config_reload"], &["general", "live_config_reload"])?; - move_value(config_table, &["working_directory"], &["general", "working_directory"])?; - move_value(config_table, &["ipc_socket"], &["general", "ipc_socket"])?; - move_value(config_table, &["import"], &["general", "import"])?; - move_value(config_table, &["shell"], &["terminal", "shell"])?; - - 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 00000000..ffd0d4b4 --- /dev/null +++ b/alacritty/src/migrate/mod.rs @@ -0,0 +1,318 @@ +//! 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["general"].get("import").and_then(|i| i.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(()), + }; + + dbg!(&key); + 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); + } +} diff --git a/alacritty/src/migrate/yaml.rs b/alacritty/src/migrate/yaml.rs new file mode 100644 index 00000000..9607e95e --- /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_config_derive/src/config_deserialize/de_struct.rs b/alacritty_config_derive/src/config_deserialize/de_struct.rs index d2a7dd82..ad38863e 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/tests/config.rs b/alacritty_config_derive/tests/config.rs index 27a968ed..be140cbe 100644 --- a/alacritty_config_derive/tests/config.rs +++ b/alacritty_config_derive/tests/config.rs @@ -1,4 +1,4 @@ -use std::sync::{Arc, Mutex}; +use std::sync::{Arc, Mutex, OnceLock}; use log::{Level, Log, Metadata, Record}; use serde::Deserialize; @@ -83,10 +83,8 @@ struct NewType(usize); #[test] fn config_deserialize() { - let logger = unsafe { - LOGGER = Some(Logger::default()); - LOGGER.as_mut().unwrap() - }; + static LOGGER: OnceLock = 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 { From 58383f4e46e22c90e7ed85db535d9640b464176b Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Wed, 2 Oct 2024 23:58:14 +0300 Subject: [PATCH 071/102] Restructure message bar log message The first line is not really useful for the user, so move it to the bottom. --- alacritty/src/logging.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/alacritty/src/logging.rs b/alacritty/src/logging.rs index 08e79469..67cad63e 100644 --- a/alacritty/src/logging.rs +++ b/alacritty/src/logging.rs @@ -113,11 +113,11 @@ impl Logger { 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); From 6067787763e663bd308e5b724a5efafc2c54a3d1 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 3 Oct 2024 01:10:42 +0300 Subject: [PATCH 072/102] 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. --- CHANGELOG.md | 1 + alacritty_terminal/src/tty/mod.rs | 4 ---- alacritty_terminal/src/tty/unix.rs | 4 ++++ 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dc858911..659a098e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -44,6 +44,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 ## 0.13.2 diff --git a/alacritty_terminal/src/tty/mod.rs b/alacritty_terminal/src/tty/mod.rs index 2bcc5da9..eed2a76d 100644 --- a/alacritty_terminal/src/tty/mod.rs +++ b/alacritty_terminal/src/tty/mod.rs @@ -98,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 8084a753..6565f20b 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. From 709738f7b50e06166b15be9f28e33a54b159150b Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sat, 5 Oct 2024 10:02:51 +0200 Subject: [PATCH 073/102] Remove unused `Clone` requirements --- 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 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/alacritty_terminal/src/grid/mod.rs b/alacritty_terminal/src/grid/mod.rs index 59769883..278bea3b 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 92ee55d7..751abae1 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 4e22e50b..d4a6e6d3 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 0a2be43b..abf57103 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(); From a1ed79bd2c014be49a85e2100ce374b86c8839e8 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sat, 5 Oct 2024 11:39:06 +0200 Subject: [PATCH 074/102] 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. --- CHANGELOG.md | 1 + alacritty/src/display/damage.rs | 9 ++ alacritty/src/display/mod.rs | 177 +++++++++++++++------------- alacritty_terminal/src/term/cell.rs | 2 - 4 files changed, 107 insertions(+), 82 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 659a098e..2026893c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -45,6 +45,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 ## 0.13.2 diff --git a/alacritty/src/display/damage.rs b/alacritty/src/display/damage.rs index 450643b7..8efe0133 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/mod.rs b/alacritty/src/display/mod.rs index 7809c824..51553288 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}; @@ -746,39 +745,37 @@ 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(); // 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(); - - if requires_full_damage { - self.damage_tracker.frame().mark_fully_damaged(); - self.damage_tracker.next_frame().mark_fully_damaged(); - } + // Invalidate highlighted hints if grid has changed. + self.validate_hints(display_offset); - 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(); @@ -802,36 +799,27 @@ 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 cells = grid_cells.into_iter().map(|mut cell| { + // Underline hints hovered by mouse or vi mode cursor. + if has_highlighted_hint { let point = term::viewport_to_point(display_offset, cell.point); - - 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)) - { - 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); - } + 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) { + damage_tracker.frame().damage_point(cell.point); + cell.flags.insert(Flags::UNDERLINE); } + } - // Update underline/strikeout. - lines.update(&cell); + // Update underline/strikeout. + lines.update(&cell); - cell - }), - ); + cell + }); + self.renderer.draw_cells(&size_info, glyph_cache, cells); } let mut rects = lines.rects(&metrics, &size_info); @@ -1025,10 +1013,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; } @@ -1052,9 +1047,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 } @@ -1113,7 +1114,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); @@ -1224,13 +1225,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); } @@ -1270,12 +1269,10 @@ impl Display { let fg = config.colors.primary.background; let bg = config.colors.normal.red; - if self.collect_damage() { - let damage = LineDamageBounds::new(point.line, point.column.0, timing.len()); - self.damage_tracker.frame().damage_line(damage); - // Damage the render timer for the next frame. - self.damage_tracker.next_frame().damage_line(damage); - } + // Damage render timer for current and next frame. + let damage = LineDamageBounds::new(point.line, point.column.0, timing.len()); + self.damage_tracker.frame().damage_line(damage); + self.damage_tracker.next_frame().damage_line(damage); let glyph_cache = &mut self.glyph_cache; self.renderer.draw_string(point, fg, bg, timing.chars(), &self.size_info, glyph_cache); @@ -1295,12 +1292,10 @@ impl Display { let column = Column(self.size_info.columns().saturating_sub(text.len())); let point = Point::new(0, column); - if self.collect_damage() { - let damage = LineDamageBounds::new(point.line, point.column.0, columns - 1); - self.damage_tracker.frame().damage_line(damage); - // Damage it on the next frame in case it goes away. - self.damage_tracker.next_frame().damage_line(damage); - } + // Damage the line indicator for current and next frame. + let damage = LineDamageBounds::new(point.line, point.column.0, columns - 1); + self.damage_tracker.frame().damage_line(damage); + self.damage_tracker.next_frame().damage_line(damage); let colors = &config.colors; let fg = colors.line_indicator.foreground.unwrap_or(colors.primary.background); @@ -1313,12 +1308,6 @@ impl Display { } } - /// Returns `true` if damage information should be collected, `false` otherwise. - #[inline] - fn collect_damage(&self) -> bool { - matches!(self.raw_window_handle, RawWindowHandle::Wayland(_)) || self.damage_tracker.debug - } - /// Highlight damaged rects. /// /// This function is for debug purposes only. @@ -1334,6 +1323,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. diff --git a/alacritty_terminal/src/term/cell.rs b/alacritty_terminal/src/term/cell.rs index 81dc1e3a..73077644 100644 --- a/alacritty_terminal/src/term/cell.rs +++ b/alacritty_terminal/src/term/cell.rs @@ -124,9 +124,7 @@ impl ResetDiscriminant for Cell { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct CellExtra { zerowidth: Vec, - underline_color: Option, - hyperlink: Option, } From c032c89f1c457c3cf97dcda3f8367115fa5f66ea Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 10 Oct 2024 21:01:44 +0300 Subject: [PATCH 075/102] 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. --- CHANGELOG.md | 1 + alacritty/src/config/ui_config.rs | 2 +- extra/man/alacritty.5.scd | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2026893c..ae486fa5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 ### Fixed diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index a6155b8a..69716dee 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -282,7 +282,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/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index 1c0aa1d1..8e92734a 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -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 From 5dca7a85e7d8e98f8e770c17af8efb442c2277d0 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Thu, 10 Oct 2024 22:56:55 +0000 Subject: [PATCH 076/102] 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. --- CHANGELOG.md | 1 + Cargo.lock | 10 +++++----- alacritty/Cargo.toml | 2 +- alacritty_terminal/Cargo.toml | 2 +- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae486fa5..ca900247 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Support relative path imports from config files - `alacritty migrate` support for TOML configuration changes +- Support for Unicode 16 characters ### Changed diff --git a/Cargo.lock b/Cargo.lock index 39a672fd..cb1a64f2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,7 +61,7 @@ dependencies = [ "tempfile", "toml", "toml_edit 0.22.21", - "unicode-width", + "unicode-width-16", "windows-sys 0.52.0", "winit", "xdg", @@ -108,7 +108,7 @@ dependencies = [ "serde", "serde_json", "signal-hook", - "unicode-width", + "unicode-width-16", "vte", "windows-sys 0.52.0", ] @@ -2011,10 +2011,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] -name = "unicode-width" -version = "0.1.13" +name = "unicode-width-16" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "9eba15036aa0f5bf8ed6cd12a624ddb61fd50b0779b1c05d89b663bcaed7b5c2" [[package]] name = "unsafe-libyaml" diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index ab44b046..81c186c9 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -40,7 +40,7 @@ serde_yaml = "0.9.25" tempfile = "3.12.0" toml = "0.8.2" toml_edit = "0.22.21" -unicode-width = "0.1" +unicode-width = { package = "unicode-width-16", version = "0.1.0" } winit = { version = "0.30.4", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index e643e081..6ac1ebb3 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4" parking_lot = "0.12.0" polling = "3.0.0" regex-automata = "0.4.3" -unicode-width = "0.1" +unicode-width = { package = "unicode-width-16", version = "0.1.0" } vte = { version = "0.13.0", default-features = false, features = ["ansi", "serde"] } serde = { version = "1", features = ["derive", "rc"], optional = true } From a2653293a8e6ac5f5fb9f7e075656799d8df3488 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Fri, 11 Oct 2024 02:23:43 +0300 Subject: [PATCH 077/102] Fix panic on missing general config section Fixes #8230. --- alacritty/src/migrate/mod.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/alacritty/src/migrate/mod.rs b/alacritty/src/migrate/mod.rs index ffd0d4b4..58f381de 100644 --- a/alacritty/src/migrate/mod.rs +++ b/alacritty/src/migrate/mod.rs @@ -134,7 +134,11 @@ fn migrate_imports( recursion_limit: usize, ) -> Result<(), String> { // Check if any imports need to be processed. - let imports = match document["general"].get("import").and_then(|i| i.as_array()) { + 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(()), }; @@ -315,4 +319,9 @@ root_value = 3 assert_eq!(output, expected); } + + #[test] + fn migrate_empty() { + assert!(migrate_toml(String::new()).unwrap().to_string().is_empty()); + } } From a5bb567c0a15bed65ff18c94d04c8c147bf817a9 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Tue, 15 Oct 2024 11:41:08 +0300 Subject: [PATCH 078/102] 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. --- CHANGELOG.md | 2 ++ alacritty/src/display/content.rs | 27 ++++++++++++++------ alacritty/src/display/cursor.rs | 4 +-- alacritty/src/display/mod.rs | 44 ++++++++++++++++++-------------- alacritty/src/event.rs | 7 ++--- 5 files changed, 49 insertions(+), 35 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ca900247..e9d8d3ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its 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 @@ -48,6 +49,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 ## 0.13.2 diff --git a/alacritty/src/display/content.rs b/alacritty/src/display/content.rs index 0e06b3ca..2fbbdec4 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}; @@ -134,8 +135,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, @@ -396,7 +402,7 @@ pub struct RenderableCursor { shape: CursorShape, cursor_color: Rgb, text_color: Rgb, - is_wide: bool, + width: NonZeroU32, point: Point, } @@ -405,15 +411,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 { @@ -424,8 +435,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 65933ccc..b0e2d6c3 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/mod.rs b/alacritty/src/display/mod.rs index 51553288..a8501da6 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -874,7 +874,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())); } @@ -1081,8 +1083,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), @@ -1125,19 +1127,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 }, @@ -1436,20 +1440,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/event.rs b/alacritty/src/event.rs index b4600ae3..46e9433c 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1843,11 +1843,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); From 6ba69f8dd469e1a9aff0b48b3ae10ce4510ca1e3 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Tue, 15 Oct 2024 14:06:59 +0000 Subject: [PATCH 079/102] 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. --- CHANGELOG.md | 1 + alacritty/src/display/mod.rs | 7 +++++-- alacritty/src/event.rs | 19 +++++++++++++++++++ alacritty/src/input/keyboard.rs | 15 +++++---------- alacritty/src/input/mod.rs | 1 + 5 files changed, 31 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9d8d3ff..7dff2d54 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -50,6 +50,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index a8501da6..d0044f8b 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -884,8 +884,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, + } }, }; diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 46e9433c..23575e21 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1218,6 +1218,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(); @@ -1291,6 +1293,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. @@ -1305,6 +1308,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() } diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index 4bc3ffee..14755594 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; } diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index c10777f2..bbd8673f 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) {} From 2a2db5b6fd23adea88906b8c2ee81512cd44cd53 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Tue, 15 Oct 2024 18:32:50 +0000 Subject: [PATCH 080/102] 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. --- CHANGELOG.md | 1 + alacritty/src/cli.rs | 6 +++- alacritty/src/event.rs | 50 ++++++++++++++++++++------------ alacritty/src/ipc.rs | 9 ++++-- alacritty/src/window_context.rs | 17 ++++------- extra/completions/_alacritty | 3 +- extra/completions/alacritty.bash | 2 +- extra/completions/alacritty.fish | 3 +- extra/man/alacritty.1.scd | 4 +++ 9 files changed, 58 insertions(+), 37 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7dff2d54..8d9d463a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Support relative path imports from config files - `alacritty migrate` support for TOML configuration changes - Support for Unicode 16 characters +- Headless mode using `alacritty --daemon` ### Changed diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index 2b4afa02..bb0a24f4 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, diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index 23575e21..f0159060 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1,6 +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}; @@ -16,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::{ @@ -80,7 +82,7 @@ pub struct Processor { initial_window_error: Option>, windows: HashMap, proxy: EventLoopProxy, - gl_display: Option, + gl_config: Option, #[cfg(unix)] global_ipc_options: ParsedOptions, cli_options: CliOptions, @@ -121,7 +123,7 @@ impl Processor { cli_options, proxy, scheduler, - gl_display: None, + gl_config: None, config: Rc::new(config), clipboard, windows: Default::default(), @@ -138,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(()) @@ -155,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(); @@ -164,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(()) @@ -210,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; @@ -338,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); } }, @@ -375,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(); @@ -439,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 diff --git a/alacritty/src/ipc.rs b/alacritty/src/ipc.rs index d06d395e..3d14c4ce 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(); diff --git a/alacritty/src/window_context.rs b/alacritty/src/window_context.rs index 062f9ef0..cfc3cd96 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/extra/completions/_alacritty b/extra/completions/_alacritty index a9260d5c..0ccce66f 100644 --- a/extra/completions/_alacritty +++ b/extra/completions/_alacritty @@ -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]' \ diff --git a/extra/completions/alacritty.bash b/extra/completions/alacritty.bash index 2c10d47c..e2213b75 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 diff --git a/extra/completions/alacritty.fish b/extra/completions/alacritty.fish index b7fa8ce6..7cfc3337 100644 --- a/extra/completions/alacritty.fish +++ b/extra/completions/alacritty.fish @@ -1,6 +1,6 @@ # 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 working-directory= hold e/command= T/title= class= o/option= h/help V/version + 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 @@ -36,6 +36,7 @@ complete -c alacritty -n "__fish_alacritty_needs_command" -l print-events -d 'Pr 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' diff --git a/extra/man/alacritty.1.scd b/extra/man/alacritty.1.scd index c8a67bb8..86630a65 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. From 1cc08ebbf81de5ab65e7ede6a4df9a1d80861acf Mon Sep 17 00:00:00 2001 From: Nathan Lilienthal Date: Tue, 15 Oct 2024 15:21:09 -0400 Subject: [PATCH 081/102] Remove dbg! in migration command --- alacritty/src/migrate/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/alacritty/src/migrate/mod.rs b/alacritty/src/migrate/mod.rs index 58f381de..2f806d36 100644 --- a/alacritty/src/migrate/mod.rs +++ b/alacritty/src/migrate/mod.rs @@ -175,7 +175,6 @@ fn move_value(document: &mut DocumentMut, origin: &[&str], target: &[&str]) -> R None => return Ok(()), }; - dbg!(&key); origin_key = Some(key); origin_item = item; From 674635c27c2a4a906a5e95d522ee8f767e36cbd2 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 17 Oct 2024 18:10:31 +0300 Subject: [PATCH 082/102] Fix pipe FD leak on X11 The pipe was not using O_CLOEXEC, so it was leaked into the child. Fixes #8249. --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cb1a64f2..55a50f33 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2626,9 +2626,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", From f90d2964a6eda906d61b76f5e0ec7b9e44c12cb1 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Fri, 18 Oct 2024 13:47:26 +0000 Subject: [PATCH 083/102] Revert "Add unicode 16 support" This reverts commit 5dca7a85e7d8e98f8e770c17af8efb442c2277d0. --- CHANGELOG.md | 1 - Cargo.lock | 10 +++++----- alacritty/Cargo.toml | 2 +- alacritty_terminal/Cargo.toml | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8d9d463a..03e6bd52 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,6 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Support relative path imports from config files - `alacritty migrate` support for TOML configuration changes -- Support for Unicode 16 characters - Headless mode using `alacritty --daemon` ### Changed diff --git a/Cargo.lock b/Cargo.lock index 55a50f33..8c77205f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,7 +61,7 @@ dependencies = [ "tempfile", "toml", "toml_edit 0.22.21", - "unicode-width-16", + "unicode-width", "windows-sys 0.52.0", "winit", "xdg", @@ -108,7 +108,7 @@ dependencies = [ "serde", "serde_json", "signal-hook", - "unicode-width-16", + "unicode-width", "vte", "windows-sys 0.52.0", ] @@ -2011,10 +2011,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" [[package]] -name = "unicode-width-16" -version = "0.1.0" +name = "unicode-width" +version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9eba15036aa0f5bf8ed6cd12a624ddb61fd50b0779b1c05d89b663bcaed7b5c2" +checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" [[package]] name = "unsafe-libyaml" diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 81c186c9..ab44b046 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -40,7 +40,7 @@ serde_yaml = "0.9.25" tempfile = "3.12.0" toml = "0.8.2" toml_edit = "0.22.21" -unicode-width = { package = "unicode-width-16", version = "0.1.0" } +unicode-width = "0.1" winit = { version = "0.30.4", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index 6ac1ebb3..e643e081 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -23,7 +23,7 @@ log = "0.4" parking_lot = "0.12.0" polling = "3.0.0" regex-automata = "0.4.3" -unicode-width = { package = "unicode-width-16", version = "0.1.0" } +unicode-width = "0.1" vte = { version = "0.13.0", default-features = false, features = ["ansi", "serde"] } serde = { version = "1", features = ["derive", "rc"], optional = true } From 6dbd785bc0063109fcf8105bdf7e4d5673892abf Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Fri, 18 Oct 2024 22:25:57 +0000 Subject: [PATCH 084/102] Bump development version to 0.15.0-dev This is only an update to the development version and does not represent a stable release. --- CHANGELOG.md | 4 +++- Cargo.lock | 8 ++++---- alacritty/Cargo.toml | 8 ++++---- alacritty/windows/wix/alacritty.wxs | 2 +- alacritty_config/Cargo.toml | 4 ++-- alacritty_config_derive/Cargo.toml | 4 ++-- alacritty_terminal/CHANGELOG.md | 16 +++++++++++++++- alacritty_terminal/Cargo.toml | 2 +- extra/osx/Alacritty.app/Contents/Info.plist | 2 +- 9 files changed, 33 insertions(+), 17 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03e6bd52..75f164d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,9 @@ 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.15.0-dev + +## 0.14.0 ### Packaging diff --git a/Cargo.lock b/Cargo.lock index 8c77205f..64db3952 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -32,7 +32,7 @@ dependencies = [ [[package]] name = "alacritty" -version = "0.14.0-dev" +version = "0.15.0-dev" dependencies = [ "ahash", "alacritty_config", @@ -69,7 +69,7 @@ dependencies = [ [[package]] name = "alacritty_config" -version = "0.2.1-dev" +version = "0.2.3-dev" dependencies = [ "alacritty_config_derive", "log", @@ -79,7 +79,7 @@ dependencies = [ [[package]] name = "alacritty_config_derive" -version = "0.2.3-dev" +version = "0.2.5-dev" dependencies = [ "alacritty_config", "log", @@ -92,7 +92,7 @@ dependencies = [ [[package]] name = "alacritty_terminal" -version = "0.24.1-dev" +version = "0.24.2-dev" dependencies = [ "base64", "bitflags 2.6.0", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index ab44b046..09a97706 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alacritty" -version = "0.14.0-dev" +version = "0.15.0-dev" authors = ["Christian Duerr ", "Joe Wilm "] license = "Apache-2.0" description = "A fast, cross-platform, OpenGL terminal emulator" @@ -12,15 +12,15 @@ rust-version = "1.74.0" [dependencies.alacritty_terminal] path = "../alacritty_terminal" -version = "0.24.1-dev" +version = "0.24.2-dev" [dependencies.alacritty_config_derive] path = "../alacritty_config_derive" -version = "0.2.3-dev" +version = "0.2.5-dev" [dependencies.alacritty_config] path = "../alacritty_config" -version = "0.2.1-dev" +version = "0.2.3-dev" [dependencies] ahash = { version = "0.8.6", features = ["no-rng"] } diff --git a/alacritty/windows/wix/alacritty.wxs b/alacritty/windows/wix/alacritty.wxs index cd64ec7b..5c05d821 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 4ca631af..a6d651bc 100644 --- a/alacritty_config/Cargo.toml +++ b/alacritty_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alacritty_config" -version = "0.2.1-dev" +version = "0.2.3-dev" authors = ["Christian Duerr "] license = "MIT OR Apache-2.0" description = "Alacritty configuration abstractions" @@ -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.5-dev", 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 f74a7cba..7d04eacc 100644 --- a/alacritty_config_derive/Cargo.toml +++ b/alacritty_config_derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "alacritty_config_derive" -version = "0.2.3-dev" +version = "0.2.5-dev" authors = ["Christian Duerr "] license = "MIT OR Apache-2.0" description = "Failure resistant deserialization derive" @@ -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.3-dev" [dev-dependencies] log = "0.4.11" diff --git a/alacritty_terminal/CHANGELOG.md b/alacritty_terminal/CHANGELOG.md index 82636168..28ed7540 100644 --- a/alacritty_terminal/CHANGELOG.md +++ b/alacritty_terminal/CHANGELOG.md @@ -8,7 +8,21 @@ 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.2-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 e643e081..eda38968 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.2-dev" authors = ["Christian Duerr ", "Joe Wilm "] license = "Apache-2.0" description = "Library for writing terminal emulators" diff --git a/extra/osx/Alacritty.app/Contents/Info.plist b/extra/osx/Alacritty.app/Contents/Info.plist index e402e372..59c70ff2 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.15.0-dev CFBundleSupportedPlatforms MacOSX From 2112e90f0dcb77a60b3ef68f3b48e5320ad46de6 Mon Sep 17 00:00:00 2001 From: YizhePKU Date: Mon, 21 Oct 2024 22:35:17 +0800 Subject: [PATCH 085/102] Do not pull serde without serde feature alacritty_terminal was pulling `serde` via vte even though serde feature was disabled. --- alacritty_terminal/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index eda38968..6afa7fef 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -24,7 +24,7 @@ parking_lot = "0.12.0" polling = "3.0.0" regex-automata = "0.4.3" unicode-width = "0.1" -vte = { version = "0.13.0", default-features = false, features = ["ansi", "serde"] } +vte = { version = "0.13.0", default-features = false, features = ["ansi"] } serde = { version = "1", features = ["derive", "rc"], optional = true } [target.'cfg(unix)'.dependencies] From c2782ad619613d79be453abba6bd58ba98cfe239 Mon Sep 17 00:00:00 2001 From: Finn2708 <58212604+Finn2708@users.noreply.github.com> Date: Thu, 24 Oct 2024 19:53:26 +0200 Subject: [PATCH 086/102] Add g++ dependency to Debian install docs --- INSTALL.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/INSTALL.md b/INSTALL.md index b5f6871c..6974e1ee 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -84,7 +84,7 @@ to build Alacritty. Here's an apt command that should install all of them. If something is still found to be missing, please open an issue. ```sh -apt install cmake pkg-config libfreetype6-dev libfontconfig1-dev libxcb-xfixes0-dev libxkbcommon-dev python3 +apt install cmake g++ pkg-config libfreetype6-dev libfontconfig1-dev libxcb-xfixes0-dev libxkbcommon-dev python3 ``` #### Arch Linux From 0542d9f4f57a8b052234bf8b15d44aef8f90c00a Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Tue, 29 Oct 2024 04:02:42 +0000 Subject: [PATCH 087/102] Fix hint highlight invalidation This fixes a couple issues with hint highlight invalidation, which would cause hints to lose their underline highlight despite the terminal itself not having changed since the highlight started. Closes #8270. --- CHANGELOG.md | 4 ++++ alacritty/src/display/damage.rs | 6 ++++-- alacritty/src/display/mod.rs | 34 ++++++++++++++++++++++++--------- 3 files changed, 33 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 75f164d0..095d5fd7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ Notable changes to the `alacritty_terminal` crate are documented in its ## 0.15.0-dev +### Fixed + +- Mouse/Vi cursor hint highlighting broken on the terminal cursor line + ## 0.14.0 ### Packaging diff --git a/alacritty/src/display/damage.rs b/alacritty/src/display/damage.rs index 8efe0133..fc6aef39 100644 --- a/alacritty/src/display/damage.rs +++ b/alacritty/src/display/damage.rs @@ -193,9 +193,11 @@ impl FrameDamage { /// Check if a range is damaged. #[inline] pub fn intersects(&self, start: Point, end: Point) -> bool { + let start_line = &self.lines[start.line]; + let end_line = &self.lines[end.line]; self.full - || self.lines[start.line].left <= start.column - || self.lines[end.line].right >= end.column + || (start_line.left..=start_line.right).contains(&start.column) + || (end_line.left..=end_line.right).contains(&end.column) || (start.line + 1..end.line).any(|line| self.lines[line].is_damaged()) } } diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index d0044f8b..d358a7c5 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -342,9 +342,13 @@ pub struct Display { /// Hint highlighted by the mouse. pub highlighted_hint: Option, + /// Frames since hint highlight was created. + highlighted_hint_age: usize, /// Hint highlighted by the vi mode cursor. pub vi_highlighted_hint: Option, + /// Frames since hint highlight was created. + vi_highlighted_hint_age: usize, pub raw_window_handle: RawWindowHandle, @@ -516,6 +520,8 @@ impl Display { font_size, window, pending_renderer_update: Default::default(), + vi_highlighted_hint_age: Default::default(), + highlighted_hint_age: Default::default(), vi_highlighted_hint: Default::default(), highlighted_hint: Default::default(), hint_mouse_point: Default::default(), @@ -759,7 +765,7 @@ impl Display { drop(terminal); // Invalidate highlighted hints if grid has changed. - self.validate_hints(display_offset); + self.validate_hint_highlights(display_offset); // Add damage from alacritty's UI elements overlapping terminal. @@ -1017,9 +1023,10 @@ impl Display { }; let mut dirty = vi_highlighted_hint != self.vi_highlighted_hint; self.vi_highlighted_hint = vi_highlighted_hint; + self.vi_highlighted_hint_age = 0; // Force full redraw if the vi mode highlight was cleared. - if dirty && self.vi_highlighted_hint.is_none() { + if dirty { self.damage_tracker.frame().mark_fully_damaged(); } @@ -1055,9 +1062,10 @@ impl Display { let mouse_highlight_dirty = self.highlighted_hint != highlighted_hint; dirty |= mouse_highlight_dirty; self.highlighted_hint = highlighted_hint; + self.highlighted_hint_age = 0; - // Force full redraw if the mouse cursor highlight was cleared. - if mouse_highlight_dirty && self.highlighted_hint.is_none() { + // Force full redraw if the mouse cursor highlight was changed. + if mouse_highlight_dirty { self.damage_tracker.frame().mark_fully_damaged(); } @@ -1331,16 +1339,24 @@ impl Display { } /// Check whether a hint highlight needs to be cleared. - fn validate_hints(&mut self, display_offset: usize) { + fn validate_hint_highlights(&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 hints = [ + (&mut self.highlighted_hint, &mut self.highlighted_hint_age, true), + (&mut self.vi_highlighted_hint, &mut self.vi_highlighted_hint_age, false), + ]; + for (hint, hint_age, reset_mouse) in hints { let (start, end) = match hint { Some(hint) => (*hint.bounds().start(), *hint.bounds().end()), - None => return, + None => continue, }; + // Ignore hints that were created this frame. + *hint_age += 1; + if *hint_age == 1 { + continue; + } + // 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(|| { From d552c6b251d199b4913754dd25fca330f87651fd Mon Sep 17 00:00:00 2001 From: Chris Kaiser <102256828+jchriskaiser@users.noreply.github.com> Date: Thu, 31 Oct 2024 17:36:27 +0100 Subject: [PATCH 088/102] Fix shell manpage example --- extra/man/alacritty.5.scd | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index 8e92734a..fa0edaaf 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -601,9 +601,7 @@ This section documents the *[terminal]* table of the configuration file. Windows: _"powershell"_ Example: - *[shell]*++ -program = _"/bin/zsh"_++ -args = [_"-l"_] + *shell* = { program = _"/bin/zsh"_, args = [_"-l"_] } *osc52* = _"Disabled"_ | _"OnlyCopy"_ | _"OnlyPaste"_ | _"CopyPaste"_ From 39ea7271e32ad88280191d8040d6f8feafe4307a Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 2 Nov 2024 12:23:33 -0700 Subject: [PATCH 089/102] Focus new windows on macOS --- CHANGELOG.md | 4 ++++ alacritty/src/display/mod.rs | 4 ++++ alacritty/src/display/window.rs | 6 ++++++ 3 files changed, 14 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 095d5fd7..1c28ddd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ Notable changes to the `alacritty_terminal` crate are documented in its ## 0.15.0-dev +### Changed + +- Always focus new windows on macOS + ### Fixed - Mouse/Vi cursor hint highlighting broken on the terminal cursor line diff --git a/alacritty/src/display/mod.rs b/alacritty/src/display/mod.rs index d358a7c5..4211da5f 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -484,6 +484,10 @@ impl Display { window.set_visible(true); + // Always focus new windows, even if no Alacritty window is currently focused. + #[cfg(target_os = "macos")] + window.focus_window(); + #[allow(clippy::single_match)] #[cfg(not(windows))] if !_tabbed { diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 1427dc75..5f0790b6 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -224,6 +224,12 @@ impl Window { self.window.set_visible(visibility); } + #[cfg(target_os = "macos")] + #[inline] + pub fn focus_window(&self) { + self.window.focus_window(); + } + /// Set the window title. #[inline] pub fn set_title(&mut self, title: String) { From fd745a9f4cb3ba81623167c9d1117747353db33a Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sat, 2 Nov 2024 20:05:51 +0000 Subject: [PATCH 090/102] Fix racing condition in hint triggering This fixes an issue with hints where it was possible that the terminal content of highlighted hints changed between the highlighted hint update and the activation of the hint. This patch always validates the hint's text content against the hint itself to ensure that the content is still valid for the original hint which triggered the highlight. Closes #8277. --- CHANGELOG.md | 1 + alacritty/src/config/bindings.rs | 11 +++--- alacritty/src/config/font.rs | 2 +- alacritty/src/config/ui_config.rs | 8 ++--- alacritty/src/display/color.rs | 6 ++-- alacritty/src/display/content.rs | 6 ++-- alacritty/src/display/damage.rs | 2 +- alacritty/src/display/hint.rs | 52 +++++++++++++++++++-------- alacritty/src/display/meter.rs | 2 +- alacritty/src/event.rs | 8 ++--- alacritty/src/input/mod.rs | 2 +- alacritty/src/migrate/mod.rs | 2 +- alacritty/src/renderer/text/gles2.rs | 6 ++-- alacritty/src/renderer/text/glsl3.rs | 6 ++-- alacritty/src/renderer/text/mod.rs | 2 +- alacritty/src/string.rs | 2 +- alacritty_terminal/src/grid/mod.rs | 2 +- alacritty_terminal/src/term/mod.rs | 2 +- alacritty_terminal/src/term/search.rs | 2 +- 19 files changed, 74 insertions(+), 50 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c28ddd1..bbe0d2f4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its ### Fixed - Mouse/Vi cursor hint highlighting broken on the terminal cursor line +- Hint launcher opening arbitrary text, when terminal content changed while opening ## 0.14.0 diff --git a/alacritty/src/config/bindings.rs b/alacritty/src/config/bindings.rs index dfe31853..931b0583 100644 --- a/alacritty/src/config/bindings.rs +++ b/alacritty/src/config/bindings.rs @@ -5,6 +5,7 @@ use std::fmt::{self, Debug, Display}; use bitflags::bitflags; use serde::de::{self, Error as SerdeError, MapAccess, Unexpected, Visitor}; use serde::{Deserialize, Deserializer}; +use std::rc::Rc; use toml::Value as SerdeValue; use winit::event::MouseButton; use winit::keyboard::{ @@ -96,7 +97,7 @@ pub enum Action { /// Regex keyboard hints. #[config(skip)] - Hint(Hint), + Hint(Rc), /// Move vi mode cursor. #[config(skip)] @@ -790,7 +791,7 @@ impl<'a> Deserialize<'a> for ModeWrapper { { struct ModeVisitor; - impl<'a> Visitor<'a> for ModeVisitor { + impl Visitor<'_> for ModeVisitor { type Value = ModeWrapper; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -844,7 +845,7 @@ impl<'a> Deserialize<'a> for MouseButtonWrapper { { struct MouseButtonVisitor; - impl<'a> Visitor<'a> for MouseButtonVisitor { + impl Visitor<'_> for MouseButtonVisitor { type Value = MouseButtonWrapper; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -956,7 +957,7 @@ impl<'a> Deserialize<'a> for RawBinding { { struct FieldVisitor; - impl<'a> Visitor<'a> for FieldVisitor { + impl Visitor<'_> for FieldVisitor { type Value = Field; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { @@ -1204,7 +1205,7 @@ impl<'a> de::Deserialize<'a> for ModsWrapper { { struct ModsVisitor; - impl<'a> Visitor<'a> for ModsVisitor { + impl Visitor<'_> for ModsVisitor { type Value = ModsWrapper; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/alacritty/src/config/font.rs b/alacritty/src/config/font.rs index 061c0f42..760c26d5 100644 --- a/alacritty/src/config/font.rs +++ b/alacritty/src/config/font.rs @@ -144,7 +144,7 @@ impl<'de> Deserialize<'de> for Size { D: Deserializer<'de>, { struct NumVisitor; - impl<'v> Visitor<'v> for NumVisitor { + impl Visitor<'_> for NumVisitor { type Value = Size; fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { diff --git a/alacritty/src/config/ui_config.rs b/alacritty/src/config/ui_config.rs index 69716dee..b44bda0d 100644 --- a/alacritty/src/config/ui_config.rs +++ b/alacritty/src/config/ui_config.rs @@ -253,7 +253,7 @@ pub struct Hints { alphabet: HintsAlphabet, /// All configured terminal hints. - pub enabled: Vec, + pub enabled: Vec>, } impl Default for Hints { @@ -274,7 +274,7 @@ impl Default for Hints { }); Self { - enabled: vec![Hint { + enabled: vec![Rc::new(Hint { content, action, persist: false, @@ -288,7 +288,7 @@ impl Default for Hints { mods: ModsWrapper(ModifiersState::SHIFT | ModifiersState::CONTROL), mode: Default::default(), }), - }], + })], alphabet: Default::default(), } } @@ -619,7 +619,7 @@ impl SerdeReplace for Program { } pub(crate) struct StringVisitor; -impl<'de> serde::de::Visitor<'de> for StringVisitor { +impl serde::de::Visitor<'_> for StringVisitor { type Value = String; fn expecting(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/alacritty/src/display/color.rs b/alacritty/src/display/color.rs index 669bf502..2e854a3f 100644 --- a/alacritty/src/display/color.rs +++ b/alacritty/src/display/color.rs @@ -18,7 +18,7 @@ pub const DIM_FACTOR: f32 = 0.66; #[derive(Copy, Clone)] pub struct List([Rgb; COUNT]); -impl<'a> From<&'a Colors> for List { +impl From<&'_ Colors> for List { fn from(colors: &Colors) -> List { // Type inference fails without this annotation. let mut list = List([Rgb::default(); COUNT]); @@ -235,7 +235,7 @@ impl<'de> Deserialize<'de> for Rgb { b: u8, } - impl<'a> Visitor<'a> for RgbVisitor { + impl Visitor<'_> for RgbVisitor { type Value = Rgb; fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { @@ -331,7 +331,7 @@ impl<'de> Deserialize<'de> for CellRgb { const EXPECTING: &str = "CellForeground, CellBackground, or hex color like #ff00ff"; struct CellRgbVisitor; - impl<'a> Visitor<'a> for CellRgbVisitor { + impl Visitor<'_> for CellRgbVisitor { type Value = CellRgb; fn expecting(&self, f: &mut Formatter<'_>) -> fmt::Result { diff --git a/alacritty/src/display/content.rs b/alacritty/src/display/content.rs index 2fbbdec4..edd2709f 100644 --- a/alacritty/src/display/content.rs +++ b/alacritty/src/display/content.rs @@ -150,7 +150,7 @@ impl<'a> RenderableContent<'a> { } } -impl<'a> Iterator for RenderableContent<'a> { +impl Iterator for RenderableContent<'_> { type Item = RenderableCell; /// Gets the next renderable cell. @@ -453,7 +453,7 @@ struct Hint<'a> { labels: &'a Vec>, } -impl<'a> Hint<'a> { +impl Hint<'_> { /// Advance the hint iterator. /// /// If the point is within a hint, the keyboard shortcut character that should be displayed at @@ -543,7 +543,7 @@ impl<'a> HintMatches<'a> { } } -impl<'a> Deref for HintMatches<'a> { +impl Deref for HintMatches<'_> { type Target = [Match]; fn deref(&self) -> &Self::Target { diff --git a/alacritty/src/display/damage.rs b/alacritty/src/display/damage.rs index fc6aef39..b0736375 100644 --- a/alacritty/src/display/damage.rs +++ b/alacritty/src/display/damage.rs @@ -251,7 +251,7 @@ impl<'a> RenderDamageIterator<'a> { } } -impl<'a> Iterator for RenderDamageIterator<'a> { +impl Iterator for RenderDamageIterator<'_> { type Item = Rect; fn next(&mut self) -> Option { diff --git a/alacritty/src/display/hint.rs b/alacritty/src/display/hint.rs index a01a1d03..3f10b4e5 100644 --- a/alacritty/src/display/hint.rs +++ b/alacritty/src/display/hint.rs @@ -1,6 +1,8 @@ +use std::borrow::Cow; use std::cmp::Reverse; use std::collections::HashSet; use std::iter; +use std::rc::Rc; use ahash::RandomState; use winit::keyboard::ModifiersState; @@ -23,7 +25,7 @@ const HINT_SPLIT_PERCENTAGE: f32 = 0.5; /// Keyboard regex hint state. pub struct HintState { /// Hint currently in use. - hint: Option, + hint: Option>, /// Alphabet for hint labels. alphabet: String, @@ -56,7 +58,7 @@ impl HintState { } /// Start the hint selection process. - pub fn start(&mut self, hint: Hint) { + pub fn start(&mut self, hint: Rc) { self.hint = Some(hint); } @@ -150,7 +152,7 @@ impl HintState { // Check if the selected label is fully matched. if label.len() == 1 { let bounds = self.matches[index].clone(); - let action = hint.action.clone(); + let hint = hint.clone(); // Exit hint mode unless it requires explicit dismissal. if hint.persist { @@ -161,7 +163,7 @@ impl HintState { // Hyperlinks take precedence over regex matches. let hyperlink = term.grid()[*bounds.start()].hyperlink(); - Some(HintMatch { action, bounds, hyperlink }) + Some(HintMatch { bounds, hyperlink, hint }) } else { // Store character to preserve the selection. self.keys.push(c); @@ -192,13 +194,14 @@ impl HintState { /// Hint match which was selected by the user. #[derive(PartialEq, Eq, Debug, Clone)] pub struct HintMatch { - /// Action for handling the text. - action: HintAction, - /// Terminal range matching the hint. bounds: Match, + /// OSC 8 hyperlink. hyperlink: Option, + + /// Hint which triggered this match. + hint: Rc, } impl HintMatch { @@ -210,7 +213,7 @@ impl HintMatch { #[inline] pub fn action(&self) -> &HintAction { - &self.action + &self.hint.action } #[inline] @@ -221,6 +224,29 @@ impl HintMatch { pub fn hyperlink(&self) -> Option<&Hyperlink> { self.hyperlink.as_ref() } + + /// Get the text content of the hint match. + /// + /// This will always revalidate the hint text, to account for terminal content + /// changes since the [`HintMatch`] was constructed. The text of the hint might + /// be different from its original value, but it will **always** be a valid + /// match for this hint. + pub fn text(&self, term: &Term) -> Option> { + // Revalidate hyperlink match. + if let Some(hyperlink) = &self.hyperlink { + let (validated, bounds) = hyperlink_at(term, *self.bounds.start())?; + return (&validated == hyperlink && bounds == self.bounds) + .then(|| hyperlink.uri().into()); + } + + // Revalidate regex match. + let regex = self.hint.content.regex.as_ref()?; + let bounds = regex.with_compiled(|regex| { + regex_match_at(term, *self.bounds.start(), regex, self.hint.post_processing) + })??; + (bounds == self.bounds) + .then(|| term.bounds_to_string(*bounds.start(), *bounds.end()).into()) + } } /// Generator for creating new hint labels. @@ -382,18 +408,14 @@ pub fn highlighted_at( if let Some((hyperlink, bounds)) = hint.content.hyperlinks.then(|| hyperlink_at(term, point)).flatten() { - return Some(HintMatch { - bounds, - action: hint.action.clone(), - hyperlink: Some(hyperlink), - }); + return Some(HintMatch { bounds, hyperlink: Some(hyperlink), hint: hint.clone() }); } let bounds = hint.content.regex.as_ref().and_then(|regex| { regex.with_compiled(|regex| regex_match_at(term, point, regex, hint.post_processing)) }); if let Some(bounds) = bounds.flatten() { - return Some(HintMatch { bounds, action: hint.action.clone(), hyperlink: None }); + return Some(HintMatch { bounds, hint: hint.clone(), hyperlink: None }); } None @@ -554,7 +576,7 @@ impl<'a, T> HintPostProcessor<'a, T> { } } -impl<'a, T> Iterator for HintPostProcessor<'a, T> { +impl Iterator for HintPostProcessor<'_, T> { type Item = Match; fn next(&mut self) -> Option { diff --git a/alacritty/src/display/meter.rs b/alacritty/src/display/meter.rs index e263100f..20cbbd1b 100644 --- a/alacritty/src/display/meter.rs +++ b/alacritty/src/display/meter.rs @@ -57,7 +57,7 @@ impl<'a> Sampler<'a> { } } -impl<'a> Drop for Sampler<'a> { +impl Drop for Sampler<'_> { fn drop(&mut self) { self.meter.add_sample(self.alive_duration()); } diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index f0159060..e82d7974 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1141,16 +1141,16 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon } let hint_bounds = hint.bounds(); - let text = match hint.hyperlink() { - Some(hyperlink) => hyperlink.uri().to_owned(), - None => self.terminal.bounds_to_string(*hint_bounds.start(), *hint_bounds.end()), + let text = match hint.text(self.terminal) { + Some(text) => text, + None => return, }; match &hint.action() { // Launch an external program. HintAction::Command(command) => { let mut args = command.args().to_vec(); - args.push(text); + args.push(text.into()); self.spawn_daemon(command.program(), &args); }, // Copy the text to the clipboard. diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index bbd8673f..1c9d6008 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -1136,7 +1136,7 @@ mod tests { inline_search_state: &'a mut InlineSearchState, } - impl<'a, T: EventListener> super::ActionContext for ActionContext<'a, T> { + impl super::ActionContext for ActionContext<'_, T> { fn search_next( &mut self, _origin: Point, diff --git a/alacritty/src/migrate/mod.rs b/alacritty/src/migrate/mod.rs index 2f806d36..42b51d27 100644 --- a/alacritty/src/migrate/mod.rs +++ b/alacritty/src/migrate/mod.rs @@ -244,7 +244,7 @@ enum Migration<'a> { Yaml((&'a Path, String)), } -impl<'a> Migration<'a> { +impl Migration<'_> { /// Get the success message for this migration. fn success_message(&self, import: bool) -> String { match self { diff --git a/alacritty/src/renderer/text/gles2.rs b/alacritty/src/renderer/text/gles2.rs index 427a60e3..8756ea80 100644 --- a/alacritty/src/renderer/text/gles2.rs +++ b/alacritty/src/renderer/text/gles2.rs @@ -346,7 +346,7 @@ pub struct RenderApi<'a> { dual_source_blending: bool, } -impl<'a> Drop for RenderApi<'a> { +impl Drop for RenderApi<'_> { fn drop(&mut self) { if !self.batch.is_empty() { self.render_batch(); @@ -354,7 +354,7 @@ impl<'a> Drop for RenderApi<'a> { } } -impl<'a> LoadGlyph for RenderApi<'a> { +impl LoadGlyph for RenderApi<'_> { fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph { Atlas::load_glyph(self.active_tex, self.atlas, self.current_atlas, rasterized) } @@ -364,7 +364,7 @@ impl<'a> LoadGlyph for RenderApi<'a> { } } -impl<'a> TextRenderApi for RenderApi<'a> { +impl TextRenderApi for RenderApi<'_> { fn batch(&mut self) -> &mut Batch { self.batch } diff --git a/alacritty/src/renderer/text/glsl3.rs b/alacritty/src/renderer/text/glsl3.rs index 7c32bf9f..fee95ce3 100644 --- a/alacritty/src/renderer/text/glsl3.rs +++ b/alacritty/src/renderer/text/glsl3.rs @@ -215,7 +215,7 @@ pub struct RenderApi<'a> { program: &'a mut TextShaderProgram, } -impl<'a> TextRenderApi for RenderApi<'a> { +impl TextRenderApi for RenderApi<'_> { fn batch(&mut self) -> &mut Batch { self.batch } @@ -261,7 +261,7 @@ impl<'a> TextRenderApi for RenderApi<'a> { } } -impl<'a> LoadGlyph for RenderApi<'a> { +impl LoadGlyph for RenderApi<'_> { fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph { Atlas::load_glyph(self.active_tex, self.atlas, self.current_atlas, rasterized) } @@ -271,7 +271,7 @@ impl<'a> LoadGlyph for RenderApi<'a> { } } -impl<'a> Drop for RenderApi<'a> { +impl Drop for RenderApi<'_> { fn drop(&mut self) { if !self.batch.is_empty() { self.render_batch(); diff --git a/alacritty/src/renderer/text/mod.rs b/alacritty/src/renderer/text/mod.rs index 886b7f8b..acd1b521 100644 --- a/alacritty/src/renderer/text/mod.rs +++ b/alacritty/src/renderer/text/mod.rs @@ -186,7 +186,7 @@ pub struct LoaderApi<'a> { current_atlas: &'a mut usize, } -impl<'a> LoadGlyph for LoaderApi<'a> { +impl LoadGlyph for LoaderApi<'_> { fn load_glyph(&mut self, rasterized: &RasterizedGlyph) -> Glyph { Atlas::load_glyph(self.active_tex, self.atlas, self.current_atlas, rasterized) } diff --git a/alacritty/src/string.rs b/alacritty/src/string.rs index a7af4394..b8c47d3b 100644 --- a/alacritty/src/string.rs +++ b/alacritty/src/string.rs @@ -106,7 +106,7 @@ impl<'a> StrShortener<'a> { } } -impl<'a> Iterator for StrShortener<'a> { +impl Iterator for StrShortener<'_> { type Item = char; fn next(&mut self) -> Option { diff --git a/alacritty_terminal/src/grid/mod.rs b/alacritty_terminal/src/grid/mod.rs index 278bea3b..fbd2c79e 100644 --- a/alacritty_terminal/src/grid/mod.rs +++ b/alacritty_terminal/src/grid/mod.rs @@ -615,7 +615,7 @@ pub trait BidirectionalIterator: Iterator { fn prev(&mut self) -> Option; } -impl<'a, T> BidirectionalIterator for GridIterator<'a, T> { +impl BidirectionalIterator for GridIterator<'_, T> { fn prev(&mut self) -> Option { let topmost_line = self.grid.topmost_line(); let last_column = self.grid.last_column(); diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 8a0410dc..1f1e52c1 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -199,7 +199,7 @@ impl<'a> TermDamageIterator<'a> { } } -impl<'a> Iterator for TermDamageIterator<'a> { +impl Iterator for TermDamageIterator<'_> { type Item = LineDamageBounds; fn next(&mut self) -> Option { diff --git a/alacritty_terminal/src/term/search.rs b/alacritty_terminal/src/term/search.rs index 33f6ee05..20a427b7 100644 --- a/alacritty_terminal/src/term/search.rs +++ b/alacritty_terminal/src/term/search.rs @@ -656,7 +656,7 @@ impl<'a, T> RegexIter<'a, T> { } } -impl<'a, T> Iterator for RegexIter<'a, T> { +impl Iterator for RegexIter<'_, T> { type Item = Match; fn next(&mut self) -> Option { From 1063706f8e8a84139e5d2b464a4978e9d840ea17 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sat, 2 Nov 2024 21:43:47 +0000 Subject: [PATCH 091/102] Bump all dependencies This patch applies all major and minor version bumps, with the exception of `unicode-width` since it will need to be handled separately for Unicode version 16. --- Cargo.lock | 535 ++++++++++--------- alacritty/Cargo.toml | 2 +- alacritty_terminal/Cargo.toml | 2 +- alacritty_terminal/src/tty/windows/child.rs | 13 +- alacritty_terminal/src/tty/windows/conpty.rs | 2 +- extra/completions/_alacritty | 36 +- 6 files changed, 317 insertions(+), 273 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 64db3952..6dbd5a04 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3,10 +3,10 @@ version = 3 [[package]] -name = "adler" -version = "1.0.2" +name = "adler2" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" [[package]] name = "ahash" @@ -41,7 +41,7 @@ dependencies = [ "bitflags 2.6.0", "clap", "clap_complete", - "cocoa", + "cocoa 0.26.0", "copypasta", "crossfont", "dirs", @@ -60,7 +60,7 @@ dependencies = [ "serde_yaml", "tempfile", "toml", - "toml_edit 0.22.21", + "toml_edit", "unicode-width", "windows-sys 0.52.0", "winit", @@ -110,7 +110,7 @@ dependencies = [ "signal-hook", "unicode-width", "vte", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -142,9 +142,9 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", @@ -157,49 +157,49 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "arrayref" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b4930d2cb77ce62f89ee5d5289b4ac049559b1c45539271f5ed4fdc7db34545" +checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" [[package]] name = "arrayvec" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "as-raw-xcb-connection" @@ -215,9 +215,9 @@ checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] name = "autocfg" -version = "1.3.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "base64" @@ -263,15 +263,15 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.16.1" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" +checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" [[package]] name = "bytes" -version = "1.6.1" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "calloop" @@ -301,12 +301,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.5" +version = "1.1.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "324c74f2155653c90b04f25b2a47a8a631360cb908f92a772695f430c7e31052" +checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -338,9 +339,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.9" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" +checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" dependencies = [ "clap_builder", "clap_derive", @@ -348,9 +349,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.9" +version = "4.5.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" +checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" dependencies = [ "anstream", "anstyle", @@ -360,18 +361,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.8" +version = "4.5.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b4be9c4c4b1f30b78d8a750e0822b6a6102d97e62061c583a6c1dea2dfb33ae" +checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -381,9 +382,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clipboard-win" @@ -403,9 +404,25 @@ checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" dependencies = [ "bitflags 1.3.2", "block", - "cocoa-foundation", - "core-foundation", - "core-graphics", + "cocoa-foundation 0.1.2", + "core-foundation 0.9.4", + "core-graphics 0.23.2", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" +dependencies = [ + "bitflags 2.6.0", + "block", + "cocoa-foundation 0.2.0", + "core-foundation 0.10.0", + "core-graphics 0.24.0", "foreign-types", "libc", "objc", @@ -419,17 +436,31 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d" +dependencies = [ + "bitflags 2.6.0", + "block", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", "libc", "objc", ] [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "combine" @@ -474,11 +505,21 @@ dependencies = [ "libc", ] +[[package]] +name = "core-foundation" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "core-graphics" @@ -487,8 +528,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", + "core-foundation 0.9.4", + "core-graphics-types 0.1.3", + "foreign-types", + "libc", +] + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", + "core-graphics-types 0.2.0", "foreign-types", "libc", ] @@ -500,7 +554,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation", + "core-foundation 0.9.4", + "libc", +] + +[[package]] +name = "core-graphics-types" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" +dependencies = [ + "bitflags 2.6.0", + "core-foundation 0.10.0", "libc", ] @@ -510,8 +575,8 @@ version = "20.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" dependencies = [ - "core-foundation", - "core-graphics", + "core-foundation 0.9.4", + "core-graphics 0.23.2", "foreign-types", "libc", ] @@ -546,10 +611,10 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c44e28d120f3c9254800ea53349b09cbb45ac1f15f09215011a16241ae0289bc" dependencies = [ - "cocoa", - "core-foundation", + "cocoa 0.25.0", + "core-foundation 0.9.4", "core-foundation-sys", - "core-graphics", + "core-graphics 0.23.2", "core-text", "dwrote", "foreign-types", @@ -635,9 +700,9 @@ dependencies = [ [[package]] name = "dwrote" -version = "0.11.0" +version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "439a1c2ba5611ad3ed731280541d36d2e9c4ac5e7fb818a27b604bdc5a6aa65b" +checksum = "70182709525a3632b2ba96b6569225467b18ecb4a77f46d255f713a6bebf05fd" dependencies = [ "lazy_static", "libc", @@ -649,9 +714,9 @@ dependencies = [ [[package]] name = "embed-resource" -version = "2.4.2" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6985554d0688b687c5cb73898a34fbe3ad6c24c58c238a4d91d5e840670ee9d" +checksum = "f4e24052d7be71f0efb50c201557f6fe7d237cfd5a64fd5bcd7fd8fe32dbbffa" dependencies = [ "cc", "memchr", @@ -679,36 +744,36 @@ dependencies = [ [[package]] name = "fastrand" -version = "2.1.0" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" +checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" [[package]] name = "fdeflate" -version = "0.3.4" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f9bfee30e4dedf0ab8b422f03af778d9612b63f502710fc500a334ebe2de645" +checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" dependencies = [ "simd-adler32", ] [[package]] name = "filetime" -version = "0.2.23" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ee447700ac8aa0b2f2bd7bc4462ad686ba06baa6727ac149a2d6277f0d240fd" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.4.1", - "windows-sys 0.52.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] name = "flate2" -version = "1.0.30" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f54427cfd1c7829e2a139fcefea601bf088ebca651d2bf53ebc600eac295dae" +checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" dependencies = [ "crc32fast", "miniz_oxide", @@ -774,9 +839,9 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a44623e20b9681a318efdd71c299b6b222ed6f231972bfe2f224ebad6311f0c1" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" [[package]] name = "gethostname" @@ -812,14 +877,14 @@ dependencies = [ [[package]] name = "glutin" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2491aa3090f682ddd920b184491844440fdd14379c7eef8f5bc10ef7fb3242fd" +checksum = "ec69412a0bf07ea7607e638b415447857a808846c2b685a43c8aa18bc6d5e499" dependencies = [ "bitflags 2.6.0", "cfg_aliases", "cgl", - "core-foundation", + "core-foundation 0.9.4", "dispatch", "glutin_egl_sys", "glutin_glx_sys", @@ -866,9 +931,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.5" +version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" [[package]] name = "heck" @@ -893,9 +958,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" dependencies = [ "equivalent", "hashbrown", @@ -923,9 +988,9 @@ dependencies = [ [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" @@ -957,18 +1022,18 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d" +checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" dependencies = [ "wasm-bindgen", ] @@ -1013,31 +1078,20 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libloading" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", "windows-targets 0.52.6", ] -[[package]] -name = "libredox" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" -dependencies = [ - "bitflags 2.6.0", - "libc", - "redox_syscall 0.4.1", -] - [[package]] name = "libredox" version = "0.1.3" @@ -1046,6 +1100,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", + "redox_syscall 0.5.7", ] [[package]] @@ -1090,20 +1145,20 @@ checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe751422e4a8caa417e13c3ea66452215d7d63e19e604f4980461212f3ae1322" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" dependencies = [ "libc", ] [[package]] name = "miniz_oxide" -version = "0.7.4" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", "simd-adler32", ] @@ -1179,18 +1234,18 @@ dependencies = [ [[package]] name = "num_enum" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02339744ee7253741199f897151b38e72257d13802d4ee837285cc2990a90845" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "681030a937600a36906c185595136d26abfebb4aa9c65701cefcaf8578bb982b" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1432,9 +1487,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.19.0" +version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" [[package]] name = "option-ext" @@ -1444,11 +1499,11 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "orbclient" -version = "0.3.47" +version = "0.3.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f0d54bde9774d3a51dcf281a5def240c71996bc6ca05d2c847ec8b2b216166" +checksum = "ba0b26cec2e24f08ed8bb31519a9333140a6599b867dac464bb150bdb796fd43" dependencies = [ - "libredox 0.0.2", + "libredox", ] [[package]] @@ -1469,7 +1524,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.3", + "redox_syscall 0.5.7", "smallvec", "windows-targets 0.52.6", ] @@ -1482,18 +1537,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "pin-project" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.5" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", @@ -1502,15 +1557,15 @@ dependencies = [ [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "piper" -version = "0.2.3" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1d5c74c9876f070d3e8fd503d748c7d974c3e48da8f41350fa5222ef9b4391" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", "fastrand", @@ -1519,15 +1574,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" -version = "0.17.13" +version = "0.17.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06e4b0d3d1312775e782c86c91a111aa1f910cbb65e1337f9975b5f9a554b5e1" +checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1538,9 +1593,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.2" +version = "3.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3ed00ed3fbf728b5816498ecd316d1716eecaced9c0c8d2c5a6740ca214985b" +checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" dependencies = [ "cfg-if", "concurrent-queue", @@ -1548,41 +1603,41 @@ dependencies = [ "pin-project-lite", "rustix", "tracing", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "proc-macro-crate" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d37c51ca738a55da99dc0c4a34860fd675453b8b36209178c2249bb13651284" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit 0.21.1", + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.86" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] [[package]] name = "quick-xml" -version = "0.34.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f24d770aeca0eacb81ac29dfbc55ebcc09312fdd1f8bbecdc7e4a84e000e3b4" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -1604,29 +1659,29 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.3" +version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd283d9651eeda4b2a83a43c1c91b266c40fd76ecd39a50a8c630ae69dc72891" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ "getrandom", - "libredox 0.1.3", + "libredox", "thiserror", ] [[package]] name = "regex-automata" -version = "0.4.7" +version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" dependencies = [ "aho-corasick", "memchr", @@ -1635,24 +1690,24 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.4" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "rustc_version" -version = "0.4.0" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" dependencies = [ "semver", ] [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" dependencies = [ "bitflags 2.6.0", "errno", @@ -1720,18 +1775,18 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.204" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" +checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.204" +version = "1.0.214" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" +checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" dependencies = [ "proc-macro2", "quote", @@ -1740,20 +1795,21 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -1771,6 +1827,12 @@ dependencies = [ "unsafe-libyaml", ] +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + [[package]] name = "signal-hook" version = "0.3.17" @@ -1870,9 +1932,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.71" +version = "2.0.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462" +checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" dependencies = [ "proc-macro2", "quote", @@ -1881,9 +1943,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04cbcdd0c794ebb0d4cf35e88edd2f7d2c4c3e9a5a6dab322839b321c6a87a64" +checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ "cfg-if", "fastrand", @@ -1894,18 +1956,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" dependencies = [ "proc-macro2", "quote", @@ -1939,14 +2001,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.14" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.21", + "toml_edit", ] [[package]] @@ -1960,26 +2022,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow 0.5.40", -] - -[[package]] -name = "toml_edit" -version = "0.22.21" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b072cee73c449a636ffd6f32bd8de3a9f7119139aff882f44943ce2986dc5cf" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.18", + "winnow", ] [[package]] @@ -2000,21 +2051,21 @@ checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-segmentation" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4c87d22b6e3f4a18d4d40ef354e97c90fcb14dd91d7dc0aa9d8a1172ebf7202" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.13" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0336d538f7abc86d282a4189614dfaa90810dfc2c6f6427eaf88e16311dd225d" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[package]] name = "unsafe-libyaml" @@ -2030,9 +2081,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "vswhom" @@ -2096,19 +2147,20 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8" +checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da" +checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", "log", @@ -2121,9 +2173,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.42" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76bc14366121efc8dbb487ab05bcc9d346b3b5ec0eaa76e46594cabbe51762c0" +checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ "cfg-if", "js-sys", @@ -2133,9 +2185,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726" +checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2143,9 +2195,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" +checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", @@ -2156,15 +2208,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.92" +version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96" +checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" [[package]] name = "wayland-backend" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f90e11ce2ca99c97b940ee83edbae9da2d56a08f9ea8158550fd77fa31722993" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" dependencies = [ "cc", "downcast-rs", @@ -2176,9 +2228,9 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.5" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e321577a0a165911bdcfb39cf029302479d7527b517ee58ab0f6ad09edf0943" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" dependencies = [ "bitflags 2.6.0", "rustix", @@ -2199,9 +2251,9 @@ dependencies = [ [[package]] name = "wayland-cursor" -version = "0.31.5" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ef9489a8df197ebf3a8ce8a7a7f0a2320035c3743f3c1bd0bdbccf07ce64f95" +checksum = "32b08bc3aafdb0035e7fe0fdf17ba0c09c268732707dca4ae098f60cb28c9e4c" dependencies = [ "rustix", "wayland-client", @@ -2210,9 +2262,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.32.3" +version = "0.32.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62989625a776e827cc0f15d41444a3cea5205b963c3a25be48ae1b52d6b4daaa" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -2222,9 +2274,9 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79f2d57c7fcc6ab4d602adba364bf59a5c24de57bd194486bf9b8360e06bfc4" +checksum = "9b31cab548ee68c7eb155517f2212049dc151f7cd7910c2b66abfd31c3ee12bd" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -2235,9 +2287,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.3.3" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd993de54a40a40fbe5601d9f1fbcaef0aebcc5fda447d7dc8f6dcbaae4f8953" +checksum = "782e12f6cd923c3c316130d56205ebab53f55d6666b7faddfad36cecaeeb4022" dependencies = [ "bitflags 2.6.0", "wayland-backend", @@ -2248,9 +2300,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.4" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7b56f89937f1cf2ee1f1259cf2936a17a1f45d8f0aa1019fae6d470d304cfa6" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" dependencies = [ "proc-macro2", "quick-xml", @@ -2259,9 +2311,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.4" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43676fe2daf68754ecf1d72026e4e6c15483198b5d24e888b74d3f22f887a148" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" dependencies = [ "dlib", "log", @@ -2271,9 +2323,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.69" +version = "0.3.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77afa9a11836342370f4817622a2f0f418b134426d91a82dfb48f532d2ec13ef" +checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" dependencies = [ "js-sys", "wasm-bindgen", @@ -2307,11 +2359,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.8" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d4cc384e1e73b93bafa6fb4f1df8c41695c8a91cf9c4c64358067d15a7b6c6b" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2536,9 +2588,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.30.4" +version = "0.30.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4225ddd8ab67b8b59a2fee4b34889ebf13c0460c1c3fa297c58e21eb87801b33" +checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" dependencies = [ "ahash", "android-activity", @@ -2549,8 +2601,8 @@ dependencies = [ "calloop", "cfg_aliases", "concurrent-queue", - "core-foundation", - "core-graphics", + "core-foundation 0.9.4", + "core-graphics 0.23.2", "cursor-icon", "dpi", "js-sys", @@ -2589,18 +2641,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.5.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" -dependencies = [ - "memchr", -] - -[[package]] -name = "winnow" -version = "0.6.18" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -2668,9 +2711,9 @@ checksum = "ec107c4503ea0b4a98ef47356329af139c0a4f7750e621cf2973cd3385ebcb3d" [[package]] name = "xcursor" -version = "0.3.5" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a0ccd7b4a5345edfcd0c3535718a4e9ff7798ffc536bb5b5a0e26ff84732911" +checksum = "0ef33da6b1660b4ddbfb3aef0ade110c8b8a781a3b6382fa5f2b5b040fd55f61" [[package]] name = "xdg" @@ -2699,9 +2742,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.20" +version = "0.8.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "791978798f0597cfc70478424c2b4fdc2b7a8024aaff78497ef00f24ef674193" +checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" [[package]] name = "yeslogic-fontconfig-sys" diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 09a97706..d3a083cd 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -56,7 +56,7 @@ xdg = "2.5.0" png = { version = "0.17.5", default-features = false, optional = true } [target.'cfg(target_os = "macos")'.dependencies] -cocoa = "0.25.0" +cocoa = "0.26.0" objc = "0.2.2" [target.'cfg(windows)'.dependencies] diff --git a/alacritty_terminal/Cargo.toml b/alacritty_terminal/Cargo.toml index 6afa7fef..32e09a72 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -34,7 +34,7 @@ signal-hook = "0.3.10" [target.'cfg(windows)'.dependencies] piper = "0.2.1" miow = "0.6.0" -windows-sys = { version = "0.52.0", features = [ +windows-sys = { version = "0.59.0", features = [ "Win32_System_Console", "Win32_Foundation", "Win32_Security", diff --git a/alacritty_terminal/src/tty/windows/child.rs b/alacritty_terminal/src/tty/windows/child.rs index dc6b992c..573eb475 100644 --- a/alacritty_terminal/src/tty/windows/child.rs +++ b/alacritty_terminal/src/tty/windows/child.rs @@ -1,6 +1,7 @@ use std::ffi::c_void; use std::io::Error; use std::num::NonZeroU32; +use std::ptr; use std::sync::atomic::{AtomicPtr, Ordering}; use std::sync::{mpsc, Arc, Mutex}; @@ -50,7 +51,7 @@ pub struct ChildExitWatcher { wait_handle: AtomicPtr, event_rx: mpsc::Receiver, interest: Arc>>, - child_handle: HANDLE, + child_handle: AtomicPtr, pid: Option, } @@ -58,12 +59,12 @@ impl ChildExitWatcher { pub fn new(child_handle: HANDLE) -> Result { let (event_tx, event_rx) = mpsc::channel(); - let mut wait_handle: HANDLE = 0; + let mut wait_handle: HANDLE = ptr::null_mut(); let interest = Arc::new(Mutex::new(None)); let sender_ref = Box::new(ChildExitSender { sender: event_tx, interest: interest.clone(), - child_handle: AtomicPtr::from(child_handle as *mut c_void), + child_handle: AtomicPtr::from(child_handle), }); let success = unsafe { @@ -82,11 +83,11 @@ impl ChildExitWatcher { } else { let pid = unsafe { NonZeroU32::new(GetProcessId(child_handle)) }; Ok(ChildExitWatcher { - wait_handle: AtomicPtr::from(wait_handle as *mut c_void), event_rx, interest, - child_handle, pid, + child_handle: AtomicPtr::from(child_handle), + wait_handle: AtomicPtr::from(wait_handle), }) } } @@ -112,7 +113,7 @@ impl ChildExitWatcher { /// If you terminate the process using this handle, the terminal will get a /// timeout error, and the child watcher will emit an `Exited` event. pub fn raw_handle(&self) -> HANDLE { - self.child_handle + self.child_handle.load(Ordering::Relaxed) as HANDLE } /// Retrieve the Process ID associated to the underlying child process. diff --git a/alacritty_terminal/src/tty/windows/conpty.rs b/alacritty_terminal/src/tty/windows/conpty.rs index 28289f90..bcbc1f0e 100644 --- a/alacritty_terminal/src/tty/windows/conpty.rs +++ b/alacritty_terminal/src/tty/windows/conpty.rs @@ -72,7 +72,7 @@ impl ConptyApi { type LoadedFn = unsafe extern "system" fn() -> isize; unsafe { let hmodule = LoadLibraryW(w!("conpty.dll")); - if hmodule == 0 { + if hmodule.is_null() { return None; } let create_fn = GetProcAddress(hmodule, s!("CreatePseudoConsole"))?; diff --git a/extra/completions/_alacritty b/extra/completions/_alacritty index 0ccce66f..a0ac0e3b 100644 --- a/extra/completions/_alacritty +++ b/extra/completions/_alacritty @@ -15,17 +15,17 @@ _alacritty() { local context curcontext="$curcontext" state line _arguments "${_arguments_options[@]}" : \ -'--embed=[X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix)]:EMBED: ' \ +'--embed=[X11 window ID to embed Alacritty within (decimal or hexadecimal with "0x" prefix)]:EMBED:_default' \ '--config-file=[Specify alternative configuration file \[default\: \$XDG_CONFIG_HOME/alacritty/alacritty.toml\]]:CONFIG_FILE:_files' \ '--socket=[Path for IPC socket creation]:SOCKET:_files' \ '--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: ' \ -'-T+[Defines the window title \[default\: Alacritty\]]:TITLE: ' \ -'--title=[Defines the window title \[default\: Alacritty\]]:TITLE: ' \ -'--class=[Defines window class/app_id on X11/Wayland \[default\: Alacritty\]]:general> | , | , | , | , Date: Thu, 21 Nov 2024 01:36:25 +0100 Subject: [PATCH 092/102] Switch to new objc2 crates --- Cargo.lock | 101 ++++++-------------------------- alacritty/Cargo.toml | 15 ++++- alacritty/src/display/window.rs | 28 ++++----- alacritty/src/macos/locale.rs | 56 ++++++------------ 4 files changed, 63 insertions(+), 137 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6dbd5a04..17db267f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -41,7 +41,6 @@ dependencies = [ "bitflags 2.6.0", "clap", "clap_complete", - "cocoa 0.26.0", "copypasta", "crossfont", "dirs", @@ -52,7 +51,9 @@ dependencies = [ "libc", "log", "notify", - "objc", + "objc2", + "objc2-app-kit", + "objc2-foundation", "parking_lot", "png", "serde", @@ -404,25 +405,9 @@ checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" dependencies = [ "bitflags 1.3.2", "block", - "cocoa-foundation 0.1.2", - "core-foundation 0.9.4", - "core-graphics 0.23.2", - "foreign-types", - "libc", - "objc", -] - -[[package]] -name = "cocoa" -version = "0.26.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f79398230a6e2c08f5c9760610eb6924b52aa9e7950a619602baba59dcbbdbb2" -dependencies = [ - "bitflags 2.6.0", - "block", - "cocoa-foundation 0.2.0", - "core-foundation 0.10.0", - "core-graphics 0.24.0", + "cocoa-foundation", + "core-foundation", + "core-graphics", "foreign-types", "libc", "objc", @@ -436,22 +421,8 @@ checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", - "libc", - "objc", -] - -[[package]] -name = "cocoa-foundation" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14045fb83be07b5acf1c0884b2180461635b433455fa35d1cd6f17f1450679d" -dependencies = [ - "bitflags 2.6.0", - "block", - "core-foundation 0.10.0", - "core-graphics-types 0.2.0", + "core-foundation", + "core-graphics-types", "libc", "objc", ] @@ -505,16 +476,6 @@ dependencies = [ "libc", ] -[[package]] -name = "core-foundation" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b55271e5c8c478ad3f38ad24ef34923091e0548492a266d19b3c0b4d82574c63" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "core-foundation-sys" version = "0.8.7" @@ -528,21 +489,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types 0.1.3", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" -dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.10.0", - "core-graphics-types 0.2.0", + "core-foundation", + "core-graphics-types", "foreign-types", "libc", ] @@ -554,18 +502,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" dependencies = [ "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" -dependencies = [ - "bitflags 2.6.0", - "core-foundation 0.10.0", + "core-foundation", "libc", ] @@ -575,8 +512,8 @@ version = "20.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9d2790b5c08465d49f8dc05c8bcae9fea467855947db39b0f8145c091aaced5" dependencies = [ - "core-foundation 0.9.4", - "core-graphics 0.23.2", + "core-foundation", + "core-graphics", "foreign-types", "libc", ] @@ -611,10 +548,10 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c44e28d120f3c9254800ea53349b09cbb45ac1f15f09215011a16241ae0289bc" dependencies = [ - "cocoa 0.25.0", - "core-foundation 0.9.4", + "cocoa", + "core-foundation", "core-foundation-sys", - "core-graphics 0.23.2", + "core-graphics", "core-text", "dwrote", "foreign-types", @@ -884,7 +821,7 @@ dependencies = [ "bitflags 2.6.0", "cfg_aliases", "cgl", - "core-foundation 0.9.4", + "core-foundation", "dispatch", "glutin_egl_sys", "glutin_glx_sys", @@ -2601,8 +2538,8 @@ dependencies = [ "calloop", "cfg_aliases", "concurrent-queue", - "core-foundation 0.9.4", - "core-graphics 0.23.2", + "core-foundation", + "core-graphics", "cursor-icon", "dpi", "js-sys", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index d3a083cd..f7f282c2 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -56,8 +56,19 @@ xdg = "2.5.0" png = { version = "0.17.5", default-features = false, optional = true } [target.'cfg(target_os = "macos")'.dependencies] -cocoa = "0.26.0" -objc = "0.2.2" +objc2 = "0.5.2" +objc2-foundation = { version = "0.2.2", default-features = false, features = [ + "std", + "NSString", + "NSLocale", +] } +objc2-app-kit = { version = "0.2.2", default-features = false, features = [ + "std", + "NSColorSpace", + "NSResponder", + "NSView", + "NSWindow", +] } [target.'cfg(windows)'.dependencies] dirs = "5.0.1" diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 5f0790b6..3d6989a0 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -20,9 +20,8 @@ use std::fmt::{self, Display, Formatter}; #[cfg(target_os = "macos")] use { - cocoa::appkit::NSColorSpace, - cocoa::base::{id, nil, NO, YES}, - objc::{msg_send, sel, sel_impl}, + objc2_app_kit::{NSColorSpace, NSView}, + objc2_foundation::is_main_thread, winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMacOS}, }; @@ -451,16 +450,15 @@ impl Window { /// This prevents rendering artifacts from showing up when the window is transparent. #[cfg(target_os = "macos")] pub fn set_has_shadow(&self, has_shadows: bool) { - let ns_view = match self.raw_window_handle() { - RawWindowHandle::AppKit(handle) => handle.ns_view.as_ptr() as id, + let view = match self.raw_window_handle() { + RawWindowHandle::AppKit(handle) => { + assert!(is_main_thread()); + unsafe { handle.ns_view.cast::().as_ref() } + }, _ => return, }; - let value = if has_shadows { YES } else { NO }; - unsafe { - let ns_window: id = msg_send![ns_view, window]; - let _: id = msg_send![ns_window, setHasShadow: value]; - } + view.window().unwrap().setHasShadow(has_shadows); } /// Select tab at the given `index`. @@ -495,13 +493,15 @@ impl Window { #[cfg(target_os = "macos")] fn use_srgb_color_space(window: &WinitWindow) { - let ns_view = match window.window_handle().unwrap().as_raw() { - RawWindowHandle::AppKit(handle) => handle.ns_view.as_ptr() as id, + let view = match window.window_handle().unwrap().as_raw() { + RawWindowHandle::AppKit(handle) => { + assert!(is_main_thread()); + unsafe { handle.ns_view.cast::().as_ref() } + }, _ => return, }; unsafe { - let ns_window: id = msg_send![ns_view, window]; - let _: () = msg_send![ns_window, setColorSpace: NSColorSpace::sRGBColorSpace(nil)]; + view.window().unwrap().setColorSpace(Some(&NSColorSpace::sRGBColorSpace())); } } diff --git a/alacritty/src/macos/locale.rs b/alacritty/src/macos/locale.rs index 2a47ace8..46996515 100644 --- a/alacritty/src/macos/locale.rs +++ b/alacritty/src/macos/locale.rs @@ -1,13 +1,12 @@ #![allow(clippy::let_unit_value)] use std::ffi::{CStr, CString}; -use std::os::raw::c_char; -use std::{env, slice, str}; +use std::{env, str}; use libc::{setlocale, LC_ALL, LC_CTYPE}; use log::debug; -use objc::runtime::{Class, Object}; -use objc::{msg_send, sel, sel_impl}; +use objc2::sel; +use objc2_foundation::{NSLocale, NSObjectProtocol}; const FALLBACK_LOCALE: &str = "UTF-8"; @@ -50,9 +49,7 @@ pub fn set_locale_environment() { /// Determine system locale based on language and country code. fn system_locale() -> String { unsafe { - let locale_class = Class::get("NSLocale").unwrap(); - let locale: *const Object = msg_send![locale_class, currentLocale]; - let _: () = msg_send![locale_class, release]; + let locale = NSLocale::currentLocale(); // `localeIdentifier` returns extra metadata with the locale (including currency and // collator) on newer versions of macOS. This is not a valid locale, so we use @@ -61,38 +58,19 @@ fn system_locale() -> String { // https://developer.apple.com/documentation/foundation/nslocale/1416263-localeidentifier?language=objc // https://developer.apple.com/documentation/foundation/nslocale/1643060-countrycode?language=objc // https://developer.apple.com/documentation/foundation/nslocale/1643026-languagecode?language=objc - let is_language_code_supported: bool = - msg_send![locale, respondsToSelector: sel!(languageCode)]; - let is_country_code_supported: bool = - msg_send![locale, respondsToSelector: sel!(countryCode)]; - let locale_id = if is_language_code_supported && is_country_code_supported { - let language_code: *const Object = msg_send![locale, languageCode]; - let language_code_str = nsstring_as_str(language_code).to_owned(); - let _: () = msg_send![language_code, release]; - - let country_code: *const Object = msg_send![locale, countryCode]; - let country_code_str = nsstring_as_str(country_code).to_owned(); - let _: () = msg_send![country_code, release]; - - format!("{}_{}.UTF-8", &language_code_str, &country_code_str) + let is_language_code_supported: bool = locale.respondsToSelector(sel!(languageCode)); + let is_country_code_supported: bool = locale.respondsToSelector(sel!(countryCode)); + if is_language_code_supported && is_country_code_supported { + let language_code = locale.languageCode(); + #[allow(deprecated)] + if let Some(country_code) = locale.countryCode() { + format!("{}_{}.UTF-8", language_code, country_code) + } else { + // Fall back to en_US in case the country code is not available. + "en_US.UTF-8".into() + } } else { - let identifier: *const Object = msg_send![locale, localeIdentifier]; - let identifier_str = nsstring_as_str(identifier).to_owned(); - let _: () = msg_send![identifier, release]; - - identifier_str + ".UTF-8" - }; - - let _: () = msg_send![locale, release]; - - locale_id + locale.localeIdentifier().to_string() + ".UTF-8" + } } } - -const UTF8_ENCODING: usize = 4; - -unsafe fn nsstring_as_str<'a>(nsstring: *const Object) -> &'a str { - let cstr: *const c_char = msg_send![nsstring, UTF8String]; - let len: usize = msg_send![nsstring, lengthOfBytesUsingEncoding: UTF8_ENCODING]; - str::from_utf8(slice::from_raw_parts(cstr as *const u8, len)).unwrap() -} From 3ac4904eb5a1cc15cc02b077c118f1ffcb9e6916 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Fri, 22 Nov 2024 01:07:08 +0000 Subject: [PATCH 093/102] Fix vi motion with wide semantic escape chars This patch fixes an issue where the semantic vi motion commands `SemanticRight` and `SemanticLeft` were not behaving as expected when a fullwidth character was used as a semantic character. Closes #8314. --- CHANGELOG.md | 1 + alacritty_terminal/src/term/mod.rs | 5 +++ alacritty_terminal/src/vi_mode.rs | 49 ++++++++++++++++++++++++++++-- 3 files changed, 52 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbe0d2f4..c9faa35c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Mouse/Vi cursor hint highlighting broken on the terminal cursor line - Hint launcher opening arbitrary text, when terminal content changed while opening +- `SemanticRight`/`SemanticLeft` vi motions breaking with wide semantic escape characters ## 0.14.0 diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index 1f1e52c1..c2d77ec7 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -930,6 +930,11 @@ impl Term { &self.config.semantic_escape_chars } + #[cfg(test)] + pub(crate) fn set_semantic_escape_chars(&mut self, semantic_escape_chars: &str) { + self.config.semantic_escape_chars = semantic_escape_chars.into(); + } + /// Active terminal cursor style. /// /// While vi mode is active, this will automatically return the vi mode cursor style. diff --git a/alacritty_terminal/src/vi_mode.rs b/alacritty_terminal/src/vi_mode.rs index 7065544e..e23e9b80 100644 --- a/alacritty_terminal/src/vi_mode.rs +++ b/alacritty_terminal/src/vi_mode.rs @@ -265,14 +265,14 @@ fn semantic( } }; - // Make sure we jump above wide chars. - point = term.expand_wide(point, direction); - // Move to word boundary. if direction != side && !is_boundary(term, point, direction) { point = expand_semantic(point); } + // Make sure we jump above wide chars. + point = term.expand_wide(point, direction); + // Skip whitespace. let mut next_point = advance(term, point, direction); while !is_boundary(term, point, direction) && is_space(term, next_point) { @@ -283,6 +283,11 @@ fn semantic( // Assure minimum movement of one cell. if !is_boundary(term, point, direction) { point = advance(term, point, direction); + + // Skip over wide cell spacers. + if direction == Direction::Left { + point = term.expand_wide(point, direction); + } } // Move to word boundary. @@ -820,4 +825,42 @@ mod tests { cursor = cursor.scroll(&term, -20); assert_eq!(cursor.point, Point::new(Line(19), Column(0))); } + + #[test] + fn wide_semantic_char() { + let mut term = term(); + term.set_semantic_escape_chars("-"); + term.grid_mut()[Line(0)][Column(0)].c = 'x'; + term.grid_mut()[Line(0)][Column(1)].c = 'x'; + term.grid_mut()[Line(0)][Column(2)].c = '-'; + term.grid_mut()[Line(0)][Column(2)].flags.insert(Flags::WIDE_CHAR); + term.grid_mut()[Line(0)][Column(3)].c = ' '; + term.grid_mut()[Line(0)][Column(3)].flags.insert(Flags::WIDE_CHAR_SPACER); + term.grid_mut()[Line(0)][Column(4)].c = 'x'; + term.grid_mut()[Line(0)][Column(5)].c = 'x'; + + // Test motion to the right. + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(0))); + cursor = cursor.motion(&mut term, ViMotion::SemanticRight); + assert_eq!(cursor.point, Point::new(Line(0), Column(2))); + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(2))); + cursor = cursor.motion(&mut term, ViMotion::SemanticRight); + assert_eq!(cursor.point, Point::new(Line(0), Column(4))); + + // Test motion to the left. + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(5))); + cursor = cursor.motion(&mut term, ViMotion::SemanticLeft); + assert_eq!(cursor.point, Point::new(Line(0), Column(4))); + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(4))); + cursor = cursor.motion(&mut term, ViMotion::SemanticLeft); + assert_eq!(cursor.point, Point::new(Line(0), Column(2))); + + let mut cursor = ViModeCursor::new(Point::new(Line(0), Column(2))); + cursor = cursor.motion(&mut term, ViMotion::SemanticLeft); + assert_eq!(cursor.point, Point::new(Line(0), Column(0))); + } } From 6e9a19fd8317e9d0d6a33aa535a1f2ea56844626 Mon Sep 17 00:00:00 2001 From: David Horner Date: Sat, 23 Nov 2024 14:20:56 -0500 Subject: [PATCH 094/102] Add `window.level` config option --- CHANGELOG.md | 4 ++++ alacritty/Cargo.toml | 2 +- alacritty/src/config/window.rs | 22 +++++++++++++++++++++- alacritty/src/display/window.rs | 3 ++- extra/man/alacritty.5.scd | 11 +++++++++++ 5 files changed, 39 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c9faa35c..e78e82ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,10 @@ Notable changes to the `alacritty_terminal` crate are documented in its ## 0.15.0-dev +### Added + +- Config option `window.level = "AlwaysOnTop"` to force Alacritty to always be the toplevel window + ### Changed - Always focus new windows on macOS diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index f7f282c2..264ecbc6 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -41,7 +41,7 @@ tempfile = "3.12.0" toml = "0.8.2" toml_edit = "0.22.21" unicode-width = "0.1" -winit = { version = "0.30.4", default-features = false, features = ["rwh_06", "serde"] } +winit = { version = "0.30.5", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] gl_generator = "0.14.0" diff --git a/alacritty/src/config/window.rs b/alacritty/src/config/window.rs index 380f7a6f..358bb76d 100644 --- a/alacritty/src/config/window.rs +++ b/alacritty/src/config/window.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Deserializer, Serialize}; #[cfg(target_os = "macos")] use winit::platform::macos::OptionAsAlt as WinitOptionAsAlt; -use winit::window::{Fullscreen, Theme as WinitTheme}; +use winit::window::{Fullscreen, Theme as WinitTheme, WindowLevel as WinitWindowLevel}; use alacritty_config_derive::{ConfigDeserialize, SerdeReplace}; @@ -61,6 +61,9 @@ pub struct WindowConfig { /// System decorations theme variant. decorations_theme_variant: Option, + + /// Window level. + pub level: WindowLevel, } impl Default for WindowConfig { @@ -80,6 +83,7 @@ impl Default for WindowConfig { resize_increments: Default::default(), decorations_theme_variant: Default::default(), option_as_alt: Default::default(), + level: Default::default(), } } } @@ -306,3 +310,19 @@ impl From for WinitTheme { } } } + +#[derive(ConfigDeserialize, Default, Debug, Clone, Copy, PartialEq, Eq)] +pub enum WindowLevel { + #[default] + Normal, + AlwaysOnTop, +} + +impl From for WinitWindowLevel { + fn from(level: WindowLevel) -> Self { + match level { + WindowLevel::Normal => WinitWindowLevel::Normal, + WindowLevel::AlwaysOnTop => WinitWindowLevel::AlwaysOnTop, + } + } +} diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 3d6989a0..1f1e7402 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -169,7 +169,8 @@ impl Window { .with_transparent(true) .with_blur(config.window.blur) .with_maximized(config.window.maximized()) - .with_fullscreen(config.window.fullscreen()); + .with_fullscreen(config.window.fullscreen()) + .with_window_level(config.window.level.into()); let window = event_loop.create_window(window_attributes)?; diff --git a/extra/man/alacritty.5.scd b/extra/man/alacritty.5.scd index fa0edaaf..18172487 100644 --- a/extra/man/alacritty.5.scd +++ b/extra/man/alacritty.5.scd @@ -195,6 +195,17 @@ This section documents the *[window]* table of the configuration file. Default: _"None"_ +*level* = _"Normal"_ | _"AlwaysOnTop"_ + + Sets window level. + + *Normal* + Window adheres to system's default z-order. + *AlwaysOnTop* + Window is a toplevel window. + + Default: _"Normal"_ + Example: *[window]*++ padding = { x = _3_, y = _3_ }++ From 1be20fbe4a556598f1b7335f56f5350853652ce5 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 28 Nov 2024 15:54:07 +0300 Subject: [PATCH 095/102] Fix recursion limit not working for toml migrate --- CHANGELOG.md | 1 + alacritty/src/migrate/mod.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e78e82ba..15bdaa2b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Mouse/Vi cursor hint highlighting broken on the terminal cursor line - Hint launcher opening arbitrary text, when terminal content changed while opening - `SemanticRight`/`SemanticLeft` vi motions breaking with wide semantic escape characters +- `alacritty migrate` crashing with recursive toml imports ## 0.14.0 diff --git a/alacritty/src/migrate/mod.rs b/alacritty/src/migrate/mod.rs index 42b51d27..ffba25f0 100644 --- a/alacritty/src/migrate/mod.rs +++ b/alacritty/src/migrate/mod.rs @@ -151,7 +151,7 @@ fn migrate_imports( // 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)?; + let migration = migrate_config(options, &normalized_path, recursion_limit - 1)?; if options.dry_run { println!("{}", migration.success_message(true)); } From 713e89a6c50ce461fc91245463974635f4940772 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Thu, 28 Nov 2024 16:07:41 +0300 Subject: [PATCH 096/102] Don't error on nonexistent TOML imports in migrate YAML import migration was already properly ignoring nonexistent imports, it was only missed for TOML ones. Fixes #8330. --- CHANGELOG.md | 1 + alacritty/src/migrate/mod.rs | 8 ++++++++ 2 files changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 15bdaa2b..ed471ce7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - Hint launcher opening arbitrary text, when terminal content changed while opening - `SemanticRight`/`SemanticLeft` vi motions breaking with wide semantic escape characters - `alacritty migrate` crashing with recursive toml imports +- Migrating nonexistent toml import breaking the entire migration ## 0.14.0 diff --git a/alacritty/src/migrate/mod.rs b/alacritty/src/migrate/mod.rs index ffba25f0..bfa72294 100644 --- a/alacritty/src/migrate/mod.rs +++ b/alacritty/src/migrate/mod.rs @@ -151,6 +151,14 @@ fn migrate_imports( // Migrate each import. for import in imports.into_iter().filter_map(|item| item.as_str()) { let normalized_path = config::normalize_import(path, import); + + if !normalized_path.exists() { + if options.dry_run { + println!("Skipping migration for nonexistent path: {}", normalized_path.display()); + } + continue; + } + let migration = migrate_config(options, &normalized_path, recursion_limit - 1)?; if options.dry_run { println!("{}", migration.success_message(true)); From 8731d157be4e49713587325f29099579d637a06a Mon Sep 17 00:00:00 2001 From: Integral Date: Tue, 10 Dec 2024 06:04:43 +0800 Subject: [PATCH 097/102] Remove unnecessary statics --- alacritty/src/display/window.rs | 2 +- alacritty/src/renderer/rects.rs | 4 ++-- alacritty/src/renderer/text/gles2.rs | 4 ++-- alacritty/src/renderer/text/glsl3.rs | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index 1f1e7402..1c8089bc 100644 --- a/alacritty/src/display/window.rs +++ b/alacritty/src/display/window.rs @@ -44,7 +44,7 @@ use crate::display::SizeInfo; /// Window icon for `_NET_WM_ICON` property. #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] -static WINDOW_ICON: &[u8] = include_bytes!("../../extra/logo/compat/alacritty-term.png"); +const WINDOW_ICON: &[u8] = include_bytes!("../../extra/logo/compat/alacritty-term.png"); /// This should match the definition of IDI_ICON from `alacritty.rc`. #[cfg(windows)] diff --git a/alacritty/src/renderer/rects.rs b/alacritty/src/renderer/rects.rs index ca2d1852..5ec2f1ef 100644 --- a/alacritty/src/renderer/rects.rs +++ b/alacritty/src/renderer/rects.rs @@ -228,8 +228,8 @@ impl RenderLines { } /// Shader sources for rect rendering program. -static RECT_SHADER_F: &str = include_str!("../../res/rect.f.glsl"); -static RECT_SHADER_V: &str = include_str!("../../res/rect.v.glsl"); +const RECT_SHADER_F: &str = include_str!("../../res/rect.f.glsl"); +const RECT_SHADER_V: &str = include_str!("../../res/rect.v.glsl"); #[repr(C)] #[derive(Debug, Clone, Copy)] diff --git a/alacritty/src/renderer/text/gles2.rs b/alacritty/src/renderer/text/gles2.rs index 8756ea80..f14fa7ba 100644 --- a/alacritty/src/renderer/text/gles2.rs +++ b/alacritty/src/renderer/text/gles2.rs @@ -20,8 +20,8 @@ use super::{ }; // Shader source. -static TEXT_SHADER_F: &str = include_str!("../../../res/gles2/text.f.glsl"); -static TEXT_SHADER_V: &str = include_str!("../../../res/gles2/text.v.glsl"); +const TEXT_SHADER_F: &str = include_str!("../../../res/gles2/text.f.glsl"); +const TEXT_SHADER_V: &str = include_str!("../../../res/gles2/text.v.glsl"); #[derive(Debug)] pub struct Gles2Renderer { diff --git a/alacritty/src/renderer/text/glsl3.rs b/alacritty/src/renderer/text/glsl3.rs index fee95ce3..8cf06784 100644 --- a/alacritty/src/renderer/text/glsl3.rs +++ b/alacritty/src/renderer/text/glsl3.rs @@ -20,8 +20,8 @@ use super::{ }; // Shader source. -pub static TEXT_SHADER_F: &str = include_str!("../../../res/glsl3/text.f.glsl"); -static TEXT_SHADER_V: &str = include_str!("../../../res/glsl3/text.v.glsl"); +pub const TEXT_SHADER_F: &str = include_str!("../../../res/glsl3/text.f.glsl"); +const TEXT_SHADER_V: &str = include_str!("../../../res/glsl3/text.v.glsl"); /// Maximum items to be drawn in a batch. const BATCH_MAX: usize = 0x1_0000; From 39daaffff9c694d3aa54d1a749cd2523341509d9 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Mon, 16 Dec 2024 16:53:04 +0000 Subject: [PATCH 098/102] Apply non-breaking dependency bumps This fixes a GitHub security alert about hashbrown, which has no significant impact on Alacritty but still seems wise to fix since it's so simple. --- Cargo.lock | 187 +++++++++++++++++++++++++++-------------------------- 1 file changed, 94 insertions(+), 93 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 17db267f..b9be9b7e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -143,9 +143,9 @@ checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" [[package]] name = "anstream" -version = "0.6.17" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -264,15 +264,15 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.19.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8334215b81e418a0a7bdb8ef0849474f40bb10c8b71f1c4ed315cff49f32494d" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" [[package]] name = "bytes" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "calloop" @@ -302,9 +302,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.34" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67b9470d453346108f93a59222a9a1a5724db32d0a4727b7ab7ace4b4d822dc9" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" dependencies = [ "jobserver", "libc", @@ -340,9 +340,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97f376d85a664d5837dbae44bf546e6477a679ff6610010f17276f686d867e8" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -350,9 +350,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.20" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc80abd44e4bed93ca373a0704ccbd1b710dc5749406201bb018272808dc54" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -362,9 +362,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.36" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86bc73de94bc81e52f3bebec71bc4463e9748f7a59166663e32044669577b0e2" +checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01" dependencies = [ "clap", ] @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.2" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clipboard-win" @@ -651,9 +651,9 @@ dependencies = [ [[package]] name = "embed-resource" -version = "2.5.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4e24052d7be71f0efb50c201557f6fe7d237cfd5a64fd5bcd7fd8fe32dbbffa" +checksum = "b68b6f9f63a0b6a38bc447d4ce84e2b388f3ec95c99c641c8ff0dd3ef89a6379" dependencies = [ "cc", "memchr", @@ -671,25 +671,25 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.9" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "fastrand" -version = "2.1.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8c02a5121d4ea3eb16a80748c74f5549a5665e4c21333c6098f283870fbdea6" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fdeflate" -version = "0.3.6" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] @@ -708,9 +708,9 @@ dependencies = [ [[package]] name = "flate2" -version = "1.0.34" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1b589b4dc103969ad3cf85c950899926ec64300a1a46d76c03a6072957036f0" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -868,9 +868,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" @@ -895,9 +895,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.6.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -931,9 +931,9 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.11" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jni" @@ -968,10 +968,11 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1015,15 +1016,15 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.161" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libloading" -version = "0.8.5" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", "windows-targets 0.52.6", @@ -1037,7 +1038,7 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", ] [[package]] @@ -1461,7 +1462,7 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.7", + "redox_syscall 0.5.8", "smallvec", "windows-targets 0.52.6", ] @@ -1517,9 +1518,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" -version = "0.17.14" +version = "0.17.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" +checksum = "b67582bd5b65bdff614270e2ea89a1cf15bef71245cc1e5f7ea126977144211d" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -1530,9 +1531,9 @@ dependencies = [ [[package]] name = "polling" -version = "3.7.3" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", @@ -1554,9 +1555,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.89" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] @@ -1596,9 +1597,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.7" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ "bitflags 2.6.0", ] @@ -1616,9 +1617,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -1642,16 +1643,16 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.38" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa260229e6538e52293eeb577aabd09945a09d6d9cc0fc550ed7529056c2e32a" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ "bitflags 2.6.0", "errno", "itoa", "libc", "linux-raw-sys", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -1706,24 +1707,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.23" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" -version = "1.0.214" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.214" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -1732,9 +1733,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.132" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", "memchr", @@ -1869,9 +1870,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.87" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25aa4ce346d03a6dcd68dd8b4010bcb74e54e62c90c573f394c46eae99aba32d" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -1880,9 +1881,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", @@ -1893,18 +1894,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d171f59dbaa811dbbb1aee1e73db92ec2b122911a48e1390dfe327a821ddede" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.66" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b08be0f17bd307950653ce45db00cd31200d82b624b36e181337d9c7d92765b5" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -1972,9 +1973,9 @@ dependencies = [ [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ "pin-project-lite", "tracing-core", @@ -1982,15 +1983,15 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "e672c95779cf947c5311f83787af4fa8fffd12fb27e4993211a84bdfd9610f9c" [[package]] name = "unicode-ident" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" @@ -2084,9 +2085,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", "once_cell", @@ -2095,13 +2096,12 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -2110,21 +2110,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.45" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -2132,9 +2133,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", @@ -2145,9 +2146,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.95" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wayland-backend" @@ -2260,9 +2261,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.72" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6488b90108c040df0fe62fa815cbdee25124641df01814dd7282749234c6112" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -2679,9 +2680,9 @@ checksum = "b9cc00251562a284751c9973bace760d86c0276c471b4be569fe6b068ee97a56" [[package]] name = "xml-rs" -version = "0.8.22" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af4e2e2f7cba5a093896c1e150fbfe177d1883e7448200efb81d40b9d339ef26" +checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" [[package]] name = "yeslogic-fontconfig-sys" From 8591a9421d0a100af16cd50b4610bc55506fb14f Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Fri, 20 Dec 2024 03:51:36 +0300 Subject: [PATCH 099/102] Always explicitly emit `1` without modifiers in kitty encoding While this doesn't change much with how parsers are implemented, it improves consistency with how key release is handled. --- CHANGELOG.md | 1 + alacritty/src/input/keyboard.rs | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed471ce7..86637383 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -48,6 +48,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 +- Always emit `1` for the first parameter when having modifiers in kitty keyboard protocol ### Fixed diff --git a/alacritty/src/input/keyboard.rs b/alacritty/src/input/keyboard.rs index 14755594..85734109 100644 --- a/alacritty/src/input/keyboard.rs +++ b/alacritty/src/input/keyboard.rs @@ -280,7 +280,7 @@ fn build_sequence(key: KeyEvent, mods: ModifiersState, mode: TermMode) -> Vec Option { + fn try_build_named_normal( + &self, + key: &KeyEvent, + has_associated_text: bool, + ) -> Option { let named = match key.logical_key { Key::Named(named) => named, _ => return None, }; // The default parameter is 1, so we can omit it. - let one_based = if self.modifiers.is_empty() && !self.kitty_event_type { "" } else { "1" }; + let one_based = + if self.modifiers.is_empty() && !self.kitty_event_type && !has_associated_text { + "" + } else { + "1" + }; let (base, terminator) = match named { NamedKey::PageUp => ("5", SequenceTerminator::Normal('~')), NamedKey::PageDown => ("6", SequenceTerminator::Normal('~')), From def2d488de558d5a3af18f3c2c78852bb1421764 Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sat, 21 Dec 2024 19:00:26 +0300 Subject: [PATCH 100/102] Bump winit to 0.30.6 Fixes #8268. --- CHANGELOG.md | 1 + Cargo.lock | 4 ++-- alacritty/Cargo.toml | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86637383..f2ca2761 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -70,6 +70,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - 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 +- Crash when pressing certain modifier keys on macOS 15+ ## 0.13.2 diff --git a/Cargo.lock b/Cargo.lock index b9be9b7e..00cd99d7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2526,9 +2526,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.30.5" +version = "0.30.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0be9e76a1f1077e04a411f0b989cbd3c93339e1771cb41e71ac4aee95bfd2c67" +checksum = "7c3d72dfa0f47e429290cd0d236884ca02f22dbd5dd33a43ad2b8bf4d79b6c18" dependencies = [ "ahash", "android-activity", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 264ecbc6..f7280deb 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -41,7 +41,7 @@ tempfile = "3.12.0" toml = "0.8.2" toml_edit = "0.22.21" unicode-width = "0.1" -winit = { version = "0.30.5", default-features = false, features = ["rwh_06", "serde"] } +winit = { version = "0.30.6", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] gl_generator = "0.14.0" From 39a7834e57bf8f3181fa517061d588bf39339fbc Mon Sep 17 00:00:00 2001 From: Kirill Chibisov Date: Sun, 22 Dec 2024 23:30:30 +0300 Subject: [PATCH 101/102] Bump winit to 0.30.7 Fixes double input on X11 after update to 0.30.6. --- Cargo.lock | 4 ++-- alacritty/Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 00cd99d7..23325812 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2526,9 +2526,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.30.6" +version = "0.30.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3d72dfa0f47e429290cd0d236884ca02f22dbd5dd33a43ad2b8bf4d79b6c18" +checksum = "dba50bc8ef4b6f1a75c9274fb95aa9a8f63fbc66c56f391bd85cf68d51e7b1a3" dependencies = [ "ahash", "android-activity", diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index f7280deb..eff0b089 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -41,7 +41,7 @@ tempfile = "3.12.0" toml = "0.8.2" toml_edit = "0.22.21" unicode-width = "0.1" -winit = { version = "0.30.6", default-features = false, features = ["rwh_06", "serde"] } +winit = { version = "0.30.7", default-features = false, features = ["rwh_06", "serde"] } [build-dependencies] gl_generator = "0.14.0" From d45eca8268eea0a1bba58dae5cc4b70c2482c7c4 Mon Sep 17 00:00:00 2001 From: Christian Duerr Date: Sun, 22 Dec 2024 21:05:45 +0000 Subject: [PATCH 102/102] Fix window options for initial daemon window This fixes an issue with daemon mode where the first spawned window would not use the window options passed to the `create-window` subcommand, but would instead use the options passed during creation of the original daemon. Closes #8371. --- CHANGELOG.md | 1 + alacritty/src/event.rs | 40 +++++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f2ca2761..94672511 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,7 @@ Notable changes to the `alacritty_terminal` crate are documented in its - `SemanticRight`/`SemanticLeft` vi motions breaking with wide semantic escape characters - `alacritty migrate` crashing with recursive toml imports - Migrating nonexistent toml import breaking the entire migration +- First daemon mode window ignoring window options passed through CLI ## 0.14.0 diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index e82d7974..79f31eef 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -140,14 +140,14 @@ impl Processor { pub fn create_initial_window( &mut self, event_loop: &ActiveEventLoop, + window_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)?; + let window_context = WindowContext::initial( + event_loop, + self.proxy.clone(), + self.config.clone(), + window_options, + )?; self.gl_config = Some(window_context.display.gl_context().config()); self.windows.insert(window_context.id(), window_context); @@ -225,10 +225,12 @@ impl ApplicationHandler for Processor { return; } - if let Err(err) = self.create_initial_window(event_loop) { - self.initial_window_error = Some(err); - event_loop.exit(); - return; + if let Some(window_options) = self.initial_window_options.take() { + if let Err(err) = self.create_initial_window(event_loop, window_options) { + self.initial_window_error = Some(err); + event_loop.exit(); + return; + } } info!("Initialisation complete"); @@ -276,7 +278,7 @@ impl ApplicationHandler for Processor { } // Handle events which don't mandate the WindowId. - match (&event.payload, event.window_id.as_ref()) { + match (event.payload, event.window_id.as_ref()) { // Process IPC config update. #[cfg(unix)] (EventType::IpcConfig(ipc_config), window_id) => { @@ -315,7 +317,7 @@ impl ApplicationHandler for Processor { } // Load config and update each terminal. - if let Ok(config) = config::reload(path, &mut self.cli_options) { + if let Ok(config) = config::reload(&path, &mut self.cli_options) { self.config = Rc::new(config); // Restart config monitor if imports changed. @@ -346,17 +348,17 @@ impl ApplicationHandler for Processor { if self.gl_config.is_none() { // Handle initial window creation in daemon mode. - if let Err(err) = self.create_initial_window(event_loop) { + if let Err(err) = self.create_initial_window(event_loop, options) { self.initial_window_error = Some(err); event_loop.exit(); } - } else if let Err(err) = self.create_window(event_loop, options.clone()) { + } else if let Err(err) = self.create_window(event_loop, options) { error!("Could not open window: {:?}", err); } }, // Process events affecting all windows. - (_, None) => { - let event = WinitEvent::UserEvent(event); + (payload, None) => { + let event = WinitEvent::UserEvent(Event::new(payload, None)); for window_context in self.windows.values_mut() { window_context.handle_event( #[cfg(target_os = "macos")] @@ -405,7 +407,7 @@ impl ApplicationHandler for Processor { } } }, - (_, Some(window_id)) => { + (payload, Some(window_id)) => { if let Some(window_context) = self.windows.get_mut(window_id) { window_context.handle_event( #[cfg(target_os = "macos")] @@ -413,7 +415,7 @@ impl ApplicationHandler for Processor { &self.proxy, &mut self.clipboard, &mut self.scheduler, - WinitEvent::UserEvent(event), + WinitEvent::UserEvent(Event::new(payload, *window_id)), ); } },