diff options
Diffstat (limited to 'vendor/dialoguer')
35 files changed, 0 insertions, 5173 deletions
diff --git a/vendor/dialoguer/.cargo-checksum.json b/vendor/dialoguer/.cargo-checksum.json deleted file mode 100644 index f3475ad..0000000 --- a/vendor/dialoguer/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"abf94b42ba3b3e8982c8f3453277488cdf254717750bdde6788659ef4847d6d1","Cargo.lock":"6491d36f2328f571f3334169897ecf4d1864da6485c0acc7d1880e83681acc1e","Cargo.toml":"543ccb04d5aea6cab6b2c425332effc08773c686ef9ca92ce156db64ffefabb8","LICENSE":"2022c11b24fc1e50fa06a5959e40198a3464f560729ad3d00139abb8a328362d","Makefile":"0247f9342ca2d816bec3173b41761ccba74c2a9fa0122cd7d7d2f46b4b13dc82","README.md":"2793836e3dd9e50b735103c216c2b4c6aa0fc2335816c367ea33956de24db132","examples/buffered.rs":"abaca0a19a6b3bfef72f37c9995341550a17794709515861f0f671c71cd95a56","examples/completion.rs":"01fe4ac9c26790e82ae1ae6263faa6dc143c44deadc8b83101900fc7276e4cb2","examples/confirm.rs":"cc8f6b68dfe07ea462de33abb6e9c2f96fb98903c6f47c48b4c47b2b1aa350cd","examples/editor.rs":"651e7ddef61cd3b2bd4655b619e76ab347dbfa5d1b90a7f95704e5ccd2d53d5e","examples/fuzzyselect.rs":"1a07a63cd2acbf54ee7dc305bb6689cf054186296a0a6bb3033d584e32fbe3c2","examples/history.rs":"dcb59f6d2db60bed5625545cebfda509e38ab61fa9db28c76009ac62a89b4bce","examples/input.rs":"81c27b4f6d05c589c946a03d72db552d16afe50efe9644a871e13dca4f111fb8","examples/multi_select.rs":"d41c1ee68e2b5fd6a93f4f58399d6094caee9883506f4f9f4ca1c7ed12e31068","examples/paging.rs":"66cd79fc4110b807bfd34121746d9ab6707b501a6cf4f8dfb9cfde774ad1fb2d","examples/password.rs":"d04586c76d8811e9b6a93608f7d19f663c6c284ebfe559794c6e7e3ef83b2d08","examples/select.rs":"49c633ce9cf30df11eca564029301f1240bce74e041e40aa8815929d69c5215e","examples/sort.rs":"39dd6c326ffb48b0afc69c0b72b7a256d212eb5c57bc6df6e0c7cb7e461bc753","examples/wizard.rs":"117038bc4a85204a667d45d0a76995e535b0f982befe3cd8bdbc9088401ee418","src/completion.rs":"f17a2af4341dd7098837c52da57f90cfc755b33db21599797ae1ff9d82f2b701","src/edit.rs":"6c4622998c7d0516525361d9cb988a50908045908af00e9398f51333704fdf3a","src/history.rs":"82e3d338a7cdf9172a16baba2617a28601e32df06fe109c954051f3a64dca374","src/lib.rs":"3467d3ed35906f93e1f6cfeceda6f4a79df9448880505c9d7fa1c572c189575f","src/paging.rs":"37e8a9851c80d415e828e43565818f6fd92532eea7d5e948eb6d49c98cc90316","src/prompts/confirm.rs":"5c88bd9a7a06682043bd196bad882e9f9cd59272da866afa5357b57e456752a6","src/prompts/fuzzy_select.rs":"862a5713792117744d88d1c91660ed768770d40d444ef30b07b18e81e6a7d8dc","src/prompts/input.rs":"aecb18548a63093703172ca223dff1dedd79ab86abb856e6e6fa60758dd7d413","src/prompts/mod.rs":"33c9ac2b7bdadcf5461e8a0fcb7db87d7635d7f77a00dc9049550d819f0ae6be","src/prompts/multi_select.rs":"53b21e8b90cbbbe1dddd798a611ebcfaefe3b845a7156411c80240e88f6c2afd","src/prompts/password.rs":"13c25b3e4dd8572fe4e6ab7910847b322da4eafcb36945b4903dc5df0f89606b","src/prompts/select.rs":"c29568116bf5b7dc281832f7fe31884737772aa8f5900a03e8fe44ac37b59e9a","src/prompts/sort.rs":"2a2fb7cb21720b59d7aa80d3fff12d1c87e8125bff99f2289a6a2f92696455a2","src/theme.rs":"3ec68222853ce2cf959900fb443b7f5123418d84db7cab64f24a7b6ddde9d5e2","src/validate.rs":"c61723bfbcceec71f7b2802203791ac9b81590c1cbe85ab1c17ad5cfc907ed97"},"package":"59c6f2989294b9a498d3ad5491a79c6deb604617378e1cdc4bfc1c1361fe2f87"}
\ No newline at end of file diff --git a/vendor/dialoguer/CHANGELOG.md b/vendor/dialoguer/CHANGELOG.md deleted file mode 100644 index 065f015..0000000 --- a/vendor/dialoguer/CHANGELOG.md +++ /dev/null @@ -1,116 +0,0 @@ -# Changelog - -## 0.10.4 - -### Enhancements - -* Added validator for password input - -## 0.10.3 - -### Enhancements - -* Fix various issues with fuzzy select -* Enable customization of number of rows for fuzzy select -* Added post completion text for input -* Various cursor movement improvements -* Correctly ignore unknown keys. -* Reset prompt height in `TermThemeRenderer::clear`. - -## 0.10.2 - -### Enhancements - -* Fix fuzzy select active item colors. -* Fix fuzzy search clear on cancel. -* Clear everything on cancel via escape key. - -## 0.10.1 - -### Enhancements - -* Allow matches highlighting for `FuzzySelect` - -## 0.10.0 - -### Enhancements - -* Loosen some trait bounds -* Improve keyboard interactions (#141, #162) -* Added `max_length` to `MultiSelect`, `Select` and `Sort` -* Allow completion support for `Input::interact_text*` behind `completion` feature - -### Breaking - -* All prompts `*::new` will now don't report selected values unless `report(true)` is called on them. - -## 0.9.0 - -### Enhancements - -* Apply input validation to the default value too in `Input` -* Added `FuzzySelect` behind `fuzzy-select` feature -* Allow history processing for `Input::interact_text*` behind `history` feature -* Added `interact_*_opt` methods for `MultiSelect` and `Sort`. - -### Breaking - -* Updated MSRV to `1.51.0` -* `Editor` is gated behind `editor` feature -* `Password`, `Theme::format_password_prompt` and `Theme::format_password_prompt_selection` are gated behind `password` feature -* Remove `Select::paged()`, `Sort::paged()` and `MultiSelect::paged()` in favor of automatic paging based on terminal size - -## 0.8.0 - -### Enhancements - -* `Input::validate_with` can take a `FnMut` (allowing multiple references) - -### Breaking - -* `Input::interact*` methods take `&mut self` instead of `&self` - -## 0.7.0 - -### Enhancements - -* Added `wait_for_newline` to `Confirm` -* More secure password prompt -* More documentation -* Added `interact_text` method for `Input` prompt -* Added `inline_selections` to `ColorfulTheme` - -### Breaking - -* Removed `theme::CustomPromptCharacterTheme` -* `Input` validators now take the input type `T` as arg -* `Confirm` has no `default` value by default now - -## 0.6.2 - -### Enhancements - -* Updating some docs - -## 0.6.1 - -### Bugfixes - -* `theme::ColorfulTheme` default styles are for stderr - -## 0.6.0 - -### Breaking - -* Removed `theme::SelectionStyle` enum -* Allowed more customization for `theme::Theme` trait by changing methods -* Allowed more customization for `theme::ColorfulTheme` by changing members -* Renamed prompt `Confirmation` to `Confirm` -* Renamed prompt `PasswordInput` to `Password` -* Renamed prompt `OrderList` to `Sort` -* Renamed prompt `Checkboxes` to `MultiSelect` - -### Enhancements - -* Improved colored theme -* Improved cursor visibility manipulation diff --git a/vendor/dialoguer/Cargo.lock b/vendor/dialoguer/Cargo.lock deleted file mode 100644 index da31c0b..0000000 --- a/vendor/dialoguer/Cargo.lock +++ /dev/null @@ -1,351 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "bitflags" -version = "1.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" - -[[package]] -name = "cc" -version = "1.0.79" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" - -[[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.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d79fbe8970a77e3e34151cc13d3b3e248aa0faaecb9f6091fa07ebefe5ad60" -dependencies = [ - "encode_unicode", - "lazy_static", - "libc", - "unicode-width", - "windows-sys 0.42.0", -] - -[[package]] -name = "dialoguer" -version = "0.10.4" -dependencies = [ - "console", - "fuzzy-matcher", - "shell-words", - "tempfile", - "zeroize", -] - -[[package]] -name = "encode_unicode" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a357d28ed41a50f9c765dbfe56cbc04a64e53e5fc58ba79fbc34c10ef3df831f" - -[[package]] -name = "errno" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" -dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.45.0", -] - -[[package]] -name = "errno-dragonfly" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" -dependencies = [ - "cc", - "libc", -] - -[[package]] -name = "fastrand" -version = "1.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] - -[[package]] -name = "fuzzy-matcher" -version = "0.3.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54614a3312934d066701a80f20f15fa3b56d67ac7722b39eea5b4c9dd1d66c94" -dependencies = [ - "thread_local", -] - -[[package]] -name = "hermit-abi" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" - -[[package]] -name = "instant" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" -dependencies = [ - "cfg-if", -] - -[[package]] -name = "io-lifetimes" -version = "1.0.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c66c74d2ae7e79a5a8f7ac924adbe38ee42a859c6539ad869eb51f0b52dc220" -dependencies = [ - "hermit-abi", - "libc", - "windows-sys 0.48.0", -] - -[[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.141" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" - -[[package]] -name = "linux-raw-sys" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" - -[[package]] -name = "once_cell" -version = "1.17.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" - -[[package]] -name = "redox_syscall" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" -dependencies = [ - "bitflags", -] - -[[package]] -name = "rustix" -version = "0.37.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aef160324be24d31a62147fae491c14d2204a3865c7ca8c3b0d7f7bcb3ea635" -dependencies = [ - "bitflags", - "errno", - "io-lifetimes", - "libc", - "linux-raw-sys", - "windows-sys 0.48.0", -] - -[[package]] -name = "shell-words" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" - -[[package]] -name = "tempfile" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" -dependencies = [ - "cfg-if", - "fastrand", - "redox_syscall", - "rustix", - "windows-sys 0.45.0", -] - -[[package]] -name = "thread_local" -version = "1.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3fdd6f064ccff2d6567adcb3873ca630700f00b5ad3f060c25b5dcfd9a4ce152" -dependencies = [ - "cfg-if", - "once_cell", -] - -[[package]] -name = "unicode-width" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" - -[[package]] -name = "windows-sys" -version = "0.42.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.45.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" -dependencies = [ - "windows-targets 0.42.2", -] - -[[package]] -name = "windows-sys" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" -dependencies = [ - "windows-targets 0.48.0", -] - -[[package]] -name = "windows-targets" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" -dependencies = [ - "windows_aarch64_gnullvm 0.42.2", - "windows_aarch64_msvc 0.42.2", - "windows_i686_gnu 0.42.2", - "windows_i686_msvc 0.42.2", - "windows_x86_64_gnu 0.42.2", - "windows_x86_64_gnullvm 0.42.2", - "windows_x86_64_msvc 0.42.2", -] - -[[package]] -name = "windows-targets" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b1eb6f0cd7c80c79759c929114ef071b87354ce476d9d94271031c0497adfd5" -dependencies = [ - "windows_aarch64_gnullvm 0.48.0", - "windows_aarch64_msvc 0.48.0", - "windows_i686_gnu 0.48.0", - "windows_i686_msvc 0.48.0", - "windows_x86_64_gnu 0.48.0", - "windows_x86_64_gnullvm 0.48.0", - "windows_x86_64_msvc 0.48.0", -] - -[[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_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" - -[[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_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" - -[[package]] -name = "windows_i686_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" - -[[package]] -name = "windows_i686_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" - -[[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_gnu" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" - -[[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_gnullvm" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.42.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.48.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" - -[[package]] -name = "zeroize" -version = "1.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" diff --git a/vendor/dialoguer/Cargo.toml b/vendor/dialoguer/Cargo.toml deleted file mode 100644 index 9c50fe5..0000000 --- a/vendor/dialoguer/Cargo.toml +++ /dev/null @@ -1,83 +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" -name = "dialoguer" -version = "0.10.4" -authors = [ - "Armin Ronacher <armin.ronacher@active-4.com>", - "Pavan Kumar Sunkara <pavan.sss1991@gmail.com>", -] -description = "A command line prompting library." -homepage = "https://github.com/mitsuhiko/dialoguer" -documentation = "https://docs.rs/dialoguer" -readme = "README.md" -keywords = [ - "cli", - "menu", - "prompt", -] -categories = ["command-line-interface"] -license = "MIT" -repository = "https://github.com/mitsuhiko/dialoguer" - -[package.metadata.docs.rs] -all-features = true - -[[example]] -name = "password" -required-features = ["password"] - -[[example]] -name = "editor" -required-features = ["editor"] - -[[example]] -name = "fuzzyselect" -required-features = ["fuzzy-select"] - -[[example]] -name = "history" -required-features = ["history"] - -[[example]] -name = "completion" -required-features = ["completion"] - -[dependencies.console] -version = "0.15.0" - -[dependencies.fuzzy-matcher] -version = "0.3.7" -optional = true - -[dependencies.shell-words] -version = "1.1.0" - -[dependencies.tempfile] -version = "3" -optional = true - -[dependencies.zeroize] -version = "1.1.1" -optional = true - -[features] -completion = [] -default = [ - "editor", - "password", -] -editor = ["tempfile"] -fuzzy-select = ["fuzzy-matcher"] -history = [] -password = ["zeroize"] diff --git a/vendor/dialoguer/LICENSE b/vendor/dialoguer/LICENSE deleted file mode 100644 index dc9a85c..0000000 --- a/vendor/dialoguer/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/dialoguer/Makefile b/vendor/dialoguer/Makefile deleted file mode 100644 index 6d25c8a..0000000 --- a/vendor/dialoguer/Makefile +++ /dev/null @@ -1,30 +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 - -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 - -.PHONY: all doc build check test format format-check lint diff --git a/vendor/dialoguer/README.md b/vendor/dialoguer/README.md deleted file mode 100644 index 2eb7ede..0000000 --- a/vendor/dialoguer/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# dialoguer - -[![Build Status](https://github.com/console-rs/dialoguer/workflows/CI/badge.svg)](https://github.com/console-rs/dialoguer/actions?query=branch%3Amaster) -[![Latest version](https://img.shields.io/crates/v/dialoguer.svg)](https://crates.io/crates/dialoguer) -[![Documentation](https://docs.rs/dialoguer/badge.svg)](https://docs.rs/dialoguer) - -A rust library for command line prompts and similar things. - -Best paired with other libraries in the family: - -* [console](https://github.com/console-rs/console) -* [indicatif](https://github.com/console-rs/indicatif) - -## License and Links - -* [Documentation](https://docs.rs/dialoguer/) -* [Issue Tracker](https://github.com/console-rs/dialoguer/issues) -* [Examples](https://github.com/console-rs/dialoguer/tree/master/examples) -* License: [MIT](https://github.com/console-rs/dialoguer/blob/main/LICENSE) diff --git a/vendor/dialoguer/examples/buffered.rs b/vendor/dialoguer/examples/buffered.rs deleted file mode 100644 index 96f62bd..0000000 --- a/vendor/dialoguer/examples/buffered.rs +++ /dev/null @@ -1,42 +0,0 @@ -use console::Term; -use dialoguer::{theme::ColorfulTheme, Confirm, Input, MultiSelect, Select, Sort}; - -fn main() { - let items = &[ - "Ice Cream", - "Vanilla Cupcake", - "Chocolate Muffin", - "A Pile of sweet, sweet mustard", - ]; - let term = Term::buffered_stderr(); - let theme = ColorfulTheme::default(); - - println!("All the following controls are run in a buffered terminal"); - Confirm::with_theme(&theme) - .with_prompt("Do you want to continue?") - .interact_on(&term) - .unwrap(); - - let _: String = Input::with_theme(&theme) - .with_prompt("Your name") - .interact_on(&term) - .unwrap(); - - Select::with_theme(&theme) - .with_prompt("Pick an item") - .items(items) - .interact_on(&term) - .unwrap(); - - MultiSelect::with_theme(&theme) - .with_prompt("Pick some items") - .items(items) - .interact_on(&term) - .unwrap(); - - Sort::with_theme(&theme) - .with_prompt("Order these items") - .items(items) - .interact_on(&term) - .unwrap(); -} diff --git a/vendor/dialoguer/examples/completion.rs b/vendor/dialoguer/examples/completion.rs deleted file mode 100644 index 76d790b..0000000 --- a/vendor/dialoguer/examples/completion.rs +++ /dev/null @@ -1,44 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, Completion, Input}; - -fn main() -> Result<(), std::io::Error> { - println!("Use the Right arrow or Tab to complete your command"); - let completion = MyCompletion::default(); - Input::<String>::with_theme(&ColorfulTheme::default()) - .with_prompt("dialoguer") - .completion_with(&completion) - .interact_text()?; - Ok(()) -} - -struct MyCompletion { - options: Vec<String>, -} - -impl Default for MyCompletion { - fn default() -> Self { - MyCompletion { - options: vec![ - "orange".to_string(), - "apple".to_string(), - "banana".to_string(), - ], - } - } -} - -impl Completion for MyCompletion { - /// Simple completion implementation based on substring - fn get(&self, input: &str) -> Option<String> { - let matches = self - .options - .iter() - .filter(|option| option.starts_with(input)) - .collect::<Vec<_>>(); - - if matches.len() == 1 { - Some(matches[0].to_string()) - } else { - None - } - } -} diff --git a/vendor/dialoguer/examples/confirm.rs b/vendor/dialoguer/examples/confirm.rs deleted file mode 100644 index 3b1d3ca..0000000 --- a/vendor/dialoguer/examples/confirm.rs +++ /dev/null @@ -1,70 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, Confirm}; - -fn main() { - if Confirm::with_theme(&ColorfulTheme::default()) - .with_prompt("Do you want to continue?") - .interact() - .unwrap() - { - println!("Looks like you want to continue"); - } else { - println!("nevermind then :("); - } - - if Confirm::with_theme(&ColorfulTheme::default()) - .with_prompt("Do you really want to continue?") - .default(true) - .interact() - .unwrap() - { - println!("Looks like you want to continue"); - } else { - println!("nevermind then :("); - } - - if Confirm::with_theme(&ColorfulTheme::default()) - .with_prompt("Do you really really want to continue?") - .default(true) - .show_default(false) - .wait_for_newline(true) - .interact() - .unwrap() - { - println!("Looks like you want to continue"); - } else { - println!("nevermind then :("); - } - - if Confirm::with_theme(&ColorfulTheme::default()) - .with_prompt("Do you really really really want to continue?") - .wait_for_newline(true) - .interact() - .unwrap() - { - println!("Looks like you want to continue"); - } else { - println!("nevermind then :("); - } - - match Confirm::with_theme(&ColorfulTheme::default()) - .with_prompt("Do you really really really really want to continue?") - .interact_opt() - .unwrap() - { - Some(true) => println!("Looks like you want to continue"), - Some(false) => println!("nevermind then :("), - None => println!("Ok, we can start over later"), - } - - match Confirm::with_theme(&ColorfulTheme::default()) - .with_prompt("Do you really really really really really want to continue?") - .default(true) - .wait_for_newline(true) - .interact_opt() - .unwrap() - { - Some(true) => println!("Looks like you want to continue"), - Some(false) => println!("nevermind then :("), - None => println!("Ok, we can start over later"), - } -} diff --git a/vendor/dialoguer/examples/editor.rs b/vendor/dialoguer/examples/editor.rs deleted file mode 100644 index 5cc21db..0000000 --- a/vendor/dialoguer/examples/editor.rs +++ /dev/null @@ -1,10 +0,0 @@ -use dialoguer::Editor; - -fn main() { - if let Some(rv) = Editor::new().edit("Enter a commit message").unwrap() { - println!("Your message:"); - println!("{}", rv); - } else { - println!("Abort!"); - } -} diff --git a/vendor/dialoguer/examples/fuzzyselect.rs b/vendor/dialoguer/examples/fuzzyselect.rs deleted file mode 100644 index 144d8b6..0000000 --- a/vendor/dialoguer/examples/fuzzyselect.rs +++ /dev/null @@ -1,43 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, FuzzySelect}; - -fn main() { - let selections = &[ - "Ice Cream", - "Vanilla Cupcake", - "Chocolate Muffin", - "A Pile of sweet, sweet mustard", - "Carrots", - "Peas", - "Pistacio", - "Mustard", - "Cream", - "Banana", - "Chocolate", - "Flakes", - "Corn", - "Cake", - "Tarte", - "Cheddar", - "Vanilla", - "Hazelnut", - "Flour", - "Sugar", - "Salt", - "Potato", - "French Fries", - "Pizza", - "Mousse au chocolat", - "Brown sugar", - "Blueberry", - "Burger", - ]; - - let selection = FuzzySelect::with_theme(&ColorfulTheme::default()) - .with_prompt("Pick your flavor") - .default(0) - .items(&selections[..]) - .interact() - .unwrap(); - - println!("Enjoy your {}!", selections[selection]); -} diff --git a/vendor/dialoguer/examples/history.rs b/vendor/dialoguer/examples/history.rs deleted file mode 100644 index 0d69b27..0000000 --- a/vendor/dialoguer/examples/history.rs +++ /dev/null @@ -1,51 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, History, Input}; -use std::{collections::VecDeque, process}; - -fn main() { - println!("Use 'exit' to quit the prompt"); - println!("In this example, history is limited to 4 entries"); - println!("Use the Up/Down arrows to scroll through history"); - println!(); - - let mut history = MyHistory::default(); - - loop { - if let Ok(cmd) = Input::<String>::with_theme(&ColorfulTheme::default()) - .with_prompt("dialoguer") - .history_with(&mut history) - .interact_text() - { - if cmd == "exit" { - process::exit(0); - } - println!("Entered {}", cmd); - } - } -} - -struct MyHistory { - max: usize, - history: VecDeque<String>, -} - -impl Default for MyHistory { - fn default() -> Self { - MyHistory { - max: 4, - history: VecDeque::new(), - } - } -} - -impl<T: ToString> History<T> for MyHistory { - fn read(&self, pos: usize) -> Option<String> { - self.history.get(pos).cloned() - } - - fn write(&mut self, val: &T) { - if self.history.len() == self.max { - self.history.pop_back(); - } - self.history.push_front(val.to_string()); - } -} diff --git a/vendor/dialoguer/examples/input.rs b/vendor/dialoguer/examples/input.rs deleted file mode 100644 index 8691c2e..0000000 --- a/vendor/dialoguer/examples/input.rs +++ /dev/null @@ -1,44 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, Input}; - -fn main() { - let input: String = Input::with_theme(&ColorfulTheme::default()) - .with_prompt("Your name") - .interact_text() - .unwrap(); - - println!("Hello {}!", input); - - let mail: String = Input::with_theme(&ColorfulTheme::default()) - .with_prompt("Your email") - .validate_with({ - let mut force = None; - move |input: &String| -> Result<(), &str> { - if input.contains('@') || force.as_ref().map_or(false, |old| old == input) { - Ok(()) - } else { - force = Some(input.clone()); - Err("This is not a mail address; type the same value again to force use") - } - } - }) - .interact_text() - .unwrap(); - - println!("Email: {}", mail); - - let mail: String = Input::with_theme(&ColorfulTheme::default()) - .with_prompt("Your planet") - .default("Earth".to_string()) - .interact_text() - .unwrap(); - - println!("Planet: {}", mail); - - let mail: String = Input::with_theme(&ColorfulTheme::default()) - .with_prompt("Your galaxy") - .with_initial_text("Milky Way".to_string()) - .interact_text() - .unwrap(); - - println!("Galaxy: {}", mail); -} diff --git a/vendor/dialoguer/examples/multi_select.rs b/vendor/dialoguer/examples/multi_select.rs deleted file mode 100644 index 97d3bae..0000000 --- a/vendor/dialoguer/examples/multi_select.rs +++ /dev/null @@ -1,42 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, MultiSelect}; - -fn main() { - let multiselected = &[ - "Ice Cream", - "Vanilla Cupcake", - "Chocolate Muffin", - "A Pile of sweet, sweet mustard", - ]; - let defaults = &[false, false, true, false]; - let selections = MultiSelect::with_theme(&ColorfulTheme::default()) - .with_prompt("Pick your food") - .items(&multiselected[..]) - .defaults(&defaults[..]) - .interact() - .unwrap(); - - if selections.is_empty() { - println!("You did not select anything :("); - } else { - println!("You selected these things:"); - for selection in selections { - println!(" {}", multiselected[selection]); - } - } - - let selections = MultiSelect::with_theme(&ColorfulTheme::default()) - .with_prompt("Pick your food") - .items(&multiselected[..]) - .defaults(&defaults[..]) - .max_length(2) - .interact() - .unwrap(); - if selections.is_empty() { - println!("You did not select anything :("); - } else { - println!("You selected these things:"); - for selection in selections { - println!(" {}", multiselected[selection]); - } - } -} diff --git a/vendor/dialoguer/examples/paging.rs b/vendor/dialoguer/examples/paging.rs deleted file mode 100644 index 63f9726..0000000 --- a/vendor/dialoguer/examples/paging.rs +++ /dev/null @@ -1,43 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, Select}; - -fn main() { - let selections = &[ - "Ice Cream", - "Vanilla Cupcake", - "Chocolate Muffin", - "A Pile of sweet, sweet mustard", - "Carrots", - "Peas", - "Pistacio", - "Mustard", - "Cream", - "Banana", - "Chocolate", - "Flakes", - "Corn", - "Cake", - "Tarte", - "Cheddar", - "Vanilla", - "Hazelnut", - "Flour", - "Sugar", - "Salt", - "Potato", - "French Fries", - "Pizza", - "Mousse au chocolat", - "Brown sugar", - "Blueberry", - "Burger", - ]; - - let selection = Select::with_theme(&ColorfulTheme::default()) - .with_prompt("Pick your flavor") - .default(0) - .items(&selections[..]) - .interact() - .unwrap(); - - println!("Enjoy your {}!", selections[selection]); -} diff --git a/vendor/dialoguer/examples/password.rs b/vendor/dialoguer/examples/password.rs deleted file mode 100644 index d85df1b..0000000 --- a/vendor/dialoguer/examples/password.rs +++ /dev/null @@ -1,18 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, Password}; - -fn main() { - let password = Password::with_theme(&ColorfulTheme::default()) - .with_prompt("Password") - .with_confirmation("Repeat password", "Error: the passwords don't match.") - .validate_with(|input: &String| -> Result<(), &str> { - if input.len() > 3 { - Ok(()) - } else { - Err("Password must be longer than 3") - } - }) - .interact() - .unwrap(); - - println!("Your password is {} characters long", password.len()); -} diff --git a/vendor/dialoguer/examples/select.rs b/vendor/dialoguer/examples/select.rs deleted file mode 100644 index 3382e8b..0000000 --- a/vendor/dialoguer/examples/select.rs +++ /dev/null @@ -1,42 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, Select}; - -fn main() { - let selections = &[ - "Ice Cream", - "Vanilla Cupcake", - "Chocolate Muffin", - "A Pile of sweet, sweet mustard", - ]; - - let selection = Select::with_theme(&ColorfulTheme::default()) - .with_prompt("Pick your flavor") - .default(0) - .items(&selections[..]) - .interact() - .unwrap(); - - println!("Enjoy your {}!", selections[selection]); - - let selection = Select::with_theme(&ColorfulTheme::default()) - .with_prompt("Optionally pick your flavor") - .default(0) - .items(&selections[..]) - .interact_opt() - .unwrap(); - - if let Some(selection) = selection { - println!("Enjoy your {}!", selections[selection]); - } else { - println!("You didn't select anything!"); - } - - let selection = Select::with_theme(&ColorfulTheme::default()) - .with_prompt("Optionally pick your flavor, hint it might be on the second page") - .default(0) - .max_length(2) - .items(&selections[..]) - .interact() - .unwrap(); - - println!("Enjoy your {}!", selections[selection]); -} diff --git a/vendor/dialoguer/examples/sort.rs b/vendor/dialoguer/examples/sort.rs deleted file mode 100644 index ae920aa..0000000 --- a/vendor/dialoguer/examples/sort.rs +++ /dev/null @@ -1,32 +0,0 @@ -use dialoguer::{theme::ColorfulTheme, Sort}; - -fn main() { - let list = &[ - "Ice Cream", - "Vanilla Cupcake", - "Chocolate Muffin", - "A Pile of sweet, sweet mustard", - ]; - let sorted = Sort::with_theme(&ColorfulTheme::default()) - .with_prompt("Order your foods by preference") - .items(&list[..]) - .interact() - .unwrap(); - - println!("Your favorite item:"); - println!(" {}", list[sorted[0]]); - println!("Your least favorite item:"); - println!(" {}", list[sorted[sorted.len() - 1]]); - - let sorted = Sort::with_theme(&ColorfulTheme::default()) - .with_prompt("Order your foods by preference") - .items(&list[..]) - .max_length(2) - .interact() - .unwrap(); - - println!("Your favorite item:"); - println!(" {}", list[sorted[0]]); - println!("Your least favorite item:"); - println!(" {}", list[sorted[sorted.len() - 1]]); -} diff --git a/vendor/dialoguer/examples/wizard.rs b/vendor/dialoguer/examples/wizard.rs deleted file mode 100644 index b914032..0000000 --- a/vendor/dialoguer/examples/wizard.rs +++ /dev/null @@ -1,81 +0,0 @@ -use std::error::Error; -use std::net::IpAddr; - -use console::Style; -use dialoguer::{theme::ColorfulTheme, Confirm, Input, Select}; - -#[derive(Debug)] -#[allow(dead_code)] -struct Config { - interface: IpAddr, - hostname: String, - use_acme: bool, - private_key: Option<String>, - cert: Option<String>, -} - -fn init_config() -> Result<Option<Config>, Box<dyn Error>> { - let theme = ColorfulTheme { - values_style: Style::new().yellow().dim(), - ..ColorfulTheme::default() - }; - println!("Welcome to the setup wizard"); - - if !Confirm::with_theme(&theme) - .with_prompt("Do you want to continue?") - .interact()? - { - return Ok(None); - } - - let interface = Input::with_theme(&theme) - .with_prompt("Interface") - .default("127.0.0.1".parse().unwrap()) - .interact()?; - - let hostname = Input::with_theme(&theme) - .with_prompt("Hostname") - .interact()?; - - let tls = Select::with_theme(&theme) - .with_prompt("Configure TLS") - .default(0) - .item("automatic with ACME") - .item("manual") - .item("no") - .interact()?; - - let (private_key, cert, use_acme) = match tls { - 0 => (Some("acme.pkey".into()), Some("acme.cert".into()), true), - 1 => ( - Some( - Input::with_theme(&theme) - .with_prompt(" Path to private key") - .interact()?, - ), - Some( - Input::with_theme(&theme) - .with_prompt(" Path to certificate") - .interact()?, - ), - false, - ), - _ => (None, None, false), - }; - - Ok(Some(Config { - hostname, - interface, - private_key, - cert, - use_acme, - })) -} - -fn main() { - match init_config() { - Ok(None) => println!("Aborted."), - Ok(Some(config)) => println!("{:#?}", config), - Err(err) => println!("error: {}", err), - } -} diff --git a/vendor/dialoguer/src/completion.rs b/vendor/dialoguer/src/completion.rs deleted file mode 100644 index 98c2a9c..0000000 --- a/vendor/dialoguer/src/completion.rs +++ /dev/null @@ -1,4 +0,0 @@ -/// Trait for completion handling. -pub trait Completion { - fn get(&self, input: &str) -> Option<String>; -} diff --git a/vendor/dialoguer/src/edit.rs b/vendor/dialoguer/src/edit.rs deleted file mode 100644 index f69844c..0000000 --- a/vendor/dialoguer/src/edit.rs +++ /dev/null @@ -1,131 +0,0 @@ -use std::{ - env, - ffi::{OsStr, OsString}, - fs, io, - io::{Read, Write}, - process, -}; - -/// Launches the default editor to edit a string. -/// -/// ## Example -/// -/// ```rust,no_run -/// use dialoguer::Editor; -/// -/// if let Some(rv) = Editor::new().edit("Enter a commit message").unwrap() { -/// println!("Your message:"); -/// println!("{}", rv); -/// } else { -/// println!("Abort!"); -/// } -/// ``` -pub struct Editor { - editor: OsString, - extension: String, - require_save: bool, - trim_newlines: bool, -} - -fn get_default_editor() -> OsString { - if let Some(prog) = env::var_os("VISUAL") { - return prog; - } - if let Some(prog) = env::var_os("EDITOR") { - return prog; - } - if cfg!(windows) { - "notepad.exe".into() - } else { - "vi".into() - } -} - -impl Default for Editor { - fn default() -> Self { - Self::new() - } -} - -impl Editor { - /// Creates a new editor. - pub fn new() -> Self { - Self { - editor: get_default_editor(), - extension: ".txt".into(), - require_save: true, - trim_newlines: true, - } - } - - /// Sets a specific editor executable. - pub fn executable<S: AsRef<OsStr>>(&mut self, val: S) -> &mut Self { - self.editor = val.as_ref().into(); - self - } - - /// Sets a specific extension - pub fn extension(&mut self, val: &str) -> &mut Self { - self.extension = val.into(); - self - } - - /// Enables or disables the save requirement. - pub fn require_save(&mut self, val: bool) -> &mut Self { - self.require_save = val; - self - } - - /// Enables or disables trailing newline stripping. - /// - /// This is on by default. - pub fn trim_newlines(&mut self, val: bool) -> &mut Self { - self.trim_newlines = val; - self - } - - /// Launches the editor to edit a string. - /// - /// Returns `None` if the file was not saved or otherwise the - /// entered text. - pub fn edit(&self, s: &str) -> io::Result<Option<String>> { - let mut f = tempfile::Builder::new() - .prefix("edit-") - .suffix(&self.extension) - .rand_bytes(12) - .tempfile()?; - f.write_all(s.as_bytes())?; - f.flush()?; - let ts = fs::metadata(f.path())?.modified()?; - - let s: String = self.editor.clone().into_string().unwrap(); - let (cmd, args) = match shell_words::split(&s) { - Ok(mut parts) => { - let cmd = parts.remove(0); - (cmd, parts) - } - Err(_) => (s, vec![]), - }; - - let rv = process::Command::new(cmd) - .args(args) - .arg(f.path()) - .spawn()? - .wait()?; - - if rv.success() && self.require_save && ts >= fs::metadata(f.path())?.modified()? { - return Ok(None); - } - - let mut new_f = fs::File::open(f.path())?; - let mut rv = String::new(); - new_f.read_to_string(&mut rv)?; - - if self.trim_newlines { - let len = rv.trim_end_matches(&['\n', '\r'][..]).len(); - rv.truncate(len); - } - - Ok(Some(rv)) - } -} diff --git a/vendor/dialoguer/src/history.rs b/vendor/dialoguer/src/history.rs deleted file mode 100644 index d0818cc..0000000 --- a/vendor/dialoguer/src/history.rs +++ /dev/null @@ -1,15 +0,0 @@ -/// Trait for history handling. -pub trait History<T> { - /// This is called with the current position that should - /// be read from history. The `pos` represents the number - /// of times the `Up`/`Down` arrow key has been pressed. - /// This would normally be used as an index to some sort - /// of vector. If the `pos` does not have an entry, [`None`](Option::None) - /// should be returned. - fn read(&self, pos: usize) -> Option<String>; - - /// This is called with the next value you should store - /// in history at the first location. Normally history - /// is implemented as a FIFO queue. - fn write(&mut self, val: &T); -} diff --git a/vendor/dialoguer/src/lib.rs b/vendor/dialoguer/src/lib.rs deleted file mode 100644 index cd8e307..0000000 --- a/vendor/dialoguer/src/lib.rs +++ /dev/null @@ -1,62 +0,0 @@ -//! dialoguer is a library for Rust that helps you build useful small -//! interactive user inputs for the command line. It provides utilities -//! to render various simple dialogs like confirmation prompts, text -//! inputs and more. -//! -//! Best paired with other libraries in the family: -//! -//! * [indicatif](https://docs.rs/indicatif) -//! * [console](https://docs.rs/console) -//! -//! # Crate Contents -//! -//! * Confirmation prompts -//! * Input prompts (regular and password) -//! * Input validation -//! * Selections prompts (single and multi) -//! * Fuzzy select prompt -//! * Other kind of prompts -//! * Editor launching -//! -//! # Crate Features -//! -//! The following crate features are available: -//! * `editor`: enables bindings to launch editor to edit strings -//! * `fuzzy-select`: enables fuzzy select prompt -//! * `history`: enables input prompts to be able to track history of inputs -//! * `password`: enables password input prompt -//! * `completion`: enables ability to implement custom tab-completion for input prompts -//! -//! By default `editor` and `password` are enabled. - -#![deny(clippy::all)] - -#[cfg(feature = "completion")] -pub use completion::Completion; -pub use console; -#[cfg(feature = "editor")] -pub use edit::Editor; -#[cfg(feature = "history")] -pub use history::History; -use paging::Paging; -pub use prompts::{ - confirm::Confirm, input::Input, multi_select::MultiSelect, select::Select, sort::Sort, -}; -pub use validate::Validator; - -#[cfg(feature = "fuzzy-select")] -pub use prompts::fuzzy_select::FuzzySelect; - -#[cfg(feature = "password")] -pub use prompts::password::Password; - -#[cfg(feature = "completion")] -mod completion; -#[cfg(feature = "editor")] -mod edit; -#[cfg(feature = "history")] -mod history; -mod paging; -mod prompts; -pub mod theme; -mod validate; diff --git a/vendor/dialoguer/src/paging.rs b/vendor/dialoguer/src/paging.rs deleted file mode 100644 index f85d9b3..0000000 --- a/vendor/dialoguer/src/paging.rs +++ /dev/null @@ -1,118 +0,0 @@ -use std::io; - -use console::Term; - -/// Creates a paging module -/// -/// The paging module serves as tracking structure to allow paged views -/// and automatically (de-)activates paging depending on the current terminal size. -pub struct Paging<'a> { - pub pages: usize, - pub current_page: usize, - pub capacity: usize, - pub active: bool, - pub max_capacity: Option<usize>, - term: &'a Term, - current_term_size: (u16, u16), - items_len: usize, - activity_transition: bool, -} - -impl<'a> Paging<'a> { - pub fn new(term: &'a Term, items_len: usize, max_capacity: Option<usize>) -> Paging<'a> { - let term_size = term.size(); - // Subtract -2 because we need space to render the prompt, if paging is active - let capacity = max_capacity - .unwrap_or(std::usize::MAX) - .clamp(3, term_size.0 as usize) - - 2; - let pages = (items_len as f64 / capacity as f64).ceil() as usize; - - Paging { - pages, - current_page: 0, - capacity, - active: pages > 1, - term, - current_term_size: term_size, - items_len, - max_capacity, - // Set transition initially to true to trigger prompt rendering for inactive paging on start - activity_transition: true, - } - } - - /// Updates all internal based on the current terminal size and cursor position - pub fn update(&mut self, cursor_pos: usize) -> io::Result<()> { - let new_term_size = self.term.size(); - - if self.current_term_size != new_term_size { - self.current_term_size = new_term_size; - self.capacity = self - .max_capacity - .unwrap_or(std::usize::MAX) - .clamp(3, self.current_term_size.0 as usize) - - 2; - self.pages = (self.items_len as f64 / self.capacity as f64).ceil() as usize; - } - - if self.active == (self.pages > 1) { - self.activity_transition = false; - } else { - self.active = self.pages > 1; - self.activity_transition = true; - // Clear everything to prevent "ghost" lines in terminal when a resize happened - self.term.clear_last_lines(self.capacity)?; - } - - if cursor_pos != !0 - && (cursor_pos < self.current_page * self.capacity - || cursor_pos >= (self.current_page + 1) * self.capacity) - { - self.current_page = cursor_pos / self.capacity; - } - - Ok(()) - } - - /// Renders a prompt when the following conditions are met: - /// * Paging is active - /// * Transition of the paging activity happened (active -> inactive / inactive -> active) - pub fn render_prompt<F>(&mut self, mut render_prompt: F) -> io::Result<()> - where - F: FnMut(Option<(usize, usize)>) -> io::Result<()>, - { - if self.active { - let paging_info = Some((self.current_page + 1, self.pages)); - render_prompt(paging_info)?; - } else if self.activity_transition { - render_prompt(None)?; - } - - self.term.flush()?; - - Ok(()) - } - - /// Navigates to the next page - pub fn next_page(&mut self) -> usize { - if self.current_page == self.pages - 1 { - self.current_page = 0; - } else { - self.current_page += 1; - } - - self.current_page * self.capacity - } - - /// Navigates to the previous page - pub fn previous_page(&mut self) -> usize { - if self.current_page == 0 { - self.current_page = self.pages - 1; - } else { - self.current_page -= 1; - } - - self.current_page * self.capacity - } -} diff --git a/vendor/dialoguer/src/prompts/confirm.rs b/vendor/dialoguer/src/prompts/confirm.rs deleted file mode 100644 index 24bcc4c..0000000 --- a/vendor/dialoguer/src/prompts/confirm.rs +++ /dev/null @@ -1,287 +0,0 @@ -use std::io; - -use crate::theme::{SimpleTheme, TermThemeRenderer, Theme}; - -use console::{Key, Term}; - -/// Renders a confirm prompt. -/// -/// ## Example usage -/// -/// ```rust,no_run -/// # fn test() -> Result<(), Box<dyn std::error::Error>> { -/// use dialoguer::Confirm; -/// -/// if Confirm::new().with_prompt("Do you want to continue?").interact()? { -/// println!("Looks like you want to continue"); -/// } else { -/// println!("nevermind then :("); -/// } -/// # Ok(()) } fn main() { test().unwrap(); } -/// ``` -pub struct Confirm<'a> { - prompt: String, - report: bool, - default: Option<bool>, - show_default: bool, - wait_for_newline: bool, - theme: &'a dyn Theme, -} - -impl Default for Confirm<'static> { - fn default() -> Self { - Self::new() - } -} - -impl Confirm<'static> { - /// Creates a confirm prompt. - pub fn new() -> Self { - Self::with_theme(&SimpleTheme) - } -} - -impl Confirm<'_> { - /// Sets the confirm prompt. - pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self { - self.prompt = prompt.into(); - self - } - - /// Indicates whether or not to report the chosen selection after interaction. - /// - /// The default is to report the chosen selection. - pub fn report(&mut self, val: bool) -> &mut Self { - self.report = val; - self - } - - #[deprecated(note = "Use with_prompt() instead", since = "0.6.0")] - #[inline] - pub fn with_text(&mut self, text: &str) -> &mut Self { - self.with_prompt(text) - } - - /// Sets when to react to user input. - /// - /// When `false` (default), we check on each user keystroke immediately as - /// it is typed. Valid inputs can be one of 'y', 'n', or a newline to accept - /// the default. - /// - /// When `true`, the user must type their choice and hit the Enter key before - /// proceeding. Valid inputs can be "yes", "no", "y", "n", or an empty string - /// to accept the default. - pub fn wait_for_newline(&mut self, wait: bool) -> &mut Self { - self.wait_for_newline = wait; - self - } - - /// Sets a default. - /// - /// Out of the box the prompt does not have a default and will continue - /// to display until the user inputs something and hits enter. If a default is set the user - /// can instead accept the default with enter. - pub fn default(&mut self, val: bool) -> &mut Self { - self.default = Some(val); - self - } - - /// Disables or enables the default value display. - /// - /// The default is to append the default value to the prompt to tell the user. - pub fn show_default(&mut self, val: bool) -> &mut Self { - self.show_default = val; - self - } - - /// Enables user interaction and returns the result. - /// - /// The dialog is rendered on stderr. - /// - /// Result contains `bool` if user answered "yes" or "no" or `default` (configured in [`default`](Self::default) if pushes enter. - /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'. - #[inline] - pub fn interact(&self) -> io::Result<bool> { - self.interact_on(&Term::stderr()) - } - - /// Enables user interaction and returns the result. - /// - /// The dialog is rendered on stderr. - /// - /// Result contains `Some(bool)` if user answered "yes" or "no" or `Some(default)` (configured in [`default`](Self::default)) if pushes enter, - /// or `None` if user cancelled with 'Esc' or 'q'. - #[inline] - pub fn interact_opt(&self) -> io::Result<Option<bool>> { - self.interact_on_opt(&Term::stderr()) - } - - /// Like [interact](#method.interact) but allows a specific terminal to be set. - /// - /// ## Examples - /// - /// ```rust,no_run - /// use dialoguer::Confirm; - /// use console::Term; - /// - /// # fn main() -> std::io::Result<()> { - /// let proceed = Confirm::new() - /// .with_prompt("Do you wish to continue?") - /// .interact_on(&Term::stderr())?; - /// # Ok(()) - /// # } - /// ``` - #[inline] - pub fn interact_on(&self, term: &Term) -> io::Result<bool> { - self._interact_on(term, false)? - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case")) - } - - /// Like [`interact_opt`](Self::interact_opt) but allows a specific terminal to be set. - /// - /// ## Examples - /// ```rust,no_run - /// use dialoguer::Confirm; - /// use console::Term; - /// - /// fn main() -> std::io::Result<()> { - /// let confirmation = Confirm::new() - /// .interact_on_opt(&Term::stdout())?; - /// - /// match confirmation { - /// Some(answer) => println!("User answered {}", if answer { "yes" } else { "no " }), - /// None => println!("User did not answer") - /// } - /// - /// Ok(()) - /// } - /// ``` - #[inline] - pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<bool>> { - self._interact_on(term, true) - } - - fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<bool>> { - let mut render = TermThemeRenderer::new(term, self.theme); - - let default_if_show = if self.show_default { - self.default - } else { - None - }; - - render.confirm_prompt(&self.prompt, default_if_show)?; - - term.hide_cursor()?; - term.flush()?; - - let rv; - - if self.wait_for_newline { - // Waits for user input and for the user to hit the Enter key - // before validation. - let mut value = default_if_show; - - loop { - let input = term.read_key()?; - - match input { - Key::Char('y') | Key::Char('Y') => { - value = Some(true); - } - Key::Char('n') | Key::Char('N') => { - value = Some(false); - } - Key::Enter => { - if !allow_quit { - value = value.or(self.default); - } - - if value.is_some() || allow_quit { - rv = value; - break; - } - continue; - } - Key::Escape | Key::Char('q') if allow_quit => { - value = None; - } - Key::Unknown => { - return Err(io::Error::new( - io::ErrorKind::NotConnected, - "Not a terminal", - )) - } - _ => { - continue; - } - }; - - term.clear_line()?; - render.confirm_prompt(&self.prompt, value)?; - } - } else { - // Default behavior: matches continuously on every keystroke, - // and does not wait for user to hit the Enter key. - loop { - let input = term.read_key()?; - let value = match input { - Key::Char('y') | Key::Char('Y') => Some(true), - Key::Char('n') | Key::Char('N') => Some(false), - Key::Enter if self.default.is_some() => Some(self.default.unwrap()), - Key::Escape | Key::Char('q') if allow_quit => None, - Key::Unknown => { - return Err(io::Error::new( - io::ErrorKind::NotConnected, - "Not a terminal", - )) - } - _ => { - continue; - } - }; - - rv = value; - break; - } - } - - term.clear_line()?; - if self.report { - render.confirm_prompt_selection(&self.prompt, rv)?; - } - term.show_cursor()?; - term.flush()?; - - Ok(rv) - } -} - -impl<'a> Confirm<'a> { - /// Creates a confirm prompt with a specific theme. - /// - /// ## Examples - /// ```rust,no_run - /// use dialoguer::{ - /// Confirm, - /// theme::ColorfulTheme - /// }; - /// - /// # fn main() -> std::io::Result<()> { - /// let proceed = Confirm::with_theme(&ColorfulTheme::default()) - /// .with_prompt("Do you wish to continue?") - /// .interact()?; - /// # Ok(()) - /// # } - /// ``` - pub fn with_theme(theme: &'a dyn Theme) -> Self { - Self { - prompt: "".into(), - report: true, - default: None, - show_default: true, - wait_for_newline: false, - theme, - } - } -} diff --git a/vendor/dialoguer/src/prompts/fuzzy_select.rs b/vendor/dialoguer/src/prompts/fuzzy_select.rs deleted file mode 100644 index 9b7f992..0000000 --- a/vendor/dialoguer/src/prompts/fuzzy_select.rs +++ /dev/null @@ -1,326 +0,0 @@ -use crate::theme::{SimpleTheme, TermThemeRenderer, Theme}; -use console::{Key, Term}; -use fuzzy_matcher::FuzzyMatcher; -use std::{io, ops::Rem}; - -/// Renders a selection menu that user can fuzzy match to reduce set. -/// -/// User can use fuzzy search to limit selectable items. -/// Interaction returns index of an item selected in the order they appear in `item` invocation or `items` slice. -/// -/// ## Examples -/// -/// ```rust,no_run -/// use dialoguer::{ -/// FuzzySelect, -/// theme::ColorfulTheme -/// }; -/// use console::Term; -/// -/// fn main() -> std::io::Result<()> { -/// let items = vec!["Item 1", "item 2"]; -/// let selection = FuzzySelect::with_theme(&ColorfulTheme::default()) -/// .items(&items) -/// .default(0) -/// .interact_on_opt(&Term::stderr())?; -/// -/// match selection { -/// Some(index) => println!("User selected item : {}", items[index]), -/// None => println!("User did not select anything") -/// } -/// -/// Ok(()) -/// } -/// ``` - -pub struct FuzzySelect<'a> { - default: Option<usize>, - items: Vec<String>, - prompt: String, - report: bool, - clear: bool, - highlight_matches: bool, - max_length: Option<usize>, - theme: &'a dyn Theme, - /// Search string that a fuzzy search with start with. - /// Defaults to an empty string. - initial_text: String, -} - -impl Default for FuzzySelect<'static> { - fn default() -> Self { - Self::new() - } -} - -impl FuzzySelect<'static> { - /// Creates the prompt with a specific text. - pub fn new() -> Self { - Self::with_theme(&SimpleTheme) - } -} - -impl FuzzySelect<'_> { - /// Sets the clear behavior of the menu. - /// - /// The default is to clear the menu. - pub fn clear(&mut self, val: bool) -> &mut Self { - self.clear = val; - self - } - - /// Sets a default for the menu - pub fn default(&mut self, val: usize) -> &mut Self { - self.default = Some(val); - self - } - - /// Add a single item to the fuzzy selector. - pub fn item<T: ToString>(&mut self, item: T) -> &mut Self { - self.items.push(item.to_string()); - self - } - - /// Adds multiple items to the fuzzy selector. - pub fn items<T: ToString>(&mut self, items: &[T]) -> &mut Self { - for item in items { - self.items.push(item.to_string()); - } - self - } - - /// Sets the search text that a fuzzy search starts with. - pub fn with_initial_text<S: Into<String>>(&mut self, initial_text: S) -> &mut Self { - self.initial_text = initial_text.into(); - self - } - - /// Prefaces the menu with a prompt. - /// - /// When a prompt is set the system also prints out a confirmation after - /// the fuzzy selection. - pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self { - self.prompt = prompt.into(); - self - } - - /// Indicates whether to report the selected value after interaction. - /// - /// The default is to report the selection. - pub fn report(&mut self, val: bool) -> &mut Self { - self.report = val; - self - } - - /// Indicates whether to highlight matched indices - /// - /// The default is to highlight the indices - pub fn highlight_matches(&mut self, val: bool) -> &mut Self { - self.highlight_matches = val; - self - } - - /// Sets the maximum number of visible options. - /// - /// The default is the height of the terminal minus 2. - pub fn max_length(&mut self, rows: usize) -> &mut Self { - self.max_length = Some(rows); - self - } - - /// Enables user interaction and returns the result. - /// - /// The user can select the items using 'Enter' and the index of selected item will be returned. - /// The dialog is rendered on stderr. - /// Result contains `index` of selected item if user hit 'Enter'. - /// This unlike [interact_opt](#method.interact_opt) does not allow to quit with 'Esc' or 'q'. - #[inline] - pub fn interact(&self) -> io::Result<usize> { - self.interact_on(&Term::stderr()) - } - - /// Enables user interaction and returns the result. - /// - /// The user can select the items using 'Enter' and the index of selected item will be returned. - /// The dialog is rendered on stderr. - /// Result contains `Some(index)` if user hit 'Enter' or `None` if user cancelled with 'Esc' or 'q'. - #[inline] - pub fn interact_opt(&self) -> io::Result<Option<usize>> { - self.interact_on_opt(&Term::stderr()) - } - - /// Like `interact` but allows a specific terminal to be set. - #[inline] - pub fn interact_on(&self, term: &Term) -> io::Result<usize> { - self._interact_on(term, false)? - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case")) - } - - /// Like `interact` but allows a specific terminal to be set. - #[inline] - pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<usize>> { - self._interact_on(term, true) - } - - /// Like `interact` but allows a specific terminal to be set. - fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<usize>> { - // Place cursor at the end of the search term - let mut position = self.initial_text.len(); - let mut search_term = self.initial_text.to_owned(); - - let mut render = TermThemeRenderer::new(term, self.theme); - let mut sel = self.default; - - let mut size_vec = Vec::new(); - for items in self.items.iter().as_slice() { - let size = &items.len(); - size_vec.push(*size); - } - - // Fuzzy matcher - let matcher = fuzzy_matcher::skim::SkimMatcherV2::default(); - - // Subtract -2 because we need space to render the prompt. - let visible_term_rows = (term.size().0 as usize).max(3) - 2; - let visible_term_rows = self - .max_length - .unwrap_or(visible_term_rows) - .min(visible_term_rows); - // Variable used to determine if we need to scroll through the list. - let mut starting_row = 0; - - term.hide_cursor()?; - - loop { - render.clear()?; - render.fuzzy_select_prompt(self.prompt.as_str(), &search_term, position)?; - - // Maps all items to a tuple of item and its match score. - let mut filtered_list = self - .items - .iter() - .map(|item| (item, matcher.fuzzy_match(item, &search_term))) - .filter_map(|(item, score)| score.map(|s| (item, s))) - .collect::<Vec<_>>(); - - // Renders all matching items, from best match to worst. - filtered_list.sort_unstable_by(|(_, s1), (_, s2)| s2.cmp(s1)); - - for (idx, (item, _)) in filtered_list - .iter() - .enumerate() - .skip(starting_row) - .take(visible_term_rows) - { - render.fuzzy_select_prompt_item( - item, - Some(idx) == sel, - self.highlight_matches, - &matcher, - &search_term, - )?; - } - term.flush()?; - - match (term.read_key()?, sel) { - (Key::Escape, _) if allow_quit => { - if self.clear { - render.clear()?; - term.flush()?; - } - term.show_cursor()?; - return Ok(None); - } - (Key::ArrowUp | Key::BackTab, _) if !filtered_list.is_empty() => { - if sel == Some(0) { - starting_row = - filtered_list.len().max(visible_term_rows) - visible_term_rows; - } else if sel == Some(starting_row) { - starting_row -= 1; - } - sel = match sel { - None => Some(filtered_list.len() - 1), - Some(sel) => Some( - ((sel as i64 - 1 + filtered_list.len() as i64) - % (filtered_list.len() as i64)) - as usize, - ), - }; - term.flush()?; - } - (Key::ArrowDown | Key::Tab, _) if !filtered_list.is_empty() => { - sel = match sel { - None => Some(0), - Some(sel) => { - Some((sel as u64 + 1).rem(filtered_list.len() as u64) as usize) - } - }; - if sel == Some(visible_term_rows + starting_row) { - starting_row += 1; - } else if sel == Some(0) { - starting_row = 0; - } - term.flush()?; - } - (Key::ArrowLeft, _) if position > 0 => { - position -= 1; - term.flush()?; - } - (Key::ArrowRight, _) if position < search_term.len() => { - position += 1; - term.flush()?; - } - (Key::Enter, Some(sel)) if !filtered_list.is_empty() => { - if self.clear { - render.clear()?; - } - - if self.report { - render - .input_prompt_selection(self.prompt.as_str(), filtered_list[sel].0)?; - } - - let sel_string = filtered_list[sel].0; - let sel_string_pos_in_items = - self.items.iter().position(|item| item.eq(sel_string)); - - term.show_cursor()?; - return Ok(sel_string_pos_in_items); - } - (Key::Backspace, _) if position > 0 => { - position -= 1; - search_term.remove(position); - term.flush()?; - } - (Key::Char(chr), _) if !chr.is_ascii_control() => { - search_term.insert(position, chr); - position += 1; - term.flush()?; - sel = Some(0); - starting_row = 0; - } - - _ => {} - } - - render.clear_preserve_prompt(&size_vec)?; - } - } -} - -impl<'a> FuzzySelect<'a> { - /// Same as `new` but with a specific theme. - pub fn with_theme(theme: &'a dyn Theme) -> Self { - Self { - default: None, - items: vec![], - prompt: "".into(), - report: true, - clear: true, - highlight_matches: true, - max_length: None, - theme, - initial_text: "".into(), - } - } -} diff --git a/vendor/dialoguer/src/prompts/input.rs b/vendor/dialoguer/src/prompts/input.rs deleted file mode 100644 index b7cd829..0000000 --- a/vendor/dialoguer/src/prompts/input.rs +++ /dev/null @@ -1,691 +0,0 @@ -use std::{cmp::Ordering, fmt::Debug, io, iter, str::FromStr}; - -#[cfg(feature = "completion")] -use crate::completion::Completion; -#[cfg(feature = "history")] -use crate::history::History; -use crate::{ - theme::{SimpleTheme, TermThemeRenderer, Theme}, - validate::Validator, -}; - -use console::{Key, Term}; - -type ValidatorCallback<'a, T> = Box<dyn FnMut(&T) -> Option<String> + 'a>; - -/// Renders an input prompt. -/// -/// ## Example usage -/// -/// ```rust,no_run -/// use dialoguer::Input; -/// -/// # fn test() -> Result<(), Box<dyn std::error::Error>> { -/// let input : String = Input::new() -/// .with_prompt("Tea or coffee?") -/// .with_initial_text("Yes") -/// .default("No".into()) -/// .interact_text()?; -/// # Ok(()) -/// # } -/// ``` -/// It can also be used with turbofish notation: -/// -/// ```rust,no_run -/// # fn test() -> Result<(), Box<dyn std::error::Error>> { -/// # use dialoguer::Input; -/// let input = Input::<String>::new() -/// .interact_text()?; -/// # Ok(()) -/// # } -/// ``` -pub struct Input<'a, T> { - prompt: String, - post_completion_text: Option<String>, - report: bool, - default: Option<T>, - show_default: bool, - initial_text: Option<String>, - theme: &'a dyn Theme, - permit_empty: bool, - validator: Option<ValidatorCallback<'a, T>>, - #[cfg(feature = "history")] - history: Option<&'a mut dyn History<T>>, - #[cfg(feature = "completion")] - completion: Option<&'a dyn Completion>, -} - -impl<T> Default for Input<'static, T> { - fn default() -> Self { - Self::new() - } -} - -impl<T> Input<'_, T> { - /// Creates an input prompt. - pub fn new() -> Self { - Self::with_theme(&SimpleTheme) - } - - /// Sets the input prompt. - pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self { - self.prompt = prompt.into(); - self - } - - /// Changes the prompt text to the post completion text after input is complete - pub fn with_post_completion_text<S: Into<String>>( - &mut self, - post_completion_text: S, - ) -> &mut Self { - self.post_completion_text = Some(post_completion_text.into()); - self - } - - /// Indicates whether to report the input value after interaction. - /// - /// The default is to report the input value. - pub fn report(&mut self, val: bool) -> &mut Self { - self.report = val; - self - } - - /// Sets initial text that user can accept or erase. - pub fn with_initial_text<S: Into<String>>(&mut self, val: S) -> &mut Self { - self.initial_text = Some(val.into()); - self - } - - /// Sets a default. - /// - /// Out of the box the prompt does not have a default and will continue - /// to display until the user inputs something and hits enter. If a default is set the user - /// can instead accept the default with enter. - pub fn default(&mut self, value: T) -> &mut Self { - self.default = Some(value); - self - } - - /// Enables or disables an empty input - /// - /// By default, if there is no default value set for the input, the user must input a non-empty string. - pub fn allow_empty(&mut self, val: bool) -> &mut Self { - self.permit_empty = val; - self - } - - /// Disables or enables the default value display. - /// - /// The default behaviour is to append [`default`](#method.default) to the prompt to tell the - /// user what is the default value. - /// - /// This method does not affect existence of default value, only its display in the prompt! - pub fn show_default(&mut self, val: bool) -> &mut Self { - self.show_default = val; - self - } -} - -impl<'a, T> Input<'a, T> { - /// Creates an input prompt with a specific theme. - pub fn with_theme(theme: &'a dyn Theme) -> Self { - Self { - prompt: "".into(), - post_completion_text: None, - report: true, - default: None, - show_default: true, - initial_text: None, - theme, - permit_empty: false, - validator: None, - #[cfg(feature = "history")] - history: None, - #[cfg(feature = "completion")] - completion: None, - } - } - - /// Enable history processing - /// - /// # Example - /// - /// ```no_run - /// # use dialoguer::{History, Input}; - /// # use std::{collections::VecDeque, fmt::Display}; - /// let mut history = MyHistory::default(); - /// loop { - /// if let Ok(input) = Input::<String>::new() - /// .with_prompt("hist") - /// .history_with(&mut history) - /// .interact_text() - /// { - /// // Do something with the input - /// } - /// } - /// # struct MyHistory { - /// # history: VecDeque<String>, - /// # } - /// # - /// # impl Default for MyHistory { - /// # fn default() -> Self { - /// # MyHistory { - /// # history: VecDeque::new(), - /// # } - /// # } - /// # } - /// # - /// # impl<T: ToString> History<T> for MyHistory { - /// # fn read(&self, pos: usize) -> Option<String> { - /// # self.history.get(pos).cloned() - /// # } - /// # - /// # fn write(&mut self, val: &T) - /// # where - /// # { - /// # self.history.push_front(val.to_string()); - /// # } - /// # } - /// ``` - #[cfg(feature = "history")] - pub fn history_with<H>(&mut self, history: &'a mut H) -> &mut Self - where - H: History<T>, - { - self.history = Some(history); - self - } - - /// Enable completion - #[cfg(feature = "completion")] - pub fn completion_with<C>(&mut self, completion: &'a C) -> &mut Self - where - C: Completion, - { - self.completion = Some(completion); - self - } -} - -impl<'a, T> Input<'a, T> -where - T: 'a, -{ - /// Registers a validator. - /// - /// # Example - /// - /// ```no_run - /// # use dialoguer::Input; - /// let mail: String = Input::new() - /// .with_prompt("Enter email") - /// .validate_with(|input: &String| -> Result<(), &str> { - /// if input.contains('@') { - /// Ok(()) - /// } else { - /// Err("This is not a mail address") - /// } - /// }) - /// .interact() - /// .unwrap(); - /// ``` - pub fn validate_with<V>(&mut self, mut validator: V) -> &mut Self - where - V: Validator<T> + 'a, - V::Err: ToString, - { - let mut old_validator_func = self.validator.take(); - - self.validator = Some(Box::new(move |value: &T| -> Option<String> { - if let Some(old) = old_validator_func.as_mut() { - if let Some(err) = old(value) { - return Some(err); - } - } - - match validator.validate(value) { - Ok(()) => None, - Err(err) => Some(err.to_string()), - } - })); - - self - } -} - -impl<T> Input<'_, T> -where - T: Clone + ToString + FromStr, - <T as FromStr>::Err: Debug + ToString, -{ - /// Enables the user to enter a printable ascii sequence and returns the result. - /// - /// Its difference from [`interact`](#method.interact) is that it only allows ascii characters for string, - /// while [`interact`](#method.interact) allows virtually any character to be used e.g arrow keys. - /// - /// The dialog is rendered on stderr. - pub fn interact_text(&mut self) -> io::Result<T> { - self.interact_text_on(&Term::stderr()) - } - - /// Like [`interact_text`](#method.interact_text) but allows a specific terminal to be set. - pub fn interact_text_on(&mut self, term: &Term) -> io::Result<T> { - let mut render = TermThemeRenderer::new(term, self.theme); - - loop { - let default_string = self.default.as_ref().map(ToString::to_string); - - let prompt_len = render.input_prompt( - &self.prompt, - if self.show_default { - default_string.as_deref() - } else { - None - }, - )?; - - // Read input by keystroke so that we can suppress ascii control characters - if !term.features().is_attended() { - return Ok("".to_owned().parse::<T>().unwrap()); - } - - let mut chars: Vec<char> = Vec::new(); - let mut position = 0; - #[cfg(feature = "history")] - let mut hist_pos = 0; - - if let Some(initial) = self.initial_text.as_ref() { - term.write_str(initial)?; - chars = initial.chars().collect(); - position = chars.len(); - } - term.flush()?; - - loop { - match term.read_key()? { - Key::Backspace if position > 0 => { - position -= 1; - chars.remove(position); - let line_size = term.size().1 as usize; - // Case we want to delete last char of a line so the cursor is at the beginning of the next line - if (position + prompt_len) % (line_size - 1) == 0 { - term.clear_line()?; - term.move_cursor_up(1)?; - term.move_cursor_right(line_size + 1)?; - } else { - term.clear_chars(1)?; - } - - let tail: String = chars[position..].iter().collect(); - - if !tail.is_empty() { - term.write_str(&tail)?; - - let total = position + prompt_len + tail.len(); - let total_line = total / line_size; - let line_cursor = (position + prompt_len) / line_size; - term.move_cursor_up(total_line - line_cursor)?; - - term.move_cursor_left(line_size)?; - term.move_cursor_right((position + prompt_len) % line_size)?; - } - - term.flush()?; - } - Key::Char(chr) if !chr.is_ascii_control() => { - chars.insert(position, chr); - position += 1; - let tail: String = - iter::once(&chr).chain(chars[position..].iter()).collect(); - term.write_str(&tail)?; - term.move_cursor_left(tail.len() - 1)?; - term.flush()?; - } - Key::ArrowLeft if position > 0 => { - if (position + prompt_len) % term.size().1 as usize == 0 { - term.move_cursor_up(1)?; - term.move_cursor_right(term.size().1 as usize)?; - } else { - term.move_cursor_left(1)?; - } - position -= 1; - term.flush()?; - } - Key::ArrowRight if position < chars.len() => { - if (position + prompt_len) % (term.size().1 as usize - 1) == 0 { - term.move_cursor_down(1)?; - term.move_cursor_left(term.size().1 as usize)?; - } else { - term.move_cursor_right(1)?; - } - position += 1; - term.flush()?; - } - Key::UnknownEscSeq(seq) if seq == vec!['b'] => { - let line_size = term.size().1 as usize; - let nb_space = chars[..position] - .iter() - .rev() - .take_while(|c| c.is_whitespace()) - .count(); - let find_last_space = chars[..position - nb_space] - .iter() - .rposition(|c| c.is_whitespace()); - - // If we find a space we set the cursor to the next char else we set it to the beginning of the input - if let Some(mut last_space) = find_last_space { - if last_space < position { - last_space += 1; - let new_line = (prompt_len + last_space) / line_size; - let old_line = (prompt_len + position) / line_size; - let diff_line = old_line - new_line; - if diff_line != 0 { - term.move_cursor_up(old_line - new_line)?; - } - - let new_pos_x = (prompt_len + last_space) % line_size; - let old_pos_x = (prompt_len + position) % line_size; - let diff_pos_x = new_pos_x as i64 - old_pos_x as i64; - //println!("new_pos_x = {}, old_pos_x = {}, diff = {}", new_pos_x, old_pos_x, diff_pos_x); - if diff_pos_x < 0 { - term.move_cursor_left(-diff_pos_x as usize)?; - } else { - term.move_cursor_right((diff_pos_x) as usize)?; - } - position = last_space; - } - } else { - term.move_cursor_left(position)?; - position = 0; - } - - term.flush()?; - } - Key::UnknownEscSeq(seq) if seq == vec!['f'] => { - let line_size = term.size().1 as usize; - let find_next_space = - chars[position..].iter().position(|c| c.is_whitespace()); - - // If we find a space we set the cursor to the next char else we set it to the beginning of the input - if let Some(mut next_space) = find_next_space { - let nb_space = chars[position + next_space..] - .iter() - .take_while(|c| c.is_whitespace()) - .count(); - next_space += nb_space; - let new_line = (prompt_len + position + next_space) / line_size; - let old_line = (prompt_len + position) / line_size; - term.move_cursor_down(new_line - old_line)?; - - let new_pos_x = (prompt_len + position + next_space) % line_size; - let old_pos_x = (prompt_len + position) % line_size; - let diff_pos_x = new_pos_x as i64 - old_pos_x as i64; - if diff_pos_x < 0 { - term.move_cursor_left(-diff_pos_x as usize)?; - } else { - term.move_cursor_right((diff_pos_x) as usize)?; - } - position += next_space; - } else { - let new_line = (prompt_len + chars.len()) / line_size; - let old_line = (prompt_len + position) / line_size; - term.move_cursor_down(new_line - old_line)?; - - let new_pos_x = (prompt_len + chars.len()) % line_size; - let old_pos_x = (prompt_len + position) % line_size; - let diff_pos_x = new_pos_x as i64 - old_pos_x as i64; - match diff_pos_x.cmp(&0) { - Ordering::Less => { - term.move_cursor_left((-diff_pos_x - 1) as usize)?; - } - Ordering::Equal => {} - Ordering::Greater => { - term.move_cursor_right((diff_pos_x) as usize)?; - } - } - position = chars.len(); - } - - term.flush()?; - } - #[cfg(feature = "completion")] - Key::ArrowRight | Key::Tab => { - if let Some(completion) = &self.completion { - let input: String = chars.clone().into_iter().collect(); - if let Some(x) = completion.get(&input) { - term.clear_chars(chars.len())?; - chars.clear(); - position = 0; - for ch in x.chars() { - chars.insert(position, ch); - position += 1; - } - term.write_str(&x)?; - term.flush()?; - } - } - } - #[cfg(feature = "history")] - Key::ArrowUp => { - let line_size = term.size().1 as usize; - if let Some(history) = &self.history { - if let Some(previous) = history.read(hist_pos) { - hist_pos += 1; - let mut chars_len = chars.len(); - while ((prompt_len + chars_len) / line_size) > 0 { - term.clear_chars(chars_len)?; - if (prompt_len + chars_len) % line_size == 0 { - chars_len -= std::cmp::min(chars_len, line_size); - } else { - chars_len -= std::cmp::min( - chars_len, - (prompt_len + chars_len + 1) % line_size, - ); - } - if chars_len > 0 { - term.move_cursor_up(1)?; - term.move_cursor_right(line_size)?; - } - } - term.clear_chars(chars_len)?; - chars.clear(); - position = 0; - for ch in previous.chars() { - chars.insert(position, ch); - position += 1; - } - term.write_str(&previous)?; - term.flush()?; - } - } - } - #[cfg(feature = "history")] - Key::ArrowDown => { - let line_size = term.size().1 as usize; - if let Some(history) = &self.history { - let mut chars_len = chars.len(); - while ((prompt_len + chars_len) / line_size) > 0 { - term.clear_chars(chars_len)?; - if (prompt_len + chars_len) % line_size == 0 { - chars_len -= std::cmp::min(chars_len, line_size); - } else { - chars_len -= std::cmp::min( - chars_len, - (prompt_len + chars_len + 1) % line_size, - ); - } - if chars_len > 0 { - term.move_cursor_up(1)?; - term.move_cursor_right(line_size)?; - } - } - term.clear_chars(chars_len)?; - chars.clear(); - position = 0; - // Move the history position back one in case we have up arrowed into it - // and the position is sitting on the next to read - if let Some(pos) = hist_pos.checked_sub(1) { - hist_pos = pos; - // Move it back again to get the previous history entry - if let Some(pos) = pos.checked_sub(1) { - if let Some(previous) = history.read(pos) { - for ch in previous.chars() { - chars.insert(position, ch); - position += 1; - } - term.write_str(&previous)?; - } - } - } - term.flush()?; - } - } - Key::Enter => break, - _ => (), - } - } - let input = chars.iter().collect::<String>(); - - term.clear_line()?; - render.clear()?; - - if chars.is_empty() { - if let Some(ref default) = self.default { - if let Some(ref mut validator) = self.validator { - if let Some(err) = validator(default) { - render.error(&err)?; - continue; - } - } - - if self.report { - render.input_prompt_selection(&self.prompt, &default.to_string())?; - } - term.flush()?; - return Ok(default.clone()); - } else if !self.permit_empty { - continue; - } - } - - match input.parse::<T>() { - Ok(value) => { - if let Some(ref mut validator) = self.validator { - if let Some(err) = validator(&value) { - render.error(&err)?; - continue; - } - } - - #[cfg(feature = "history")] - if let Some(history) = &mut self.history { - history.write(&value); - } - - if self.report { - if let Some(post_completion_text) = &self.post_completion_text { - render.input_prompt_selection(post_completion_text, &input)?; - } else { - render.input_prompt_selection(&self.prompt, &input)?; - } - } - term.flush()?; - - return Ok(value); - } - Err(err) => { - render.error(&err.to_string())?; - continue; - } - } - } - } -} - -impl<T> Input<'_, T> -where - T: Clone + ToString + FromStr, - <T as FromStr>::Err: ToString, -{ - /// Enables user interaction and returns the result. - /// - /// Allows any characters as input, including e.g arrow keys. - /// Some of the keys might have undesired behavior. - /// For more limited version, see [`interact_text`](#method.interact_text). - /// - /// If the user confirms the result is `true`, `false` otherwise. - /// The dialog is rendered on stderr. - pub fn interact(&mut self) -> io::Result<T> { - self.interact_on(&Term::stderr()) - } - - /// Like [`interact`](#method.interact) but allows a specific terminal to be set. - pub fn interact_on(&mut self, term: &Term) -> io::Result<T> { - let mut render = TermThemeRenderer::new(term, self.theme); - - loop { - let default_string = self.default.as_ref().map(ToString::to_string); - - render.input_prompt( - &self.prompt, - if self.show_default { - default_string.as_deref() - } else { - None - }, - )?; - term.flush()?; - - let input = if let Some(initial_text) = self.initial_text.as_ref() { - term.read_line_initial_text(initial_text)? - } else { - term.read_line()? - }; - - render.add_line(); - term.clear_line()?; - render.clear()?; - - if input.is_empty() { - if let Some(ref default) = self.default { - if let Some(ref mut validator) = self.validator { - if let Some(err) = validator(default) { - render.error(&err)?; - continue; - } - } - - if self.report { - render.input_prompt_selection(&self.prompt, &default.to_string())?; - } - term.flush()?; - return Ok(default.clone()); - } else if !self.permit_empty { - continue; - } - } - - match input.parse::<T>() { - Ok(value) => { - if let Some(ref mut validator) = self.validator { - if let Some(err) = validator(&value) { - render.error(&err)?; - continue; - } - } - - if self.report { - render.input_prompt_selection(&self.prompt, &input)?; - } - term.flush()?; - - return Ok(value); - } - Err(err) => { - render.error(&err.to_string())?; - continue; - } - } - } - } -} diff --git a/vendor/dialoguer/src/prompts/mod.rs b/vendor/dialoguer/src/prompts/mod.rs deleted file mode 100644 index 1c13185..0000000 --- a/vendor/dialoguer/src/prompts/mod.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![allow(clippy::needless_doctest_main)] - -pub mod confirm; -pub mod input; -pub mod multi_select; -pub mod select; -pub mod sort; - -#[cfg(feature = "fuzzy-select")] -pub mod fuzzy_select; - -#[cfg(feature = "password")] -pub mod password; diff --git a/vendor/dialoguer/src/prompts/multi_select.rs b/vendor/dialoguer/src/prompts/multi_select.rs deleted file mode 100644 index eed55a1..0000000 --- a/vendor/dialoguer/src/prompts/multi_select.rs +++ /dev/null @@ -1,356 +0,0 @@ -use std::{io, iter::repeat, ops::Rem}; - -use crate::{ - theme::{SimpleTheme, TermThemeRenderer, Theme}, - Paging, -}; - -use console::{Key, Term}; - -/// Renders a multi select prompt. -/// -/// ## Example usage -/// ```rust,no_run -/// # fn test() -> Result<(), Box<dyn std::error::Error>> { -/// use dialoguer::MultiSelect; -/// -/// let items = vec!["Option 1", "Option 2"]; -/// let chosen : Vec<usize> = MultiSelect::new() -/// .items(&items) -/// .interact()?; -/// # Ok(()) -/// # } -/// ``` -pub struct MultiSelect<'a> { - defaults: Vec<bool>, - items: Vec<String>, - prompt: Option<String>, - report: bool, - clear: bool, - max_length: Option<usize>, - theme: &'a dyn Theme, -} - -impl Default for MultiSelect<'static> { - fn default() -> Self { - Self::new() - } -} - -impl MultiSelect<'static> { - /// Creates a multi select prompt. - pub fn new() -> Self { - Self::with_theme(&SimpleTheme) - } -} - -impl MultiSelect<'_> { - /// Sets the clear behavior of the menu. - /// - /// The default is to clear the menu. - pub fn clear(&mut self, val: bool) -> &mut Self { - self.clear = val; - self - } - - /// Sets a defaults for the menu. - pub fn defaults(&mut self, val: &[bool]) -> &mut Self { - self.defaults = val - .to_vec() - .iter() - .copied() - .chain(repeat(false)) - .take(self.items.len()) - .collect(); - self - } - - /// Sets an optional max length for a page - /// - /// Max length is disabled by None - pub fn max_length(&mut self, val: usize) -> &mut Self { - // Paging subtracts two from the capacity, paging does this to - // make an offset for the page indicator. So to make sure that - // we can show the intended amount of items we need to add two - // to our value. - self.max_length = Some(val + 2); - self - } - - /// Add a single item to the selector. - #[inline] - pub fn item<T: ToString>(&mut self, item: T) -> &mut Self { - self.item_checked(item, false) - } - - /// Add a single item to the selector with a default checked state. - pub fn item_checked<T: ToString>(&mut self, item: T, checked: bool) -> &mut Self { - self.items.push(item.to_string()); - self.defaults.push(checked); - self - } - - /// Adds multiple items to the selector. - pub fn items<T: ToString>(&mut self, items: &[T]) -> &mut Self { - for item in items { - self.items.push(item.to_string()); - self.defaults.push(false); - } - self - } - - /// Adds multiple items to the selector with checked state - pub fn items_checked<T: ToString>(&mut self, items: &[(T, bool)]) -> &mut Self { - for &(ref item, checked) in items { - self.items.push(item.to_string()); - self.defaults.push(checked); - } - self - } - - /// Prefaces the menu with a prompt. - /// - /// By default, when a prompt is set the system also prints out a confirmation after - /// the selection. You can opt-out of this with [`report`](#method.report). - pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self { - self.prompt = Some(prompt.into()); - self - } - - /// Indicates whether to report the selected values after interaction. - /// - /// The default is to report the selections. - pub fn report(&mut self, val: bool) -> &mut Self { - self.report = val; - self - } - - /// Enables user interaction and returns the result. - /// - /// The user can select the items with the 'Space' bar and on 'Enter' the indices of selected items will be returned. - /// The dialog is rendered on stderr. - /// Result contains `Vec<index>` if user hit 'Enter'. - /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'. - #[inline] - pub fn interact(&self) -> io::Result<Vec<usize>> { - self.interact_on(&Term::stderr()) - } - - /// Enables user interaction and returns the result. - /// - /// The user can select the items with the 'Space' bar and on 'Enter' the indices of selected items will be returned. - /// The dialog is rendered on stderr. - /// Result contains `Some(Vec<index>)` if user hit 'Enter' or `None` if user cancelled with 'Esc' or 'q'. - #[inline] - pub fn interact_opt(&self) -> io::Result<Option<Vec<usize>>> { - self.interact_on_opt(&Term::stderr()) - } - - /// Like [interact](#method.interact) but allows a specific terminal to be set. - /// - /// ## Examples - ///```rust,no_run - /// use dialoguer::MultiSelect; - /// use console::Term; - /// - /// fn main() -> std::io::Result<()> { - /// let selections = MultiSelect::new() - /// .item("Option A") - /// .item("Option B") - /// .interact_on(&Term::stderr())?; - /// - /// println!("User selected options at indices {:?}", selections); - /// - /// Ok(()) - /// } - ///``` - #[inline] - pub fn interact_on(&self, term: &Term) -> io::Result<Vec<usize>> { - self._interact_on(term, false)? - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case")) - } - - /// Like [`interact_opt`](Self::interact_opt) but allows a specific terminal to be set. - /// - /// ## Examples - /// ```rust,no_run - /// use dialoguer::MultiSelect; - /// use console::Term; - /// - /// fn main() -> std::io::Result<()> { - /// let selections = MultiSelect::new() - /// .item("Option A") - /// .item("Option B") - /// .interact_on_opt(&Term::stdout())?; - /// - /// match selections { - /// Some(positions) => println!("User selected options at indices {:?}", positions), - /// None => println!("User exited using Esc or q") - /// } - /// - /// Ok(()) - /// } - /// ``` - #[inline] - pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<Vec<usize>>> { - self._interact_on(term, true) - } - - fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<Vec<usize>>> { - if self.items.is_empty() { - return Err(io::Error::new( - io::ErrorKind::Other, - "Empty list of items given to `MultiSelect`", - )); - } - - let mut paging = Paging::new(term, self.items.len(), self.max_length); - let mut render = TermThemeRenderer::new(term, self.theme); - let mut sel = 0; - - let mut size_vec = Vec::new(); - - for items in self - .items - .iter() - .flat_map(|i| i.split('\n')) - .collect::<Vec<_>>() - { - let size = &items.len(); - size_vec.push(*size); - } - - let mut checked: Vec<bool> = self.defaults.clone(); - - term.hide_cursor()?; - - loop { - if let Some(ref prompt) = self.prompt { - paging - .render_prompt(|paging_info| render.multi_select_prompt(prompt, paging_info))?; - } - - for (idx, item) in self - .items - .iter() - .enumerate() - .skip(paging.current_page * paging.capacity) - .take(paging.capacity) - { - render.multi_select_prompt_item(item, checked[idx], sel == idx)?; - } - - term.flush()?; - - match term.read_key()? { - Key::ArrowDown | Key::Tab | Key::Char('j') => { - if sel == !0 { - sel = 0; - } else { - sel = (sel as u64 + 1).rem(self.items.len() as u64) as usize; - } - } - Key::ArrowUp | Key::BackTab | Key::Char('k') => { - if sel == !0 { - sel = self.items.len() - 1; - } else { - sel = ((sel as i64 - 1 + self.items.len() as i64) - % (self.items.len() as i64)) as usize; - } - } - Key::ArrowLeft | Key::Char('h') => { - if paging.active { - sel = paging.previous_page(); - } - } - Key::ArrowRight | Key::Char('l') => { - if paging.active { - sel = paging.next_page(); - } - } - Key::Char(' ') => { - checked[sel] = !checked[sel]; - } - Key::Char('a') => { - if checked.iter().all(|&item_checked| item_checked) { - checked.fill(false); - } else { - checked.fill(true); - } - } - Key::Escape | Key::Char('q') => { - if allow_quit { - if self.clear { - render.clear()?; - } else { - term.clear_last_lines(paging.capacity)?; - } - - term.show_cursor()?; - term.flush()?; - - return Ok(None); - } - } - Key::Enter => { - if self.clear { - render.clear()?; - } - - if let Some(ref prompt) = self.prompt { - if self.report { - let selections: Vec<_> = checked - .iter() - .enumerate() - .filter_map(|(idx, &checked)| { - if checked { - Some(self.items[idx].as_str()) - } else { - None - } - }) - .collect(); - - render.multi_select_prompt_selection(prompt, &selections[..])?; - } - } - - term.show_cursor()?; - term.flush()?; - - return Ok(Some( - checked - .into_iter() - .enumerate() - .filter_map(|(idx, checked)| if checked { Some(idx) } else { None }) - .collect(), - )); - } - _ => {} - } - - paging.update(sel)?; - - if paging.active { - render.clear()?; - } else { - render.clear_preserve_prompt(&size_vec)?; - } - } - } -} - -impl<'a> MultiSelect<'a> { - /// Creates a multi select prompt with a specific theme. - pub fn with_theme(theme: &'a dyn Theme) -> Self { - Self { - items: vec![], - defaults: vec![], - clear: true, - prompt: None, - report: true, - max_length: None, - theme, - } - } -} diff --git a/vendor/dialoguer/src/prompts/password.rs b/vendor/dialoguer/src/prompts/password.rs deleted file mode 100644 index 7327605..0000000 --- a/vendor/dialoguer/src/prompts/password.rs +++ /dev/null @@ -1,194 +0,0 @@ -use std::io; - -use crate::{ - theme::{SimpleTheme, TermThemeRenderer, Theme}, - validate::PasswordValidator, -}; - -use console::Term; -use zeroize::Zeroizing; - -type PasswordValidatorCallback<'a> = Box<dyn Fn(&String) -> Option<String> + 'a>; - -/// Renders a password input prompt. -/// -/// ## Example usage -/// -/// ```rust,no_run -/// # fn test() -> Result<(), Box<std::error::Error>> { -/// use dialoguer::Password; -/// -/// let password = Password::new().with_prompt("New Password") -/// .with_confirmation("Confirm password", "Passwords mismatching") -/// .interact()?; -/// println!("Length of the password is: {}", password.len()); -/// # Ok(()) } fn main() { test().unwrap(); } -/// ``` -pub struct Password<'a> { - prompt: String, - report: bool, - theme: &'a dyn Theme, - allow_empty_password: bool, - confirmation_prompt: Option<(String, String)>, - validator: Option<PasswordValidatorCallback<'a>>, -} - -impl Default for Password<'static> { - fn default() -> Password<'static> { - Self::new() - } -} - -impl Password<'static> { - /// Creates a password input prompt. - pub fn new() -> Password<'static> { - Self::with_theme(&SimpleTheme) - } -} - -impl<'a> Password<'a> { - /// Sets the password input prompt. - pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self { - self.prompt = prompt.into(); - self - } - - /// Indicates whether to report confirmation after interaction. - /// - /// The default is to report. - pub fn report(&mut self, val: bool) -> &mut Self { - self.report = val; - self - } - - /// Enables confirmation prompting. - pub fn with_confirmation<A, B>(&mut self, prompt: A, mismatch_err: B) -> &mut Self - where - A: Into<String>, - B: Into<String>, - { - self.confirmation_prompt = Some((prompt.into(), mismatch_err.into())); - self - } - - /// Allows/Disables empty password. - /// - /// By default this setting is set to false (i.e. password is not empty). - pub fn allow_empty_password(&mut self, allow_empty_password: bool) -> &mut Self { - self.allow_empty_password = allow_empty_password; - self - } - - /// Registers a validator. - /// - /// # Example - /// - /// ```no_run - /// # use dialoguer::Password; - /// let password: String = Password::new() - /// .with_prompt("Enter password") - /// .validate_with(|input: &String| -> Result<(), &str> { - /// if input.len() > 8 { - /// Ok(()) - /// } else { - /// Err("Password must be longer than 8") - /// } - /// }) - /// .interact() - /// .unwrap(); - /// ``` - pub fn validate_with<V>(&mut self, validator: V) -> &mut Self - where - V: PasswordValidator + 'a, - V::Err: ToString, - { - let old_validator_func = self.validator.take(); - - self.validator = Some(Box::new(move |value: &String| -> Option<String> { - if let Some(old) = &old_validator_func { - if let Some(err) = old(value) { - return Some(err); - } - } - - match validator.validate(value) { - Ok(()) => None, - Err(err) => Some(err.to_string()), - } - })); - - self - } - - /// Enables user interaction and returns the result. - /// - /// If the user confirms the result is `true`, `false` otherwise. - /// The dialog is rendered on stderr. - pub fn interact(&self) -> io::Result<String> { - self.interact_on(&Term::stderr()) - } - - /// Like `interact` but allows a specific terminal to be set. - pub fn interact_on(&self, term: &Term) -> io::Result<String> { - let mut render = TermThemeRenderer::new(term, self.theme); - render.set_prompts_reset_height(false); - - loop { - let password = Zeroizing::new(self.prompt_password(&mut render, &self.prompt)?); - - if let Some(ref validator) = self.validator { - if let Some(err) = validator(&password) { - render.error(&err)?; - continue; - } - } - - if let Some((ref prompt, ref err)) = self.confirmation_prompt { - let pw2 = Zeroizing::new(self.prompt_password(&mut render, prompt)?); - - if *password != *pw2 { - render.error(err)?; - continue; - } - } - - render.clear()?; - - if self.report { - render.password_prompt_selection(&self.prompt)?; - } - term.flush()?; - - return Ok((*password).clone()); - } - } - - fn prompt_password(&self, render: &mut TermThemeRenderer, prompt: &str) -> io::Result<String> { - loop { - render.password_prompt(prompt)?; - render.term().flush()?; - - let input = render.term().read_secure_line()?; - - render.add_line(); - - if !input.is_empty() || self.allow_empty_password { - return Ok(input); - } - } - } -} - -impl<'a> Password<'a> { - /// Creates a password input prompt with a specific theme. - pub fn with_theme(theme: &'a dyn Theme) -> Self { - Self { - prompt: "".into(), - report: true, - theme, - allow_empty_password: false, - confirmation_prompt: None, - validator: None, - } - } -} diff --git a/vendor/dialoguer/src/prompts/select.rs b/vendor/dialoguer/src/prompts/select.rs deleted file mode 100644 index d080abd..0000000 --- a/vendor/dialoguer/src/prompts/select.rs +++ /dev/null @@ -1,419 +0,0 @@ -use std::{io, ops::Rem}; - -use crate::paging::Paging; -use crate::theme::{SimpleTheme, TermThemeRenderer, Theme}; - -use console::{Key, Term}; - -/// Renders a select prompt. -/// -/// User can select from one or more options. -/// Interaction returns index of an item selected in the order they appear in `item` invocation or `items` slice. -/// -/// ## Examples -/// -/// ```rust,no_run -/// use dialoguer::{console::Term, theme::ColorfulTheme, Select}; -/// -/// fn main() -> std::io::Result<()> { -/// let items = vec!["Item 1", "item 2"]; -/// let selection = Select::with_theme(&ColorfulTheme::default()) -/// .items(&items) -/// .default(0) -/// .interact_on_opt(&Term::stderr())?; -/// -/// match selection { -/// Some(index) => println!("User selected item : {}", items[index]), -/// None => println!("User did not select anything") -/// } -/// -/// Ok(()) -/// } -/// ``` -pub struct Select<'a> { - default: usize, - items: Vec<String>, - prompt: Option<String>, - report: bool, - clear: bool, - theme: &'a dyn Theme, - max_length: Option<usize>, -} - -impl Default for Select<'static> { - fn default() -> Self { - Self::new() - } -} - -impl Select<'static> { - /// Creates a select prompt builder with default theme. - pub fn new() -> Self { - Self::with_theme(&SimpleTheme) - } -} - -impl Select<'_> { - /// Indicates whether select menu should be erased from the screen after interaction. - /// - /// The default is to clear the menu. - pub fn clear(&mut self, val: bool) -> &mut Self { - self.clear = val; - self - } - - /// Sets initial selected element when select menu is rendered - /// - /// Element is indicated by the index at which it appears in `item` method invocation or `items` slice. - pub fn default(&mut self, val: usize) -> &mut Self { - self.default = val; - self - } - - /// Sets an optional max length for a page. - /// - /// Max length is disabled by None - pub fn max_length(&mut self, val: usize) -> &mut Self { - // Paging subtracts two from the capacity, paging does this to - // make an offset for the page indicator. So to make sure that - // we can show the intended amount of items we need to add two - // to our value. - self.max_length = Some(val + 2); - self - } - - /// Add a single item to the selector. - /// - /// ## Examples - /// ```rust,no_run - /// use dialoguer::Select; - /// - /// fn main() -> std::io::Result<()> { - /// let selection: usize = Select::new() - /// .item("Item 1") - /// .item("Item 2") - /// .interact()?; - /// - /// Ok(()) - /// } - /// ``` - pub fn item<T: ToString>(&mut self, item: T) -> &mut Self { - self.items.push(item.to_string()); - self - } - - /// Adds multiple items to the selector. - /// - /// ## Examples - /// ```rust,no_run - /// use dialoguer::Select; - /// - /// fn main() -> std::io::Result<()> { - /// let items = vec!["Item 1", "Item 2"]; - /// let selection: usize = Select::new() - /// .items(&items) - /// .interact()?; - /// - /// println!("{}", items[selection]); - /// - /// Ok(()) - /// } - /// ``` - pub fn items<T: ToString>(&mut self, items: &[T]) -> &mut Self { - for item in items { - self.items.push(item.to_string()); - } - self - } - - /// Sets the select prompt. - /// - /// By default, when a prompt is set the system also prints out a confirmation after - /// the selection. You can opt-out of this with [`report`](#method.report). - /// - /// ## Examples - /// ```rust,no_run - /// use dialoguer::Select; - /// - /// fn main() -> std::io::Result<()> { - /// let selection = Select::new() - /// .with_prompt("Which option do you prefer?") - /// .item("Option A") - /// .item("Option B") - /// .interact()?; - /// - /// Ok(()) - /// } - /// ``` - pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self { - self.prompt = Some(prompt.into()); - self.report = true; - self - } - - /// Indicates whether to report the selected value after interaction. - /// - /// The default is to report the selection. - pub fn report(&mut self, val: bool) -> &mut Self { - self.report = val; - self - } - - /// Enables user interaction and returns the result. - /// - /// The user can select the items with the 'Space' bar or 'Enter' and the index of selected item will be returned. - /// The dialog is rendered on stderr. - /// Result contains `index` if user selected one of items using 'Enter'. - /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'. - #[inline] - pub fn interact(&self) -> io::Result<usize> { - self.interact_on(&Term::stderr()) - } - - /// Enables user interaction and returns the result. - /// - /// The user can select the items with the 'Space' bar or 'Enter' and the index of selected item will be returned. - /// The dialog is rendered on stderr. - /// Result contains `Some(index)` if user selected one of items using 'Enter' or `None` if user cancelled with 'Esc' or 'q'. - #[inline] - pub fn interact_opt(&self) -> io::Result<Option<usize>> { - self.interact_on_opt(&Term::stderr()) - } - - /// Like [interact](#method.interact) but allows a specific terminal to be set. - /// - /// ## Examples - ///```rust,no_run - /// use dialoguer::{console::Term, Select}; - /// - /// fn main() -> std::io::Result<()> { - /// let selection = Select::new() - /// .item("Option A") - /// .item("Option B") - /// .interact_on(&Term::stderr())?; - /// - /// println!("User selected option at index {}", selection); - /// - /// Ok(()) - /// } - ///``` - #[inline] - pub fn interact_on(&self, term: &Term) -> io::Result<usize> { - self._interact_on(term, false)? - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case")) - } - - /// Like [`interact_opt`](Self::interact_opt) but allows a specific terminal to be set. - /// - /// ## Examples - /// ```rust,no_run - /// use dialoguer::{console::Term, Select}; - /// - /// fn main() -> std::io::Result<()> { - /// let selection = Select::new() - /// .item("Option A") - /// .item("Option B") - /// .interact_on_opt(&Term::stdout())?; - /// - /// match selection { - /// Some(position) => println!("User selected option at index {}", position), - /// None => println!("User did not select anything or exited using Esc or q") - /// } - /// - /// Ok(()) - /// } - /// ``` - #[inline] - pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<usize>> { - self._interact_on(term, true) - } - - /// Like `interact` but allows a specific terminal to be set. - fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<usize>> { - if self.items.is_empty() { - return Err(io::Error::new( - io::ErrorKind::Other, - "Empty list of items given to `Select`", - )); - } - - let mut paging = Paging::new(term, self.items.len(), self.max_length); - let mut render = TermThemeRenderer::new(term, self.theme); - let mut sel = self.default; - - let mut size_vec = Vec::new(); - - for items in self - .items - .iter() - .flat_map(|i| i.split('\n')) - .collect::<Vec<_>>() - { - let size = &items.len(); - size_vec.push(*size); - } - - term.hide_cursor()?; - - loop { - if let Some(ref prompt) = self.prompt { - paging.render_prompt(|paging_info| render.select_prompt(prompt, paging_info))?; - } - - for (idx, item) in self - .items - .iter() - .enumerate() - .skip(paging.current_page * paging.capacity) - .take(paging.capacity) - { - render.select_prompt_item(item, sel == idx)?; - } - - term.flush()?; - - match term.read_key()? { - Key::ArrowDown | Key::Tab | Key::Char('j') => { - if sel == !0 { - sel = 0; - } else { - sel = (sel as u64 + 1).rem(self.items.len() as u64) as usize; - } - } - Key::Escape | Key::Char('q') => { - if allow_quit { - if self.clear { - render.clear()?; - } else { - term.clear_last_lines(paging.capacity)?; - } - - term.show_cursor()?; - term.flush()?; - - return Ok(None); - } - } - Key::ArrowUp | Key::BackTab | Key::Char('k') => { - if sel == !0 { - sel = self.items.len() - 1; - } else { - sel = ((sel as i64 - 1 + self.items.len() as i64) - % (self.items.len() as i64)) as usize; - } - } - Key::ArrowLeft | Key::Char('h') => { - if paging.active { - sel = paging.previous_page(); - } - } - Key::ArrowRight | Key::Char('l') => { - if paging.active { - sel = paging.next_page(); - } - } - - Key::Enter | Key::Char(' ') if sel != !0 => { - if self.clear { - render.clear()?; - } - - if let Some(ref prompt) = self.prompt { - if self.report { - render.select_prompt_selection(prompt, &self.items[sel])?; - } - } - - term.show_cursor()?; - term.flush()?; - - return Ok(Some(sel)); - } - _ => {} - } - - paging.update(sel)?; - - if paging.active { - render.clear()?; - } else { - render.clear_preserve_prompt(&size_vec)?; - } - } - } -} - -impl<'a> Select<'a> { - /// Creates a select prompt builder with a specific theme. - /// - /// ## Examples - /// ```rust,no_run - /// use dialoguer::{ - /// Select, - /// theme::ColorfulTheme - /// }; - /// - /// fn main() -> std::io::Result<()> { - /// let selection = Select::with_theme(&ColorfulTheme::default()) - /// .item("Option A") - /// .item("Option B") - /// .interact()?; - /// - /// Ok(()) - /// } - /// ``` - pub fn with_theme(theme: &'a dyn Theme) -> Self { - Self { - default: !0, - items: vec![], - prompt: None, - report: false, - clear: true, - max_length: None, - theme, - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_str() { - let selections = &[ - "Ice Cream", - "Vanilla Cupcake", - "Chocolate Muffin", - "A Pile of sweet, sweet mustard", - ]; - - assert_eq!( - Select::new().default(0).items(&selections[..]).items, - selections - ); - } - - #[test] - fn test_string() { - let selections = vec!["a".to_string(), "b".to_string()]; - - assert_eq!( - Select::new().default(0).items(&selections[..]).items, - selections - ); - } - - #[test] - fn test_ref_str() { - let a = "a"; - let b = "b"; - - let selections = &[a, b]; - - assert_eq!( - Select::new().default(0).items(&selections[..]).items, - selections - ); - } -} diff --git a/vendor/dialoguer/src/prompts/sort.rs b/vendor/dialoguer/src/prompts/sort.rs deleted file mode 100644 index 03152bf..0000000 --- a/vendor/dialoguer/src/prompts/sort.rs +++ /dev/null @@ -1,348 +0,0 @@ -use std::{io, ops::Rem}; - -use crate::{ - theme::{SimpleTheme, TermThemeRenderer, Theme}, - Paging, -}; - -use console::{Key, Term}; - -/// Renders a sort prompt. -/// -/// Returns list of indices in original items list sorted according to user input. -/// -/// ## Example usage -/// ```rust,no_run -/// use dialoguer::Sort; -/// -/// # fn test() -> Result<(), Box<dyn std::error::Error>> { -/// let items_to_order = vec!["Item 1", "Item 2", "Item 3"]; -/// let ordered = Sort::new() -/// .with_prompt("Order the items") -/// .items(&items_to_order) -/// .interact()?; -/// # Ok(()) -/// # } -/// ``` -pub struct Sort<'a> { - items: Vec<String>, - prompt: Option<String>, - report: bool, - clear: bool, - max_length: Option<usize>, - theme: &'a dyn Theme, -} - -impl Default for Sort<'static> { - fn default() -> Self { - Self::new() - } -} - -impl Sort<'static> { - /// Creates a sort prompt. - pub fn new() -> Self { - Self::with_theme(&SimpleTheme) - } -} - -impl Sort<'_> { - /// Sets the clear behavior of the menu. - /// - /// The default is to clear the menu after user interaction. - pub fn clear(&mut self, val: bool) -> &mut Self { - self.clear = val; - self - } - - /// Sets an optional max length for a page - /// - /// Max length is disabled by None - pub fn max_length(&mut self, val: usize) -> &mut Self { - // Paging subtracts two from the capacity, paging does this to - // make an offset for the page indicator. So to make sure that - // we can show the intended amount of items we need to add two - // to our value. - self.max_length = Some(val + 2); - self - } - - /// Add a single item to the selector. - pub fn item<T: ToString>(&mut self, item: T) -> &mut Self { - self.items.push(item.to_string()); - self - } - - /// Adds multiple items to the selector. - pub fn items<T: ToString>(&mut self, items: &[T]) -> &mut Self { - for item in items { - self.items.push(item.to_string()); - } - self - } - - /// Prefaces the menu with a prompt. - /// - /// By default, when a prompt is set the system also prints out a confirmation after - /// the selection. You can opt-out of this with [`report`](#method.report). - pub fn with_prompt<S: Into<String>>(&mut self, prompt: S) -> &mut Self { - self.prompt = Some(prompt.into()); - self - } - - /// Indicates whether to report the selected order after interaction. - /// - /// The default is to report the selected order. - pub fn report(&mut self, val: bool) -> &mut Self { - self.report = val; - self - } - - /// Enables user interaction and returns the result. - /// - /// The user can order the items with the 'Space' bar and the arrows. On 'Enter' ordered list of the incides of items will be returned. - /// The dialog is rendered on stderr. - /// Result contains `Vec<index>` if user hit 'Enter'. - /// This unlike [`interact_opt`](Self::interact_opt) does not allow to quit with 'Esc' or 'q'. - #[inline] - pub fn interact(&self) -> io::Result<Vec<usize>> { - self.interact_on(&Term::stderr()) - } - - /// Enables user interaction and returns the result. - /// - /// The user can order the items with the 'Space' bar and the arrows. On 'Enter' ordered list of the incides of items will be returned. - /// The dialog is rendered on stderr. - /// Result contains `Some(Vec<index>)` if user hit 'Enter' or `None` if user cancelled with 'Esc' or 'q'. - #[inline] - pub fn interact_opt(&self) -> io::Result<Option<Vec<usize>>> { - self.interact_on_opt(&Term::stderr()) - } - - /// Like [interact](#method.interact) but allows a specific terminal to be set. - /// - /// ## Examples - ///```rust,no_run - /// use dialoguer::Sort; - /// use console::Term; - /// - /// fn main() -> std::io::Result<()> { - /// let selections = Sort::new() - /// .item("Option A") - /// .item("Option B") - /// .interact_on(&Term::stderr())?; - /// - /// println!("User sorted options as indices {:?}", selections); - /// - /// Ok(()) - /// } - ///``` - #[inline] - pub fn interact_on(&self, term: &Term) -> io::Result<Vec<usize>> { - self._interact_on(term, false)? - .ok_or_else(|| io::Error::new(io::ErrorKind::Other, "Quit not allowed in this case")) - } - - /// Like [`interact_opt`](Self::interact_opt) but allows a specific terminal to be set. - /// - /// ## Examples - /// ```rust,no_run - /// use dialoguer::Sort; - /// use console::Term; - /// - /// fn main() -> std::io::Result<()> { - /// let selections = Sort::new() - /// .item("Option A") - /// .item("Option B") - /// .interact_on_opt(&Term::stdout())?; - /// - /// match selections { - /// Some(positions) => println!("User sorted options as indices {:?}", positions), - /// None => println!("User exited using Esc or q") - /// } - /// - /// Ok(()) - /// } - /// ``` - #[inline] - pub fn interact_on_opt(&self, term: &Term) -> io::Result<Option<Vec<usize>>> { - self._interact_on(term, true) - } - - fn _interact_on(&self, term: &Term, allow_quit: bool) -> io::Result<Option<Vec<usize>>> { - if self.items.is_empty() { - return Err(io::Error::new( - io::ErrorKind::Other, - "Empty list of items given to `Sort`", - )); - } - - let mut paging = Paging::new(term, self.items.len(), self.max_length); - let mut render = TermThemeRenderer::new(term, self.theme); - let mut sel = 0; - - let mut size_vec = Vec::new(); - - for items in self.items.iter().as_slice() { - let size = &items.len(); - size_vec.push(*size); - } - - let mut order: Vec<_> = (0..self.items.len()).collect(); - let mut checked: bool = false; - - term.hide_cursor()?; - - loop { - if let Some(ref prompt) = self.prompt { - paging.render_prompt(|paging_info| render.sort_prompt(prompt, paging_info))?; - } - - for (idx, item) in order - .iter() - .enumerate() - .skip(paging.current_page * paging.capacity) - .take(paging.capacity) - { - render.sort_prompt_item(&self.items[*item], checked, sel == idx)?; - } - - term.flush()?; - - match term.read_key()? { - Key::ArrowDown | Key::Tab | Key::Char('j') => { - let old_sel = sel; - - if sel == !0 { - sel = 0; - } else { - sel = (sel as u64 + 1).rem(self.items.len() as u64) as usize; - } - - if checked && old_sel != sel { - order.swap(old_sel, sel); - } - } - Key::ArrowUp | Key::BackTab | Key::Char('k') => { - let old_sel = sel; - - if sel == !0 { - sel = self.items.len() - 1; - } else { - sel = ((sel as i64 - 1 + self.items.len() as i64) - % (self.items.len() as i64)) as usize; - } - - if checked && old_sel != sel { - order.swap(old_sel, sel); - } - } - Key::ArrowLeft | Key::Char('h') => { - if paging.active { - let old_sel = sel; - let old_page = paging.current_page; - - sel = paging.previous_page(); - - if checked { - let indexes: Vec<_> = if old_page == 0 { - let indexes1: Vec<_> = (0..=old_sel).rev().collect(); - let indexes2: Vec<_> = (sel..self.items.len()).rev().collect(); - [indexes1, indexes2].concat() - } else { - (sel..=old_sel).rev().collect() - }; - - for index in 0..(indexes.len() - 1) { - order.swap(indexes[index], indexes[index + 1]); - } - } - } - } - Key::ArrowRight | Key::Char('l') => { - if paging.active { - let old_sel = sel; - let old_page = paging.current_page; - - sel = paging.next_page(); - - if checked { - let indexes: Vec<_> = if old_page == paging.pages - 1 { - let indexes1: Vec<_> = (old_sel..self.items.len()).collect(); - let indexes2: Vec<_> = vec![0]; - [indexes1, indexes2].concat() - } else { - (old_sel..=sel).collect() - }; - - for index in 0..(indexes.len() - 1) { - order.swap(indexes[index], indexes[index + 1]); - } - } - } - } - Key::Char(' ') => { - checked = !checked; - } - Key::Escape | Key::Char('q') => { - if allow_quit { - if self.clear { - render.clear()?; - } else { - term.clear_last_lines(paging.capacity)?; - } - - term.show_cursor()?; - term.flush()?; - - return Ok(None); - } - } - Key::Enter => { - if self.clear { - render.clear()?; - } - - if let Some(ref prompt) = self.prompt { - if self.report { - let list: Vec<_> = order - .iter() - .enumerate() - .map(|(_, item)| self.items[*item].as_str()) - .collect(); - render.sort_prompt_selection(prompt, &list[..])?; - } - } - - term.show_cursor()?; - term.flush()?; - - return Ok(Some(order)); - } - _ => {} - } - - paging.update(sel)?; - - if paging.active { - render.clear()?; - } else { - render.clear_preserve_prompt(&size_vec)?; - } - } - } -} - -impl<'a> Sort<'a> { - /// Creates a sort prompt with a specific theme. - pub fn with_theme(theme: &'a dyn Theme) -> Self { - Self { - items: vec![], - clear: true, - prompt: None, - report: true, - max_length: None, - theme, - } - } -} diff --git a/vendor/dialoguer/src/theme.rs b/vendor/dialoguer/src/theme.rs deleted file mode 100644 index 1fbde92..0000000 --- a/vendor/dialoguer/src/theme.rs +++ /dev/null @@ -1,976 +0,0 @@ -//! Customizes the rendering of the elements. -use std::{fmt, io}; - -use console::{measure_text_width, style, Style, StyledObject, Term}; -#[cfg(feature = "fuzzy-select")] -use fuzzy_matcher::{skim::SkimMatcherV2, FuzzyMatcher}; - -/// Implements a theme for dialoguer. -pub trait Theme { - /// Formats a prompt. - #[inline] - fn format_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { - write!(f, "{}:", prompt) - } - - /// Formats out an error. - #[inline] - fn format_error(&self, f: &mut dyn fmt::Write, err: &str) -> fmt::Result { - write!(f, "error: {}", err) - } - - /// Formats a confirm prompt. - fn format_confirm_prompt( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - default: Option<bool>, - ) -> fmt::Result { - if !prompt.is_empty() { - write!(f, "{} ", &prompt)?; - } - match default { - None => write!(f, "[y/n] ")?, - Some(true) => write!(f, "[Y/n] ")?, - Some(false) => write!(f, "[y/N] ")?, - } - Ok(()) - } - - /// Formats a confirm prompt after selection. - fn format_confirm_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - selection: Option<bool>, - ) -> fmt::Result { - let selection = selection.map(|b| if b { "yes" } else { "no" }); - - match selection { - Some(selection) if prompt.is_empty() => { - write!(f, "{}", selection) - } - Some(selection) => { - write!(f, "{} {}", &prompt, selection) - } - None if prompt.is_empty() => Ok(()), - None => { - write!(f, "{}", &prompt) - } - } - } - - /// Formats an input prompt. - fn format_input_prompt( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - default: Option<&str>, - ) -> fmt::Result { - match default { - Some(default) if prompt.is_empty() => write!(f, "[{}]: ", default), - Some(default) => write!(f, "{} [{}]: ", prompt, default), - None => write!(f, "{}: ", prompt), - } - } - - /// Formats an input prompt after selection. - #[inline] - fn format_input_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - sel: &str, - ) -> fmt::Result { - write!(f, "{}: {}", prompt, sel) - } - - /// Formats a password prompt. - #[inline] - #[cfg(feature = "password")] - fn format_password_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { - self.format_input_prompt(f, prompt, None) - } - - /// Formats a password prompt after selection. - #[inline] - #[cfg(feature = "password")] - fn format_password_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - ) -> fmt::Result { - self.format_input_prompt_selection(f, prompt, "[hidden]") - } - - /// Formats a select prompt. - #[inline] - fn format_select_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { - self.format_prompt(f, prompt) - } - - /// Formats a select prompt after selection. - #[inline] - fn format_select_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - sel: &str, - ) -> fmt::Result { - self.format_input_prompt_selection(f, prompt, sel) - } - - /// Formats a multi select prompt. - #[inline] - fn format_multi_select_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { - self.format_prompt(f, prompt) - } - - /// Formats a sort prompt. - #[inline] - fn format_sort_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { - self.format_prompt(f, prompt) - } - - /// Formats a multi_select prompt after selection. - fn format_multi_select_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - selections: &[&str], - ) -> fmt::Result { - write!(f, "{}: ", prompt)?; - for (idx, sel) in selections.iter().enumerate() { - write!(f, "{}{}", if idx == 0 { "" } else { ", " }, sel)?; - } - Ok(()) - } - - /// Formats a sort prompt after selection. - #[inline] - fn format_sort_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - selections: &[&str], - ) -> fmt::Result { - self.format_multi_select_prompt_selection(f, prompt, selections) - } - - /// Formats a select prompt item. - fn format_select_prompt_item( - &self, - f: &mut dyn fmt::Write, - text: &str, - active: bool, - ) -> fmt::Result { - write!(f, "{} {}", if active { ">" } else { " " }, text) - } - - /// Formats a multi select prompt item. - fn format_multi_select_prompt_item( - &self, - f: &mut dyn fmt::Write, - text: &str, - checked: bool, - active: bool, - ) -> fmt::Result { - write!( - f, - "{} {}", - match (checked, active) { - (true, true) => "> [x]", - (true, false) => " [x]", - (false, true) => "> [ ]", - (false, false) => " [ ]", - }, - text - ) - } - - /// Formats a sort prompt item. - fn format_sort_prompt_item( - &self, - f: &mut dyn fmt::Write, - text: &str, - picked: bool, - active: bool, - ) -> fmt::Result { - write!( - f, - "{} {}", - match (picked, active) { - (true, true) => "> [x]", - (false, true) => "> [ ]", - (_, false) => " [ ]", - }, - text - ) - } - - /// Formats a fuzzy select prompt item. - #[cfg(feature = "fuzzy-select")] - fn format_fuzzy_select_prompt_item( - &self, - f: &mut dyn fmt::Write, - text: &str, - active: bool, - highlight_matches: bool, - matcher: &SkimMatcherV2, - search_term: &str, - ) -> fmt::Result { - write!(f, "{} ", if active { ">" } else { " " })?; - - if highlight_matches { - if let Some((_score, indices)) = matcher.fuzzy_indices(text, &search_term) { - for (idx, c) in text.chars().into_iter().enumerate() { - if indices.contains(&idx) { - write!(f, "{}", style(c).for_stderr().bold())?; - } else { - write!(f, "{}", c)?; - } - } - - return Ok(()); - } - } - - write!(f, "{}", text) - } - - /// Formats a fuzzy select prompt. - #[cfg(feature = "fuzzy-select")] - fn format_fuzzy_select_prompt( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - search_term: &str, - cursor_pos: usize, - ) -> fmt::Result { - if !prompt.is_empty() { - write!(f, "{} ", prompt,)?; - } - - if cursor_pos < search_term.len() { - let st_head = search_term[0..cursor_pos].to_string(); - let st_tail = search_term[cursor_pos..search_term.len()].to_string(); - let st_cursor = "|".to_string(); - write!(f, "{}{}{}", st_head, st_cursor, st_tail) - } else { - let cursor = "|".to_string(); - write!(f, "{}{}", search_term.to_string(), cursor) - } - } -} - -/// The default theme. -pub struct SimpleTheme; - -impl Theme for SimpleTheme {} - -/// A colorful theme -pub struct ColorfulTheme { - /// The style for default values - pub defaults_style: Style, - /// The style for prompt - pub prompt_style: Style, - /// Prompt prefix value and style - pub prompt_prefix: StyledObject<String>, - /// Prompt suffix value and style - pub prompt_suffix: StyledObject<String>, - /// Prompt on success prefix value and style - pub success_prefix: StyledObject<String>, - /// Prompt on success suffix value and style - pub success_suffix: StyledObject<String>, - /// Error prefix value and style - pub error_prefix: StyledObject<String>, - /// The style for error message - pub error_style: Style, - /// The style for hints - pub hint_style: Style, - /// The style for values on prompt success - pub values_style: Style, - /// The style for active items - pub active_item_style: Style, - /// The style for inactive items - pub inactive_item_style: Style, - /// Active item in select prefix value and style - pub active_item_prefix: StyledObject<String>, - /// Inctive item in select prefix value and style - pub inactive_item_prefix: StyledObject<String>, - /// Checked item in multi select prefix value and style - pub checked_item_prefix: StyledObject<String>, - /// Unchecked item in multi select prefix value and style - pub unchecked_item_prefix: StyledObject<String>, - /// Picked item in sort prefix value and style - pub picked_item_prefix: StyledObject<String>, - /// Unpicked item in sort prefix value and style - pub unpicked_item_prefix: StyledObject<String>, - /// Formats the cursor for a fuzzy select prompt - #[cfg(feature = "fuzzy-select")] - pub fuzzy_cursor_style: Style, - // Formats the highlighting if matched characters - #[cfg(feature = "fuzzy-select")] - pub fuzzy_match_highlight_style: Style, - /// Show the selections from certain prompts inline - pub inline_selections: bool, -} - -impl Default for ColorfulTheme { - fn default() -> ColorfulTheme { - ColorfulTheme { - defaults_style: Style::new().for_stderr().cyan(), - prompt_style: Style::new().for_stderr().bold(), - prompt_prefix: style("?".to_string()).for_stderr().yellow(), - prompt_suffix: style("›".to_string()).for_stderr().black().bright(), - success_prefix: style("✔".to_string()).for_stderr().green(), - success_suffix: style("·".to_string()).for_stderr().black().bright(), - error_prefix: style("✘".to_string()).for_stderr().red(), - error_style: Style::new().for_stderr().red(), - hint_style: Style::new().for_stderr().black().bright(), - values_style: Style::new().for_stderr().green(), - active_item_style: Style::new().for_stderr().cyan(), - inactive_item_style: Style::new().for_stderr(), - active_item_prefix: style("❯".to_string()).for_stderr().green(), - inactive_item_prefix: style(" ".to_string()).for_stderr(), - checked_item_prefix: style("✔".to_string()).for_stderr().green(), - unchecked_item_prefix: style("✔".to_string()).for_stderr().black(), - picked_item_prefix: style("❯".to_string()).for_stderr().green(), - unpicked_item_prefix: style(" ".to_string()).for_stderr(), - #[cfg(feature = "fuzzy-select")] - fuzzy_cursor_style: Style::new().for_stderr().black().on_white(), - #[cfg(feature = "fuzzy-select")] - fuzzy_match_highlight_style: Style::new().for_stderr().bold(), - inline_selections: true, - } - } -} - -impl Theme for ColorfulTheme { - /// Formats a prompt. - fn format_prompt(&self, f: &mut dyn fmt::Write, prompt: &str) -> fmt::Result { - if !prompt.is_empty() { - write!( - f, - "{} {} ", - &self.prompt_prefix, - self.prompt_style.apply_to(prompt) - )?; - } - - write!(f, "{}", &self.prompt_suffix) - } - - /// Formats an error - fn format_error(&self, f: &mut dyn fmt::Write, err: &str) -> fmt::Result { - write!( - f, - "{} {}", - &self.error_prefix, - self.error_style.apply_to(err) - ) - } - - /// Formats an input prompt. - fn format_input_prompt( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - default: Option<&str>, - ) -> fmt::Result { - if !prompt.is_empty() { - write!( - f, - "{} {} ", - &self.prompt_prefix, - self.prompt_style.apply_to(prompt) - )?; - } - - match default { - Some(default) => write!( - f, - "{} {} ", - self.hint_style.apply_to(&format!("({})", default)), - &self.prompt_suffix - ), - None => write!(f, "{} ", &self.prompt_suffix), - } - } - - /// Formats a confirm prompt. - fn format_confirm_prompt( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - default: Option<bool>, - ) -> fmt::Result { - if !prompt.is_empty() { - write!( - f, - "{} {} ", - &self.prompt_prefix, - self.prompt_style.apply_to(prompt) - )?; - } - - match default { - None => write!( - f, - "{} {}", - self.hint_style.apply_to("(y/n)"), - &self.prompt_suffix - ), - Some(true) => write!( - f, - "{} {} {}", - self.hint_style.apply_to("(y/n)"), - &self.prompt_suffix, - self.defaults_style.apply_to("yes") - ), - Some(false) => write!( - f, - "{} {} {}", - self.hint_style.apply_to("(y/n)"), - &self.prompt_suffix, - self.defaults_style.apply_to("no") - ), - } - } - - /// Formats a confirm prompt after selection. - fn format_confirm_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - selection: Option<bool>, - ) -> fmt::Result { - if !prompt.is_empty() { - write!( - f, - "{} {} ", - &self.success_prefix, - self.prompt_style.apply_to(prompt) - )?; - } - let selection = selection.map(|b| if b { "yes" } else { "no" }); - - match selection { - Some(selection) => { - write!( - f, - "{} {}", - &self.success_suffix, - self.values_style.apply_to(selection) - ) - } - None => { - write!(f, "{}", &self.success_suffix) - } - } - } - - /// Formats an input prompt after selection. - fn format_input_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - sel: &str, - ) -> fmt::Result { - if !prompt.is_empty() { - write!( - f, - "{} {} ", - &self.success_prefix, - self.prompt_style.apply_to(prompt) - )?; - } - - write!( - f, - "{} {}", - &self.success_suffix, - self.values_style.apply_to(sel) - ) - } - - /// Formats a password prompt after selection. - #[cfg(feature = "password")] - fn format_password_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - ) -> fmt::Result { - self.format_input_prompt_selection(f, prompt, "********") - } - - /// Formats a multi select prompt after selection. - fn format_multi_select_prompt_selection( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - selections: &[&str], - ) -> fmt::Result { - if !prompt.is_empty() { - write!( - f, - "{} {} ", - &self.success_prefix, - self.prompt_style.apply_to(prompt) - )?; - } - - write!(f, "{} ", &self.success_suffix)?; - - if self.inline_selections { - for (idx, sel) in selections.iter().enumerate() { - write!( - f, - "{}{}", - if idx == 0 { "" } else { ", " }, - self.values_style.apply_to(sel) - )?; - } - } - - Ok(()) - } - - /// Formats a select prompt item. - fn format_select_prompt_item( - &self, - f: &mut dyn fmt::Write, - text: &str, - active: bool, - ) -> fmt::Result { - let details = if active { - ( - &self.active_item_prefix, - self.active_item_style.apply_to(text), - ) - } else { - ( - &self.inactive_item_prefix, - self.inactive_item_style.apply_to(text), - ) - }; - - write!(f, "{} {}", details.0, details.1) - } - - /// Formats a multi select prompt item. - fn format_multi_select_prompt_item( - &self, - f: &mut dyn fmt::Write, - text: &str, - checked: bool, - active: bool, - ) -> fmt::Result { - let details = match (checked, active) { - (true, true) => ( - &self.checked_item_prefix, - self.active_item_style.apply_to(text), - ), - (true, false) => ( - &self.checked_item_prefix, - self.inactive_item_style.apply_to(text), - ), - (false, true) => ( - &self.unchecked_item_prefix, - self.active_item_style.apply_to(text), - ), - (false, false) => ( - &self.unchecked_item_prefix, - self.inactive_item_style.apply_to(text), - ), - }; - - write!(f, "{} {}", details.0, details.1) - } - - /// Formats a sort prompt item. - fn format_sort_prompt_item( - &self, - f: &mut dyn fmt::Write, - text: &str, - picked: bool, - active: bool, - ) -> fmt::Result { - let details = match (picked, active) { - (true, true) => ( - &self.picked_item_prefix, - self.active_item_style.apply_to(text), - ), - (false, true) => ( - &self.unpicked_item_prefix, - self.active_item_style.apply_to(text), - ), - (_, false) => ( - &self.unpicked_item_prefix, - self.inactive_item_style.apply_to(text), - ), - }; - - write!(f, "{} {}", details.0, details.1) - } - - /// Formats a fuzzy select prompt item. - #[cfg(feature = "fuzzy-select")] - fn format_fuzzy_select_prompt_item( - &self, - f: &mut dyn fmt::Write, - text: &str, - active: bool, - highlight_matches: bool, - matcher: &SkimMatcherV2, - search_term: &str, - ) -> fmt::Result { - write!( - f, - "{} ", - if active { - &self.active_item_prefix - } else { - &self.inactive_item_prefix - } - )?; - - if highlight_matches { - if let Some((_score, indices)) = matcher.fuzzy_indices(text, &search_term) { - for (idx, c) in text.chars().into_iter().enumerate() { - if indices.contains(&idx) { - if active { - write!( - f, - "{}", - self.active_item_style - .apply_to(self.fuzzy_match_highlight_style.apply_to(c)) - )?; - } else { - write!(f, "{}", self.fuzzy_match_highlight_style.apply_to(c))?; - } - } else { - if active { - write!(f, "{}", self.active_item_style.apply_to(c))?; - } else { - write!(f, "{}", c)?; - } - } - } - - return Ok(()); - } - } - - write!(f, "{}", text) - } - - /// Formats a fuzzy-selectprompt after selection. - #[cfg(feature = "fuzzy-select")] - fn format_fuzzy_select_prompt( - &self, - f: &mut dyn fmt::Write, - prompt: &str, - search_term: &str, - cursor_pos: usize, - ) -> fmt::Result { - if !prompt.is_empty() { - write!( - f, - "{} {} ", - &self.prompt_prefix, - self.prompt_style.apply_to(prompt) - )?; - } - - if cursor_pos < search_term.len() { - let st_head = search_term[0..cursor_pos].to_string(); - let st_tail = search_term[cursor_pos + 1..search_term.len()].to_string(); - let st_cursor = self - .fuzzy_cursor_style - .apply_to(search_term.to_string().chars().nth(cursor_pos).unwrap()); - write!( - f, - "{} {}{}{}", - &self.prompt_suffix, st_head, st_cursor, st_tail - ) - } else { - let cursor = self.fuzzy_cursor_style.apply_to(" "); - write!( - f, - "{} {}{}", - &self.prompt_suffix, - search_term.to_string(), - cursor - ) - } - } -} - -/// Helper struct to conveniently render a theme of a term. -pub(crate) struct TermThemeRenderer<'a> { - term: &'a Term, - theme: &'a dyn Theme, - height: usize, - prompt_height: usize, - prompts_reset_height: bool, -} - -impl<'a> TermThemeRenderer<'a> { - pub fn new(term: &'a Term, theme: &'a dyn Theme) -> TermThemeRenderer<'a> { - TermThemeRenderer { - term, - theme, - height: 0, - prompt_height: 0, - prompts_reset_height: true, - } - } - - #[cfg(feature = "password")] - pub fn set_prompts_reset_height(&mut self, val: bool) { - self.prompts_reset_height = val; - } - - #[cfg(feature = "password")] - pub fn term(&self) -> &Term { - self.term - } - - pub fn add_line(&mut self) { - self.height += 1; - } - - fn write_formatted_str< - F: FnOnce(&mut TermThemeRenderer, &mut dyn fmt::Write) -> fmt::Result, - >( - &mut self, - f: F, - ) -> io::Result<usize> { - let mut buf = String::new(); - f(self, &mut buf).map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; - self.height += buf.chars().filter(|&x| x == '\n').count(); - self.term.write_str(&buf)?; - Ok(measure_text_width(&buf)) - } - - fn write_formatted_line< - F: FnOnce(&mut TermThemeRenderer, &mut dyn fmt::Write) -> fmt::Result, - >( - &mut self, - f: F, - ) -> io::Result<()> { - let mut buf = String::new(); - f(self, &mut buf).map_err(|err| io::Error::new(io::ErrorKind::Other, err))?; - self.height += buf.chars().filter(|&x| x == '\n').count() + 1; - self.term.write_line(&buf) - } - - fn write_formatted_prompt< - F: FnOnce(&mut TermThemeRenderer, &mut dyn fmt::Write) -> fmt::Result, - >( - &mut self, - f: F, - ) -> io::Result<()> { - self.write_formatted_line(f)?; - if self.prompts_reset_height { - self.prompt_height = self.height; - self.height = 0; - } - Ok(()) - } - - fn write_paging_info(buf: &mut dyn fmt::Write, paging_info: (usize, usize)) -> fmt::Result { - write!(buf, " [Page {}/{}] ", paging_info.0, paging_info.1) - } - - pub fn error(&mut self, err: &str) -> io::Result<()> { - self.write_formatted_line(|this, buf| this.theme.format_error(buf, err)) - } - - pub fn confirm_prompt(&mut self, prompt: &str, default: Option<bool>) -> io::Result<usize> { - self.write_formatted_str(|this, buf| this.theme.format_confirm_prompt(buf, prompt, default)) - } - - pub fn confirm_prompt_selection(&mut self, prompt: &str, sel: Option<bool>) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme.format_confirm_prompt_selection(buf, prompt, sel) - }) - } - - #[cfg(feature = "fuzzy-select")] - pub fn fuzzy_select_prompt( - &mut self, - prompt: &str, - search_term: &str, - cursor_pos: usize, - ) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme - .format_fuzzy_select_prompt(buf, prompt, search_term, cursor_pos) - }) - } - - pub fn input_prompt(&mut self, prompt: &str, default: Option<&str>) -> io::Result<usize> { - self.write_formatted_str(|this, buf| this.theme.format_input_prompt(buf, prompt, default)) - } - - pub fn input_prompt_selection(&mut self, prompt: &str, sel: &str) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme.format_input_prompt_selection(buf, prompt, sel) - }) - } - - #[cfg(feature = "password")] - pub fn password_prompt(&mut self, prompt: &str) -> io::Result<usize> { - self.write_formatted_str(|this, buf| { - write!(buf, "\r")?; - this.theme.format_password_prompt(buf, prompt) - }) - } - - #[cfg(feature = "password")] - pub fn password_prompt_selection(&mut self, prompt: &str) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme.format_password_prompt_selection(buf, prompt) - }) - } - - pub fn select_prompt( - &mut self, - prompt: &str, - paging_info: Option<(usize, usize)>, - ) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme.format_select_prompt(buf, prompt)?; - - if let Some(paging_info) = paging_info { - TermThemeRenderer::write_paging_info(buf, paging_info)?; - } - - Ok(()) - }) - } - - pub fn select_prompt_selection(&mut self, prompt: &str, sel: &str) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme.format_select_prompt_selection(buf, prompt, sel) - }) - } - - pub fn select_prompt_item(&mut self, text: &str, active: bool) -> io::Result<()> { - self.write_formatted_line(|this, buf| { - this.theme.format_select_prompt_item(buf, text, active) - }) - } - - #[cfg(feature = "fuzzy-select")] - pub fn fuzzy_select_prompt_item( - &mut self, - text: &str, - active: bool, - highlight: bool, - matcher: &SkimMatcherV2, - search_term: &str, - ) -> io::Result<()> { - self.write_formatted_line(|this, buf| { - this.theme.format_fuzzy_select_prompt_item( - buf, - text, - active, - highlight, - matcher, - search_term, - ) - }) - } - - pub fn multi_select_prompt( - &mut self, - prompt: &str, - paging_info: Option<(usize, usize)>, - ) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme.format_multi_select_prompt(buf, prompt)?; - - if let Some(paging_info) = paging_info { - TermThemeRenderer::write_paging_info(buf, paging_info)?; - } - - Ok(()) - }) - } - - pub fn multi_select_prompt_selection(&mut self, prompt: &str, sel: &[&str]) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme - .format_multi_select_prompt_selection(buf, prompt, sel) - }) - } - - pub fn multi_select_prompt_item( - &mut self, - text: &str, - checked: bool, - active: bool, - ) -> io::Result<()> { - self.write_formatted_line(|this, buf| { - this.theme - .format_multi_select_prompt_item(buf, text, checked, active) - }) - } - - pub fn sort_prompt( - &mut self, - prompt: &str, - paging_info: Option<(usize, usize)>, - ) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme.format_sort_prompt(buf, prompt)?; - - if let Some(paging_info) = paging_info { - TermThemeRenderer::write_paging_info(buf, paging_info)?; - } - - Ok(()) - }) - } - - pub fn sort_prompt_selection(&mut self, prompt: &str, sel: &[&str]) -> io::Result<()> { - self.write_formatted_prompt(|this, buf| { - this.theme.format_sort_prompt_selection(buf, prompt, sel) - }) - } - - pub fn sort_prompt_item(&mut self, text: &str, picked: bool, active: bool) -> io::Result<()> { - self.write_formatted_line(|this, buf| { - this.theme - .format_sort_prompt_item(buf, text, picked, active) - }) - } - - pub fn clear(&mut self) -> io::Result<()> { - self.term - .clear_last_lines(self.height + self.prompt_height)?; - self.height = 0; - self.prompt_height = 0; - Ok(()) - } - - pub fn clear_preserve_prompt(&mut self, size_vec: &[usize]) -> io::Result<()> { - let mut new_height = self.height; - let prefix_width = 2; - //Check each item size, increment on finding an overflow - for size in size_vec { - if *size > self.term.size().1 as usize { - new_height += (((*size as f64 + prefix_width as f64) / self.term.size().1 as f64) - .ceil()) as usize - - 1; - } - } - - self.term.clear_last_lines(new_height)?; - self.height = 0; - Ok(()) - } -} diff --git a/vendor/dialoguer/src/validate.rs b/vendor/dialoguer/src/validate.rs deleted file mode 100644 index addc9b4..0000000 --- a/vendor/dialoguer/src/validate.rs +++ /dev/null @@ -1,49 +0,0 @@ -//! Provides validation for text inputs - -/// Trait for input validators. -/// -/// A generic implementation for `Fn(&str) -> Result<(), E>` is provided -/// to facilitate development. -pub trait Validator<T> { - type Err; - - /// Invoked with the value to validate. - /// - /// If this produces `Ok(())` then the value is used and parsed, if - /// an error is returned validation fails with that error. - fn validate(&mut self, input: &T) -> Result<(), Self::Err>; -} - -impl<T, F, E> Validator<T> for F -where - F: FnMut(&T) -> Result<(), E>, -{ - type Err = E; - - fn validate(&mut self, input: &T) -> Result<(), Self::Err> { - self(input) - } -} - -/// Trait for password validators. -#[allow(clippy::ptr_arg)] -pub trait PasswordValidator { - type Err; - - /// Invoked with the value to validate. - /// - /// If this produces `Ok(())` then the value is used and parsed, if - /// an error is returned validation fails with that error. - fn validate(&self, input: &String) -> Result<(), Self::Err>; -} - -impl<F, E> PasswordValidator for F -where - F: Fn(&String) -> Result<(), E>, -{ - type Err = E; - - fn validate(&self, input: &String) -> Result<(), Self::Err> { - self(input) - } -} |