mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Enhancement - header, footer, message
- Added header, footer and message sinks. - Added individual colorization of headers, footers and messages. - Added new configuration variables to Config.cpp, taskrc.5. - Added colorization functions to rules.cpp
This commit is contained in:
parent
e7a0a20d55
commit
8a22ac7cf2
8 changed files with 130 additions and 46 deletions
|
@ -230,6 +230,18 @@ Colors any task assigned to project X.
|
|||
.TP
|
||||
.B color.keyword.X=on_blue
|
||||
Colors any task where the description contains X.
|
||||
|
||||
.TP
|
||||
.B color.header=green
|
||||
Colors any of the messages printed prior to the report output.
|
||||
|
||||
.TP
|
||||
.B color.message=green
|
||||
Colors any of the messages printed after the report output.
|
||||
|
||||
.TP
|
||||
.B color.footnote=green
|
||||
Colors any of the messages printed last.
|
||||
.RE
|
||||
|
||||
.TP
|
||||
|
|
|
@ -147,6 +147,9 @@ void Config::createDefault (const std::string& home)
|
|||
fprintf (out, "#color.project.garden=on_green\n"); // TODO i18n
|
||||
fprintf (out, "#color.keyword.car=on_blue\n"); // TODO i18n
|
||||
fprintf (out, "#color.recurring=on_red\n"); // TODO i18n
|
||||
fprintf (out, "#color.header=bold_green\n"); // TODO i18n
|
||||
fprintf (out, "#color.footnote=bold_green\n"); // TODO i18n
|
||||
fprintf (out, "#color.message=bold_red\n"); // TODO i18n
|
||||
fprintf (out, "#shadow.file=%s/shadow.txt\n", dataDir.c_str ()); // TODO i18n
|
||||
fprintf (out, "#shadow.command=list\n"); // TODO i18n
|
||||
fprintf (out, "#shadow.notify=on\n"); // TODO i18n
|
||||
|
|
|
@ -100,6 +100,9 @@ void Context::initialize ()
|
|||
config.set ("color", "off");
|
||||
}
|
||||
|
||||
if (config.get ("color", true))
|
||||
initializeColorRules ();
|
||||
|
||||
// Load appropriate stringtable as soon after the config file as possible, to
|
||||
// allow all subsequent messages to be localizable.
|
||||
std::string location = expandPath (config.get ("data.location"));
|
||||
|
@ -126,10 +129,11 @@ void Context::initialize ()
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
int Context::run ()
|
||||
{
|
||||
std::string output;
|
||||
try
|
||||
{
|
||||
parse (); // Parse command line.
|
||||
std::cout << dispatch (); // Dispatch to command handlers.
|
||||
output = dispatch (); // Dispatch to command handlers.
|
||||
}
|
||||
|
||||
catch (const std::string& error)
|
||||
|
@ -142,15 +146,23 @@ int Context::run ()
|
|||
message (stringtable.get (100, "Unknown error."));
|
||||
}
|
||||
|
||||
// Dump all headers.
|
||||
foreach (h, headers)
|
||||
std::cout << colorizeHeader (*h) << std::endl;
|
||||
|
||||
// Dump the report output.
|
||||
std::cout << output;
|
||||
|
||||
// Dump all messages.
|
||||
foreach (m, messages)
|
||||
std::cout << *m << std::endl;
|
||||
std::cout << colorizeMessage (*m) << std::endl;
|
||||
|
||||
// Dump all footnotes.
|
||||
if (footnotes.size ())
|
||||
{
|
||||
std::cout << std::endl;
|
||||
foreach (f, footnotes)
|
||||
std::cout << *f << std::endl;
|
||||
std::cout << colorizeFootnote (*f) << std::endl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -347,10 +359,10 @@ void Context::parse ()
|
|||
{
|
||||
// The '--' argument shuts off all parsing - everything is an argument.
|
||||
if (*arg == "--")
|
||||
{
|
||||
std::cout << "[1;31m# parse terminator '" << *arg << "'[0m" << std::endl;
|
||||
{
|
||||
header ("parse terminator '" + *arg + "'");
|
||||
terminated = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Sequence
|
||||
// Note: "add" doesn't require an ID
|
||||
|
@ -358,7 +370,7 @@ std::cout << "[1;31m# parse terminator '" << *arg << "'[0m" << std::endl;
|
|||
! foundSomethingAfterSequence &&
|
||||
sequence.valid (*arg))
|
||||
{
|
||||
std::cout << "[1;31m# parse sequence '" << *arg << "'[0m" << std::endl;
|
||||
header ("parse sequence '" + *arg + "'");
|
||||
sequence.parse (*arg);
|
||||
foundSequence = true;
|
||||
}
|
||||
|
@ -368,7 +380,7 @@ std::cout << "[1;31m# parse sequence '" << *arg << "'[0m" << std::endl;
|
|||
(*arg)[0] == '+' &&
|
||||
validTag (*arg))
|
||||
{
|
||||
std::cout << "[1;31m# parse tag addition '" << *arg << "'[0m" << std::endl;
|
||||
header ("parse tag addition '" + *arg + "'");
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
|
@ -381,7 +393,7 @@ std::cout << "[1;31m# parse tag addition '" << *arg << "'[0m" << std::endl;
|
|||
(*arg)[0] == '-' &&
|
||||
validTag (*arg))
|
||||
{
|
||||
std::cout << "[1;31m# parse tag removal '" << *arg << "'[0m" << std::endl;
|
||||
header ("parse tag removal '" + *arg + "'");
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
|
@ -395,7 +407,7 @@ std::cout << "[1;31m# parse tag removal '" << *arg << "'[0m" << std::endl;
|
|||
// Atributes - name[.mod]:[value]
|
||||
else if (attribute.valid (*arg))
|
||||
{
|
||||
std::cout << "[1;31m# parse attribute '" << *arg << "'[0m" << std::endl;
|
||||
header ("parse attribute '" + *arg + "'");
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
|
@ -419,7 +431,7 @@ std::cout << "[1;31m# parse attribute '" << *arg << "'[0m" << std::endl;
|
|||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
std::cout << "[1;31m# parse subst '" << *arg << "'[0m" << std::endl;
|
||||
header ("parse subst '" + *arg + "'");
|
||||
subst.parse (*arg);
|
||||
}
|
||||
|
||||
|
@ -427,7 +439,7 @@ std::cout << "[1;31m# parse subst '" << *arg << "'[0m" << std::endl;
|
|||
else if (cmd.command == "" &&
|
||||
cmd.valid (*arg))
|
||||
{
|
||||
std::cout << "[1;31m# parse cmd '" << *arg << "'[0m" << std::endl;
|
||||
header ("parse cmd '" + *arg + "'");
|
||||
cmd.parse (*arg);
|
||||
|
||||
if (foundSequence)
|
||||
|
@ -437,7 +449,7 @@ std::cout << "[1;31m# parse cmd '" << *arg << "'[0m" << std::endl;
|
|||
// Anything else is just considered description.
|
||||
else
|
||||
{
|
||||
std::cout << "[1;31m# parse description '" << *arg << "'[0m" << std::endl;
|
||||
header ("parse description '" + *arg + "'");
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
|
@ -450,7 +462,7 @@ std::cout << "[1;31m# parse description '" << *arg << "'[0m" << std::endl;
|
|||
// terminated, therefore everything subsequently is a description.
|
||||
else
|
||||
{
|
||||
std::cout << "[1;31m# parse post-termination description '" << *arg << "'[0m" << std::endl;
|
||||
header ("parse post-termination description '" + *arg + "'");
|
||||
if (foundSequence)
|
||||
foundSomethingAfterSequence = true;
|
||||
|
||||
|
@ -480,7 +492,7 @@ std::cout << "[1;31m# parse post-termination description '" << *arg << "'[0m"
|
|||
// Stuff the command line.
|
||||
args.clear ();
|
||||
split (args, defaultCommand, ' ');
|
||||
std::cout << "[task " << defaultCommand << "]" << std::endl;
|
||||
header ("[task " + defaultCommand + "]");
|
||||
|
||||
// Reinitialize the context and recurse.
|
||||
initialize ();
|
||||
|
@ -503,7 +515,7 @@ void Context::autoFilter ()
|
|||
foreach (word, words)
|
||||
{
|
||||
filter.push_back (Att ("description", "has", *word));
|
||||
std::cout << "[1;31m# auto filter: " << att->first << ".has:" << *word << "[0m" << std::endl;
|
||||
header ("auto filter: " + att->first + ".has:" + *word);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -511,7 +523,7 @@ void Context::autoFilter ()
|
|||
else if (att->first == "project")
|
||||
{
|
||||
filter.push_back (Att ("project", "startswith", att->second.value ()));
|
||||
std::cout << "[1;31m# auto filter: " << att->first << ".startswith:" << att->second.value () << "[0m" << std::endl;
|
||||
header ("auto filter: " + att->first + ".startswith:" + att->second.value ());
|
||||
}
|
||||
|
||||
// TODO Don't create a uuid for every task?
|
||||
|
@ -523,7 +535,7 @@ void Context::autoFilter ()
|
|||
att->first != "project")
|
||||
{
|
||||
filter.push_back (att->second);
|
||||
std::cout << "[1;31m# auto filter: " << att->first << ":" << att->second.value () << "[0m" << std::endl;
|
||||
header ("auto filter: " + att->first + ":" + att->second.value ());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -533,17 +545,23 @@ void Context::autoFilter ()
|
|||
foreach (tag, tagAdditions)
|
||||
{
|
||||
filter.push_back (Att ("tags", "has", *tag));
|
||||
std::cout << "[1;31m# auto filter: +" << *tag << "[0m" << std::endl;
|
||||
header ("auto filter: +" + *tag);
|
||||
}
|
||||
|
||||
// Include tagRemovals.
|
||||
foreach (tag, tagRemovals)
|
||||
{
|
||||
filter.push_back (Att ("tags", "hasnt", *tag));
|
||||
std::cout << "[1;31m# auto filter: -" << *tag << "[0m" << std::endl;
|
||||
header ("auto filter: -" + *tag);
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Context::header (const std::string& input)
|
||||
{
|
||||
headers.push_back (input);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
void Context::message (const std::string& input)
|
||||
{
|
||||
|
|
|
@ -52,6 +52,7 @@ public:
|
|||
|
||||
int getWidth (); // determine terminal width
|
||||
|
||||
void header (const std::string&); // Header sink
|
||||
void message (const std::string&); // Message sink
|
||||
void footnote (const std::string&); // Footnote sink
|
||||
|
||||
|
@ -76,6 +77,7 @@ public:
|
|||
std::vector <std::string> tagRemovals;
|
||||
|
||||
private:
|
||||
std::vector <std::string> headers;
|
||||
std::vector <std::string> messages;
|
||||
std::vector <std::string> footnotes;
|
||||
bool inShadow;
|
||||
|
|
|
@ -380,14 +380,15 @@ std::string handleVersion ()
|
|||
std::string recognized =
|
||||
" blanklines color color.active color.due color.overdue color.pri.H "
|
||||
"color.pri.L color.pri.M color.pri.none color.recurring color.tagged "
|
||||
"confirmation curses data.location dateformat default.command "
|
||||
"default.priority defaultwidth displayweeknumber due echo.command locale "
|
||||
"locking monthsperline nag next project shadow.command shadow.file "
|
||||
"shadow.notify weekstart editor import.synonym.id import.synonym.uuid "
|
||||
"import.synonym.status import.synonym.tags import.synonym.entry "
|
||||
"import.synonym.start import.synonym.due import.synonym.recur "
|
||||
"import.synonym.end import.synonym.project import.synonym.priority "
|
||||
"import.synonym.fg import.synonym.bg import.synonym.description ";
|
||||
"color.footnote color.message confirmation curses data.location dateformat "
|
||||
"default.command default.priority defaultwidth displayweeknumber due "
|
||||
"echo.command locale locking monthsperline nag next project shadow.command "
|
||||
"shadow.file shadow.notify weekstart editor import.synonym.id "
|
||||
"import.synonym.uuid import.synonym.status import.synonym.tags "
|
||||
"import.synonym.entry import.synonym.start import.synonym.due "
|
||||
"import.synonym.recur import.synonym.end import.synonym.project "
|
||||
"import.synonym.priority import.synonym.fg import.synonym.bg "
|
||||
"import.synonym.description ";
|
||||
|
||||
// This configuration variable is supported, but not documented. It exists
|
||||
// so that unit tests can force color to be on even when the output from task
|
||||
|
|
|
@ -116,7 +116,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
|
||||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount, task->id);
|
||||
table.addCell (row++, columnCount, task->id);
|
||||
}
|
||||
|
||||
else if (*col == "uuid")
|
||||
|
@ -127,7 +127,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
|
||||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount, task->get ("uuid"));
|
||||
table.addCell (row++, columnCount, task->get ("uuid"));
|
||||
}
|
||||
|
||||
else if (*col == "project")
|
||||
|
@ -138,7 +138,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
|
||||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount, task->get ("project"));
|
||||
table.addCell (row++, columnCount, task->get ("project"));
|
||||
}
|
||||
|
||||
else if (*col == "priority")
|
||||
|
@ -149,7 +149,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
|
||||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount, task->get ("priority"));
|
||||
table.addCell (row++, columnCount, task->get ("priority"));
|
||||
}
|
||||
|
||||
else if (*col == "entry")
|
||||
|
@ -167,7 +167,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
{
|
||||
Date dt (::atoi (entered.c_str ()));
|
||||
entered = dt.toString (context.config.get ("dateformat", "m/d/Y"));
|
||||
table.addCell (++row, columnCount, entered);
|
||||
table.addCell (row++, columnCount, entered);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -187,7 +187,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
{
|
||||
Date dt (::atoi (started.c_str ()));
|
||||
started = dt.toString (context.config.get ("dateformat", "m/d/Y"));
|
||||
table.addCell (++row, columnCount, started);
|
||||
table.addCell (row++, columnCount, started);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -207,7 +207,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
{
|
||||
Date dt (::atoi (started.c_str ()));
|
||||
started = dt.toString (context.config.get ("dateformat", "m/d/Y"));
|
||||
table.addCell (++row, columnCount, started);
|
||||
table.addCell (row++, columnCount, started);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
int row = 0;
|
||||
std::string due;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount, getDueDate (*task));
|
||||
table.addCell (row++, columnCount, getDueDate (*task));
|
||||
|
||||
dueColumn = columnCount;
|
||||
}
|
||||
|
@ -243,7 +243,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
{
|
||||
Date dt (::atoi (created.c_str ()));
|
||||
age = formatSeconds ((time_t) (now - dt));
|
||||
table.addCell (++row, columnCount, age);
|
||||
table.addCell (row++, columnCount, age);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
{
|
||||
Date dt (::atoi (created.c_str ()));
|
||||
age = formatSecondsCompact ((time_t) (now - dt));
|
||||
table.addCell (++row, columnCount, age);
|
||||
table.addCell (row++, columnCount, age);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -279,7 +279,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
if (task->get ("start") != "")
|
||||
table.addCell (++row, columnCount, "*");
|
||||
table.addCell (row++, columnCount, "*");
|
||||
}
|
||||
|
||||
else if (*col == "tags")
|
||||
|
@ -295,7 +295,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
{
|
||||
task->getTags (all);
|
||||
join (tags, " ", all);
|
||||
table.addCell (++row, columnCount, tags);
|
||||
table.addCell (row++, columnCount, tags);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -307,7 +307,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
|
||||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount, task->get ("description"));
|
||||
table.addCell (row++, columnCount, task->get ("description"));
|
||||
}
|
||||
|
||||
else if (*col == "description")
|
||||
|
@ -318,7 +318,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
|
||||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount, getFullDescription (*task));
|
||||
table.addCell (row++, columnCount, getFullDescription (*task));
|
||||
}
|
||||
|
||||
else if (*col == "recur")
|
||||
|
@ -329,7 +329,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
|
||||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount, task->get ("recur"));
|
||||
table.addCell (row++, columnCount, task->get ("recur"));
|
||||
}
|
||||
|
||||
else if (*col == "recurrence_indicator")
|
||||
|
@ -340,7 +340,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
|
||||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount,
|
||||
table.addCell (row++, columnCount,
|
||||
task->get ("recur") != "" ? "R" : "");
|
||||
}
|
||||
|
||||
|
@ -352,7 +352,7 @@ std::string handleCustomReport (const std::string& report)
|
|||
|
||||
int row = 0;
|
||||
foreach (task, tasks)
|
||||
table.addCell (++row, columnCount,
|
||||
table.addCell (row++, columnCount,
|
||||
task->getTagCount () ? "+" : "");
|
||||
}
|
||||
|
||||
|
|
|
@ -102,6 +102,9 @@ std::string handleCustomReport (const std::string&);
|
|||
// rules.cpp
|
||||
void initializeColorRules ();
|
||||
void autoColorize (Task&, Text::color&, Text::color&);
|
||||
std::string colorizeHeader (const std::string&);
|
||||
std::string colorizeMessage (const std::string&);
|
||||
std::string colorizeFootnote (const std::string&);
|
||||
|
||||
// import.cpp
|
||||
std::string handleImport ();
|
||||
|
|
|
@ -236,4 +236,49 @@ void autoColorize (
|
|||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string colorizeHeader (const std::string& input)
|
||||
{
|
||||
if (gsFg["color.header"] != Text::nocolor ||
|
||||
gsBg["color.header"] != Text::nocolor)
|
||||
{
|
||||
return Text::colorize (
|
||||
gsFg["color.header"],
|
||||
gsBg["color.header"],
|
||||
input);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string colorizeMessage (const std::string& input)
|
||||
{
|
||||
if (gsFg["color.message"] != Text::nocolor ||
|
||||
gsBg["color.message"] != Text::nocolor)
|
||||
{
|
||||
return Text::colorize (
|
||||
gsFg["color.message"],
|
||||
gsBg["color.message"],
|
||||
input);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string colorizeFootnote (const std::string& input)
|
||||
{
|
||||
if (gsFg["color.footnote"] != Text::nocolor ||
|
||||
gsBg["color.footnote"] != Text::nocolor)
|
||||
{
|
||||
return Text::colorize (
|
||||
gsFg["color.footnote"],
|
||||
gsBg["color.footnote"],
|
||||
input);
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue