diff options
| author | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 16:24:20 +0300 |
|---|---|---|
| committer | Can Celik <ogulcancelik@gmail.com> | 2026-04-05 16:38:50 +0300 |
| commit | b2e6929aa8199574565fd4adf1e631c68d479e6c (patch) | |
| tree | 99964965fe84f9ea31a0dec7ede2393631dc7f50 /vendor | |
| parent | 822c3b9e2d1edb7481fa558497dd33c7f5dca9ee (diff) | |
refactor: remove vt100 backend and make ghostty default
Diffstat (limited to 'vendor')
| -rw-r--r-- | vendor/vt100/.cargo-ok | 1 | ||||
| -rw-r--r-- | vendor/vt100/.cargo_vcs_info.json | 6 | ||||
| -rw-r--r-- | vendor/vt100/CHANGELOG.md | 396 | ||||
| -rw-r--r-- | vendor/vt100/Cargo.lock | 540 | ||||
| -rw-r--r-- | vendor/vt100/Cargo.toml | 75 | ||||
| -rw-r--r-- | vendor/vt100/Cargo.toml.orig | 28 | ||||
| -rw-r--r-- | vendor/vt100/LICENSE | 21 | ||||
| -rw-r--r-- | vendor/vt100/README.md | 36 | ||||
| -rw-r--r-- | vendor/vt100/src/attrs.rs | 144 | ||||
| -rw-r--r-- | vendor/vt100/src/callbacks.rs | 69 | ||||
| -rw-r--r-- | vendor/vt100/src/cell.rs | 179 | ||||
| -rw-r--r-- | vendor/vt100/src/grid.rs | 740 | ||||
| -rw-r--r-- | vendor/vt100/src/lib.rs | 64 | ||||
| -rw-r--r-- | vendor/vt100/src/parser.rs | 96 | ||||
| -rw-r--r-- | vendor/vt100/src/perform.rs | 277 | ||||
| -rw-r--r-- | vendor/vt100/src/row.rs | 474 | ||||
| -rw-r--r-- | vendor/vt100/src/screen.rs | 1354 | ||||
| -rw-r--r-- | vendor/vt100/src/term.rs | 551 |
18 files changed, 0 insertions, 5051 deletions
diff --git a/vendor/vt100/.cargo-ok b/vendor/vt100/.cargo-ok deleted file mode 100644 index 5f8b7958..00000000 --- a/vendor/vt100/.cargo-ok +++ /dev/null @@ -1 +0,0 @@ -{"v":1}
\ No newline at end of file diff --git a/vendor/vt100/.cargo_vcs_info.json b/vendor/vt100/.cargo_vcs_info.json deleted file mode 100644 index 99725106..00000000 --- a/vendor/vt100/.cargo_vcs_info.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "git": { - "sha1": "eb66ffaf7d771c13303ef73b29f6f2a56fdacecf" - }, - "path_in_vcs": "" -}
\ No newline at end of file diff --git a/vendor/vt100/CHANGELOG.md b/vendor/vt100/CHANGELOG.md deleted file mode 100644 index d589ed7a..00000000 --- a/vendor/vt100/CHANGELOG.md +++ /dev/null @@ -1,396 +0,0 @@ -# Changelog - -## [0.16.2] - 2025-07-11 - -### Fixed - -* Fixed potential cursor out of bounds when using decrc after resizing. (#13) - -## [0.16.1] - 2025-07-10 - -### Changed - -* Reverted to the 2021 edition for now. - -## [0.16.0] - 2025-07-08 - -### Added - -* `Parser::process_cb`, which works the same as `Parser::process` except that - it calls callbacks during parsing when it finds a terminal escape which is - potentially useful but not something that affects the screen itself. -* Support for xterm window resize request escape codes, via the new callback - mechanism. -* Support for dim formatting. (Daniel Faust, #9) -* Support for CNL/CPL escape codes. (Danny Weinberg, #10) -* Support for OSC 52 (clipboard manipulation). - -### Removed - -* These methods on `Screen` have been removed in favor of the new callback - API described above: - * `title_formatted` - * `title_diff` - * `title` - * `icon_name` - * `bells_diff` - * `audible_bell_count` - * `visual_bell_count` - * `errors` -* Additionally, unhandled escape sequences no longer log to STDERR; they - instead call various callback methods which can be defined to log if - desired. -* `Cell` no longer implements `Default`. -* `Screen` no longer implements `vte::Perform`. - -### Changed - -* `Parser::set_size` and `Parser::set_scrollback` have been moved to methods - on `Screen`, and `Parser::screen_mut` was added to get a mutable reference - to the screen. -* `Cell::contents` now returns `&str` instead of `String`, eliminating an - allocation in many cases. (Chris Olszewski, #14) - -### Fixed - -* Fixed some issues with calculating scrollback offsets correctly in - `Grid::visible_rows`. (rezigned, #11) - -## [0.15.2] - 2023-02-05 - -### Changed - -* Bumped dependencies - -## [0.15.1] - 2021-12-21 - -### Changed - -* Removed a lot of unnecessary test data from the packaged crate, making - downloads faster - -## [0.15.0] - 2021-12-15 - -### Added - -* `Screen::errors` to track the number of parsing errors seen so far - -### Fixed - -* No longer generate spurious diffs in some cases where the cursor is past the - end of a row -* Fix restoring the cursor position when scrolled back - -### Changed - -* Various internal refactorings - -## [0.14.0] - 2021-12-06 - -### Changed - -* Unknown UTF-8 characters default to a width of 1, rather than 0 (except for - control characters, as mentioned below) - -### Fixed - -* Ignore C1 control characters rather than adding them to the cell data, since - they are non-printable - -## [0.13.2] - 2021-12-05 - -### Changed - -* Delay allocation of the alternate screen until it is used (saves a bit of - memory in basic cases) - -## [0.13.1] - 2021-12-04 - -### Fixed - -* Fixed various line wrapping state issues -* Fixed cursor positioning after writing zero width characters at the end of - the line -* Fixed `Screen::cursor_state_formatted` to draw the last character in a line - with the appropriate drawing attributes if it needs to redraw it - -## [0.13.0] - 2021-11-17 - -### Added - -* `Screen::alternate_screen` to determine if the alternate screen is in use -* `Screen::row_wrapped` to determine whether the row at the given index should - wrap its text -* `Screen::cursor_state_formatted` to set the cursor position and hidden state - (including internal state like the one-past-the-end state which isn't visible - in the return value of `cursor_position`) - -### Fixed - -* `Screen::rows_formatted` now outputs correct escape codes in some edge cases - at the beginning of a row when the previous row was wrapped -* VPA escape sequence can no longer position the cursor off the screen - -## [0.12.0] - 2021-03-09 - -### Added - -* `Screen::state_formatted` and `Screen::state_diff` convenience wrappers - -### Fixed - -* `Screen::attributes_formatted` now correctly resets previously set attributes - where necessary - -### Removed - -* Removed `Screen::attributes_diff`, since I can't actually think of any - situation where it does a thing that makes sense. - -## [0.11.1] - 2021-03-07 - -### Changed - -* Drop dependency on `enumset` - -## [0.11.0] - 2021-03-07 - -### Added - -* `Screen::attributes_formatted` and `Screen::attributes_diff` to retrieve the - current state of the drawing attributes as escape sequences -* `Screen::fgcolor`, `Screen::bgcolor`, `Screen::bold`, `Screen::italic`, - `Screen::underline`, and `Screen::inverse` to retrieve the current state of - the drawing attributes directly - -## [0.10.0] - 2021-03-06 - -### Added - -* Implementation of `std::io::Write` for `Parser` - -## [0.9.0] - 2021-03-05 - -### Added - -* `Screen::contents_between`, for returning the contents logically between two - given cells (for things like clipboard selection) -* Support SGR subparameters (so `\e[38:2:255:0:0m` behaves the same way as - `\e[38;2;255;0;0m`) - -### Fixed - -* Bump `enumset` to fix a dependency which fails to build - -## [0.8.1] - 2020-02-09 - -### Changed - -* Bumped `vte` dep to 0.6. - -## [0.8.0] - 2019-12-07 - -### Removed - -* Removed the unicode-normalization feature altogether - it turns out that it - still has a couple edge cases where it causes incorrect behavior, and fixing - those would be a lot more effort. - -### Fixed - -* Fix a couple more end-of-line/wrapping bugs, especially around cursor - positioning. -* Fix applying combining characters to wide characters. -* Ensure cells can't have contents with width zero (to avoid ambiguity). If an - empty cell gets a combining character applied to it, default that cell to a - (normal-width) space first. - -## [0.7.0] - 2019-11-23 - -### Added - -* New (default-on) cargo feature `unicode-normalization` which can be disabled - to disable normalizing cell contents to NFC - it's a pretty small edge case, - and the data tables required to support it are quite large, which affects - size-sensitive targets like wasm - -## [0.6.3] - 2019-11-20 - -### Fixed - -* Fix output of `contents_formatted` and `contents_diff` when the cursor - position ends at one past the end of a row. -* If the cursor position is one past the end of a row, any char, even a - combining char, needs to cause the cursor position to wrap. - -## [0.6.2] - 2019-11-13 - -### Fixed - -* Fix zero-width characters when the cursor is at the end of a row. - -## [0.6.1] - 2019-11-13 - -### Added - -* Add more debug logging for unhandled escape sequences. - -### Changed - -* Unhandled escape sequence warnings are now at the `debug` log level. - -## [0.6.0] - 2019-11-13 - -### Added - -* `Screen::input_mode_formatted` and `Screen::input_mode_diff` give escape - codes to set the current terminal input modes. -* `Screen::title_formatted` and `Screen::title_diff` give escape codes to set - the terminal window title. -* `Screen::bells_diff` gives escape codes to trigger any audible or visual - bells which have been seen since the previous state. - -### Changed - -* `Screen::contents_diff` no longer includes audible or visual bells (see - `Screen::bells_diff` instead). - -## [0.5.1] - 2019-11-12 - -### Fixed - -* `Screen::set_size` now actually resizes when requested (previously the - underlying storage was not being resized, leading to panics when writing - outside of the original screen). - -## [0.5.0] - 2019-11-12 - -### Added - -* Scrollback support. -* `Default` impl for `Parser` which creates an 80x24 terminal with no - scrollback. - -### Removed - -* `Parser::screen_mut` (and the `pub` `&mut self` methods on `Screen`). The few - things you can do to change the screen state directly are now exposed as - methods on `Parser` itself. - -### Changed - -* `Cell::contents` now returns a `String` instead of a `&str`. -* `Screen::check_audible_bell` and `Screen::check_visual_bell` have been - replaced with `Screen::audible_bell_count` and `Screen::visual_bell_count`. - You should keep track of the "since the last method call" state yourself - instead of having the screen track it for you. - -### Fixed - -* Lots of performance and output optimizations. -* Clearing a cell now sets all of that cell's attributes to the current - attribute set, since different terminals render different things for an empty - cell based on the attributes. -* `Screen::contents_diff` now includes audible and visual bells when - appropriate. - -## [0.4.0] - 2019-11-08 - -### Removed - -* `Screen::fgcolor`, `Screen::bgcolor`, `Screen::bold`, `Screen::italic`, - `Screen::underline`, `Screen::inverse`, and `Screen::alternate_screen`: - these are just implementation details that people shouldn't need to care - about. - -### Fixed - -* Fixed cursor movement when the cursor position is already outside of an - active scroll region. - -## [0.3.2] - 2019-11-08 - -### Fixed - -* Clearing cells now correctly sets the cell background color. -* Fixed a couple bugs in wide character handling in `contents_formatted` and - `contents_diff`. -* Fixed RI when the cursor is at the top of the screen (fixes scrolling up in - `less`, for instance). -* Fixed VPA incorrectly being clamped to the scroll region. -* Stop treating soft hyphen specially (as far as i can tell, no other terminals - do this, and i'm not sure why i thought it was necessary to begin with). -* `contents_formatted` now also resets attributes at the start, like - `contents_diff` does. - -## [0.3.1] - 2019-11-06 - -### Fixed - -* Make `contents_formatted` explicitly show the cursor when necessary, in case - the cursor was previously hidden. - -## [0.3.0] - 2019-11-06 - -### Added - -* `Screen::rows` which is like `Screen::contents` except that it returns the - data by row instead of all at once, and also allows you to restrict the - region returned to a subset of columns. -* `Screen::rows_formatted` which is like `Screen::rows`, but returns escape - sequences sufficient to draw the requested subset of each row. -* `Screen::contents_diff` and `Screen::rows_diff` which return escape sequences - sufficient to turn the visible state of one screen (or a subset of the screen - in the case of `rows_diff`) into another. - -### Changed - -* The screen is now exposed separately from the parser, and is cloneable. -* `contents_formatted` now returns `Vec<u8>` instead of `String`. -* `contents` and `contents_formatted` now only allow getting the contents of - the entire screen rather than a subset (but see the entry for `rows` and - `rows_formatted` above). - -### Removed - -* `Cell::new`, since there's not really any reason that this is useful for - someone to do from outside of the crate. - -### Fixed - -* `contents_formatted` now preserves the state of empty cells instead of - filling them with spaces. -* We now clear the row wrapping state when the number of columns in the - terminal is changed. -* `contents_formatted` now ensures that the cursor has the correct hidden state - and location. -* `contents_formatted` now clears the screen before starting to draw. - -## [0.2.0] - 2019-11-04 - -### Changed - -* Reimplemented in pure safe rust, with a much more accurate parser -* A bunch of minor API tweaks, some backwards-incompatible - -## [0.1.2] - 2016-06-04 - -### Fixed - -* Fix returning uninit memory in get_string_formatted/get_string_plaintext -* Handle emoji and zero width unicode characters properly -* Fix cursor positioning with regards to scroll regions and wrapping -* Fix parsing of (ignored) character set escapes -* Explicitly suppress status report escapes - -## [0.1.1] - 2016-04-28 - -### Fixed - -* Fix builds - -## [0.1.0] - 2016-04-28 - -### Added - -* Initial release diff --git a/vendor/vt100/Cargo.lock b/vendor/vt100/Cargo.lock deleted file mode 100644 index b984ee78..00000000 --- a/vendor/vt100/Cargo.lock +++ /dev/null @@ -1,540 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" -dependencies = [ - "memchr", -] - -[[package]] -name = "arrayvec" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" - -[[package]] -name = "bitflags" -version = "2.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" - -[[package]] -name = "cfg-if" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" - -[[package]] -name = "cfg_aliases" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" - -[[package]] -name = "env_logger" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a19187fea3ac7e84da7dacf48de0c45d63c6a76f9490dae389aead16c243fce3" -dependencies = [ - "log", - "regex", -] - -[[package]] -name = "errno" -version = "0.3.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" -dependencies = [ - "libc", - "windows-sys 0.60.2", -] - -[[package]] -name = "getrandom" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" -dependencies = [ - "cfg-if", - "libc", - "wasi 0.11.1+wasi-snapshot-preview1", -] - -[[package]] -name = "getrandom" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" -dependencies = [ - "cfg-if", - "libc", - "r-efi", - "wasi 0.14.2+wasi-0.2.4", -] - -[[package]] -name = "itoa" -version = "1.0.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" - -[[package]] -name = "libc" -version = "0.2.174" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1171693293099992e19cddea4e8b849964e9846f4acee11b3948bcc337be8776" - -[[package]] -name = "linux-raw-sys" -version = "0.9.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" - -[[package]] -name = "log" -version = "0.4.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" - -[[package]] -name = "memchr" -version = "2.7.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" - -[[package]] -name = "nix" -version = "0.30.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6" -dependencies = [ - "bitflags", - "cfg-if", - "cfg_aliases", - "libc", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" -dependencies = [ - "zerocopy", -] - -[[package]] -name = "proc-macro2" -version = "1.0.95" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quickcheck" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "588f6378e4dd99458b60ec275b4477add41ce4fa9f64dcba6f15adccb19b50d6" -dependencies = [ - "env_logger", - "log", - "rand 0.8.5", -] - -[[package]] -name = "quote" -version = "1.0.40" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "r-efi" -version = "5.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "rand_core 0.6.4", -] - -[[package]] -name = "rand" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" -dependencies = [ - "rand_chacha", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_chacha" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" -dependencies = [ - "ppv-lite86", - "rand_core 0.9.3", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom 0.2.16", -] - -[[package]] -name = "rand_core" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" -dependencies = [ - "getrandom 0.3.3", -] - -[[package]] -name = "regex" -version = "1.11.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" - -[[package]] -name = "rustix" -version = "1.0.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" -dependencies = [ - "bitflags", - "errno", - "libc", - "linux-raw-sys", - "windows-sys 0.59.0", -] - -[[package]] -name = "ryu" -version = "1.0.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f" - -[[package]] -name = "serde" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.219" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.140" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373" -dependencies = [ - "itoa", - "memchr", - "ryu", - "serde", -] - -[[package]] -name = "syn" -version = "2.0.104" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17b6f705963418cdb9927482fa304bc562ece2fdd4f616084c50b7023b435a40" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "terminal_size" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" -dependencies = [ - "rustix", - "windows-sys 0.59.0", -] - -[[package]] -name = "unicode-ident" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" - -[[package]] -name = "unicode-width" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a1a07cc7db3810833284e8d372ccdc6da29741639ecc70c9ec107df0fa6154c" - -[[package]] -name = "vt100" -version = "0.16.2" -dependencies = [ - "itoa", - "nix", - "quickcheck", - "rand 0.9.1", - "serde", - "serde_json", - "terminal_size", - "unicode-width", - "vte", -] - -[[package]] -name = "vte" -version = "0.15.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5924018406ce0063cd67f8e008104968b74b563ee1b85dde3ed1f7cb87d3dbd" -dependencies = [ - "arrayvec", - "memchr", -] - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "wasi" -version = "0.14.2+wasi-0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" -dependencies = [ - "wit-bindgen-rt", -] - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets 0.52.6", -] - -[[package]] -name = "windows-sys" -version = "0.60.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" -dependencies = [ - "windows-targets 0.53.2", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm 0.52.6", - "windows_aarch64_msvc 0.52.6", - "windows_i686_gnu 0.52.6", - "windows_i686_gnullvm 0.52.6", - "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]] -name = "windows-targets" -version = "0.53.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef" -dependencies = [ - "windows_aarch64_gnullvm 0.53.0", - "windows_aarch64_msvc 0.53.0", - "windows_i686_gnu 0.53.0", - "windows_i686_gnullvm 0.53.0", - "windows_i686_msvc 0.53.0", - "windows_x86_64_gnu 0.53.0", - "windows_x86_64_gnullvm 0.53.0", - "windows_x86_64_msvc 0.53.0", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_i686_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.53.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" - -[[package]] -name = "wit-bindgen-rt" -version = "0.39.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" -dependencies = [ - "bitflags", -] - -[[package]] -name = "zerocopy" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f" -dependencies = [ - "zerocopy-derive", -] - -[[package]] -name = "zerocopy-derive" -version = "0.8.26" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] diff --git a/vendor/vt100/Cargo.toml b/vendor/vt100/Cargo.toml deleted file mode 100644 index 098eea05..00000000 --- a/vendor/vt100/Cargo.toml +++ /dev/null @@ -1,75 +0,0 @@ -# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO -# -# When uploading crates to the registry Cargo will automatically -# "normalize" Cargo.toml files for maximal compatibility -# with all versions of Cargo and also rewrite `path` dependencies -# to registry (e.g., crates.io) dependencies. -# -# If you are reading this file be aware that the original Cargo.toml -# will likely look very different (and much more reasonable). -# See Cargo.toml.orig for the original contents. - -[package] -edition = "2021" -rust-version = "1.70" -name = "vt100" -version = "0.16.2" -authors = ["Jesse Luehrs <doy@tozt.net>"] -build = false -include = [ - "src/**/*", - "LICENSE", - "README.md", - "CHANGELOG.md", -] -autolib = false -autobins = false -autoexamples = false -autotests = false -autobenches = false -description = "Library for parsing terminal data" -homepage = "https://github.com/doy/vt100-rust" -readme = "README.md" -keywords = [ - "terminal", - "vt100", -] -categories = [ - "command-line-interface", - "encoding", -] -license = "MIT" -repository = "https://github.com/doy/vt100-rust" - -[lib] -name = "vt100" -path = "src/lib.rs" - -[dependencies.itoa] -version = "1.0.15" - -[dependencies.unicode-width] -version = "0.2.1" - -[dependencies.vte] -version = "0.15.0" - -[dev-dependencies.nix] -version = "0.30.1" -features = ["term"] - -[dev-dependencies.quickcheck] -version = "1.0" - -[dev-dependencies.rand] -version = "0.9" - -[dev-dependencies.serde] -version = "1.0.219" -features = ["derive"] - -[dev-dependencies.serde_json] -version = "1.0.140" - -[dev-dependencies.terminal_size] -version = "0.4.2" diff --git a/vendor/vt100/Cargo.toml.orig b/vendor/vt100/Cargo.toml.orig deleted file mode 100644 index db35e207..00000000 --- a/vendor/vt100/Cargo.toml.orig +++ /dev/null @@ -1,28 +0,0 @@ -[package] -name = "vt100" -version = "0.16.2" -authors = ["Jesse Luehrs <doy@tozt.net>"] -edition = "2021" -rust-version = "1.70" - -description = "Library for parsing terminal data" -homepage = "https://github.com/doy/vt100-rust" -repository = "https://github.com/doy/vt100-rust" -readme = "README.md" -keywords = ["terminal", "vt100"] -categories = ["command-line-interface", "encoding"] -license = "MIT" -include = ["src/**/*", "LICENSE", "README.md", "CHANGELOG.md"] - -[dependencies] -itoa = "1.0.15" -unicode-width = "0.2.1" -vte = "0.15.0" - -[dev-dependencies] -nix = { version = "0.30.1", features = ["term"] } -quickcheck = "1.0" -rand = "0.9" -serde = { version = "1.0.219", features = ["derive"] } -serde_json = "1.0.140" -terminal_size = "0.4.2" diff --git a/vendor/vt100/LICENSE b/vendor/vt100/LICENSE deleted file mode 100644 index a1dd5b0e..00000000 --- a/vendor/vt100/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2016 Jesse Luehrs - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/vendor/vt100/README.md b/vendor/vt100/README.md deleted file mode 100644 index a8e1b8f6..00000000 --- a/vendor/vt100/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# vt100 - -This crate parses a terminal byte stream and provides an in-memory -representation of the rendered contents. - -## Overview - -This is essentially the terminal parser component of a graphical terminal -emulator pulled out into a separate crate. Although you can use this crate -to build a graphical terminal emulator, it also contains functionality -necessary for implementing terminal applications that want to run other -terminal applications - programs like `screen` or `tmux` for example. - -## Synopsis - -```rust -let mut parser = vt100::Parser::new(24, 80, 0); - -let screen = parser.screen().clone(); -parser.process(b"this text is \x1b[31mRED\x1b[m"); -assert_eq!( - parser.screen().cell(0, 13).unwrap().fgcolor(), - vt100::Color::Idx(1), -); - -let screen = parser.screen().clone(); -parser.process(b"\x1b[3D\x1b[32mGREEN"); -assert_eq!( - parser.screen().contents_formatted(), - &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jthis text is \x1b[32mGREEN"[..], -); -assert_eq!( - parser.screen().contents_diff(&screen), - &b"\x1b[1;14H\x1b[32mGREEN"[..], -); -``` diff --git a/vendor/vt100/src/attrs.rs b/vendor/vt100/src/attrs.rs deleted file mode 100644 index e5044f2e..00000000 --- a/vendor/vt100/src/attrs.rs +++ /dev/null @@ -1,144 +0,0 @@ -use crate::term::BufWrite as _; - -/// Represents a foreground or background color for cells. -#[derive(Eq, PartialEq, Debug, Copy, Clone, Default)] -pub enum Color { - /// The default terminal color. - #[default] - Default, - - /// An indexed terminal color. - Idx(u8), - - /// An RGB terminal color. The parameters are (red, green, blue). - Rgb(u8, u8, u8), -} - -const TEXT_MODE_INTENSITY: u8 = 0b0000_0011; -const TEXT_MODE_BOLD: u8 = 0b0000_0001; -const TEXT_MODE_DIM: u8 = 0b0000_0010; -const TEXT_MODE_ITALIC: u8 = 0b0000_0100; -const TEXT_MODE_UNDERLINE: u8 = 0b0000_1000; -const TEXT_MODE_INVERSE: u8 = 0b0001_0000; - -#[derive(Default, Clone, Copy, PartialEq, Eq, Debug)] -pub struct Attrs { - pub fgcolor: Color, - pub bgcolor: Color, - pub mode: u8, -} - -impl Attrs { - pub fn bold(&self) -> bool { - self.mode & TEXT_MODE_BOLD != 0 - } - - pub fn dim(&self) -> bool { - self.mode & TEXT_MODE_DIM != 0 - } - - fn intensity(&self) -> u8 { - self.mode & TEXT_MODE_INTENSITY - } - - pub fn set_bold(&mut self) { - self.mode &= !TEXT_MODE_INTENSITY; - self.mode |= TEXT_MODE_BOLD; - } - - pub fn set_dim(&mut self) { - self.mode &= !TEXT_MODE_INTENSITY; - self.mode |= TEXT_MODE_DIM; - } - - pub fn set_normal_intensity(&mut self) { - self.mode &= !TEXT_MODE_INTENSITY; - } - - pub fn italic(&self) -> bool { - self.mode & TEXT_MODE_ITALIC != 0 - } - - pub fn set_italic(&mut self, italic: bool) { - if italic { - self.mode |= TEXT_MODE_ITALIC; - } else { - self.mode &= !TEXT_MODE_ITALIC; - } - } - - pub fn underline(&self) -> bool { - self.mode & TEXT_MODE_UNDERLINE != 0 - } - - pub fn set_underline(&mut self, underline: bool) { - if underline { - self.mode |= TEXT_MODE_UNDERLINE; - } else { - self.mode &= !TEXT_MODE_UNDERLINE; - } - } - - pub fn inverse(&self) -> bool { - self.mode & TEXT_MODE_INVERSE != 0 - } - - pub fn set_inverse(&mut self, inverse: bool) { - if inverse { - self.mode |= TEXT_MODE_INVERSE; - } else { - self.mode &= !TEXT_MODE_INVERSE; - } - } - - pub fn write_escape_code_diff( - &self, - contents: &mut Vec<u8>, - other: &Self, - ) { - if self != other && self == &Self::default() { - crate::term::ClearAttrs.write_buf(contents); - return; - } - - let attrs = crate::term::Attrs::default(); - - let attrs = if self.fgcolor == other.fgcolor { - attrs - } else { - attrs.fgcolor(self.fgcolor) - }; - let attrs = if self.bgcolor == other.bgcolor { - attrs - } else { - attrs.bgcolor(self.bgcolor) - }; - let attrs = if self.intensity() == other.intensity() { - attrs - } else { - attrs.intensity(match self.intensity() { - 0 => crate::term::Intensity::Normal, - TEXT_MODE_BOLD => crate::term::Intensity::Bold, - TEXT_MODE_DIM => crate::term::Intensity::Dim, - _ => unreachable!(), - }) - }; - let attrs = if self.italic() == other.italic() { - attrs - } else { - attrs.italic(self.italic()) - }; - let attrs = if self.underline() == other.underline() { - attrs - } else { - attrs.underline(self.underline()) - }; - let attrs = if self.inverse() == other.inverse() { - attrs - } else { - attrs.inverse(self.inverse()) - }; - - attrs.write_buf(contents); - } -} diff --git a/vendor/vt100/src/callbacks.rs b/vendor/vt100/src/callbacks.rs deleted file mode 100644 index cce6f6c0..00000000 --- a/vendor/vt100/src/callbacks.rs +++ /dev/null @@ -1,69 +0,0 @@ -/// This trait is used by the parser to handle extra escape sequences that -/// don't have an impact on the terminal screen directly. -pub trait Callbacks { - /// This callback is called when the terminal requests an audible bell - /// (typically with `^G`). - fn audible_bell(&mut self, _: &mut crate::Screen) {} - /// This callback is called when the terminal requests a visual bell - /// (typically with `\eg`). - fn visual_bell(&mut self, _: &mut crate::Screen) {} - /// This callback is called when the terminal requests a resize - /// (typically with `\e[8;<rows>;<cols>t`). - fn resize(&mut self, _: &mut crate::Screen, _request: (u16, u16)) {} - /// This callback is called when the terminal requests the window title - /// to be set (typically with `\e]1;<icon_name>\a`) - fn set_window_icon_name( - &mut self, - _: &mut crate::Screen, - _icon_name: &[u8], - ) { - } - /// This callback is called when the terminal requests the window title - /// to be set (typically with `\e]2;<title>\a`) - fn set_window_title(&mut self, _: &mut crate::Screen, _title: &[u8]) {} - /// This callback is called when the terminal requests data to be copied - /// to the system clipboard (typically with `\e]52;<ty>;<data>\a`). Note - /// that `data` will be encoded as base64. - fn copy_to_clipboard( - &mut self, - _: &mut crate::Screen, - _ty: &[u8], - _data: &[u8], - ) { - } - /// This callback is called when the terminal requests data to be pasted - /// from the system clipboard (typically with `\e]52;<ty>;?\a`). - fn paste_from_clipboard(&mut self, _: &mut crate::Screen, _ty: &[u8]) {} - /// This callback is called when the terminal receives an escape sequence - /// which is otherwise not implemented. - fn unhandled_char(&mut self, _: &mut crate::Screen, _c: char) {} - /// This callback is called when the terminal receives a control - /// character which is otherwise not implemented. - fn unhandled_control(&mut self, _: &mut crate::Screen, _b: u8) {} - /// This callback is called when the terminal receives an escape sequence - /// which is otherwise not implemented. - fn unhandled_escape( - &mut self, - _: &mut crate::Screen, - _i1: Option<u8>, - _i2: Option<u8>, - _b: u8, - ) { - } - /// This callback is called when the terminal receives a CSI sequence - /// (`\e[`) which is otherwise not implemented. - fn unhandled_csi( - &mut self, - _: &mut crate::Screen, - _i1: Option<u8>, - _i2: Option<u8>, - _params: &[&[u16]], - _c: char, - ) { - } - /// This callback is called when the terminal receives a OSC sequence - /// (`\e]`) which is otherwise not implemented. - fn unhandled_osc(&mut self, _: &mut crate::Screen, _params: &[&[u8]]) {} -} - -impl Callbacks for () {} diff --git a/vendor/vt100/src/cell.rs b/vendor/vt100/src/cell.rs deleted file mode 100644 index c000cf30..00000000 --- a/vendor/vt100/src/cell.rs +++ /dev/null @@ -1,179 +0,0 @@ -use unicode_width::UnicodeWidthChar as _; - -// chosen to make the size of the cell struct 32 bytes -const CONTENT_BYTES: usize = 22; - -const IS_WIDE: u8 = 0b1000_0000; -const IS_WIDE_CONTINUATION: u8 = 0b0100_0000; -const LEN_BITS: u8 = 0b0001_1111; - -/// Represents a single terminal cell. -#[derive(Clone, Debug, Eq)] -pub struct Cell { - contents: [u8; CONTENT_BYTES], - len: u8, - attrs: crate::attrs::Attrs, -} -const _: () = assert!(std::mem::size_of::<Cell>() == 32); - -impl PartialEq<Self> for Cell { - fn eq(&self, other: &Self) -> bool { - if self.len != other.len { - return false; - } - if self.attrs != other.attrs { - return false; - } - let len = self.len(); - self.contents[..len] == other.contents[..len] - } -} - -impl Cell { - pub(crate) fn new() -> Self { - Self { - contents: Default::default(), - len: 0, - attrs: crate::attrs::Attrs::default(), - } - } - - fn len(&self) -> usize { - usize::from(self.len & LEN_BITS) - } - - pub(crate) fn set(&mut self, c: char, a: crate::attrs::Attrs) { - self.len = 0; - self.append_char(0, c); - // strings in this context should always be an arbitrary character - // followed by zero or more zero-width characters, so we should only - // have to look at the first character - self.set_wide(c.width().unwrap_or(1) > 1); - self.attrs = a; - } - - pub(crate) fn append(&mut self, c: char) { - let len = self.len(); - if len >= CONTENT_BYTES - 4 { - return; - } - if len == 0 { - self.contents[0] = b' '; - self.len += 1; - } - - // we already checked that we have space for another codepoint - self.append_char(self.len(), c); - } - - // Writes bytes representing c at start - // Requires caller to verify start <= CODEPOINTS_IN_CELL * 4 - fn append_char(&mut self, start: usize, c: char) { - c.encode_utf8(&mut self.contents[start..]); - self.len += u8::try_from(c.len_utf8()).unwrap(); - } - - pub(crate) fn clear(&mut self, attrs: crate::attrs::Attrs) { - self.len = 0; - self.attrs = attrs; - } - - /// Returns the text contents of the cell. - /// - /// Can include multiple unicode characters if combining characters are - /// used, but will contain at most one character with a non-zero character - /// width. - // Since contents has been constructed by appending chars encoded as UTF-8 it will be valid UTF-8 - #[allow(clippy::missing_panics_doc)] - #[must_use] - pub fn contents(&self) -> &str { - std::str::from_utf8(&self.contents[..self.len()]).unwrap() - } - - /// Returns whether the cell contains any text data. - #[must_use] - pub fn has_contents(&self) -> bool { - self.len() > 0 - } - - /// Returns whether the text data in the cell represents a wide character. - #[must_use] - pub fn is_wide(&self) -> bool { - self.len & IS_WIDE != 0 - } - - /// Returns whether the cell contains the second half of a wide character - /// (in other words, whether the previous cell in the row contains a wide - /// character) - #[must_use] - pub fn is_wide_continuation(&self) -> bool { - self.len & IS_WIDE_CONTINUATION != 0 - } - - fn set_wide(&mut self, wide: bool) { - if wide { - self.len |= IS_WIDE; - } else { - self.len &= !IS_WIDE; - } - } - - pub(crate) fn set_wide_continuation(&mut self, wide: bool) { - if wide { - self.len |= IS_WIDE_CONTINUATION; - } else { - self.len &= !IS_WIDE_CONTINUATION; - } - } - - pub(crate) fn attrs(&self) -> &crate::attrs::Attrs { - &self.attrs - } - - /// Returns the foreground color of the cell. - #[must_use] - pub fn fgcolor(&self) -> crate::Color { - self.attrs.fgcolor - } - - /// Returns the background color of the cell. - #[must_use] - pub fn bgcolor(&self) -> crate::Color { - self.attrs.bgcolor - } - - /// Returns whether the cell should be rendered with the bold text - /// attribute. - #[must_use] - pub fn bold(&self) -> bool { - self.attrs.bold() - } - - /// Returns whether the cell should be rendered with the dim text - /// attribute. - #[must_use] - pub fn dim(&self) -> bool { - self.attrs.dim() - } - - /// Returns whether the cell should be rendered with the italic text - /// attribute. - #[must_use] - pub fn italic(&self) -> bool { - self.attrs.italic() - } - - /// Returns whether the cell should be rendered with the underlined text - /// attribute. - #[must_use] - pub fn underline(&self) -> bool { - self.attrs.underline() - } - - /// Returns whether the cell should be rendered with the inverse text - /// attribute. - #[must_use] - pub fn inverse(&self) -> bool { - self.attrs.inverse() - } -} diff --git a/vendor/vt100/src/grid.rs b/vendor/vt100/src/grid.rs deleted file mode 100644 index f8958579..00000000 --- a/vendor/vt100/src/grid.rs +++ /dev/null @@ -1,740 +0,0 @@ -use crate::term::BufWrite as _; - -#[derive(Clone, Debug)] -pub struct Grid { - size: Size, - pos: Pos, - saved_pos: Pos, - rows: Vec<crate::row::Row>, - scroll_top: u16, - scroll_bottom: u16, - origin_mode: bool, - saved_origin_mode: bool, - scrollback: std::collections::VecDeque<crate::row::Row>, - scrollback_len: usize, - scrollback_offset: usize, -} - -impl Grid { - pub fn new(size: Size, scrollback_len: usize) -> Self { - Self { - size, - pos: Pos::default(), - saved_pos: Pos::default(), - rows: vec![], - scroll_top: 0, - scroll_bottom: size.rows - 1, - origin_mode: false, - saved_origin_mode: false, - scrollback: std::collections::VecDeque::new(), - scrollback_len, - scrollback_offset: 0, - } - } - - pub fn allocate_rows(&mut self) { - if self.rows.is_empty() { - self.rows.extend( - std::iter::repeat_with(|| { - crate::row::Row::new(self.size.cols) - }) - .take(usize::from(self.size.rows)), - ); - } - } - - fn new_row(&self) -> crate::row::Row { - crate::row::Row::new(self.size.cols) - } - - pub fn clear(&mut self) { - self.pos = Pos::default(); - self.saved_pos = Pos::default(); - for row in self.drawing_rows_mut() { - row.clear(crate::attrs::Attrs::default()); - } - self.scroll_top = 0; - self.scroll_bottom = self.size.rows - 1; - self.origin_mode = false; - self.saved_origin_mode = false; - } - - pub fn size(&self) -> Size { - self.size - } - - pub fn set_size(&mut self, size: Size) { - if size.cols != self.size.cols { - for row in &mut self.rows { - row.wrap(false); - } - } - - if self.scroll_bottom == self.size.rows - 1 { - self.scroll_bottom = size.rows - 1; - } - - self.size = size; - for row in &mut self.rows { - row.resize(size.cols, crate::Cell::new()); - } - self.rows.resize(usize::from(size.rows), self.new_row()); - - if self.scroll_bottom >= size.rows { - self.scroll_bottom = size.rows - 1; - } - if self.scroll_bottom < self.scroll_top { - self.scroll_top = 0; - } - - self.row_clamp_top(false); - self.row_clamp_bottom(false); - self.col_clamp(); - - if self.saved_pos.row > self.size.rows - 1 { - self.saved_pos.row = self.size.rows - 1; - } - if self.saved_pos.col > self.size.cols - 1 { - self.saved_pos.col = self.size.cols - 1; - } - } - - pub fn pos(&self) -> Pos { - self.pos - } - - pub fn set_pos(&mut self, mut pos: Pos) { - if self.origin_mode { - pos.row = pos.row.saturating_add(self.scroll_top); - } - self.pos = pos; - self.row_clamp_top(self.origin_mode); - self.row_clamp_bottom(self.origin_mode); - self.col_clamp(); - } - - pub fn save_cursor(&mut self) { - self.saved_pos = self.pos; - self.saved_origin_mode = self.origin_mode; - } - - pub fn restore_cursor(&mut self) { - self.pos = self.saved_pos; - self.origin_mode = self.saved_origin_mode; - } - - pub fn visible_rows(&self) -> impl Iterator<Item = &crate::row::Row> { - let scrollback_len = self.scrollback.len(); - let rows_len = self.rows.len(); - self.scrollback - .iter() - .skip(scrollback_len - self.scrollback_offset) - // when scrollback_offset > rows_len (e.g. rows = 3, - // scrollback_len = 10, offset = 9) the skip(10 - 9) - // will take 9 rows instead of 3. we need to set - // the upper bound to rows_len (e.g. 3) - .take(rows_len) - // same for rows_len - scrollback_offset (e.g. 3 - 9). - // it'll panic with overflow. we have to saturate the subtraction. - .chain( - self.rows - .iter() - .take(rows_len.saturating_sub(self.scrollback_offset)), - ) - } - - pub fn drawing_rows(&self) -> impl Iterator<Item = &crate::row::Row> { - self.rows.iter() - } - - pub fn drawing_rows_mut( - &mut self, - ) -> impl Iterator<Item = &mut crate::row::Row> { - self.rows.iter_mut() - } - - pub fn visible_row(&self, row: u16) -> Option<&crate::row::Row> { - self.visible_rows().nth(usize::from(row)) - } - - pub fn drawing_row(&self, row: u16) -> Option<&crate::row::Row> { - self.drawing_rows().nth(usize::from(row)) - } - - pub fn drawing_row_mut( - &mut self, - row: u16, - ) -> Option<&mut crate::row::Row> { - self.drawing_rows_mut().nth(usize::from(row)) - } - - pub fn current_row_mut(&mut self) -> &mut crate::row::Row { - self.drawing_row_mut(self.pos.row) - // we assume self.pos.row is always valid - .unwrap() - } - - pub fn visible_cell(&self, pos: Pos) -> Option<&crate::Cell> { - self.visible_row(pos.row).and_then(|r| r.get(pos.col)) - } - - pub fn drawing_cell(&self, pos: Pos) -> Option<&crate::Cell> { - self.drawing_row(pos.row).and_then(|r| r.get(pos.col)) - } - - pub fn drawing_cell_mut(&mut self, pos: Pos) -> Option<&mut crate::Cell> { - self.drawing_row_mut(pos.row) - .and_then(|r| r.get_mut(pos.col)) - } - - pub fn scrollback_len(&self) -> usize { - self.scrollback_len - } - - pub fn scrollback(&self) -> usize { - self.scrollback_offset - } - - pub fn set_scrollback(&mut self, rows: usize) { - self.scrollback_offset = rows.min(self.scrollback.len()); - } - - pub fn write_contents(&self, contents: &mut String) { - let mut wrapping = false; - for row in self.visible_rows() { - row.write_contents(contents, 0, self.size.cols, wrapping); - if !row.wrapped() { - contents.push('\n'); - } - wrapping = row.wrapped(); - } - - while contents.ends_with('\n') { - contents.truncate(contents.len() - 1); - } - } - - pub fn write_contents_formatted( - &self, - contents: &mut Vec<u8>, - ) -> crate::attrs::Attrs { - crate::term::ClearAttrs.write_buf(contents); - crate::term::ClearScreen.write_buf(contents); - - let mut prev_attrs = crate::attrs::Attrs::default(); - let mut prev_pos = Pos::default(); - let mut wrapping = false; - for (i, row) in self.visible_rows().enumerate() { - // we limit the number of cols to a u16 (see Size), so - // visible_rows() can never return more rows than will fit - let i = i.try_into().unwrap(); - let (new_pos, new_attrs) = row.write_contents_formatted( - contents, - 0, - self.size.cols, - i, - wrapping, - Some(prev_pos), - Some(prev_attrs), - ); - prev_pos = new_pos; - prev_attrs = new_attrs; - wrapping = row.wrapped(); - } - - self.write_cursor_position_formatted( - contents, - Some(prev_pos), - Some(prev_attrs), - ); - - prev_attrs - } - - pub fn write_contents_diff( - &self, - contents: &mut Vec<u8>, - prev: &Self, - mut prev_attrs: crate::attrs::Attrs, - ) -> crate::attrs::Attrs { - let mut prev_pos = prev.pos; - let mut wrapping = false; - let mut prev_wrapping = false; - for (i, (row, prev_row)) in - self.visible_rows().zip(prev.visible_rows()).enumerate() - { - // we limit the number of cols to a u16 (see Size), so - // visible_rows() can never return more rows than will fit - let i = i.try_into().unwrap(); - let (new_pos, new_attrs) = row.write_contents_diff( - contents, - prev_row, - 0, - self.size.cols, - i, - wrapping, - prev_wrapping, - prev_pos, - prev_attrs, - ); - prev_pos = new_pos; - prev_attrs = new_attrs; - wrapping = row.wrapped(); - prev_wrapping = prev_row.wrapped(); - } - - self.write_cursor_position_formatted( - contents, - Some(prev_pos), - Some(prev_attrs), - ); - - prev_attrs - } - - pub fn write_cursor_position_formatted( - &self, - contents: &mut Vec<u8>, - prev_pos: Option<Pos>, - prev_attrs: Option<crate::attrs::Attrs>, - ) { - let prev_attrs = prev_attrs.unwrap_or_default(); - // writing a character to the last column of a row doesn't wrap the - // cursor immediately - it waits until the next character is actually - // drawn. it is only possible for the cursor to have this kind of - // position after drawing a character though, so if we end in this - // position, we need to redraw the character at the end of the row. - if prev_pos != Some(self.pos) && self.pos.col >= self.size.cols { - let mut pos = Pos { - row: self.pos.row, - col: self.size.cols - 1, - }; - if self - .drawing_cell(pos) - // we assume self.pos.row is always valid, and self.size.cols - // - 1 is always a valid column - .unwrap() - .is_wide_continuation() - { - pos.col = self.size.cols - 2; - } - let cell = - // we assume self.pos.row is always valid, and self.size.cols - // - 2 must be a valid column because self.size.cols - 1 is - // always valid and we just checked that the cell at - // self.size.cols - 1 is a wide continuation character, which - // means that the first half of the wide character must be - // before it - self.drawing_cell(pos).unwrap(); - if cell.has_contents() { - if let Some(prev_pos) = prev_pos { - crate::term::MoveFromTo::new(prev_pos, pos) - .write_buf(contents); - } else { - crate::term::MoveTo::new(pos).write_buf(contents); - } - cell.attrs().write_escape_code_diff(contents, &prev_attrs); - contents.extend(cell.contents().as_bytes()); - prev_attrs.write_escape_code_diff(contents, cell.attrs()); - } else { - // if the cell doesn't have contents, we can't have gotten - // here by drawing a character in the last column. this means - // that as far as i'm aware, we have to have reached here from - // a newline when we were already after the end of an earlier - // row. in the case where we are already after the end of an - // earlier row, we can just write a few newlines, otherwise we - // also need to do the same as above to get ourselves to after - // the end of a row. - let mut found = false; - for i in (0..self.pos.row).rev() { - pos.row = i; - pos.col = self.size.cols - 1; - if self - .drawing_cell(pos) - // i is always less than self.pos.row, which we assume - // to be always valid, so it must also be valid. - // self.size.cols - 1 is always a valid col. - .unwrap() - .is_wide_continuation() - { - pos.col = self.size.cols - 2; - } - let cell = self - .drawing_cell(pos) - // i is always less than self.pos.row, which we assume - // to be always valid, so it must also be valid. - // self.size.cols - 2 is valid because self.size.cols - // - 1 is always valid, and col gets set to - // self.size.cols - 2 when the cell at self.size.cols - // - 1 is a wide continuation character, meaning that - // the first half of the wide character must be before - // it - .unwrap(); - if cell.has_contents() { - if let Some(prev_pos) = prev_pos { - if prev_pos.row != i - || prev_pos.col < self.size.cols - { - crate::term::MoveFromTo::new(prev_pos, pos) - .write_buf(contents); - cell.attrs().write_escape_code_diff( - contents, - &prev_attrs, - ); - contents.extend(cell.contents().as_bytes()); - prev_attrs.write_escape_code_diff( - contents, - cell.attrs(), - ); - } - } else { - crate::term::MoveTo::new(pos).write_buf(contents); - cell.attrs().write_escape_code_diff( - contents, - &prev_attrs, - ); - contents.extend(cell.contents().as_bytes()); - prev_attrs.write_escape_code_diff( - contents, - cell.attrs(), - ); - } - contents.extend( - "\n".repeat(usize::from(self.pos.row - i)) - .as_bytes(), - ); - found = true; - break; - } - } - - // this can happen if you get the cursor off the end of a row, - // and then do something to clear the end of the current row - // without moving the cursor (IL, DL, ED, EL, etc). we know - // there can't be something in the last column because we - // would have caught that above, so it should be safe to - // overwrite it. - if !found { - pos = Pos { - row: self.pos.row, - col: self.size.cols - 1, - }; - if let Some(prev_pos) = prev_pos { - crate::term::MoveFromTo::new(prev_pos, pos) - .write_buf(contents); - } else { - crate::term::MoveTo::new(pos).write_buf(contents); - } - contents.push(b' '); - // we know that the cell has no contents, but it still may - // have drawing attributes (background color, etc) - let end_cell = self - .drawing_cell(pos) - // we assume self.pos.row is always valid, and - // self.size.cols - 1 is always a valid column - .unwrap(); - end_cell - .attrs() - .write_escape_code_diff(contents, &prev_attrs); - crate::term::SaveCursor.write_buf(contents); - crate::term::Backspace.write_buf(contents); - crate::term::EraseChar::new(1).write_buf(contents); - crate::term::RestoreCursor.write_buf(contents); - prev_attrs - .write_escape_code_diff(contents, end_cell.attrs()); - } - } - } else if let Some(prev_pos) = prev_pos { - crate::term::MoveFromTo::new(prev_pos, self.pos) - .write_buf(contents); - } else { - crate::term::MoveTo::new(self.pos).write_buf(contents); - } - } - - pub fn erase_all(&mut self, attrs: crate::attrs::Attrs) { - for row in self.drawing_rows_mut() { - row.clear(attrs); - } - } - - pub fn erase_all_forward(&mut self, attrs: crate::attrs::Attrs) { - let pos = self.pos; - for row in self.drawing_rows_mut().skip(usize::from(pos.row) + 1) { - row.clear(attrs); - } - - self.erase_row_forward(attrs); - } - - pub fn erase_all_backward(&mut self, attrs: crate::attrs::Attrs) { - let pos = self.pos; - for row in self.drawing_rows_mut().take(usize::from(pos.row)) { - row.clear(attrs); - } - - self.erase_row_backward(attrs); - } - - pub fn erase_row(&mut self, attrs: crate::attrs::Attrs) { - self.current_row_mut().clear(attrs); - } - - pub fn erase_row_forward(&mut self, attrs: crate::attrs::Attrs) { - let size = self.size; - let pos = self.pos; - let row = self.current_row_mut(); - for col in pos.col..size.cols { - row.erase(col, attrs); - } - } - - pub fn erase_row_backward(&mut self, attrs: crate::attrs::Attrs) { - let size = self.size; - let pos = self.pos; - let row = self.current_row_mut(); - for col in 0..=pos.col.min(size.cols - 1) { - row.erase(col, attrs); - } - } - - pub fn insert_cells(&mut self, count: u16) { - let size = self.size; - let pos = self.pos; - let wide = pos.col < size.cols - && self - .drawing_cell(pos) - // we assume self.pos.row is always valid, and we know we are - // not off the end of a row because we just checked pos.col < - // size.cols - .unwrap() - .is_wide_continuation(); - let row = self.current_row_mut(); - for _ in 0..count { - if wide { - row.get_mut(pos.col).unwrap().set_wide_continuation(false); - } - row.insert(pos.col, crate::Cell::new()); - if wide { - row.get_mut(pos.col).unwrap().set_wide_continuation(true); - } - } - row.truncate(size.cols); - } - - pub fn delete_cells(&mut self, count: u16) { - let size = self.size; - let pos = self.pos; - let row = self.current_row_mut(); - for _ in 0..(count.min(size.cols - pos.col)) { - row.remove(pos.col); - } - row.resize(size.cols, crate::Cell::new()); - } - - pub fn erase_cells(&mut self, count: u16, attrs: crate::attrs::Attrs) { - let size = self.size; - let pos = self.pos; - let row = self.current_row_mut(); - for col in pos.col..((pos.col.saturating_add(count)).min(size.cols)) { - row.erase(col, attrs); - } - } - - pub fn insert_lines(&mut self, count: u16) { - for _ in 0..count { - self.rows.remove(usize::from(self.scroll_bottom)); - self.rows.insert(usize::from(self.pos.row), self.new_row()); - // self.scroll_bottom is maintained to always be a valid row - self.rows[usize::from(self.scroll_bottom)].wrap(false); - } - } - - pub fn delete_lines(&mut self, count: u16) { - for _ in 0..(count.min(self.size.rows - self.pos.row)) { - self.rows - .insert(usize::from(self.scroll_bottom) + 1, self.new_row()); - self.rows.remove(usize::from(self.pos.row)); - } - } - - pub fn scroll_up(&mut self, count: u16) { - for _ in 0..(count.min(self.size.rows - self.scroll_top)) { - self.rows - .insert(usize::from(self.scroll_bottom) + 1, self.new_row()); - let removed = self.rows.remove(usize::from(self.scroll_top)); - // Top-anchored scroll regions still represent terminal output moving - // off the visible transcript and should feed host scrollback. - if self.scrollback_len > 0 && self.scroll_top == 0 { - self.scrollback.push_back(removed); - while self.scrollback.len() > self.scrollback_len { - self.scrollback.pop_front(); - } - if self.scrollback_offset > 0 { - self.scrollback_offset = - self.scrollback.len().min(self.scrollback_offset + 1); - } - } - } - } - - pub fn scroll_down(&mut self, count: u16) { - for _ in 0..count { - self.rows.remove(usize::from(self.scroll_bottom)); - self.rows - .insert(usize::from(self.scroll_top), self.new_row()); - // self.scroll_bottom is maintained to always be a valid row - self.rows[usize::from(self.scroll_bottom)].wrap(false); - } - } - - pub fn set_scroll_region(&mut self, top: u16, bottom: u16) { - let bottom = bottom.min(self.size().rows - 1); - if top < bottom { - self.scroll_top = top; - self.scroll_bottom = bottom; - } else { - self.scroll_top = 0; - self.scroll_bottom = self.size().rows - 1; - } - self.pos.row = self.scroll_top; - self.pos.col = 0; - } - - fn in_scroll_region(&self) -> bool { - self.pos.row >= self.scroll_top && self.pos.row <= self.scroll_bottom - } - - pub fn set_origin_mode(&mut self, mode: bool) { - self.origin_mode = mode; - self.set_pos(Pos { row: 0, col: 0 }); - } - - pub fn row_inc_clamp(&mut self, count: u16) { - let in_scroll_region = self.in_scroll_region(); - self.pos.row = self.pos.row.saturating_add(count); - self.row_clamp_bottom(in_scroll_region); - } - - pub fn row_inc_scroll(&mut self, count: u16) -> u16 { - let in_scroll_region = self.in_scroll_region(); - self.pos.row = self.pos.row.saturating_add(count); - let lines = self.row_clamp_bottom(in_scroll_region); - if in_scroll_region { - self.scroll_up(lines); - lines - } else { - 0 - } - } - - pub fn row_dec_clamp(&mut self, count: u16) { - let in_scroll_region = self.in_scroll_region(); - self.pos.row = self.pos.row.saturating_sub(count); - self.row_clamp_top(in_scroll_region); - } - - pub fn row_dec_scroll(&mut self, count: u16) { - let in_scroll_region = self.in_scroll_region(); - // need to account for clamping by both row_clamp_top and by - // saturating_sub - let extra_lines = count.saturating_sub(self.pos.row); - self.pos.row = self.pos.row.saturating_sub(count); - let lines = self.row_clamp_top(in_scroll_region); - self.scroll_down(lines + extra_lines); - } - - pub fn row_set(&mut self, i: u16) { - self.pos.row = i; - self.row_clamp(); - } - - pub fn col_inc(&mut self, count: u16) { - self.pos.col = self.pos.col.saturating_add(count); - } - - pub fn col_inc_clamp(&mut self, count: u16) { - self.pos.col = self.pos.col.saturating_add(count); - self.col_clamp(); - } - - pub fn col_dec(&mut self, count: u16) { - self.pos.col = self.pos.col.saturating_sub(count); - } - - pub fn col_tab(&mut self) { - self.pos.col -= self.pos.col % 8; - self.pos.col += 8; - self.col_clamp(); - } - - pub fn col_set(&mut self, i: u16) { - self.pos.col = i; - self.col_clamp(); - } - - pub fn col_wrap(&mut self, width: u16, wrap: bool) { - if self.pos.col > self.size.cols - width { - let mut prev_pos = self.pos; - self.pos.col = 0; - let scrolled = self.row_inc_scroll(1); - prev_pos.row -= scrolled; - let new_pos = self.pos; - self.drawing_row_mut(prev_pos.row) - // we assume self.pos.row is always valid, and so prev_pos.row - // must be valid because it is always less than or equal to - // self.pos.row - .unwrap() - .wrap(wrap && prev_pos.row + 1 == new_pos.row); - } - } - - fn row_clamp_top(&mut self, limit_to_scroll_region: bool) -> u16 { - if limit_to_scroll_region && self.pos.row < self.scroll_top { - let rows = self.scroll_top - self.pos.row; - self.pos.row = self.scroll_top; - rows - } else { - 0 - } - } - - fn row_clamp_bottom(&mut self, limit_to_scroll_region: bool) -> u16 { - let bottom = if limit_to_scroll_region { - self.scroll_bottom - } else { - self.size.rows - 1 - }; - if self.pos.row > bottom { - let rows = self.pos.row - bottom; - self.pos.row = bottom; - rows - } else { - 0 - } - } - - fn row_clamp(&mut self) { - if self.pos.row > self.size.rows - 1 { - self.pos.row = self.size.rows - 1; - } - } - - fn col_clamp(&mut self) { - if self.pos.col > self.size.cols - 1 { - self.pos.col = self.size.cols - 1; - } - } -} - -#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] -pub struct Size { - pub rows: u16, - pub cols: u16, -} - -#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] -pub struct Pos { - pub row: u16, - pub col: u16, -} diff --git a/vendor/vt100/src/lib.rs b/vendor/vt100/src/lib.rs deleted file mode 100644 index 19746a94..00000000 --- a/vendor/vt100/src/lib.rs +++ /dev/null @@ -1,64 +0,0 @@ -//! This crate parses a terminal byte stream and provides an in-memory -//! representation of the rendered contents. -//! -//! # Overview -//! -//! This is essentially the terminal parser component of a graphical terminal -//! emulator pulled out into a separate crate. Although you can use this crate -//! to build a graphical terminal emulator, it also contains functionality -//! necessary for implementing terminal applications that want to run other -//! terminal applications - programs like `screen` or `tmux` for example. -//! -//! # Synopsis -//! -//! ``` -//! let mut parser = vt100::Parser::new(24, 80, 0); -//! -//! let screen = parser.screen().clone(); -//! parser.process(b"this text is \x1b[31mRED\x1b[m"); -//! assert_eq!( -//! parser.screen().cell(0, 13).unwrap().fgcolor(), -//! vt100::Color::Idx(1), -//! ); -//! -//! let screen = parser.screen().clone(); -//! parser.process(b"\x1b[3D\x1b[32mGREEN"); -//! assert_eq!( -//! parser.screen().contents_formatted(), -//! &b"\x1b[?25h\x1b[m\x1b[H\x1b[Jthis text is \x1b[32mGREEN"[..], -//! ); -//! assert_eq!( -//! parser.screen().contents_diff(&screen), -//! &b"\x1b[1;14H\x1b[32mGREEN"[..], -//! ); -//! ``` - -#![warn(missing_docs)] -#![warn(clippy::cargo)] -#![warn(clippy::pedantic)] -#![warn(clippy::nursery)] -#![warn(clippy::as_conversions)] -#![warn(clippy::get_unwrap)] -#![allow(clippy::cognitive_complexity)] -#![allow(clippy::missing_const_for_fn)] -#![allow(clippy::similar_names)] -#![allow(clippy::struct_excessive_bools)] -#![allow(clippy::too_many_arguments)] -#![allow(clippy::too_many_lines)] -#![allow(clippy::type_complexity)] - -mod attrs; -mod callbacks; -mod cell; -mod grid; -mod parser; -mod perform; -mod row; -mod screen; -mod term; - -pub use attrs::Color; -pub use callbacks::Callbacks; -pub use cell::Cell; -pub use parser::Parser; -pub use screen::{MouseProtocolEncoding, MouseProtocolMode, Screen}; diff --git a/vendor/vt100/src/parser.rs b/vendor/vt100/src/parser.rs deleted file mode 100644 index c81495b8..00000000 --- a/vendor/vt100/src/parser.rs +++ /dev/null @@ -1,96 +0,0 @@ -/// A parser for terminal output which produces an in-memory representation of -/// the terminal contents. -pub struct Parser<CB: crate::callbacks::Callbacks = ()> { - parser: vte::Parser, - screen: crate::perform::WrappedScreen<CB>, -} - -impl Parser { - /// Creates a new terminal parser of the given size and with the given - /// amount of scrollback. - #[must_use] - pub fn new(rows: u16, cols: u16, scrollback_len: usize) -> Self { - Self { - parser: vte::Parser::new(), - screen: crate::perform::WrappedScreen::new( - rows, - cols, - scrollback_len, - ), - } - } -} - -impl<CB: crate::callbacks::Callbacks> Parser<CB> { - /// Creates a new terminal parser of the given size and with the given - /// amount of scrollback. Terminal events will be reported via method - /// calls on the provided [`Callbacks`](crate::callbacks::Callbacks) - /// implementation. - pub fn new_with_callbacks( - rows: u16, - cols: u16, - scrollback_len: usize, - callbacks: CB, - ) -> Self { - Self { - parser: vte::Parser::new(), - screen: crate::perform::WrappedScreen::new_with_callbacks( - rows, - cols, - scrollback_len, - callbacks, - ), - } - } - - /// Processes the contents of the given byte string, and updates the - /// in-memory terminal state. - pub fn process(&mut self, bytes: &[u8]) { - self.parser.advance(&mut self.screen, bytes); - } - - /// Returns a reference to a [`Screen`](crate::Screen) object containing - /// the terminal state. - #[must_use] - pub fn screen(&self) -> &crate::Screen { - &self.screen.screen - } - - /// Returns a mutable reference to a [`Screen`](crate::Screen) object - /// containing the terminal state. - #[must_use] - pub fn screen_mut(&mut self) -> &mut crate::Screen { - &mut self.screen.screen - } - - /// Returns a reference to the [`Callbacks`](crate::callbacks::Callbacks) - /// state object passed into the constructor. - pub fn callbacks(&self) -> &CB { - &self.screen.callbacks - } - - /// Returns a mutable reference to the - /// [`Callbacks`](crate::callbacks::Callbacks) state object passed into - /// the constructor. - pub fn callbacks_mut(&mut self) -> &mut CB { - &mut self.screen.callbacks - } -} - -impl Default for Parser { - /// Returns a parser with dimensions 80x24 and no scrollback. - fn default() -> Self { - Self::new(24, 80, 0) - } -} - -impl std::io::Write for Parser { - fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> { - self.process(buf); - Ok(buf.len()) - } - - fn flush(&mut self) -> std::io::Result<()> { - Ok(()) - } -} diff --git a/vendor/vt100/src/perform.rs b/vendor/vt100/src/perform.rs deleted file mode 100644 index e36cfd83..00000000 --- a/vendor/vt100/src/perform.rs +++ /dev/null @@ -1,277 +0,0 @@ -const BASE64: &[u8] = - b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; -const CLIPBOARD_SELECTOR: &[u8] = b"cpqs01234567"; - -pub struct WrappedScreen<CB: crate::callbacks::Callbacks = ()> { - pub screen: crate::screen::Screen, - pub callbacks: CB, -} - -impl WrappedScreen<()> { - pub fn new(rows: u16, cols: u16, scrollback_len: usize) -> Self { - Self::new_with_callbacks(rows, cols, scrollback_len, ()) - } -} - -impl<CB: crate::callbacks::Callbacks> WrappedScreen<CB> { - pub fn new_with_callbacks( - rows: u16, - cols: u16, - scrollback_len: usize, - callbacks: CB, - ) -> Self { - Self { - screen: crate::screen::Screen::new( - crate::grid::Size { rows, cols }, - scrollback_len, - ), - callbacks, - } - } -} - -impl<CB: crate::callbacks::Callbacks> vte::Perform for WrappedScreen<CB> { - fn print(&mut self, c: char) { - if c == '\u{fffd}' || ('\u{80}'..'\u{a0}').contains(&c) { - self.callbacks.unhandled_char(&mut self.screen, c); - } else { - self.screen.text(c); - } - } - - fn execute(&mut self, b: u8) { - match b { - 7 => self.callbacks.audible_bell(&mut self.screen), - 8 => self.screen.bs(), - 9 => self.screen.tab(), - 10 => self.screen.lf(), - 11 => self.screen.vt(), - 12 => self.screen.ff(), - 13 => self.screen.cr(), - // we don't implement shift in/out alternate character sets, but - // it shouldn't count as an "error" - 14 | 15 => {} - _ => self.callbacks.unhandled_control(&mut self.screen, b), - } - } - - fn esc_dispatch(&mut self, intermediates: &[u8], _ignore: bool, b: u8) { - if let Some(i) = intermediates.first() { - self.callbacks.unhandled_escape( - &mut self.screen, - Some(*i), - intermediates.get(1).copied(), - b, - ); - } else { - match b { - b'7' => self.screen.decsc(), - b'8' => self.screen.decrc(), - b'=' => self.screen.deckpam(), - b'>' => self.screen.deckpnm(), - b'M' => self.screen.ri(), - b'c' => self.screen.ris(), - b'g' => self.callbacks.visual_bell(&mut self.screen), - _ => { - self.callbacks.unhandled_escape( - &mut self.screen, - None, - None, - b, - ); - } - } - } - } - - fn csi_dispatch( - &mut self, - params: &vte::Params, - intermediates: &[u8], - _ignore: bool, - c: char, - ) { - let unhandled = |screen: &mut crate::screen::Screen| { - self.callbacks.unhandled_csi( - screen, - intermediates.first().copied(), - intermediates.get(1).copied(), - ¶ms.iter().collect::<Vec<_>>(), - c, - ); - }; - match intermediates.first() { - None => match c { - '@' => self.screen.ich(canonicalize_params_1(params, 1)), - 'A' => self.screen.cuu(canonicalize_params_1(params, 1)), - 'B' => self.screen.cud(canonicalize_params_1(params, 1)), - 'C' => self.screen.cuf(canonicalize_params_1(params, 1)), - 'D' => self.screen.cub(canonicalize_params_1(params, 1)), - 'E' => self.screen.cnl(canonicalize_params_1(params, 1)), - 'F' => self.screen.cpl(canonicalize_params_1(params, 1)), - 'G' => self.screen.cha(canonicalize_params_1(params, 1)), - 'H' => self.screen.cup(canonicalize_params_2(params, 1, 1)), - 'J' => self - .screen - .ed(canonicalize_params_1(params, 0), unhandled), - 'K' => self - .screen - .el(canonicalize_params_1(params, 0), unhandled), - 'L' => self.screen.il(canonicalize_params_1(params, 1)), - 'M' => self.screen.dl(canonicalize_params_1(params, 1)), - 'P' => self.screen.dch(canonicalize_params_1(params, 1)), - 'S' => self.screen.su(canonicalize_params_1(params, 1)), - 'T' => self.screen.sd(canonicalize_params_1(params, 1)), - 'X' => self.screen.ech(canonicalize_params_1(params, 1)), - 'd' => self.screen.vpa(canonicalize_params_1(params, 1)), - 'm' => self.screen.sgr(params, unhandled), - 'r' => self.screen.decstbm(canonicalize_params_decstbm( - params, - self.screen.grid().size(), - )), - 't' => { - let mut params_iter = params.iter(); - let op = - params_iter.next().and_then(|x| x.first().copied()); - if op == Some(8) { - let (screen_rows, screen_cols) = self.screen.size(); - let rows = - params_iter.next().map_or(screen_rows, |x| { - *x.first().unwrap_or(&screen_rows) - }); - let cols = - params_iter.next().map_or(screen_cols, |x| { - *x.first().unwrap_or(&screen_cols) - }); - self.callbacks.resize(&mut self.screen, (rows, cols)); - } else { - self.callbacks.unhandled_csi( - &mut self.screen, - None, - None, - ¶ms.iter().collect::<Vec<_>>(), - c, - ); - } - } - _ => { - self.callbacks.unhandled_csi( - &mut self.screen, - None, - None, - ¶ms.iter().collect::<Vec<_>>(), - c, - ); - } - }, - Some(b'?') => match c { - 'J' => self - .screen - .decsed(canonicalize_params_1(params, 0), unhandled), - 'K' => self - .screen - .decsel(canonicalize_params_1(params, 0), unhandled), - 'h' => self.screen.decset(params, unhandled), - 'l' => self.screen.decrst(params, unhandled), - _ => { - self.callbacks.unhandled_csi( - &mut self.screen, - Some(b'?'), - intermediates.get(1).copied(), - ¶ms.iter().collect::<Vec<_>>(), - c, - ); - } - }, - Some(i) => { - self.callbacks.unhandled_csi( - &mut self.screen, - Some(*i), - intermediates.get(1).copied(), - ¶ms.iter().collect::<Vec<_>>(), - c, - ); - } - } - } - - fn osc_dispatch(&mut self, params: &[&[u8]], _bel_terminated: bool) { - match params { - [b"0", s] => { - self.callbacks.set_window_icon_name(&mut self.screen, s); - self.callbacks.set_window_title(&mut self.screen, s); - } - [b"1", s] => { - self.callbacks.set_window_icon_name(&mut self.screen, s); - } - [b"2", s] => { - self.callbacks.set_window_title(&mut self.screen, s); - } - [b"52", ty, data] => { - match ( - ty.iter().all(|c| CLIPBOARD_SELECTOR.contains(c)), - *data, - ) { - (true, b"?") => { - self.callbacks - .paste_from_clipboard(&mut self.screen, ty); - } - (true, data) - if data.iter().all(|c| BASE64.contains(c)) => - { - self.callbacks.copy_to_clipboard( - &mut self.screen, - ty, - data, - ); - } - _ => { - self.callbacks - .unhandled_osc(&mut self.screen, params); - } - } - } - _ => { - self.callbacks.unhandled_osc(&mut self.screen, params); - } - } - } -} - -fn canonicalize_params_1(params: &vte::Params, default: u16) -> u16 { - let first = params.iter().next().map_or(0, |x| *x.first().unwrap_or(&0)); - if first == 0 { - default - } else { - first - } -} - -fn canonicalize_params_2( - params: &vte::Params, - default1: u16, - default2: u16, -) -> (u16, u16) { - let mut iter = params.iter(); - let first = iter.next().map_or(0, |x| *x.first().unwrap_or(&0)); - let first = if first == 0 { default1 } else { first }; - - let second = iter.next().map_or(0, |x| *x.first().unwrap_or(&0)); - let second = if second == 0 { default2 } else { second }; - - (first, second) -} - -fn canonicalize_params_decstbm( - params: &vte::Params, - size: crate::grid::Size, -) -> (u16, u16) { - let mut iter = params.iter(); - let top = iter.next().map_or(0, |x| *x.first().unwrap_or(&0)); - let top = if top == 0 { 1 } else { top }; - - let bottom = iter.next().map_or(0, |x| *x.first().unwrap_or(&0)); - let bottom = if bottom == 0 { size.rows } else { bottom }; - - (top, bottom) -} diff --git a/vendor/vt100/src/row.rs b/vendor/vt100/src/row.rs deleted file mode 100644 index 4ae8d868..00000000 --- a/vendor/vt100/src/row.rs +++ /dev/null @@ -1,474 +0,0 @@ -use crate::term::BufWrite as _; - -#[derive(Clone, Debug)] -pub struct Row { - cells: Vec<crate::Cell>, - wrapped: bool, -} - -impl Row { - pub fn new(cols: u16) -> Self { - Self { - cells: vec![crate::Cell::new(); usize::from(cols)], - wrapped: false, - } - } - - fn cols(&self) -> u16 { - self.cells - .len() - .try_into() - // we limit the number of cols to a u16 (see Size) - .unwrap() - } - - pub fn clear(&mut self, attrs: crate::attrs::Attrs) { - for cell in &mut self.cells { - cell.clear(attrs); - } - self.wrapped = false; - } - - fn cells(&self) -> impl Iterator<Item = &crate::Cell> { - self.cells.iter() - } - - pub fn get(&self, col: u16) -> Option<&crate::Cell> { - self.cells.get(usize::from(col)) - } - - pub fn get_mut(&mut self, col: u16) -> Option<&mut crate::Cell> { - self.cells.get_mut(usize::from(col)) - } - - pub fn insert(&mut self, i: u16, cell: crate::Cell) { - self.cells.insert(usize::from(i), cell); - self.wrapped = false; - } - - pub fn remove(&mut self, i: u16) { - self.clear_wide(i); - self.cells.remove(usize::from(i)); - self.wrapped = false; - } - - pub fn erase(&mut self, i: u16, attrs: crate::attrs::Attrs) { - let wide = self.cells[usize::from(i)].is_wide(); - self.clear_wide(i); - self.cells[usize::from(i)].clear(attrs); - if i == self.cols() - if wide { 2 } else { 1 } { - self.wrapped = false; - } - } - - pub fn truncate(&mut self, len: u16) { - self.cells.truncate(usize::from(len)); - self.wrapped = false; - let last_cell = &mut self.cells[usize::from(len) - 1]; - if last_cell.is_wide() { - last_cell.clear(*last_cell.attrs()); - } - } - - pub fn resize(&mut self, len: u16, cell: crate::Cell) { - self.cells.resize(usize::from(len), cell); - self.wrapped = false; - } - - pub fn wrap(&mut self, wrap: bool) { - self.wrapped = wrap; - } - - pub fn wrapped(&self) -> bool { - self.wrapped - } - - pub fn clear_wide(&mut self, col: u16) { - let cell = &self.cells[usize::from(col)]; - let other = if cell.is_wide() { - &mut self.cells[usize::from(col + 1)] - } else if cell.is_wide_continuation() { - &mut self.cells[usize::from(col - 1)] - } else { - return; - }; - other.clear(*other.attrs()); - } - - pub fn write_contents( - &self, - contents: &mut String, - start: u16, - width: u16, - wrapping: bool, - ) { - let mut prev_was_wide = false; - - let mut prev_col = start; - for (col, cell) in self - .cells() - .enumerate() - .skip(usize::from(start)) - .take(usize::from(width)) - { - if prev_was_wide { - prev_was_wide = false; - continue; - } - prev_was_wide = cell.is_wide(); - - // we limit the number of cols to a u16 (see Size) - let col: u16 = col.try_into().unwrap(); - if cell.has_contents() { - for _ in 0..(col - prev_col) { - contents.push(' '); - } - prev_col += col - prev_col; - - contents.push_str(cell.contents()); - prev_col += if cell.is_wide() { 2 } else { 1 }; - } - } - if prev_col == start && wrapping { - contents.push('\n'); - } - } - - pub fn write_contents_formatted( - &self, - contents: &mut Vec<u8>, - start: u16, - width: u16, - row: u16, - wrapping: bool, - prev_pos: Option<crate::grid::Pos>, - prev_attrs: Option<crate::attrs::Attrs>, - ) -> (crate::grid::Pos, crate::attrs::Attrs) { - let mut prev_was_wide = false; - let default_cell = crate::Cell::new(); - - let mut prev_pos = prev_pos.unwrap_or_else(|| { - if wrapping { - crate::grid::Pos { - row: row - 1, - col: self.cols(), - } - } else { - crate::grid::Pos { row, col: start } - } - }); - let mut prev_attrs = prev_attrs.unwrap_or_default(); - - let first_cell = &self.cells[usize::from(start)]; - if wrapping && first_cell == &default_cell { - let default_attrs = default_cell.attrs(); - if &prev_attrs != default_attrs { - default_attrs.write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *default_attrs; - } - contents.push(b' '); - crate::term::Backspace.write_buf(contents); - crate::term::EraseChar::new(1).write_buf(contents); - prev_pos = crate::grid::Pos { row, col: 0 }; - } - - let mut erase: Option<(u16, &crate::attrs::Attrs)> = None; - for (col, cell) in self - .cells() - .enumerate() - .skip(usize::from(start)) - .take(usize::from(width)) - { - if prev_was_wide { - prev_was_wide = false; - continue; - } - prev_was_wide = cell.is_wide(); - - // we limit the number of cols to a u16 (see Size) - let col: u16 = col.try_into().unwrap(); - let pos = crate::grid::Pos { row, col }; - - if let Some((prev_col, attrs)) = erase { - if cell.has_contents() || cell.attrs() != attrs { - let new_pos = crate::grid::Pos { row, col: prev_col }; - if wrapping - && prev_pos.row + 1 == new_pos.row - && prev_pos.col >= self.cols() - { - if new_pos.col > 0 { - contents.extend( - " ".repeat(usize::from(new_pos.col)) - .as_bytes(), - ); - } else { - contents.extend(b" "); - crate::term::Backspace.write_buf(contents); - } - } else { - crate::term::MoveFromTo::new(prev_pos, new_pos) - .write_buf(contents); - } - prev_pos = new_pos; - if &prev_attrs != attrs { - attrs.write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *attrs; - } - crate::term::EraseChar::new(pos.col - prev_col) - .write_buf(contents); - erase = None; - } - } - - if cell != &default_cell { - let attrs = cell.attrs(); - if cell.has_contents() { - if pos != prev_pos { - if !wrapping - || prev_pos.row + 1 != pos.row - || prev_pos.col - < self.cols() - u16::from(cell.is_wide()) - || pos.col != 0 - { - crate::term::MoveFromTo::new(prev_pos, pos) - .write_buf(contents); - } - prev_pos = pos; - } - - if &prev_attrs != attrs { - attrs.write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *attrs; - } - - prev_pos.col += if cell.is_wide() { 2 } else { 1 }; - let cell_contents = cell.contents(); - contents.extend(cell_contents.as_bytes()); - } else if erase.is_none() { - erase = Some((pos.col, attrs)); - } - } - } - if let Some((prev_col, attrs)) = erase { - let new_pos = crate::grid::Pos { row, col: prev_col }; - if wrapping - && prev_pos.row + 1 == new_pos.row - && prev_pos.col >= self.cols() - { - if new_pos.col > 0 { - contents.extend( - " ".repeat(usize::from(new_pos.col)).as_bytes(), - ); - } else { - contents.extend(b" "); - crate::term::Backspace.write_buf(contents); - } - } else { - crate::term::MoveFromTo::new(prev_pos, new_pos) - .write_buf(contents); - } - prev_pos = new_pos; - if &prev_attrs != attrs { - attrs.write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *attrs; - } - crate::term::ClearRowForward.write_buf(contents); - } - - (prev_pos, prev_attrs) - } - - // while it's true that most of the logic in this is identical to - // write_contents_formatted, i can't figure out how to break out the - // common parts without making things noticeably slower. - pub fn write_contents_diff( - &self, - contents: &mut Vec<u8>, - prev: &Self, - start: u16, - width: u16, - row: u16, - wrapping: bool, - prev_wrapping: bool, - mut prev_pos: crate::grid::Pos, - mut prev_attrs: crate::attrs::Attrs, - ) -> (crate::grid::Pos, crate::attrs::Attrs) { - let mut prev_was_wide = false; - - let first_cell = &self.cells[usize::from(start)]; - let prev_first_cell = &prev.cells[usize::from(start)]; - if wrapping - && !prev_wrapping - && first_cell == prev_first_cell - && prev_pos.row + 1 == row - && prev_pos.col - >= self.cols() - u16::from(prev_first_cell.is_wide()) - { - let first_cell_attrs = first_cell.attrs(); - if &prev_attrs != first_cell_attrs { - first_cell_attrs - .write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *first_cell_attrs; - } - let mut cell_contents = prev_first_cell.contents(); - let need_erase = if cell_contents.is_empty() { - cell_contents = " "; - true - } else { - false - }; - contents.extend(cell_contents.as_bytes()); - crate::term::Backspace.write_buf(contents); - if prev_first_cell.is_wide() { - crate::term::Backspace.write_buf(contents); - } - if need_erase { - crate::term::EraseChar::new(1).write_buf(contents); - } - prev_pos = crate::grid::Pos { row, col: 0 }; - } - - let mut erase: Option<(u16, &crate::attrs::Attrs)> = None; - for (col, (cell, prev_cell)) in self - .cells() - .zip(prev.cells()) - .enumerate() - .skip(usize::from(start)) - .take(usize::from(width)) - { - if prev_was_wide { - prev_was_wide = false; - continue; - } - prev_was_wide = cell.is_wide(); - - // we limit the number of cols to a u16 (see Size) - let col: u16 = col.try_into().unwrap(); - let pos = crate::grid::Pos { row, col }; - - if let Some((prev_col, attrs)) = erase { - if cell.has_contents() || cell.attrs() != attrs { - let new_pos = crate::grid::Pos { row, col: prev_col }; - if wrapping - && prev_pos.row + 1 == new_pos.row - && prev_pos.col >= self.cols() - { - if new_pos.col > 0 { - contents.extend( - " ".repeat(usize::from(new_pos.col)) - .as_bytes(), - ); - } else { - contents.extend(b" "); - crate::term::Backspace.write_buf(contents); - } - } else { - crate::term::MoveFromTo::new(prev_pos, new_pos) - .write_buf(contents); - } - prev_pos = new_pos; - if &prev_attrs != attrs { - attrs.write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *attrs; - } - crate::term::EraseChar::new(pos.col - prev_col) - .write_buf(contents); - erase = None; - } - } - - if cell != prev_cell { - let attrs = cell.attrs(); - if cell.has_contents() { - if pos != prev_pos { - if !wrapping - || prev_pos.row + 1 != pos.row - || prev_pos.col - < self.cols() - u16::from(cell.is_wide()) - || pos.col != 0 - { - crate::term::MoveFromTo::new(prev_pos, pos) - .write_buf(contents); - } - prev_pos = pos; - } - - if &prev_attrs != attrs { - attrs.write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *attrs; - } - - prev_pos.col += if cell.is_wide() { 2 } else { 1 }; - contents.extend(cell.contents().as_bytes()); - } else if erase.is_none() { - erase = Some((pos.col, attrs)); - } - } - } - if let Some((prev_col, attrs)) = erase { - let new_pos = crate::grid::Pos { row, col: prev_col }; - if wrapping - && prev_pos.row + 1 == new_pos.row - && prev_pos.col >= self.cols() - { - if new_pos.col > 0 { - contents.extend( - " ".repeat(usize::from(new_pos.col)).as_bytes(), - ); - } else { - contents.extend(b" "); - crate::term::Backspace.write_buf(contents); - } - } else { - crate::term::MoveFromTo::new(prev_pos, new_pos) - .write_buf(contents); - } - prev_pos = new_pos; - if &prev_attrs != attrs { - attrs.write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *attrs; - } - crate::term::ClearRowForward.write_buf(contents); - } - - // if this row is going from wrapped to not wrapped, we need to erase - // and redraw the last character to break wrapping. if this row is - // wrapped, we need to redraw the last character without erasing it to - // position the cursor after the end of the line correctly so that - // drawing the next line can just start writing and be wrapped. - if (!self.wrapped && prev.wrapped) || (!prev.wrapped && self.wrapped) - { - let end_pos = if self.cells[usize::from(self.cols() - 1)] - .is_wide_continuation() - { - crate::grid::Pos { - row, - col: self.cols() - 2, - } - } else { - crate::grid::Pos { - row, - col: self.cols() - 1, - } - }; - crate::term::MoveFromTo::new(prev_pos, end_pos) - .write_buf(contents); - prev_pos = end_pos; - if !self.wrapped { - crate::term::EraseChar::new(1).write_buf(contents); - } - let end_cell = &self.cells[usize::from(end_pos.col)]; - if end_cell.has_contents() { - let attrs = end_cell.attrs(); - if &prev_attrs != attrs { - attrs.write_escape_code_diff(contents, &prev_attrs); - prev_attrs = *attrs; - } - contents.extend(end_cell.contents().as_bytes()); - prev_pos.col += if end_cell.is_wide() { 2 } else { 1 }; - } - } - - (prev_pos, prev_attrs) - } -} diff --git a/vendor/vt100/src/screen.rs b/vendor/vt100/src/screen.rs deleted file mode 100644 index 7dfec97d..00000000 --- a/vendor/vt100/src/screen.rs +++ /dev/null @@ -1,1354 +0,0 @@ -use crate::term::BufWrite as _; -use unicode_width::UnicodeWidthChar as _; - -const MODE_APPLICATION_KEYPAD: u8 = 0b0000_0001; -const MODE_APPLICATION_CURSOR: u8 = 0b0000_0010; -const MODE_HIDE_CURSOR: u8 = 0b0000_0100; -const MODE_ALTERNATE_SCREEN: u8 = 0b0000_1000; -const MODE_BRACKETED_PASTE: u8 = 0b0001_0000; - -/// The xterm mouse handling mode currently in use. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] -pub enum MouseProtocolMode { - /// Mouse handling is disabled. - #[default] - None, - - /// Mouse button events should be reported on button press. Also known as - /// X10 mouse mode. - Press, - - /// Mouse button events should be reported on button press and release. - /// Also known as VT200 mouse mode. - PressRelease, - - // Highlight, - /// Mouse button events should be reported on button press and release, as - /// well as when the mouse moves between cells while a button is held - /// down. - ButtonMotion, - - /// Mouse button events should be reported on button press and release, - /// and mouse motion events should be reported when the mouse moves - /// between cells regardless of whether a button is held down or not. - AnyMotion, - // DecLocator, -} - -/// The encoding to use for the enabled [`MouseProtocolMode`]. -#[derive(Copy, Clone, Debug, Eq, PartialEq, Default)] -pub enum MouseProtocolEncoding { - /// Default single-printable-byte encoding. - #[default] - Default, - - /// UTF-8-based encoding. - Utf8, - - /// SGR-like encoding. - Sgr, - // Urxvt, -} - -/// Represents the overall terminal state. -#[derive(Clone, Debug)] -pub struct Screen { - grid: crate::grid::Grid, - alternate_grid: crate::grid::Grid, - - attrs: crate::attrs::Attrs, - saved_attrs: crate::attrs::Attrs, - - modes: u8, - mouse_protocol_mode: MouseProtocolMode, - mouse_protocol_encoding: MouseProtocolEncoding, -} - -impl Screen { - pub(crate) fn new( - size: crate::grid::Size, - scrollback_len: usize, - ) -> Self { - let mut grid = crate::grid::Grid::new(size, scrollback_len); - grid.allocate_rows(); - Self { - grid, - alternate_grid: crate::grid::Grid::new(size, 0), - - attrs: crate::attrs::Attrs::default(), - saved_attrs: crate::attrs::Attrs::default(), - - modes: 0, - mouse_protocol_mode: MouseProtocolMode::default(), - mouse_protocol_encoding: MouseProtocolEncoding::default(), - } - } - - /// Resizes the terminal. - pub fn set_size(&mut self, rows: u16, cols: u16) { - self.grid.set_size(crate::grid::Size { rows, cols }); - self.alternate_grid - .set_size(crate::grid::Size { rows, cols }); - } - - /// Returns the current size of the terminal. - /// - /// The return value will be (rows, cols). - #[must_use] - pub fn size(&self) -> (u16, u16) { - let size = self.grid().size(); - (size.rows, size.cols) - } - - /// Scrolls to the given position in the scrollback. - /// - /// This position indicates the offset from the top of the screen, and - /// should be `0` to put the normal screen in view. - /// - /// This affects the return values of methods called on the screen: for - /// instance, `screen.cell(0, 0)` will return the top left corner of the - /// screen after taking the scrollback offset into account. - /// - /// The value given will be clamped to the actual size of the scrollback. - pub fn set_scrollback(&mut self, rows: usize) { - self.grid_mut().set_scrollback(rows); - } - - /// Returns the current position in the scrollback. - /// - /// This position indicates the offset from the top of the screen, and is - /// `0` when the normal screen is in view. - #[must_use] - pub fn scrollback(&self) -> usize { - self.grid().scrollback() - } - - /// Returns the text contents of the terminal. - /// - /// This will not include any formatting information, and will be in plain - /// text format. - #[must_use] - pub fn contents(&self) -> String { - let mut contents = String::new(); - self.write_contents(&mut contents); - contents - } - - fn write_contents(&self, contents: &mut String) { - self.grid().write_contents(contents); - } - - /// Returns the text contents of the terminal by row, restricted to the - /// given subset of columns. - /// - /// This will not include any formatting information, and will be in plain - /// text format. - /// - /// Newlines will not be included. - pub fn rows( - &self, - start: u16, - width: u16, - ) -> impl Iterator<Item = String> + '_ { - self.grid().visible_rows().map(move |row| { - let mut contents = String::new(); - row.write_contents(&mut contents, start, width, false); - contents - }) - } - - /// Returns the text contents of the terminal logically between two cells. - /// This will include the remainder of the starting row after `start_col`, - /// followed by the entire contents of the rows between `start_row` and - /// `end_row`, followed by the beginning of the `end_row` up until - /// `end_col`. This is useful for things like determining the contents of - /// a clipboard selection. - #[must_use] - pub fn contents_between( - &self, - start_row: u16, - start_col: u16, - end_row: u16, - end_col: u16, - ) -> String { - match start_row.cmp(&end_row) { - std::cmp::Ordering::Less => { - let (_, cols) = self.size(); - let mut contents = String::new(); - for (i, row) in self - .grid() - .visible_rows() - .enumerate() - .skip(usize::from(start_row)) - .take(usize::from(end_row) - usize::from(start_row) + 1) - { - if i == usize::from(start_row) { - row.write_contents( - &mut contents, - start_col, - cols - start_col, - false, - ); - if !row.wrapped() { - contents.push('\n'); - } - } else if i == usize::from(end_row) { - row.write_contents(&mut contents, 0, end_col, false); - } else { - row.write_contents(&mut contents, 0, cols, false); - if !row.wrapped() { - contents.push('\n'); - } - } - } - contents - } - std::cmp::Ordering::Equal => { - if start_col < end_col { - self.rows(start_col, end_col - start_col) - .nth(usize::from(start_row)) - .unwrap_or_default() - } else { - String::new() - } - } - std::cmp::Ordering::Greater => String::new(), - } - } - - /// Return escape codes sufficient to reproduce the entire contents of the - /// current terminal state. This is a convenience wrapper around - /// [`contents_formatted`](Self::contents_formatted) and - /// [`input_mode_formatted`](Self::input_mode_formatted). - #[must_use] - pub fn state_formatted(&self) -> Vec<u8> { - let mut contents = vec![]; - self.write_contents_formatted(&mut contents); - self.write_input_mode_formatted(&mut contents); - contents - } - - /// Return escape codes sufficient to turn the terminal state of the - /// screen `prev` into the current terminal state. This is a convenience - /// wrapper around [`contents_diff`](Self::contents_diff) and - /// [`input_mode_diff`](Self::input_mode_diff). - #[must_use] - pub fn state_diff(&self, prev: &Self) -> Vec<u8> { - let mut contents = vec![]; - self.write_contents_diff(&mut contents, prev); - self.write_input_mode_diff(&mut contents, prev); - contents - } - - /// Returns the formatted visible contents of the terminal. - /// - /// Formatting information will be included inline as terminal escape - /// codes. The result will be suitable for feeding directly to a raw - /// terminal parser, and will result in the same visual output. - #[must_use] - pub fn contents_formatted(&self) -> Vec<u8> { - let mut contents = vec![]; - self.write_contents_formatted(&mut contents); - contents - } - - fn write_contents_formatted(&self, contents: &mut Vec<u8>) { - crate::term::HideCursor::new(self.hide_cursor()).write_buf(contents); - let prev_attrs = self.grid().write_contents_formatted(contents); - self.attrs.write_escape_code_diff(contents, &prev_attrs); - } - - /// Returns the formatted visible contents of the terminal by row, - /// restricted to the given subset of columns. - /// - /// Formatting information will be included inline as terminal escape - /// codes. The result will be suitable for feeding directly to a raw - /// terminal parser, and will result in the same visual output. - /// - /// You are responsible for positioning the cursor before printing each - /// row, and the final cursor position after displaying each row is - /// unspecified. - // the unwraps in this method shouldn't be reachable - #[allow(clippy::missing_panics_doc)] - pub fn rows_formatted( - &self, - start: u16, - width: u16, - ) -> impl Iterator<Item = Vec<u8>> + '_ { - let mut wrapping = false; - self.grid().visible_rows().enumerate().map(move |(i, row)| { - // number of rows in a grid is stored in a u16 (see Size), so - // visible_rows can never return enough rows to overflow here - let i = i.try_into().unwrap(); - let mut contents = vec![]; - row.write_contents_formatted( - &mut contents, - start, - width, - i, - wrapping, - None, - None, - ); - if start == 0 && width == self.grid.size().cols { - wrapping = row.wrapped(); - } - contents - }) - } - - /// Returns a terminal byte stream sufficient to turn the visible contents - /// of the screen described by `prev` into the visible contents of the - /// screen described by `self`. - /// - /// The result of rendering `prev.contents_formatted()` followed by - /// `self.contents_diff(prev)` should be equivalent to the result of - /// rendering `self.contents_formatted()`. This is primarily useful when - /// you already have a terminal parser whose state is described by `prev`, - /// since the diff will likely require less memory and cause less - /// flickering than redrawing the entire screen contents. - #[must_use] - pub fn contents_diff(&self, prev: &Self) -> Vec<u8> { - let mut contents = vec![]; - self.write_contents_diff(&mut contents, prev); - contents - } - - fn write_contents_diff(&self, contents: &mut Vec<u8>, prev: &Self) { - if self.hide_cursor() != prev.hide_cursor() { - crate::term::HideCursor::new(self.hide_cursor()) - .write_buf(contents); - } - let prev_attrs = self.grid().write_contents_diff( - contents, - prev.grid(), - prev.attrs, - ); - self.attrs.write_escape_code_diff(contents, &prev_attrs); - } - - /// Returns a sequence of terminal byte streams sufficient to turn the - /// visible contents of the subset of each row from `prev` (as described - /// by `start` and `width`) into the visible contents of the corresponding - /// row subset in `self`. - /// - /// You are responsible for positioning the cursor before printing each - /// row, and the final cursor position after displaying each row is - /// unspecified. - // the unwraps in this method shouldn't be reachable - #[allow(clippy::missing_panics_doc)] - pub fn rows_diff<'a>( - &'a self, - prev: &'a Self, - start: u16, - width: u16, - ) -> impl Iterator<Item = Vec<u8>> + 'a { - self.grid() - .visible_rows() - .zip(prev.grid().visible_rows()) - .enumerate() - .map(move |(i, (row, prev_row))| { - // number of rows in a grid is stored in a u16 (see Size), so - // visible_rows can never return enough rows to overflow here - let i = i.try_into().unwrap(); - let mut contents = vec![]; - row.write_contents_diff( - &mut contents, - prev_row, - start, - width, - i, - false, - false, - crate::grid::Pos { row: i, col: start }, - crate::attrs::Attrs::default(), - ); - contents - }) - } - - /// Returns terminal escape sequences sufficient to set the current - /// terminal's input modes. - /// - /// Supported modes are: - /// * application keypad - /// * application cursor - /// * bracketed paste - /// * xterm mouse support - #[must_use] - pub fn input_mode_formatted(&self) -> Vec<u8> { - let mut contents = vec![]; - self.write_input_mode_formatted(&mut contents); - contents - } - - fn write_input_mode_formatted(&self, contents: &mut Vec<u8>) { - crate::term::ApplicationKeypad::new( - self.mode(MODE_APPLICATION_KEYPAD), - ) - .write_buf(contents); - crate::term::ApplicationCursor::new( - self.mode(MODE_APPLICATION_CURSOR), - ) - .write_buf(contents); - crate::term::BracketedPaste::new(self.mode(MODE_BRACKETED_PASTE)) - .write_buf(contents); - crate::term::MouseProtocolMode::new( - self.mouse_protocol_mode, - MouseProtocolMode::None, - ) - .write_buf(contents); - crate::term::MouseProtocolEncoding::new( - self.mouse_protocol_encoding, - MouseProtocolEncoding::Default, - ) - .write_buf(contents); - } - - /// Returns terminal escape sequences sufficient to change the previous - /// terminal's input modes to the input modes enabled in the current - /// terminal. - #[must_use] - pub fn input_mode_diff(&self, prev: &Self) -> Vec<u8> { - let mut contents = vec![]; - self.write_input_mode_diff(&mut contents, prev); - contents - } - - fn write_input_mode_diff(&self, contents: &mut Vec<u8>, prev: &Self) { - if self.mode(MODE_APPLICATION_KEYPAD) - != prev.mode(MODE_APPLICATION_KEYPAD) - { - crate::term::ApplicationKeypad::new( - self.mode(MODE_APPLICATION_KEYPAD), - ) - .write_buf(contents); - } - if self.mode(MODE_APPLICATION_CURSOR) - != prev.mode(MODE_APPLICATION_CURSOR) - { - crate::term::ApplicationCursor::new( - self.mode(MODE_APPLICATION_CURSOR), - ) - .write_buf(contents); - } - if self.mode(MODE_BRACKETED_PASTE) != prev.mode(MODE_BRACKETED_PASTE) - { - crate::term::BracketedPaste::new(self.mode(MODE_BRACKETED_PASTE)) - .write_buf(contents); - } - crate::term::MouseProtocolMode::new( - self.mouse_protocol_mode, - prev.mouse_protocol_mode, - ) - .write_buf(contents); - crate::term::MouseProtocolEncoding::new( - self.mouse_protocol_encoding, - prev.mouse_protocol_encoding, - ) - .write_buf(contents); - } - - /// Returns terminal escape sequences sufficient to set the current - /// terminal's drawing attributes. - /// - /// Supported drawing attributes are: - /// * fgcolor - /// * bgcolor - /// * bold - /// * dim - /// * italic - /// * underline - /// * inverse - /// - /// This is not typically necessary, since - /// [`contents_formatted`](Self::contents_formatted) will leave - /// the current active drawing attributes in the correct state, but this - /// can be useful in the case of drawing additional things on top of a - /// terminal output, since you will need to restore the terminal state - /// without the terminal contents necessarily being the same. - #[must_use] - pub fn attributes_formatted(&self) -> Vec<u8> { - let mut contents = vec![]; - self.write_attributes_formatted(&mut contents); - contents - } - - fn write_attributes_formatted(&self, contents: &mut Vec<u8>) { - crate::term::ClearAttrs.write_buf(contents); - self.attrs.write_escape_code_diff( - contents, - &crate::attrs::Attrs::default(), - ); - } - - /// Returns the current cursor position of the terminal. - /// - /// The return value will be (row, col). - #[must_use] - pub fn cursor_position(&self) -> (u16, u16) { - let pos = self.grid().pos(); - (pos.row, pos.col) - } - - /// Returns terminal escape sequences sufficient to set the current - /// cursor state of the terminal. - /// - /// This is not typically necessary, since - /// [`contents_formatted`](Self::contents_formatted) will leave - /// the cursor in the correct state, but this can be useful in the case of - /// drawing additional things on top of a terminal output, since you will - /// need to restore the terminal state without the terminal contents - /// necessarily being the same. - /// - /// Note that the bytes returned by this function may alter the active - /// drawing attributes, because it may require redrawing existing cells in - /// order to position the cursor correctly (for instance, in the case - /// where the cursor is past the end of a row). Therefore, you should - /// ensure to reset the active drawing attributes if necessary after - /// processing this data, for instance by using - /// [`attributes_formatted`](Self::attributes_formatted). - #[must_use] - pub fn cursor_state_formatted(&self) -> Vec<u8> { - let mut contents = vec![]; - self.write_cursor_state_formatted(&mut contents); - contents - } - - fn write_cursor_state_formatted(&self, contents: &mut Vec<u8>) { - crate::term::HideCursor::new(self.hide_cursor()).write_buf(contents); - self.grid() - .write_cursor_position_formatted(contents, None, None); - - // we don't just call write_attributes_formatted here, because that - // would still be confusing - consider the case where the user sets - // their own unrelated drawing attributes (on a different parser - // instance) and then calls cursor_state_formatted. just documenting - // it and letting the user handle it on their own is more - // straightforward. - } - - /// Returns the [`Cell`](crate::Cell) object at the given location in the - /// terminal, if it exists. - #[must_use] - pub fn cell(&self, row: u16, col: u16) -> Option<&crate::Cell> { - self.grid().visible_cell(crate::grid::Pos { row, col }) - } - - /// Returns whether the text in row `row` should wrap to the next line. - #[must_use] - pub fn row_wrapped(&self, row: u16) -> bool { - self.grid() - .visible_row(row) - .is_some_and(crate::row::Row::wrapped) - } - - /// Returns whether the alternate screen is currently in use. - #[must_use] - pub fn alternate_screen(&self) -> bool { - self.mode(MODE_ALTERNATE_SCREEN) - } - - /// Returns whether the terminal should be in application keypad mode. - #[must_use] - pub fn application_keypad(&self) -> bool { - self.mode(MODE_APPLICATION_KEYPAD) - } - - /// Returns whether the terminal should be in application cursor mode. - #[must_use] - pub fn application_cursor(&self) -> bool { - self.mode(MODE_APPLICATION_CURSOR) - } - - /// Returns whether the terminal should be in hide cursor mode. - #[must_use] - pub fn hide_cursor(&self) -> bool { - self.mode(MODE_HIDE_CURSOR) - } - - /// Returns whether the terminal should be in bracketed paste mode. - #[must_use] - pub fn bracketed_paste(&self) -> bool { - self.mode(MODE_BRACKETED_PASTE) - } - - /// Returns the currently active [`MouseProtocolMode`]. - #[must_use] - pub fn mouse_protocol_mode(&self) -> MouseProtocolMode { - self.mouse_protocol_mode - } - - /// Returns the currently active [`MouseProtocolEncoding`]. - #[must_use] - pub fn mouse_protocol_encoding(&self) -> MouseProtocolEncoding { - self.mouse_protocol_encoding - } - - /// Returns the currently active foreground color. - #[must_use] - pub fn fgcolor(&self) -> crate::Color { - self.attrs.fgcolor - } - - /// Returns the currently active background color. - #[must_use] - pub fn bgcolor(&self) -> crate::Color { - self.attrs.bgcolor - } - - /// Returns whether newly drawn text should be rendered with the bold text - /// attribute. - #[must_use] - pub fn bold(&self) -> bool { - self.attrs.bold() - } - - /// Returns whether newly drawn text should be rendered with the dim text - /// attribute. - #[must_use] - pub fn dim(&self) -> bool { - self.attrs.dim() - } - - /// Returns whether newly drawn text should be rendered with the italic - /// text attribute. - #[must_use] - pub fn italic(&self) -> bool { - self.attrs.italic() - } - - /// Returns whether newly drawn text should be rendered with the - /// underlined text attribute. - #[must_use] - pub fn underline(&self) -> bool { - self.attrs.underline() - } - - /// Returns whether newly drawn text should be rendered with the inverse - /// text attribute. - #[must_use] - pub fn inverse(&self) -> bool { - self.attrs.inverse() - } - - pub(crate) fn grid(&self) -> &crate::grid::Grid { - if self.mode(MODE_ALTERNATE_SCREEN) { - &self.alternate_grid - } else { - &self.grid - } - } - - fn grid_mut(&mut self) -> &mut crate::grid::Grid { - if self.mode(MODE_ALTERNATE_SCREEN) { - &mut self.alternate_grid - } else { - &mut self.grid - } - } - - fn enter_alternate_grid(&mut self) { - self.grid_mut().set_scrollback(0); - self.set_mode(MODE_ALTERNATE_SCREEN); - self.alternate_grid.allocate_rows(); - } - - fn exit_alternate_grid(&mut self) { - self.clear_mode(MODE_ALTERNATE_SCREEN); - } - - fn save_cursor(&mut self) { - self.grid_mut().save_cursor(); - self.saved_attrs = self.attrs; - } - - fn restore_cursor(&mut self) { - self.grid_mut().restore_cursor(); - self.attrs = self.saved_attrs; - } - - fn set_mode(&mut self, mode: u8) { - self.modes |= mode; - } - - fn clear_mode(&mut self, mode: u8) { - self.modes &= !mode; - } - - fn mode(&self, mode: u8) -> bool { - self.modes & mode != 0 - } - - fn set_mouse_mode(&mut self, mode: MouseProtocolMode) { - self.mouse_protocol_mode = mode; - } - - fn clear_mouse_mode(&mut self, mode: MouseProtocolMode) { - if self.mouse_protocol_mode == mode { - self.mouse_protocol_mode = MouseProtocolMode::default(); - } - } - - fn set_mouse_encoding(&mut self, encoding: MouseProtocolEncoding) { - self.mouse_protocol_encoding = encoding; - } - - fn clear_mouse_encoding(&mut self, encoding: MouseProtocolEncoding) { - if self.mouse_protocol_encoding == encoding { - self.mouse_protocol_encoding = MouseProtocolEncoding::default(); - } - } -} - -impl Screen { - pub(crate) fn text(&mut self, c: char) { - let pos = self.grid().pos(); - let size = self.grid().size(); - let attrs = self.attrs; - - let width = c.width(); - if width.is_none() && (u32::from(c)) < 256 { - // don't even try to draw control characters - return; - } - let width = width - .unwrap_or(1) - .try_into() - // width() can only return 0, 1, or 2 - .unwrap(); - - // it doesn't make any sense to wrap if the last column in a row - // didn't already have contents. don't try to handle the case where a - // character wraps because there was only one column left in the - // previous row - literally everything handles this case differently, - // and this is tmux behavior (and also the simplest). i'm open to - // reconsidering this behavior, but only with a really good reason - // (xterm handles this by introducing the concept of triple width - // cells, which i really don't want to do). - let mut wrap = false; - if pos.col > size.cols - width { - let last_cell = self - .grid() - .drawing_cell(crate::grid::Pos { - row: pos.row, - col: size.cols - 1, - }) - // pos.row is valid, since it comes directly from - // self.grid().pos() which we assume to always have a valid - // row value. size.cols - 1 is also always a valid column. - .unwrap(); - if last_cell.has_contents() || last_cell.is_wide_continuation() { - wrap = true; - } - } - self.grid_mut().col_wrap(width, wrap); - let pos = self.grid().pos(); - - if width == 0 { - if pos.col > 0 { - let mut prev_cell = self - .grid_mut() - .drawing_cell_mut(crate::grid::Pos { - row: pos.row, - col: pos.col - 1, - }) - // pos.row is valid, since it comes directly from - // self.grid().pos() which we assume to always have a - // valid row value. pos.col - 1 is valid because we just - // checked for pos.col > 0. - .unwrap(); - if prev_cell.is_wide_continuation() { - prev_cell = self - .grid_mut() - .drawing_cell_mut(crate::grid::Pos { - row: pos.row, - col: pos.col - 2, - }) - // pos.row is valid, since it comes directly from - // self.grid().pos() which we assume to always have a - // valid row value. we know pos.col - 2 is valid - // because the cell at pos.col - 1 is a wide - // continuation character, which means there must be - // the first half of the wide character before it. - .unwrap(); - } - prev_cell.append(c); - } else if pos.row > 0 { - let prev_row = self - .grid() - .drawing_row(pos.row - 1) - // pos.row is valid, since it comes directly from - // self.grid().pos() which we assume to always have a - // valid row value. pos.row - 1 is valid because we just - // checked for pos.row > 0. - .unwrap(); - if prev_row.wrapped() { - let mut prev_cell = self - .grid_mut() - .drawing_cell_mut(crate::grid::Pos { - row: pos.row - 1, - col: size.cols - 1, - }) - // pos.row is valid, since it comes directly from - // self.grid().pos() which we assume to always have a - // valid row value. pos.row - 1 is valid because we - // just checked for pos.row > 0. col of size.cols - 1 - // is always valid. - .unwrap(); - if prev_cell.is_wide_continuation() { - prev_cell = self - .grid_mut() - .drawing_cell_mut(crate::grid::Pos { - row: pos.row - 1, - col: size.cols - 2, - }) - // pos.row is valid, since it comes directly from - // self.grid().pos() which we assume to always - // have a valid row value. pos.row - 1 is valid - // because we just checked for pos.row > 0. col of - // size.cols - 2 is valid because the cell at - // size.cols - 1 is a wide continuation character, - // so it must have the first half of the wide - // character before it. - .unwrap(); - } - prev_cell.append(c); - } - } - } else { - if self - .grid() - .drawing_cell(pos) - // pos.row is valid because we assume self.grid().pos() to - // always have a valid row value. pos.col is valid because we - // called col_wrap() immediately before this, which ensures - // that self.grid().pos().col has a valid value. - .unwrap() - .is_wide_continuation() - { - let prev_cell = self - .grid_mut() - .drawing_cell_mut(crate::grid::Pos { - row: pos.row, - col: pos.col - 1, - }) - // pos.row is valid because we assume self.grid().pos() to - // always have a valid row value. pos.col is valid because - // we called col_wrap() immediately before this, which - // ensures that self.grid().pos().col has a valid value. - // pos.col - 1 is valid because the cell at pos.col is a - // wide continuation character, so it must have the first - // half of the wide character before it. - .unwrap(); - prev_cell.clear(attrs); - } - - if self - .grid() - .drawing_cell(pos) - // pos.row is valid because we assume self.grid().pos() to - // always have a valid row value. pos.col is valid because we - // called col_wrap() immediately before this, which ensures - // that self.grid().pos().col has a valid value. - .unwrap() - .is_wide() - { - let next_cell = self - .grid_mut() - .drawing_cell_mut(crate::grid::Pos { - row: pos.row, - col: pos.col + 1, - }) - // pos.row is valid because we assume self.grid().pos() to - // always have a valid row value. pos.col is valid because - // we called col_wrap() immediately before this, which - // ensures that self.grid().pos().col has a valid value. - // pos.col + 1 is valid because the cell at pos.col is a - // wide character, so it must have the second half of the - // wide character after it. - .unwrap(); - next_cell.set(' ', attrs); - } - - let cell = self - .grid_mut() - .drawing_cell_mut(pos) - // pos.row is valid because we assume self.grid().pos() to - // always have a valid row value. pos.col is valid because we - // called col_wrap() immediately before this, which ensures - // that self.grid().pos().col has a valid value. - .unwrap(); - cell.set(c, attrs); - self.grid_mut().col_inc(1); - if width > 1 { - let pos = self.grid().pos(); - if self - .grid() - .drawing_cell(pos) - // pos.row is valid because we assume self.grid().pos() to - // always have a valid row value. pos.col is valid because - // we called col_wrap() earlier, which ensures that - // self.grid().pos().col has a valid value. this is true - // even though we just called col_inc, because this branch - // only happens if width > 1, and col_wrap takes width - // into account. - .unwrap() - .is_wide() - { - let next_next_pos = crate::grid::Pos { - row: pos.row, - col: pos.col + 1, - }; - let next_next_cell = self - .grid_mut() - .drawing_cell_mut(next_next_pos) - // pos.row is valid because we assume - // self.grid().pos() to always have a valid row value. - // pos.col is valid because we called col_wrap() - // earlier, which ensures that self.grid().pos().col - // has a valid value. this is true even though we just - // called col_inc, because this branch only happens if - // width > 1, and col_wrap takes width into account. - // pos.col + 1 is valid because the cell at pos.col is - // wide, and so it must have the second half of the - // wide character after it. - .unwrap(); - next_next_cell.clear(attrs); - if next_next_pos.col == size.cols - 1 { - self.grid_mut() - .drawing_row_mut(pos.row) - // we assume self.grid().pos().row is always valid - .unwrap() - .wrap(false); - } - } - let next_cell = self - .grid_mut() - .drawing_cell_mut(pos) - // pos.row is valid because we assume self.grid().pos() to - // always have a valid row value. pos.col is valid because - // we called col_wrap() earlier, which ensures that - // self.grid().pos().col has a valid value. this is true - // even though we just called col_inc, because this branch - // only happens if width > 1, and col_wrap takes width - // into account. - .unwrap(); - next_cell.clear(crate::attrs::Attrs::default()); - next_cell.set_wide_continuation(true); - self.grid_mut().col_inc(1); - } - } - } - - // control codes - - pub(crate) fn bs(&mut self) { - self.grid_mut().col_dec(1); - } - - pub(crate) fn tab(&mut self) { - self.grid_mut().col_tab(); - } - - pub(crate) fn lf(&mut self) { - self.grid_mut().row_inc_scroll(1); - } - - pub(crate) fn vt(&mut self) { - self.lf(); - } - - pub(crate) fn ff(&mut self) { - self.lf(); - } - - pub(crate) fn cr(&mut self) { - self.grid_mut().col_set(0); - } - - // escape codes - - // ESC 7 - pub(crate) fn decsc(&mut self) { - self.save_cursor(); - } - - // ESC 8 - pub(crate) fn decrc(&mut self) { - self.restore_cursor(); - } - - // ESC = - pub(crate) fn deckpam(&mut self) { - self.set_mode(MODE_APPLICATION_KEYPAD); - } - - // ESC > - pub(crate) fn deckpnm(&mut self) { - self.clear_mode(MODE_APPLICATION_KEYPAD); - } - - // ESC M - pub(crate) fn ri(&mut self) { - self.grid_mut().row_dec_scroll(1); - } - - // ESC c - pub(crate) fn ris(&mut self) { - *self = Self::new(self.grid.size(), self.grid.scrollback_len()); - } - - // csi codes - - // CSI @ - pub(crate) fn ich(&mut self, count: u16) { - self.grid_mut().insert_cells(count); - } - - // CSI A - pub(crate) fn cuu(&mut self, offset: u16) { - self.grid_mut().row_dec_clamp(offset); - } - - // CSI B - pub(crate) fn cud(&mut self, offset: u16) { - self.grid_mut().row_inc_clamp(offset); - } - - // CSI C - pub(crate) fn cuf(&mut self, offset: u16) { - self.grid_mut().col_inc_clamp(offset); - } - - // CSI D - pub(crate) fn cub(&mut self, offset: u16) { - self.grid_mut().col_dec(offset); - } - - // CSI E - pub(crate) fn cnl(&mut self, offset: u16) { - self.grid_mut().col_set(0); - self.grid_mut().row_inc_clamp(offset); - } - - // CSI F - pub(crate) fn cpl(&mut self, offset: u16) { - self.grid_mut().col_set(0); - self.grid_mut().row_dec_clamp(offset); - } - - // CSI G - pub(crate) fn cha(&mut self, col: u16) { - self.grid_mut().col_set(col - 1); - } - - // CSI H - pub(crate) fn cup(&mut self, (row, col): (u16, u16)) { - self.grid_mut().set_pos(crate::grid::Pos { - row: row - 1, - col: col - 1, - }); - } - - // CSI J - pub(crate) fn ed( - &mut self, - mode: u16, - mut unhandled: impl FnMut(&mut Self), - ) { - let attrs = self.attrs; - match mode { - 0 => self.grid_mut().erase_all_forward(attrs), - 1 => self.grid_mut().erase_all_backward(attrs), - 2 => self.grid_mut().erase_all(attrs), - _ => unhandled(self), - } - } - - // CSI ? J - pub(crate) fn decsed( - &mut self, - mode: u16, - unhandled: impl FnMut(&mut Self), - ) { - self.ed(mode, unhandled); - } - - // CSI K - pub(crate) fn el( - &mut self, - mode: u16, - mut unhandled: impl FnMut(&mut Self), - ) { - let attrs = self.attrs; - match mode { - 0 => self.grid_mut().erase_row_forward(attrs), - 1 => self.grid_mut().erase_row_backward(attrs), - 2 => self.grid_mut().erase_row(attrs), - _ => unhandled(self), - } - } - - // CSI ? K - pub(crate) fn decsel( - &mut self, - mode: u16, - unhandled: impl FnMut(&mut Self), - ) { - self.el(mode, unhandled); - } - - // CSI L - pub(crate) fn il(&mut self, count: u16) { - self.grid_mut().insert_lines(count); - } - - // CSI M - pub(crate) fn dl(&mut self, count: u16) { - self.grid_mut().delete_lines(count); - } - - // CSI P - pub(crate) fn dch(&mut self, count: u16) { - self.grid_mut().delete_cells(count); - } - - // CSI S - pub(crate) fn su(&mut self, count: u16) { - self.grid_mut().scroll_up(count); - } - - // CSI T - pub(crate) fn sd(&mut self, count: u16) { - self.grid_mut().scroll_down(count); - } - - // CSI X - pub(crate) fn ech(&mut self, count: u16) { - let attrs = self.attrs; - self.grid_mut().erase_cells(count, attrs); - } - - // CSI d - pub(crate) fn vpa(&mut self, row: u16) { - self.grid_mut().row_set(row - 1); - } - - // CSI ? h - pub(crate) fn decset( - &mut self, - params: &vte::Params, - mut unhandled: impl FnMut(&mut Self), - ) { - for param in params { - match param { - [1] => self.set_mode(MODE_APPLICATION_CURSOR), - [6] => self.grid_mut().set_origin_mode(true), - [9] => self.set_mouse_mode(MouseProtocolMode::Press), - [25] => self.clear_mode(MODE_HIDE_CURSOR), - [47] => self.enter_alternate_grid(), - [1000] => { - self.set_mouse_mode(MouseProtocolMode::PressRelease); - } - [1002] => { - self.set_mouse_mode(MouseProtocolMode::ButtonMotion); - } - [1003] => self.set_mouse_mode(MouseProtocolMode::AnyMotion), - [1005] => { - self.set_mouse_encoding(MouseProtocolEncoding::Utf8); - } - [1006] => { - self.set_mouse_encoding(MouseProtocolEncoding::Sgr); - } - [1049] => { - self.decsc(); - self.alternate_grid.clear(); - self.enter_alternate_grid(); - } - [2004] => self.set_mode(MODE_BRACKETED_PASTE), - _ => unhandled(self), - } - } - } - - // CSI ? l - pub(crate) fn decrst( - &mut self, - params: &vte::Params, - mut unhandled: impl FnMut(&mut Self), - ) { - for param in params { - match param { - [1] => self.clear_mode(MODE_APPLICATION_CURSOR), - [6] => self.grid_mut().set_origin_mode(false), - [9] => self.clear_mouse_mode(MouseProtocolMode::Press), - [25] => self.set_mode(MODE_HIDE_CURSOR), - [47] => { - self.exit_alternate_grid(); - } - [1000] => { - self.clear_mouse_mode(MouseProtocolMode::PressRelease); - } - [1002] => { - self.clear_mouse_mode(MouseProtocolMode::ButtonMotion); - } - [1003] => { - self.clear_mouse_mode(MouseProtocolMode::AnyMotion); - } - [1005] => { - self.clear_mouse_encoding(MouseProtocolEncoding::Utf8); - } - [1006] => { - self.clear_mouse_encoding(MouseProtocolEncoding::Sgr); - } - [1049] => { - self.exit_alternate_grid(); - self.decrc(); - } - [2004] => self.clear_mode(MODE_BRACKETED_PASTE), - _ => unhandled(self), - } - } - } - - // CSI m - pub(crate) fn sgr( - &mut self, - params: &vte::Params, - mut unhandled: impl FnMut(&mut Self), - ) { - // XXX really i want to just be able to pass in a default Params - // instance with a 0 in it, but vte doesn't allow creating new Params - // instances - if params.is_empty() { - self.attrs = crate::attrs::Attrs::default(); - return; - } - - let mut iter = params.iter(); - - macro_rules! next_param { - () => { - match iter.next() { - Some(n) => n, - _ => return, - } - }; - } - - macro_rules! to_u8 { - ($n:expr) => { - if let Some(n) = u16_to_u8($n) { - n - } else { - return; - } - }; - } - - macro_rules! next_param_u8 { - () => { - if let &[n] = next_param!() { - to_u8!(n) - } else { - return; - } - }; - } - - loop { - match next_param!() { - [0] => self.attrs = crate::attrs::Attrs::default(), - [1] => self.attrs.set_bold(), - [2] => self.attrs.set_dim(), - [3] => self.attrs.set_italic(true), - [4] => self.attrs.set_underline(true), - [7] => self.attrs.set_inverse(true), - [22] => self.attrs.set_normal_intensity(), - [23] => self.attrs.set_italic(false), - [24] => self.attrs.set_underline(false), - [27] => self.attrs.set_inverse(false), - [n] if (30..=37).contains(n) => { - self.attrs.fgcolor = crate::Color::Idx(to_u8!(*n) - 30); - } - [38, 2, r, g, b] => { - self.attrs.fgcolor = - crate::Color::Rgb(to_u8!(*r), to_u8!(*g), to_u8!(*b)); - } - [38, 5, i] => { - self.attrs.fgcolor = crate::Color::Idx(to_u8!(*i)); - } - [38] => match next_param!() { - [2] => { - let r = next_param_u8!(); - let g = next_param_u8!(); - let b = next_param_u8!(); - self.attrs.fgcolor = crate::Color::Rgb(r, g, b); - } - [5] => { - self.attrs.fgcolor = - crate::Color::Idx(next_param_u8!()); - } - _ => { - unhandled(self); - return; - } - }, - [39] => { - self.attrs.fgcolor = crate::Color::Default; - } - [n] if (40..=47).contains(n) => { - self.attrs.bgcolor = crate::Color::Idx(to_u8!(*n) - 40); - } - [48, 2, r, g, b] => { - self.attrs.bgcolor = - crate::Color::Rgb(to_u8!(*r), to_u8!(*g), to_u8!(*b)); - } - [48, 5, i] => { - self.attrs.bgcolor = crate::Color::Idx(to_u8!(*i)); - } - [48] => match next_param!() { - [2] => { - let r = next_param_u8!(); - let g = next_param_u8!(); - let b = next_param_u8!(); - self.attrs.bgcolor = crate::Color::Rgb(r, g, b); - } - [5] => { - self.attrs.bgcolor = - crate::Color::Idx(next_param_u8!()); - } - _ => { - unhandled(self); - return; - } - }, - [49] => { - self.attrs.bgcolor = crate::Color::Default; - } - [n] if (90..=97).contains(n) => { - self.attrs.fgcolor = crate::Color::Idx(to_u8!(*n) - 82); - } - [n] if (100..=107).contains(n) => { - self.attrs.bgcolor = crate::Color::Idx(to_u8!(*n) - 92); - } - _ => unhandled(self), - } - } - } - - // CSI r - pub(crate) fn decstbm(&mut self, (top, bottom): (u16, u16)) { - self.grid_mut().set_scroll_region(top - 1, bottom - 1); - } -} - -fn u16_to_u8(i: u16) -> Option<u8> { - if i > u16::from(u8::MAX) { - None - } else { - // safe because we just ensured that the value fits in a u8 - Some(i.try_into().unwrap()) - } -} diff --git a/vendor/vt100/src/term.rs b/vendor/vt100/src/term.rs deleted file mode 100644 index b6b898c6..00000000 --- a/vendor/vt100/src/term.rs +++ /dev/null @@ -1,551 +0,0 @@ -// TODO: read all of this from terminfo - -pub trait BufWrite { - fn write_buf(&self, buf: &mut Vec<u8>); -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct ClearScreen; - -impl BufWrite for ClearScreen { - fn write_buf(&self, buf: &mut Vec<u8>) { - buf.extend_from_slice(b"\x1b[H\x1b[J"); - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct ClearRowForward; - -impl BufWrite for ClearRowForward { - fn write_buf(&self, buf: &mut Vec<u8>) { - buf.extend_from_slice(b"\x1b[K"); - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct Crlf; - -impl BufWrite for Crlf { - fn write_buf(&self, buf: &mut Vec<u8>) { - buf.extend_from_slice(b"\r\n"); - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct Backspace; - -impl BufWrite for Backspace { - fn write_buf(&self, buf: &mut Vec<u8>) { - buf.extend_from_slice(b"\x08"); - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct SaveCursor; - -impl BufWrite for SaveCursor { - fn write_buf(&self, buf: &mut Vec<u8>) { - buf.extend_from_slice(b"\x1b7"); - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct RestoreCursor; - -impl BufWrite for RestoreCursor { - fn write_buf(&self, buf: &mut Vec<u8>) { - buf.extend_from_slice(b"\x1b8"); - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct MoveTo { - row: u16, - col: u16, -} - -impl MoveTo { - pub fn new(pos: crate::grid::Pos) -> Self { - Self { - row: pos.row, - col: pos.col, - } - } -} - -impl BufWrite for MoveTo { - fn write_buf(&self, buf: &mut Vec<u8>) { - if self.row == 0 && self.col == 0 { - buf.extend_from_slice(b"\x1b[H"); - } else { - buf.extend_from_slice(b"\x1b["); - extend_itoa(buf, self.row + 1); - buf.push(b';'); - extend_itoa(buf, self.col + 1); - buf.push(b'H'); - } - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct ClearAttrs; - -impl BufWrite for ClearAttrs { - fn write_buf(&self, buf: &mut Vec<u8>) { - buf.extend_from_slice(b"\x1b[m"); - } -} - -#[derive(Debug, Clone, Copy)] -pub enum Intensity { - Normal, - Bold, - Dim, -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct Attrs { - fgcolor: Option<crate::Color>, - bgcolor: Option<crate::Color>, - intensity: Option<Intensity>, - italic: Option<bool>, - underline: Option<bool>, - inverse: Option<bool>, -} - -impl Attrs { - pub fn fgcolor(mut self, fgcolor: crate::Color) -> Self { - self.fgcolor = Some(fgcolor); - self - } - - pub fn bgcolor(mut self, bgcolor: crate::Color) -> Self { - self.bgcolor = Some(bgcolor); - self - } - - pub fn intensity(mut self, intensity: Intensity) -> Self { - self.intensity = Some(intensity); - self - } - - pub fn italic(mut self, italic: bool) -> Self { - self.italic = Some(italic); - self - } - - pub fn underline(mut self, underline: bool) -> Self { - self.underline = Some(underline); - self - } - - pub fn inverse(mut self, inverse: bool) -> Self { - self.inverse = Some(inverse); - self - } -} - -impl BufWrite for Attrs { - #[allow(unused_assignments)] - #[allow(clippy::branches_sharing_code)] - fn write_buf(&self, buf: &mut Vec<u8>) { - if self.fgcolor.is_none() - && self.bgcolor.is_none() - && self.intensity.is_none() - && self.italic.is_none() - && self.underline.is_none() - && self.inverse.is_none() - { - return; - } - - buf.extend_from_slice(b"\x1b["); - let mut first = true; - - macro_rules! write_param { - ($i:expr) => {{ - if first { - first = false; - } else { - buf.push(b';'); - } - extend_itoa(buf, $i); - }}; - } - - if let Some(fgcolor) = self.fgcolor { - match fgcolor { - crate::Color::Default => { - write_param!(39); - } - crate::Color::Idx(i) => { - if i < 8 { - write_param!(i + 30); - } else if i < 16 { - write_param!(i + 82); - } else { - write_param!(38); - write_param!(5); - write_param!(i); - } - } - crate::Color::Rgb(r, g, b) => { - write_param!(38); - write_param!(2); - write_param!(r); - write_param!(g); - write_param!(b); - } - } - } - - if let Some(bgcolor) = self.bgcolor { - match bgcolor { - crate::Color::Default => { - write_param!(49); - } - crate::Color::Idx(i) => { - if i < 8 { - write_param!(i + 40); - } else if i < 16 { - write_param!(i + 92); - } else { - write_param!(48); - write_param!(5); - write_param!(i); - } - } - crate::Color::Rgb(r, g, b) => { - write_param!(48); - write_param!(2); - write_param!(r); - write_param!(g); - write_param!(b); - } - } - } - - if let Some(intensity) = self.intensity { - match intensity { - Intensity::Normal => write_param!(22), - Intensity::Bold => write_param!(1), - Intensity::Dim => write_param!(2), - } - } - - if let Some(italic) = self.italic { - if italic { - write_param!(3); - } else { - write_param!(23); - } - } - - if let Some(underline) = self.underline { - if underline { - write_param!(4); - } else { - write_param!(24); - } - } - - if let Some(inverse) = self.inverse { - if inverse { - write_param!(7); - } else { - write_param!(27); - } - } - - buf.push(b'm'); - } -} - -#[derive(Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct MoveRight { - count: u16, -} - -impl MoveRight { - pub fn new(count: u16) -> Self { - Self { count } - } -} - -impl Default for MoveRight { - fn default() -> Self { - Self { count: 1 } - } -} - -impl BufWrite for MoveRight { - fn write_buf(&self, buf: &mut Vec<u8>) { - match self.count { - 0 => {} - 1 => buf.extend_from_slice(b"\x1b[C"), - n => { - buf.extend_from_slice(b"\x1b["); - extend_itoa(buf, n); - buf.push(b'C'); - } - } - } -} - -#[derive(Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct EraseChar { - count: u16, -} - -impl EraseChar { - pub fn new(count: u16) -> Self { - Self { count } - } -} - -impl Default for EraseChar { - fn default() -> Self { - Self { count: 1 } - } -} - -impl BufWrite for EraseChar { - fn write_buf(&self, buf: &mut Vec<u8>) { - match self.count { - 0 => {} - 1 => buf.extend_from_slice(b"\x1b[X"), - n => { - buf.extend_from_slice(b"\x1b["); - extend_itoa(buf, n); - buf.push(b'X'); - } - } - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct HideCursor { - state: bool, -} - -impl HideCursor { - pub fn new(state: bool) -> Self { - Self { state } - } -} - -impl BufWrite for HideCursor { - fn write_buf(&self, buf: &mut Vec<u8>) { - if self.state { - buf.extend_from_slice(b"\x1b[?25l"); - } else { - buf.extend_from_slice(b"\x1b[?25h"); - } - } -} - -#[derive(Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct MoveFromTo { - from: crate::grid::Pos, - to: crate::grid::Pos, -} - -impl MoveFromTo { - pub fn new(from: crate::grid::Pos, to: crate::grid::Pos) -> Self { - Self { from, to } - } -} - -impl BufWrite for MoveFromTo { - fn write_buf(&self, buf: &mut Vec<u8>) { - if self.to.row == self.from.row + 1 && self.to.col == 0 { - crate::term::Crlf.write_buf(buf); - } else if self.from.row == self.to.row && self.from.col < self.to.col - { - crate::term::MoveRight::new(self.to.col - self.from.col) - .write_buf(buf); - } else if self.to != self.from { - crate::term::MoveTo::new(self.to).write_buf(buf); - } - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct ApplicationKeypad { - state: bool, -} - -impl ApplicationKeypad { - pub fn new(state: bool) -> Self { - Self { state } - } -} - -impl BufWrite for ApplicationKeypad { - fn write_buf(&self, buf: &mut Vec<u8>) { - if self.state { - buf.extend_from_slice(b"\x1b="); - } else { - buf.extend_from_slice(b"\x1b>"); - } - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct ApplicationCursor { - state: bool, -} - -impl ApplicationCursor { - pub fn new(state: bool) -> Self { - Self { state } - } -} - -impl BufWrite for ApplicationCursor { - fn write_buf(&self, buf: &mut Vec<u8>) { - if self.state { - buf.extend_from_slice(b"\x1b[?1h"); - } else { - buf.extend_from_slice(b"\x1b[?1l"); - } - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct BracketedPaste { - state: bool, -} - -impl BracketedPaste { - pub fn new(state: bool) -> Self { - Self { state } - } -} - -impl BufWrite for BracketedPaste { - fn write_buf(&self, buf: &mut Vec<u8>) { - if self.state { - buf.extend_from_slice(b"\x1b[?2004h"); - } else { - buf.extend_from_slice(b"\x1b[?2004l"); - } - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct MouseProtocolMode { - mode: crate::MouseProtocolMode, - prev: crate::MouseProtocolMode, -} - -impl MouseProtocolMode { - pub fn new( - mode: crate::MouseProtocolMode, - prev: crate::MouseProtocolMode, - ) -> Self { - Self { mode, prev } - } -} - -impl BufWrite for MouseProtocolMode { - fn write_buf(&self, buf: &mut Vec<u8>) { - if self.mode == self.prev { - return; - } - - match self.mode { - crate::MouseProtocolMode::None => match self.prev { - crate::MouseProtocolMode::None => {} - crate::MouseProtocolMode::Press => { - buf.extend_from_slice(b"\x1b[?9l"); - } - crate::MouseProtocolMode::PressRelease => { - buf.extend_from_slice(b"\x1b[?1000l"); - } - crate::MouseProtocolMode::ButtonMotion => { - buf.extend_from_slice(b"\x1b[?1002l"); - } - crate::MouseProtocolMode::AnyMotion => { - buf.extend_from_slice(b"\x1b[?1003l"); - } - }, - crate::MouseProtocolMode::Press => { - buf.extend_from_slice(b"\x1b[?9h"); - } - crate::MouseProtocolMode::PressRelease => { - buf.extend_from_slice(b"\x1b[?1000h"); - } - crate::MouseProtocolMode::ButtonMotion => { - buf.extend_from_slice(b"\x1b[?1002h"); - } - crate::MouseProtocolMode::AnyMotion => { - buf.extend_from_slice(b"\x1b[?1003h"); - } - } - } -} - -#[derive(Default, Debug)] -#[must_use = "this struct does nothing unless you call write_buf"] -pub struct MouseProtocolEncoding { - encoding: crate::MouseProtocolEncoding, - prev: crate::MouseProtocolEncoding, -} - -impl MouseProtocolEncoding { - pub fn new( - encoding: crate::MouseProtocolEncoding, - prev: crate::MouseProtocolEncoding, - ) -> Self { - Self { encoding, prev } - } -} - -impl BufWrite for MouseProtocolEncoding { - fn write_buf(&self, buf: &mut Vec<u8>) { - if self.encoding == self.prev { - return; - } - - match self.encoding { - crate::MouseProtocolEncoding::Default => match self.prev { - crate::MouseProtocolEncoding::Default => {} - crate::MouseProtocolEncoding::Utf8 => { - buf.extend_from_slice(b"\x1b[?1005l"); - } - crate::MouseProtocolEncoding::Sgr => { - buf.extend_from_slice(b"\x1b[?1006l"); - } - }, - crate::MouseProtocolEncoding::Utf8 => { - buf.extend_from_slice(b"\x1b[?1005h"); - } - crate::MouseProtocolEncoding::Sgr => { - buf.extend_from_slice(b"\x1b[?1006h"); - } - } - } -} - -fn extend_itoa<I: itoa::Integer>(buf: &mut Vec<u8>, i: I) { - let mut itoa_buf = itoa::Buffer::new(); - buf.extend_from_slice(itoa_buf.format(i).as_bytes()); -} |
