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 1da1fa4c..c65e7f82 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,24 +14,24 @@ jobs: runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Stable run: cargo test - name: Stable (no default features) run: cargo test -p alacritty_terminal --no-default-features - name: Oldstable run: | - rustup default 1.76.0 + rustup default $(cat alacritty/Cargo.toml | grep "rust-version" | sed 's/.*"\(.*\)".*/\1/') cargo test - name: Clippy 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 + - uses: actions/checkout@v4 - 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 1db8a4d7..c9578ded 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 + - uses: actions/checkout@v4 - 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 @@ -37,7 +37,7 @@ jobs: shell: bash steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Test run: cargo test --release - name: Build @@ -48,10 +48,10 @@ jobs: ./.github/workflows/upload_asset.sh \ ./Chartacritty-${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 "./Chartacritty-${GITHUB_REF##*/}-installer.msi" "alacritty/windows/wix/alacritty.wxs" - name: Upload msi installer @@ -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 \ diff --git a/CHANGELOG.md b/CHANGELOG.md index 7d0bc36f..94672511 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,75 @@ 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/). -## 0.14.0-dev +Notable changes to the `alacritty_terminal` crate are documented in its +[CHANGELOG](./alacritty_terminal/CHANGELOG.md). + +## 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 + +### Fixed + +- 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 +- Migrating nonexistent toml import breaking the entire migration +- First daemon mode window ignoring window options passed through CLI + +## 0.14.0 + +### Packaging + +- Minimum Rust version has been bumped to 1.74.0 + +### Added + +- Support relative path imports from config files +- `alacritty migrate` support for TOML configuration changes +- Headless mode using `alacritty --daemon` + +### Changed + +- Pressing `Alt` with unicode input will now add `ESC` like for ASCII input +- Decorations use opaque style and system window background on macOS +- No longer source `~/.zshenv` on macOS +- Moved config options `import`, `working_directory`, `live_config_reload`, and `ipc_socket` + to the new `general` section +- Moved config option `shell` to `terminal.shell` +- `ctrl+shift+u` binding to open links to `ctrl+shift+o` to avoid collisions with IMEs +- Use `Beam` cursor for single char cursor inside the IME preview +- Always emit `1` for the first parameter when having modifiers in kitty keyboard protocol + +### Fixed + +- 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 +- 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 nonexistent import paths +- Kitty keyboard protocol reporting shifted key codes +- Broken search with words broken across line boundary on the first character +- Config import changes not being live reloaded +- Cursor color requests with default cursor colors +- Fullwidth semantic escape characters +- Windows app icon now displays properly in old alt+tab on Windows +- Alacritty not being properly activated with startup notify +- Invalid URL highlights after terminal scrolling +- Hollow block cursor not spanning multiple chars being edited inside the IME preview +- Vi inline search only working for direct key input without modifiers +- Crash when pressing certain modifier keys on macOS 15+ + +## 0.13.2 ### Added @@ -18,6 +86,16 @@ 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 +- 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 +- 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 +- Kitty encoding used for regular keys when they don't carry text ### Changed @@ -285,7 +363,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - 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 @@ -309,7 +387,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - 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` @@ -475,7 +553,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 @@ -641,7 +719,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - 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 @@ -849,7 +927,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - 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 @@ -919,7 +997,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ### 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 334a3e76..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) @@ -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. @@ -90,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 008d584d..bc818202 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,27 +4,27 @@ version = 3 [[package]] name = "addr2line" -version = "0.21.0" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" dependencies = [ "gimli", ] [[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" -version = "0.8.6" +version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ "cfg-if", - "getrandom 0.2.11", + "getrandom 0.2.15", "once_cell", "version_check", "zerocopy", @@ -32,16 +32,16 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.2" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" dependencies = [ "memchr", ] [[package]] name = "alacritty_config" -version = "0.2.1-dev" +version = "0.2.3-dev" dependencies = [ "alacritty_config_derive", "log", @@ -51,7 +51,7 @@ dependencies = [ [[package]] name = "alacritty_config_derive" -version = "0.2.3-dev" +version = "0.2.5-dev" dependencies = [ "alacritty_config", "log", @@ -64,10 +64,10 @@ dependencies = [ [[package]] name = "alacritty_terminal" -version = "0.22.1-dev" +version = "0.24.2-dev" dependencies = [ - "base64", - "bitflags 2.4.1", + "base64 0.22.1", + "bitflags 2.6.0", "bytes", "chrono", "env_logger", @@ -100,17 +100,17 @@ dependencies = [ "tracing-log", "unicode-width", "vte", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "android-activity" -version = "0.5.1" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39b801912a977c3fd52d80511fe1c0c8480c6f957f21ae2ce1b92ffe970cf4b9" +checksum = "ef6978589202a00cd7e118380c448a08b6ed394c3a8df3a430d0898e3a42d046" dependencies = [ "android-properties", - "bitflags 2.4.1", + "bitflags 2.6.0", "cc", "cesu8", "jni", @@ -147,9 +147,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" dependencies = [ "anstyle", "anstyle-parse", @@ -162,36 +162,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.4" +version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87" +checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" [[package]] name = "anstyle-parse" -version = "0.2.3" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.0.0" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.1" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -205,15 +205,15 @@ dependencies = [ [[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" @@ -227,43 +227,38 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" -[[package]] -name = "atty" -version = "0.2.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" -dependencies = [ - "hermit-abi 0.1.19", - "libc", - "winapi", -] - [[package]] name = "autocfg" -version = "1.1.0" +version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", "miniz_oxide", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] name = "base64" -version = "0.21.5" +version = "0.21.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" +checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" [[package]] name = "bitflags" @@ -273,9 +268,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.4.1" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -286,50 +281,52 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-sys" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dd7cf50912cddc06dc5ea7c08c5e81c1b2c842a70d19def1848d54c586fed92" -dependencies = [ - "objc-sys", -] - [[package]] name = "block2" -version = "0.3.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15b55663a85f33501257357e6421bb33e769d5c9ffb5ba0921c975a123e35e68" +checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" dependencies = [ - "block-sys", "objc2", ] [[package]] name = "bumpalo" -version = "3.14.0" +version = "3.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "by_address" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64fa3c856b712db6612c019f14756e64e4bcea13337a6b33b696333a9eaa2d06" [[package]] name = "bytemuck" -version = "1.14.0" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374d28ec25809ee0e23827c2ab573d729e293f281dfe393500e7ad618baa61c6" +checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" [[package]] -name = "bytes" +name = "byteorder" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" + +[[package]] +name = "bytes" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" [[package]] name = "calloop" -version = "0.12.3" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b50b5a44d59a98c55a9eeb518f39bf7499ba19fd98ee7d22618687f3f10adbf" +checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "log", "polling", "rustix", @@ -339,9 +336,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", @@ -351,12 +348,13 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.83" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0" +checksum = "9157bbaa6b165880c27a4293a474c91cdcf265cc68cc829bf10be0964a391caf" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -373,9 +371,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "cfg_aliases" -version = "0.1.1" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" [[package]] name = "cgl" @@ -388,16 +386,15 @@ dependencies = [ [[package]] name = "chartacritty" -version = "0.14.0-dev" +version = "0.15.0-dev" dependencies = [ "ahash", "alacritty_config", "alacritty_config_derive", "alacritty_terminal", - "bitflags 2.4.1", + "bitflags 2.6.0", "clap", "clap_complete", - "cocoa", "copypasta", "crossfont", "dirs", @@ -410,26 +407,29 @@ dependencies = [ "log", "lyon", "notify", - "objc", + "objc2", + "objc2-app-kit", + "objc2-foundation", "parking_lot", "png", - "raw-window-handle", "serde", "serde_json", "serde_yaml", + "tempfile", "tokio", "toml", + "toml_edit", "unicode-width", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "winit", "xdg", ] [[package]] name = "chrono" -version = "0.4.33" +version = "0.4.39" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f13690e35a5e4ace198e7beea2895d29f3a9cc55015fcebe6336bd2010af9eb" +checksum = "7e36cc9d416881d2e24f9a963be5fb1cd90966419ac844274161d10488b3e825" dependencies = [ "android-tzdata", "iana-time-zone", @@ -437,14 +437,14 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] name = "clap" -version = "4.4.11" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfaff671f6b22ca62406885ece523383b9b64022e341e53e009a62ebc47a45f2" +checksum = "3135e7ec2ef7b10c6ed8950f0f792ed96ee093fa088608f1c76e569722700c84" dependencies = [ "clap_builder", "clap_derive", @@ -452,9 +452,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.4.11" +version = "4.5.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a216b506622bb1d316cd51328dce24e07bdff4a6128a47c7e7fad11878d5adbb" +checksum = "30582fc632330df2bd26877bde0c1f4470d57c582bbc070376afcd04d8cb4838" dependencies = [ "anstream", "anstyle", @@ -464,18 +464,18 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.4.4" +version = "4.5.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bffe91f06a11b4b9420f62103854e90867812cd5d01557f853c5ee8e791b12ae" +checksum = "d9647a559c112175f17cf724dc72d3645680a883c58481332779192b0d8e7a01" dependencies = [ "clap", ] [[package]] name = "clap_derive" -version = "4.4.7" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -485,9 +485,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.6.0" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1" +checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6" [[package]] name = "clipboard-win" @@ -499,15 +499,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" @@ -540,15 +531,15 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.0" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[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", @@ -556,18 +547,18 @@ 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", ] [[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", @@ -589,15 +580,15 @@ dependencies = [ [[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" -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", @@ -631,37 +622,33 @@ dependencies = [ [[package]] name = "crc32fast" -version = "1.3.2" +version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b540bd8bc810d3885c6ea91e2018302f68baba2129ab3e88f32389ee9370880d" +checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ "cfg-if", ] [[package]] name = "crossbeam-channel" -version = "0.5.10" +version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82a9b73a36529d9c47029b9fb3a6f0ea3cc916a261195352ba19e770fc1748b2" +checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "cfg-if", "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.18" +version = "0.8.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c" -dependencies = [ - "cfg-if", -] +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" [[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", @@ -676,8 +663,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]] @@ -716,6 +713,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "displaydoc" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "dlib" version = "0.5.2" @@ -727,15 +735,24 @@ dependencies = [ [[package]] name = "downcast-rs" -version = "1.2.0" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" + +[[package]] +name = "dpi" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ea835d29036a4087793836fa931b08837ad5e957da9e23886b29586fb9b6650" +checksum = "f25c0e292a7ca6d6498557ff1df68f32c99850012b6ea401cf8daf771f22ff53" +dependencies = [ + "serde", +] [[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", @@ -747,37 +764,48 @@ dependencies = [ [[package]] name = "embed-resource" -version = "2.4.0" +version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f54cc3e827ee1c3812239a9a41dede7b4d7d5d5464faa32d71bd7cba28ce2cb2" +checksum = "b68b6f9f63a0b6a38bc447d4ce84e2b388f3ec95c99c641c8ff0dd3ef89a6379" dependencies = [ "cc", + "memchr", "rustc_version", "toml", "vswhom", - "winreg 0.51.0", + "winreg 0.52.0", ] [[package]] name = "encoding_rs" -version = "0.8.33" +version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ "cfg-if", ] +[[package]] +name = "env_filter" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186e05a59d4c50738528153b83b0b0194d3a29507dfec16eccd4b342903397d0" +dependencies = [ + "log", + "regex", +] + [[package]] name = "env_logger" -version = "0.7.1" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +checksum = "dcaee3d8e3cfc3fd92428d477bc97fc29ec8716d180c0d74c643bb26166660e0" dependencies = [ - "atty", + "anstream", + "anstyle", + "env_filter", "humantime", "log", - "regex", - "termcolor", ] [[package]] @@ -788,34 +816,24 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.7" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "euclid" -version = "0.22.9" +version = "0.22.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f253bc5c813ca05792837a0ff4b3a580336b224512d48f7eda1d7dd9210787" +checksum = "ad9cdb4b747e485a12abb0e6566612956c7a1bafa3bdb8d682c5b6d403589e48" dependencies = [ "num-traits", "serde", ] -[[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 = "fast-srgb8" version = "1.0.0" @@ -824,36 +842,36 @@ checksum = "dd2e7510819d6fbf51a5545c8f922716ecfb14df168a3242f7d33e0239efe6a1" [[package]] name = "fastrand" -version = "2.0.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" [[package]] name = "fdeflate" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "209098dd6dfc4445aa6111f0e98653ac323eaa4dfd212c9ca3931bf9955c31bd" +checksum = "1e6853b52649d4ac5c0bd02320cddc5ba956bdb407c4b75a2c6b75bf51500f8c" dependencies = [ "simd-adler32", ] [[package]] name = "filetime" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4029edd3e734da6fe05b6cd7bd2960760a616bd2ddd0d59a0124746d6272af0" +checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.3.5", - "windows-sys 0.48.0", + "libredox", + "windows-sys 0.59.0", ] [[package]] name = "flate2" -version = "1.0.28" +version = "1.0.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46303f565772937ffe1d394a4fac6f411c6013172fadde9dcdb1e147a086940e" +checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" dependencies = [ "crc32fast", "miniz_oxide", @@ -924,22 +942,22 @@ dependencies = [ [[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.6.0", "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", ] @@ -955,9 +973,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "645c6916888f6cb6350d2550b80fb63e734897a8498abe35cfb732b6487804b0" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" dependencies = [ "futures-channel", "futures-core", @@ -970,9 +988,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eac8f7d7865dcb88bd4373ab671c8cf4508703796caa2b1985a9ca867b3fcb78" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" dependencies = [ "futures-core", "futures-sink", @@ -980,15 +998,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" [[package]] name = "futures-executor" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a576fc72ae164fca6b9db127eaa9a9dda0d61316034f33a0a0d4eda41f02b01d" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" dependencies = [ "futures-core", "futures-task", @@ -997,15 +1015,15 @@ 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 = "futures-macro" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", @@ -1014,21 +1032,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" [[package]] name = "futures-task" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38d84fa142264698cdce1a9f9172cf383a0c82de1bddcf3092901442c4097004" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" [[package]] name = "futures-util" -version = "0.3.30" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6401deb83407ab3da39eba7e33987a73c3df0c82b4bb5813ee871c19c41d48" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" dependencies = [ "futures-channel", "futures-core", @@ -1042,16 +1060,6 @@ dependencies = [ "slab", ] -[[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" @@ -1075,9 +1083,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.11" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ "cfg-if", "libc", @@ -1086,9 +1094,9 @@ dependencies = [ [[package]] name = "gimli" -version = "0.28.1" +version = "0.31.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] name = "gl_generator" @@ -1103,11 +1111,11 @@ dependencies = [ [[package]] name = "glutin" -version = "0.31.2" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "005459a22af86adc706522d78d360101118e2638ec21df3852fcc626e0dbb212" +checksum = "ec69412a0bf07ea7607e638b415447857a808846c2b685a43c8aa18bc6d5e499" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "cfg_aliases", "cgl", "core-foundation", @@ -1115,31 +1123,32 @@ dependencies = [ "glutin_egl_sys", "glutin_glx_sys", "glutin_wgl_sys", - "icrate", "libloading", "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", @@ -1147,9 +1156,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", ] @@ -1175,45 +1184,36 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.14.3" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f1a1d9242c78d09ce40a5e87e7554ee637af1351968159f4952f028f75604" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" [[package]] name = "heck" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" - -[[package]] -name = "hermit-abi" -version = "0.1.19" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" -dependencies = [ - "libc", -] +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "hermit-abi" -version = "0.3.5" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0c62115964e08cb8039170eb33c1d0e2388a256930279edca206fff675f82c3" +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 = "http" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" +checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" dependencies = [ "bytes", "fnv", @@ -1233,9 +1233,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" [[package]] name = "httpdate" @@ -1245,18 +1245,15 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" [[package]] name = "humantime" -version = "1.3.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" -dependencies = [ - "quick-error", -] +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.28" +version = "0.14.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +checksum = "41dfc780fdec9373c01bae43289ea34c972e40ee3c9f6b3c8801a35f35586ce7" dependencies = [ "bytes", "futures-channel", @@ -1291,9 +1288,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.60" +version = "0.1.61" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7ffbb5a1b541ea2561f8c41c087286cc091e21e556a4f09a8f6cbf17b69b141" +checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -1313,31 +1310,149 @@ dependencies = [ ] [[package]] -name = "icrate" -version = "0.0.4" +name = "icu_collections" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d3aaff8a54577104bafdf686ff18565c3b6903ca5782a2026ef06e2c7aa319" +checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" dependencies = [ - "block2", - "dispatch", - "objc2", + "displaydoc", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_locid" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" +dependencies = [ + "displaydoc", + "litemap", + "tinystr", + "writeable", + "zerovec", +] + +[[package]] +name = "icu_locid_transform" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_locid_transform_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_locid_transform_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" + +[[package]] +name = "icu_normalizer" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_normalizer_data", + "icu_properties", + "icu_provider", + "smallvec", + "utf16_iter", + "utf8_iter", + "write16", + "zerovec", +] + +[[package]] +name = "icu_normalizer_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" + +[[package]] +name = "icu_properties" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" +dependencies = [ + "displaydoc", + "icu_collections", + "icu_locid_transform", + "icu_properties_data", + "icu_provider", + "tinystr", + "zerovec", +] + +[[package]] +name = "icu_properties_data" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" + +[[package]] +name = "icu_provider" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" +dependencies = [ + "displaydoc", + "icu_locid", + "icu_provider_macros", + "stable_deref_trait", + "tinystr", + "writeable", + "yoke", + "zerofrom", + "zerovec", +] + +[[package]] +name = "icu_provider_macros" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" +dependencies = [ + "proc-macro2", + "quote", + "syn", ] [[package]] name = "idna" -version = "0.5.0" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" +dependencies = [ + "idna_adapter", + "smallvec", + "utf8_iter", +] + +[[package]] +name = "idna_adapter" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" dependencies = [ - "unicode-bidi", - "unicode-normalization", + "icu_normalizer", + "icu_properties", ] [[package]] name = "indexmap" -version = "2.1.0" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d530e1a18b1cb4c484e6e34556a0d948706958449fca0cab753d649f2bce3d1f" +checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", "hashbrown", @@ -1365,9 +1480,9 @@ dependencies = [ [[package]] name = "ipnet" -version = "2.9.0" +version = "2.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" +checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708" [[package]] name = "is_terminal_polyfill" @@ -1377,9 +1492,9 @@ checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itoa" -version = "1.0.10" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" [[package]] name = "jni" @@ -1405,19 +1520,20 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.27" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] [[package]] name = "js-sys" -version = "0.3.66" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" +checksum = "6717b6b5b077764fb5966237269cb3c64edddde4b14ce42647430a78ced9e7b7" dependencies = [ + "once_cell", "wasm-bindgen", ] @@ -1455,65 +1571,60 @@ 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.151" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "libloading" -version = "0.8.1" +version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161" +checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-sys 0.48.0", + "windows-targets 0.52.6", ] [[package]] name = "libm" -version = "0.2.8" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" +checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" [[package]] name = "libredox" -version = "0.0.1" +version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85c833ca1e66078851dba29046874e38f08b2c883700aa29a03ddd3b23814ee8" +checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "libc", - "redox_syscall 0.4.1", + "redox_syscall 0.5.8", ] [[package]] -name = "libredox" -version = "0.0.2" +name = "linux-raw-sys" +version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3af92c55d7d839293953fcd0fda5ecfe93297cfde6ffbdec13b41d99c0ba6607" -dependencies = [ - "bitflags 2.4.1", - "libc", - "redox_syscall 0.4.1", -] +checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] -name = "linux-raw-sys" -version = "0.4.12" +name = "litemap" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4cd1a83af159aa67994778be9070f0ae1bd732942279cabb14f86f986a21456" +checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" [[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", @@ -1521,9 +1632,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.20" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" dependencies = [ "serde", ] @@ -1540,9 +1651,9 @@ dependencies = [ [[package]] name = "lyon_algorithms" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3bca95f9a4955b3e4a821fbbcd5edfbd9be2a9a50bb5758173e5358bfb4c623" +checksum = "f13c9be19d257c7d37e70608ed858e8eab4b2afcea2e3c9a622e892acbf43c08" dependencies = [ "lyon_path", "num-traits", @@ -1550,9 +1661,9 @@ dependencies = [ [[package]] name = "lyon_geom" -version = "1.0.5" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edecfb8d234a2b0be031ab02ebcdd9f3b9ee418fb35e265f7a540a48d197bff9" +checksum = "8af69edc087272df438b3ee436c4bb6d7c04aa8af665cfd398feae627dbd8570" dependencies = [ "arrayvec", "euclid", @@ -1562,9 +1673,9 @@ dependencies = [ [[package]] name = "lyon_path" -version = "1.0.4" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca507745ba7ccbc76e5c44e7b63b1a29d2b0d6126f375806a5bbaf657c7d6c45" +checksum = "8e0b8aec2f58586f6eef237985b9a9b7cb3a3aff4417c575075cf95bf925252e" dependencies = [ "lyon_geom", "num-traits", @@ -1573,9 +1684,9 @@ dependencies = [ [[package]] name = "lyon_tessellation" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8c7c67b5bc8123b352b2e7e742b47d1f236a13fe77619433be9568fbd888e9c0" +checksum = "579d42360a4b09846eff2feef28f538696c7d6c7439bfa65874ff3cbe0951b2c" dependencies = [ "float_next_after", "lyon_path", @@ -1594,28 +1705,19 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "memmap2" -version = "0.9.3" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45fd3a57831bf88bc63f8cebc0cf956116276e97fef3966103e96416209f7c92" +checksum = "fd3f7eed9d3848f8b98834af67102b720745c4ec028fcd0aa0239277e7de374f" 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 = "mime" version = "0.3.17" @@ -1624,11 +1726,11 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "miniz_oxide" -version = "0.7.1" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7810e0be55b428ada41041c41f32c9f1a42817901b4ccf45fa3d4b6561e74c7" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" dependencies = [ - "adler", + "adler2", "simd-adler32", ] @@ -1644,6 +1746,17 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi 0.11.0+wasi-snapshot-preview1", + "windows-sys 0.52.0", +] + [[package]] name = "miow" version = "0.6.0" @@ -1661,11 +1774,10 @@ checksum = "7984c1e5817a8e5559d0e7719e766b52048ced9553d932cdfd094f82ea7b79cd" [[package]] name = "native-tls" -version = "0.2.11" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07226173c32f2926027b63cce4bcd8076c3552846cbe7925f3aaffeac0a3b92e" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ - "lazy_static", "libc", "log", "openssl", @@ -1679,11 +1791,11 @@ 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.1", + "bitflags 2.6.0", "jni-sys", "log", "ndk-sys", @@ -1700,25 +1812,13 @@ 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", ] -[[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 = "noise" version = "0.8.2" @@ -1736,7 +1836,7 @@ version = "6.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6205bd8bb1e454ad2e27422015fb5e4f2bcc7e08fa8f27058670d208324a4d2d" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "crossbeam-channel", "filetime", "fsevent-sys", @@ -1744,45 +1844,35 @@ dependencies = [ "kqueue", "libc", "log", - "mio", + "mio 0.8.11", "walkdir", "windows-sys 0.48.0", ] [[package]] name = "num-traits" -version = "0.2.18" +version = "0.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0df0e5185db44f69b44f26786fe401b6c293d1907744beaa7fa62b2e5a517a" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", "libm", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi 0.3.5", - "libc", -] - [[package]] name = "num_enum" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683751d591e6d81200c39fb0d1032608b77724f34114db54f571ff1317b337c0" +checksum = "4e613fc340b2220f734a8595782c551f1250e969d87d3be1ae0579e8d4065179" dependencies = [ "num_enum_derive", ] [[package]] name = "num_enum_derive" -version = "0.7.1" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c11e44798ad209ccdd91fc192f0526a369a01234f7373e1b141c96d7cee4f0e" +checksum = "af1844ef2428cc3e1cb900be36181049ef3d3193c63e43026cfe202983b27a56" dependencies = [ "proc-macro-crate", "proc-macro2", @@ -1812,25 +1902,206 @@ dependencies = [ [[package]] name = "objc-sys" -version = "0.3.2" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7c71324e4180d0899963fc83d9d241ac39e699609fc1025a850aadac8257459" +checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" [[package]] name = "objc2" -version = "0.4.1" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "559c5a40fdd30eb5e344fbceacf7595a81e242529fb4e21cf5f43fb4f11ff98d" +checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" dependencies = [ "objc-sys", "objc2-encode", ] +[[package]] +name = "objc2-app-kit" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +dependencies = [ + "bitflags 2.6.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.6.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.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +dependencies = [ + "bitflags 2.6.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 = "3.0.0" +version = "4.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7891e71393cd1f227313c9379a26a584ff3d7e6e7159e988851f0934c993f0f8" + +[[package]] +name = "objc2-foundation" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +dependencies = [ + "bitflags 2.6.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.6.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.6.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.6.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 = "d079845b37af429bfe5dfa76e6d087d788031045b25cfc6fd898486fd9847666" +checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +dependencies = [ + "bitflags 2.6.0", + "block2", + "objc2", + "objc2-core-location", + "objc2-foundation", +] [[package]] name = "objc_id" @@ -1843,26 +2114,26 @@ dependencies = [ [[package]] name = "object" -version = "0.32.2" +version = "0.36.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" dependencies = [ "memchr", ] [[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 = "openssl" -version = "0.10.66" +version = "0.10.68" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" +checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "cfg-if", "foreign-types 0.3.2", "libc", @@ -1890,9 +2161,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.103" +version = "0.9.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" +checksum = "45abf306cbf99debc8195b66b7346498d7b10c210de50418b5ccd7ceba08c741" dependencies = [ "cc", "libc", @@ -1908,18 +2179,18 @@ 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]] name = "palette" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d38e6e5ca1612e2081cc31188f08c3cba630ce4ba44709a153f1a0f38d678f2" +checksum = "4cbf71184cc5ecc2e4e1baccdb21026c20e5fc3dcf63028a086131b3ab00b6e6" dependencies = [ "approx", "fast-srgb8", @@ -1930,10 +2201,11 @@ dependencies = [ [[package]] name = "palette_derive" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e05d1c929301fee6830dafa764341118829b2535c216b0571e3821ecac5c885b" +checksum = "f5030daf005bface118c096f510ffb781fc28f9ab6a32ab224d8631be6851d30" dependencies = [ + "by_address", "proc-macro2", "quote", "syn", @@ -1941,9 +2213,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", @@ -1951,15 +2223,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.8", "smallvec", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -2005,16 +2277,36 @@ dependencies = [ name = "phf_shared" version = "0.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +checksum = "90fcb95eef784c2ac79119d1dd819e162b5da872ce6f3c3abe1e8ca1c082f72b" +dependencies = [ + "siphasher", +] + +[[package]] +name = "pin-project" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ - "siphasher", + "proc-macro2", + "quote", + "syn", ] [[package]] name = "pin-project-lite" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8afb450f006bf6385ca15ef45d71d2288452bc3683ce2e2cacc0d18e4be60b58" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -2024,9 +2316,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "piper" -version = "0.2.1" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "668d31b1c4eba19242f2088b2bf3316b82ca31082a8335764db4e083db7485d4" +checksum = "96c8c490f422ef9a4efd2cb5b42b76c8613d7e7dfc1caf667b8a3350a5acc066" dependencies = [ "atomic-waker", "fastrand", @@ -2035,15 +2327,15 @@ dependencies = [ [[package]] name = "pkg-config" -version = "0.3.28" +version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69d3587f8a9e599cc7ec2c00e331f71c4e69a5f9a4b8a6efd5b07466b9736f9a" +checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" [[package]] name = "png" -version = "0.17.10" +version = "0.17.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd75bf2d8dd3702b9707cdbc56a5b9ef42cec752eb8b3bafc01234558442aa64" +checksum = "b67582bd5b65bdff614270e2ea89a1cf15bef71245cc1e5f7ea126977144211d" dependencies = [ "bitflags 1.3.2", "crc32fast", @@ -2054,62 +2346,60 @@ dependencies = [ [[package]] name = "polling" -version = "3.3.0" +version = "3.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e53b6af1f60f36f8c2ac2aad5459d75a5a9b4be1e8cdd40264f315d78193e531" +checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f" dependencies = [ "cfg-if", "concurrent-queue", + "hermit-abi", "pin-project-lite", "rustix", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" +dependencies = [ + "zerocopy", +] [[package]] name = "proc-macro-crate" -version = "2.0.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e8366a6159044a37876a2b9817124296703c586a5c92e2c53751fa06d8d43e8" +checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" dependencies = [ - "toml_edit 0.20.7", + "toml_edit", ] [[package]] name = "proc-macro2" -version = "1.0.71" +version = "1.0.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75cb1540fadbd5b8fbccc4dddad2734eba435053f725621c070711a14bb5f4b8" +checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" dependencies = [ "unicode-ident", ] -[[package]] -name = "quick-error" -version = "1.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" - [[package]] name = "quick-xml" -version = "0.31.0" +version = "0.36.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1004a344b30a54e2ee58d66a71b32d2db2feb0a31f9a2d302bf0536f15de2a33" +checksum = "f7649a7b4df05aed9ea7ec6f628c67c9953a43869b8bc50929569b2999d443fe" dependencies = [ "memchr", ] [[package]] name = "quote" -version = "1.0.33" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2173,7 +2463,7 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" dependencies = [ - "getrandom 0.2.11", + "getrandom 0.2.15", ] [[package]] @@ -2196,44 +2486,44 @@ 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" -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.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", ] [[package]] name = "redox_users" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a18479200779601e498ada4e8c1e1f50e3ee19deb0259c25825a98b5603b2cb4" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" dependencies = [ - "getrandom 0.2.11", - "libredox 0.0.1", + "getrandom 0.2.15", + "libredox", "thiserror", ] [[package]] name = "regex" -version = "1.10.2" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -2243,9 +2533,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.3" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" +checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" dependencies = [ "aho-corasick", "memchr", @@ -2254,17 +2544,17 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.8.2" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" [[package]] name = "reqwest" -version = "0.11.24" +version = "0.11.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6920094eb85afde5e4a138be3f2de8bbdf28000f0029e72c45025a56b042251" +checksum = "dd67538700a17451e7cba03ac727fb961abb7607553461627b97de0b89cf4a62" dependencies = [ - "base64", + "base64 0.21.7", "bytes", "encoding_rs", "futures-core", @@ -2300,31 +2590,31 @@ dependencies = [ [[package]] name = "rustc-demangle" -version = "0.1.23" +version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" [[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.25" +version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" +checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "errno", "itoa", "libc", "linux-raw-sys", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -2344,14 +2634,14 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64", + "base64 0.21.7", ] [[package]] name = "ryu" -version = "1.0.16" +version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "same-file" @@ -2364,11 +2654,11 @@ dependencies = [ [[package]] name = "schannel" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +checksum = "1f29ebaa345f945cec9fbbc532eb307f0fdad8161f281b6369539c8d84876b3d" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -2385,9 +2675,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sctk-adwaita" -version = "0.8.1" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b2eaf3a5b264a521b988b2e73042e742df700c4f962cde845d1541adb46550" +checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" dependencies = [ "crossfont", "log", @@ -2397,11 +2687,11 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.9.2" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -2410,9 +2700,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.9.1" +version = "2.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" +checksum = "1863fd3768cd83c56a7f60faa4dc0d403f1b6df0a38c3c25f44b7894e45370d5" dependencies = [ "core-foundation-sys", "libc", @@ -2420,24 +2710,24 @@ dependencies = [ [[package]] name = "semver" -version = "1.0.20" +version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090" +checksum = "3cb6eb87a131f756572d7fb904f6e7b68633f09cca868c5df1c4b8d1a694bbba" [[package]] name = "serde" -version = "1.0.193" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25dd9975e68d0cb5aa1120c288333fc98731bd1dd12f561e468ea4728c042b89" +checksum = "0b9781016e935a97e8beecf0c933758c97a5520d32930e460142b4cd80c6338e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.193" +version = "1.0.216" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43576ca501357b9b071ac53cdc7da8ef0cbd9493d8df094cd821777ea6e894d3" +checksum = "46f859dbbf73865c6627ed570e78961cd3ac92407a2d117204c49232485da55e" dependencies = [ "proc-macro2", "quote", @@ -2446,20 +2736,21 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.108" +version = "1.0.133" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b" +checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" dependencies = [ "itoa", + "memchr", "ryu", "serde", ] [[package]] name = "serde_spanned" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb3622f419d1296904700073ea6cc23ad690adbd66f13ea683df73298736f0c1" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" dependencies = [ "serde", ] @@ -2478,9 +2769,9 @@ dependencies = [ [[package]] name = "serde_yaml" -version = "0.9.29" +version = "0.9.34+deprecated" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a15e0ef66bf939a7c890a0bf6d5a733c70202225f9888a89ed5c62298b019129" +checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" dependencies = [ "indexmap", "itoa", @@ -2490,25 +2781,10 @@ dependencies = [ ] [[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" +name = "shlex" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e36b879db9892dfa40f95da1c38a835d41634b825fbd8c4c418093d53c24b388" -dependencies = [ - "expat-sys", - "freetype-sys", - "pkg-config", -] +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" [[package]] name = "signal-hook" @@ -2522,9 +2798,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", ] @@ -2552,17 +2828,17 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.2" +version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" [[package]] name = "smithay-client-toolkit" -version = "0.18.0" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60e3d9941fa3bacf7c2bf4b065304faa14164151254cd16ce1b1bc8fc381600f" +checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "calloop", "calloop-wayland-source", "cursor-icon", @@ -2583,9 +2859,9 @@ dependencies = [ [[package]] name = "smithay-clipboard" -version = "0.7.0" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb62b280ce5a5cba847669933a0948d00904cf83845c944eae96a4738cea1a6" +checksum = "cc8216eec463674a0e90f29e0ae41a4db573ec5b56b1c6c1c71615d249b6d846" dependencies = [ "libc", "smithay-client-toolkit", @@ -2594,23 +2870,29 @@ dependencies = [ [[package]] name = "smol_str" -version = "0.2.0" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.5.5" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b5fac59a5cb5dd637972e5fca70daf0523c9067fcdc4842f053dae04a18f8e9" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "strict-num" version = "0.1.1" @@ -2619,15 +2901,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.43" +version = "2.0.90" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee659fb5f3d355364e1f3e5bc10fb82068efbf824a1e9d1c9504244a6469ad53" +checksum = "919d3b74a5dd0ccd15aeb8f93e7006bd9e14c295087c9896a110f490752bcf31" dependencies = [ "proc-macro2", "quote", @@ -2640,6 +2922,17 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "synstructure" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "system-configuration" version = "0.5.1" @@ -2663,40 +2956,31 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.8.1" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" +checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.4.1", + "once_cell", "rustix", - "windows-sys 0.48.0", -] - -[[package]] -name = "termcolor" -version = "1.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" -dependencies = [ - "winapi-util", + "windows-sys 0.59.0", ] [[package]] name = "thiserror" -version = "1.0.52" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83a48fd946b02c0a526b2e9481c8e2a17755e47039164a86c4070446e3a4614d" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.52" +version = "1.0.69" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e7fbe9b594d6568a6a1443250a7e67d80b74e1e96f6d1715e1e21cc1888291d3" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" dependencies = [ "proc-macro2", "quote", @@ -2705,9 +2989,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", @@ -2719,9 +3003,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", @@ -2729,44 +3013,38 @@ dependencies = [ ] [[package]] -name = "tinyvec" -version = "1.6.0" +name = "tinystr" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" dependencies = [ - "tinyvec_macros", + "displaydoc", + "zerovec", ] -[[package]] -name = "tinyvec_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" - [[package]] name = "tokio" -version = "1.36.0" +version = "1.42.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61285f6515fa018fb2d1e46eb21223fff441ee8db5d0f1435e8ab4f5cdb80931" +checksum = "5cec9b21b0450273377fc97bd4c33a8acffc8c996c987a7c5b319a0083707551" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.3", "parking_lot", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] name = "tokio-macros" -version = "2.2.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b8a1e28f2deaa14e508979454cb3a223b10b938b45af148bc0986de36f1923b" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", @@ -2785,55 +3063,43 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.10" +version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +checksum = "d7fcaa8d55a2bdd6b83ace262b016eca0d79ee02818c5c1bcdf0305114081078" dependencies = [ "bytes", "futures-core", "futures-sink", "pin-project-lite", "tokio", - "tracing", ] [[package]] name = "toml" -version = "0.8.8" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a195ec8c9da26928f773888e0742ca3ca1040c6cd859c919c9f59c1954ab35" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.21.0", + "toml_edit", ] [[package]] name = "toml_datetime" -version = "0.6.5" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3550f4e9685620ac18a50ed434eb3aec30db8ba93b0287467bca5826ea25baf1" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] [[package]] name = "toml_edit" -version = "0.20.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70f427fce4d84c72b5b732388bf4a9f4531b53f74e2887e3ecb2481f68f66d81" -dependencies = [ - "indexmap", - "toml_datetime", - "winnow", -] - -[[package]] -name = "toml_edit" -version = "0.21.0" +version = "0.22.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d34d383cd00a163b4a5b85053df514d45bc330f6de7737edfe0a93311d1eaa03" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" dependencies = [ "indexmap", "serde", @@ -2844,15 +3110,15 @@ dependencies = [ [[package]] name = "tower-service" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" [[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 = [ "log", "pin-project-lite", @@ -2862,9 +3128,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "395ae124c09f9e6918a2310af6038fba074bcf474ac352496d5910dd59a2226d" dependencies = [ "proc-macro2", "quote", @@ -2873,9 +3139,9 @@ 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" dependencies = [ "once_cell", "valuable", @@ -2898,61 +3164,58 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" -[[package]] -name = "unicode-bidi" -version = "0.3.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" - [[package]] name = "unicode-ident" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" - -[[package]] -name = "unicode-normalization" -version = "0.1.22" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c5713f0fc4b5db668a2ac63cdb7bb4469d8c9fed047b1d0292cc7b0ce2ba921" -dependencies = [ - "tinyvec", -] +checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" [[package]] name = "unicode-segmentation" -version = "1.10.1" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" [[package]] name = "unicode-width" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" +checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af" [[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 = "url" -version = "2.5.0" +version = "2.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" +checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" dependencies = [ "form_urlencoded", "idna", "percent-encoding", ] +[[package]] +name = "utf16_iter" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" + +[[package]] +name = "utf8_iter" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" + [[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 = "valuable" @@ -2968,9 +3231,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[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" @@ -2998,7 +3261,7 @@ version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40eb22ae96f050e0c0d6f7ce43feeae26c348fc4dea56928ca81537cfaa6188b" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "cursor-icon", "log", "serde", @@ -3008,9 +3271,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", @@ -3018,9 +3281,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", @@ -3049,23 +3312,23 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.89" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" +checksum = "a474f6281d1d70c17ae7aa6a613c87fce69a127e2624002df63dcb39d6cf6396" dependencies = [ "cfg-if", + "once_cell", "wasm-bindgen-macro", ] [[package]] name = "wasm-bindgen-backend" -version = "0.2.89" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" +checksum = "5f89bb38646b4f81674e8f5c3fb81b562be1fd936d84320f3264486418519c79" dependencies = [ "bumpalo", "log", - "once_cell", "proc-macro2", "quote", "syn", @@ -3074,21 +3337,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.39" +version = "0.4.49" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac36a15a220124ac510204aec1c3e5db8a22ab06fd6706d881dc6149f8ed9a12" +checksum = "38176d9b44ea84e9184eff0bc34cc167ed044f816accfe5922e54d84cf48eca2" dependencies = [ "cfg-if", "js-sys", + "once_cell", "wasm-bindgen", "web-sys", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.89" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" +checksum = "2cc6181fd9a7492eef6fef1f33961e3695e4579b9872a6f7c83aee556666d4fe" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -3096,9 +3360,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.89" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" +checksum = "30d7a95b763d3c45903ed6c81f156801839e5ee968bb07e534c44df0fcd330c2" dependencies = [ "proc-macro2", "quote", @@ -3109,15 +3373,15 @@ dependencies = [ [[package]] name = "wasm-bindgen-shared" -version = "0.2.89" +version = "0.2.99" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" +checksum = "943aab3fdaaa029a6e0271b35ea10b72b943135afe9bffca82384098ad0e06a6" [[package]] name = "wayland-backend" -version = "0.3.3" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d50fa61ce90d76474c87f5fc002828d81b32677340112b4ef08079a9d459a40" +checksum = "056535ced7a150d45159d3a8dc30f91a2e2d588ca0b23f70e56033622b8016f6" dependencies = [ "cc", "downcast-rs", @@ -3129,11 +3393,11 @@ dependencies = [ [[package]] name = "wayland-client" -version = "0.31.2" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fb96ee935c2cea6668ccb470fb7771f6215d1691746c2d896b447a00ad3f1f" +checksum = "b66249d3fc69f76fd74c82cc319300faa554e9d865dab1f7cd66cc20db10b280" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "rustix", "wayland-backend", "wayland-scanner", @@ -3145,16 +3409,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "cursor-icon", "wayland-backend", ] [[package]] name = "wayland-cursor" -version = "0.31.1" +version = "0.31.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71ce5fa868dd13d11a0d04c5e2e65726d0897be8de247c0c5a65886e283231ba" +checksum = "32b08bc3aafdb0035e7fe0fdf17ba0c09c268732707dca4ae098f60cb28c9e4c" dependencies = [ "rustix", "wayland-client", @@ -3163,11 +3427,11 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.31.2" +version = "0.32.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +checksum = "7cd0ade57c4e6e9a8952741325c30bf82f4246885dca8bf561898b86d0c1f58e" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-scanner", @@ -3175,11 +3439,11 @@ dependencies = [ [[package]] name = "wayland-protocols-plasma" -version = "0.2.0" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23803551115ff9ea9bce586860c5c5a971e360825a0309264102a9495a5ff479" +checksum = "9b31cab548ee68c7eb155517f2212049dc151f7cd7910c2b66abfd31c3ee12bd" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -3188,11 +3452,11 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.2.0" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +checksum = "782e12f6cd923c3c316130d56205ebab53f55d6666b7faddfad36cecaeeb4022" dependencies = [ - "bitflags 2.4.1", + "bitflags 2.6.0", "wayland-backend", "wayland-client", "wayland-protocols", @@ -3201,9 +3465,9 @@ dependencies = [ [[package]] name = "wayland-scanner" -version = "0.31.1" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b3a62929287001986fb58c789dce9b67604a397c15c611ad9f747300b6c283" +checksum = "597f2001b2e5fc1121e3d5b9791d3e78f05ba6bfa4641053846248e3a13661c3" dependencies = [ "proc-macro2", "quick-xml", @@ -3212,9 +3476,9 @@ dependencies = [ [[package]] name = "wayland-sys" -version = "0.31.1" +version = "0.31.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15a0c8eaff5216d07f226cb7a549159267f3467b289d9a2e52fd3ef5aae2b7af" +checksum = "efa8ac0d8e8ed3e3b5c9fc92c7881406a268e11555abe36493efabe649a29e09" dependencies = [ "dlib", "log", @@ -3224,9 +3488,9 @@ dependencies = [ [[package]] name = "web-sys" -version = "0.3.66" +version = "0.3.76" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c24a44ec86bb68fbecd1b3efed7e85ea5621b39b35ef2766b66cd984f8010f" +checksum = "04dd7223427d52553d3702c004d3b2fe07c148165faa56313cb00211e31c12bc" dependencies = [ "js-sys", "wasm-bindgen", @@ -3234,9 +3498,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", @@ -3260,20 +3524,11 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" -dependencies = [ - "winapi", -] - -[[package]] -name = "winapi-wsapoll" -version = "0.1.1" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c17110f57155602a80dca10be03852116403c9ff3cd25b079d666f2aa3df6e" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" dependencies = [ - "winapi", + "windows-sys 0.59.0", ] [[package]] @@ -3288,7 +3543,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.6", ] [[package]] @@ -3315,7 +3570,16 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "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]] @@ -3350,17 +3614,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "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.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -3377,9 +3642,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -3395,9 +3660,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -3413,9 +3678,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -3431,9 +3702,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -3449,9 +3720,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -3467,9 +3738,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -3485,44 +3756,48 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winit" -version = "0.29.9" +version = "0.30.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2376dab13e09c01ad8b679f0dbc7038af4ec43d9a91344338e37bd686481550" +checksum = "dba50bc8ef4b6f1a75c9274fb95aa9a8f63fbc66c56f391bd85cf68d51e7b1a3" dependencies = [ "ahash", "android-activity", "atomic-waker", - "bitflags 2.4.1", + "bitflags 2.6.0", + "block2", "bytemuck", "calloop", "cfg_aliases", + "concurrent-queue", "core-foundation", "core-graphics", "cursor-icon", - "icrate", + "dpi", "js-sys", "libc", - "log", "memmap2", "ndk", - "ndk-sys", "objc2", - "once_cell", + "objc2-app-kit", + "objc2-foundation", + "objc2-ui-kit", "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", @@ -3532,17 +3807,17 @@ dependencies = [ "wayland-protocols-plasma", "web-sys", "web-time", - "windows-sys 0.48.0", + "windows-sys 0.52.0", "x11-dl", - "x11rb 0.13.0", + "x11rb", "xkbcommon-dl", ] [[package]] name = "winnow" -version = "0.5.30" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b5c3db89721d50d0e2a673f5043fc4722f76dcc352d7b1ab8b8288bed4ed2c5" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" dependencies = [ "memchr", ] @@ -3559,9 +3834,9 @@ dependencies = [ [[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", @@ -3576,13 +3851,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "write16" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" + +[[package]] +name = "writeable" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" + [[package]] name = "x11-clipboard" -version = "0.8.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41aca1115b1f195f21c541c5efb423470848d48143127d0f07f8b90c27440df" +checksum = "662d74b3d77e396b8e5beb00b9cad6a9eccf40b2ef68cc858784b14c41d535a3" dependencies = [ - "x11rb 0.12.0", + "libc", + "x11rb", ] [[package]] @@ -3598,52 +3886,30 @@ dependencies = [ [[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" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8f25ead8c7e4cba123243a6367da5d3990e0d3affa708ea19dce96356bd9f1a" +checksum = "5d91ffca73ee7f68ce055750bf9f6eca0780b8c85eff9bc046a3b0da41755e12" 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]] 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" -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" @@ -3653,11 +3919,11 @@ 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", + "bitflags 2.6.0", "dlib", "log", "once_cell", @@ -3666,30 +3932,110 @@ 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.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ea8b391c9a790b496184c29f7f93b9ed5b16abb306c05415b68bcc16e4d06432" + +[[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 = "yoke" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" +dependencies = [ + "serde", + "stable_deref_trait", + "yoke-derive", + "zerofrom", +] + +[[package]] +name = "yoke-derive" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" +checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] [[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 = [ + "byteorder", "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 = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "zerofrom" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" +dependencies = [ + "zerofrom-derive", +] + +[[package]] +name = "zerofrom-derive" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "synstructure", +] + +[[package]] +name = "zerovec" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" +dependencies = [ + "yoke", + "zerofrom", + "zerovec-derive", +] + +[[package]] +name = "zerovec-derive" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" +checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" dependencies = [ "proc-macro2", "quote", 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 diff --git a/alacritty/Cargo.toml b/alacritty/Cargo.toml index 484c8ddc..ae1daa9e 100644 --- a/alacritty/Cargo.toml +++ b/alacritty/Cargo.toml @@ -1,25 +1,30 @@ [package] name = "chartacritty" -version = "0.14.0-dev" -authors = ["Christian Duerr ", "Joe Wilm ", "Seb Ospina "] +version = "0.15.0-dev" +authors = [ + "Christian Duerr ", + "Joe Wilm ", + "Seb Ospina ", +] license = "Apache-2.0" description = "Alacritty plus prometheus metrics, charts and decorations" readme = "README.md" homepage = "https://github.com/sebosp/chartacritty" +repository = "https://github.com/sebosp/chartacritty" edition = "2021" -rust-version = "1.70.0" +rust-version = "1.74.0" [dependencies.alacritty_terminal] path = "../alacritty_terminal" -version = "0.22.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] tokio = { version = "1.28", features = ["full"] } @@ -28,21 +33,28 @@ lyon = "1.0" 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 } -crossfont = { version = "0.7.0", features = ["force_system_fontconfig"] } -glutin = { version = "0.31.1", default-features = false, features = ["egl", "wgl"] } +copypasta = { version = "0.10.1", default-features = false } +crossfont = "0.8.0" +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 = { 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.29.9", default-features = false, features = ["rwh_05", "serde"] } +winit = { version = "0.30.7", default-features = false, features = [ + "rwh_06", + "serde", +] } [build-dependencies] gl_generator = "0.14.0" @@ -57,30 +69,35 @@ xdg = "2.5.0" png = { version = "0.17.5", default-features = false, optional = true } [target.'cfg(target_os = "macos")'.dependencies] -cocoa = "0.25.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" -windows-sys = { version = "0.48", features = [ +windows-sys = { version = "0.52", features = [ "Win32_UI_WindowsAndMessaging", "Win32_System_Threading", "Win32_System_Console", "Win32_Foundation", -]} +] } [target.'cfg(windows)'.build-dependencies] embed-resource = "2.2.0" [features] default = ["wayland", "x11"] -x11 = [ - "copypasta/x11", - "winit/x11", - "glutin/x11", - "glutin/glx", - "png", -] +x11 = ["copypasta/x11", "winit/x11", "glutin/x11", "glutin/glx", "png"] wayland = [ "copypasta/wayland", "glutin/wayland", diff --git a/alacritty/src/cli.rs b/alacritty/src/cli.rs index cd97e2e7..bb0a24f4 100644 --- a/alacritty/src/cli.rs +++ b/alacritty/src/cli.rs @@ -1,11 +1,12 @@ use std::cmp::max; +use std::collections::HashMap; use std::ops::{Deref, DerefMut}; use std::path::PathBuf; 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; @@ -25,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). @@ -61,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, @@ -87,11 +92,10 @@ 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.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()); @@ -195,6 +199,7 @@ impl From for PtyOptions { working_directory: options.working_directory.take(), shell: options.command().map(Into::into), hold: options.hold, + env: HashMap::new(), } } } @@ -215,10 +220,10 @@ impl WindowIdentity { /// Override the [`WindowIdentity`]'s fields with the [`WindowOptions`]. pub fn override_identity_config(&self, identity: &mut Identity) { if let Some(title) = &self.title { - identity.title = title.clone(); + identity.title.clone_from(title); } if let Some(class) = &self.class { - identity.class = class.clone(); + identity.class.clone_from(class); } } } @@ -423,19 +428,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(); @@ -520,4 +512,35 @@ mod tests { let value = parse_hex_or_decimal("0xa0xx0d"); assert_eq!(value, None); } + + #[cfg(target_os = "linux")] + #[test] + fn completions() { + let mut clap = Options::command(); + + for (shell, file) in &[ + (Shell::Bash, "alacritty.bash"), + (Shell::Fish, "alacritty.fish"), + (Shell::Zsh, "_alacritty"), + ] { + let mut generated = Vec::new(); + clap_complete::generate(*shell, &mut clap, "alacritty", &mut generated); + let generated = String::from_utf8_lossy(&generated); + + let mut completion = String::new(); + let mut file = File::open(format!("../extra/completions/{file}")).unwrap(); + file.read_to_string(&mut completion).unwrap(); + + assert_eq!(generated, completion); + } + + // NOTE: Use this to generate new completions. + // + // let mut file = File::create("../extra/completions/alacritty.bash").unwrap(); + // clap_complete::generate(Shell::Bash, &mut clap, "alacritty", &mut file); + // let mut file = File::create("../extra/completions/alacritty.fish").unwrap(); + // clap_complete::generate(Shell::Fish, &mut clap, "alacritty", &mut file); + // let mut file = File::create("../extra/completions/_alacritty").unwrap(); + // clap_complete::generate(Shell::Zsh, &mut clap, "alacritty", &mut file); + } } diff --git a/alacritty/src/clipboard.rs b/alacritty/src/clipboard.rs index b3818c75..7853de47 100644 --- a/alacritty/src/clipboard.rs +++ b/alacritty/src/clipboard.rs @@ -1,9 +1,8 @@ use log::{debug, warn}; -use raw_window_handle::RawDisplayHandle; +use winit::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; @@ -24,16 +23,15 @@ 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(), } } - /// 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/config/bindings.rs b/alacritty/src/config/bindings.rs index 9a63047a..11610145 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)] @@ -290,7 +291,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:?}"), } } } @@ -793,7 +794,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 { @@ -847,7 +848,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 { @@ -959,7 +960,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 { @@ -1027,8 +1028,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}" ))); }, }, @@ -1083,8 +1083,7 @@ impl<'a> Deserialize<'a> for RawBinding { _ => return Err(err), }; return Err(V::Error::custom(format!( - "unknown keyboard action `{}`", - value + "unknown keyboard action `{value}`" ))); }, } @@ -1125,8 +1124,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 @@ -1210,7 +1208,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/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 a3b049d0..c5d32f85 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; @@ -47,9 +48,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), @@ -69,7 +67,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(), @@ -82,14 +79,13 @@ 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) + 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}"), } } } @@ -102,11 +98,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) } } @@ -182,6 +174,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) @@ -213,7 +209,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)) } @@ -245,9 +241,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}"); @@ -266,13 +267,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) }, @@ -282,14 +282,15 @@ fn load_imports(config: &Value, config_paths: &mut Vec, recursion_limit 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()), @@ -303,7 +304,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())); @@ -311,17 +312,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); - } + let normalized = normalize_import(base_path, path); - import_paths.push(Ok(path)); + import_paths.push(Ok(normalized)); } Ok(import_paths) } +/// Normalize import paths. +pub fn normalize_import(base_config_path: &Path, import_path: impl Into) -> PathBuf { + let mut import_path = import_path.into(); + + // Resolve paths relative to user's home directory. + if let (Ok(stripped), Some(home_dir)) = (import_path.strip_prefix("~/"), home::home_dir()) { + import_path = home_dir.join(stripped); + } + + if import_path.is_relative() { + if let Some(base_config_dir) = base_config_path.parent() { + import_path = base_config_dir.join(import_path) + } + } + + import_path +} + /// Prune the nulls from the YAML to ensure TOML compatibility. fn prune_yaml_nulls(value: &mut serde_yaml::Value, warn_pruned: bool) { fn walk(value: &mut serde_yaml::Value, warn_pruned: bool) -> bool { diff --git a/alacritty/src/config/monitor.rs b/alacritty/src/config/monitor.rs index f4b39a22..3f73f120 100644 --- a/alacritty/src/config/monitor.rs +++ b/alacritty/src/config/monitor.rs @@ -1,9 +1,15 @@ +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; 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 +21,172 @@ 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>, + watched_hash: Option, +} - // 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); + // 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| { + // 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 }, - _ => (), - }, - 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; - }, - }; + }; + + 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); + } + }, + Ok(Err(err)) => { + debug!("Config watcher errors: {:?}", err); + }, + Err(err) => { + debug!("Config watcher channel dropped unexpectedly: {}", err); + break; + }, + }; + } + }); + + Some(Self { watched_hash, 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:?}"); + } + } + + /// Check if the config monitor needs to be restarted. + /// + /// This checks the supplied list of files against the monitored files to determine if a + /// restart is necessary. + pub fn needs_restart(&self, files: &[PathBuf]) -> bool { + Self::hash_paths(files).map_or(true, |hash| Some(hash) == self.watched_hash) + } + + /// Generate the hash for a list of paths. + fn hash_paths(files: &[PathBuf]) -> Option { + // Use file count limit to avoid allocations. + const MAX_PATHS: usize = 1024; + if files.len() > MAX_PATHS { + return None; + } + + // Sort files to avoid restart on order change. + let mut sorted_files = [None; MAX_PATHS]; + for (i, file) in files.iter().enumerate() { + sorted_files[i] = Some(file); } - }); + sorted_files.sort_unstable(); + + // Calculate hash for the paths, regardless of order. + let mut hasher = DefaultHasher::new(); + Hash::hash_slice(&sorted_files, &mut hasher); + Some(hasher.finish()) + } } diff --git a/alacritty/src/config/terminal.rs b/alacritty/src/config/terminal.rs index 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 f3f4ff7c..056b7faf 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}; @@ -28,7 +28,8 @@ use crate::config::cursor::Cursor; use crate::config::debug::Debug; use crate::config::decorations::Decorations; 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; @@ -40,8 +41,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, @@ -66,14 +70,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, @@ -87,78 +83,37 @@ 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, + /// Path to a shell program to run on startup. + #[config(deprecated = "use terminal.shell instead")] + shell: Option, - /// Keybindings. - #[config(deprecated = "use keyboard.bindings instead")] - key_bindings: Option, + #[config(deprecated = "use general.import instead")] + import: Option>, - /// Bindings for the mouse. - #[config(deprecated = "use mouse.bindings instead")] - mouse_bindings: Option, + /// Shell startup directory. + #[config(deprecated = "use general.working_directory instead")] + working_directory: 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, + /// 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, pub charts: Option, pub decorations: 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(), - charts: Default::default(), - decorations: Default::default(), - } - } -} - impl UiConfig { /// Derive [`TermConfig`] from the config. pub fn term_options(&self) -> TermConfig { @@ -174,21 +129,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 } + 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, @@ -203,7 +151,7 @@ impl UiConfig { action: Action::Hint(hint.clone()), }; - key_bindings.push(binding); + self.keyboard.bindings.0.push(binding); } } @@ -214,25 +162,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) } } @@ -309,7 +255,7 @@ pub struct Hints { alphabet: HintsAlphabet, /// All configured terminal hints. - pub enabled: Vec, + pub enabled: Vec>, } impl Default for Hints { @@ -330,7 +276,7 @@ impl Default for Hints { }); Self { - enabled: vec![Hint { + enabled: vec![Rc::new(Hint { content, action, persist: false, @@ -338,13 +284,13 @@ 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), mode: Default::default(), }), - }], + })], alphabet: Default::default(), } } @@ -502,7 +448,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", )); } @@ -675,7 +621,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/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/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/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 30439fc0..edd2709f 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, @@ -144,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. @@ -328,7 +334,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 +354,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, ) { @@ -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 { @@ -442,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 @@ -532,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/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/damage.rs b/alacritty/src/display/damage.rs index 450643b7..b0736375 100644 --- a/alacritty/src/display/damage.rs +++ b/alacritty/src/display/damage.rs @@ -189,6 +189,17 @@ 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 { + let start_line = &self.lines[start.line]; + let end_line = &self.lines[end.line]; + self.full + || (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()) + } } /// Convert viewport `y` coordinate to [`Rect`] damage coordinate. @@ -240,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 bd09a881..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); @@ -183,7 +185,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(); } } @@ -192,24 +194,26 @@ 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 { #[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] pub fn action(&self) -> &HintAction { - &self.action + &self.hint.action } #[inline] @@ -220,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. @@ -381,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 @@ -400,49 +423,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)) @@ -572,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/display/mod.rs b/alacritty/src/display/mod.rs index 0d40953f..7527906c 100644 --- a/alacritty/src/display/mod.rs +++ b/alacritty/src/display/mod.rs @@ -15,13 +15,13 @@ use glutin::surface::{Surface, SwapInterval, WindowSurface}; use log::{debug, error, 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::{self, Rasterize, Rasterizer, Size as FontSize}; +use crossfont::{Rasterize, Rasterizer, Size as FontSize}; use unicode_width::UnicodeWidthChar; use alacritty_terminal::event::{EventListener, OnResize, WindowSize}; @@ -30,8 +30,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}; @@ -365,9 +364,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, @@ -505,6 +508,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 { @@ -546,6 +553,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(), @@ -833,39 +842,37 @@ impl Display { } // 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_hint_highlights(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(); @@ -889,36 +896,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); @@ -973,7 +971,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())); } @@ -981,8 +981,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, + } }, }; @@ -1265,11 +1268,19 @@ 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.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; } @@ -1293,8 +1304,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; + self.highlighted_hint_age = 0; + + // Force full redraw if the mouse cursor highlight was changed. + if mouse_highlight_dirty { + self.damage_tracker.frame().mark_fully_damaged(); + } dirty } @@ -1321,8 +1339,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), @@ -1354,7 +1372,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); @@ -1365,19 +1383,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 }, @@ -1465,13 +1485,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); } @@ -1482,7 +1500,7 @@ impl Display { fn draw_search(&mut self, config: &UiConfig, text: &str) { // Assure text length is at least num_cols. let num_cols = self.size_info.columns(); - let text = format!("{:<1$}", text, num_cols); + let text = format!("{text: bool { - matches!(self.raw_window_handle, RawWindowHandle::Wayland(_)) || self.damage_tracker.debug - } - /// Highlight damaged rects. /// /// This function is for debug purposes only. @@ -1575,6 +1583,42 @@ impl Display { } } + /// Check whether a hint highlight needs to be cleared. + fn validate_hint_highlights(&mut self, display_offset: usize) { + let frame = self.damage_tracker.frame(); + 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 => 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(|| { + 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. @@ -1660,20 +1704,22 @@ pub struct Preedit { /// Byte offset for cursor start into the preedit text. /// /// `None` means that the cursor is invisible. - cursor_byte_offset: Option, + cursor_byte_offset: Option<(usize, usize)>, - /// The cursor offset from the end of the preedit in char width. - cursor_end_offset: Option, + /// The cursor offset from the end of the start of the preedit in char width. + cursor_end_offset: Option<(usize, usize)>, } impl Preedit { - pub fn new(text: String, cursor_byte_offset: Option) -> Self { + pub fn new(text: String, cursor_byte_offset: Option<(usize, usize)>) -> Self { let cursor_end_offset = if let Some(byte_offset) = cursor_byte_offset { // Convert byte offset into char offset. - let cursor_end_offset = - text[byte_offset..].chars().fold(0, |acc, ch| acc + ch.width().unwrap_or(1)); + let start_to_end_offset = + text[byte_offset.0..].chars().fold(0, |acc, ch| acc + ch.width().unwrap_or(1)); + let end_to_end_offset = + text[byte_offset.1..].chars().fold(0, |acc, ch| acc + ch.width().unwrap_or(1)); - Some(cursor_end_offset) + Some((start_to_end_offset, end_to_end_offset)) } else { None }; diff --git a/alacritty/src/display/window.rs b/alacritty/src/display/window.rs index be0f2a36..b6d8eab8 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, @@ -20,21 +20,20 @@ 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}, - winit::platform::macos::{OptionAsAlt, WindowBuilderExtMacOS, WindowExtMacOS}, + objc2_app_kit::{NSColorSpace, NSView}, + objc2_foundation::is_main_thread, + 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::platform::windows::{IconExtWindows, WindowAttributesExtWindows}; +use winit::raw_window_handle::{HasWindowHandle, RawWindowHandle}; use winit::window::{ CursorIcon, Fullscreen, ImePurpose, Theme, UserAttentionType, Window as WinitWindow, - WindowBuilder, WindowId, + WindowAttributes, WindowId, }; use alacritty_terminal::index::Point; @@ -45,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/chartacritty-term.png"); +const WINDOW_ICON: &[u8] = include_bytes!("../../extra/logo/compat/chartacritty-term.png"); /// This should match the definition of IDI_ICON from `alacritty.rc`. #[cfg(windows)] @@ -76,7 +75,7 @@ impl std::error::Error for Error { impl Display for Error { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { match self { - Error::WindowCreation(err) => write!(f, "Error creating GL context; {}", err), + Error::WindowCreation(err) => write!(f, "Error creating GL context; {err}"), Error::Font(err) => err.fmt(f), } } @@ -121,8 +120,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 +132,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 +142,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,10 +159,10 @@ 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) @@ -171,11 +170,13 @@ impl Window { .with_blur(config.window.blur) .with_maximized(config.window.maximized()) .with_fullscreen(config.window.fullscreen()) - .build(event_loop)?; + .with_window_level(config.window.level.into()); + + 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); @@ -189,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, @@ -205,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] @@ -223,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) { @@ -248,7 +255,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 +274,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 +286,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,12 +303,13 @@ 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()) + .with_window_icon(icon.as_ref().ok().cloned()) + .with_taskbar_icon(icon.ok()) } #[cfg(target_os = "macos")] @@ -309,8 +317,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); @@ -442,15 +451,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 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 _: id = msg_send![raw_window, setHasShadow: value]; - } + view.window().unwrap().setHasShadow(has_shadows); } /// Select tab at the given `index`. @@ -485,12 +494,15 @@ 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 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 _: () = msg_send![raw_window, setColorSpace: NSColorSpace::sRGBColorSpace(nil)]; + view.window().unwrap().setColorSpace(Some(&NSColorSpace::sRGBColorSpace())); } } diff --git a/alacritty/src/event.rs b/alacritty/src/event.rs index beded737..4b94221e 100644 --- a/alacritty/src/event.rs +++ b/alacritty/src/event.rs @@ -1,5 +1,7 @@ //! Process window events. +use crate::ConfigMonitor; +use glutin::config::GetGlConfig; use std::borrow::Cow; use std::cmp::min; use std::collections::{HashMap, HashSet, VecDeque}; @@ -15,16 +17,16 @@ 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 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::raw_window_handle::HasDisplayHandle; use winit::window::WindowId; use alacritty_terminal::event::{Event as TerminalEvent, EventListener, Notify}; @@ -34,6 +36,7 @@ use alacritty_terminal::index::{Boundary, Column, Direction, Line, Point, Side}; use alacritty_terminal::selection::{Selection, SelectionType}; use alacritty_terminal::term::search::{Match, RegexSearch}; use alacritty_terminal::term::{self, ClipboardType, Term, TermMode}; +use alacritty_terminal::vte::ansi::NamedColor; #[cfg(unix)] use crate::cli::{IpcConfig, ParsedOptions}; @@ -49,7 +52,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 +69,412 @@ 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 { + pub config_monitor: Option, + + clipboard: Clipboard, + scheduler: Scheduler, + initial_window_options: Option, + initial_window_error: Option>, + windows: HashMap, + proxy: EventLoopProxy, + gl_config: 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.display_handle().unwrap().as_raw()) }; + + // Create a config monitor. + // + // The monitor watches the config file for changes and reloads it. Pending + // config changes are processed in the main loop. + let mut config_monitor = None; + if config.live_config_reload() { + config_monitor = + ConfigMonitor::new(config.config_paths.clone(), event_loop.create_proxy()); + } + + Processor { + initial_window_options, + initial_window_error: None, + cli_options, + proxy, + scheduler, + gl_config: None, + config: Rc::new(config), + clipboard, + windows: Default::default(), + #[cfg(unix)] + global_ipc_options: Default::default(), + config_monitor, + } + } + + /// 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, + window_options: WindowOptions, + ) -> Result<(), Box> { + 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); + + Ok(()) + } + + /// Create a new terminal window. + pub fn create_window( + &mut self, + event_loop: &ActiveEventLoop, + options: WindowOptions, + ) -> Result<(), Box> { + let gl_config = self.gl_config.as_ref().unwrap(); + + // Override 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); + + 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(()) + } + + /// 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(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 || self.cli_options.daemon { + 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"); + } + + 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, event.window_id.as_ref()) { + // Process IPC config update. + #[cfg(unix)] + (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); + } + } + }, + (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); + + // 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()); + } + } + }, + // 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 self.gl_config.is_none() { + // Handle initial window creation in daemon mode. + 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) { + error!("Could not open window: {:?}", err); + } + }, + // Process events affecting all windows. + (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")] + 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), Some(window_id)) => { + // 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() && !self.cli_options.daemon { + // 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, 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(); + } + } + }, + (payload, Some(window_id)) => { + 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::new(payload, *window_id)), + ); + } + }, + }; + } + + 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_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 + // 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 { @@ -217,7 +626,8 @@ pub struct ActionContext<'a, N, T> { pub message_buffer: &'a mut MessageBuffer, pub config: &'a UiConfig, pub cursor_blink_timed_out: &'a mut bool, - pub event_loop: &'a EventLoopWindowTarget, + #[cfg(target_os = "macos")] + pub event_loop: &'a ActiveEventLoop, pub event_proxy: &'a EventLoopProxy, pub scheduler: &'a mut Scheduler, pub search_state: &'a mut SearchState, @@ -733,16 +1143,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. @@ -822,6 +1232,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(); @@ -895,6 +1307,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. @@ -909,6 +1322,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() } @@ -917,7 +1346,8 @@ impl<'a, N: Notify + 'a, T: EventListener> input::ActionContext for ActionCon self.config } - fn event_loop(&self) -> &EventLoopWindowTarget { + #[cfg(target_os = "macos")] + fn event_loop(&self) -> &ActiveEventLoop { self.event_loop } @@ -1068,7 +1498,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 { @@ -1212,7 +1642,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, @@ -1233,7 +1662,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(), @@ -1312,7 +1740,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()); } }, @@ -1343,9 +1771,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) => { @@ -1355,7 +1786,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 => (), TerminalEvent::DecorEvent => self.ctx.display.pending_update.dirty = true, TerminalEvent::ChartEvent => self.ctx.display.pending_update.dirty = true, }, @@ -1447,11 +1878,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); @@ -1470,12 +1898,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(_) @@ -1495,359 +1924,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( - 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( - 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( - 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( - 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/keyboard.rs b/alacritty/src/input/keyboard.rs index c9cee364..948cff71 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")] @@ -30,6 +29,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; } @@ -46,15 +48,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; } @@ -127,7 +122,7 @@ impl> Processor { self.ctx.modifiers().state().alt_key() } }, - _ => text.len() == 1 && alt_send_esc, + _ => alt_send_esc && text.chars().count() == 1, } } @@ -231,7 +226,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(), @@ -286,7 +281,7 @@ fn build_sequence(key: KeyEvent, mods: ModifiersState, mode: TermMode) -> Vec 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() { @@ -348,7 +343,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, }; @@ -374,7 +369,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)) @@ -489,14 +484,23 @@ impl SequenceBuilder { } /// Try building from [`NamedKey`]. - fn try_build_named_normal(&self, key: &KeyEvent) -> 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('~')), diff --git a/alacritty/src/input/mod.rs b/alacritty/src/input/mod.rs index a8e8a82e..a4cc6795 100644 --- a/alacritty/src/input/mod.rs +++ b/alacritty/src/input/mod.rs @@ -19,10 +19,11 @@ use winit::dpi::PhysicalPosition; use winit::event::{ ElementState, Modifiers, MouseButton, MouseScrollDelta, Touch as TouchEvent, TouchPhase, }; -use winit::event_loop::EventLoopWindowTarget; +#[cfg(target_os = "macos")] +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; @@ -35,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; @@ -103,7 +106,8 @@ pub trait ActionContext { fn pop_message(&mut self) {} fn message(&self) -> Option<&Message>; fn config(&self) -> &UiConfig; - fn event_loop(&self) -> &EventLoopWindowTarget; + #[cfg(target_os = "macos")] + fn event_loop(&self) -> &ActiveEventLoop; fn mouse_mode(&self) -> bool; fn clipboard_mut(&mut self) -> &mut Clipboard; fn scheduler_mut(&mut self) -> &mut Scheduler; @@ -123,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) {} @@ -384,8 +389,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(), @@ -803,7 +811,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()); } } @@ -998,17 +1006,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) { @@ -1128,7 +1137,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, @@ -1217,7 +1226,8 @@ mod tests { self.clipboard } - fn event_loop(&self) -> &EventLoopWindowTarget { + #[cfg(target_os = "macos")] + fn event_loop(&self) -> &ActiveEventLoop { unimplemented!(); } @@ -1319,9 +1329,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, @@ -1335,9 +1345,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, @@ -1351,9 +1361,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, @@ -1367,9 +1377,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, @@ -1383,9 +1393,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, @@ -1399,9 +1409,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, @@ -1415,9 +1425,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, @@ -1431,9 +1441,9 @@ mod tests { event: WindowEvent::MouseInput { state: ElementState::Pressed, button: MouseButton::Right, - device_id: unsafe { DeviceId::dummy() }, + device_id: DeviceId::dummy(), }, - window_id: unsafe { WindowId::dummy() }, + window_id: WindowId::dummy(), }, end_state: ClickState::Click, input_delay: Duration::ZERO, diff --git a/alacritty/src/ipc.rs b/alacritty/src/ipc.rs index 1cb7a1c8..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(); @@ -111,7 +116,7 @@ fn find_socket(socket_path: Option) -> IoResult { if let Some(socket_path) = socket_path { // Ensure we inform the user about an invalid path. return UnixStream::connect(&socket_path).map_err(|err| { - let message = format!("invalid socket path {:?}", socket_path); + let message = format!("invalid socket path {socket_path:?}"); IoError::new(err.kind(), message) }); } diff --git a/alacritty/src/logging.rs b/alacritty/src/logging.rs index 42f1536e..67cad63e 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; @@ -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", @@ -104,16 +108,16 @@ impl Logger { }; #[cfg(not(windows))] - let env_var = format!("${}", ALACRITTY_LOG_ENV); + let env_var = format!("${ALACRITTY_LOG_ENV}"); #[cfg(windows)] let env_var = format!("%{}%", ALACRITTY_LOG_ENV); let message = format!( - "[{}] See log at {} ({}):\n{}", + "[{}] {}\nSee log at {} ({})", record.level(), + record.args(), logfile_path, env_var, - record.args(), ); let mut message = Message::new(message, message_type); @@ -223,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/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() -} diff --git a/alacritty/src/main.rs b/alacritty/src/main.rs index 91d99cbe..6bbf8dfd 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. @@ -21,9 +21,9 @@ use std::{env, fs}; use log::info; #[cfg(windows)] use windows_sys::Win32::System::Console::{AttachConsole, FreeConsole, ATTACH_PARENT_PROCESS}; -use winit::event_loop::EventLoopBuilder as WinitEventLoopBuilder; +use winit::event_loop::EventLoop; #[cfg(all(feature = "x11", not(any(target_os = "macos", windows))))] -use winit::platform::x11::EventLoopWindowTargetExtX11; +use winit::raw_window_handle::{HasDisplayHandle, RawDisplayHandle}; use alacritty_terminal::tty; @@ -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; @@ -124,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()) @@ -134,7 +135,17 @@ 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.display_handle().unwrap().as_raw(), + RawDisplayHandle::Wayland(_) + ) { + "Wayland" + } else { + "X11" + } + ); #[cfg(not(any(feature = "x11", target_os = "macos", windows)))] info!("Running on Wayland"); @@ -161,17 +172,9 @@ fn alacritty(mut options: Options) -> Result<(), Box> { #[cfg(target_os = "macos")] locale::set_locale_environment(); - // Create a config monitor when config was loaded from path. - // - // The monitor watches the config file for changes and reloads it. Pending - // config changes are processed in the main loop. - if config.live_config_reload { - monitor::watch(config.config_paths.clone(), window_event_loop.create_proxy()); - } - // Create the IPC socket listener. #[cfg(unix)] - let socket_path = if config.ipc_socket { + let socket_path = if config.ipc_socket() { ipc::spawn_ipc_socket(&options, window_event_loop.create_proxy()) } else { None @@ -186,13 +189,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); // 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 @@ -203,10 +207,11 @@ fn alacritty(mut options: Options) -> Result<(), Box> { // order. // // 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) = processor.config_monitor.take() { + config_monitor.shutdown(); + } // Without explicitly detaching the console cmd won't redraw it's prompt. #[cfg(windows)] @@ -229,5 +234,5 @@ fn log_config_path(config: &UiConfig) { let _ = write!(msg, "\n {:?}", path.display()); } - info!("{}", msg); + info!("{msg}"); } diff --git a/alacritty/src/migrate.rs b/alacritty/src/migrate.rs deleted file mode 100644 index dbcfb2ae..00000000 --- a/alacritty/src/migrate.rs +++ /dev/null @@ -1,266 +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, 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, - recursion_limit: usize, -) -> Result<(), String> { - let imports = match config::imports(config, recursion_limit) { - Ok(imports) => imports, - Err(err) => return Err(format!("import error: {err}")), - }; - - // Migrate the individual imports. - let mut new_imports = Vec::new(); - for import in imports { - let import = match import { - Ok(import) => import, - Err(err) => return Err(format!("import error: {err}")), - }; - - // Keep yaml import if path does not exist. - if !import.exists() { - if options.dry_run { - eprintln!("Keeping yaml config for nonexistent import: {import:?}"); - } - new_imports.push(Value::String(import.to_string_lossy().into())); - continue; - } - - let new_path = migrate_config(options, &import, recursion_limit - 1)?; - - // Print new import path. - if options.dry_run { - println!("Successfully migrated import {import:?} to {new_path:?}"); - } - - new_imports.push(Value::String(new_path)); - } - - // Update the imports field. - if let Some(import) = config.get_mut("import") { - *import = Value::Array(new_imports); - } - - Ok(()) -} - -/// Migrate deprecated fields. -fn migrate_renames(config: &mut Value) -> Result<(), String> { - let config_table = match config.as_table_mut() { - Some(config_table) => config_table, - None => return Ok(()), - }; - - // draw_bold_text_with_bright_colors -> colors.draw_bold_text_with_bright_colors - move_value(config_table, &["draw_bold_text_with_bright_colors"], &[ - "colors", - "draw_bold_text_with_bright_colors", - ])?; - - // key_bindings -> keyboard.bindings - move_value(config_table, &["key_bindings"], &["keyboard", "bindings"])?; - - // mouse_bindings -> mouse.bindings - move_value(config_table, &["mouse_bindings"], &["mouse", "bindings"])?; - - Ok(()) -} - -/// Move a toml value from one map to another. -fn move_value(config_table: &mut Table, origin: &[&str], target: &[&str]) -> Result<(), String> { - if let Some(value) = remove_node(config_table, origin)? { - if !insert_node_if_empty(config_table, target, value)? { - return Err(format!( - "conflict: both `{}` and `{}` are set", - origin.join("."), - target.join(".") - )); - } - } - - Ok(()) -} - -/// Remove a node from a tree of tables. -fn remove_node(table: &mut Table, path: &[&str]) -> Result, String> { - if path.len() == 1 { - Ok(table.remove(path[0])) - } else { - let next_table_value = match table.get_mut(path[0]) { - Some(next_table_value) => next_table_value, - None => return Ok(None), - }; - - let next_table = match next_table_value.as_table_mut() { - Some(next_table) => next_table, - None => return Err(format!("invalid `{}` table", path[0])), - }; - - remove_node(next_table, &path[1..]) - } -} - -/// Try to insert a node into a tree of tables. -/// -/// Returns `false` if the node already exists. -fn insert_node_if_empty(table: &mut Table, path: &[&str], node: Value) -> Result { - if path.len() == 1 { - match table.entry(path[0]) { - Entry::Vacant(vacant_entry) => { - vacant_entry.insert(node); - Ok(true) - }, - Entry::Occupied(_) => Ok(false), - } - } else { - let next_table_value = table.entry(path[0]).or_insert_with(|| Value::Table(Table::new())); - - let next_table = match next_table_value.as_table_mut() { - Some(next_table) => next_table, - None => return Err(format!("invalid `{}` table", path[0])), - }; - - insert_node_if_empty(next_table, &path[1..], node) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn move_values() { - let input = r#" -root_value = 3 - -[table] -table_value = 5 - -[preexisting] -not_moved = 9 - "#; - - let mut value: Value = toml::from_str(input).unwrap(); - let table = value.as_table_mut().unwrap(); - - move_value(table, &["root_value"], &["new_table", "root_value"]).unwrap(); - move_value(table, &["table", "table_value"], &["preexisting", "subtable", "new_name"]) - .unwrap(); - - let output = toml::to_string(table).unwrap(); - - assert_eq!( - output, - "[new_table]\nroot_value = 3\n\n[preexisting]\nnot_moved = \ - 9\n\n[preexisting.subtable]\nnew_name = 5\n\n[table]\n" - ); - } -} diff --git a/alacritty/src/migrate/mod.rs b/alacritty/src/migrate/mod.rs new file mode 100644 index 00000000..bfa72294 --- /dev/null +++ b/alacritty/src/migrate/mod.rs @@ -0,0 +1,334 @@ +//! Configuration file migration. + +use std::fmt::Debug; +use std::path::Path; +use std::{fs, mem}; + +use tempfile::NamedTempFile; +use toml_edit::{DocumentMut, Item}; + +use crate::cli::MigrateOptions; +use crate::config; + +mod yaml; + +/// Handle migration. +pub fn migrate(options: MigrateOptions) { + // Find configuration file path. + let config_path = options + .config_file + .clone() + .or_else(|| config::installed_config("toml")) + .or_else(|| config::installed_config("yml")); + + // Abort if system has no installed configuration. + let config_path = match config_path { + Some(config_path) => config_path, + None => { + eprintln!("No configuration file found"); + std::process::exit(1); + }, + }; + + // If we're doing a wet run, perform a dry run first for safety. + if !options.dry_run { + #[allow(clippy::redundant_clone)] + let mut options = options.clone(); + options.silent = true; + options.dry_run = true; + if let Err(err) = migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) { + eprintln!("Configuration file migration failed:"); + eprintln!(" {config_path:?}: {err}"); + std::process::exit(1); + } + } + + // Migrate the root config. + match migrate_config(&options, &config_path, config::IMPORT_RECURSION_LIMIT) { + Ok(migration) => { + if !options.silent { + println!("{}", migration.success_message(false)); + } + }, + Err(err) => { + eprintln!("Configuration file migration failed:"); + eprintln!(" {config_path:?}: {err}"); + std::process::exit(1); + }, + } +} + +/// Migrate a specific configuration file. +fn migrate_config<'a>( + options: &MigrateOptions, + path: &'a Path, + recursion_limit: usize, +) -> Result, String> { + // Ensure configuration file has an extension. + let path_str = path.to_string_lossy(); + let (prefix, suffix) = match path_str.rsplit_once('.') { + Some((prefix, suffix)) => (prefix, suffix), + None => return Err("missing file extension".to_string()), + }; + + // Handle legacy YAML files. + if suffix == "yml" { + let new_path = yaml::migrate(options, path, recursion_limit, prefix)?; + return Ok(Migration::Yaml((path, new_path))); + } + + // TOML only does renames, so return early if they are disabled. + if options.skip_renames { + if options.dry_run { + eprintln!("Ignoring TOML file {path:?} since `--skip-renames` was supplied"); + } + return Ok(Migration::Toml(path)); + } + + // Read TOML file and perform all in-file migrations. + let toml = fs::read_to_string(path).map_err(|err| format!("{err}"))?; + let mut migrated = migrate_toml(toml)?; + + // Recursively migrate imports. + migrate_imports(options, path, &mut migrated, recursion_limit)?; + + // Write migrated TOML file. + write_results(options, path, &migrated.to_string())?; + + Ok(Migration::Toml(path)) +} + +/// Migrate TOML config to the latest version. +fn migrate_toml(toml: String) -> Result { + // Parse TOML file. + let mut document = match toml.parse::() { + Ok(document) => document, + Err(err) => return Err(format!("TOML parsing error: {err}")), + }; + + // Move `draw_bold_text_with_bright_colors` to its own section. + move_value(&mut document, &["draw_bold_text_with_bright_colors"], &[ + "colors", + "draw_bold_text_with_bright_colors", + ])?; + + // Move bindings to their own section. + move_value(&mut document, &["key_bindings"], &["keyboard", "bindings"])?; + move_value(&mut document, &["mouse_bindings"], &["mouse", "bindings"])?; + + // Avoid warnings due to introduction of the new `general` section. + move_value(&mut document, &["live_config_reload"], &["general", "live_config_reload"])?; + move_value(&mut document, &["working_directory"], &["general", "working_directory"])?; + move_value(&mut document, &["ipc_socket"], &["general", "ipc_socket"])?; + move_value(&mut document, &["import"], &["general", "import"])?; + move_value(&mut document, &["shell"], &["terminal", "shell"])?; + + Ok(document) +} + +/// Migrate TOML imports to the latest version. +fn migrate_imports( + options: &MigrateOptions, + path: &Path, + document: &mut DocumentMut, + recursion_limit: usize, +) -> Result<(), String> { + // Check if any imports need to be processed. + let imports = match document + .get("general") + .and_then(|general| general.get("import")) + .and_then(|import| import.as_array()) + { + Some(array) if !array.is_empty() => array, + _ => return Ok(()), + }; + + // Abort once recursion limit is exceeded. + if recursion_limit == 0 { + return Err("Exceeded maximum configuration import depth".into()); + } + + // Migrate each import. + for import in imports.into_iter().filter_map(|item| item.as_str()) { + let normalized_path = config::normalize_import(path, import); + + 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)); + } + } + + Ok(()) +} + +/// Move a TOML value from one map to another. +fn move_value(document: &mut DocumentMut, origin: &[&str], target: &[&str]) -> Result<(), String> { + // Find and remove the original item. + let (mut origin_key, mut origin_item) = (None, document.as_item_mut()); + for element in origin { + let table = match origin_item.as_table_like_mut() { + Some(table) => table, + None => panic!("Moving from unsupported TOML structure"), + }; + + let (key, item) = match table.get_key_value_mut(element) { + Some((key, item)) => (key, item), + None => return Ok(()), + }; + + origin_key = Some(key); + origin_item = item; + + // Ensure no empty tables are left behind. + if let Some(table) = origin_item.as_table_mut() { + table.set_implicit(true) + } + } + + let origin_key_decor = + origin_key.map(|key| (key.leaf_decor().clone(), key.dotted_decor().clone())); + let origin_item = mem::replace(origin_item, Item::None); + + // Create all dependencies for the new location. + let mut target_item = document.as_item_mut(); + for (i, element) in target.iter().enumerate() { + let table = match target_item.as_table_like_mut() { + Some(table) => table, + None => panic!("Moving into unsupported TOML structure"), + }; + + if i + 1 == target.len() { + table.insert(element, origin_item); + // Move original key decorations. + if let Some((leaf, dotted)) = origin_key_decor { + let mut key = table.key_mut(element).unwrap(); + *key.leaf_decor_mut() = leaf; + *key.dotted_decor_mut() = dotted; + } + + break; + } else { + // Create missing parent tables. + target_item = target_item[element].or_insert(toml_edit::table()); + } + } + + Ok(()) +} + +/// Write migrated TOML to its target location. +fn write_results

(options: &MigrateOptions, path: P, toml: &str) -> Result<(), String> +where + P: AsRef + Debug, +{ + let path = path.as_ref(); + if options.dry_run && !options.silent { + // Output new content to STDOUT. + println!( + "\nv-----Start TOML for {path:?}-----v\n\n{toml}\n^-----End TOML for {path:?}-----^\n" + ); + } else if !options.dry_run { + // Atomically replace the configuration file. + let tmp = NamedTempFile::new_in(path.parent().unwrap()) + .map_err(|err| format!("could not create temporary file: {err}"))?; + fs::write(tmp.path(), toml).map_err(|err| format!("filesystem error: {err}"))?; + tmp.persist(path).map_err(|err| format!("atomic replacement failed: {err}"))?; + } + Ok(()) +} + +/// Performed migration mode. +enum Migration<'a> { + /// In-place TOML migration. + Toml(&'a Path), + /// YAML to TOML migration. + Yaml((&'a Path, String)), +} + +impl Migration<'_> { + /// Get the success message for this migration. + fn success_message(&self, import: bool) -> String { + match self { + Self::Yaml((original_path, new_path)) if import => { + format!("Successfully migrated import {original_path:?} to {new_path:?}") + }, + Self::Yaml((original_path, new_path)) => { + format!("Successfully migrated {original_path:?} to {new_path:?}") + }, + Self::Toml(original_path) if import => { + format!("Successfully migrated import {original_path:?}") + }, + Self::Toml(original_path) => format!("Successfully migrated {original_path:?}"), + } + } + + /// Get the file path after migration. + fn new_path(&self) -> String { + match self { + Self::Toml(path) => path.to_string_lossy().into(), + Self::Yaml((_, path)) => path.into(), + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn move_values() { + let input = r#" +# This is a root_value. +# +# Use it with care. +root_value = 3 + +[table] +table_value = 5 + +[preexisting] +not_moved = 9 + "#; + + let mut document = input.parse::().unwrap(); + + move_value(&mut document, &["root_value"], &["new_table", "root_value"]).unwrap(); + move_value(&mut document, &["table", "table_value"], &[ + "preexisting", + "subtable", + "new_name", + ]) + .unwrap(); + + let output = document.to_string(); + + let expected = r#" +[preexisting] +not_moved = 9 + +[preexisting.subtable] +new_name = 5 + +[new_table] + +# This is a root_value. +# +# Use it with care. +root_value = 3 + "#; + + assert_eq!(output, expected); + } + + #[test] + fn migrate_empty() { + assert!(migrate_toml(String::new()).unwrap().to_string().is_empty()); + } +} diff --git a/alacritty/src/migrate/yaml.rs b/alacritty/src/migrate/yaml.rs new file mode 100644 index 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/src/renderer/hex_bg.rs b/alacritty/src/renderer/hex_bg.rs index 24d5dedd..ed0f06d4 100644 --- a/alacritty/src/renderer/hex_bg.rs +++ b/alacritty/src/renderer/hex_bg.rs @@ -9,6 +9,7 @@ use crate::renderer::{self, cstr}; static HXBG_SHADER_F: &str = include_str!("../../res/hex_bg.f.glsl"); static HXBG_SHADER_V: &str = include_str!("../../res/hex_bg.v.glsl"); +#[allow(dead_code)] #[derive(Debug)] pub struct HexBgRenderer { // GL buffer objects. diff --git a/alacritty/src/renderer/mod.rs b/alacritty/src/renderer/mod.rs index f1f1c201..31b72f07 100644 --- a/alacritty/src/renderer/mod.rs +++ b/alacritty/src/renderer/mod.rs @@ -103,10 +103,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}") }, } } @@ -150,9 +150,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()), } } } @@ -248,30 +248,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); 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/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/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/src/renderer/text/gles2.rs b/alacritty/src/renderer/text/gles2.rs index 427a60e3..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 { @@ -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..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; @@ -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/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/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/src/window_context.rs b/alacritty/src/window_context.rs index c4d43ed8..f8133fc0 100644 --- a/alacritty/src/window_context.rs +++ b/alacritty/src/window_context.rs @@ -9,15 +9,15 @@ 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; 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::raw_window_handle::HasDisplayHandle; use winit::window::WindowId; use alacritty_terminal::event::Event as TerminalEvent; @@ -70,12 +70,12 @@ 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, ) -> 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); @@ -119,18 +119,14 @@ impl WindowContext { /// Create additional context with the graphics platform other windows are using. pub fn additional( - &self, - event_loop: &EventLoopWindowTarget, + 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")] @@ -418,7 +411,7 @@ impl WindowContext { /// Process events for this terminal window. pub fn handle_event( &mut self, - event_loop: &EventLoopWindowTarget, + #[cfg(target_os = "macos")] event_loop: &ActiveEventLoop, event_proxy: &EventLoopProxy, clipboard: &mut Clipboard, scheduler: &mut Scheduler, @@ -464,6 +457,7 @@ impl WindowContext { preserve_title: self.preserve_title, config: &self.config, event_proxy, + #[cfg(target_os = "macos")] event_loop, clipboard, scheduler, diff --git a/alacritty/windows/wix/alacritty.wxs b/alacritty/windows/wix/alacritty.wxs index e3625fa8..39afdd05 100644 --- a/alacritty/windows/wix/alacritty.wxs +++ b/alacritty/windows/wix/alacritty.wxs @@ -1,5 +1,5 @@ - + @@ -41,7 +41,7 @@ - + diff --git a/alacritty_config/Cargo.toml b/alacritty_config/Cargo.toml index e773d810..a6d651bc 100644 --- a/alacritty_config/Cargo.toml +++ b/alacritty_config/Cargo.toml @@ -1,12 +1,13 @@ [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" -homepage = "https://github.com/alacritty/alacritty" +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"] } @@ -14,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 655cde3c..7d04eacc 100644 --- a/alacritty_config_derive/Cargo.toml +++ b/alacritty_config_derive/Cargo.toml @@ -1,12 +1,13 @@ [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" -homepage = "https://github.com/alacritty/alacritty" +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 @@ -18,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_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/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_config_derive/src/serde_replace.rs b/alacritty_config_derive/src/serde_replace.rs index 0a703b4c..cd56b3bc 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 \"{ident}\" has no alias value"))? + .value(); + + if value.trim().is_empty() { + return Err(format!("Field \"{ident}\" has an empty alias value")); + } + + 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..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; @@ -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, } @@ -78,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); @@ -129,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 { @@ -189,6 +193,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 +229,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); +} diff --git a/alacritty_terminal/CHANGELOG.md b/alacritty_terminal/CHANGELOG.md new file mode 100644 index 00000000..28ed7540 --- /dev/null +++ b/alacritty_terminal/CHANGELOG.md @@ -0,0 +1,35 @@ +# 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.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 + +### 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/Cargo.toml b/alacritty_terminal/Cargo.toml index c95c841d..1b7137ec 100644 --- a/alacritty_terminal/Cargo.toml +++ b/alacritty_terminal/Cargo.toml @@ -1,17 +1,25 @@ [package] name = "alacritty_terminal" -version = "0.22.1-dev" -authors = ["Christian Duerr ", "Joe Wilm "] +version = "0.24.2-dev" +authors = [ + "Christian Duerr ", + "Joe Wilm ", +] license = "Apache-2.0" description = "Library for writing terminal emulators" readme = "../README.md" -homepage = "https://github.com/alacritty/alacritty" +homepage = "https://github.com/sebosp/alacritty" +repository = "https://github.com/sebosp/chartacritty" edition = "2021" -rust-version = "1.70.0" +rust-version = "1.74.0" + +[features] +default = ["serde"] +serde = ["dep:serde", "bitflags/serde", "vte/serde"] [dependencies] -base64 = "0.21.3" -bitflags = { version = "2.4.1", features = ["serde"] } +base64 = "0.22.0" +bitflags = "2.4.1" home = "0.5.5" libc = "0.2" log = "0.4" @@ -19,8 +27,8 @@ 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"] } -serde = { version = "1", features = ["derive", "rc"]} +vte = { version = "0.13.0", default-features = false, features = ["ansi"] } +serde = { version = "1", features = ["derive", "rc"], optional = true } reqwest = { version = "0.11", features = ["json"] } tokio = { version = "1.36", features = ["full"] } futures = "0.3.28" @@ -29,13 +37,13 @@ tower-service = "0.3" serde_derive = "1.0" serde_json = "1" serde_yaml = "0.9" -env_logger = "0.7" +env_logger = "0.11" tracing = { version = "0.1", features = ["log", "log-always"] } -tracing-log = { version = "0.2"} +tracing-log = { version = "0.2" } percent-encoding = "2.2" rand = "0.8.5" -lyon = { version ="1.0", features = ["serialization"] } -chrono = { version = "0.4.31", features = [ "serde" ] } +lyon = { version = "1.0", features = ["serialization"] } +chrono = { version = "0.4.31", features = ["serde"] } moon-phase = "0.1.0" noise = "0.8.2" palette = { version = "0.7.3", features = ["serializing", "named"] } @@ -48,14 +56,14 @@ 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.59.0", features = [ "Win32_System_Console", "Win32_Foundation", "Win32_Security", "Win32_System_LibraryLoader", "Win32_System_Threading", "Win32_System_WindowsProgramming", -]} +] } [dev-dependencies] serde_json = "1" diff --git a/alacritty_terminal/src/charts/mod.rs b/alacritty_terminal/src/charts/mod.rs index 706c4a58..94558914 100644 --- a/alacritty_terminal/src/charts/mod.rs +++ b/alacritty_terminal/src/charts/mod.rs @@ -606,8 +606,8 @@ impl TimeSeriesChart { let span = span!(Level::TRACE, "calculate_stats", name = self.name.clone().as_str()); let _enter = span.enter(); event!(Level::TRACE, "TimeSeriesChart::calculate_stats start"); - let mut max_metric_value = std::f64::MIN; - let mut min_metric_value = std::f64::MAX; + let mut max_metric_value = f64::MIN; + let mut min_metric_value = f64::MAX; let mut sum_metric_values = 0f64; let mut total_count = 0usize; let mut max_epoch = 0u64; @@ -788,8 +788,8 @@ impl TimeSeries { // Recalculating seems to be necessary because we are constantly // moving items out of the Vec<> so our cache can easily get out of // sync - let mut max_metric_value = std::f64::MIN; - let mut min_metric_value = std::f64::MAX; + let mut max_metric_value = f64::MIN; + let mut min_metric_value = f64::MAX; let mut sum_metric_values = 0f64; let mut filled_metrics = 0usize; // XXX What is it the vec is empty? what should `first` and `last` be? diff --git a/alacritty_terminal/src/event.rs b/alacritty_terminal/src/event.rs index f5b892df..3ac97444 100644 --- a/alacritty_terminal/src/event.rs +++ b/alacritty_terminal/src/event.rs @@ -53,6 +53,9 @@ pub enum Event { /// Shutdown request. Exit, + /// Child process exited with an error code. + ChildExit(i32), + /// A decoration may request an update to draw the terminal$ DecorEvent, // a decoration may request an update to draw the terminal @@ -75,6 +78,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})"), Event::DecorEvent => write!(f, "DecorEvent"), Event::ChartEvent => write!(f, "ChartEvent"), } diff --git a/alacritty_terminal/src/event_loop.rs b/alacritty_terminal/src/event_loop.rs index 7a35c4ed..445e3a20 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; @@ -280,7 +279,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()); @@ -288,7 +291,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/grid/mod.rs b/alacritty_terminal/src/grid/mod.rs index f637f94b..94611894 100644 --- a/alacritty_terminal/src/grid/mod.rs +++ b/alacritty_terminal/src/grid/mod.rs @@ -135,7 +135,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), @@ -266,33 +266,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); } } @@ -346,7 +354,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() { @@ -382,7 +390,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(); @@ -605,7 +613,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/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 66e741b5..13d478f4 100644 --- a/alacritty_terminal/src/grid/row.rs +++ b/alacritty_terminal/src/grid/row.rs @@ -28,7 +28,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. @@ -289,7 +289,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)] } } diff --git a/alacritty_terminal/src/grid/storage.rs b/alacritty_terminal/src/grid/storage.rs index 4671ba61..8ed83a20 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}; @@ -64,7 +64,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); @@ -77,7 +77,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; @@ -123,7 +123,7 @@ impl Storage { #[inline] pub fn initialize(&mut self, additional_rows: usize, columns: usize) where - T: Clone + Default, + T: Default, { if self.len + additional_rows > self.inner.len() { self.rezero(); diff --git a/alacritty_terminal/src/lib.rs b/alacritty_terminal/src/lib.rs index 8967a9b0..a61802ac 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; diff --git a/alacritty_terminal/src/term/cell.rs b/alacritty_terminal/src/term/cell.rs index 942d8447..bd050a24 100644 --- a/alacritty_terminal/src/term/cell.rs +++ b/alacritty_terminal/src/term/cell.rs @@ -119,9 +119,7 @@ impl ResetDiscriminant for Cell { #[derive(Default, Debug, Clone, Eq, PartialEq, Serialize, Deserialize)] pub struct CellExtra { zerowidth: Vec, - underline_color: Option, - hyperlink: Option, } diff --git a/alacritty_terminal/src/term/mod.rs b/alacritty_terminal/src/term/mod.rs index efc34113..2506eb23 100644 --- a/alacritty_terminal/src/term/mod.rs +++ b/alacritty_terminal/src/term/mod.rs @@ -57,30 +57,30 @@ bitflags! { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct TermMode: u32 { const NONE = 0; - const SHOW_CURSOR = 0b0000_0000_0000_0000_0000_0001; - const APP_CURSOR = 0b0000_0000_0000_0000_0000_0010; - const APP_KEYPAD = 0b0000_0000_0000_0000_0000_0100; - const MOUSE_REPORT_CLICK = 0b0000_0000_0000_0000_0000_1000; - const BRACKETED_PASTE = 0b0000_0000_0000_0000_0001_0000; - const SGR_MOUSE = 0b0000_0000_0000_0000_0010_0000; - const MOUSE_MOTION = 0b0000_0000_0000_0000_0100_0000; - const LINE_WRAP = 0b0000_0000_0000_0000_1000_0000; - const LINE_FEED_NEW_LINE = 0b0000_0000_0000_0001_0000_0000; - const ORIGIN = 0b0000_0000_0000_0010_0000_0000; - const INSERT = 0b0000_0000_0000_0100_0000_0000; - const FOCUS_IN_OUT = 0b0000_0000_0000_1000_0000_0000; - const ALT_SCREEN = 0b0000_0000_0001_0000_0000_0000; - const MOUSE_DRAG = 0b0000_0000_0010_0000_0000_0000; - const MOUSE_MODE = 0b0000_0000_0010_0000_0100_1000; - const UTF8_MOUSE = 0b0000_0000_0100_0000_0000_0000; - const ALTERNATE_SCROLL = 0b0000_0000_1000_0000_0000_0000; - const VI = 0b0000_0001_0000_0000_0000_0000; - const URGENCY_HINTS = 0b0000_0010_0000_0000_0000_0000; - const DISAMBIGUATE_ESC_CODES = 0b0000_0100_0000_0000_0000_0000; - const REPORT_EVENT_TYPES = 0b0000_1000_0000_0000_0000_0000; - const REPORT_ALTERNATE_KEYS = 0b0001_0000_0000_0000_0000_0000; - const REPORT_ALL_KEYS_AS_ESC = 0b0010_0000_0000_0000_0000_0000; - const REPORT_ASSOCIATED_TEXT = 0b0100_0000_0000_0000_0000_0000; + const SHOW_CURSOR = 1; + const APP_CURSOR = 1 << 1; + const APP_KEYPAD = 1 << 2; + const MOUSE_REPORT_CLICK = 1 << 3; + const BRACKETED_PASTE = 1 << 4; + const SGR_MOUSE = 1 << 5; + const MOUSE_MOTION = 1 << 6; + const LINE_WRAP = 1 << 7; + const LINE_FEED_NEW_LINE = 1 << 8; + const ORIGIN = 1 << 9; + const INSERT = 1 << 10; + const FOCUS_IN_OUT = 1 << 11; + const ALT_SCREEN = 1 << 12; + const MOUSE_DRAG = 1 << 13; + const UTF8_MOUSE = 1 << 14; + const ALTERNATE_SCROLL = 1 << 15; + const VI = 1 << 16; + const URGENCY_HINTS = 1 << 17; + const DISAMBIGUATE_ESC_CODES = 1 << 18; + const REPORT_EVENT_TYPES = 1 << 19; + const REPORT_ALTERNATE_KEYS = 1 << 20; + const REPORT_ALL_KEYS_AS_ESC = 1 << 21; + const REPORT_ASSOCIATED_TEXT = 1 << 22; + const MOUSE_MODE = Self::MOUSE_REPORT_CLICK.bits() | Self::MOUSE_MOTION.bits() | Self::MOUSE_DRAG.bits(); const KITTY_KEYBOARD_PROTOCOL = Self::DISAMBIGUATE_ESC_CODES.bits() | Self::REPORT_EVENT_TYPES.bits() | Self::REPORT_ALTERNATE_KEYS.bits() @@ -296,7 +296,7 @@ impl<'a> TermDamageIterator<'a> { } } -impl<'a> Iterator for TermDamageIterator<'a> { +impl Iterator for TermDamageIterator<'_> { type Item = LineDamageBounds; fn next(&mut self) -> Option { @@ -510,13 +510,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()); @@ -526,25 +526,25 @@ 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, + is_focused: Default::default(), + selection: Default::default(), + title: Default::default(), + mode: Default::default(), decorations_enabled: true, - damage, - config: options, tokio_setup: None, } } @@ -1087,6 +1087,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. @@ -1462,7 +1467,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); @@ -1604,15 +1609,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) @@ -2241,7 +2246,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; }, }; @@ -2346,7 +2351,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), @@ -2547,10 +2552,8 @@ pub mod test { use super::*; use serde::{Deserialize, Serialize}; - use unicode_width::UnicodeWidthChar; use crate::event::VoidListener; - use crate::index::Column; #[derive(Serialize, Deserialize)] pub struct TermSize { diff --git a/alacritty_terminal/src/term/search.rs b/alacritty_terminal/src/term/search.rs index 585e191c..20a427b7 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(); @@ -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); } @@ -649,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 { @@ -1155,4 +1162,32 @@ 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)); + } + + #[test] + fn fullwidth_semantic() { + #[rustfmt::skip] + let mut term = mock_term("test-x-test"); + term.config.semantic_escape_chars = "-".into(); + + let start = term.semantic_search_left(Point::new(Line(0), Column(6))); + let end = term.semantic_search_right(Point::new(Line(0), Column(6))); + assert_eq!(start, Point::new(Line(0), Column(6))); + assert_eq!(end, Point::new(Line(0), Column(6))); + } } diff --git a/alacritty_terminal/src/tty/mod.rs b/alacritty_terminal/src/tty/mod.rs index d1bb023c..eed2a76d 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. @@ -46,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; @@ -67,8 +72,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). @@ -93,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 2c06d54f..6565f20b 100644 --- a/alacritty_terminal/src/tty/unix.rs +++ b/alacritty_terminal/src/tty/unix.rs @@ -5,22 +5,22 @@ 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}; -use libc::{self, c_int, TIOCSCTTY}; +use libc::{c_int, TIOCSCTTY}; use log::error; use polling::{Event, PollMode, Poller}; 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}; @@ -38,17 +38,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 { @@ -113,6 +102,7 @@ pub struct Pty { child: Child, file: File, signals: UnixStream, + sig_id: SigId, } impl Pty { @@ -134,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); @@ -188,13 +178,19 @@ 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 } /// 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); + 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(); @@ -216,21 +212,24 @@ pub fn new(config: &Options, window_size: WindowSize, window_id: u64) -> Result< }; // 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(); 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); + } + + // 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 || { @@ -263,13 +262,13 @@ pub fn new(config: &Options, window_size: WindowSize, window_id: u64) -> Result< } // 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() { @@ -280,7 +279,7 @@ pub fn new(config: &Options, window_size: WindowSize, window_id: u64) -> Result< 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(), @@ -299,6 +298,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(); } } @@ -381,7 +384,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 6bc9ed20..573eb475 100644 --- a/alacritty_terminal/src/tty/windows/child.rs +++ b/alacritty_terminal/src/tty/windows/child.rs @@ -1,15 +1,17 @@ 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}; 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::{ - RegisterWaitForSingleObject, UnregisterWait, INFINITE, WT_EXECUTEINWAITTHREAD, - WT_EXECUTEONLYONCE, + GetExitCodeProcess, GetProcessId, RegisterWaitForSingleObject, UnregisterWait, INFINITE, + WT_EXECUTEINWAITTHREAD, WT_EXECUTEONLYONCE, }; use crate::tty::ChildEvent; @@ -22,6 +24,7 @@ struct Interest { struct ChildExitSender { sender: mpsc::Sender, interest: Arc>>, + child_handle: AtomicPtr, } /// WinAPI callback to run when child process exits. @@ -31,7 +34,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(); @@ -42,15 +51,21 @@ pub struct ChildExitWatcher { wait_handle: AtomicPtr, event_rx: mpsc::Receiver, interest: Arc>>, + child_handle: AtomicPtr, + pid: Option, } 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() }); + let sender_ref = Box::new(ChildExitSender { + sender: event_tx, + interest: interest.clone(), + child_handle: AtomicPtr::from(child_handle), + }); let success = unsafe { RegisterWaitForSingleObject( @@ -66,10 +81,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, + pid, + child_handle: AtomicPtr::from(child_handle), + wait_handle: AtomicPtr::from(wait_handle), }) } } @@ -85,6 +103,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.load(Ordering::Relaxed) as HANDLE + } + + /// Retrieve the Process ID associated to the underlying child process. + pub fn pid(&self) -> Option { + self.pid + } } impl Drop for ChildExitWatcher { @@ -122,6 +157,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/conpty.rs b/alacritty_terminal/src/tty/windows/conpty.rs index 9731b4f0..bcbc1f0e 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 std::io::Error; +use log::{info, warn}; +use std::collections::{HashMap, HashSet}; +use std::ffi::OsStr; +use std::io::{Error, Result}; +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}; @@ -69,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"))?; @@ -104,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; @@ -112,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 { @@ -151,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()); } } @@ -177,7 +180,7 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { ) > 0; if !success { - panic_shell_spawn(); + return Err(Error::last_os_error()); } } @@ -194,12 +197,22 @@ pub fn new(config: &Options, window_size: WindowSize) -> Option { ) > 0; if !success { - panic_shell_spawn(); + return Err(Error::last_os_error()); } } + // 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,30 +222,82 @@ 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, ) > 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 +// 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) } -// Panic with the last os error as message. -fn panic_shell_spawn() { - panic!("Unable to spawn shell: {}", Error::last_os_error()); +// 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); } impl OnResize for Conpty { diff --git a/alacritty_terminal/src/tty/windows/mod.rs b/alacritty_terminal/src/tty/windows/mod.rs index cbd803f1..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 { @@ -47,6 +46,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 { @@ -111,7 +114,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)), } } } diff --git a/alacritty_terminal/src/vi_mode.rs b/alacritty_terminal/src/vi_mode.rs index 84712f97..9d68f4fd 100644 --- a/alacritty_terminal/src/vi_mode.rs +++ b/alacritty_terminal/src/vi_mode.rs @@ -264,14 +264,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) { @@ -282,6 +282,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. @@ -819,4 +824,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))); + } } diff --git a/alacritty_terminal/tests/ref.rs b/alacritty_terminal/tests/ref.rs index 7f864ae8..76942197 100644 --- a/alacritty_terminal/tests/ref.rs +++ b/alacritty_terminal/tests/ref.rs @@ -70,6 +70,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 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/extra/osx/Chartacritty.app/Contents/Info.plist b/extra/osx/Chartacritty.app/Contents/Info.plist index 8c208c0a..9a93a35f 100644 --- a/extra/osx/Chartacritty.app/Contents/Info.plist +++ b/extra/osx/Chartacritty.app/Contents/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 0.14.0-dev + 0.15.0-dev CFBundleSupportedPlatforms MacOSX @@ -54,5 +54,7 @@ An application in Chartacritty would like to access your reminders. NSSystemAdministrationUsageDescription An application in Chartacritty requires elevated permissions. + NSBluetoothAlwaysUsageDescription + An application in Chartacritty wants to use Bluetooth. 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