mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-08-29 07:57:20 +02:00
Enhancement - Integration
- Integrated Cmd object. - Enhanced Context object with dispatch and shadow methods. - Fixed bug in Context::parse. - Implemented command parsing. - Fixed Sequence bug, and unit tests.
This commit is contained in:
parent
190c6b53fc
commit
d702ba8f24
7 changed files with 128 additions and 35 deletions
|
@ -134,7 +134,7 @@ void Cmd::loadCommands ()
|
||||||
commands.push_back (context.stringtable.get (CMD_OVERDUE, "overdue"));
|
commands.push_back (context.stringtable.get (CMD_OVERDUE, "overdue"));
|
||||||
commands.push_back (context.stringtable.get (CMD_PROJECTS, "projects"));
|
commands.push_back (context.stringtable.get (CMD_PROJECTS, "projects"));
|
||||||
commands.push_back (context.stringtable.get (CMD_START, "start"));
|
commands.push_back (context.stringtable.get (CMD_START, "start"));
|
||||||
commands.push_back (context.stringtable.get (CMD_STATS, "statistics"));
|
commands.push_back (context.stringtable.get (CMD_STATS, "stats"));
|
||||||
commands.push_back (context.stringtable.get (CMD_STOP, "stop"));
|
commands.push_back (context.stringtable.get (CMD_STOP, "stop"));
|
||||||
commands.push_back (context.stringtable.get (CMD_SUMMARY, "summary"));
|
commands.push_back (context.stringtable.get (CMD_SUMMARY, "summary"));
|
||||||
commands.push_back (context.stringtable.get (CMD_TAGS, "tags"));
|
commands.push_back (context.stringtable.get (CMD_TAGS, "tags"));
|
||||||
|
|
139
src/Context.cpp
139
src/Context.cpp
|
@ -46,7 +46,8 @@ Context::Context ()
|
||||||
, task ()
|
, task ()
|
||||||
, tdb ()
|
, tdb ()
|
||||||
, stringtable ()
|
, stringtable ()
|
||||||
, command ("")
|
, program ("")
|
||||||
|
, cmd ()
|
||||||
{
|
{
|
||||||
// Set up randomness.
|
// Set up randomness.
|
||||||
#ifdef HAVE_SRANDOM
|
#ifdef HAVE_SRANDOM
|
||||||
|
@ -68,8 +69,9 @@ Context::Context (const Context& other)
|
||||||
task = other.task;
|
task = other.task;
|
||||||
tdb = other.tdb;
|
tdb = other.tdb;
|
||||||
stringtable = other.stringtable;
|
stringtable = other.stringtable;
|
||||||
|
program = other.program;
|
||||||
args = other.args;
|
args = other.args;
|
||||||
command = other.command;
|
cmd = other.cmd;
|
||||||
messages = other.messages;
|
messages = other.messages;
|
||||||
footnotes = other.footnotes;
|
footnotes = other.footnotes;
|
||||||
}
|
}
|
||||||
|
@ -88,8 +90,9 @@ Context& Context::operator= (const Context& other)
|
||||||
task = other.task;
|
task = other.task;
|
||||||
tdb = other.tdb;
|
tdb = other.tdb;
|
||||||
stringtable = other.stringtable;
|
stringtable = other.stringtable;
|
||||||
|
program = other.program;
|
||||||
args = other.args;
|
args = other.args;
|
||||||
command = other.command;
|
cmd = other.cmd;
|
||||||
messages = other.messages;
|
messages = other.messages;
|
||||||
footnotes = other.footnotes;
|
footnotes = other.footnotes;
|
||||||
}
|
}
|
||||||
|
@ -107,6 +110,9 @@ void Context::initialize (int argc, char** argv)
|
||||||
{
|
{
|
||||||
// Capture the args.
|
// Capture the args.
|
||||||
for (int i = 0; i < argc; ++i)
|
for (int i = 0; i < argc; ++i)
|
||||||
|
if (i == 0)
|
||||||
|
program = argv[i];
|
||||||
|
else
|
||||||
args.push_back (argv[i]);
|
args.push_back (argv[i]);
|
||||||
|
|
||||||
// Load the configuration file from the home directory. If the file cannot
|
// Load the configuration file from the home directory. If the file cannot
|
||||||
|
@ -148,12 +154,11 @@ int Context::run ()
|
||||||
std::cout << "[1;32m--- start 1.8.0 ---[0m" << std::endl;
|
std::cout << "[1;32m--- start 1.8.0 ---[0m" << std::endl;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
parse ();
|
parse (); // Parse command line.
|
||||||
|
|
||||||
// TODO Dispatch to command handlers.
|
|
||||||
// TODO Auto shadow update.
|
|
||||||
// TODO Auto gc.
|
|
||||||
// TODO tdb.load (Filter);
|
// TODO tdb.load (Filter);
|
||||||
|
dispatch (); // Dispatch to command handlers.
|
||||||
|
// TODO Auto gc.
|
||||||
|
shadow (); // Auto shadow update.
|
||||||
}
|
}
|
||||||
|
|
||||||
catch (const std::string& error)
|
catch (const std::string& error)
|
||||||
|
@ -181,6 +186,86 @@ int Context::run ()
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Context::dispatch ()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
// If argc == 1 and there is a default.command, use it. Otherwise use
|
||||||
|
// argc/argv.
|
||||||
|
std::string defaultCommand = context.config.get ("default.command");
|
||||||
|
if (args.size () == 0 || defaultCommand != "")
|
||||||
|
{
|
||||||
|
// Stuff the command line.
|
||||||
|
args.clear ();
|
||||||
|
split (args, defaultCommand, ' ');
|
||||||
|
std::cout << "[task " << defaultCommand << "]" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadCustomReports ();
|
||||||
|
|
||||||
|
std::string command;
|
||||||
|
T task;
|
||||||
|
parse (args, command, task);
|
||||||
|
|
||||||
|
bool gcMod = false; // Change occurred by way of gc.
|
||||||
|
bool cmdMod = false; // Change occurred by way of command type.
|
||||||
|
std::string out;
|
||||||
|
|
||||||
|
// Read-only commands with no side effects.
|
||||||
|
if (command == "export") { out = handleExport (tdb, task); }
|
||||||
|
else if (command == "projects") { out = handleProjects (tdb, task); }
|
||||||
|
else if (command == "tags") { out = handleTags (tdb, task); }
|
||||||
|
else if (command == "info") { out = handleInfo (tdb, task); }
|
||||||
|
else if (command == "stats") { out = handleReportStats (tdb, task); }
|
||||||
|
else if (command == "history") { out = handleReportHistory (tdb, task); }
|
||||||
|
else if (command == "ghistory") { out = handleReportGHistory (tdb, task); }
|
||||||
|
else if (command == "calendar") { out = handleReportCalendar (tdb, task); }
|
||||||
|
else if (command == "summary") { out = handleReportSummary (tdb, task); }
|
||||||
|
else if (command == "timesheet") { out = handleReportTimesheet (tdb, task); }
|
||||||
|
else if (command == "colors") { out = handleColor ( ); }
|
||||||
|
else if (command == "version") { out = handleVersion ( ); }
|
||||||
|
else if (command == "help") { out = longUsage ( ); }
|
||||||
|
|
||||||
|
// Commands that cause updates.
|
||||||
|
else if (command == "" && task.getId ()) { cmdMod = true; out = handleModify (tdb, task); }
|
||||||
|
else if (command == "add") { cmdMod = true; out = handleAdd (tdb, task); }
|
||||||
|
else if (command == "append") { cmdMod = true; out = handleAppend (tdb, task); }
|
||||||
|
else if (command == "annotate") { cmdMod = true; out = handleAnnotate (tdb, task); }
|
||||||
|
else if (command == "done") { cmdMod = true; out = handleDone (tdb, task); }
|
||||||
|
else if (command == "undelete") { cmdMod = true; out = handleUndelete (tdb, task); }
|
||||||
|
else if (command == "delete") { cmdMod = true; out = handleDelete (tdb, task); }
|
||||||
|
else if (command == "start") { cmdMod = true; out = handleStart (tdb, task); }
|
||||||
|
else if (command == "stop") { cmdMod = true; out = handleStop (tdb, task); }
|
||||||
|
else if (command == "undo") { cmdMod = true; out = handleUndo (tdb, task); }
|
||||||
|
else if (command == "import") { cmdMod = true; out = handleImport (tdb, task); }
|
||||||
|
else if (command == "duplicate") { cmdMod = true; out = handleDuplicate (tdb, task); }
|
||||||
|
else if (command == "edit") { cmdMod = true; out = handleEdit (tdb, task); }
|
||||||
|
|
||||||
|
// Command that display IDs and therefore need TDB::gc first.
|
||||||
|
else if (command == "completed") { if (gc) gcMod = tdb.gc (); out = handleCompleted (tdb, task); }
|
||||||
|
else if (command == "next") { if (gc) gcMod = tdb.gc (); out = handleReportNext (tdb, task); }
|
||||||
|
else if (command == "active") { if (gc) gcMod = tdb.gc (); out = handleReportActive (tdb, task); }
|
||||||
|
else if (command == "overdue") { if (gc) gcMod = tdb.gc (); out = handleReportOverdue (tdb, task); }
|
||||||
|
else if (isCustomReport (command)) { if (gc) gcMod = tdb.gc (); out = handleCustomReport (tdb, task, command); }
|
||||||
|
|
||||||
|
// If the command is not recognized, display usage.
|
||||||
|
else { out = shortUsage (); }
|
||||||
|
|
||||||
|
// Only update the shadow file if such an update was not suppressed (shadow),
|
||||||
|
// and if an actual change occurred (gcMod || cmdMod).
|
||||||
|
if (shadow && (gcMod || cmdMod))
|
||||||
|
updateShadowFile (tdb);
|
||||||
|
|
||||||
|
return out;
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
void Context::shadow ()
|
||||||
|
{
|
||||||
|
throw std::string ("unimplemented Context::shadow");
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Context::loadCorrectConfigFile ()
|
void Context::loadCorrectConfigFile ()
|
||||||
{
|
{
|
||||||
|
@ -237,7 +322,6 @@ void Context::loadCorrectConfigFile ()
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
void Context::parse ()
|
void Context::parse ()
|
||||||
{
|
{
|
||||||
command = "";
|
|
||||||
std::string descCandidate = "";
|
std::string descCandidate = "";
|
||||||
bool terminated = false;
|
bool terminated = false;
|
||||||
bool foundSequence = false;
|
bool foundSequence = false;
|
||||||
|
@ -249,15 +333,18 @@ void Context::parse ()
|
||||||
{
|
{
|
||||||
// The '--' argument shuts off all parsing - everything is an argument.
|
// The '--' argument shuts off all parsing - everything is an argument.
|
||||||
if (*arg == "--")
|
if (*arg == "--")
|
||||||
|
{
|
||||||
|
std::cout << "# parse terminator '" << *arg << "'" << std::endl;
|
||||||
terminated = true;
|
terminated = true;
|
||||||
|
}
|
||||||
|
|
||||||
// Sequence
|
// Sequence
|
||||||
// Note: "add" doesn't require an ID
|
// Note: "add" doesn't require an ID
|
||||||
else if (command != "add" &&
|
else if (cmd.command != "add" &&
|
||||||
sequence.valid (*arg) &&
|
! foundSomethingAfterSequence &&
|
||||||
! foundSomethingAfterSequence)
|
sequence.valid (*arg))
|
||||||
{
|
{
|
||||||
std::cout << "# found sequence" << std::endl;
|
std::cout << "# parse sequence '" << *arg << "'" << std::endl;
|
||||||
sequence.parse (*arg);
|
sequence.parse (*arg);
|
||||||
foundSequence = true;
|
foundSequence = true;
|
||||||
}
|
}
|
||||||
|
@ -309,30 +396,25 @@ void Context::parse ()
|
||||||
if (foundSequence)
|
if (foundSequence)
|
||||||
foundSomethingAfterSequence = true;
|
foundSomethingAfterSequence = true;
|
||||||
|
|
||||||
std::cout << "# found subst" << std::endl;
|
std::cout << "# parse subst '" << *arg << "'" << std::endl;
|
||||||
subst.parse (*arg);
|
subst.parse (*arg);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
// Command.
|
// It might be a command if one has not already been found.
|
||||||
else if (command == "")
|
else if (cmd.command == "" &&
|
||||||
|
cmd.valid (*arg))
|
||||||
{
|
{
|
||||||
|
std::cout << "# parse cmd '" << *arg << "'" << std::endl;
|
||||||
|
cmd.parse (*arg);
|
||||||
|
|
||||||
if (foundSequence)
|
if (foundSequence)
|
||||||
foundSomethingAfterSequence = true;
|
foundSomethingAfterSequence = true;
|
||||||
|
}
|
||||||
|
|
||||||
std::string l = lowerCase (arg);
|
|
||||||
if (isCommand (l) && validCommand (l))
|
|
||||||
command = l;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (descCandidate.length ())
|
|
||||||
descCandidate += " ";
|
|
||||||
descCandidate += arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// Anything else is just considered description.
|
// Anything else is just considered description.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
std::cout << "# parse description '" << *arg << "'" << std::endl;
|
||||||
if (foundSequence)
|
if (foundSequence)
|
||||||
foundSomethingAfterSequence = true;
|
foundSomethingAfterSequence = true;
|
||||||
|
|
||||||
|
@ -345,6 +427,7 @@ void Context::parse ()
|
||||||
// terminated, therefore everything subsequently is a description.
|
// terminated, therefore everything subsequently is a description.
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
std::cout << "# parse post-termination description '" << *arg << "'" << std::endl;
|
||||||
if (foundSequence)
|
if (foundSequence)
|
||||||
foundSomethingAfterSequence = true;
|
foundSomethingAfterSequence = true;
|
||||||
|
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Sequence.h"
|
#include "Sequence.h"
|
||||||
#include "Subst.h"
|
#include "Subst.h"
|
||||||
|
#include "Cmd.h"
|
||||||
#include "T2.h"
|
#include "T2.h"
|
||||||
#include "TDB2.h"
|
#include "TDB2.h"
|
||||||
#include "StringTable.h"
|
#include "StringTable.h"
|
||||||
|
@ -47,6 +48,8 @@ public:
|
||||||
void initialize (int, char**); // all startup
|
void initialize (int, char**); // all startup
|
||||||
int run (); // task classic
|
int run (); // task classic
|
||||||
int interactive (); // task interactive (not implemented)
|
int interactive (); // task interactive (not implemented)
|
||||||
|
void dispatch (); // command handler dispatch
|
||||||
|
void shadow (); // shadow file update
|
||||||
|
|
||||||
void message (const std::string&); // Message sink
|
void message (const std::string&); // Message sink
|
||||||
void footnote (const std::string&); // Footnote sink
|
void footnote (const std::string&); // Footnote sink
|
||||||
|
@ -64,8 +67,9 @@ public:
|
||||||
T2 task;
|
T2 task;
|
||||||
TDB2 tdb;
|
TDB2 tdb;
|
||||||
StringTable stringtable;
|
StringTable stringtable;
|
||||||
|
std::string program;
|
||||||
std::vector <std::string> args;
|
std::vector <std::string> args;
|
||||||
std::string command;
|
Cmd cmd;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector <std::string> messages;
|
std::vector <std::string> messages;
|
||||||
|
|
|
@ -68,6 +68,12 @@ bool Sequence::valid (const std::string& input) const
|
||||||
if (range.size () < 1 ||
|
if (range.size () < 1 ||
|
||||||
range.size () > 2)
|
range.size () > 2)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (range.size () == 1 && !validId (range[0]))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (range.size () == 2 && !validId (range[1]))
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -5,7 +5,7 @@ LIBS =
|
||||||
OBJECTS = main.o ../Context.o ../TDB2.o ../T2.o ../Sequence.o ../Filter.o \
|
OBJECTS = main.o ../Context.o ../TDB2.o ../T2.o ../Sequence.o ../Filter.o \
|
||||||
../Att.o ../Keymap.o ../Record.o ../StringTable.o ../Location.o \
|
../Att.o ../Keymap.o ../Record.o ../StringTable.o ../Location.o \
|
||||||
../util.o ../text.o ../Date.o ../Config.o ../Subst.o ../Nibbler.o \
|
../util.o ../text.o ../Date.o ../Config.o ../Subst.o ../Nibbler.o \
|
||||||
../parse.o ../Duration.o ../T.o
|
../parse.o ../Duration.o ../T.o ../Cmd.o
|
||||||
|
|
||||||
all: $(PROJECT)
|
all: $(PROJECT)
|
||||||
|
|
||||||
|
|
|
@ -304,7 +304,7 @@ int main (int argc, char** argv)
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
context.initialize (argc, argv);
|
context.initialize (argc, argv);
|
||||||
if (context.args[0].find ("itask") != std::string::npos)
|
if (context.program.find ("itask") != std::string::npos)
|
||||||
status = context.interactive ();
|
status = context.interactive ();
|
||||||
else
|
else
|
||||||
status = context.run ();
|
status = context.run ();
|
||||||
|
|
|
@ -48,6 +48,8 @@ int main (int argc, char** argv)
|
||||||
t.notok (seq.valid ("1--2"), "not valid 1--2");
|
t.notok (seq.valid ("1--2"), "not valid 1--2");
|
||||||
t.notok (seq.valid ("1-2-3"), "not valid 1-2-3");
|
t.notok (seq.valid ("1-2-3"), "not valid 1-2-3");
|
||||||
t.notok (seq.valid ("-1-2"), "not valid -1-2");
|
t.notok (seq.valid ("-1-2"), "not valid -1-2");
|
||||||
|
t.notok (seq.valid ("1-two"), "not valid 1-two");
|
||||||
|
t.notok (seq.valid ("one-2"), "not valid one-2");
|
||||||
|
|
||||||
t.ok (seq.valid ("1"), "valid 1");
|
t.ok (seq.valid ("1"), "valid 1");
|
||||||
t.ok (seq.valid ("1,3"), "valid 1,3");
|
t.ok (seq.valid ("1,3"), "valid 1,3");
|
||||||
|
@ -55,8 +57,6 @@ int main (int argc, char** argv)
|
||||||
t.ok (seq.valid ("1,3-5,7"), "valid 1,3-5,7");
|
t.ok (seq.valid ("1,3-5,7"), "valid 1,3-5,7");
|
||||||
t.ok (seq.valid ("1-1000"), "valid 1-1000");
|
t.ok (seq.valid ("1-1000"), "valid 1-1000");
|
||||||
t.ok (seq.valid ("1-1001"), "valid 1-1001");
|
t.ok (seq.valid ("1-1001"), "valid 1-1001");
|
||||||
t.ok (seq.valid ("1-two"), "valid 1-two");
|
|
||||||
t.ok (seq.valid ("one-2"), "valid one-2");
|
|
||||||
t.ok (seq.valid ("1-5,3-7"), "valid 1-5,3-7");
|
t.ok (seq.valid ("1-5,3-7"), "valid 1-5,3-7");
|
||||||
|
|
||||||
// 1
|
// 1
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue