1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
use crate::consts::errors;
use std::collections::HashSet;
use std::io;
use std::str::FromStr;
use std::sync::mpsc::Sender;
/// Gets [anything that implements FromStr](https://doc.rust-lang.org/std/str/trait.FromStr.html)
/// or q
pub fn get_item<T>() -> Option<T>
where
T: FromStr,
{
loop {
let mut attempt = String::new();
io::stdin().read_line(&mut attempt).expect(errors::AQ);
match attempt.trim() {
"\\q" => break None,
item => match item.parse::<T>() {
Ok(item) => break Some(item),
Err(_) => {
println!("{},", errors::AQ);
continue;
}
},
}
}
}
/// Gets a vector that stops at a none parameter.
/// It is append only.
/// It must be provided with a closure (or function) that returns an option
/// You can get such a thing from a function that returns error using
/// ```rust
/// # use focus::interact::get_vec;
/// # fn returns_error()->Result< (), () >{
/// # Err(())
/// # }
/// # let a =
/// get_vec(||{returns_error().ok()})
/// # ;
/// # assert_eq!(a.len(), 0);
/// ```
pub fn get_vec<T, U>(function: T) -> Vec<U>
where
T: Fn(&mut Vec<U>) -> Option<U>,
{
let mut vec: Vec<U> = Vec::new();
loop {
match function(&mut vec) {
Some(item) => vec.push(item),
None => break vec,
}
}
}
/// Adds or removes processes from the current processes HashSet
/// It admits four types of interactions
/// 1. `\q`: Stop adding processes
/// 1. `\w`: See the processes list
/// 1. `rm process name`: remove a process from the list
/// 1. `process name`: add a process to the list
pub fn get_proc(mut set: HashSet<String>) -> HashSet<String> {
loop {
let mut attempt = String::new();
io::stdin().read_line(&mut attempt).expect(errors::AQ);
match attempt.trim() {
"\\q" => break set,
"\\w" => println!("{:?}", set),
item => match item.parse::<String>() {
Ok(item) => {
let inst: Vec<&str> = item.split_whitespace().collect();
if inst.len() > 1 {
match inst[0] {
"rm" => {
set.remove(&inst[1..].join(" "));
}
_ => {
set.insert(item.to_string());
}
}
} else {
set.insert(item);
}
}
Err(_) => {
println!("{},", errors::AQ);
continue;
}
},
};
}
}
/// Non blocking string input.
/// It sends whatever is inputed and then dies.
/// It can be "polled" with ```try_recv```
pub fn async_string(tx: Sender<String>) {
let mut attempt = String::new();
io::stdin().read_line(&mut attempt).expect(errors::AQ);
tx.send(attempt).expect(errors::COM);
}
/// prints a 80 character wide string of -
pub fn bar() {
println!("--------------------------------------------------------------------------------");
}
/// The implementor of this trait has a field that can be guessed up to three times
pub trait GuessablePassword {
/// The field must be accessible to the trait through this method.
fn get_password(&self) -> String;
/// When called starts a series of interactions with the user that result
/// in a boolean
/// It returns `true` whenever the Password is guessed right and `false`
/// When it has been guessed wrongly three times
fn check_pass(&self, checks: Option<u8>) -> bool {
let mut counter = 0;
let checks = checks.unwrap_or(3);
while counter < checks {
println!("Password: ({}/{})", counter + 1, checks);
let pass: String = get_item().unwrap();
if pass == self.get_password() {
break;
}
counter += 1;
}
counter < checks
}
}