aboutsummaryrefslogtreecommitdiff
path: root/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.rs')
-rw-r--r--src/main.rs471
1 files changed, 225 insertions, 246 deletions
diff --git a/src/main.rs b/src/main.rs
index cd401e2..5341939 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,261 +1,240 @@
+use chrono::Duration;
use clap::{
- Arg,
- App,
- ArgMatches,
- crate_version,
- crate_authors,
- crate_description
+ crate_authors, crate_description, crate_version, App, Arg, ArgMatches,
};
-use chrono::Duration;
use colored::*;
use budget::*;
fn main() {
- let matches = get_cli_matches();
-
- let no_color = matches.occurrences_of("plain") > 0;
- let force_color = matches.occurrences_of("force-color") > 0;
- let input = matches.value_of("INPUT").unwrap();
-
- let account = match budget::parse_account(input) {
- Ok(data) => data,
- Err(error) => {
- match error {
- ParseError::IOError(kind) => {
- println!("IO error while parsing: {:?}", kind);
- },
- ParseError::DeserializerError(_) => {
- println!("Can't parse the file, invalid syntax");
- },
- }
-
- ::std::process::exit(1);
- }
- };
- let maybe_calculated = budget::calculate(&account);
-
- if no_color && !force_color {
- colored::control::set_override(false);
- } else if force_color {
- colored::control::set_override(true);
- }
-
- output(account, maybe_calculated);
+ let matches = get_cli_matches();
+
+ let no_color = matches.occurrences_of("plain") > 0;
+ let force_color = matches.occurrences_of("force-color") > 0;
+ let input = matches.value_of("INPUT").unwrap();
+
+ let account = match budget::parse_account(input) {
+ Ok(data) => data,
+ Err(error) => {
+ match error {
+ ParseError::IOError(kind) => {
+ println!("IO error while parsing: {:?}", kind);
+ }
+ ParseError::DeserializerError(_) => {
+ println!("Can't parse the file, invalid syntax");
+ }
+ }
+
+ ::std::process::exit(1);
+ }
+ };
+ let maybe_calculated = budget::calculate(&account);
+
+ if no_color && !force_color {
+ colored::control::set_override(false);
+ } else if force_color {
+ colored::control::set_override(true);
+ }
+
+ output(account, maybe_calculated);
}
fn get_cli_matches() -> ArgMatches<'static> {
- App::new("finbudg")
- .version(crate_version!())
- .author(crate_authors!())
- .about(crate_description!())
- .arg(Arg::with_name("plain")
- .short("p")
- .long("plain")
- .help("Don't colorize the output. Can also be set \
- with the NO_COLOR environment variable.")
- .takes_value(false))
- .arg(Arg::with_name("force-color")
- .long("force-color")
- .help("Forces colorized output even when piping. Takes \
+ App::new("finbudg")
+ .version(crate_version!())
+ .author(crate_authors!())
+ .about(crate_description!())
+ .arg(
+ Arg::with_name("plain")
+ .short("p")
+ .long("plain")
+ .help(
+ "Don't colorize the output. Can also be set \
+ with the NO_COLOR environment variable.",
+ )
+ .takes_value(false),
+ )
+ .arg(
+ Arg::with_name("force-color")
+ .long("force-color")
+ .help(
+ "Forces colorized output even when piping. Takes \
precedence over --plain flag and NO_COLOR environment \
- variable")
- .takes_value(false))
- .arg(Arg::with_name("INPUT")
- .help("Expenses file in toml format to calculate from.")
- .required(true)
- .index(1))
- .get_matches()
+ variable",
+ )
+ .takes_value(false),
+ )
+ .arg(
+ Arg::with_name("INPUT")
+ .help("Expenses file in toml format to calculate from.")
+ .required(true)
+ .index(1),
+ )
+ .get_matches()
}
fn output(account: Account, maybe_calculated: Option<Calculated>) {
- println!(
- "{}",
- format!(
- "Your expenses for the period of {} - {}",
- account.start_date.format("%Y-%m-%d"),
- account.end_date.format("%Y-%m-%d"),
- ).cyan(),
- );
-
- let calculated = match maybe_calculated {
- Some(data) => data,
- None => {
- println!();
- println!("{}", "You have no expenses...".italic());
-
- ::std::process::exit(0);
- }
- };
-
- let days_until_end = account.end_date - calculated.last_day;
-
- println!(
- "{}",
- format!(
- "Last day on entry: {}",
- calculated.last_day.format("%Y-%m-%d"),
- ).cyan(),
- );
-
- println!(
- "{}",
- format!(
- "Days until period end: {}",
- days_until_end.num_days(),
- ).cyan(),
- );
-
- if days_until_end < Duration::zero() {
- println!();
- println!(
- "{}",
- "Your last day on entry is set after the last date of the period!"
- .yellow(),
- );
- println!();
- }
-
- println!(
- "{}",
- format!(
- "Budget: {:.2}",
- account.budget,
- ).cyan(),
- );
-
- println!();
-
- for (category, expenses) in calculated.categories_day_average.iter() {
- println!(
- "Average per day in {}: {:.2}",
- category,
- expenses,
- );
- }
-
- println!(
- "Average per day in essential expenses: {:.2}",
- calculated.essential_day_average,
- );
-
- println!(
- "Average per day: {:.2}",
- calculated.all_day_average,
- );
-
- println!();
-
- for (category, expenses) in calculated.categories_subtotal.iter() {
- println!(
- "Total in {}: {:.2}",
- category,
- expenses,
- );
- }
-
- println!(
- "Total in essential expenses: {:.2}",
- calculated.essential_subtotal,
- );
-
- println!(
- "Total: {:.2}",
- calculated.total,
- );
-
- println!();
-
- let balance_output = format!("{:.2}", calculated.balance);
- let balance_output = if calculated.balance > 0.0 {
- if account.budget / calculated.balance < 10.0 {
- balance_output.green()
- } else {
- balance_output.yellow()
- }
- } else {
- balance_output.red()
- };
-
- println!("Left on balance: {}", balance_output);
-
- println!();
-
- for (n, owed) in calculated.total_owed.iter() {
- println!(
- "{} person(s) owe you in shared expenses: {:.2}",
- n - 1,
- owed,
- );
-
- if *n > 2 {
- println!("Each owes you: {}", *owed / (*n as f64 - 1.0));
- }
-
- println!();
- }
-
- println!("Days until balance runs out:");
-
- let days_left_output = format!(
- "{:.2}",
- calculated.days_left,
- );
- let days_left_essential_output = format!(
- "{:.2}",
- calculated.days_left_essential,
- );
-
- // TODO: also show much money would be left by the end of the period
-
- let mut all_are_healthy = true;
- let mut essential_are_healthy = true;
-
- let days_left_output =
- if days_until_end.num_days() as f64 <= calculated.days_left {
- days_left_output.green()
- } else {
- all_are_healthy = false;
-
- days_left_output.red()
- };
- let days_left_essential_output =
- if days_until_end.num_days() as f64 <= calculated.days_left_essential {
- days_left_essential_output.green()
- } else {
- essential_are_healthy = false;
-
- days_left_essential_output.red()
- };
-
- println!(
- "...taking into account all expenses: {}",
- days_left_output,
- );
- println!(
- "...taking into account only essential expenses: {}",
- days_left_essential_output,
- );
- println!();
-
- if all_are_healthy {
- println!(
- "{}",
- "Your expenses are healthy, they should last you from your last \
- day on entry through your last day of the period.".green(),
- );
- } else {
- println!(
- "{}",
- "You are spending more than you can afford with your current \
- budget. Try minimizing your expenses".red(),
- );
- if essential_are_healthy {
- println!(
- "{}",
- "On the other hand, if you only spend money on essentials, \
- you should be able keep within your budget.".yellow(),
- );
- }
- }
+ println!(
+ "{}",
+ format!(
+ "Your expenses for the period of {} - {}",
+ account.start_date.format("%Y-%m-%d"),
+ account.end_date.format("%Y-%m-%d"),
+ )
+ .cyan(),
+ );
+
+ let calculated = match maybe_calculated {
+ Some(data) => data,
+ None => {
+ println!();
+ println!("{}", "You have no expenses...".italic());
+
+ ::std::process::exit(0);
+ }
+ };
+
+ let days_until_end = account.end_date - calculated.last_day;
+
+ println!(
+ "{}",
+ format!(
+ "Last day on entry: {}",
+ calculated.last_day.format("%Y-%m-%d"),
+ )
+ .cyan(),
+ );
+
+ println!(
+ "{}",
+ format!("Days until period end: {}", days_until_end.num_days(),).cyan(),
+ );
+
+ if days_until_end < Duration::zero() {
+ println!();
+ println!(
+ "{}",
+ "Your last day on entry is set after the last date of the period!"
+ .yellow(),
+ );
+ println!();
+ }
+
+ println!("{}", format!("Budget: {:.2}", account.budget,).cyan(),);
+
+ println!();
+
+ for (category, expenses) in calculated.categories_day_average.iter() {
+ println!("Average per day in {}: {:.2}", category, expenses,);
+ }
+
+ println!(
+ "Average per day in essential expenses: {:.2}",
+ calculated.essential_day_average,
+ );
+
+ println!("Average per day: {:.2}", calculated.all_day_average,);
+
+ println!();
+
+ for (category, expenses) in calculated.categories_subtotal.iter() {
+ println!("Total in {}: {:.2}", category, expenses,);
+ }
+
+ println!(
+ "Total in essential expenses: {:.2}",
+ calculated.essential_subtotal,
+ );
+
+ println!("Total: {:.2}", calculated.total,);
+
+ println!();
+
+ let balance_output = format!("{:.2}", calculated.balance);
+ let balance_output = if calculated.balance > 0.0 {
+ if account.budget / calculated.balance < 10.0 {
+ balance_output.green()
+ } else {
+ balance_output.yellow()
+ }
+ } else {
+ balance_output.red()
+ };
+
+ println!("Left on balance: {}", balance_output);
+
+ println!();
+
+ for (n, owed) in calculated.total_owed.iter() {
+ println!(
+ "{} person(s) owe you in shared expenses: {:.2}",
+ n - 1,
+ owed,
+ );
+
+ if *n > 2 {
+ println!("Each owes you: {}", *owed / (*n as f64 - 1.0));
+ }
+
+ println!();
+ }
+
+ println!("Days until balance runs out:");
+
+ let days_left_output = format!("{:.2}", calculated.days_left,);
+ let days_left_essential_output =
+ format!("{:.2}", calculated.days_left_essential,);
+
+ // TODO: also show much money would be left by the end of the period
+
+ let mut all_are_healthy = true;
+ let mut essential_are_healthy = true;
+
+ let days_left_output =
+ if days_until_end.num_days() as f64 <= calculated.days_left {
+ days_left_output.green()
+ } else {
+ all_are_healthy = false;
+
+ days_left_output.red()
+ };
+ let days_left_essential_output =
+ if days_until_end.num_days() as f64 <= calculated.days_left_essential {
+ days_left_essential_output.green()
+ } else {
+ essential_are_healthy = false;
+
+ days_left_essential_output.red()
+ };
+
+ println!("...taking into account all expenses: {}", days_left_output,);
+ println!(
+ "...taking into account only essential expenses: {}",
+ days_left_essential_output,
+ );
+ println!();
+
+ if all_are_healthy {
+ println!(
+ "{}",
+ "Your expenses are healthy, they should last you from your last \
+ day on entry through your last day of the period."
+ .green(),
+ );
+ } else {
+ println!(
+ "{}",
+ "You are spending more than you can afford with your current \
+ budget. Try minimizing your expenses"
+ .red(),
+ );
+ if essential_are_healthy {
+ println!(
+ "{}",
+ "On the other hand, if you only spend money on essentials, \
+ you should be able keep within your budget."
+ .yellow(),
+ );
+ }
+ }
}