Cause: any answer other than y was treated as no, so your t discarded the changes. Fix: the prompt now only accepts y (save), n (discard) or c (cancel the exit). Anything else asks again, so a typo can't lose data. In my test, t, an empty line, then y saved correctly. Also: I changed the db restore confirmation to y/n only, with no cancel option. Closing stdin still saves automatically. Wait without a time tsk restat <task> wait: works with no time while the task's account is still waiting, and the task just follows that wait. tsk add <task> <acc> wait works the same way. Time required: otherwise it asks for one, with a message saying why. That covers an account that isn't waiting, an account whose wait is already over (Limit reset), and a task with no account. acc wait: it still requires a time. A plain acc wait would have nothing to do, since the account already has a wait. Account panel: there's a new RESET column showing when the account's wait ends. It shows 16:30 for today, tomorrow 06:40 for the next day, or a full date like 2020-01-01 10:00 (which is how an old, already-reset wait appears). Accounts with no wait show -. Since the time is in its own column now, an account with a wait but no task showing it lists just (wait) or (limit reset) in the TASKS column.
102 lines
3.1 KiB
C++
102 lines
3.1 KiB
C++
#pragma once
|
|
|
|
#include <cstddef>
|
|
#include <ctime>
|
|
#include <optional>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "CommandSpec.h"
|
|
#include "Completer.h"
|
|
#include "Config.h"
|
|
#include "Database.h"
|
|
#include "Display.h"
|
|
#include "LineEditor.h"
|
|
#include "Status.h"
|
|
|
|
// Interactive prompt: commands are typed live, one per line.
|
|
class Repl {
|
|
public:
|
|
Repl(Database& db, Display& display, Config& config);
|
|
|
|
int run();
|
|
|
|
private:
|
|
using Args = std::vector<std::string>;
|
|
using Handler = bool (Repl::*)(const Args&); // returns true if the panels should be redrawn
|
|
|
|
struct Command {
|
|
CommandSpec spec;
|
|
Handler handler;
|
|
};
|
|
|
|
void registerCommands();
|
|
void add(const std::string& key, const std::string& usage, const std::string& help,
|
|
std::size_t minArgs, std::size_t maxArgs, const std::vector<ArgKind>& argKinds,
|
|
Handler handler);
|
|
const Command* find(const Args& tokens, std::size_t& consumed) const;
|
|
|
|
void execute(const std::string& line);
|
|
void refresh() const;
|
|
void say(const std::string& message);
|
|
void setAccountWait(const std::string& account, std::time_t until);
|
|
void noteAccountWait(const std::string& taskName);
|
|
void flushMessages();
|
|
bool endOfInput(); // true if the program should exit
|
|
|
|
enum class Answer { Yes, No, Cancel };
|
|
// Asks until the reply is valid (y / n, and c when allowed). nullopt if input closed.
|
|
std::optional<Answer> ask(const std::string& question, bool allowCancel) const;
|
|
|
|
// Helpers
|
|
static void requireName(const std::string& name);
|
|
static Status parseStatusFrom(const Args& args, std::size_t from);
|
|
static bool isBareWait(const Args& args, std::size_t from);
|
|
std::optional<std::time_t> runningWait(const std::string& account) const;
|
|
void makeTaskFollowAccount(const TaskRow& task);
|
|
|
|
// Account commands
|
|
bool cmdAccAdd(const Args& args);
|
|
bool cmdAccDel(const Args& args);
|
|
bool cmdAccRename(const Args& args);
|
|
bool cmdAccWait(const Args& args);
|
|
bool cmdAccUnwait(const Args& args);
|
|
bool cmdAccLs(const Args& args);
|
|
|
|
// Task commands
|
|
bool cmdTskAdd(const Args& args);
|
|
bool cmdTskDel(const Args& args);
|
|
bool cmdTskLs(const Args& args);
|
|
bool cmdTskRename(const Args& args);
|
|
bool cmdTskReacc(const Args& args);
|
|
bool cmdTskRestat(const Args& args);
|
|
bool cmdTskNotes(const Args& args);
|
|
|
|
// Display commands
|
|
bool cmdDisp(const Args& args);
|
|
bool cmdDispTsk(const Args& args);
|
|
bool cmdDispTskLevel(const Args& args);
|
|
bool cmdDispAcc(const Args& args);
|
|
bool cmdDispAccLevel(const Args& args);
|
|
|
|
// Database commands
|
|
bool cmdDbSave(const Args& args);
|
|
bool cmdDbBackup(const Args& args);
|
|
bool cmdDbRestore(const Args& args);
|
|
|
|
// Misc
|
|
bool cmdEditor(const Args& args);
|
|
bool cmdHelp(const Args& args);
|
|
bool cmdQuit(const Args& args);
|
|
|
|
Database& db_;
|
|
Display& display_;
|
|
Config& config_;
|
|
std::vector<Command> commands_;
|
|
std::vector<CommandSpec> specs_;
|
|
Completer completer_;
|
|
LineEditor lineEditor_;
|
|
std::vector<std::string> messages_;
|
|
bool quit_;
|
|
};
|