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
use std::collections::HashSet;
use std::io;
use std::str::FromStr;
use std::sync::mpsc::Sender;
use std::time::Instant;
pub mod consts;

// Ascend
pub use consts::{config, errors, interact};

pub enum Coms {
    Message(crate::config::Config, Option<Instant>),
    End,
}

/// 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 =>if let Ok(it)= item.parse::<T>() {
                break Some(it);
            },
        };
        println!("{},", errors::AQ);
    }
}

/// 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 => {if let Ok(item) = item.parse::<String>() {
                    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);
                    }
                } else {
                    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
    }
}