Basic external printer (#467)

Addresses #320, #236

* Adding External printer

* Made ExternalPrinter as an optional feature. Clippy is happy, test pass, docs added.

* ExternalPrinter: prints multiple messages if available, more on error-handling.

* Bug(s) fixed. Prints messages. Working example in examples folder. Code formatted, clippyed, tests pass.

* Generic ExternalPrinter<T> where T: Display.

* Fixed: Works with buffers larger than a line.

* Fixed: Works with buffers larger than a line, refactored.

* Different approach, seems to look like what is expected. Gives the "illusion" of one line being entered. Needs more testing, could have some off by one errors ;)

Co-authored-by: Gregor Engberding <gregor@meinkopter.de>
This commit is contained in:
Gregor 2022-09-14 21:58:45 +02:00 committed by GitHub
parent dc091e8285
commit 70118f732c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 490 additions and 119 deletions

361
Cargo.lock generated
View File

@ -13,6 +13,15 @@ dependencies = [
"version_check",
]
[[package]]
name = "android_system_properties"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d7ed72e1635e121ca3e79420540282af22da58be50de153d36f81ddc6b83aa9e"
dependencies = [
"libc",
]
[[package]]
name = "ansi_term"
version = "0.12.1"
@ -46,6 +55,12 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "bumpalo"
version = "3.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d"
[[package]]
name = "cc"
version = "1.0.73"
@ -60,14 +75,16 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]]
name = "chrono"
version = "0.4.19"
version = "0.4.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73"
checksum = "bfd4d1b31faaa3a89d7934dbded3111da0d2ef28e3ebccdb4f0179f5929d1ef1"
dependencies = [
"libc",
"iana-time-zone",
"js-sys",
"num-integer",
"num-traits",
"time",
"wasm-bindgen",
"winapi",
]
@ -93,6 +110,81 @@ dependencies = [
"winapi",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]]
name = "crossbeam"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2801af0d36612ae591caa9568261fddce32ce6e08a7275ea334a06a4ad021a2c"
dependencies = [
"cfg-if",
"crossbeam-channel",
"crossbeam-deque",
"crossbeam-epoch",
"crossbeam-queue",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-channel"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c2dd04ddaf88237dc3b8d8f9a3c1004b506b54b3313403944054d23c0870c521"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-deque"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "715e8152b692bba2d374b53d4875445368fdf21a94751410af607a5ac677d1fc"
dependencies = [
"cfg-if",
"crossbeam-epoch",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-epoch"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "045ebe27666471bb549370b4b0b3e51b07f56325befa4284db65fc89c02511b1"
dependencies = [
"autocfg",
"cfg-if",
"crossbeam-utils",
"memoffset",
"once_cell",
"scopeguard",
]
[[package]]
name = "crossbeam-queue"
version = "0.3.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd42583b04998a5363558e5f9291ee5a5ff6b49944332103f251e7479a82aa7"
dependencies = [
"cfg-if",
"crossbeam-utils",
]
[[package]]
name = "crossbeam-utils"
version = "0.8.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51887d4adc7b564537b15adcfb307936f8075dfcd5f00dde9a9f1d29383682bc"
dependencies = [
"cfg-if",
"once_cell",
]
[[package]]
name = "crossterm"
version = "0.24.0"
@ -121,9 +213,9 @@ dependencies = [
[[package]]
name = "ctor"
version = "0.1.22"
version = "0.1.23"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f877be4f7c9f246b183111634f75baa039715e3f46ce860677d3b19a69fb229c"
checksum = "cdffe87e1d521a10f9696f833fe502293ea446d7f256c06128293a4119bdf4cb"
dependencies = [
"quote",
"syn",
@ -131,15 +223,15 @@ dependencies = [
[[package]]
name = "diff"
version = "0.1.12"
version = "0.1.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e25ea47919b1560c4e3b7fe0aaab9becf5b84a10325ddf7db0f0ba5e1026499"
checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8"
[[package]]
name = "either"
version = "1.6.1"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457"
checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797"
[[package]]
name = "errno"
@ -176,22 +268,22 @@ checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a"
[[package]]
name = "fastrand"
version = "1.7.0"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3fcf0cee53519c866c09b5de1f6c56ff9d647101f81c1964fa632e148896cdf"
checksum = "a7a407cfaa3385c4ae6b23e84623d48c2798d06e3e6a1878f7f59f17b3f86499"
dependencies = [
"instant",
]
[[package]]
name = "fd-lock"
version = "3.0.5"
version = "3.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46e245f4c8ec30c6415c56cb132c07e69e74f1942f6b4a4061da748b49f486ca"
checksum = "e11dcc7e4d79a8c89b9ab4c6f5c30b1fc4a83c420792da3542fd31179ed5f517"
dependencies = [
"cfg-if",
"rustix",
"windows-sys 0.30.0",
"windows-sys",
]
[[package]]
@ -206,13 +298,13 @@ dependencies = [
[[package]]
name = "getrandom"
version = "0.2.5"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d39cd93900197114fa1fcb7ae84ca742095eed9442088988ae74fa744e930e77"
checksum = "4eb1a864a501629691edf6c15a593b7a51eebaa1e8468e9ddc623de7c9b58ec6"
dependencies = [
"cfg-if",
"libc",
"wasi 0.10.0+wasi-snapshot-preview1",
"wasi 0.11.0+wasi-snapshot-preview1",
]
[[package]]
@ -239,6 +331,19 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2540771e65fc8cb83cd6e8a237f70c319bd5c29f78ed1084ba5d50eeac86f7f9"
[[package]]
name = "iana-time-zone"
version = "0.1.46"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501"
dependencies = [
"android_system_properties",
"core-foundation-sys",
"js-sys",
"wasm-bindgen",
"winapi",
]
[[package]]
name = "instant"
version = "0.1.12"
@ -250,9 +355,9 @@ dependencies = [
[[package]]
name = "io-lifetimes"
version = "0.6.1"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9448015e586b611e5d322f6703812bbca2f1e709d5773ecd38ddb4e3bb649504"
checksum = "1ea37f355c05dde75b84bba2d767906ad522e97cd9e2eef2be7a4ab7fb442c06"
[[package]]
name = "itertools"
@ -265,15 +370,24 @@ dependencies = [
[[package]]
name = "itoa"
version = "1.0.1"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35"
checksum = "6c8af84674fe1f223a982c933a0ee1086ac4d4052aa0fb8060c12c6ad838e754"
[[package]]
name = "js-sys"
version = "0.3.59"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "258451ab10b34f8af53416d1fdab72c22e805f0c92a1136d59470ec0b11138b2"
dependencies = [
"wasm-bindgen",
]
[[package]]
name = "libc"
version = "0.2.126"
version = "0.2.132"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836"
checksum = "8371e4e5341c3a96db127eb2465ac681ced4c433e01dd0e938adbef26ba93ba5"
[[package]]
name = "libsqlite3-sys"
@ -321,15 +435,24 @@ dependencies = [
]
[[package]]
name = "mio"
version = "0.8.3"
name = "memoffset"
version = "0.6.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799"
checksum = "5aa361d4faea93603064a027415f07bd8e1d5c88c9fbf68bf56a285428fd79ce"
dependencies = [
"autocfg",
]
[[package]]
name = "mio"
version = "0.8.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf"
dependencies = [
"libc",
"log",
"wasi 0.11.0+wasi-snapshot-preview1",
"windows-sys 0.36.1",
"windows-sys",
]
[[package]]
@ -392,9 +515,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.10.0"
version = "1.13.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "87f3e037eac156d1775da914196f0f37741a274155e34a0b7e427c35d2a2ecb9"
checksum = "074864da206b4973b84eb91683020dbefd6a8c3f0f38e054d93954e891935e4e"
[[package]]
name = "output_vt100"
@ -431,7 +554,7 @@ dependencies = [
"libc",
"redox_syscall",
"smallvec",
"windows-sys 0.36.1",
"windows-sys",
]
[[package]]
@ -454,27 +577,27 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.39"
version = "1.0.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
dependencies = [
"unicode-ident",
]
[[package]]
name = "quote"
version = "1.0.18"
version = "1.0.21"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1"
checksum = "bbe448f377a7d6961e30f5955f9b8d106c3f5e449d493ee1b125c1d43c2b5179"
dependencies = [
"proc-macro2",
]
[[package]]
name = "redox_syscall"
version = "0.2.13"
version = "0.2.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62f25bc4c7e55e0b0b7a1d43fb893f4fa1361d0abe38b9ce4f323c2adfe6ef42"
checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
dependencies = [
"bitflags",
]
@ -485,6 +608,7 @@ version = "0.11.0"
dependencies = [
"chrono",
"clipboard",
"crossbeam",
"crossterm",
"fd-lock",
"gethostname",
@ -561,29 +685,29 @@ dependencies = [
[[package]]
name = "rustix"
version = "0.34.8"
version = "0.35.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2079c267b8394eb529872c3cf92e181c378b41fea36e68130357b52493701d2e"
checksum = "72c825b8aa8010eb9ee99b75f05e10180b9278d161583034d7574c9d617aeada"
dependencies = [
"bitflags",
"errno",
"io-lifetimes",
"libc",
"linux-raw-sys",
"winapi",
"windows-sys",
]
[[package]]
name = "rustversion"
version = "1.0.6"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2cc38e8fa666e2de3c4aba7edeb5ffc5246c1c2ed0e3d17e560aeeba736b23f"
checksum = "97477e48b4cf8603ad5f7aaf897467cf42ab4218a38ef76fb14c2d6773a6d6a8"
[[package]]
name = "ryu"
version = "1.0.9"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f"
checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09"
[[package]]
name = "scopeguard"
@ -593,24 +717,24 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "semver"
version = "1.0.9"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cb243bdfdb5936c8dc3c45762a19d12ab4550cdc753bc247637d4ec35a040fd"
checksum = "93f6841e709003d68bb2deee8c343572bf446003ec20a583e76f7b15cebf3711"
[[package]]
name = "serde"
version = "1.0.137"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
dependencies = [
"serde_derive",
]
[[package]]
name = "serde_derive"
version = "1.0.137"
version = "1.0.144"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
dependencies = [
"proc-macro2",
"quote",
@ -619,9 +743,9 @@ dependencies = [
[[package]]
name = "serde_json"
version = "1.0.79"
version = "1.0.85"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e8d9fa5c3b304765ce1fd9c4c8a3de2c8db365a5b91be52f186efc675681d95"
checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44"
dependencies = [
"itoa",
"ryu",
@ -660,9 +784,9 @@ dependencies = [
[[package]]
name = "smallvec"
version = "1.8.0"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83"
checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1"
[[package]]
name = "strip-ansi-escapes"
@ -675,15 +799,15 @@ dependencies = [
[[package]]
name = "strum"
version = "0.24.0"
version = "0.24.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e96acfc1b70604b8b2f1ffa4c57e59176c7dbb05d556c71ecd2f5498a1dee7f8"
checksum = "063e6045c0e62079840579a7e47a355ae92f60eb74daaf156fb1e84ba164e63f"
[[package]]
name = "strum_macros"
version = "0.24.0"
version = "0.24.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6878079b17446e4d3eba6192bb0a2950d5b14f0ed8424b852310e5a94345d0ef"
checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59"
dependencies = [
"heck",
"proc-macro2",
@ -694,9 +818,9 @@ dependencies = [
[[package]]
name = "syn"
version = "1.0.96"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf"
checksum = "58dbef6ec655055e20b86b15a8cc6d439cca19b667537ac6a1369572d151ab13"
dependencies = [
"proc-macro2",
"quote",
@ -719,18 +843,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.31"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd829fe32373d27f76265620b5309d0340cb8550f523c1dda251d6298069069a"
checksum = "f5f6586b7f764adc0231f4c79be7b920e766bb2f3e51b3661cdb263828f19994"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.31"
version = "1.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0396bc89e626244658bef819e22d0cc459e795a5ebe878e6ec336d1674a8d79a"
checksum = "12bafc5b54507e0149cdf1b145a5d80ab80a90bcd9275df43d4fff68460f6c21"
dependencies = [
"proc-macro2",
"quote",
@ -750,9 +874,9 @@ dependencies = [
[[package]]
name = "unicode-ident"
version = "1.0.0"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee"
checksum = "c4f5b37a154999a8f3f98cc23a628d850e154479cd94decf3414696e12e31aaf"
[[package]]
name = "unicode-segmentation"
@ -817,6 +941,60 @@ version = "0.11.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]]
name = "wasm-bindgen"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7652e3f6c4706c8d9cd54832c4a4ccb9b5336e2c3bd154d5cccfbf1c1f5f7d"
dependencies = [
"cfg-if",
"wasm-bindgen-macro",
]
[[package]]
name = "wasm-bindgen-backend"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "662cd44805586bd52971b9586b1df85cdbbd9112e4ef4d8f41559c334dc6ac3f"
dependencies = [
"bumpalo",
"log",
"once_cell",
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-macro"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b260f13d3012071dfb1512849c033b1925038373aea48ced3012c09df952c602"
dependencies = [
"quote",
"wasm-bindgen-macro-support",
]
[[package]]
name = "wasm-bindgen-macro-support"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5be8e654bdd9b79216c2929ab90721aa82faf65c48cdf08bdc4e7f51357b80da"
dependencies = [
"proc-macro2",
"quote",
"syn",
"wasm-bindgen-backend",
"wasm-bindgen-shared",
]
[[package]]
name = "wasm-bindgen-shared"
version = "0.2.82"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6598dd0bd3c7d51095ff6531a5b23e02acdc81804e30d8f07afb77b7215a140a"
[[package]]
name = "winapi"
version = "0.3.9"
@ -839,86 +1017,43 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]]
name = "windows-sys"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "030b7ff91626e57a05ca64a07c481973cbb2db774e4852c9c7ca342408c6a99a"
dependencies = [
"windows_aarch64_msvc 0.30.0",
"windows_i686_gnu 0.30.0",
"windows_i686_msvc 0.30.0",
"windows_x86_64_gnu 0.30.0",
"windows_x86_64_msvc 0.30.0",
]
[[package]]
name = "windows-sys"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ea04155a16a59f9eab786fe12a4a450e75cdb175f9e0d80da1e17db09f55b8d2"
dependencies = [
"windows_aarch64_msvc 0.36.1",
"windows_i686_gnu 0.36.1",
"windows_i686_msvc 0.36.1",
"windows_x86_64_gnu 0.36.1",
"windows_x86_64_msvc 0.36.1",
"windows_aarch64_msvc",
"windows_i686_gnu",
"windows_i686_msvc",
"windows_x86_64_gnu",
"windows_x86_64_msvc",
]
[[package]]
name = "windows_aarch64_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29277a4435d642f775f63c7d1faeb927adba532886ce0287bd985bffb16b6bca"
[[package]]
name = "windows_aarch64_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bb8c3fd39ade2d67e9874ac4f3db21f0d710bee00fe7cab16949ec184eeaa47"
[[package]]
name = "windows_i686_gnu"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1145e1989da93956c68d1864f32fb97c8f561a8f89a5125f6a2b7ea75524e4b8"
[[package]]
name = "windows_i686_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "180e6ccf01daf4c426b846dfc66db1fc518f074baa793aa7d9b9aaeffad6a3b6"
[[package]]
name = "windows_i686_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4a09e3a0d4753b73019db171c1339cd4362c8c44baf1bcea336235e955954a6"
[[package]]
name = "windows_i686_msvc"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2e7917148b2812d1eeafaeb22a97e4813dfa60a3f8f78ebe204bcc88f12f024"
[[package]]
name = "windows_x86_64_gnu"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ca64fcb0220d58db4c119e050e7af03c69e6f4f415ef69ec1773d9aab422d5a"
[[package]]
name = "windows_x86_64_gnu"
version = "0.36.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4dcd171b8776c41b97521e5da127a2d86ad280114807d0b2ab1e462bc764d9e1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08cabc9f0066848fef4bc6a1c1668e6efce38b661d2aeec75d18d8617eebb5f1"
[[package]]
name = "windows_x86_64_msvc"
version = "0.36.1"

View File

@ -32,14 +32,15 @@ rusqlite = { version = "0.28.0", optional = true, features = ["bundled"] }
serde_json = { version = "1.0.79", optional = true }
gethostname = { version = "0.2.3", optional = true }
thiserror = "1.0.31"
crossbeam = { version = "0.8.2", optional = true }
[dev-dependencies]
tempfile = "3.3.0"
pretty_assertions = "1.1.0"
rstest = {version = "0.15.0", default-features = false}
rstest = { version = "0.15.0", default-features = false }
[features]
system_clipboard = ["clipboard"]
bashisms = []
sqlite = ["rusqlite", "serde_json", "gethostname"]
external_printer = ["crossbeam"]

View File

@ -0,0 +1,64 @@
// Create a default reedline object to handle user input
// to run:
// cargo run --example external_printer --features=external_printer
#[cfg(feature = "external_printer")]
use {
reedline::ExternalPrinter,
reedline::{DefaultPrompt, Reedline, Signal},
std::thread,
std::thread::sleep,
std::time::Duration,
};
#[cfg(feature = "external_printer")]
fn main() {
let printer = ExternalPrinter::default();
// make a clone to use it in a different thread
let p_clone = printer.clone();
// get the Sender<String> to have full sending control
let p_sender = printer.sender();
// external printer that prints a message every second
thread::spawn(move || {
let mut i = 1;
loop {
sleep(Duration::from_secs(1));
assert!(p_clone.print(format!("Message {} delivered.", i)).is_ok());
i += 1;
}
});
// external printer that prints a bunch of messages after 3 seconds
thread::spawn(move || {
sleep(Duration::from_secs(3));
for _ in 0..10 {
sleep(Duration::from_millis(1));
assert!(p_sender.send(format!("Fast Hello !")).is_ok());
}
});
let mut line_editor = Reedline::create().with_external_printer(printer);
let prompt = DefaultPrompt::default();
loop {
if let Ok(sig) = line_editor.read_line(&prompt) {
match sig {
Signal::Success(buffer) => {
println!("We processed: {}", buffer);
}
Signal::CtrlD | Signal::CtrlC => {
println!("\nAborted!");
break;
}
}
continue;
}
break;
}
}
#[cfg(not(feature = "external_printer"))]
fn main() {
println!("Please enable the feature: external_printer")
}

View File

@ -5,6 +5,12 @@ use crate::{
};
use crate::result::{ReedlineError, ReedlineErrorVariants};
#[cfg(feature = "external_printer")]
use {
crate::external_printer::ExternalPrinter,
crossbeam::channel::TryRecvError,
std::io::{Error, ErrorKind},
};
use {
crate::{
completion::{Completer, DefaultCompleter},
@ -86,7 +92,8 @@ pub struct Reedline {
// History
history: Box<dyn History>,
history_cursor: HistoryCursor,
history_session_id: Option<HistorySessionId>, // none if history doesn't support this
history_session_id: Option<HistorySessionId>,
// none if history doesn't support this
history_last_run_id: Option<HistoryItemId>,
input_mode: InputMode,
@ -119,6 +126,9 @@ pub struct Reedline {
// Text editor used to open the line buffer for editing
buffer_editor: Option<BufferEditor>,
#[cfg(feature = "external_printer")]
external_printer: Option<ExternalPrinter<String>>,
}
struct BufferEditor {
@ -167,6 +177,8 @@ impl Reedline {
use_ansi_coloring: true,
menus: Vec::new(),
buffer_editor: None,
#[cfg(feature = "external_printer")]
external_printer: None,
}
}
@ -454,7 +466,22 @@ impl Reedline {
loop {
let mut paste_enter_state = false;
if event::poll(Duration::from_millis(1000))? {
#[cfg(feature = "external_printer")]
if let Some(ref external_printer) = self.external_printer {
// get messages from printer as crlf separated "lines"
let messages = Self::external_messages(external_printer)?;
if !messages.is_empty() {
// print the message(s)
self.painter.print_external_message(
messages,
self.editor.line_buffer(),
prompt,
)?;
self.repaint(prompt)?;
}
}
if event::poll(Duration::from_millis(100))? {
let mut latest_resize = None;
// There could be multiple events queued up!
@ -1384,6 +1411,36 @@ impl Reedline {
self.painter
.repaint_buffer(prompt, &lines, menu, self.use_ansi_coloring)
}
/// Adds an external printer
#[cfg(feature = "external_printer")]
pub fn with_external_printer(mut self, printer: ExternalPrinter<String>) -> Self {
self.external_printer = Some(printer);
self
}
#[cfg(feature = "external_printer")]
fn external_messages(external_printer: &ExternalPrinter<String>) -> Result<Vec<String>> {
let mut messages = Vec::new();
loop {
let result = external_printer.receiver().try_recv();
match result {
Ok(line) => {
messages.push(line);
}
Err(TryRecvError::Empty) => {
break;
}
Err(TryRecvError::Disconnected) => {
return Err(Error::new(
ErrorKind::NotConnected,
TryRecvError::Disconnected,
));
}
}
}
Ok(messages)
}
}
#[test]

65
src/external_printer.rs Normal file
View File

@ -0,0 +1,65 @@
//! To print messages while editing a line
//! See example:
//! cargo run --example external_printer --features=external_printer
#[cfg(feature = "external_printer")]
use {
crossbeam::channel::{bounded, Receiver, SendError, Sender},
std::fmt::Display,
};
#[cfg(feature = "external_printer")]
pub const EXTERNAL_PRINTER_DEFAULT_CAPACITY: usize = 20;
/// An ExternalPrinter allows to print messages of text while editing a line.
/// The message is printed as a new line, the line-edit will continue below the
/// output.
#[cfg(feature = "external_printer")]
#[derive(Debug, Clone)]
pub struct ExternalPrinter<T>
where
T: Display,
{
sender: Sender<T>,
receiver: Receiver<T>,
}
#[cfg(feature = "external_printer")]
impl<T> ExternalPrinter<T>
where
T: Display,
{
/// Creates an ExternalPrinter to store lines with a max_cap
pub fn new(max_cap: usize) -> Self {
let (sender, receiver) = bounded::<T>(max_cap);
Self { sender, receiver }
}
/// Gets a Sender to use the printer externally by sending lines to it
pub fn sender(&self) -> Sender<T> {
self.sender.clone()
}
/// Receiver to get messages if any
pub fn receiver(&self) -> &Receiver<T> {
&self.receiver
}
/// Convenience method if the whole Printer is cloned, blocks if max_cap is reached.
///
pub fn print(&self, line: T) -> Result<(), SendError<T>> {
self.sender.send(line)
}
/// Convenience method to get a line if any, doesn´t block.
pub fn get_line(&self) -> Option<T> {
self.receiver.try_recv().ok()
}
}
#[cfg(feature = "external_printer")]
impl<T> Default for ExternalPrinter<T>
where
T: Display,
{
fn default() -> Self {
Self::new(EXTERNAL_PRINTER_DEFAULT_CAPACITY)
}
}

View File

@ -259,6 +259,8 @@ pub use menu::{
};
mod utils;
mod external_printer;
pub use utils::{
get_reedline_default_keybindings, get_reedline_edit_commands,
get_reedline_keybinding_modifiers, get_reedline_keycodes, get_reedline_prompt_edit_modes,
@ -267,3 +269,5 @@ pub use utils::{
// Reexport the key types to be independent from an explicit crossterm dependency.
pub use crossterm::event::{KeyCode, KeyModifiers};
#[cfg(feature = "external_printer")]
pub use external_printer::ExternalPrinter;

View File

@ -3,10 +3,10 @@ use {
crate::{
menu::{Menu, ReedlineMenu},
painting::PromptLines,
Prompt,
LineBuffer, Prompt,
},
crossterm::{
cursor::{self, MoveTo, RestorePosition, SavePosition},
cursor::{self, MoveTo, MoveUp, RestorePosition, SavePosition},
style::{Attribute, Print, ResetColor, SetAttribute, SetForegroundColor},
terminal::{self, Clear, ClearType, ScrollUp},
QueueableCommand, Result,
@ -452,6 +452,51 @@ impl Painter {
self.stdout.flush()
}
/// Prints an external message
pub fn print_external_message(
&mut self,
messages: Vec<String>,
line_buffer: &LineBuffer,
prompt: &dyn Prompt,
) -> Result<()> {
// adding 3 seems to be right for first line-wrap
let prompt_len = prompt.render_prompt_right().len() + 3;
let mut buffer_num_lines = 0_u16;
for (i, line) in line_buffer.get_buffer().lines().enumerate() {
let screen_lines = match i {
0 => {
// the first line has to deal with the prompt
let first_line_len = line.len() + prompt_len;
// at least, it is one line
((first_line_len as u16) / (self.screen_width())) + 1
}
_ => {
// the n-th line, no prompt, at least, it is one line
((line.len() as u16) / self.screen_width()) + 1
}
};
// count up screen-lines
buffer_num_lines = buffer_num_lines.saturating_add(screen_lines);
}
// move upward to start print if the line-buffer is more than one screen-line
if buffer_num_lines > 1 {
self.stdout.queue(MoveUp(buffer_num_lines - 1))?;
}
let erase_line = format!("\r{}\r", " ".repeat(self.screen_width().into()));
for line in messages {
self.stdout.queue(Print(&erase_line))?;
self.paint_line(&line)?;
let new_start = self.prompt_start_row.saturating_add(1);
let height = self.screen_height();
if new_start >= height {
self.prompt_start_row = height - 1;
} else {
self.prompt_start_row = new_start;
}
}
Ok(())
}
}
#[cfg(test)]