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
use std::io::{stdin, stdout, Write}; use std::ops::Add; use colored::*; use crate::CausedResult; static STEP_PREFIX_MARKER: &str = "+"; static ERROR_PREFIX_MARKER: &str = "!"; static DEBUG_PREFIX_MARKER: &str = "-"; static QUESTION_PREFIX_MARKER: &str = "?"; static NO_PREFIX: &str = ""; fn make_padding(length: i32) -> String { let mut pad = String::new(); if length > 0 { pad = String::new(); for _ in 0..length { pad = pad.add("| "); } } pad } pub struct OutputManager { pub verbose: bool, padding: i32 } impl OutputManager { pub fn new(verbose: bool) -> OutputManager { OutputManager{ verbose, padding: 0 } } pub fn push(&self) -> OutputManager { OutputManager{ verbose: self.verbose, padding: self.padding+1 } } pub fn with_padding(&self, padding: i32) -> OutputManager { OutputManager{ verbose: self.verbose, padding } } fn print(&self, msg: ColoredString, prefix_marker: &str, verbose_only: bool) { if !self.verbose && verbose_only { return; } let pad = make_padding(self.padding); println!("{}{} {}", pad, prefix_marker, msg); } fn print_sameline(&self, msg: ColoredString, prefix_marker: &str, verbose_only: bool) { if !self.verbose && verbose_only { return; } let pad = make_padding(self.padding); print!("{}{} {}", pad, prefix_marker, msg); } pub fn step(&self, msg: &str) { self.print(msg.yellow(), STEP_PREFIX_MARKER, false); } pub fn progress(&self, msg: &str) { self.print(ColoredString::from(msg), NO_PREFIX, false); } pub fn success(&self, msg: &str) { self.print(msg.green(), STEP_PREFIX_MARKER, false); } pub fn debug(&self, msg: &str) { self.print(msg.blue(), DEBUG_PREFIX_MARKER, true); } pub fn error(&self, msg: &str) { self.print(msg.red(), ERROR_PREFIX_MARKER, false); } pub fn prompt_yn(&self, msg: &str, default: bool) -> CausedResult<bool> { if default { self.print_sameline(format!("{} [Y/n] - ", msg).blue(), QUESTION_PREFIX_MARKER, false); } else { self.print_sameline(format!("{} [y/N] - ", msg).blue(), QUESTION_PREFIX_MARKER, false); } let mut user_input = String::new(); stdout().flush()?; stdin().read_line(&mut user_input)?; let user_pick = user_input.trim().to_ascii_lowercase(); if default { Ok(&user_pick != "n") } else { Ok(&user_pick == "y") } } }