331 lines
9.5 KiB
C++
331 lines
9.5 KiB
C++
//
|
|
// Created by quentin on 1/8/23.
|
|
//
|
|
#include "mainOptHandler.h"
|
|
#include "accountOperation.h"
|
|
#include "createOperation.h"
|
|
#include "earnOperation.h"
|
|
#include "PaymentOperation.h"
|
|
#include <iostream>
|
|
#include <getopt.h>
|
|
#include <cstring>
|
|
|
|
using namespace Budget::OptHandlers;
|
|
|
|
MainOptHandler::MainOptHandler(const std::vector<char *> &_argv) : argv(_argv){
|
|
struct option actionLongOpts[] = {
|
|
{"help", no_argument, nullptr, 'h'},
|
|
{"account", required_argument, nullptr, 'a'},
|
|
{"create", required_argument, nullptr, 'c'},
|
|
{"earn", required_argument, nullptr, 'e'},
|
|
{"payment", required_argument, nullptr, 'p'}
|
|
};
|
|
|
|
while (true) {
|
|
int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:", actionLongOpts, nullptr);
|
|
if (opt == -1)
|
|
break;
|
|
|
|
switch (opt) {
|
|
case 'h':
|
|
help();
|
|
exit(0);
|
|
case 'a':
|
|
accountOptHandler(optarg);
|
|
break;
|
|
case 'c':
|
|
createOptHandler(optarg);
|
|
break;
|
|
case 'e':
|
|
earnOptHandler(optarg);
|
|
break;
|
|
case 'p':
|
|
paymentOptHandler(optarg);
|
|
break;
|
|
case '?':
|
|
help();
|
|
exit(0);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MainOptHandler::accountOptHandler(std::string account) {
|
|
struct option accountLongOpts[] = {
|
|
{"help", no_argument, nullptr, 'h'},
|
|
{"account", required_argument, nullptr, 'a'},
|
|
{"create", required_argument, nullptr, 'c'},
|
|
{"earn", required_argument, nullptr, 'e'},
|
|
{"payment", required_argument, nullptr, 'p'},
|
|
|
|
{"delete", no_argument, nullptr, 'd'},
|
|
{"force-delete", no_argument, nullptr, 'F'},
|
|
{"value", no_argument, nullptr, 'v'},
|
|
{"description", no_argument, nullptr, 'D'},
|
|
};
|
|
|
|
auto acctOperation = std::make_unique<AccountOperation>();
|
|
|
|
while (true) {
|
|
int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:dFvD", accountLongOpts, nullptr);
|
|
if (opt == -1)
|
|
break;
|
|
|
|
switch (opt) {
|
|
case 'h':
|
|
help();
|
|
exit(0);
|
|
case 'a':
|
|
case 'c':
|
|
case 'e':
|
|
case 'p':
|
|
optind--;
|
|
operations.push(std::move(acctOperation));
|
|
return;
|
|
case 'd':
|
|
acctOperation->flags.del = true;
|
|
break;
|
|
case 'F':
|
|
acctOperation->flags.del = true;
|
|
acctOperation->flags.forceDel = true;
|
|
break;
|
|
case 'v':
|
|
acctOperation->flags.value = true;
|
|
break;
|
|
case 'D':
|
|
acctOperation->flags.description = optarg;
|
|
break;
|
|
case '?':
|
|
help();
|
|
exit(0);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
operations.push(std::move(acctOperation));
|
|
}
|
|
|
|
void MainOptHandler::createOptHandler(std::string account) {
|
|
struct option createLongOpts[] = {
|
|
{"help", no_argument, nullptr, 'h'},
|
|
{"account", required_argument, nullptr, 'a'},
|
|
{"create", required_argument, nullptr, 'c'},
|
|
{"earn", required_argument, nullptr, 'e'},
|
|
{"payment", required_argument, nullptr, 'p'},
|
|
|
|
{"description", required_argument, nullptr, 'd'},
|
|
};
|
|
|
|
auto createOperation = std::make_unique<CreateOperation>();
|
|
|
|
while (true) {
|
|
int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:d:", createLongOpts, nullptr);
|
|
if (opt == -1)
|
|
break;
|
|
|
|
switch (opt) {
|
|
case 'h':
|
|
help();
|
|
exit(0);
|
|
case 'a':
|
|
case 'c':
|
|
case 'e':
|
|
case 'p':
|
|
optind--;
|
|
operations.push(std::move(createOperation));
|
|
return;
|
|
case 'd':
|
|
createOperation->flags.description = optarg;
|
|
break;
|
|
case '?':
|
|
help();
|
|
exit(0);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
operations.push(std::move(createOperation));
|
|
}
|
|
|
|
void MainOptHandler::earnOptHandler(std::string account) {
|
|
struct option earnLongOpts[] = {
|
|
{"help", no_argument, nullptr, 'h'},
|
|
{"account", required_argument, nullptr, 'a'},
|
|
{"create", required_argument, nullptr, 'c'},
|
|
{"earn", required_argument, nullptr, 'e'},
|
|
{"payment", required_argument, nullptr, 'p'},
|
|
|
|
{"value", required_argument, nullptr, 'v'},
|
|
{"description", required_argument, nullptr, 'd'},
|
|
{"receipt", required_argument, nullptr, 'r'},
|
|
{"date", required_argument, nullptr, 'D'},
|
|
};
|
|
|
|
auto earnOperation = std::make_unique<EarnOperation>();
|
|
|
|
while (true) {
|
|
int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:v:d:r:D:", earnLongOpts, nullptr);
|
|
if (opt == -1)
|
|
break;
|
|
|
|
switch (opt) {
|
|
case 'h':
|
|
help();
|
|
exit(0);
|
|
case 'a':
|
|
case 'c':
|
|
case 'e':
|
|
case 'p':
|
|
optind--;
|
|
operations.push(std::move(earnOperation));
|
|
return;
|
|
case 'v': {
|
|
try {
|
|
earnOperation->flags.value = std::stod(optarg);
|
|
} catch (std::exception const &e) {
|
|
help();
|
|
std::cout << "Bad value value" << std::endl;
|
|
exit(1);
|
|
}
|
|
break;
|
|
}
|
|
case 'd':
|
|
earnOperation->flags.description = optarg;
|
|
break;
|
|
case 'r':
|
|
earnOperation->flags.receipt = optarg;
|
|
break;
|
|
case 'D': {
|
|
struct tm t{};
|
|
time_t ts;
|
|
memset(&t, 0, sizeof(struct tm));
|
|
if (strptime(optarg, "%m/%d/%YT%H:%M:%S", &t) == nullptr) {
|
|
help();
|
|
std::cout << "Bad time value" << std::endl;
|
|
exit(1);
|
|
}
|
|
ts = mktime(&t);
|
|
earnOperation->flags.date = (long long) ts;
|
|
break;
|
|
}
|
|
case '?':
|
|
help();
|
|
exit(0);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
operations.push(std::move(earnOperation));
|
|
}
|
|
|
|
void MainOptHandler::paymentOptHandler(std::string account) {
|
|
struct option paymentLongOpts[] = {
|
|
{"help", no_argument, nullptr, 'h'},
|
|
{"account", required_argument, nullptr, 'a'},
|
|
{"create", required_argument, nullptr, 'c'},
|
|
{"earn", required_argument, nullptr, 'e'},
|
|
{"payment", required_argument, nullptr, 'p'},
|
|
|
|
{"value", required_argument, nullptr, 'v'},
|
|
{"description", required_argument, nullptr, 'd'},
|
|
{"receipt", required_argument, nullptr, 'r'},
|
|
{"date", required_argument, nullptr, 'D'},
|
|
};
|
|
|
|
auto payOperation = std::make_unique<PaymentOperation>();
|
|
|
|
while (true) {
|
|
int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:v:d:r:D", paymentLongOpts, nullptr);
|
|
if (opt == -1)
|
|
break;
|
|
|
|
switch (opt) {
|
|
case 'h':
|
|
help();
|
|
exit(0);
|
|
case 'a':
|
|
case 'c':
|
|
case 'e':
|
|
case 'p':
|
|
optind--;
|
|
operations.push(std::move(payOperation));
|
|
return;
|
|
case 'v': {
|
|
try {
|
|
payOperation->flags.value = std::stod(optarg);
|
|
} catch (std::exception const &e) {
|
|
help();
|
|
std::cout << "Bad value value" << std::endl;
|
|
exit(1);
|
|
}
|
|
break;
|
|
}
|
|
case 'd':
|
|
payOperation->flags.description = optarg;
|
|
break;
|
|
case 'r':
|
|
payOperation->flags.receipt = optarg;
|
|
break;
|
|
case 'D': {
|
|
struct tm t{};
|
|
time_t ts;
|
|
memset(&t, 0, sizeof(struct tm));
|
|
if (strptime(optarg, "%m/%d/%YT%H:%M:%S", &t) == nullptr) {
|
|
help();
|
|
std::cout << "Bad time value" << std::endl;
|
|
exit(1);
|
|
}
|
|
ts = mktime(&t);
|
|
payOperation->flags.date = (long long) ts;
|
|
break;
|
|
}
|
|
case '?':
|
|
help();
|
|
exit(0);
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
operations.push(std::move(payOperation));
|
|
}
|
|
|
|
void MainOptHandler::help() {
|
|
std::cout << "Output of budget." << std::endl;
|
|
std::cout << "Usage:" << std::endl;
|
|
std::cout << "\tbudget <action> [options] ..." << std::endl;
|
|
std::cout << "Actions:" << std::endl;
|
|
std::cout << "\t-h --help Prints this." << std::endl;
|
|
std::cout << "\t-a --account<=STRING> Management tools for an account." << std::endl;
|
|
std::cout << "\t-c --create<=STRING> Creates a new account with NAME." << std::endl;
|
|
std::cout << "\t-e --earn<=STRING> Add an earning to an account." << std::endl;
|
|
std::cout << "\t-p --payment<=STRING> Add a payment to an account." << std::endl;
|
|
std::cout << "Account Options: [-dvD]" << std::endl;
|
|
std::cout << "\t-d --delete Deletes specified account." << std::endl;
|
|
std::cout << "\t--force-delete Deletes the specified account without confirmation." << std::endl;
|
|
std::cout << "\t-v --value Gets the current value of the account." << std::endl;
|
|
std::cout << "\t-D --description<=STRING> Changes the description of the account." << std::endl;
|
|
std::cout << "Create Options: [-d]" << std::endl;
|
|
std::cout << "\t-d --description<=STRING> Sets a description for an account." << std::endl;
|
|
std::cout << "Earn Options: -v [-drD]" << std::endl;
|
|
std::cout << "\t-v --value=<FlOAT> Value for earning." << std::endl;
|
|
std::cout << "\t-d --description=<STRING> Description for earning." << std::endl;
|
|
std::cout << "\t-r --receipt=<PATH> Path to file to store in DB as receipt." << std::endl;
|
|
std::cout << "\t-D --date=<mm/dd/yyyyTHH:MM:SS> Date as dd/mm/yyyyTHH:MM:SS. Default will be today." << std::endl;
|
|
std::cout << "Payment Options: -v [-drD]" << std::endl;
|
|
std::cout << "\t-v --value=<FlOAT> Value for payment." << std::endl;
|
|
std::cout << "\t-d --description=<STRING> Description for payment." << std::endl;
|
|
std::cout << "\t-r --receipt=<PATH> Path to file to store in DB as receipt." << std::endl;
|
|
std::cout << "\t-D --date=<mm/dd/yyyyTHH:MM:SS> Date as dd/mm/yyyyTHH:MM:SS. Default will be today." << std::endl;
|
|
std::cout << std::endl;
|
|
std::cout << "Arguments are processed like blocks with each one terminated by the next Action. For example"
|
|
<< std::endl;
|
|
std::cout << std::endl;
|
|
std::cout << R"(budget -cAcct -eAcct -v10.00 -r"./receipt.pdf" -pAcct -v5.50 -r"./payment.pdf")" << std::endl;
|
|
std::cout << std::endl;
|
|
std::cout << "Does the following in order:" << std::endl;
|
|
std::cout << "Creates an account named Acct with no description." << std::endl;
|
|
std::cout << "Earns 10.00 to it with a receipt." << std::endl;
|
|
std::cout << "Pays 5.50 to it with a receipt." << std::endl;
|
|
}
|