diff options
Diffstat (limited to 'vendor/console')
24 files changed, 0 insertions, 4433 deletions
diff --git a/vendor/console/.cargo-checksum.json b/vendor/console/.cargo-checksum.json deleted file mode 100644 index ab16746..0000000 --- a/vendor/console/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"705c0d0cea7a8c090d679ac9399d9dcc31ed15c40eb571d91f03947ad86efe70","Cargo.lock":"3f19acf9c8353b6860267b136400702ec92486f700fc49d18f8862c9db056157","Cargo.toml":"9dccef268d95485475a4be6261bc2f51af881c6e78187dc881afa01621a23e01","LICENSE":"2022c11b24fc1e50fa06a5959e40198a3464f560729ad3d00139abb8a328362d","Makefile":"e708c1503cf3c5e6a218cdd703467f3ff7155f52b5a17950c6ecdf889a9e1338","README.md":"4f2d74ab86b2c1c517aafee98a8d7e53c0da38e1a4b765c7f1a8e0d6e7b1d07a","benches/ansi_parser.rs":"d323989ce68c1a1c0b6cd10f573e4dde11836a168f1b1bbe6c9c21b8db082629","examples/colors.rs":"395c5f8c4950830f3f960ed9b5522e93d5fdbda1d9c3d16c77144f4d87b503c7","examples/colors256.rs":"523682df72f7a4fe398e8d681661a007b96ad52d0c4c963cb22b07b85b1b4f2d","examples/cursor_at.rs":"9e21cedb6d0211fab831c71131bbf5e54e6df8e50129c36faee8957a45c33e1f","examples/term.rs":"10739f800cf0548bb8639d809c1f32b886f27ae4ba716d5db642fb6f37f580c4","scripts/wasmtime-wrapper.sh":"f7cbec1e6de7a456880c737ee264f2d010a40e6e80b4241e4099fb149389291a","src/ansi.rs":"b42b6806a7ca971e3ce2f307b74a3e7ff3f867b67cb342209b1153c0fed2e292","src/common_term.rs":"c924164ac0731148f3c696af0a9af5759465c959631d12fb90462a515e8c186c","src/kb.rs":"72f56323ca7b6741ddb2982c67610fe944cd58095051d84403a15d6e061422d0","src/lib.rs":"1bc9f12672660506c74a313132bb3d2f4fdec550b46c6df75b1cc8124b13d583","src/term.rs":"390403b40053f484a446795198dbaaf9774ea678f153bb19cd70d247b5e01947","src/unix_term.rs":"a1f70fcca92fa019159a7da82d52c62c242acfa51ba85ebae81623c7e6e603aa","src/utils.rs":"1d481c0f6593b29155238fd335f18096b14988fcb725eb2d82667b8f324ac6f6","src/wasm_term.rs":"43b9968ef158df93a269b62d5224837c10ef4d0b7f9c7a3253f8ad099a448af5","src/windows_term/colors.rs":"4c7a53c2341502965dc339f7cd9df54bf3f0b9fbddbba5158757743900e028c5","src/windows_term/mod.rs":"3da9e7e19b9ec0bd172403c8f142192f3e418210d3e28858f363a61e8a041eaf","tests/data/sample_zellij_session.log":"341286d8721451c0a7dc647e7b98438191651199b2d5f03d132e3e971aeddadb"},"package":"c926e00cc70edefdc64d3a5ff31cc65bb97a3460097762bd23afb4d8145fccf8"}
\ No newline at end of file diff --git a/vendor/console/CHANGELOG.md b/vendor/console/CHANGELOG.md deleted file mode 100644 index 1f13206..0000000 --- a/vendor/console/CHANGELOG.md +++ /dev/null @@ -1,103 +0,0 @@ -# Changelog - -## 0.15.7 - -### Enhancements - -* Set an appropriate lower version of libc for macos changes. -* Improved behavior of `read_single_key` so it does not disturb other - threads quite as much. (#165) -* More reliably reset raw mode in terminal. (#171) - -## 0.15.6 - -### Enhancements - -* Switch to `select()` on macOS for polling on TTYs to work around - a macOS bug. (#169) -* Added blink fast and strikethrough attributes. (#159) - -## 0.15.5 - -### Enhancements - -* Removed `regex` dependency. (#153) -* Clarified that `clicolors-control` is no longer used. -* Handle non-tty terminals in `read_char`. (#124) - -## 0.15.4 - -### Enhancements - -* Fix for regression where console size was misreported on windows. (#151) - -## 0.15.3 - -### Enhancements - -* Dropped `terminal_size` dependency. - -## 0.15.2 - -### Enhancements - -* Dropped `once_cell` dependency to support MSRV again. - -## 0.15.1 - -### Enhancements - -* ANSI support no longer depends on `regex` crate. -* Crate now supports `minver`. - -## 0.15.0 - -### Enhancements - -* Added more key recognitions -* Exposed `pad_str_with` to public API -* Added `ReadWritePair` -* Support `color256` in `Style::from_dotted_str` - -### BREAKING - -* Added `ReadWritePair` to `TermTarget` to allow arbitrary read write pairs behave as a term -* Removed `Copy` and `PartialEq` from `TermTarget` - -## 0.14.1 - -### Enhancements - -* Added `NO_COLOR` support -* Added some more key recognitions -* Undeprecate `Term::is_term` - -## 0.14.0 - -### Enhancements - -* Added emoji support for newer Windows terminals. - -### BREAKING - -* Made the windows terminal emulation a non default feature (`windows-console-colors`) - -## 0.13.0 - -### Enhancements - -* Added `user_attended_stderr` for checking if stderr is a terminal -* Removed `termios` dependency - -### Bug Fixes - -* Better handling of key recognition on unix -* `Term::terminal_size()` on stderr terms correctly returns stderr term info - -### Deprecated - -* Deprecate `Term::is_term()` in favor of `Term::features().is_attended()` - -### BREAKING - -* Remove `Term::want_emoji()` in favor of `Term::features().wants_emoji()` diff --git a/vendor/console/Cargo.lock b/vendor/console/Cargo.lock deleted file mode 100644 index 22334e6..0000000 --- a/vendor/console/Cargo.lock +++ /dev/null @@ -1,272 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "aho-corasick" -version = "0.7.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4f55bd91a0978cbfd91c457a164bab8b4001c833b7f323132c0a4e1922dd44e" -dependencies = [ - "memchr", -] - -[[package]] -name = "autocfg" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" - -[[package]] -name = "bit-set" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0700ddab506f33b20a03b13996eccd309a48e5ff77d0d95926aa0210fb4e95f1" -dependencies = [ - "bit-vec", -] - -[[package]] -name = "bit-vec" -version = "0.6.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f9b6a179ed607305526ca489b34ad0a41aed5f7980fa90eb03160b69598fb" - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "byteorder" -version = "1.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" - -[[package]] -name = "cfg-if" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" - -[[package]] -name = "console" -version = "0.15.7" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "proptest", - "regex", - "unicode-width", - "windows-sys", -] - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "getrandom" -version = "0.2.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "lazy_static" -version = "1.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" - -[[package]] -name = "libc" -version = "0.2.133" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f80d65747a3e43d1596c7c5492d95d5edddaabd45a7fcdb02b95f644164966" - -[[package]] -name = "memchr" -version = "2.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" - -[[package]] -name = "num-traits" -version = "0.2.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" -dependencies = [ - "autocfg", -] - -[[package]] -name = "ppv-lite86" -version = "0.2.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" - -[[package]] -name = "proptest" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e0d9cc07f18492d879586c92b485def06bc850da3118075cd45d50e9c95b0e5" -dependencies = [ - "bit-set", - "bitflags", - "byteorder", - "lazy_static", - "num-traits", - "quick-error", - "rand", - "rand_chacha", - "rand_xorshift", - "regex-syntax", -] - -[[package]] -name = "quick-error" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" - -[[package]] -name = "rand" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" -dependencies = [ - "libc", - "rand_chacha", - "rand_core", -] - -[[package]] -name = "rand_chacha" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" -dependencies = [ - "ppv-lite86", - "rand_core", -] - -[[package]] -name = "rand_core" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" -dependencies = [ - "getrandom", -] - -[[package]] -name = "rand_xorshift" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d25bf25ec5ae4a3f1b92f929810509a2f53d7dca2f50b794ff57e3face536c8f" -dependencies = [ - "rand_core", -] - -[[package]] -name = "regex" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.6.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "wasi" -version = "0.11.0+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_i686_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" diff --git a/vendor/console/Cargo.toml b/vendor/console/Cargo.toml deleted file mode 100644 index 85849e1..0000000 --- a/vendor/console/Cargo.toml +++ /dev/null @@ -1,72 +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 = "2018" -rust-version = "1.48.0" -name = "console" -version = "0.15.7" -authors = ["Armin Ronacher <armin.ronacher@active-4.com>"] -description = "A terminal and console abstraction for Rust" -homepage = "https://github.com/console-rs/console" -documentation = "https://docs.rs/console" -readme = "README.md" -keywords = [ - "cli", - "terminal", - "colors", - "console", - "ansi", -] -license = "MIT" -repository = "https://github.com/console-rs/console" - -[dependencies.lazy_static] -version = "1.4.0" - -[dependencies.libc] -version = "0.2.99" - -[dependencies.unicode-width] -version = "0.1" -optional = true - -[dev-dependencies.proptest] -version = "1.0.0" -features = [ - "std", - "bit-set", - "break-dead-code", -] -default-features = false - -[dev-dependencies.regex] -version = "1.4.2" - -[features] -ansi-parsing = [] -default = [ - "unicode-width", - "ansi-parsing", -] -windows-console-colors = ["ansi-parsing"] - -[target."cfg(windows)".dependencies.encode_unicode] -version = "0.3" - -[target."cfg(windows)".dependencies.windows-sys] -version = "0.45.0" -features = [ - "Win32_Foundation", - "Win32_System_Console", - "Win32_Storage_FileSystem", - "Win32_UI_Input_KeyboardAndMouse", -] diff --git a/vendor/console/LICENSE b/vendor/console/LICENSE deleted file mode 100644 index dc9a85c..0000000 --- a/vendor/console/LICENSE +++ /dev/null @@ -1,22 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2017 Armin Ronacher <armin.ronacher@active-4.com> - -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/console/Makefile b/vendor/console/Makefile deleted file mode 100644 index ccab99d..0000000 --- a/vendor/console/Makefile +++ /dev/null @@ -1,39 +0,0 @@ -all: test - -check: - @cargo check --all-features - -build: - @cargo build --all-features - -doc: - @cargo doc --all-features - -test: - @echo "CARGO TESTS" - @cargo test - @cargo test --all-features - @cargo test --no-default-features - -check-minver: - @echo "MINVER CHECK" - @cargo minimal-versions check - @cargo minimal-versions check --all-features - @cargo minimal-versions check --no-default-features - -format: - @rustup component add rustfmt 2> /dev/null - @cargo fmt --all - -format-check: - @rustup component add rustfmt 2> /dev/null - @cargo fmt --all -- --check - -lint: - @rustup component add clippy 2> /dev/null - @cargo clippy --examples --tests - -msrv-lock: - @cargo update -p proptest --precise=1.0.0 - -.PHONY: all doc build check test format format-check lint check-minver msrv-lock diff --git a/vendor/console/README.md b/vendor/console/README.md deleted file mode 100644 index 9a046d8..0000000 --- a/vendor/console/README.md +++ /dev/null @@ -1,76 +0,0 @@ -# `console` - -[![Build Status](https://github.com/console-rs/console/workflows/CI/badge.svg?branch=master)](https://github.com/console-rs/console/actions?query=workflow%3ACI) -[![Crates.io](https://img.shields.io/crates/d/console.svg)](https://crates.io/crates/console) -[![License](https://img.shields.io/github/license/console-rs/console)](https://github.com/console-rs/console/blob/master/LICENSE) -[![rustc 1.48.0](https://img.shields.io/badge/rust-1.48%2B-orange.svg)](https://img.shields.io/badge/rust-1.48%2B-orange.svg) -[![Documentation](https://docs.rs/console/badge.svg)](https://docs.rs/console) - -**console** is a library for Rust that provides access to various terminal -features so you can build nicer looking command line interfaces. It -comes with various tools and utilities for working with Terminals and -formatting text. - -Best paired with other libraries in the family: - -* [dialoguer](https://docs.rs/dialoguer) -* [indicatif](https://docs.rs/indicatif) - -## Terminal Access - -The terminal is abstracted through the `console::Term` type. It can -either directly provide access to the connected terminal or by buffering -up commands. A buffered terminal will however not be completely buffered -on windows where cursor movements are currently directly passed through. - -Example usage: - -```rust -use std::thread; -use std::time::Duration; - -use console::Term; - -let term = Term::stdout(); -term.write_line("Hello World!")?; -thread::sleep(Duration::from_millis(2000)); -term.clear_line()?; -``` - -## Colors and Styles - -`console` automaticaly detects when to use colors based on the tty flag. It also -provides higher level wrappers for styling text and other things that can be -displayed with the `style` function and utility types. - -Example usage: - -```rust -use console::style; - -println!("This is {} neat", style("quite").cyan()); -``` - -You can also store styles and apply them to text later: - -```rust -use console::Style; - -let cyan = Style::new().cyan(); -println!("This is {} neat", cyan.apply_to("quite")); -``` - -## Working with ANSI Codes - -The crate provides the function `strip_ansi_codes` to remove ANSI codes -from a string as well as `measure_text_width` to calculate the width of a -string as it would be displayed by the terminal. Both of those together -are useful for more complex formatting. - -## Unicode Width Support - -By default this crate depends on the `unicode-width` crate to calculate -the width of terminal characters. If you do not need this you can disable -the `unicode-width` feature which will cut down on dependencies. - -License: MIT diff --git a/vendor/console/benches/ansi_parser.rs b/vendor/console/benches/ansi_parser.rs deleted file mode 100644 index 2d74c42..0000000 --- a/vendor/console/benches/ansi_parser.rs +++ /dev/null @@ -1,27 +0,0 @@ -use console::{strip_ansi_codes, AnsiCodeIterator}; -use criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}; - -use std::{fs, path::Path}; - -pub fn parse_throughput(c: &mut Criterion) { - let session_log_path = Path::new("tests") - .join("data") - .join("sample_zellij_session.log"); - let session_log = fs::read_to_string(session_log_path).unwrap(); - - let mut group = c.benchmark_group("ansi-parsing"); - group.throughput(Throughput::Bytes(session_log.len() as u64)); - group.bench_function("parse", |b| { - b.iter(|| { - let v: Vec<_> = AnsiCodeIterator::new(&session_log).collect(); - black_box(v); - }) - }); - group.bench_function("strip", |b| { - b.iter(|| black_box(strip_ansi_codes(&session_log))) - }); - group.finish(); -} - -criterion_group!(throughput, parse_throughput); -criterion_main!(throughput); diff --git a/vendor/console/examples/colors.rs b/vendor/console/examples/colors.rs deleted file mode 100644 index 69c51fd..0000000 --- a/vendor/console/examples/colors.rs +++ /dev/null @@ -1,14 +0,0 @@ -use console::style; - -fn main() { - println!( - "This is red on black: {:010x}", - style(42).red().on_black().bold() - ); - println!("This is reversed: [{}]", style("whatever").reverse()); - println!("This is cyan: {}", style("whatever").cyan()); - eprintln!( - "This is black bright: {}", - style("whatever").for_stderr().bright().black() - ); -} diff --git a/vendor/console/examples/colors256.rs b/vendor/console/examples/colors256.rs deleted file mode 100644 index 60acb88..0000000 --- a/vendor/console/examples/colors256.rs +++ /dev/null @@ -1,17 +0,0 @@ -use console::style; - -fn main() { - for i in 0..=255 { - print!("{:03} ", style(i).color256(i)); - if i % 16 == 15 { - println!(); - } - } - - for i in 0..=255 { - print!("{:03} ", style(i).black().on_color256(i)); - if i % 16 == 15 { - println!(); - } - } -} diff --git a/vendor/console/examples/cursor_at.rs b/vendor/console/examples/cursor_at.rs deleted file mode 100644 index 9a1bb3d..0000000 --- a/vendor/console/examples/cursor_at.rs +++ /dev/null @@ -1,30 +0,0 @@ -extern crate console; - -use std::io; -use std::thread; -use std::time::Duration; - -use console::{style, Term}; - -fn write_chars() -> io::Result<()> { - let term = Term::stdout(); - let (heigth, width) = term.size(); - for x in 0..width { - for y in 0..heigth { - term.move_cursor_to(x as usize, y as usize)?; - let text = if (x + y) % 2 == 0 { - format!("{}", style(x % 10).black().on_red()) - } else { - format!("{}", style(x % 10).red().on_black()) - }; - - term.write_str(&text)?; - thread::sleep(Duration::from_micros(600)); - } - } - Ok(()) -} - -fn main() { - write_chars().unwrap(); -} diff --git a/vendor/console/examples/term.rs b/vendor/console/examples/term.rs deleted file mode 100644 index a0637f7..0000000 --- a/vendor/console/examples/term.rs +++ /dev/null @@ -1,33 +0,0 @@ -use std::io::{self, Write}; -use std::thread; -use std::time::Duration; - -use console::{style, Term}; - -fn do_stuff() -> io::Result<()> { - let term = Term::stdout(); - term.set_title("Counting..."); - term.write_line("Going to do some counting now")?; - term.hide_cursor()?; - for x in 0..10 { - if x != 0 { - term.move_cursor_up(1)?; - } - term.write_line(&format!("Counting {}/10", style(x + 1).cyan()))?; - thread::sleep(Duration::from_millis(400)); - } - term.show_cursor()?; - term.clear_last_lines(1)?; - term.write_line("Done counting!")?; - writeln!(&term, "Hello World!")?; - - write!(&term, "To edit: ")?; - let res = term.read_line_initial_text("default")?; - writeln!(&term, "\n{}", res)?; - - Ok(()) -} - -fn main() { - do_stuff().unwrap(); -} diff --git a/vendor/console/scripts/wasmtime-wrapper.sh b/vendor/console/scripts/wasmtime-wrapper.sh deleted file mode 100755 index 75d8ca5..0000000 --- a/vendor/console/scripts/wasmtime-wrapper.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/bash -SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" -cd $SCRIPT_DIR/.. -wasmtime run --env INSTA_WORKSPACE_ROOT=/ --mapdir "/::$(pwd)" -- "$@" diff --git a/vendor/console/src/ansi.rs b/vendor/console/src/ansi.rs deleted file mode 100644 index 3a3c96c..0000000 --- a/vendor/console/src/ansi.rs +++ /dev/null @@ -1,438 +0,0 @@ -use std::{ - borrow::Cow, - iter::{FusedIterator, Peekable}, - str::CharIndices, -}; - -#[derive(Debug, Clone, Copy)] -enum State { - Start, - S1, - S2, - S3, - S4, - S5, - S6, - S7, - S8, - S9, - S10, - S11, - Trap, -} - -impl Default for State { - fn default() -> Self { - Self::Start - } -} - -impl State { - fn is_final(&self) -> bool { - #[allow(clippy::match_like_matches_macro)] - match self { - Self::S3 | Self::S5 | Self::S6 | Self::S7 | Self::S8 | Self::S9 | Self::S11 => true, - _ => false, - } - } - - fn is_trapped(&self) -> bool { - #[allow(clippy::match_like_matches_macro)] - match self { - Self::Trap => true, - _ => false, - } - } - - fn transition(&mut self, c: char) { - *self = match c { - '\u{1b}' | '\u{9b}' => match self { - Self::Start => Self::S1, - _ => Self::Trap, - }, - '(' | ')' => match self { - Self::S1 => Self::S2, - Self::S2 | Self::S4 => Self::S4, - _ => Self::Trap, - }, - ';' => match self { - Self::S1 | Self::S2 | Self::S4 => Self::S4, - Self::S5 | Self::S6 | Self::S7 | Self::S8 | Self::S10 => Self::S10, - _ => Self::Trap, - }, - - '[' | '#' | '?' => match self { - Self::S1 | Self::S2 | Self::S4 => Self::S4, - _ => Self::Trap, - }, - '0'..='2' => match self { - Self::S1 | Self::S4 => Self::S5, - Self::S2 => Self::S3, - Self::S5 => Self::S6, - Self::S6 => Self::S7, - Self::S7 => Self::S8, - Self::S8 => Self::S9, - Self::S10 => Self::S5, - _ => Self::Trap, - }, - '3'..='9' => match self { - Self::S1 | Self::S4 => Self::S5, - Self::S2 => Self::S5, - Self::S5 => Self::S6, - Self::S6 => Self::S7, - Self::S7 => Self::S8, - Self::S8 => Self::S9, - Self::S10 => Self::S5, - _ => Self::Trap, - }, - 'A'..='P' | 'R' | 'Z' | 'c' | 'f'..='n' | 'q' | 'r' | 'y' | '=' | '>' | '<' => { - match self { - Self::S1 - | Self::S2 - | Self::S4 - | Self::S5 - | Self::S6 - | Self::S7 - | Self::S8 - | Self::S10 => Self::S11, - _ => Self::Trap, - } - } - _ => Self::Trap, - }; - } -} - -#[derive(Debug)] -struct Matches<'a> { - s: &'a str, - it: Peekable<CharIndices<'a>>, -} - -impl<'a> Matches<'a> { - fn new(s: &'a str) -> Self { - let it = s.char_indices().peekable(); - Self { s, it } - } -} - -#[derive(Debug)] -struct Match<'a> { - text: &'a str, - start: usize, - end: usize, -} - -impl<'a> Match<'a> { - #[inline] - pub fn as_str(&self) -> &'a str { - &self.text[self.start..self.end] - } -} - -impl<'a> Iterator for Matches<'a> { - type Item = Match<'a>; - - fn next(&mut self) -> Option<Self::Item> { - find_ansi_code_exclusive(&mut self.it).map(|(start, end)| Match { - text: self.s, - start, - end, - }) - } -} - -impl<'a> FusedIterator for Matches<'a> {} - -fn find_ansi_code_exclusive(it: &mut Peekable<CharIndices>) -> Option<(usize, usize)> { - 'outer: loop { - if let (start, '\u{1b}') | (start, '\u{9b}') = it.peek()? { - let start = *start; - let mut state = State::default(); - let mut maybe_end = None; - - loop { - let item = it.peek(); - - if let Some((idx, c)) = item { - state.transition(*c); - - if state.is_final() { - maybe_end = Some(*idx); - } - } - - // The match is greedy so run till we hit the trap state no matter what. A valid - // match is just one that was final at some point - if state.is_trapped() || item.is_none() { - match maybe_end { - Some(end) => { - // All possible final characters are a single byte so it's safe to make - // the end exclusive by just adding one - return Some((start, end + 1)); - } - // The character we are peeking right now might be the start of a match so - // we want to continue the loop without popping off that char - None => continue 'outer, - } - } - - it.next(); - } - } - - it.next(); - } -} - -/// Helper function to strip ansi codes. -pub fn strip_ansi_codes(s: &str) -> Cow<str> { - let mut char_it = s.char_indices().peekable(); - match find_ansi_code_exclusive(&mut char_it) { - Some(_) => { - let stripped: String = AnsiCodeIterator::new(s) - .filter_map(|(text, is_ansi)| if is_ansi { None } else { Some(text) }) - .collect(); - Cow::Owned(stripped) - } - None => Cow::Borrowed(s), - } -} - -/// An iterator over ansi codes in a string. -/// -/// This type can be used to scan over ansi codes in a string. -/// It yields tuples in the form `(s, is_ansi)` where `s` is a slice of -/// the original string and `is_ansi` indicates if the slice contains -/// ansi codes or string values. -pub struct AnsiCodeIterator<'a> { - s: &'a str, - pending_item: Option<(&'a str, bool)>, - last_idx: usize, - cur_idx: usize, - iter: Matches<'a>, -} - -impl<'a> AnsiCodeIterator<'a> { - /// Creates a new ansi code iterator. - pub fn new(s: &'a str) -> AnsiCodeIterator<'a> { - AnsiCodeIterator { - s, - pending_item: None, - last_idx: 0, - cur_idx: 0, - iter: Matches::new(s), - } - } - - /// Returns the string slice up to the current match. - pub fn current_slice(&self) -> &str { - &self.s[..self.cur_idx] - } - - /// Returns the string slice from the current match to the end. - pub fn rest_slice(&self) -> &str { - &self.s[self.cur_idx..] - } -} - -impl<'a> Iterator for AnsiCodeIterator<'a> { - type Item = (&'a str, bool); - - fn next(&mut self) -> Option<(&'a str, bool)> { - if let Some(pending_item) = self.pending_item.take() { - self.cur_idx += pending_item.0.len(); - Some(pending_item) - } else if let Some(m) = self.iter.next() { - let s = &self.s[self.last_idx..m.start]; - self.last_idx = m.end; - if s.is_empty() { - self.cur_idx = m.end; - Some((m.as_str(), true)) - } else { - self.cur_idx = m.start; - self.pending_item = Some((m.as_str(), true)); - Some((s, false)) - } - } else if self.last_idx < self.s.len() { - let rv = &self.s[self.last_idx..]; - self.cur_idx = self.s.len(); - self.last_idx = self.s.len(); - Some((rv, false)) - } else { - None - } - } -} - -impl<'a> FusedIterator for AnsiCodeIterator<'a> {} - -#[cfg(test)] -mod tests { - use super::*; - - use lazy_static::lazy_static; - use proptest::prelude::*; - use regex::Regex; - - // The manual dfa `State` is a handwritten translation from the previously used regex. That - // regex is kept here and used to ensure that the new matches are the same as the old - lazy_static! { - static ref STRIP_ANSI_RE: Regex = Regex::new( - r"[\x1b\x9b]([()][012AB]|[\[()#;?]*(?:[0-9]{1,4}(?:;[0-9]{0,4})*)?[0-9A-PRZcf-nqry=><])", - ) - .unwrap(); - } - - impl<'a, 'b> PartialEq<Match<'a>> for regex::Match<'b> { - fn eq(&self, other: &Match<'a>) -> bool { - self.start() == other.start && self.end() == other.end - } - } - - proptest! { - #[test] - fn dfa_matches_old_regex(s in r"([\x1b\x9b]?.*){0,5}") { - let old_matches: Vec<_> = STRIP_ANSI_RE.find_iter(&s).collect(); - let new_matches: Vec<_> = Matches::new(&s).collect(); - assert_eq!(old_matches, new_matches); - } - } - - #[test] - fn dfa_matches_regex_on_small_strings() { - // To make sure the test runs in a reasonable time this is a slimmed down list of - // characters to reduce the groups that are only used with each other along with one - // arbitrarily chosen character not used in the regex (' ') - const POSSIBLE_BYTES: &[u8] = &[b' ', 0x1b, 0x9b, b'(', b'0', b'[', b';', b'3', b'C']; - - fn check_all_strings_of_len(len: usize) { - _check_all_strings_of_len(len, &mut Vec::with_capacity(len)); - } - - fn _check_all_strings_of_len(len: usize, chunk: &mut Vec<u8>) { - if len == 0 { - if let Ok(s) = std::str::from_utf8(chunk) { - let old_matches: Vec<_> = STRIP_ANSI_RE.find_iter(s).collect(); - let new_matches: Vec<_> = Matches::new(s).collect(); - assert_eq!(old_matches, new_matches); - } - - return; - } - - for b in POSSIBLE_BYTES { - chunk.push(*b); - _check_all_strings_of_len(len - 1, chunk); - chunk.pop(); - } - } - - for str_len in 0..=6 { - check_all_strings_of_len(str_len); - } - } - - #[test] - fn complex_data() { - let s = std::fs::read_to_string( - std::path::Path::new("tests") - .join("data") - .join("sample_zellij_session.log"), - ) - .unwrap(); - - let old_matches: Vec<_> = STRIP_ANSI_RE.find_iter(&s).collect(); - let new_matches: Vec<_> = Matches::new(&s).collect(); - assert_eq!(old_matches, new_matches); - } - - #[test] - fn state_machine() { - let ansi_code = "\x1b)B"; - let mut state = State::default(); - assert!(!state.is_final()); - - for c in ansi_code.chars() { - state.transition(c); - } - assert!(state.is_final()); - - state.transition('A'); - assert!(state.is_trapped()); - } - - #[test] - fn back_to_back_entry_char() { - let s = "\x1b\x1bf"; - let matches: Vec<_> = Matches::new(s).map(|m| m.as_str()).collect(); - assert_eq!(&["\x1bf"], matches.as_slice()); - } - - #[test] - fn early_paren_can_use_many_chars() { - let s = "\x1b(C"; - let matches: Vec<_> = Matches::new(s).map(|m| m.as_str()).collect(); - assert_eq!(&[s], matches.as_slice()); - } - - #[test] - fn long_run_of_digits() { - let s = "\u{1b}00000"; - let matches: Vec<_> = Matches::new(s).map(|m| m.as_str()).collect(); - assert_eq!(&[s], matches.as_slice()); - } - - #[test] - fn test_ansi_iter_re_vt100() { - let s = "\x1b(0lpq\x1b)Benglish"; - let mut iter = AnsiCodeIterator::new(s); - assert_eq!(iter.next(), Some(("\x1b(0", true))); - assert_eq!(iter.next(), Some(("lpq", false))); - assert_eq!(iter.next(), Some(("\x1b)B", true))); - assert_eq!(iter.next(), Some(("english", false))); - } - - #[test] - fn test_ansi_iter_re() { - use crate::style; - let s = format!("Hello {}!", style("World").red().force_styling(true)); - let mut iter = AnsiCodeIterator::new(&s); - assert_eq!(iter.next(), Some(("Hello ", false))); - assert_eq!(iter.current_slice(), "Hello "); - assert_eq!(iter.rest_slice(), "\x1b[31mWorld\x1b[0m!"); - assert_eq!(iter.next(), Some(("\x1b[31m", true))); - assert_eq!(iter.current_slice(), "Hello \x1b[31m"); - assert_eq!(iter.rest_slice(), "World\x1b[0m!"); - assert_eq!(iter.next(), Some(("World", false))); - assert_eq!(iter.current_slice(), "Hello \x1b[31mWorld"); - assert_eq!(iter.rest_slice(), "\x1b[0m!"); - assert_eq!(iter.next(), Some(("\x1b[0m", true))); - assert_eq!(iter.current_slice(), "Hello \x1b[31mWorld\x1b[0m"); - assert_eq!(iter.rest_slice(), "!"); - assert_eq!(iter.next(), Some(("!", false))); - assert_eq!(iter.current_slice(), "Hello \x1b[31mWorld\x1b[0m!"); - assert_eq!(iter.rest_slice(), ""); - assert_eq!(iter.next(), None); - } - - #[test] - fn test_ansi_iter_re_on_multi() { - use crate::style; - let s = format!("{}", style("a").red().bold().force_styling(true)); - let mut iter = AnsiCodeIterator::new(&s); - assert_eq!(iter.next(), Some(("\x1b[31m", true))); - assert_eq!(iter.current_slice(), "\x1b[31m"); - assert_eq!(iter.rest_slice(), "\x1b[1ma\x1b[0m"); - assert_eq!(iter.next(), Some(("\x1b[1m", true))); - assert_eq!(iter.current_slice(), "\x1b[31m\x1b[1m"); - assert_eq!(iter.rest_slice(), "a\x1b[0m"); - assert_eq!(iter.next(), Some(("a", false))); - assert_eq!(iter.current_slice(), "\x1b[31m\x1b[1ma"); - assert_eq!(iter.rest_slice(), "\x1b[0m"); - assert_eq!(iter.next(), Some(("\x1b[0m", true))); - assert_eq!(iter.current_slice(), "\x1b[31m\x1b[1ma\x1b[0m"); - assert_eq!(iter.rest_slice(), ""); - assert_eq!(iter.next(), None); - } -} diff --git a/vendor/console/src/common_term.rs b/vendor/console/src/common_term.rs deleted file mode 100644 index 020660a..0000000 --- a/vendor/console/src/common_term.rs +++ /dev/null @@ -1,72 +0,0 @@ -use std::io; - -use crate::term::Term; - -pub fn move_cursor_down(out: &Term, n: usize) -> io::Result<()> { - if n > 0 { - out.write_str(&format!("\x1b[{}B", n)) - } else { - Ok(()) - } -} - -pub fn move_cursor_up(out: &Term, n: usize) -> io::Result<()> { - if n > 0 { - out.write_str(&format!("\x1b[{}A", n)) - } else { - Ok(()) - } -} -pub fn move_cursor_left(out: &Term, n: usize) -> io::Result<()> { - if n > 0 { - out.write_str(&format!("\x1b[{}D", n)) - } else { - Ok(()) - } -} - -pub fn move_cursor_right(out: &Term, n: usize) -> io::Result<()> { - if n > 0 { - out.write_str(&format!("\x1b[{}C", n)) - } else { - Ok(()) - } -} - -#[inline] -pub fn move_cursor_to(out: &Term, x: usize, y: usize) -> io::Result<()> { - out.write_str(&format!("\x1B[{};{}H", y + 1, x + 1)) -} - -pub fn clear_chars(out: &Term, n: usize) -> io::Result<()> { - if n > 0 { - out.write_str(&format!("\x1b[{}D\x1b[0K", n)) - } else { - Ok(()) - } -} - -#[inline] -pub fn clear_line(out: &Term) -> io::Result<()> { - out.write_str("\r\x1b[2K") -} - -#[inline] -pub fn clear_screen(out: &Term) -> io::Result<()> { - out.write_str("\r\x1b[2J\r\x1b[H") -} - -#[inline] -pub fn clear_to_end_of_screen(out: &Term) -> io::Result<()> { - out.write_str("\r\x1b[0J") -} - -#[inline] -pub fn show_cursor(out: &Term) -> io::Result<()> { - out.write_str("\x1b[?25h") -} - -#[inline] -pub fn hide_cursor(out: &Term) -> io::Result<()> { - out.write_str("\x1b[?25l") -} diff --git a/vendor/console/src/kb.rs b/vendor/console/src/kb.rs deleted file mode 100644 index 5258c13..0000000 --- a/vendor/console/src/kb.rs +++ /dev/null @@ -1,29 +0,0 @@ -/// Key mapping -/// -/// This is an incomplete mapping of keys that are supported for reading -/// from the keyboard. -#[non_exhaustive] -#[derive(Clone, PartialEq, Eq, Debug, Hash)] -pub enum Key { - Unknown, - /// Unrecognized sequence containing Esc and a list of chars - UnknownEscSeq(Vec<char>), - ArrowLeft, - ArrowRight, - ArrowUp, - ArrowDown, - Enter, - Escape, - Backspace, - Home, - End, - Tab, - BackTab, - Alt, - Del, - Shift, - Insert, - PageUp, - PageDown, - Char(char), -} diff --git a/vendor/console/src/lib.rs b/vendor/console/src/lib.rs deleted file mode 100644 index 1b18afc..0000000 --- a/vendor/console/src/lib.rs +++ /dev/null @@ -1,104 +0,0 @@ -//! console is a library for Rust that provides access to various terminal -//! features so you can build nicer looking command line interfaces. It -//! comes with various tools and utilities for working with Terminals and -//! formatting text. -//! -//! Best paired with other libraries in the family: -//! -//! * [dialoguer](https://docs.rs/dialoguer) -//! * [indicatif](https://docs.rs/indicatif) -//! -//! # Terminal Access -//! -//! The terminal is abstracted through the `console::Term` type. It can -//! either directly provide access to the connected terminal or by buffering -//! up commands. A buffered terminal will however not be completely buffered -//! on windows where cursor movements are currently directly passed through. -//! -//! Example usage: -//! -//! ``` -//! # fn test() -> Result<(), Box<dyn std::error::Error>> { -//! use std::thread; -//! use std::time::Duration; -//! -//! use console::Term; -//! -//! let term = Term::stdout(); -//! term.write_line("Hello World!")?; -//! thread::sleep(Duration::from_millis(2000)); -//! term.clear_line()?; -//! # Ok(()) } test().unwrap(); -//! ``` -//! -//! # Colors and Styles -//! -//! `console` automaticaly detects when to use colors based on the tty flag. It also -//! provides higher level wrappers for styling text and other things that can be -//! displayed with the `style` function and utility types. -//! -//! Example usage: -//! -//! ``` -//! use console::style; -//! -//! println!("This is {} neat", style("quite").cyan()); -//! ``` -//! -//! You can also store styles and apply them to text later: -//! -//! ``` -//! use console::Style; -//! -//! let cyan = Style::new().cyan(); -//! println!("This is {} neat", cyan.apply_to("quite")); -//! ``` -//! -//! # Working with ANSI Codes -//! -//! The crate provids the function `strip_ansi_codes` to remove ANSI codes -//! from a string as well as `measure_text_width` to calculate the width of a -//! string as it would be displayed by the terminal. Both of those together -//! are useful for more complex formatting. -//! -//! # Unicode Width Support -//! -//! By default this crate depends on the `unicode-width` crate to calculate -//! the width of terminal characters. If you do not need this you can disable -//! the `unicode-width` feature which will cut down on dependencies. -//! -//! # Features -//! -//! By default all features are enabled. The following features exist: -//! -//! * `unicode-width`: adds support for unicode width calculations -//! * `ansi-parsing`: adds support for parsing ansi codes (this adds support -//! for stripping and taking ansi escape codes into account for length -//! calculations). - -pub use crate::kb::Key; -pub use crate::term::{ - user_attended, user_attended_stderr, Term, TermFamily, TermFeatures, TermTarget, -}; -pub use crate::utils::{ - colors_enabled, colors_enabled_stderr, measure_text_width, pad_str, pad_str_with, - set_colors_enabled, set_colors_enabled_stderr, style, truncate_str, Alignment, Attribute, - Color, Emoji, Style, StyledObject, -}; - -#[cfg(feature = "ansi-parsing")] -pub use crate::ansi::{strip_ansi_codes, AnsiCodeIterator}; - -mod common_term; -mod kb; -mod term; -#[cfg(unix)] -mod unix_term; -mod utils; -#[cfg(target_arch = "wasm32")] -mod wasm_term; -#[cfg(windows)] -mod windows_term; - -#[cfg(feature = "ansi-parsing")] -mod ansi; diff --git a/vendor/console/src/term.rs b/vendor/console/src/term.rs deleted file mode 100644 index 0a40258..0000000 --- a/vendor/console/src/term.rs +++ /dev/null @@ -1,632 +0,0 @@ -use std::fmt::{Debug, Display}; -use std::io::{self, Read, Write}; -use std::sync::{Arc, Mutex}; - -#[cfg(unix)] -use std::os::unix::io::{AsRawFd, RawFd}; -#[cfg(windows)] -use std::os::windows::io::{AsRawHandle, RawHandle}; - -use crate::{kb::Key, utils::Style}; - -#[cfg(unix)] -trait TermWrite: Write + Debug + AsRawFd + Send {} -#[cfg(unix)] -impl<T: Write + Debug + AsRawFd + Send> TermWrite for T {} - -#[cfg(unix)] -trait TermRead: Read + Debug + AsRawFd + Send {} -#[cfg(unix)] -impl<T: Read + Debug + AsRawFd + Send> TermRead for T {} - -#[cfg(unix)] -#[derive(Debug, Clone)] -pub struct ReadWritePair { - #[allow(unused)] - read: Arc<Mutex<dyn TermRead>>, - write: Arc<Mutex<dyn TermWrite>>, - style: Style, -} - -/// Where the term is writing. -#[derive(Debug, Clone)] -pub enum TermTarget { - Stdout, - Stderr, - #[cfg(unix)] - ReadWritePair(ReadWritePair), -} - -#[derive(Debug)] -pub struct TermInner { - target: TermTarget, - buffer: Option<Mutex<Vec<u8>>>, -} - -/// The family of the terminal. -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum TermFamily { - /// Redirected to a file or file like thing. - File, - /// A standard unix terminal. - UnixTerm, - /// A cmd.exe like windows console. - WindowsConsole, - /// A dummy terminal (for instance on wasm) - Dummy, -} - -/// Gives access to the terminal features. -#[derive(Debug, Clone)] -pub struct TermFeatures<'a>(&'a Term); - -impl<'a> TermFeatures<'a> { - /// Check if this is a real user attended terminal (`isatty`) - #[inline] - pub fn is_attended(&self) -> bool { - is_a_terminal(self.0) - } - - /// Check if colors are supported by this terminal. - /// - /// This does not check if colors are enabled. Currently all terminals - /// are considered to support colors - #[inline] - pub fn colors_supported(&self) -> bool { - is_a_color_terminal(self.0) - } - - /// Check if this terminal is an msys terminal. - /// - /// This is sometimes useful to disable features that are known to not - /// work on msys terminals or require special handling. - #[inline] - pub fn is_msys_tty(&self) -> bool { - #[cfg(windows)] - { - msys_tty_on(self.0) - } - #[cfg(not(windows))] - { - false - } - } - - /// Check if this terminal wants emojis. - #[inline] - pub fn wants_emoji(&self) -> bool { - self.is_attended() && wants_emoji() - } - - /// Return the family of the terminal. - #[inline] - pub fn family(&self) -> TermFamily { - if !self.is_attended() { - return TermFamily::File; - } - #[cfg(windows)] - { - TermFamily::WindowsConsole - } - #[cfg(unix)] - { - TermFamily::UnixTerm - } - #[cfg(target_arch = "wasm32")] - { - TermFamily::Dummy - } - } -} - -/// Abstraction around a terminal. -/// -/// A terminal can be cloned. If a buffer is used it's shared across all -/// clones which means it largely acts as a handle. -#[derive(Clone, Debug)] -pub struct Term { - inner: Arc<TermInner>, - pub(crate) is_msys_tty: bool, - pub(crate) is_tty: bool, -} - -impl Term { - fn with_inner(inner: TermInner) -> Term { - let mut term = Term { - inner: Arc::new(inner), - is_msys_tty: false, - is_tty: false, - }; - - term.is_msys_tty = term.features().is_msys_tty(); - term.is_tty = term.features().is_attended(); - term - } - - /// Return a new unbuffered terminal. - #[inline] - pub fn stdout() -> Term { - Term::with_inner(TermInner { - target: TermTarget::Stdout, - buffer: None, - }) - } - - /// Return a new unbuffered terminal to stderr. - #[inline] - pub fn stderr() -> Term { - Term::with_inner(TermInner { - target: TermTarget::Stderr, - buffer: None, - }) - } - - /// Return a new buffered terminal. - pub fn buffered_stdout() -> Term { - Term::with_inner(TermInner { - target: TermTarget::Stdout, - buffer: Some(Mutex::new(vec![])), - }) - } - - /// Return a new buffered terminal to stderr. - pub fn buffered_stderr() -> Term { - Term::with_inner(TermInner { - target: TermTarget::Stderr, - buffer: Some(Mutex::new(vec![])), - }) - } - - /// Return a terminal for the given Read/Write pair styled like stderr. - #[cfg(unix)] - pub fn read_write_pair<R, W>(read: R, write: W) -> Term - where - R: Read + Debug + AsRawFd + Send + 'static, - W: Write + Debug + AsRawFd + Send + 'static, - { - Self::read_write_pair_with_style(read, write, Style::new().for_stderr()) - } - - /// Return a terminal for the given Read/Write pair. - #[cfg(unix)] - pub fn read_write_pair_with_style<R, W>(read: R, write: W, style: Style) -> Term - where - R: Read + Debug + AsRawFd + Send + 'static, - W: Write + Debug + AsRawFd + Send + 'static, - { - Term::with_inner(TermInner { - target: TermTarget::ReadWritePair(ReadWritePair { - read: Arc::new(Mutex::new(read)), - write: Arc::new(Mutex::new(write)), - style, - }), - buffer: None, - }) - } - - /// Return the style for this terminal. - #[inline] - pub fn style(&self) -> Style { - match self.inner.target { - TermTarget::Stderr => Style::new().for_stderr(), - TermTarget::Stdout => Style::new().for_stdout(), - #[cfg(unix)] - TermTarget::ReadWritePair(ReadWritePair { ref style, .. }) => style.clone(), - } - } - - /// Return the target of this terminal. - #[inline] - pub fn target(&self) -> TermTarget { - self.inner.target.clone() - } - - #[doc(hidden)] - pub fn write_str(&self, s: &str) -> io::Result<()> { - match self.inner.buffer { - Some(ref buffer) => buffer.lock().unwrap().write_all(s.as_bytes()), - None => self.write_through(s.as_bytes()), - } - } - - /// Write a string to the terminal and add a newline. - pub fn write_line(&self, s: &str) -> io::Result<()> { - match self.inner.buffer { - Some(ref mutex) => { - let mut buffer = mutex.lock().unwrap(); - buffer.extend_from_slice(s.as_bytes()); - buffer.push(b'\n'); - Ok(()) - } - None => self.write_through(format!("{}\n", s).as_bytes()), - } - } - - /// Read a single character from the terminal. - /// - /// This does not echo the character and blocks until a single character - /// or complete key chord is entered. If the terminal is not user attended - /// the return value will be an error. - pub fn read_char(&self) -> io::Result<char> { - if !self.is_tty { - return Err(io::Error::new( - io::ErrorKind::NotConnected, - "Not a terminal", - )); - } - loop { - match self.read_key()? { - Key::Char(c) => { - return Ok(c); - } - Key::Enter => { - return Ok('\n'); - } - _ => {} - } - } - } - - /// Read a single key form the terminal. - /// - /// This does not echo anything. If the terminal is not user attended - /// the return value will always be the unknown key. - pub fn read_key(&self) -> io::Result<Key> { - if !self.is_tty { - Ok(Key::Unknown) - } else { - read_single_key() - } - } - - /// Read one line of input. - /// - /// This does not include the trailing newline. If the terminal is not - /// user attended the return value will always be an empty string. - pub fn read_line(&self) -> io::Result<String> { - if !self.is_tty { - return Ok("".into()); - } - let mut rv = String::new(); - io::stdin().read_line(&mut rv)?; - let len = rv.trim_end_matches(&['\r', '\n'][..]).len(); - rv.truncate(len); - Ok(rv) - } - - /// Read one line of input with initial text. - /// - /// This does not include the trailing newline. If the terminal is not - /// user attended the return value will always be an empty string. - pub fn read_line_initial_text(&self, initial: &str) -> io::Result<String> { - if !self.is_tty { - return Ok("".into()); - } - self.write_str(initial)?; - - let mut chars: Vec<char> = initial.chars().collect(); - - loop { - match self.read_key()? { - Key::Backspace => { - if chars.pop().is_some() { - self.clear_chars(1)?; - } - self.flush()?; - } - Key::Char(chr) => { - chars.push(chr); - let mut bytes_char = [0; 4]; - chr.encode_utf8(&mut bytes_char); - self.write_str(chr.encode_utf8(&mut bytes_char))?; - self.flush()?; - } - Key::Enter => { - self.write_line("")?; - break; - } - _ => (), - } - } - Ok(chars.iter().collect::<String>()) - } - - /// Read a line of input securely. - /// - /// This is similar to `read_line` but will not echo the output. This - /// also switches the terminal into a different mode where not all - /// characters might be accepted. - pub fn read_secure_line(&self) -> io::Result<String> { - if !self.is_tty { - return Ok("".into()); - } - match read_secure() { - Ok(rv) => { - self.write_line("")?; - Ok(rv) - } - Err(err) => Err(err), - } - } - - /// Flush internal buffers. - /// - /// This forces the contents of the internal buffer to be written to - /// the terminal. This is unnecessary for unbuffered terminals which - /// will automatically flush. - pub fn flush(&self) -> io::Result<()> { - if let Some(ref buffer) = self.inner.buffer { - let mut buffer = buffer.lock().unwrap(); - if !buffer.is_empty() { - self.write_through(&buffer[..])?; - buffer.clear(); - } - } - Ok(()) - } - - /// Check if the terminal is indeed a terminal. - #[inline] - pub fn is_term(&self) -> bool { - self.is_tty - } - - /// Check for common terminal features. - #[inline] - pub fn features(&self) -> TermFeatures<'_> { - TermFeatures(self) - } - - /// Return the terminal size in rows and columns or gets sensible defaults. - #[inline] - pub fn size(&self) -> (u16, u16) { - self.size_checked().unwrap_or((24, DEFAULT_WIDTH)) - } - - /// Return the terminal size in rows and columns. - /// - /// If the size cannot be reliably determined `None` is returned. - #[inline] - pub fn size_checked(&self) -> Option<(u16, u16)> { - terminal_size(self) - } - - /// Move the cursor to row `x` and column `y`. Values are 0-based. - #[inline] - pub fn move_cursor_to(&self, x: usize, y: usize) -> io::Result<()> { - move_cursor_to(self, x, y) - } - - /// Move the cursor up by `n` lines, if possible. - /// - /// If there are less than `n` lines above the current cursor position, - /// the cursor is moved to the top line of the terminal (i.e., as far up as possible). - #[inline] - pub fn move_cursor_up(&self, n: usize) -> io::Result<()> { - move_cursor_up(self, n) - } - - /// Move the cursor down by `n` lines, if possible. - /// - /// If there are less than `n` lines below the current cursor position, - /// the cursor is moved to the bottom line of the terminal (i.e., as far down as possible). - #[inline] - pub fn move_cursor_down(&self, n: usize) -> io::Result<()> { - move_cursor_down(self, n) - } - - /// Move the cursor `n` characters to the left, if possible. - /// - /// If there are fewer than `n` characters to the left of the current cursor position, - /// the cursor is moved to the beginning of the line (i.e., as far to the left as possible). - #[inline] - pub fn move_cursor_left(&self, n: usize) -> io::Result<()> { - move_cursor_left(self, n) - } - - /// Move the cursor `n` characters to the right. - /// - /// If there are fewer than `n` characters to the right of the current cursor position, - /// the cursor is moved to the end of the current line (i.e., as far to the right as possible). - #[inline] - pub fn move_cursor_right(&self, n: usize) -> io::Result<()> { - move_cursor_right(self, n) - } - - /// Clear the current line. - /// - /// Position the cursor at the beginning of the current line. - #[inline] - pub fn clear_line(&self) -> io::Result<()> { - clear_line(self) - } - - /// Clear the last `n` lines before the current line. - /// - /// Position the cursor at the beginning of the first line that was cleared. - pub fn clear_last_lines(&self, n: usize) -> io::Result<()> { - self.move_cursor_up(n)?; - for _ in 0..n { - self.clear_line()?; - self.move_cursor_down(1)?; - } - self.move_cursor_up(n)?; - Ok(()) - } - - /// Clear the entire screen. - /// - /// Move the cursor to the upper left corner of the screen. - #[inline] - pub fn clear_screen(&self) -> io::Result<()> { - clear_screen(self) - } - - /// Clear everything from the current cursor position to the end of the screen. - /// The cursor stays in its position. - #[inline] - pub fn clear_to_end_of_screen(&self) -> io::Result<()> { - clear_to_end_of_screen(self) - } - - /// Clear the last `n` characters of the current line. - #[inline] - pub fn clear_chars(&self, n: usize) -> io::Result<()> { - clear_chars(self, n) - } - - /// Set the terminal title. - pub fn set_title<T: Display>(&self, title: T) { - if !self.is_tty { - return; - } - set_title(title); - } - - /// Make the cursor visible again. - #[inline] - pub fn show_cursor(&self) -> io::Result<()> { - show_cursor(self) - } - - /// Hide the cursor. - #[inline] - pub fn hide_cursor(&self) -> io::Result<()> { - hide_cursor(self) - } - - // helpers - - #[cfg(all(windows, feature = "windows-console-colors"))] - fn write_through(&self, bytes: &[u8]) -> io::Result<()> { - if self.is_msys_tty || !self.is_tty { - self.write_through_common(bytes) - } else { - match self.inner.target { - TermTarget::Stdout => console_colors(self, Console::stdout()?, bytes), - TermTarget::Stderr => console_colors(self, Console::stderr()?, bytes), - } - } - } - - #[cfg(not(all(windows, feature = "windows-console-colors")))] - fn write_through(&self, bytes: &[u8]) -> io::Result<()> { - self.write_through_common(bytes) - } - - pub(crate) fn write_through_common(&self, bytes: &[u8]) -> io::Result<()> { - match self.inner.target { - TermTarget::Stdout => { - io::stdout().write_all(bytes)?; - io::stdout().flush()?; - } - TermTarget::Stderr => { - io::stderr().write_all(bytes)?; - io::stderr().flush()?; - } - #[cfg(unix)] - TermTarget::ReadWritePair(ReadWritePair { ref write, .. }) => { - let mut write = write.lock().unwrap(); - write.write_all(bytes)?; - write.flush()?; - } - } - Ok(()) - } -} - -/// A fast way to check if the application has a user attended for stdout. -/// -/// This means that stdout is connected to a terminal instead of a -/// file or redirected by other means. This is a shortcut for -/// checking the `is_attended` feature on the stdout terminal. -#[inline] -pub fn user_attended() -> bool { - Term::stdout().features().is_attended() -} - -/// A fast way to check if the application has a user attended for stderr. -/// -/// This means that stderr is connected to a terminal instead of a -/// file or redirected by other means. This is a shortcut for -/// checking the `is_attended` feature on the stderr terminal. -#[inline] -pub fn user_attended_stderr() -> bool { - Term::stderr().features().is_attended() -} - -#[cfg(unix)] -impl AsRawFd for Term { - fn as_raw_fd(&self) -> RawFd { - match self.inner.target { - TermTarget::Stdout => libc::STDOUT_FILENO, - TermTarget::Stderr => libc::STDERR_FILENO, - TermTarget::ReadWritePair(ReadWritePair { ref write, .. }) => { - write.lock().unwrap().as_raw_fd() - } - } - } -} - -#[cfg(windows)] -impl AsRawHandle for Term { - fn as_raw_handle(&self) -> RawHandle { - use windows_sys::Win32::System::Console::{ - GetStdHandle, STD_ERROR_HANDLE, STD_OUTPUT_HANDLE, - }; - - unsafe { - GetStdHandle(match self.inner.target { - TermTarget::Stdout => STD_OUTPUT_HANDLE, - TermTarget::Stderr => STD_ERROR_HANDLE, - }) as RawHandle - } - } -} - -impl Write for Term { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - match self.inner.buffer { - Some(ref buffer) => buffer.lock().unwrap().write_all(buf), - None => self.write_through(buf), - }?; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Term::flush(self) - } -} - -impl<'a> Write for &'a Term { - fn write(&mut self, buf: &[u8]) -> io::Result<usize> { - match self.inner.buffer { - Some(ref buffer) => buffer.lock().unwrap().write_all(buf), - None => self.write_through(buf), - }?; - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - Term::flush(self) - } -} - -impl Read for Term { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - io::stdin().read(buf) - } -} - -impl<'a> Read for &'a Term { - fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { - io::stdin().read(buf) - } -} - -#[cfg(unix)] -pub use crate::unix_term::*; -#[cfg(target_arch = "wasm32")] -pub use crate::wasm_term::*; -#[cfg(windows)] -pub use crate::windows_term::*; diff --git a/vendor/console/src/unix_term.rs b/vendor/console/src/unix_term.rs deleted file mode 100644 index 8e1e592..0000000 --- a/vendor/console/src/unix_term.rs +++ /dev/null @@ -1,362 +0,0 @@ -use std::env; -use std::fmt::Display; -use std::fs; -use std::io; -use std::io::{BufRead, BufReader}; -use std::mem; -use std::os::unix::io::AsRawFd; -use std::ptr; -use std::str; - -use crate::kb::Key; -use crate::term::Term; - -pub use crate::common_term::*; - -pub const DEFAULT_WIDTH: u16 = 80; - -#[inline] -pub fn is_a_terminal(out: &Term) -> bool { - unsafe { libc::isatty(out.as_raw_fd()) != 0 } -} - -pub fn is_a_color_terminal(out: &Term) -> bool { - if !is_a_terminal(out) { - return false; - } - - if env::var("NO_COLOR").is_ok() { - return false; - } - - match env::var("TERM") { - Ok(term) => term != "dumb", - Err(_) => false, - } -} - -pub fn c_result<F: FnOnce() -> libc::c_int>(f: F) -> io::Result<()> { - let res = f(); - if res != 0 { - Err(io::Error::last_os_error()) - } else { - Ok(()) - } -} - -pub fn terminal_size(out: &Term) -> Option<(u16, u16)> { - unsafe { - if libc::isatty(libc::STDOUT_FILENO) != 1 { - return None; - } - - let mut winsize: libc::winsize = std::mem::zeroed(); - - // FIXME: ".into()" used as a temporary fix for a libc bug - // https://github.com/rust-lang/libc/pull/704 - #[allow(clippy::useless_conversion)] - libc::ioctl(out.as_raw_fd(), libc::TIOCGWINSZ.into(), &mut winsize); - if winsize.ws_row > 0 && winsize.ws_col > 0 { - Some((winsize.ws_row as u16, winsize.ws_col as u16)) - } else { - None - } - } -} - -pub fn read_secure() -> io::Result<String> { - let f_tty; - let fd = unsafe { - if libc::isatty(libc::STDIN_FILENO) == 1 { - f_tty = None; - libc::STDIN_FILENO - } else { - let f = fs::OpenOptions::new() - .read(true) - .write(true) - .open("/dev/tty")?; - let fd = f.as_raw_fd(); - f_tty = Some(BufReader::new(f)); - fd - } - }; - - let mut termios = core::mem::MaybeUninit::uninit(); - c_result(|| unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) })?; - let mut termios = unsafe { termios.assume_init() }; - let original = termios; - termios.c_lflag &= !libc::ECHO; - c_result(|| unsafe { libc::tcsetattr(fd, libc::TCSAFLUSH, &termios) })?; - let mut rv = String::new(); - - let read_rv = if let Some(mut f) = f_tty { - f.read_line(&mut rv) - } else { - io::stdin().read_line(&mut rv) - }; - - c_result(|| unsafe { libc::tcsetattr(fd, libc::TCSAFLUSH, &original) })?; - - read_rv.map(|_| { - let len = rv.trim_end_matches(&['\r', '\n'][..]).len(); - rv.truncate(len); - rv - }) -} - -fn poll_fd(fd: i32, timeout: i32) -> io::Result<bool> { - let mut pollfd = libc::pollfd { - fd, - events: libc::POLLIN, - revents: 0, - }; - let ret = unsafe { libc::poll(&mut pollfd as *mut _, 1, timeout) }; - if ret < 0 { - Err(io::Error::last_os_error()) - } else { - Ok(pollfd.revents & libc::POLLIN != 0) - } -} - -#[cfg(target_os = "macos")] -fn select_fd(fd: i32, timeout: i32) -> io::Result<bool> { - unsafe { - let mut read_fd_set: libc::fd_set = mem::zeroed(); - - let mut timeout_val; - let timeout = if timeout < 0 { - ptr::null_mut() - } else { - timeout_val = libc::timeval { - tv_sec: (timeout / 1000) as _, - tv_usec: (timeout * 1000) as _, - }; - &mut timeout_val - }; - - libc::FD_ZERO(&mut read_fd_set); - libc::FD_SET(fd, &mut read_fd_set); - let ret = libc::select( - fd + 1, - &mut read_fd_set, - ptr::null_mut(), - ptr::null_mut(), - timeout, - ); - if ret < 0 { - Err(io::Error::last_os_error()) - } else { - Ok(libc::FD_ISSET(fd, &read_fd_set)) - } - } -} - -fn select_or_poll_term_fd(fd: i32, timeout: i32) -> io::Result<bool> { - // There is a bug on macos that ttys cannot be polled, only select() - // works. However given how problematic select is in general, we - // normally want to use poll there too. - #[cfg(target_os = "macos")] - { - if unsafe { libc::isatty(fd) == 1 } { - return select_fd(fd, timeout); - } - } - poll_fd(fd, timeout) -} - -fn read_single_char(fd: i32) -> io::Result<Option<char>> { - // timeout of zero means that it will not block - let is_ready = select_or_poll_term_fd(fd, 0)?; - - if is_ready { - // if there is something to be read, take 1 byte from it - let mut buf: [u8; 1] = [0]; - - read_bytes(fd, &mut buf, 1)?; - Ok(Some(buf[0] as char)) - } else { - //there is nothing to be read - Ok(None) - } -} - -// Similar to libc::read. Read count bytes into slice buf from descriptor fd. -// If successful, return the number of bytes read. -// Will return an error if nothing was read, i.e when called at end of file. -fn read_bytes(fd: i32, buf: &mut [u8], count: u8) -> io::Result<u8> { - let read = unsafe { libc::read(fd, buf.as_mut_ptr() as *mut _, count as usize) }; - if read < 0 { - Err(io::Error::last_os_error()) - } else if read == 0 { - Err(io::Error::new( - io::ErrorKind::UnexpectedEof, - "Reached end of file", - )) - } else if buf[0] == b'\x03' { - Err(io::Error::new( - io::ErrorKind::Interrupted, - "read interrupted", - )) - } else { - Ok(read as u8) - } -} - -fn read_single_key_impl(fd: i32) -> Result<Key, io::Error> { - loop { - match read_single_char(fd)? { - Some('\x1b') => { - // Escape was read, keep reading in case we find a familiar key - break if let Some(c1) = read_single_char(fd)? { - if c1 == '[' { - if let Some(c2) = read_single_char(fd)? { - match c2 { - 'A' => Ok(Key::ArrowUp), - 'B' => Ok(Key::ArrowDown), - 'C' => Ok(Key::ArrowRight), - 'D' => Ok(Key::ArrowLeft), - 'H' => Ok(Key::Home), - 'F' => Ok(Key::End), - 'Z' => Ok(Key::BackTab), - _ => { - let c3 = read_single_char(fd)?; - if let Some(c3) = c3 { - if c3 == '~' { - match c2 { - '1' => Ok(Key::Home), // tmux - '2' => Ok(Key::Insert), - '3' => Ok(Key::Del), - '4' => Ok(Key::End), // tmux - '5' => Ok(Key::PageUp), - '6' => Ok(Key::PageDown), - '7' => Ok(Key::Home), // xrvt - '8' => Ok(Key::End), // xrvt - _ => Ok(Key::UnknownEscSeq(vec![c1, c2, c3])), - } - } else { - Ok(Key::UnknownEscSeq(vec![c1, c2, c3])) - } - } else { - // \x1b[ and 1 more char - Ok(Key::UnknownEscSeq(vec![c1, c2])) - } - } - } - } else { - // \x1b[ and no more input - Ok(Key::UnknownEscSeq(vec![c1])) - } - } else { - // char after escape is not [ - Ok(Key::UnknownEscSeq(vec![c1])) - } - } else { - //nothing after escape - Ok(Key::Escape) - }; - } - Some(c) => { - let byte = c as u8; - let mut buf: [u8; 4] = [byte, 0, 0, 0]; - - break if byte & 224u8 == 192u8 { - // a two byte unicode character - read_bytes(fd, &mut buf[1..], 1)?; - Ok(key_from_utf8(&buf[..2])) - } else if byte & 240u8 == 224u8 { - // a three byte unicode character - read_bytes(fd, &mut buf[1..], 2)?; - Ok(key_from_utf8(&buf[..3])) - } else if byte & 248u8 == 240u8 { - // a four byte unicode character - read_bytes(fd, &mut buf[1..], 3)?; - Ok(key_from_utf8(&buf[..4])) - } else { - Ok(match c { - '\n' | '\r' => Key::Enter, - '\x7f' => Key::Backspace, - '\t' => Key::Tab, - '\x01' => Key::Home, // Control-A (home) - '\x05' => Key::End, // Control-E (end) - '\x08' => Key::Backspace, // Control-H (8) (Identical to '\b') - _ => Key::Char(c), - }) - }; - } - None => { - // there is no subsequent byte ready to be read, block and wait for input - // negative timeout means that it will block indefinitely - match select_or_poll_term_fd(fd, -1) { - Ok(_) => continue, - Err(_) => break Err(io::Error::last_os_error()), - } - } - } - } -} - -pub fn read_single_key() -> io::Result<Key> { - let tty_f; - let fd = unsafe { - if libc::isatty(libc::STDIN_FILENO) == 1 { - libc::STDIN_FILENO - } else { - tty_f = fs::OpenOptions::new() - .read(true) - .write(true) - .open("/dev/tty")?; - tty_f.as_raw_fd() - } - }; - let mut termios = core::mem::MaybeUninit::uninit(); - c_result(|| unsafe { libc::tcgetattr(fd, termios.as_mut_ptr()) })?; - let mut termios = unsafe { termios.assume_init() }; - let original = termios; - unsafe { libc::cfmakeraw(&mut termios) }; - termios.c_oflag = original.c_oflag; - c_result(|| unsafe { libc::tcsetattr(fd, libc::TCSADRAIN, &termios) })?; - let rv: io::Result<Key> = read_single_key_impl(fd); - c_result(|| unsafe { libc::tcsetattr(fd, libc::TCSADRAIN, &original) })?; - - // if the user hit ^C we want to signal SIGINT to outselves. - if let Err(ref err) = rv { - if err.kind() == io::ErrorKind::Interrupted { - unsafe { - libc::raise(libc::SIGINT); - } - } - } - - rv -} - -pub fn key_from_utf8(buf: &[u8]) -> Key { - if let Ok(s) = str::from_utf8(buf) { - if let Some(c) = s.chars().next() { - return Key::Char(c); - } - } - Key::Unknown -} - -#[cfg(not(target_os = "macos"))] -lazy_static::lazy_static! { - static ref IS_LANG_UTF8: bool = match std::env::var("LANG") { - Ok(lang) => lang.to_uppercase().ends_with("UTF-8"), - _ => false, - }; -} - -#[cfg(target_os = "macos")] -pub fn wants_emoji() -> bool { - true -} - -#[cfg(not(target_os = "macos"))] -pub fn wants_emoji() -> bool { - *IS_LANG_UTF8 -} - -pub fn set_title<T: Display>(title: T) { - print!("\x1b]0;{}\x07", title); -} diff --git a/vendor/console/src/utils.rs b/vendor/console/src/utils.rs deleted file mode 100644 index 9e6b942..0000000 --- a/vendor/console/src/utils.rs +++ /dev/null @@ -1,962 +0,0 @@ -use std::borrow::Cow; -use std::collections::BTreeSet; -use std::env; -use std::fmt; -use std::sync::atomic::{AtomicBool, Ordering}; - -use lazy_static::lazy_static; - -use crate::term::{wants_emoji, Term}; - -#[cfg(feature = "ansi-parsing")] -use crate::ansi::{strip_ansi_codes, AnsiCodeIterator}; - -#[cfg(not(feature = "ansi-parsing"))] -fn strip_ansi_codes(s: &str) -> &str { - s -} - -fn default_colors_enabled(out: &Term) -> bool { - (out.features().colors_supported() - && &env::var("CLICOLOR").unwrap_or_else(|_| "1".into()) != "0") - || &env::var("CLICOLOR_FORCE").unwrap_or_else(|_| "0".into()) != "0" -} - -lazy_static! { - static ref STDOUT_COLORS: AtomicBool = AtomicBool::new(default_colors_enabled(&Term::stdout())); - static ref STDERR_COLORS: AtomicBool = AtomicBool::new(default_colors_enabled(&Term::stderr())); -} - -/// Returns `true` if colors should be enabled for stdout. -/// -/// This honors the [clicolors spec](http://bixense.com/clicolors/). -/// -/// * `CLICOLOR != 0`: ANSI colors are supported and should be used when the program isn't piped. -/// * `CLICOLOR == 0`: Don't output ANSI color escape codes. -/// * `CLICOLOR_FORCE != 0`: ANSI colors should be enabled no matter what. -#[inline] -pub fn colors_enabled() -> bool { - STDOUT_COLORS.load(Ordering::Relaxed) -} - -/// Forces colorization on or off for stdout. -/// -/// This overrides the default for the current process and changes the return value of the -/// `colors_enabled` function. -#[inline] -pub fn set_colors_enabled(val: bool) { - STDOUT_COLORS.store(val, Ordering::Relaxed) -} - -/// Returns `true` if colors should be enabled for stderr. -/// -/// This honors the [clicolors spec](http://bixense.com/clicolors/). -/// -/// * `CLICOLOR != 0`: ANSI colors are supported and should be used when the program isn't piped. -/// * `CLICOLOR == 0`: Don't output ANSI color escape codes. -/// * `CLICOLOR_FORCE != 0`: ANSI colors should be enabled no matter what. -#[inline] -pub fn colors_enabled_stderr() -> bool { - STDERR_COLORS.load(Ordering::Relaxed) -} - -/// Forces colorization on or off for stderr. -/// -/// This overrides the default for the current process and changes the return value of the -/// `colors_enabled` function. -#[inline] -pub fn set_colors_enabled_stderr(val: bool) { - STDERR_COLORS.store(val, Ordering::Relaxed) -} - -/// Measure the width of a string in terminal characters. -pub fn measure_text_width(s: &str) -> usize { - str_width(&strip_ansi_codes(s)) -} - -/// A terminal color. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum Color { - Black, - Red, - Green, - Yellow, - Blue, - Magenta, - Cyan, - White, - Color256(u8), -} - -impl Color { - #[inline] - fn ansi_num(self) -> usize { - match self { - Color::Black => 0, - Color::Red => 1, - Color::Green => 2, - Color::Yellow => 3, - Color::Blue => 4, - Color::Magenta => 5, - Color::Cyan => 6, - Color::White => 7, - Color::Color256(x) => x as usize, - } - } - - #[inline] - fn is_color256(self) -> bool { - #[allow(clippy::match_like_matches_macro)] - match self { - Color::Color256(_) => true, - _ => false, - } - } -} - -/// A terminal style attribute. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd)] -pub enum Attribute { - Bold, - Dim, - Italic, - Underlined, - Blink, - BlinkFast, - Reverse, - Hidden, - StrikeThrough, -} - -impl Attribute { - #[inline] - fn ansi_num(self) -> usize { - match self { - Attribute::Bold => 1, - Attribute::Dim => 2, - Attribute::Italic => 3, - Attribute::Underlined => 4, - Attribute::Blink => 5, - Attribute::BlinkFast => 6, - Attribute::Reverse => 7, - Attribute::Hidden => 8, - Attribute::StrikeThrough => 9, - } - } -} - -/// Defines the alignment for padding operations. -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum Alignment { - Left, - Center, - Right, -} - -/// A stored style that can be applied. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct Style { - fg: Option<Color>, - bg: Option<Color>, - fg_bright: bool, - bg_bright: bool, - attrs: BTreeSet<Attribute>, - force: Option<bool>, - for_stderr: bool, -} - -impl Default for Style { - fn default() -> Style { - Style::new() - } -} - -impl Style { - /// Returns an empty default style. - pub fn new() -> Style { - Style { - fg: None, - bg: None, - fg_bright: false, - bg_bright: false, - attrs: BTreeSet::new(), - force: None, - for_stderr: false, - } - } - - /// Creates a style from a dotted string. - /// - /// Effectively the string is split at each dot and then the - /// terms in between are applied. For instance `red.on_blue` will - /// create a string that is red on blue background. `9.on_12` is - /// the same, but using 256 color numbers. Unknown terms are - /// ignored. - pub fn from_dotted_str(s: &str) -> Style { - let mut rv = Style::new(); - for part in s.split('.') { - rv = match part { - "black" => rv.black(), - "red" => rv.red(), - "green" => rv.green(), - "yellow" => rv.yellow(), - "blue" => rv.blue(), - "magenta" => rv.magenta(), - "cyan" => rv.cyan(), - "white" => rv.white(), - "bright" => rv.bright(), - "on_black" => rv.on_black(), - "on_red" => rv.on_red(), - "on_green" => rv.on_green(), - "on_yellow" => rv.on_yellow(), - "on_blue" => rv.on_blue(), - "on_magenta" => rv.on_magenta(), - "on_cyan" => rv.on_cyan(), - "on_white" => rv.on_white(), - "on_bright" => rv.on_bright(), - "bold" => rv.bold(), - "dim" => rv.dim(), - "underlined" => rv.underlined(), - "blink" => rv.blink(), - "blink_fast" => rv.blink_fast(), - "reverse" => rv.reverse(), - "hidden" => rv.hidden(), - "strikethrough" => rv.strikethrough(), - on_c if on_c.starts_with("on_") => { - if let Ok(n) = on_c[3..].parse::<u8>() { - rv.on_color256(n) - } else { - continue; - } - } - c => { - if let Ok(n) = c.parse::<u8>() { - rv.color256(n) - } else { - continue; - } - } - }; - } - rv - } - - /// Apply the style to something that can be displayed. - pub fn apply_to<D>(&self, val: D) -> StyledObject<D> { - StyledObject { - style: self.clone(), - val, - } - } - - /// Forces styling on or off. - /// - /// This overrides the automatic detection. - #[inline] - pub fn force_styling(mut self, value: bool) -> Style { - self.force = Some(value); - self - } - - /// Specifies that style is applying to something being written on stderr. - #[inline] - pub fn for_stderr(mut self) -> Style { - self.for_stderr = true; - self - } - - /// Specifies that style is applying to something being written on stdout. - /// - /// This is the default behaviour. - #[inline] - pub fn for_stdout(mut self) -> Style { - self.for_stderr = false; - self - } - - /// Sets a foreground color. - #[inline] - pub fn fg(mut self, color: Color) -> Style { - self.fg = Some(color); - self - } - - /// Sets a background color. - #[inline] - pub fn bg(mut self, color: Color) -> Style { - self.bg = Some(color); - self - } - - /// Adds a attr. - #[inline] - pub fn attr(mut self, attr: Attribute) -> Style { - self.attrs.insert(attr); - self - } - - #[inline] - pub fn black(self) -> Style { - self.fg(Color::Black) - } - #[inline] - pub fn red(self) -> Style { - self.fg(Color::Red) - } - #[inline] - pub fn green(self) -> Style { - self.fg(Color::Green) - } - #[inline] - pub fn yellow(self) -> Style { - self.fg(Color::Yellow) - } - #[inline] - pub fn blue(self) -> Style { - self.fg(Color::Blue) - } - #[inline] - pub fn magenta(self) -> Style { - self.fg(Color::Magenta) - } - #[inline] - pub fn cyan(self) -> Style { - self.fg(Color::Cyan) - } - #[inline] - pub fn white(self) -> Style { - self.fg(Color::White) - } - #[inline] - pub fn color256(self, color: u8) -> Style { - self.fg(Color::Color256(color)) - } - - #[inline] - pub fn bright(mut self) -> Style { - self.fg_bright = true; - self - } - - #[inline] - pub fn on_black(self) -> Style { - self.bg(Color::Black) - } - #[inline] - pub fn on_red(self) -> Style { - self.bg(Color::Red) - } - #[inline] - pub fn on_green(self) -> Style { - self.bg(Color::Green) - } - #[inline] - pub fn on_yellow(self) -> Style { - self.bg(Color::Yellow) - } - #[inline] - pub fn on_blue(self) -> Style { - self.bg(Color::Blue) - } - #[inline] - pub fn on_magenta(self) -> Style { - self.bg(Color::Magenta) - } - #[inline] - pub fn on_cyan(self) -> Style { - self.bg(Color::Cyan) - } - #[inline] - pub fn on_white(self) -> Style { - self.bg(Color::White) - } - #[inline] - pub fn on_color256(self, color: u8) -> Style { - self.bg(Color::Color256(color)) - } - - #[inline] - pub fn on_bright(mut self) -> Style { - self.bg_bright = true; - self - } - - #[inline] - pub fn bold(self) -> Style { - self.attr(Attribute::Bold) - } - #[inline] - pub fn dim(self) -> Style { - self.attr(Attribute::Dim) - } - #[inline] - pub fn italic(self) -> Style { - self.attr(Attribute::Italic) - } - #[inline] - pub fn underlined(self) -> Style { - self.attr(Attribute::Underlined) - } - #[inline] - pub fn blink(self) -> Style { - self.attr(Attribute::Blink) - } - #[inline] - pub fn blink_fast(self) -> Style { - self.attr(Attribute::BlinkFast) - } - #[inline] - pub fn reverse(self) -> Style { - self.attr(Attribute::Reverse) - } - #[inline] - pub fn hidden(self) -> Style { - self.attr(Attribute::Hidden) - } - #[inline] - pub fn strikethrough(self) -> Style { - self.attr(Attribute::StrikeThrough) - } -} - -/// Wraps an object for formatting for styling. -/// -/// Example: -/// -/// ```rust,no_run -/// # use console::style; -/// format!("Hello {}", style("World").cyan()); -/// ``` -/// -/// This is a shortcut for making a new style and applying it -/// to a value: -/// -/// ```rust,no_run -/// # use console::Style; -/// format!("Hello {}", Style::new().cyan().apply_to("World")); -/// ``` -pub fn style<D>(val: D) -> StyledObject<D> { - Style::new().apply_to(val) -} - -/// A formatting wrapper that can be styled for a terminal. -#[derive(Clone)] -pub struct StyledObject<D> { - style: Style, - val: D, -} - -impl<D> StyledObject<D> { - /// Forces styling on or off. - /// - /// This overrides the automatic detection. - #[inline] - pub fn force_styling(mut self, value: bool) -> StyledObject<D> { - self.style = self.style.force_styling(value); - self - } - - /// Specifies that style is applying to something being written on stderr - #[inline] - pub fn for_stderr(mut self) -> StyledObject<D> { - self.style = self.style.for_stderr(); - self - } - - /// Specifies that style is applying to something being written on stdout - /// - /// This is the default - #[inline] - pub fn for_stdout(mut self) -> StyledObject<D> { - self.style = self.style.for_stdout(); - self - } - - /// Sets a foreground color. - #[inline] - pub fn fg(mut self, color: Color) -> StyledObject<D> { - self.style = self.style.fg(color); - self - } - - /// Sets a background color. - #[inline] - pub fn bg(mut self, color: Color) -> StyledObject<D> { - self.style = self.style.bg(color); - self - } - - /// Adds a attr. - #[inline] - pub fn attr(mut self, attr: Attribute) -> StyledObject<D> { - self.style = self.style.attr(attr); - self - } - - #[inline] - pub fn black(self) -> StyledObject<D> { - self.fg(Color::Black) - } - #[inline] - pub fn red(self) -> StyledObject<D> { - self.fg(Color::Red) - } - #[inline] - pub fn green(self) -> StyledObject<D> { - self.fg(Color::Green) - } - #[inline] - pub fn yellow(self) -> StyledObject<D> { - self.fg(Color::Yellow) - } - #[inline] - pub fn blue(self) -> StyledObject<D> { - self.fg(Color::Blue) - } - #[inline] - pub fn magenta(self) -> StyledObject<D> { - self.fg(Color::Magenta) - } - #[inline] - pub fn cyan(self) -> StyledObject<D> { - self.fg(Color::Cyan) - } - #[inline] - pub fn white(self) -> StyledObject<D> { - self.fg(Color::White) - } - #[inline] - pub fn color256(self, color: u8) -> StyledObject<D> { - self.fg(Color::Color256(color)) - } - - #[inline] - pub fn bright(mut self) -> StyledObject<D> { - self.style = self.style.bright(); - self - } - - #[inline] - pub fn on_black(self) -> StyledObject<D> { - self.bg(Color::Black) - } - #[inline] - pub fn on_red(self) -> StyledObject<D> { - self.bg(Color::Red) - } - #[inline] - pub fn on_green(self) -> StyledObject<D> { - self.bg(Color::Green) - } - #[inline] - pub fn on_yellow(self) -> StyledObject<D> { - self.bg(Color::Yellow) - } - #[inline] - pub fn on_blue(self) -> StyledObject<D> { - self.bg(Color::Blue) - } - #[inline] - pub fn on_magenta(self) -> StyledObject<D> { - self.bg(Color::Magenta) - } - #[inline] - pub fn on_cyan(self) -> StyledObject<D> { - self.bg(Color::Cyan) - } - #[inline] - pub fn on_white(self) -> StyledObject<D> { - self.bg(Color::White) - } - #[inline] - pub fn on_color256(self, color: u8) -> StyledObject<D> { - self.bg(Color::Color256(color)) - } - - #[inline] - pub fn on_bright(mut self) -> StyledObject<D> { - self.style = self.style.on_bright(); - self - } - - #[inline] - pub fn bold(self) -> StyledObject<D> { - self.attr(Attribute::Bold) - } - #[inline] - pub fn dim(self) -> StyledObject<D> { - self.attr(Attribute::Dim) - } - #[inline] - pub fn italic(self) -> StyledObject<D> { - self.attr(Attribute::Italic) - } - #[inline] - pub fn underlined(self) -> StyledObject<D> { - self.attr(Attribute::Underlined) - } - #[inline] - pub fn blink(self) -> StyledObject<D> { - self.attr(Attribute::Blink) - } - #[inline] - pub fn blink_fast(self) -> StyledObject<D> { - self.attr(Attribute::BlinkFast) - } - #[inline] - pub fn reverse(self) -> StyledObject<D> { - self.attr(Attribute::Reverse) - } - #[inline] - pub fn hidden(self) -> StyledObject<D> { - self.attr(Attribute::Hidden) - } - #[inline] - pub fn strikethrough(self) -> StyledObject<D> { - self.attr(Attribute::StrikeThrough) - } -} - -macro_rules! impl_fmt { - ($name:ident) => { - impl<D: fmt::$name> fmt::$name for StyledObject<D> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let mut reset = false; - if self - .style - .force - .unwrap_or_else(|| match self.style.for_stderr { - true => colors_enabled_stderr(), - false => colors_enabled(), - }) - { - if let Some(fg) = self.style.fg { - if fg.is_color256() { - write!(f, "\x1b[38;5;{}m", fg.ansi_num())?; - } else if self.style.fg_bright { - write!(f, "\x1b[38;5;{}m", fg.ansi_num() + 8)?; - } else { - write!(f, "\x1b[{}m", fg.ansi_num() + 30)?; - } - reset = true; - } - if let Some(bg) = self.style.bg { - if bg.is_color256() { - write!(f, "\x1b[48;5;{}m", bg.ansi_num())?; - } else if self.style.bg_bright { - write!(f, "\x1b[48;5;{}m", bg.ansi_num() + 8)?; - } else { - write!(f, "\x1b[{}m", bg.ansi_num() + 40)?; - } - reset = true; - } - for attr in &self.style.attrs { - write!(f, "\x1b[{}m", attr.ansi_num())?; - reset = true; - } - } - fmt::$name::fmt(&self.val, f)?; - if reset { - write!(f, "\x1b[0m")?; - } - Ok(()) - } - } - }; -} - -impl_fmt!(Binary); -impl_fmt!(Debug); -impl_fmt!(Display); -impl_fmt!(LowerExp); -impl_fmt!(LowerHex); -impl_fmt!(Octal); -impl_fmt!(Pointer); -impl_fmt!(UpperExp); -impl_fmt!(UpperHex); - -/// "Intelligent" emoji formatter. -/// -/// This struct intelligently wraps an emoji so that it is rendered -/// only on systems that want emojis and renders a fallback on others. -/// -/// Example: -/// -/// ```rust -/// use console::Emoji; -/// println!("[3/4] {}Downloading ...", Emoji("🚚 ", "")); -/// println!("[4/4] {} Done!", Emoji("✨", ":-)")); -/// ``` -#[derive(Copy, Clone)] -pub struct Emoji<'a, 'b>(pub &'a str, pub &'b str); - -impl<'a, 'b> Emoji<'a, 'b> { - pub fn new(emoji: &'a str, fallback: &'b str) -> Emoji<'a, 'b> { - Emoji(emoji, fallback) - } -} - -impl<'a, 'b> fmt::Display for Emoji<'a, 'b> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if wants_emoji() { - write!(f, "{}", self.0) - } else { - write!(f, "{}", self.1) - } - } -} - -fn str_width(s: &str) -> usize { - #[cfg(feature = "unicode-width")] - { - use unicode_width::UnicodeWidthStr; - s.width() - } - #[cfg(not(feature = "unicode-width"))] - { - s.chars().count() - } -} - -#[cfg(feature = "ansi-parsing")] -fn char_width(c: char) -> usize { - #[cfg(feature = "unicode-width")] - { - use unicode_width::UnicodeWidthChar; - c.width().unwrap_or(0) - } - #[cfg(not(feature = "unicode-width"))] - { - let _c = c; - 1 - } -} - -/// Truncates a string to a certain number of characters. -/// -/// This ensures that escape codes are not screwed up in the process. -/// If the maximum length is hit the string will be truncated but -/// escapes code will still be honored. If truncation takes place -/// the tail string will be appended. -pub fn truncate_str<'a>(s: &'a str, width: usize, tail: &str) -> Cow<'a, str> { - #[cfg(feature = "ansi-parsing")] - { - use std::cmp::Ordering; - let mut iter = AnsiCodeIterator::new(s); - let mut length = 0; - let mut rv = None; - - while let Some(item) = iter.next() { - match item { - (s, false) => { - if rv.is_none() { - if str_width(s) + length > width - str_width(tail) { - let ts = iter.current_slice(); - - let mut s_byte = 0; - let mut s_width = 0; - let rest_width = width - str_width(tail) - length; - for c in s.chars() { - s_byte += c.len_utf8(); - s_width += char_width(c); - match s_width.cmp(&rest_width) { - Ordering::Equal => break, - Ordering::Greater => { - s_byte -= c.len_utf8(); - break; - } - Ordering::Less => continue, - } - } - - let idx = ts.len() - s.len() + s_byte; - let mut buf = ts[..idx].to_string(); - buf.push_str(tail); - rv = Some(buf); - } - length += str_width(s); - } - } - (s, true) => { - if rv.is_some() { - rv.as_mut().unwrap().push_str(s); - } - } - } - } - - if let Some(buf) = rv { - Cow::Owned(buf) - } else { - Cow::Borrowed(s) - } - } - - #[cfg(not(feature = "ansi-parsing"))] - { - if s.len() <= width - tail.len() { - Cow::Borrowed(s) - } else { - Cow::Owned(format!( - "{}{}", - s.get(..width - tail.len()).unwrap_or_default(), - tail - )) - } - } -} - -/// Pads a string to fill a certain number of characters. -/// -/// This will honor ansi codes correctly and allows you to align a string -/// on the left, right or centered. Additionally truncation can be enabled -/// by setting `truncate` to a string that should be used as a truncation -/// marker. -pub fn pad_str<'a>( - s: &'a str, - width: usize, - align: Alignment, - truncate: Option<&str>, -) -> Cow<'a, str> { - pad_str_with(s, width, align, truncate, ' ') -} -/// Pads a string with specific padding to fill a certain number of characters. -/// -/// This will honor ansi codes correctly and allows you to align a string -/// on the left, right or centered. Additionally truncation can be enabled -/// by setting `truncate` to a string that should be used as a truncation -/// marker. -pub fn pad_str_with<'a>( - s: &'a str, - width: usize, - align: Alignment, - truncate: Option<&str>, - pad: char, -) -> Cow<'a, str> { - let cols = measure_text_width(s); - - if cols >= width { - return match truncate { - None => Cow::Borrowed(s), - Some(tail) => truncate_str(s, width, tail), - }; - } - - let diff = width - cols; - - let (left_pad, right_pad) = match align { - Alignment::Left => (0, diff), - Alignment::Right => (diff, 0), - Alignment::Center => (diff / 2, diff - diff / 2), - }; - - let mut rv = String::new(); - for _ in 0..left_pad { - rv.push(pad); - } - rv.push_str(s); - for _ in 0..right_pad { - rv.push(pad); - } - Cow::Owned(rv) -} - -#[test] -fn test_text_width() { - let s = style("foo") - .red() - .on_black() - .bold() - .force_styling(true) - .to_string(); - assert_eq!( - measure_text_width(&s), - if cfg!(feature = "ansi-parsing") { - 3 - } else if cfg!(feature = "unicode-width") { - 17 - } else { - 21 - } - ); -} - -#[test] -#[cfg(all(feature = "unicode-width", feature = "ansi-parsing"))] -fn test_truncate_str() { - let s = format!("foo {}", style("bar").red().force_styling(true)); - assert_eq!( - &truncate_str(&s, 5, ""), - &format!("foo {}", style("b").red().force_styling(true)) - ); - let s = format!("foo {}", style("bar").red().force_styling(true)); - assert_eq!( - &truncate_str(&s, 5, "!"), - &format!("foo {}", style("!").red().force_styling(true)) - ); - let s = format!("foo {} baz", style("bar").red().force_styling(true)); - assert_eq!( - &truncate_str(&s, 10, "..."), - &format!("foo {}...", style("bar").red().force_styling(true)) - ); - let s = format!("foo {}", style("バー").red().force_styling(true)); - assert_eq!( - &truncate_str(&s, 5, ""), - &format!("foo {}", style("").red().force_styling(true)) - ); - let s = format!("foo {}", style("バー").red().force_styling(true)); - assert_eq!( - &truncate_str(&s, 6, ""), - &format!("foo {}", style("バ").red().force_styling(true)) - ); -} - -#[test] -fn test_truncate_str_no_ansi() { - assert_eq!(&truncate_str("foo bar", 5, ""), "foo b"); - assert_eq!(&truncate_str("foo bar", 5, "!"), "foo !"); - assert_eq!(&truncate_str("foo bar baz", 10, "..."), "foo bar..."); -} - -#[test] -fn test_pad_str() { - assert_eq!(pad_str("foo", 7, Alignment::Center, None), " foo "); - assert_eq!(pad_str("foo", 7, Alignment::Left, None), "foo "); - assert_eq!(pad_str("foo", 7, Alignment::Right, None), " foo"); - assert_eq!(pad_str("foo", 3, Alignment::Left, None), "foo"); - assert_eq!(pad_str("foobar", 3, Alignment::Left, None), "foobar"); - assert_eq!(pad_str("foobar", 3, Alignment::Left, Some("")), "foo"); - assert_eq!( - pad_str("foobarbaz", 6, Alignment::Left, Some("...")), - "foo..." - ); -} - -#[test] -fn test_pad_str_with() { - assert_eq!( - pad_str_with("foo", 7, Alignment::Center, None, '#'), - "##foo##" - ); - assert_eq!( - pad_str_with("foo", 7, Alignment::Left, None, '#'), - "foo####" - ); - assert_eq!( - pad_str_with("foo", 7, Alignment::Right, None, '#'), - "####foo" - ); - assert_eq!(pad_str_with("foo", 3, Alignment::Left, None, '#'), "foo"); - assert_eq!( - pad_str_with("foobar", 3, Alignment::Left, None, '#'), - "foobar" - ); - assert_eq!( - pad_str_with("foobar", 3, Alignment::Left, Some(""), '#'), - "foo" - ); - assert_eq!( - pad_str_with("foobarbaz", 6, Alignment::Left, Some("..."), '#'), - "foo..." - ); -} diff --git a/vendor/console/src/wasm_term.rs b/vendor/console/src/wasm_term.rs deleted file mode 100644 index 764bc34..0000000 --- a/vendor/console/src/wasm_term.rs +++ /dev/null @@ -1,54 +0,0 @@ -use std::fmt::Display; -use std::io; - -use crate::kb::Key; -use crate::term::Term; - -pub use crate::common_term::*; - -pub const DEFAULT_WIDTH: u16 = 80; - -#[inline] -pub fn is_a_terminal(_out: &Term) -> bool { - #[cfg(target = "wasm32-wasi")] - { - unsafe { libc::isatty(out.as_raw_fd()) != 0 } - } - #[cfg(not(target = "wasm32-wasi"))] - { - false - } -} - -#[inline] -pub fn is_a_color_terminal(_out: &Term) -> bool { - // We currently never report color terminals. For discussion see - // the issue in the WASI repo: https://github.com/WebAssembly/WASI/issues/162 - false -} - -#[inline] -pub fn terminal_size(_out: &Term) -> Option<(u16, u16)> { - None -} - -pub fn read_secure() -> io::Result<String> { - Err(io::Error::new( - io::ErrorKind::Other, - "unsupported operation", - )) -} - -pub fn read_single_key() -> io::Result<Key> { - Err(io::Error::new( - io::ErrorKind::Other, - "unsupported operation", - )) -} - -#[inline] -pub fn wants_emoji() -> bool { - false -} - -pub fn set_title<T: Display>(_title: T) {} diff --git a/vendor/console/src/windows_term/colors.rs b/vendor/console/src/windows_term/colors.rs deleted file mode 100644 index dc8209d..0000000 --- a/vendor/console/src/windows_term/colors.rs +++ /dev/null @@ -1,451 +0,0 @@ -use std::io; -use std::mem; -use std::os::windows::io::AsRawHandle; -use std::str::Bytes; - -use windows_sys::Win32::Foundation::HANDLE; -use windows_sys::Win32::System::Console::{ - GetConsoleScreenBufferInfo, SetConsoleTextAttribute, CONSOLE_SCREEN_BUFFER_INFO, - FOREGROUND_BLUE as FG_BLUE, FOREGROUND_GREEN as FG_GREEN, FOREGROUND_INTENSITY as FG_INTENSITY, - FOREGROUND_RED as FG_RED, -}; - -use crate::Term; - -type WORD = u16; - -const FG_CYAN: WORD = FG_BLUE | FG_GREEN; -const FG_MAGENTA: WORD = FG_BLUE | FG_RED; -const FG_YELLOW: WORD = FG_GREEN | FG_RED; -const FG_WHITE: WORD = FG_BLUE | FG_GREEN | FG_RED; - -/// Query the given handle for information about the console's screen buffer. -/// -/// The given handle should represent a console. Otherwise, an error is -/// returned. -/// -/// This corresponds to calling [`GetConsoleScreenBufferInfo`]. -/// -/// [`GetConsoleScreenBufferInfo`]: https://docs.microsoft.com/en-us/windows/console/getconsolescreenbufferinfo -pub fn screen_buffer_info(h: HANDLE) -> io::Result<ScreenBufferInfo> { - unsafe { - let mut info: CONSOLE_SCREEN_BUFFER_INFO = mem::zeroed(); - let rc = GetConsoleScreenBufferInfo(h, &mut info); - if rc == 0 { - return Err(io::Error::last_os_error()); - } - Ok(ScreenBufferInfo(info)) - } -} - -/// Set the text attributes of the console represented by the given handle. -/// -/// This corresponds to calling [`SetConsoleTextAttribute`]. -/// -/// [`SetConsoleTextAttribute`]: https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute -pub fn set_text_attributes(h: HANDLE, attributes: u16) -> io::Result<()> { - if unsafe { SetConsoleTextAttribute(h, attributes) } == 0 { - Err(io::Error::last_os_error()) - } else { - Ok(()) - } -} - -/// Represents console screen buffer information such as size, cursor position -/// and styling attributes. -/// -/// This wraps a [`CONSOLE_SCREEN_BUFFER_INFO`]. -/// -/// [`CONSOLE_SCREEN_BUFFER_INFO`]: https://docs.microsoft.com/en-us/windows/console/console-screen-buffer-info-str -#[derive(Clone)] -pub struct ScreenBufferInfo(CONSOLE_SCREEN_BUFFER_INFO); - -impl ScreenBufferInfo { - /// Returns the character attributes associated with this console. - /// - /// This corresponds to `wAttributes`. - /// - /// See [`char info`] for more details. - /// - /// [`char info`]: https://docs.microsoft.com/en-us/windows/console/char-info-str - pub fn attributes(&self) -> u16 { - self.0.wAttributes - } -} - -/// A Windows console. -/// -/// This represents a very limited set of functionality available to a Windows -/// console. In particular, it can only change text attributes such as color -/// and intensity. This may grow over time. If you need more routines, please -/// file an issue and/or PR. -/// -/// There is no way to "write" to this console. Simply write to -/// stdout or stderr instead, while interleaving instructions to the console -/// to change text attributes. -/// -/// A common pitfall when using a console is to forget to flush writes to -/// stdout before setting new text attributes. -#[derive(Debug)] -pub struct Console { - kind: HandleKind, - start_attr: TextAttributes, - cur_attr: TextAttributes, -} - -#[derive(Clone, Copy, Debug)] -enum HandleKind { - Stdout, - Stderr, -} - -impl HandleKind { - fn handle(&self) -> HANDLE { - match *self { - HandleKind::Stdout => io::stdout().as_raw_handle() as HANDLE, - HandleKind::Stderr => io::stderr().as_raw_handle() as HANDLE, - } - } -} - -impl Console { - /// Get a console for a standard I/O stream. - fn create_for_stream(kind: HandleKind) -> io::Result<Console> { - let h = kind.handle(); - let info = screen_buffer_info(h)?; - let attr = TextAttributes::from_word(info.attributes()); - Ok(Console { - kind: kind, - start_attr: attr, - cur_attr: attr, - }) - } - - /// Create a new Console to stdout. - /// - /// If there was a problem creating the console, then an error is returned. - pub fn stdout() -> io::Result<Console> { - Self::create_for_stream(HandleKind::Stdout) - } - - /// Create a new Console to stderr. - /// - /// If there was a problem creating the console, then an error is returned. - pub fn stderr() -> io::Result<Console> { - Self::create_for_stream(HandleKind::Stderr) - } - - /// Applies the current text attributes. - fn set(&mut self) -> io::Result<()> { - set_text_attributes(self.kind.handle(), self.cur_attr.to_word()) - } - - /// Apply the given intensity and color attributes to the console - /// foreground. - /// - /// If there was a problem setting attributes on the console, then an error - /// is returned. - pub fn fg(&mut self, intense: Intense, color: Color) -> io::Result<()> { - self.cur_attr.fg_color = color; - self.cur_attr.fg_intense = intense; - self.set() - } - - /// Apply the given intensity and color attributes to the console - /// background. - /// - /// If there was a problem setting attributes on the console, then an error - /// is returned. - pub fn bg(&mut self, intense: Intense, color: Color) -> io::Result<()> { - self.cur_attr.bg_color = color; - self.cur_attr.bg_intense = intense; - self.set() - } - - /// Reset the console text attributes to their original settings. - /// - /// The original settings correspond to the text attributes on the console - /// when this `Console` value was created. - /// - /// If there was a problem setting attributes on the console, then an error - /// is returned. - pub fn reset(&mut self) -> io::Result<()> { - self.cur_attr = self.start_attr; - self.set() - } -} - -/// A representation of text attributes for the Windows console. -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -struct TextAttributes { - fg_color: Color, - fg_intense: Intense, - bg_color: Color, - bg_intense: Intense, -} - -impl TextAttributes { - fn to_word(&self) -> WORD { - let mut w = 0; - w |= self.fg_color.to_fg(); - w |= self.fg_intense.to_fg(); - w |= self.bg_color.to_bg(); - w |= self.bg_intense.to_bg(); - w - } - - fn from_word(word: WORD) -> TextAttributes { - TextAttributes { - fg_color: Color::from_fg(word), - fg_intense: Intense::from_fg(word), - bg_color: Color::from_bg(word), - bg_intense: Intense::from_bg(word), - } - } -} - -/// Whether to use intense colors or not. -#[allow(missing_docs)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Intense { - Yes, - No, -} - -impl Intense { - fn to_bg(&self) -> WORD { - self.to_fg() << 4 - } - - fn from_bg(word: WORD) -> Intense { - Intense::from_fg(word >> 4) - } - - fn to_fg(&self) -> WORD { - match *self { - Intense::No => 0, - Intense::Yes => FG_INTENSITY, - } - } - - fn from_fg(word: WORD) -> Intense { - if word & FG_INTENSITY > 0 { - Intense::Yes - } else { - Intense::No - } - } -} - -/// The set of available colors for use with a Windows console. -#[allow(missing_docs)] -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -pub enum Color { - Black, - Blue, - Green, - Red, - Cyan, - Magenta, - Yellow, - White, -} - -impl Color { - fn to_bg(&self) -> WORD { - self.to_fg() << 4 - } - - fn from_bg(word: WORD) -> Color { - Color::from_fg(word >> 4) - } - - fn to_fg(&self) -> WORD { - match *self { - Color::Black => 0, - Color::Blue => FG_BLUE, - Color::Green => FG_GREEN, - Color::Red => FG_RED, - Color::Cyan => FG_CYAN, - Color::Magenta => FG_MAGENTA, - Color::Yellow => FG_YELLOW, - Color::White => FG_WHITE, - } - } - - fn from_fg(word: WORD) -> Color { - match word & 0b111 { - FG_BLUE => Color::Blue, - FG_GREEN => Color::Green, - FG_RED => Color::Red, - FG_CYAN => Color::Cyan, - FG_MAGENTA => Color::Magenta, - FG_YELLOW => Color::Yellow, - FG_WHITE => Color::White, - _ => Color::Black, - } - } -} - -pub fn console_colors(out: &Term, mut con: Console, bytes: &[u8]) -> io::Result<()> { - use crate::ansi::AnsiCodeIterator; - use std::str::from_utf8; - - let s = from_utf8(bytes).expect("data to be printed is not an ansi string"); - let mut iter = AnsiCodeIterator::new(s); - - while !iter.rest_slice().is_empty() { - if let Some((part, is_esc)) = iter.next() { - if !is_esc { - out.write_through_common(part.as_bytes())?; - } else if part == "\x1b[0m" { - con.reset()?; - } else if let Some((intense, color, fg_bg)) = driver(parse_color, part) { - match fg_bg { - FgBg::Foreground => con.fg(intense, color), - FgBg::Background => con.bg(intense, color), - }?; - } else if driver(parse_attr, part).is_none() { - out.write_through_common(part.as_bytes())?; - } - } - } - - Ok(()) -} - -#[derive(Debug, PartialEq, Eq)] -enum FgBg { - Foreground, - Background, -} - -impl FgBg { - fn new(byte: u8) -> Option<Self> { - match byte { - b'3' => Some(Self::Foreground), - b'4' => Some(Self::Background), - _ => None, - } - } -} - -fn driver<Out>(parse: fn(Bytes<'_>) -> Option<Out>, part: &str) -> Option<Out> { - let mut bytes = part.bytes(); - - loop { - while bytes.next()? != b'\x1b' {} - - if let ret @ Some(_) = (parse)(bytes.clone()) { - return ret; - } - } -} - -// `driver(parse_color, s)` parses the equivalent of the regex -// \x1b\[(3|4)8;5;(8|9|1[0-5])m -// for intense or -// \x1b\[(3|4)([0-7])m -// for normal -fn parse_color(mut bytes: Bytes<'_>) -> Option<(Intense, Color, FgBg)> { - parse_prefix(&mut bytes)?; - - let fg_bg = FgBg::new(bytes.next()?)?; - let (intense, color) = match bytes.next()? { - b @ b'0'..=b'7' => (Intense::No, normal_color_ansi_from_byte(b)?), - b'8' => { - if &[bytes.next()?, bytes.next()?, bytes.next()?] != b";5;" { - return None; - } - (Intense::Yes, parse_intense_color_ansi(&mut bytes)?) - } - _ => return None, - }; - - parse_suffix(&mut bytes)?; - Some((intense, color, fg_bg)) -} - -// `driver(parse_attr, s)` parses the equivalent of the regex -// \x1b\[([1-8])m -fn parse_attr(mut bytes: Bytes<'_>) -> Option<u8> { - parse_prefix(&mut bytes)?; - let attr = match bytes.next()? { - attr @ b'1'..=b'8' => attr, - _ => return None, - }; - parse_suffix(&mut bytes)?; - Some(attr) -} - -fn parse_prefix(bytes: &mut Bytes<'_>) -> Option<()> { - if bytes.next()? == b'[' { - Some(()) - } else { - None - } -} - -fn parse_intense_color_ansi(bytes: &mut Bytes<'_>) -> Option<Color> { - let color = match bytes.next()? { - b'8' => Color::Black, - b'9' => Color::Red, - b'1' => match bytes.next()? { - b'0' => Color::Green, - b'1' => Color::Yellow, - b'2' => Color::Blue, - b'3' => Color::Magenta, - b'4' => Color::Cyan, - b'5' => Color::White, - _ => return None, - }, - _ => return None, - }; - Some(color) -} - -fn normal_color_ansi_from_byte(b: u8) -> Option<Color> { - let color = match b { - b'0' => Color::Black, - b'1' => Color::Red, - b'2' => Color::Green, - b'3' => Color::Yellow, - b'4' => Color::Blue, - b'5' => Color::Magenta, - b'6' => Color::Cyan, - b'7' => Color::White, - _ => return None, - }; - Some(color) -} - -fn parse_suffix(bytes: &mut Bytes<'_>) -> Option<()> { - if bytes.next()? == b'm' { - Some(()) - } else { - None - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn color_parsing() { - let intense_color = "leading bytes \x1b[38;5;10m trailing bytes"; - let parsed = driver(parse_color, intense_color).unwrap(); - assert_eq!(parsed, (Intense::Yes, Color::Green, FgBg::Foreground)); - - let normal_color = "leading bytes \x1b[40m trailing bytes"; - let parsed = driver(parse_color, normal_color).unwrap(); - assert_eq!(parsed, (Intense::No, Color::Black, FgBg::Background)); - } - - #[test] - fn attr_parsing() { - let attr = "leading bytes \x1b[1m trailing bytes"; - let parsed = driver(parse_attr, attr).unwrap(); - assert_eq!(parsed, b'1'); - } -} diff --git a/vendor/console/src/windows_term/mod.rs b/vendor/console/src/windows_term/mod.rs deleted file mode 100644 index c4ec193..0000000 --- a/vendor/console/src/windows_term/mod.rs +++ /dev/null @@ -1,563 +0,0 @@ -use std::cmp; -use std::env; -use std::ffi::OsStr; -use std::fmt::Display; -use std::io; -use std::iter::once; -use std::mem; -use std::os::raw::c_void; -use std::os::windows::ffi::OsStrExt; -use std::os::windows::io::AsRawHandle; -use std::slice; -use std::{char, mem::MaybeUninit}; - -use encode_unicode::error::InvalidUtf16Tuple; -use encode_unicode::CharExt; -use windows_sys::Win32::Foundation::{CHAR, HANDLE, INVALID_HANDLE_VALUE, MAX_PATH}; -use windows_sys::Win32::Storage::FileSystem::{ - FileNameInfo, GetFileInformationByHandleEx, FILE_NAME_INFO, -}; -use windows_sys::Win32::System::Console::{ - FillConsoleOutputAttribute, FillConsoleOutputCharacterA, GetConsoleCursorInfo, GetConsoleMode, - GetConsoleScreenBufferInfo, GetNumberOfConsoleInputEvents, GetStdHandle, ReadConsoleInputW, - SetConsoleCursorInfo, SetConsoleCursorPosition, SetConsoleMode, SetConsoleTitleW, - CONSOLE_CURSOR_INFO, CONSOLE_SCREEN_BUFFER_INFO, COORD, INPUT_RECORD, KEY_EVENT, - KEY_EVENT_RECORD, STD_ERROR_HANDLE, STD_HANDLE, STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, -}; -use windows_sys::Win32::UI::Input::KeyboardAndMouse::VIRTUAL_KEY; - -use crate::common_term; -use crate::kb::Key; -use crate::term::{Term, TermTarget}; - -#[cfg(feature = "windows-console-colors")] -mod colors; - -#[cfg(feature = "windows-console-colors")] -pub use self::colors::*; - -const ENABLE_VIRTUAL_TERMINAL_PROCESSING: u32 = 0x4; -pub const DEFAULT_WIDTH: u16 = 79; - -pub fn as_handle(term: &Term) -> HANDLE { - // convert between windows_sys::Win32::Foundation::HANDLE and std::os::windows::raw::HANDLE - term.as_raw_handle() as HANDLE -} - -pub fn is_a_terminal(out: &Term) -> bool { - let (fd, others) = match out.target() { - TermTarget::Stdout => (STD_OUTPUT_HANDLE, [STD_INPUT_HANDLE, STD_ERROR_HANDLE]), - TermTarget::Stderr => (STD_ERROR_HANDLE, [STD_INPUT_HANDLE, STD_OUTPUT_HANDLE]), - }; - - if unsafe { console_on_any(&[fd]) } { - // False positives aren't possible. If we got a console then - // we definitely have a tty on stdin. - return true; - } - - // At this point, we *could* have a false negative. We can determine that - // this is true negative if we can detect the presence of a console on - // any of the other streams. If another stream has a console, then we know - // we're in a Windows console and can therefore trust the negative. - if unsafe { console_on_any(&others) } { - return false; - } - - msys_tty_on(out) -} - -pub fn is_a_color_terminal(out: &Term) -> bool { - if !is_a_terminal(out) { - return false; - } - if msys_tty_on(out) { - return match env::var("TERM") { - Ok(term) => term != "dumb", - Err(_) => true, - }; - } - enable_ansi_on(out) -} - -fn enable_ansi_on(out: &Term) -> bool { - unsafe { - let handle = as_handle(out); - - let mut dw_mode = 0; - if GetConsoleMode(handle, &mut dw_mode) == 0 { - return false; - } - - dw_mode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING; - if SetConsoleMode(handle, dw_mode) == 0 { - return false; - } - - true - } -} - -unsafe fn console_on_any(fds: &[STD_HANDLE]) -> bool { - for &fd in fds { - let mut out = 0; - let handle = GetStdHandle(fd); - if GetConsoleMode(handle, &mut out) != 0 { - return true; - } - } - false -} - -pub fn terminal_size(out: &Term) -> Option<(u16, u16)> { - use windows_sys::Win32::System::Console::SMALL_RECT; - - // convert between windows_sys::Win32::Foundation::HANDLE and std::os::windows::raw::HANDLE - let handle = out.as_raw_handle(); - let hand = handle as windows_sys::Win32::Foundation::HANDLE; - - if hand == INVALID_HANDLE_VALUE { - return None; - } - - let zc = COORD { X: 0, Y: 0 }; - let mut csbi = CONSOLE_SCREEN_BUFFER_INFO { - dwSize: zc, - dwCursorPosition: zc, - wAttributes: 0, - srWindow: SMALL_RECT { - Left: 0, - Top: 0, - Right: 0, - Bottom: 0, - }, - dwMaximumWindowSize: zc, - }; - if unsafe { GetConsoleScreenBufferInfo(hand, &mut csbi) } == 0 { - return None; - } - - let rows = (csbi.srWindow.Bottom - csbi.srWindow.Top + 1) as u16; - let columns = (csbi.srWindow.Right - csbi.srWindow.Left + 1) as u16; - - Some((rows, columns)) -} - -pub fn move_cursor_to(out: &Term, x: usize, y: usize) -> io::Result<()> { - if out.is_msys_tty { - return common_term::move_cursor_to(out, x, y); - } - if let Some((hand, _)) = get_console_screen_buffer_info(as_handle(out)) { - unsafe { - SetConsoleCursorPosition( - hand, - COORD { - X: x as i16, - Y: y as i16, - }, - ); - } - } - Ok(()) -} - -pub fn move_cursor_up(out: &Term, n: usize) -> io::Result<()> { - if out.is_msys_tty { - return common_term::move_cursor_up(out, n); - } - - if let Some((_, csbi)) = get_console_screen_buffer_info(as_handle(out)) { - move_cursor_to(out, 0, csbi.dwCursorPosition.Y as usize - n)?; - } - Ok(()) -} - -pub fn move_cursor_down(out: &Term, n: usize) -> io::Result<()> { - if out.is_msys_tty { - return common_term::move_cursor_down(out, n); - } - - if let Some((_, csbi)) = get_console_screen_buffer_info(as_handle(out)) { - move_cursor_to(out, 0, csbi.dwCursorPosition.Y as usize + n)?; - } - Ok(()) -} - -pub fn move_cursor_left(out: &Term, n: usize) -> io::Result<()> { - if out.is_msys_tty { - return common_term::move_cursor_left(out, n); - } - - if let Some((_, csbi)) = get_console_screen_buffer_info(as_handle(out)) { - move_cursor_to( - out, - csbi.dwCursorPosition.X as usize - n, - csbi.dwCursorPosition.Y as usize, - )?; - } - Ok(()) -} - -pub fn move_cursor_right(out: &Term, n: usize) -> io::Result<()> { - if out.is_msys_tty { - return common_term::move_cursor_right(out, n); - } - - if let Some((_, csbi)) = get_console_screen_buffer_info(as_handle(out)) { - move_cursor_to( - out, - csbi.dwCursorPosition.X as usize + n, - csbi.dwCursorPosition.Y as usize, - )?; - } - Ok(()) -} - -pub fn clear_line(out: &Term) -> io::Result<()> { - if out.is_msys_tty { - return common_term::clear_line(out); - } - if let Some((hand, csbi)) = get_console_screen_buffer_info(as_handle(out)) { - unsafe { - let width = csbi.srWindow.Right - csbi.srWindow.Left; - let pos = COORD { - X: 0, - Y: csbi.dwCursorPosition.Y, - }; - let mut written = 0; - FillConsoleOutputCharacterA(hand, b' ' as CHAR, width as u32, pos, &mut written); - FillConsoleOutputAttribute(hand, csbi.wAttributes, width as u32, pos, &mut written); - SetConsoleCursorPosition(hand, pos); - } - } - Ok(()) -} - -pub fn clear_chars(out: &Term, n: usize) -> io::Result<()> { - if out.is_msys_tty { - return common_term::clear_chars(out, n); - } - if let Some((hand, csbi)) = get_console_screen_buffer_info(as_handle(out)) { - unsafe { - let width = cmp::min(csbi.dwCursorPosition.X, n as i16); - let pos = COORD { - X: csbi.dwCursorPosition.X - width, - Y: csbi.dwCursorPosition.Y, - }; - let mut written = 0; - FillConsoleOutputCharacterA(hand, b' ' as CHAR, width as u32, pos, &mut written); - FillConsoleOutputAttribute(hand, csbi.wAttributes, width as u32, pos, &mut written); - SetConsoleCursorPosition(hand, pos); - } - } - Ok(()) -} - -pub fn clear_screen(out: &Term) -> io::Result<()> { - if out.is_msys_tty { - return common_term::clear_screen(out); - } - if let Some((hand, csbi)) = get_console_screen_buffer_info(as_handle(out)) { - unsafe { - let cells = csbi.dwSize.X as u32 * csbi.dwSize.Y as u32; // as u32, or else this causes stack overflows. - let pos = COORD { X: 0, Y: 0 }; - let mut written = 0; - FillConsoleOutputCharacterA(hand, b' ' as CHAR, cells, pos, &mut written); // cells as u32 no longer needed. - FillConsoleOutputAttribute(hand, csbi.wAttributes, cells, pos, &mut written); - SetConsoleCursorPosition(hand, pos); - } - } - Ok(()) -} - -pub fn clear_to_end_of_screen(out: &Term) -> io::Result<()> { - if out.is_msys_tty { - return common_term::clear_to_end_of_screen(out); - } - if let Some((hand, csbi)) = get_console_screen_buffer_info(as_handle(out)) { - unsafe { - let bottom = csbi.srWindow.Right as u32 * csbi.srWindow.Bottom as u32; - let cells = bottom - (csbi.dwCursorPosition.X as u32 * csbi.dwCursorPosition.Y as u32); // as u32, or else this causes stack overflows. - let pos = COORD { - X: 0, - Y: csbi.dwCursorPosition.Y, - }; - let mut written = 0; - FillConsoleOutputCharacterA(hand, b' ' as CHAR, cells, pos, &mut written); // cells as u32 no longer needed. - FillConsoleOutputAttribute(hand, csbi.wAttributes, cells, pos, &mut written); - SetConsoleCursorPosition(hand, pos); - } - } - Ok(()) -} - -pub fn show_cursor(out: &Term) -> io::Result<()> { - if out.is_msys_tty { - return common_term::show_cursor(out); - } - if let Some((hand, mut cci)) = get_console_cursor_info(as_handle(out)) { - unsafe { - cci.bVisible = 1; - SetConsoleCursorInfo(hand, &cci); - } - } - Ok(()) -} - -pub fn hide_cursor(out: &Term) -> io::Result<()> { - if out.is_msys_tty { - return common_term::hide_cursor(out); - } - if let Some((hand, mut cci)) = get_console_cursor_info(as_handle(out)) { - unsafe { - cci.bVisible = 0; - SetConsoleCursorInfo(hand, &cci); - } - } - Ok(()) -} - -fn get_console_screen_buffer_info(hand: HANDLE) -> Option<(HANDLE, CONSOLE_SCREEN_BUFFER_INFO)> { - let mut csbi: CONSOLE_SCREEN_BUFFER_INFO = unsafe { mem::zeroed() }; - match unsafe { GetConsoleScreenBufferInfo(hand, &mut csbi) } { - 0 => None, - _ => Some((hand, csbi)), - } -} - -fn get_console_cursor_info(hand: HANDLE) -> Option<(HANDLE, CONSOLE_CURSOR_INFO)> { - let mut cci: CONSOLE_CURSOR_INFO = unsafe { mem::zeroed() }; - match unsafe { GetConsoleCursorInfo(hand, &mut cci) } { - 0 => None, - _ => Some((hand, cci)), - } -} - -pub fn key_from_key_code(code: VIRTUAL_KEY) -> Key { - use windows_sys::Win32::UI::Input::KeyboardAndMouse; - - match code { - KeyboardAndMouse::VK_LEFT => Key::ArrowLeft, - KeyboardAndMouse::VK_RIGHT => Key::ArrowRight, - KeyboardAndMouse::VK_UP => Key::ArrowUp, - KeyboardAndMouse::VK_DOWN => Key::ArrowDown, - KeyboardAndMouse::VK_RETURN => Key::Enter, - KeyboardAndMouse::VK_ESCAPE => Key::Escape, - KeyboardAndMouse::VK_BACK => Key::Backspace, - KeyboardAndMouse::VK_TAB => Key::Tab, - KeyboardAndMouse::VK_HOME => Key::Home, - KeyboardAndMouse::VK_END => Key::End, - KeyboardAndMouse::VK_DELETE => Key::Del, - KeyboardAndMouse::VK_SHIFT => Key::Shift, - KeyboardAndMouse::VK_MENU => Key::Alt, - _ => Key::Unknown, - } -} - -pub fn read_secure() -> io::Result<String> { - let mut rv = String::new(); - loop { - match read_single_key()? { - Key::Enter => { - break; - } - Key::Char('\x08') => { - if !rv.is_empty() { - let new_len = rv.len() - 1; - rv.truncate(new_len); - } - } - Key::Char(c) => { - rv.push(c); - } - _ => {} - } - } - Ok(rv) -} - -pub fn read_single_key() -> io::Result<Key> { - let key_event = read_key_event()?; - - let unicode_char = unsafe { key_event.uChar.UnicodeChar }; - if unicode_char == 0 { - Ok(key_from_key_code(key_event.wVirtualKeyCode)) - } else { - // This is a unicode character, in utf-16. Try to decode it by itself. - match char::from_utf16_tuple((unicode_char, None)) { - Ok(c) => { - // Maintain backward compatibility. The previous implementation (_getwch()) would return - // a special keycode for `Enter`, while ReadConsoleInputW() prefers to use '\r'. - if c == '\r' { - Ok(Key::Enter) - } else if c == '\x08' { - Ok(Key::Backspace) - } else if c == '\x1B' { - Ok(Key::Escape) - } else { - Ok(Key::Char(c)) - } - } - // This is part of a surrogate pair. Try to read the second half. - Err(InvalidUtf16Tuple::MissingSecond) => { - // Confirm that there is a next character to read. - if get_key_event_count()? == 0 { - let message = format!( - "Read invlid utf16 {}: {}", - unicode_char, - InvalidUtf16Tuple::MissingSecond - ); - return Err(io::Error::new(io::ErrorKind::InvalidData, message)); - } - - // Read the next character. - let next_event = read_key_event()?; - let next_surrogate = unsafe { next_event.uChar.UnicodeChar }; - - // Attempt to decode it. - match char::from_utf16_tuple((unicode_char, Some(next_surrogate))) { - Ok(c) => Ok(Key::Char(c)), - - // Return an InvalidData error. This is the recommended value for UTF-related I/O errors. - // (This error is given when reading a non-UTF8 file into a String, for example.) - Err(e) => { - let message = format!( - "Read invalid surrogate pair ({}, {}): {}", - unicode_char, next_surrogate, e - ); - Err(io::Error::new(io::ErrorKind::InvalidData, message)) - } - } - } - - // Return an InvalidData error. This is the recommended value for UTF-related I/O errors. - // (This error is given when reading a non-UTF8 file into a String, for example.) - Err(e) => { - let message = format!("Read invalid utf16 {}: {}", unicode_char, e); - Err(io::Error::new(io::ErrorKind::InvalidData, message)) - } - } - } -} - -fn get_stdin_handle() -> io::Result<HANDLE> { - let handle = unsafe { GetStdHandle(STD_INPUT_HANDLE) }; - if handle == INVALID_HANDLE_VALUE { - Err(io::Error::last_os_error()) - } else { - Ok(handle) - } -} - -/// Get the number of pending events in the ReadConsoleInput queue. Note that while -/// these aren't necessarily key events, the only way that multiple events can be -/// put into the queue simultaneously is if a unicode character spanning multiple u16's -/// is read. -/// -/// Therefore, this is accurate as long as at least one KEY_EVENT has already been read. -fn get_key_event_count() -> io::Result<u32> { - let handle = get_stdin_handle()?; - let mut event_count: u32 = unsafe { mem::zeroed() }; - - let success = unsafe { GetNumberOfConsoleInputEvents(handle, &mut event_count) }; - if success == 0 { - Err(io::Error::last_os_error()) - } else { - Ok(event_count) - } -} - -fn read_key_event() -> io::Result<KEY_EVENT_RECORD> { - let handle = get_stdin_handle()?; - let mut buffer: INPUT_RECORD = unsafe { mem::zeroed() }; - - let mut events_read: u32 = unsafe { mem::zeroed() }; - - let mut key_event: KEY_EVENT_RECORD; - loop { - let success = unsafe { ReadConsoleInputW(handle, &mut buffer, 1, &mut events_read) }; - if success == 0 { - return Err(io::Error::last_os_error()); - } - if events_read == 0 { - return Err(io::Error::new( - io::ErrorKind::Other, - "ReadConsoleInput returned no events, instead of waiting for an event", - )); - } - - if events_read == 1 && buffer.EventType != KEY_EVENT as u16 { - // This isn't a key event; ignore it. - continue; - } - - key_event = unsafe { mem::transmute(buffer.Event) }; - - if key_event.bKeyDown == 0 { - // This is a key being released; ignore it. - continue; - } - - return Ok(key_event); - } -} - -pub fn wants_emoji() -> bool { - // If WT_SESSION is set, we can assume we're running in the nne - // Windows Terminal. The correct way to detect this is not available - // yet. See https://github.com/microsoft/terminal/issues/1040 - env::var("WT_SESSION").is_ok() -} - -/// Returns true if there is an MSYS tty on the given handle. -pub fn msys_tty_on(term: &Term) -> bool { - let handle = term.as_raw_handle(); - unsafe { - // Check whether the Windows 10 native pty is enabled - { - let mut out = MaybeUninit::uninit(); - let res = GetConsoleMode(handle as HANDLE, out.as_mut_ptr()); - if res != 0 // If res is true then out was initialized. - && (out.assume_init() & ENABLE_VIRTUAL_TERMINAL_PROCESSING) - == ENABLE_VIRTUAL_TERMINAL_PROCESSING - { - return true; - } - } - - let size = mem::size_of::<FILE_NAME_INFO>(); - let mut name_info_bytes = vec![0u8; size + MAX_PATH as usize * mem::size_of::<u16>()]; - let res = GetFileInformationByHandleEx( - handle as HANDLE, - FileNameInfo, - &mut *name_info_bytes as *mut _ as *mut c_void, - name_info_bytes.len() as u32, - ); - if res == 0 { - return false; - } - let name_info: &FILE_NAME_INFO = &*(name_info_bytes.as_ptr() as *const FILE_NAME_INFO); - let s = slice::from_raw_parts( - name_info.FileName.as_ptr(), - name_info.FileNameLength as usize / 2, - ); - let name = String::from_utf16_lossy(s); - // This checks whether 'pty' exists in the file name, which indicates that - // a pseudo-terminal is attached. To mitigate against false positives - // (e.g., an actual file name that contains 'pty'), we also require that - // either the strings 'msys-' or 'cygwin-' are in the file name as well.) - let is_msys = name.contains("msys-") || name.contains("cygwin-"); - let is_pty = name.contains("-pty"); - is_msys && is_pty - } -} - -pub fn set_title<T: Display>(title: T) { - let buffer: Vec<u16> = OsStr::new(&format!("{}", title)) - .encode_wide() - .chain(once(0)) - .collect(); - unsafe { - SetConsoleTitleW(buffer.as_ptr()); - } -} diff --git a/vendor/console/tests/data/sample_zellij_session.log b/vendor/console/tests/data/sample_zellij_session.log deleted file mode 100755 index a777258..0000000 --- a/vendor/console/tests/data/sample_zellij_session.log +++ /dev/null @@ -1,56 +0,0 @@ -[1m[7m%[27m[1m[0m
]2;wintermute@ai:~/Programming/Repos/lib/console]1;..s/lib/console
[0m[27m[24m[J
-[1;36mconsole[0m on [1;35m [0m[1;35muse-handwritten-ansi-parser[0m [1;31m[[0m[1;31m![0m[1;31m][0m is [1;38;5;208m📦 [0m[1;38;5;208mv0.15.0[0m via [1;31m🦀 [0m[1;31mv1.57.0[0m[1;31m [0m
-[1;32m❯[0m [K[?1h=[?2004h[1m[31mn[0m[39m[1m[31mn[0m[39m[90mf[39m[0m[32mn[32mf[39m[?1l>[?2004l
-]2;neofetch]1;nf[?25l[?7l[0m[36m[1m -`
- .o+`
- `ooo/
- `+oooo:
- `+oooooo:
- -+oooooo+:
- `/:-:++oooo+:
- `/++++/+++++++:
- `/++++++++++++++:
- `/+++o[0m[36m[1moooooooo[0m[36m[1moooo/`
-[0m[36m[1m [0m[36m[1m./[0m[36m[1mooosssso++osssssso[0m[36m[1m+`
-[0m[36m[1m .oossssso-````/ossssss+`
- -osssssso. :ssssssso.
- :osssssss/ osssso+++.
- /ossssssss/ +ssssooo/-
- `/ossssso+/:- -:/+osssso+-
- `+sso+:-` `.-/+oso:
- `++:. `-/+/
- .` `/[0m
-[19A[9999999D[41C[0m[1m[36m[1mwintermute[0m@[36m[1mai[0m
-[41C[0m-------------[0m
-[41C[0m[36m[1mOS[0m[0m:[0m Arch Linux x86_64[0m
-[41C[0m[36m[1mHost[0m[0m:[0m 82BH Yoga 7 14ITL5[0m
-[41C[0m[36m[1mKernel[0m[0m:[0m 5.15.12-arch1-1[0m
-[41C[0m[36m[1mUptime[0m[0m:[0m 6 hours, 14 mins[0m
-[41C[0m[36m[1mPackages[0m[0m:[0m 1397 (pacman)[0m
-[41C[0m[36m[1mShell[0m[0m:[0m zsh 5.8[0m
-[41C[0m[36m[1mResolution[0m[0m:[0m 2560x1440[0m
-[41C[0m[36m[1mWM[0m[0m:[0m i3[0m
-[41C[0m[36m[1mTheme[0m[0m:[0m Adwaita [GTK3][0m
-[41C[0m[36m[1mIcons[0m[0m:[0m Adwaita [GTK3][0m
-[41C[0m[36m[1mTerminal[0m[0m:[0m zellij[0m
-[41C[0m[36m[1mCPU[0m[0m:[0m 11th Gen Intel i5-1135G7 (8) @ 4.200GHz[0m
-[41C[0m[36m[1mGPU[0m[0m:[0m Intel TigerLake-LP GT2 [Iris Xe Graphics][0m
-[41C[0m[36m[1mMemory[0m[0m:[0m 6181MiB / 15800MiB[0m
-
-[41C[30m[40m [31m[41m [32m[42m [33m[43m [34m[44m [35m[45m [36m[46m [37m[47m [m
-[41C[38;5;8m[48;5;8m [38;5;9m[48;5;9m [38;5;10m[48;5;10m [38;5;11m[48;5;11m [38;5;12m[48;5;12m [38;5;13m[48;5;13m [38;5;14m[48;5;14m [38;5;15m[48;5;15m [m
-
-
-[?25h[?7h[1m[7m%[27m[1m[0m
]2;wintermute@ai:~/Programming/Repos/lib/console]1;..s/lib/console
[0m[27m[24m[J
-[1;36mconsole[0m on [1;35m [0m[1;35muse-handwritten-ansi-parser[0m [1;31m[[0m[1;31m![0m[1;31m][0m is [1;38;5;208m📦 [0m[1;38;5;208mv0.15.0[0m via [1;31m🦀 [0m[1;31mv1.57.0[0m[1;31m [0m
-[1;32m❯[0m [K[?1h=[?2004h[?2004l
-[1m[7m%[27m[1m[0m
]2;wintermute@ai:~/Programming/Repos/lib/console]1;..s/lib/console
[0m[27m[24m[J
-[1;36mconsole[0m on [1;35m [0m[1;35muse-handwritten-ansi-parser[0m [1;31m[[0m[1;31m![0m[1;31m][0m is [1;38;5;208m📦 [0m[1;38;5;208mv0.15.0[0m via [1;31m🦀 [0m[1;31mv1.57.0[0m[1;31m [0m
-[1;31m❯[0m [K[?1h=[?2004h^[32mj[39m[32mj[39m[90mq rslt.json[39m[11D[1m[31mj[1m[31mj[0m[39m[90mq[90m [90mr[90ms[90ml[90mt[90m.[90mj[90ms[90mo[90mn[39m[11D[1m[31mj[1m[31mj[1m[31mc[0m[39m[39m [39m [39m [39m [39m [39m [39m [39m [39m [39m [10D[1m[31mc[1m[31mc[0m[39m
[A[A[0m[27m[24m[J
-[1;36mconsole[0m on [1;35m [0m[1;35muse-handwritten-ansi-parser[0m [1;31m[[0m[1;31m![0m[1;31m][0m is [1;38;5;208m📦 [0m[1;38;5;208mv0.15.0[0m via [1;31m🦀 [0m[1;31mv1.57.0[0m[1;31m [0m
-[1;32m❮[0m [1m[31mjjcc[0m[39m[K
[A[A[0m[27m[24m[J
-[1;36mconsole[0m on [1;35m [0m[1;35muse-handwritten-ansi-parser[0m [1;31m[[0m[1;31m![0m[1;31m][0m is [1;38;5;208m📦 [0m[1;38;5;208mv0.15.0[0m via [1;31m🦀 [0m[1;31mv1.57.0[0m[1;31m [0m
-[1;31m❯[0m [K[32mr[39m[1m[31mr[1m[31ma[0m[39m[90mnger[39m[1m[31mr[1m[31ma[1m[31mn[0m[39m[1m[31mn[1m[31mg[0m[39m[1m[31mg[1m[31me[0m[39m[0m[32mr[0m[32ma[0m[32mn[0m[32mg[0m[32me[32mr[39m[?1l>[?2004l
-]2;. ranger]1;ranger[?1049h[22;0;0t[1;58r(B[m[4l[?7h[?1h=[?25l[39;49m[?1006;1000h[39;49m(B[m[H[2J[2d[J[Aloading...[Kkranger\[?1h=[?1006;1000hkranger\
(B[0;1m[32mwintermute@ai [34m/home/wintermute/Programming/Repos/lib/console/[39mexamples[K
[2d[91m [94ma2s-rs (B[0m[32m=✓[39m(B[m (B[0;1;7m[94m examples 4 [39m(B[m ...
[3d(B[0;1;7m[94m console [39m(B[m (B[0;1m[91m [94msrc[44X[3;66H9 (B[0m[94m
[4d(B[0;1m[91m [94mfast_rsync [39m(B[m (B[0;1m[91m [94mtarget[41X[4;66H4 (B[0m[94m
[5d(B[0;1m[91m [94mfax [39m(B[m (B[0;1m[91m (B[0mCargo.lock[5;62H8.1 K
[6d(B[0;1m[91m [94mghostwriter [39m(B[m (B[0;1m[91m (B[0mCargo.toml[6;61H1.08 K
[7d(B[0;1m[91m [94mlead-oxide [39m(B[m (B[0;1m[91m (B[0mCHANGELOG.md[7;61H1.09 K
[8d(B[0;1m[91m [94mpdf [39m(B[m (B[0;1m[91m (B[0mLICENSE[8;61H1.09 K
[9d(B[0;1m[91m [94mpubproxpy [39m(B[m (B[0;1m[91m (B[0mREADME.md[9;61H1.89 K
[10d(B[0;1m[91m [94mrand-dir
[11d[91m [94mrust-s3
[12d[91m [94mrust-slack
[13d[91m [94msteamlocate-~
[14d[91m [94msubwinder
[15d[91m [94msysinfo
[16d[91m [94mthing
[17d[91m [94mvdf-rs
[18d[91m [94mzip-extensio~
[58d(B[0m[36mdrwxr-xr-x[39m 2 wintermute wintermute 4 2022-01-03 00:11 [34m(git: use-handwritten-ansi-parser)[39m [36m2022-01-05 11:59[39m 13.3K sum, 126G free 1/8 Al[?7ll[?7h[1;11H(B[m[2;18H[2;70H(B[0;7m colors.rs [3;70H(B[0;1m[91m (B[0mcolors256.rs[4;70H(B[0;1m[91m (B[0mcursor_at.rs[5;70H(B[0;1m[91m (B[0mterm.rs[58;90H[32m⌂[39m [36m2022-01-05 11:59[2;18H[39m(B[m[3;15H(B[0;1;7m[94m⌂+[4d(B[0m[34m>[32m✓[5d=✓[6d=✓[7d=✓[8d[34m>[36m?[9d[32m=✓[10d=✓[11d=✓[12d⌂[31m+[13d[32m=✓[14d=✓[15d=✓[16d⌂[36m?[17d[32m=[31m+[18d[32m=✓[2;18H[39m(B[m[2;68H(B[0;1;7m[94m✓[139G(B[0;7m✓[3;68H(B[0m[31m+[139G[32m✓[4;68H[39m·[139G[32m✓[5;68H[39m·[139G[32m✓[6;68H✓[7d✓[8d✓[9d✓[58;91H✓[39m [36m2022-01-05 11:59[2;18H[39m(B[m[1;62H(B[0;1msrc[K[2;18H[91m [94mexamples[39X[2;66H4 (B[0m[32m✓[39m(B[m ...(B[m[K[3;18H(B[0;1;7m[94m src 9 +[39m(B[m[K[4d [K[5d[K[58;36H9[58;47H5 17:39[58;91H[31m+[132G[39m2[2;18H(B[m[3d[2;70H(B[0;7m ansi.rs +[3;70H(B[0;1m[91m (B[0mcommon_term.rs[139G[32m✓[4;70H(B[0;1m[91m (B[0mkb.rs[139G[32m✓[5;70H(B[0;1m[91m (B[0mlib.rs[139G[32m✓[6;70H(B[0;1m[91m (B[0mterm.rs[139G[32m✓[7;70H(B[0;1m[91m (B[0munix_term.rs[139G[32m✓[8;70H(B[0;1m[91m (B[0mutils.rs[139G[32m✓[9;70H(B[0;1m[91m (B[0mwasm_term.rs[139G[32m✓[10;70H(B[0;1m[91m (B[0mwindows_term.rs[139G[32m✓[3;18H[39m(B[m[1;62H(B[0;1mtarget[2;70H(B[0m...(B[m[K[3;18H(B[0;1m[91m [94msrc[44X[3;66H9 (B[0m[31m+[39m(B[m[K[4;18H(B[0;1;7m[94m target 4 ·[39m(B[m[K[5d [K[6d[K[7d[K[8d[K[9d[K[10d[K[58;12H4[58;36H4[58;50H2:53[58;91H·[132G3[3;18H(B[m[4d[2;70H(B[0;1;7m[94m debug ·[3;70H(B[0;1m[91m [94mrelease[61X[139G(B[0m·[4;70H(B[0;1m[91m (B[0mCACHEDIR.TAG[139G·[4;18H(B[m[1;62H(B[0;1m[34mtarget/[39mdebug[2;2H[94mexamples (B[0m[32m✓[39m(B[m (B[0;1;7m[94m debug 6 ·[39m(B[m ...(B[m[K
[3d(B[0;1m[91m [94msrc (B[0m[31m+[39m(B[m (B[0;1m[91m [94mrelease[3;66H8 (B[0m·(B[m[K
[4d(B[0;1;7m[94m target ·[39m(B[m (B[0;1m[91m (B[0mCACHEDIR.TAG[31X[4;62H177 B ·(B[m[K[5;2HCargo.lock ·(B[m[K[6;2HCargo.toml [32m✓[39m(B[m[K[7;2HCHANGELOG.md [32m✓[39m(B[m[K[8;2HLICENSE [32m✓[39m(B[m[K[9;2HREADME.md [32m✓[39m(B[m[K
[10d[K[11d[K[12d[K[13d[K[14d[K[15d[K[16d[K[17d[K[18d[K[58;12H7[58;36H6[58;110H5.06[132G1/3[4;18H(B[m[2d[2;70H(B[0;1;7m[94m build ·[3;70H(B[0;1m[91m [94mdeps[64X[139G(B[0m·[4;70H(B[0;1m[91m [94mexamples[60X[139G(B[0m·[5;70H(B[0;1m[91m [94mincremental[57X[139G(B[0m·[2;18H(B[m[1;69H(B[0;1mrelease[2;18H[91m [94mdebug[42X[2;66H6 (B[0m·(B[m ...(B[m[K[3;18H(B[0;1;7m[94m release 8 ·[39m(B[m[K[4d [K[5d[K[58;36H8[58;53H1[132G2[2;18H(B[m[3d[2;70H(B[0;1;7m[94m build ·[3;70H(B[0;1m[91m [94mdeps[64X[139G(B[0m·[4;70H(B[0;1m[91m [94mexamples[60X[139G(B[0m·[5;70H(B[0;1m[91m [94mincremental[57X[139G(B[0m·[6;70H(B[0;1m[91m (B[0mlibconsole.d[139G·[7;70H(B[0;1m[91m (B[0mlibconsole.rlib[139G·[3;18H(B[m[1;69H(B[0;1m[34mrelease/[39mbuild[2;2H[94mdebug [16G(B[0m·(B[m (B[0;1;7m[94m build 6 ·[39m(B[m ...(B[m[K
[3d(B[0;1;7m[94m release ·[39m(B[m (B[0;1m[91m [94mdeps[41X[3;64H107 (B[0m·(B[m[K
[4d(B[0;1m[91m (B[0mCACHEDIR.TAG ·(B[m (B[0;1m[91m [94mexamples[39X[4;66H0 [C[39m(B[m[K[5;17H[1K (B[0;1m[91m [94mincremental[36X[5;66H0 (B[0m·(B[m[K[6;17H[1K (B[0;1m[91m (B[0mlibconsole.d[6;62H502 B ·(B[m[K[7;17H[1K (B[0;1m[91m (B[0mlibconsole.rlib[7;62H839 K ·(B[m[K
[8d[K[9d[K[58;12H8[58;36H6[58;50H3[58;110H 840[132G1/6[3;18H(B[m[A[2;70H(B[0;1;7m[94m libc-09f1df6a1e55c67a ·[3;70H(B[0;1m[91m [94mlibc-34b2cd9a598131ff[47X[139G(B[0m·[4;70H(B[0;1m[91m [94mlibc-1205fcf5a10a7473[47X[139G(B[0m·[5;70H(B[0;1m[91m [94mlibc-2978e3f83ccd5ba9[47X[139G(B[0m·[6;70H(B[0;1m[91m [94mnum-traits-4b89db8e22802f0d[41X[139G(B[0m·[7;70H(B[0;1m[91m [94mnum-traits-b59938ea688eb694[41X[139G(B[0m·[2;18H(B[m[?1l>[?12l[?25h[?1006;1000l[58;1H[?1049l[23;0;0t
[?1l>[1m[7m%[27m[1m[0m
]2;wintermute@ai:~/Programming/Repos/lib/console/target/release]1;..arget/release
[0m[27m[24m[J
-[1;36mconsole/target/release[0m on [1;35m [0m[1;35muse-handwritten-ansi-parser[0m [1;31m[[0m[1;31m![0m[1;31m][0m took [1;33m3s[0m
-[1;32m❯[0m [K[?1h=[?2004h
\ No newline at end of file |