move most printing/styling into own file
This commit is contained in:
parent
01bcf92d9c
commit
a633f4e228
2 changed files with 86 additions and 85 deletions
99
src/main.rs
99
src/main.rs
|
|
@ -3,6 +3,7 @@ mod cachefile;
|
|||
mod cli;
|
||||
mod file;
|
||||
mod impl_ureq;
|
||||
mod output;
|
||||
mod sharry;
|
||||
|
||||
use std::{
|
||||
|
|
@ -15,54 +16,11 @@ use std::{
|
|||
|
||||
use clap::Parser;
|
||||
use console::style;
|
||||
use dialoguer::{Select, theme::ColorfulTheme};
|
||||
use log::{error, info, trace};
|
||||
use log::{info, trace};
|
||||
|
||||
use appstate::AppState;
|
||||
use cli::Cli;
|
||||
use sharry::ClientError;
|
||||
|
||||
fn prompt_continue() -> bool {
|
||||
let prompt = format!(
|
||||
"This operation has previously been stopped. {}",
|
||||
style("How to proceed?").cyan()
|
||||
);
|
||||
|
||||
let choices = [
|
||||
format!("Load and {}", style("continue operation").green().bold()),
|
||||
format!("Start a {}", style("new operation").cyan().bold()),
|
||||
format!("Quit {}", style("ShrUpl").yellow().bold()),
|
||||
];
|
||||
|
||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||
.with_prompt(prompt)
|
||||
.default(0)
|
||||
.items(&choices)
|
||||
.interact()
|
||||
.unwrap_or(2);
|
||||
|
||||
if selection == 2 {
|
||||
process::exit(255);
|
||||
}
|
||||
|
||||
selection == 0
|
||||
}
|
||||
|
||||
fn handle_error(e: &ClientError) {
|
||||
if e.is_fatal() {
|
||||
// react to fatal error
|
||||
error!("fatal error: {e:?}");
|
||||
eprintln!(
|
||||
"{} {}",
|
||||
style("Error!").red().bold(),
|
||||
style(e.to_string()).cyan().italic(),
|
||||
);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
// handle recoverable error
|
||||
info!("recoverable error: {e:?}");
|
||||
}
|
||||
use output::{Log, SHRUPL, prompt_continue};
|
||||
|
||||
fn main() {
|
||||
env_logger::init();
|
||||
|
|
@ -87,11 +45,7 @@ fn main() {
|
|||
let args = Cli::parse();
|
||||
info!("args: {args:#?}");
|
||||
|
||||
println!(
|
||||
"{} to {}!",
|
||||
style("Welcome").magenta().bold(),
|
||||
style("ShrUpl").yellow().bold(),
|
||||
);
|
||||
println!("{} to {}!", style("Welcome").magenta().bold(), *SHRUPL);
|
||||
|
||||
let mut state = AppState::try_resume(&args)
|
||||
.and_then(|state| prompt_continue().then_some(state))
|
||||
|
|
@ -101,34 +55,22 @@ fn main() {
|
|||
match AppState::from_args(&args) {
|
||||
Ok(state) => {
|
||||
state.save().unwrap_or_else(|e| {
|
||||
eprintln!(
|
||||
"{} Failed to save {} state: {e}",
|
||||
style("Warning:").red().bold(),
|
||||
style("ShrUpl").yellow().bold(),
|
||||
);
|
||||
Log::warning(format_args!("Failed to save state: {e}"));
|
||||
});
|
||||
state
|
||||
}
|
||||
Err(e) => {
|
||||
handle_error(&e);
|
||||
process::exit(1);
|
||||
Log::handle(&e);
|
||||
Log::error(format_args!("Failed to create state: {e}"));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
info!("continuing with state: {state:#?}");
|
||||
|
||||
let fns_magenta = state
|
||||
.file_names()
|
||||
.iter()
|
||||
.map(|&n| style(n).magenta().to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join(", ");
|
||||
let fns_magenta = output::style_all(&state.file_names(), |s| style(s).magenta()).join(", ");
|
||||
|
||||
println!(
|
||||
"{} is uploading: {fns_magenta}",
|
||||
style("ShrUpl").yellow().bold(),
|
||||
);
|
||||
println!("{} is uploading: {fns_magenta}", *SHRUPL);
|
||||
|
||||
let mut buffer = vec![0; args.chunk_size * 1024 * 1024];
|
||||
|
||||
|
|
@ -137,14 +79,13 @@ fn main() {
|
|||
Err(e) => {
|
||||
// TODO better error handling (this will just retry endlessly)
|
||||
// Error 404: Share might have been deleted
|
||||
handle_error(&e);
|
||||
Log::handle(&e);
|
||||
|
||||
if let Some(s) = state.rewind() {
|
||||
trace!("State rewound, retrying last chunk");
|
||||
state = s;
|
||||
} else {
|
||||
eprintln!("{} Failed to retry chunk!", style("Error:").red().bold());
|
||||
process::exit(1);
|
||||
Log::error("Failed to retry chunk!");
|
||||
}
|
||||
}
|
||||
Ok(false) => {
|
||||
|
|
@ -157,26 +98,14 @@ fn main() {
|
|||
}
|
||||
|
||||
state.save().unwrap_or_else(|e| {
|
||||
eprintln!(
|
||||
"{} Failed to save {} state: {e}",
|
||||
style("Warning:").red().bold(),
|
||||
style("ShrUpl").yellow().bold(),
|
||||
);
|
||||
Log::warning(format_args!("Failed to save state: {e}"));
|
||||
});
|
||||
check_ctrlc();
|
||||
}
|
||||
|
||||
state.clear().unwrap_or_else(|e| {
|
||||
eprintln!(
|
||||
"{} Failed to remove {} state: {e}",
|
||||
style("Warning:").red().bold(),
|
||||
style("ShrUpl").yellow().bold(),
|
||||
);
|
||||
Log::warning(format_args!("Failed to remove state: {e}"));
|
||||
});
|
||||
|
||||
println!(
|
||||
"{} finished {}",
|
||||
style("ShrUpl").yellow().bold(),
|
||||
style("successfully!").green()
|
||||
);
|
||||
println!("{} finished {}", *SHRUPL, style("successfully!").green());
|
||||
}
|
||||
|
|
|
|||
72
src/output.rs
Normal file
72
src/output.rs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
use std::{fmt, process, sync::LazyLock};
|
||||
|
||||
use console::{StyledObject, style};
|
||||
use dialoguer::{Select, theme::ColorfulTheme};
|
||||
use log::{error, info};
|
||||
|
||||
use crate::sharry;
|
||||
|
||||
type StaticStyled<'t> = LazyLock<StyledObject<&'t str>>;
|
||||
|
||||
pub static SHRUPL: StaticStyled = LazyLock::new(|| style("ShrUpl").yellow().bold());
|
||||
|
||||
pub fn prompt_continue() -> bool {
|
||||
let prompt = format!(
|
||||
"This operation has previously been stopped. {}",
|
||||
style("How to proceed?").cyan()
|
||||
);
|
||||
|
||||
let choices = [
|
||||
format!("Load and {}", style("continue operation").green().bold()),
|
||||
format!("Start a {}", style("new operation").cyan().bold()),
|
||||
format!("Quit {}", *SHRUPL),
|
||||
];
|
||||
|
||||
let selection = Select::with_theme(&ColorfulTheme::default())
|
||||
.with_prompt(prompt)
|
||||
.default(0)
|
||||
.items(&choices)
|
||||
.interact()
|
||||
.unwrap_or(2);
|
||||
|
||||
if selection == 2 {
|
||||
process::exit(0);
|
||||
}
|
||||
|
||||
selection == 0
|
||||
}
|
||||
|
||||
pub fn style_all<'t, F>(strs: &[&'t str], f: F) -> Vec<String>
|
||||
where
|
||||
F: Fn(&'t str) -> StyledObject<&'t str>,
|
||||
{
|
||||
strs.iter().map(|&s| f(s).to_string()).collect()
|
||||
}
|
||||
|
||||
pub enum Log {}
|
||||
|
||||
impl Log {
|
||||
fn eprintln(kind: impl fmt::Display, msg: impl fmt::Display) {
|
||||
eprintln!("{} {}: {}", *SHRUPL, kind, style(msg).cyan().italic(),);
|
||||
}
|
||||
|
||||
pub fn warning(msg: impl fmt::Display) {
|
||||
Self::eprintln(style("Warning").magenta().bold(), msg);
|
||||
}
|
||||
|
||||
pub fn error(msg: impl fmt::Display) -> ! {
|
||||
Self::eprintln(style("Error").red().bold(), msg);
|
||||
process::exit(1);
|
||||
}
|
||||
|
||||
pub fn handle(e: &sharry::ClientError) {
|
||||
if e.is_fatal() {
|
||||
// react to fatal error
|
||||
error!("fatal error: {e:?}");
|
||||
Self::error(e);
|
||||
}
|
||||
|
||||
// handle recoverable error
|
||||
info!("recoverable error: {e:?}");
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue