Read Input
A simple CLI tool that asks for user input until the data inputted is valid.
Help
If you run into any issues or need help with using read_input
in your project please email incoming+efunb/read_input@incoming.gitlab.com
Why you need it
When writing programs you will often need to take input from the user. If the user inputs invalid information the program needs to ask them again. Having to make this loop distracts from the useful logic in your program.
read_input
attempts to make it easy to get input from the user without having to think about converting types.
How to use
Add
= "0.8"
to your cargo.toml
under [dependencies]
and add
use *;
to your main file.
You can get input with.
.get
Where Type
is the type you want. You can use all types that implement std::str::FromStr
. This currently includes the standard library types isize
, usize
, i8
, u8
, i16
, u16
, f32
, i32
, u32
, f64
, i64
, u64
, i128
, u128
, char
, Ipv4Addr
, Ipv6Addr
, SocketAddrV4
, SocketAddrV6
and String
. Many crates also implement std::str::FromStr
for their types.
For example, if you want to assign a valid unsigned 32bit value to a variable called input
, you could write.
let input = .get;
Rust can often work out the type. When this is the case you can skip explicitly stating the type.
input.get
Input message
Custom messages are written on the same line as input and are specified with .msg()
. Note that the type annotations can been moved from the input()
function to the variable name when assigning input to variables.
let username: String = input.msg.get;
Alternatively .repeat_msg()
can be used. Messages specified with .repeat_msg()
will be repeated every time input is requested. You should try .msg()
and .repeat_msg()
to find what style works best for you.
let username: String = input.repeat_msg.get;
If you don't like having the message on the same line as input you can force input on to a new line by adding \n
to the end of the message.
let username: String = input.repeat_msg.get;
Default values
If the user presses enter before typing anything .get()
will return a default value when .default()
is used. Note the absence type annotations. Rust can infer the type by looking at the type of value used in .default()
.
let input = input.msg.default.get;
Change error message
The default error message is "That value does not pass. Please try again". You can change the error message with .err()
. For example.
let input =
.msg
.err
.get;
Add Checks
You can add your own checks to ensure the value meets your criteria.
If you want an integer that is not 6 you could write.
let input = input.add_test.get;
The .inside()
method can be used to ensure the inputted value is within a range.
If you want an integer from 4 to 9 you could write.
let input = input.inside.get;
.inside()
can also except an array or vector as well as ranges. .inside(4..=9)
is the same as .inside([4, 5, 6, 7, 8, 9])
.
In the same style you can specify custom test errors and multiple checks. Both .add_test()
and .inside()
have .add_err_test()
and .inside_err()
variants that allow for custom error messages.
If you want a value from 4 to 9 that is not 6 you could write.
let input = input
.msg
.inside_err
.add_err_test
.err
.get;
Other check methods
- Set a minimum value.
.min(minimum_value)
. - Set a maximum value.
.max(maximum_value)
. - Set a minimum and maximum value.
.min_max(minimum_value, maximum_value)
. - Set a restricted value.
.not(unwanted_value)
. - Set a minimum value with error message.
.min_err(minimum_value, error_message)
. - Set a maximum value with error message.
.max_err(maximum_value, error_message)
. - Set a minimum and maximum value with error message.
.min_max_err(minimum_value, maximum_value, error_message)
. - Sets a restricted value with error message.
.not_err(unwanted_value, error_message)
.
Match errors
You can specify custom error messages that depend on the errors produced by from_str()
with .err_match()
.
Here is an extract from the point_input
example showing this in practice.
let point =
.repeat_msg
.err_match
.get;
In nightly rust this can also be done with integers with the feature flag #![feature(int_error_matching)]
shown in the example match_num_err
.
use *;
let input =
.err_match
.repeat_msg
.get;
The with_description
function can be used if Err
associated type for the FromStr
implementation for the type you are using implements Error
. This can give quick error messages.
You will have to bring into scope with
use with_description;
and you can use it like this
let number =
.err_match
.repeat_msg
.get;
Shortcut functions
Using input().get()
can be a little verbose in simple situations. The functions simple_input()
and valid_input()
can make things simpler.
You can bring them into scope so that you can use them with
use ;
simple_input()
is the same as input().get()
.
valid_input(|x| 4 < *x && *x < 9)
is the same as input().add_test(|x| 4 < *x && *x < 9).get()
.
input_inside(..)
is the same as input().inside(..).get()
.
input_d
input_d()
works like input()
but uses the default input settings that are specified by the DefaultBuilderSettings
trait.
You can bring it into scope so that you can use them with
use input_d;
and it can be used like input()
let input: u32 = input_d.get
Using match
with checked input.
It is common to use match on values produced by input. For example if .inside()
or input_inside()
is used on an integer, match
would need to have branches for all possible integers even though the range of possible valid inputs may be quite small. In these cases, an unreachable wildcard can be used.
match input_inside
How to use with custom type
To use read_input
with a custom type you need to implement std::str::FromStr
for that type.
More complex examples
Example | Download | Description |
---|---|---|
simple_guessing_game |
Windows Linux Source | The guessing game form the rust book made to use read_input . |
guessing_game |
Windows Linux Source | The guessing game form the rust book made to use read_input + some extra features. |
how_long_until |
Windows Linux Source | Program that uses read_input with the crate chrono . |
point_input |
Windows Linux Source | Program written to show the use of the err_match() method. |
url |
Windows Linux Source | Program that lets users input URLs with the url crate and prints helpful errors when invalid urls are inputted. |
default |
Windows Linux Source | This example shows input_d in use. |
match |
Windows Linux Source | This example shows how best to use match on a inputted value. |
inside_vector |
Windows Linux Source | This example shows use of .inside() with a vector. |
inside_array |
Windows Linux Source | This example shows use of .inside() with an array. |
inside_range |
Windows Linux Source | This example shows use of .inside() with a range. |
constraints |
Windows Linux Source | This example shows use InputConstraints methods. |
Docs
Warning
If you are viewing this from GitHub then this is a read only copy. Please contribute to the GitLab copy here.