console-rs / dialoguer Goto Github PK
View Code? Open in Web Editor NEWRust utility library for nice command line prompts and similar things
License: MIT License
Rust utility library for nice command line prompts and similar things
License: MIT License
just wanted to leave a note to say what a nice crate this is. The rust ecosystem really needs something like this for cli prompting.
I also wanted to also drop some potentially aspirational inspiration of another cli prompter with a few more usability features. https://github.com/terkelg/prompts I like the number selector and the type suggestions for validation errors in particular.
I'm really excited to see where this crate can go.
I'm using the password input in some parts of my application. All other input mechanisms don't exit the program unless I'm on the main menu. When I make the user write an old or new password, and they hit Ctrl+c, the program ends. The problem with this is a) I don't want it to end, I want it to go to the main menu b) I can't execute some cleanup functions since I use a customized exit fn.
Would be nice to have a way to supres this, as an option. Or maybe there's already an easy enough way to achieve this? Please let me know.
I think it would be nicer if this crate didn't force ":"
at the end of the prompts.
An example use case is if one wants to make an input with a different prompt, or password input with an icon, etc.
# Allow a custom prompt character, like ">"
Username >>
# Alternatively have an icon at the password prompt:
Password: 🔑
everytime i try to enter a capital letter (or rather press shift) i get a "Not a terminal" error.
Application output is the following:
✔ Instance Server? · https://b.z0ne.social
✔ Instance API? · Honk
? Username? › Feb 23 14:32:52.984 ERROR ThreadId(01) tracing_unwrap: called `Result::unwrap_or_log()` on an `Err` value: Not a terminal
thread 'main' panicked at 'explicit panic', src\main.rs:36:16
stack backtrace:
0: std::panicking::begin_panic<str*>
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\std\src\panicking.rs:521
1: tracing_unwrap::failed_with
at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tracing-unwrap-0.9.2\src\lib.rs:287
2: tracing_unwrap::{{impl}}::unwrap_or_log<tuple<>,anyhow::Error>
at ~\.cargo\registry\src\github.com-1ecc6299db9ec823\tracing-unwrap-0.9.2\src\lib.rs:133
3: smexy::main
at .\src\main.rs:36
4: core::ops::function::FnOnce::call_once<fn(),tuple<>>
at ~\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\library\core\src\ops\function.rs:227
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
error: process didn't exit successfully: `target\debug\smexy.exe init` (exit code: 101)
Im calling dialoguer like this:
username: Input::<String>::with_theme(&ColorfulTheme::default())
.with_prompt("Username?")
.interact_text()?,
I need to run dialoguer with interact
, even though interact_text
should work form documentation perspective
If I build the password example and I try to pipe it, it messes up the terminal, I cannot see what I type after that, I will have to close the terminal:
$ password-example | bat
It won't position the cursor correctly every time it re-renders.
Thank you for this great project :)
I wrote an interactive cli program. I want to do unit tests for some of these input actions to try to improve my test coverage.
But I have encountered difficulties, I tried to use io::stdout
, but it didn't work.
How do I test the movements of dialoguer?
When pasting a password it is displayed in cleartext and only "hidden" (by displaying asterisks) upon confirmation message. Is this wanted behavior?
I would expect the password input to be hidden as well, otherwise one can grep the terminal history for passwords.
Additionally there is an unexpected empty line displayed between password input and confirmation message.
This is how I create the password input:
let monero_wallet_password = Password::with_theme(&ColorfulTheme::default())
.with_prompt("Enter Monero Wallet Password or hit enter for empty password.")
.allow_empty_password(true)
.interact()?;
This is the terminal output:
System: Mac BigSur
Terminal running zsh
I'd like to be able to manage user input by keystroke as it is being collected, so that I can avoid displaying unprintable characters and detect ESC as a cancel action.
I'm not sure what would be the best way to accomplish this. One solution would be to add a new flavor of read_line
to the console
crate and a new prompt type to dialoguer
. Is this something you think is worthwhile? It would require some coordination of PRs between dialoguer
and console
.
My current solution is to replace the read_line
calls in prompt/input
:
// We'd like to hide non-ascii keystrokes and also offer "ESC" as a way for the user to
// cancel input... but console::term doesn't allow this. Perhaps new public functions
// could be added to the console library but this would require us to patch
// both dialoguer and console. Instead I've moved the internals of console's
// read_line_initial_text fn here and modified it to suit our purpose.
let mut chars: Vec<char> = Vec::new();
if let Some(initial) = self.initial_text.as_ref() {
term.write_str(initial)?;
chars = initial.chars().collect();
}
loop {
match term.read_key()? {
Key::Backspace => {
if chars.pop().is_some() {
term.clear_chars(1)?;
}
term.flush()?;
}
Key::Escape => {
chars = vec!['\x1B'];
break;
}
Key::Enter => break,
Key::Char(chr) => {
if chr.is_ascii_alphanumeric() || chr.is_ascii_whitespace() {
chars.push(chr);
let mut bytes_char = [0; 4];
chr.encode_utf8(&mut bytes_char);
term.write_str(chr.encode_utf8(&mut bytes_char))?;
term.flush()?;
}
}
_ => (),
}
}
let input = chars.iter().collect::<String>();
I'm sure the ESC handling sequence could be a lot cleaner but this seems to be working...
A showcase of the capabilities of this crate with some screenshots in the Readme file would be great.
Hi! Thanks for this awesome crate.
I wonder whether I can help with adding a directory prompt like this to the crate:
https://github.com/nicksrandall/inquirer-directory
I can try to add a similar feature to the crate if it is necessary and if it is not something has a very specific use.
Let me know.
Hello
Thank you for this wonderful crate.
I was wondering why it is that the Checkbox struct implements the items method with param &[&str] while the Select struct implements the method with the type &[T]?
For refactoring it might be more convenient if they both took the same type as param.
Kind Regards
Daniel
I was wondering why there is no interact_opt
on the input
prompt. Is there a specific reason or just not implemented yet?
I use dialoguer to select from a moderate set of strings and was wondering
there is space to add some kind of search?
It does not need to be particularly clever, and could be added as an option?
What I'd like to do is similar to bash where you can press up/down to load previous inputs or start typing. Does dialoguer
support anything like this? I haven't been able to find a way to get Input
and read_key
to work together in such a seamless way.
I think it would need some way to report non-char keys until the prompt is entered. And the prompt should be redrawable, either automatically (based on char inputs) or internally (ie if I want to load a prompt from history/as a response from non char key input)
This is a common security problem: once password appears in the memory, it stays there unless it is explicitly erased. The problem is solved using a type which erases buffer on drop
.
There is a crate rpassword
which does only one function: it prompts for a password, reads the input, but all password buffers are erased on drop
.
@mitsuhiko I saw your blog, seems like you're alive :) Is there a sense to provide a PR so you will review it?
There are 2 options to implement it: using the secrecy
crate which implements SecretString
and it is pretty stable (it is used in Rust Crypto), or implement own type, but I would suggest secrecy
. (Tech detail: it's not enough to fill the buffer with zeroes, because compiler will optimize memset
in the end of the function as a redundant peace of code).
Thank you for a feedback!
Sometimes, I ask the user a question, but then something happens and that question becomes obsolete before it got answered. I don't think dialoguer
can handle this yet(?), since the interact
method is blocking.
I may be having a similar bug as a previously closed issue (#10), except with Checkboxes. I apologize if this is not a dialoguer issue. I am not sure if this is a Windows or dialoguer issue, or if this is how the terminal behaves naturally.
If an item from the selector is longer than the width of the terminal and/or you resize the terminal's width to make it smaller than an item in the selector, and you move up or down with the arrow keys, the menu becomes malformed. In my example below, cycling through the items appears to clear the previous lines, and I can no longer scroll up.
I have tried to enable/disable line wrapping on cmd, but get the same results.
I was able to reproduce this behavior with cmd and cmder (version 1.3.11) on Windows 10 (version 1903).
I would expect to be able to cycle through an item of various lengths and/or resize the terminal, and the menu be intact. If I was to start the terminal in full screen (for the example in the .gif) and/or have items that are shorter than the size of the terminal then this is not an issue.
The Input prompt has a few issues at the moment, mainly:
We could use the rustyline crate underneath so we get all the readline functionality for free, and it should work in terminal multiplexers and cross-platform.
Hi! It seems like master
contains a lot of changes that are not published yet (like zeroize:1
), are there any plans to publish an update to crates.io any time soon?
Thanks!
Assuming #42 gets merged, then we can always guarantee that the input value is of type T
instead of using &str
. So I have a request of changing the validator to receive &T
instead of &str
.
Examples:
As in, this:
Input::<i32>::new()
.validate_with(|input: &i32| -> Result<(), &str> {
todo!()
});
Input::<char>::new()
.validate_with(|input: &char| -> Result<(), &str> {
todo!()
});
Instead of:
Input::<i32>::new()
.validate_with(|input: &str| -> Result<(), &str> {
todo!()
});
Input::<char>::new()
.validate_with(|input: &str| -> Result<(), &str> {
todo!()
});
Note &i32
and &char
vs &str
and&str
.
I use this crate over at https://github.com/SirWindfield/git-cm and a user opened an issue stating that after they press ctrl-c, their cursor disappears:
I think this is a bug/oversight inside of dialoguer or console and not my crate to be honest 🤔
In a CLI-based wizard, it's quite easy to accidentally hit the Enter key an accidental extra time and mistakenly select a default confirmation you wanted to change.
As a feature, it would be nice not only to change the default, but to disable a default all-together, such that you must type a "y" or "n" before the prompt returns.
$ echo $EDITOR
vim -N -u NONE
$ RUST_BACKTRACE=1 cargo r --example edit
Finished dev [unoptimized + debuginfo] target(s) in 0.10s
Running `target/debug/jiqia`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', src/main.rs:4:68
stack backtrace:
0: rust_begin_unwind
at /rustc/c71248b70870960af9993de4f31d3cba9bbce7e8/library/std/src/panicking.rs:483:5
1: core::panicking::panic_fmt
at /rustc/c71248b70870960af9993de4f31d3cba9bbce7e8/library/core/src/panicking.rs:85:14
2: core::option::expect_none_failed
at /rustc/c71248b70870960af9993de4f31d3cba9bbce7e8/library/core/src/option.rs:1237:5
3: core::result::Result<T,E>::unwrap
at /home/sjtu-lyj/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/result.rs:973:23
4: jiqia::main
at ./src/main.rs:4:23
5: core::ops::function::FnOnce::call_once
at /home/sjtu-lyj/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/core/src/ops/function.rs:227:5
note: Some details are omitted, run with `RUST_BACKTRACE=full` for a verbose backtrace.
It would be nice to have something similar:
For reasons that are yet unclear to me, ColorfulTheme becomes monochrome when being used with an empty environment (env -i [binary]
).
This, in turn, makes its MultiSelect
, that exclusively relies on colors to identify which items are selected, unusable.
Would it make sense to have ColorfulTheme automatically detect when it's being used in a way that will make colors not work, and have it fall back to SimpleTheme? If not, how would you suggest one to handle this scenario?
Anyway, thank you for indicatif and dialoguer, they're both awesome crates :)
The Select
prompt hides my terminal cursor when I'm selecting the option (which makes sense) but it doesn't restore it after execution, which is frustrating.
Currently, after prompting for a password, I have the following output (with no theme):
Master key: [hidden]
Is it possible to disable this output ? Even if there is a blank line that would be ok.
Thank you.
Hi, something else: I would like to have a multi field editor. Just multiple Input
fields (if possible in more than one column, to save line-space) which can be cycled by arrow up/arrow down and tabulator. What do you think about such a feature?
This would be brilliant for embedded devices. Would you be interested in a patch to take a UART as an alternative to stdout?
Currently the confirmation proceeds immediately on a single key being input, which isn't really inline with conventional CLI design. I'd expect it to wait for Enter to be pressed even when giving an explicit answer.
If you open a dialoguer::Input
and just hit enter, the terminal will insert a newline but won't actually end the prompt and return the empty string as expected.
On Windows 10 machine, using Powershell shell, pressing +
sign while using Input
prompt in interact_text
mode, causes following error:
Code used is :
use dialoguer::Input;
fn main() -> std::io::Result<()> {
let input = Input::<String>::new()
.with_prompt("Data: ")
.interact_text()?;
Ok(())
}
I'd expect +
sign to be rendered or at least not throw error. This error might occur for more characters, but this is the one I found.
Awesome crate. Thanks!
I was struggling with using it without realizing that the current source is not all published with 0.4.0
.
Commit that I'm personally after, which is, as I now see - the only thing missing from. 0.4.1
? 1.0.0
?
Looking to build a Select that only displays 3 at a time. I think this would be a useful feature that I'd be happy to add if others would find it useful.
However I'm running into compiler issues. I'm a beginner so apologies if I'm missing something obvious:
fn three_at_a_time() -> Result<()> {
let mut results_iter = vec![1,2,3,4,5].iter();
let items_per_page = 3;
let mut selector = Select::new();
for _ in 1..=items_per_page {
let next = results_iter.next();
if next.is_none() {
selector = selector.item(next.unwrap());
}
}
let _chosen = selector.interact()?;
Ok(())
}
Error:
error[E0308]: mismatched types
--> src/main.rs:44:24
|
44 | selector = selector.item(next.unwrap())
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected struct `Select`, found `&mut Select<'_>`
Sometimes, a user might be presented with a (y/n)
prompt, and be undecided (i.e. neither "yes" nor "no"). It would be helpful if this library added interact_opt
and interact_on_opt
to the Confirm
struct, which would return Option<bool>
.
Don't pay attention to the title, I can't describe the issue with one sentence.
I just created a select menu with:
let choice = dialoguer::Select::new().with_prompt(&menu.prompt)
.items(&menu.get_items_labels()[..])
.interact()
.unwrap();
menu
is just a struct I made to hold all of the menu information in one place.
This code yields a menu with no cursor to start with. Using 'up' and 'down' arrow keys will spawn the cursor at the top or bottom, once the cursor has spawned everything is handled correctly, typing 'A', 'left arrow' or anything else doesn't do anything. Works as intended.
The issue arises when the cursor hasn't spawned yet. Using anything else than the 'up' or 'down' arrow will:
thread 'main' panicked at 'attempt to multiply with overflow', /home/user/.cargo/registry/src/github.com-1ecc6299db9ec823/dialoguer-0.4.0/src/select.rs:208:48
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
Note that using an 'up' or 'down' arrow key after the first invalid keypress that erases the menu will bring the menu back and work like intended.
EDIT: Fixed the menu method, it was with a Select
menu, not Checkboxes
.
While enhancing documentation I had hard time understanding what is the difference between interact_on
and interact_text_on
in Input
prompt (and I failed)
Solution would be to either:
Entering input that contains special characters, like áäüöæø on an international keyboard leads to overwriting characters in the read.
This happens because the text cursor is only partly moved forward, as these special characters contain multiple bytes to encode themself.
I will be posting a proposed fix but I am not sure if this one will be universally correct. (Different OS may be handling the input differently?)
Is there a way I can get a visual indicator when the password is typed in, like a *
for every character typed at the prompt?
The phone validator on master is currently too strict. It assumes certain input formats that are not met in the real world in some countries. (eg: Austria typically has +43 XXX YY YY YYY
or +43 XXX YYYY YYY
.
More often then not I come across the need to have both dialoguer
and console
available to me for various needs. For example clearing the page or writing styled report lines.
It would be nice to have dialoguer
expose console
through pub use console
.
When I used Select
as follows
dialoguer::Select::new()
.items(crate::generes::TYPES)
.paged(false)
.with_prompt("genere")
.interact()?;
the terminal in Windows
gives me the following error.
I tried GitBash, Powershell, Cmd and result are the same.
When you scroll down with arrow keys program crashes
thread 'main' panicked at 'attempt to subtract with overflow', C:\Users\Kasun\.cargo\registry\src\github.com-1ecc6299db9ec823\console-0.11.3\src\windows_term.rs:152:32
stack backtrace:
0: backtrace::backtrace::trace_unsynchronized
at C:\Users\VssAdministrator\.cargo\registry\src\github.com-1ecc6299db9ec823\backtrace-0.3.46\src\backtrace\mod.rs:66
1: std::sys_common::backtrace::_print_fmt
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\sys_common\backtrace.rs:78
2: std::sys_common::backtrace::_print::{{impl}}::fmt
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\sys_common\backtrace.rs:59
3: core::fmt::write
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libcore\fmt\mod.rs:1069
4: std::io::Write::write_fmt<std::sys::windows::stdio::Stderr>
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\io\mod.rs:1504
5: std::sys_common::backtrace::_print
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\sys_common\backtrace.rs:62
6: std::sys_common::backtrace::print
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\sys_common\backtrace.rs:49
7: std::panicking::default_hook::{{closure}}
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:198
8: std::panicking::default_hook
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:218
9: std::panicking::rust_panic_with_hook
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:511
10: std::panicking::begin_panic_handler
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:419
11: core::panicking::panic_fmt
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libcore\panicking.rs:111
12: core::panicking::panic
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libcore\panicking.rs:54
13: console::windows_term::move_cursor_up
at C:\Users\Kasun\.cargo\registry\src\github.com-1ecc6299db9ec823\console-0.11.3\src\windows_term.rs:152
14: console::term::Term::move_cursor_up
at C:\Users\Kasun\.cargo\registry\src\github.com-1ecc6299db9ec823\console-0.11.3\src\term.rs:362
15: console::term::Term::clear_last_lines
at C:\Users\Kasun\.cargo\registry\src\github.com-1ecc6299db9ec823\console-0.11.3\src\term.rs:396
16: dialoguer::theme::TermThemeRenderer::clear
at C:\Users\Kasun\.cargo\registry\src\github.com-1ecc6299db9ec823\dialoguer-0.6.2\src\theme.rs:755
17: dialoguer::prompts::select::Select::_interact_on
at C:\Users\Kasun\.cargo\registry\src\github.com-1ecc6299db9ec823\dialoguer-0.6.2\src\prompts\select.rs:209
18: dialoguer::prompts::select::Select::interact_on
at C:\Users\Kasun\.cargo\registry\src\github.com-1ecc6299db9ec823\dialoguer-0.6.2\src\prompts\select.rs:103
19: dialoguer::prompts::select::Select::interact
at C:\Users\Kasun\.cargo\registry\src\github.com-1ecc6299db9ec823\dialoguer-0.6.2\src\prompts\select.rs:89
20: mp3t::commands::edit::edit
at .\src\commands\edit.rs:27
21: mp3t::run_app
at .\src\bin\mp3t.rs:66
22: mp3t::main
at .\src\bin\mp3t.rs:79
23: std::rt::lang_start::{{closure}}<()>
at C:\Users\Kasun\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\rt.rs:67
24: std::rt::lang_start_internal::{{closure}}
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\rt.rs:52
25: std::panicking::try::do_call
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:331
26: std::panicking::try
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panicking.rs:274
27: std::panic::catch_unwind
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\panic.rs:394
28: std::rt::lang_start_internal
at /rustc/c7087fe00d2ba919df1d813c040a5d47e43b0fe7\/src\libstd\rt.rs:51
29: std::rt::lang_start<()>
at C:\Users\Kasun\.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src\libstd\rt.rs:67
30: main
31: invoke_main
at d:\agent\_work\5\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
32: __scrt_common_main_seh
at d:\agent\_work\5\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
33: BaseThreadInitThunk
34: RtlUserThreadStart
Hello there 😄 Thank you for contributing to Open Source. I am really enjoying using your library. I have created a function that given a String returns a Result<bool, Error>
depending if a text input follows some criteria. Recently, I found that your library supports a validate_with
function. Would it be easy to provide me with a usage example of validate_with
?
I seem to get a Custom { kind: NotConnected, error: "Not a terminal" }
whenever I try to use shift together with a letter on Windows 10. This happens also when I run the dialoguer input example on the same machine.
This does not seem to depend on the terminal. I have the error in PowerShell as well as in the regular cmd.
I also tried to use an older version of dialogue 0.7.1
with the same result.
The terminal consumes all normal characters and breaks as soon as the shift + character
is encountered.
If you pass Select
an empty list of items, and don't have paginated output enabled, you get a division by zero panic at this line:
I'm using dialoguer
0.6.2.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.