mirror of
https://github.com/GothenburgBitFactory/taskwarrior.git
synced 2025-06-26 10:54:26 +02:00
Journal Feature
- Added change log display to the 'info' command, controlled by the 'journal.info' configuration setting.
This commit is contained in:
parent
31cf470cc8
commit
4c3354fa50
8 changed files with 219 additions and 16 deletions
10
ChangeLog
10
ChangeLog
|
@ -2,11 +2,13 @@
|
|||
------ current release ---------------------------
|
||||
|
||||
1.9.4 ()
|
||||
+ Added burndown charts - burndown.daily, burndown.weekly, burndown.monthly,
|
||||
that use color.burndown.pending, color.burndown.started and
|
||||
color.burndown.done colors.
|
||||
+ Added highlighting for the show command that indicates which values differ
|
||||
+ Added burndown charts - 'burndown.daily', 'burndown.weekly',
|
||||
'burndown.monthly', that use 'color.burndown.pending', 'color.burndown.started'
|
||||
and 'color.burndown.done' colors.
|
||||
+ Added highlighting for the 'show' command that indicates which values differ
|
||||
from the defaults.
|
||||
+ Added change log display to the 'info' command, controlled by the
|
||||
'journal.info' configuration setting.
|
||||
+ Added feature #158, regular expression support for filters and substitutions.
|
||||
+ Added feature #247, providing infinite width reports when redirecting output
|
||||
to a file, by setting defaultwidth to 0.
|
||||
|
|
3
NEWS
3
NEWS
|
@ -7,6 +7,7 @@ New Features in taskwarrior 1.9.4
|
|||
- Regular expression support in filters and substitutions.
|
||||
- Added highlighting for the show command that indicates which values differ
|
||||
from the defaults.
|
||||
- Added change log display to the 'info' command.
|
||||
|
||||
Please refer to the ChangeLog file for full details. There are too many to
|
||||
list here.
|
||||
|
@ -29,6 +30,8 @@ New configuration options in taskwarrior 1.9.4
|
|||
- regex=on enables regular expression searches for filters (task list a...e
|
||||
matches 'above') and substitutions (task <id> /a...e/over/ changes 'above'
|
||||
to 'over'). Default is off, as this is an advanced feature.
|
||||
- journal.info controls whether a change log for each task is displayed by
|
||||
the 'info' command.
|
||||
|
||||
Newly deprecated features in taskwarrior 1.9.4
|
||||
|
||||
|
|
|
@ -474,7 +474,7 @@ turned off by setting the variable to none. The default value is "none".
|
|||
.B journal.time=no
|
||||
May be yes or no, and determines whether the 'start' and 'stop' commands should
|
||||
record an annotation when being executed. The default value is "no". The text of
|
||||
the corresponding annotations is controlled by
|
||||
the corresponding annotations is controlled by:
|
||||
|
||||
.TP journal.time.start.annotation=Started task
|
||||
The text of the annotation that is recorded when executing the start command and
|
||||
|
@ -484,6 +484,10 @@ having set journal.time.
|
|||
The text of the annotation that is recorded when executing the stop command and
|
||||
having set journal.time.
|
||||
|
||||
.TP journal.info=on
|
||||
When enabled, this setting causes a change log of each task to be displayed by
|
||||
the 'info' command. Default value is "on".
|
||||
|
||||
.SS Holidays
|
||||
Holidays are entered either directly in the .taskrc file or via an include file
|
||||
that is specified in .taskrc. For each holiday the name and the date is
|
||||
|
|
|
@ -103,6 +103,7 @@ std::string Config::defaults =
|
|||
"journal.time=no # Record start/stop commands as annotation\n"
|
||||
"journal.time.start.annotation=Started task # Annotation description for the start journal entry\n"
|
||||
"journal.time.stop.annotation=Stopped task # Annotation description for the stop journal entry\n"
|
||||
"journal.info=on # Display task journal with info command\n"
|
||||
"\n"
|
||||
"# Dependency controls\n"
|
||||
"dependency.reminder=on # Nags on dependency chain violations\n"
|
||||
|
|
|
@ -907,7 +907,7 @@ int handleShow (std::string& outs)
|
|||
"default.command default.priority default.project defaultwidth due "
|
||||
"dependency.confirmation dependency.reminder locale displayweeknumber "
|
||||
"export.ical.class echo.command fontunderline locking monthsperline nag "
|
||||
"next journal.time journal.time.start.annotation "
|
||||
"next journal.time journal.time.start.annotation journal.info "
|
||||
"journal.time.stop.annotation project shadow.command shadow.file "
|
||||
"shadow.notify weekstart editor import.synonym.id import.synonym.uuid "
|
||||
"complete.all.projects complete.all.tags search.case.sensitive hooks "
|
||||
|
|
|
@ -37,15 +37,15 @@
|
|||
#include <pwd.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "Context.h"
|
||||
#include "Directory.h"
|
||||
#include "File.h"
|
||||
#include "Date.h"
|
||||
#include "Duration.h"
|
||||
#include "Table.h"
|
||||
#include "text.h"
|
||||
#include "util.h"
|
||||
#include "main.h"
|
||||
#include <Context.h>
|
||||
#include <Directory.h>
|
||||
#include <File.h>
|
||||
#include <Date.h>
|
||||
#include <Duration.h>
|
||||
#include <Table.h>
|
||||
#include <text.h>
|
||||
#include <util.h>
|
||||
#include <main.h>
|
||||
|
||||
#ifdef HAVE_LIBNCURSES
|
||||
#include <ncurses.h>
|
||||
|
@ -396,6 +396,15 @@ int handleInfo (std::string& outs)
|
|||
// Filter sequence.
|
||||
context.filter.applySequence (tasks, context.sequence);
|
||||
|
||||
// Read the undo file.
|
||||
std::vector <std::string> undo;
|
||||
if (context.config.getBoolean ("journal.info"))
|
||||
{
|
||||
Directory location (context.config.get ("data.location"));
|
||||
std::string undoFile = location.data + "/undo.data";
|
||||
File::read (undoFile, undo);
|
||||
}
|
||||
|
||||
// Find the task.
|
||||
std::stringstream out;
|
||||
foreach (task, tasks)
|
||||
|
@ -614,7 +623,7 @@ int handleInfo (std::string& outs)
|
|||
// uuid
|
||||
row = table.addRow ();
|
||||
table.addCell (row, 0, "UUID");
|
||||
value = task->get ("uuid");
|
||||
std::string uuid = value = task->get ("uuid");
|
||||
context.hooks.trigger ("format-uuid", "uuid", value);
|
||||
table.addCell (row, 1, value);
|
||||
|
||||
|
@ -659,17 +668,82 @@ int handleInfo (std::string& outs)
|
|||
//table.addCell (row, 0, "Urgency");
|
||||
//table.addCell (row, 1, task->urgency ());
|
||||
|
||||
Table journal;
|
||||
|
||||
// If an alternating row color is specified, notify the table.
|
||||
if (context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor"))
|
||||
{
|
||||
Color alternate (context.config.get ("color.alternate"));
|
||||
if (alternate.nontrivial ())
|
||||
{
|
||||
table.setTableAlternateColor (alternate);
|
||||
journal.setTableAlternateColor (alternate);
|
||||
}
|
||||
}
|
||||
|
||||
out << optionalBlankLine ()
|
||||
<< table.render ()
|
||||
<< "\n";
|
||||
|
||||
journal.setTableWidth (context.getWidth ());
|
||||
journal.setDateFormat (context.config.get ("dateformat"));
|
||||
|
||||
journal.addColumn ("Date");
|
||||
journal.addColumn ("Modification");
|
||||
|
||||
if ((context.config.getBoolean ("color") || context.config.getBoolean ("_forcecolor")) &&
|
||||
context.config.getBoolean ("fontunderline"))
|
||||
{
|
||||
journal.setColumnUnderline (0);
|
||||
journal.setColumnUnderline (1);
|
||||
}
|
||||
else
|
||||
journal.setTableDashedUnderline ();
|
||||
|
||||
journal.setColumnWidth (0, Table::minimum);
|
||||
journal.setColumnWidth (1, Table::flexible);
|
||||
|
||||
journal.setColumnJustification (0, Table::left);
|
||||
journal.setColumnJustification (1, Table::left);
|
||||
|
||||
if (context.config.getBoolean ("journal.info") &&
|
||||
undo.size () > 3)
|
||||
{
|
||||
// Scan the undo data for entries matching this task.
|
||||
std::string when;
|
||||
std::string previous;
|
||||
std::string current;
|
||||
unsigned int i = 0;
|
||||
while (i < undo.size ())
|
||||
{
|
||||
when = undo[i++];
|
||||
previous = "";
|
||||
if (undo[i].substr (0, 3) == "old")
|
||||
previous = undo[i++];
|
||||
|
||||
current = undo[i++];
|
||||
i++; // Separator
|
||||
|
||||
if (current.find ("uuid:\"" + uuid) != std::string::npos)
|
||||
{
|
||||
if (previous != "")
|
||||
{
|
||||
int row = journal.addRow ();
|
||||
|
||||
Date timestamp (atoi (when.substr (5).c_str ()));
|
||||
journal.addCell (row, 0, timestamp.toString (context.config.get ("dateformat")));
|
||||
|
||||
Task before (previous.substr (4));
|
||||
Task after (current.substr (4));
|
||||
journal.addCell (row, 1, taskInfoDifferences (before, after));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (journal.rowCount () > 0)
|
||||
out << journal.render ()
|
||||
<< "\n";
|
||||
}
|
||||
}
|
||||
|
||||
if (! tasks.size ())
|
||||
|
|
118
src/util.cpp
118
src/util.cpp
|
@ -435,6 +435,124 @@ std::string taskDifferences (const Task& before, const Task& after)
|
|||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string taskInfoDifferences (const Task& before, const Task& after)
|
||||
{
|
||||
// Attributes are all there is, so figure the different attribute names
|
||||
// between before and after.
|
||||
std::vector <std::string> beforeAtts;
|
||||
foreach (att, before)
|
||||
beforeAtts.push_back (att->first);
|
||||
|
||||
std::vector <std::string> afterAtts;
|
||||
foreach (att, after)
|
||||
afterAtts.push_back (att->first);
|
||||
|
||||
std::vector <std::string> beforeOnly;
|
||||
std::vector <std::string> afterOnly;
|
||||
listDiff (beforeAtts, afterAtts, beforeOnly, afterOnly);
|
||||
|
||||
// Now start generating a description of the differences.
|
||||
std::stringstream out;
|
||||
foreach (name, beforeOnly)
|
||||
{
|
||||
if (*name == "depends")
|
||||
{
|
||||
std::vector <int> deps_before;
|
||||
before.getDependencies (deps_before);
|
||||
std::string from;
|
||||
join (from, ",", deps_before);
|
||||
|
||||
out << "dependencies '"
|
||||
<< from
|
||||
<< "' deleted\n";
|
||||
}
|
||||
else if (name->substr (0, 11) == "annotation_")
|
||||
{
|
||||
out << "annotation '"
|
||||
<< before.get (*name)
|
||||
<< "' deleted";
|
||||
}
|
||||
else
|
||||
{
|
||||
out << *name
|
||||
<< " deleted\n";
|
||||
}
|
||||
}
|
||||
|
||||
foreach (name, afterOnly)
|
||||
{
|
||||
if (*name == "depends")
|
||||
{
|
||||
std::vector <int> deps_after;
|
||||
after.getDependencies (deps_after);
|
||||
std::string to;
|
||||
join (to, ",", deps_after);
|
||||
|
||||
out << *name
|
||||
<< " set to '"
|
||||
<< to
|
||||
<< "'\n";
|
||||
}
|
||||
else if (name->substr (0, 11) == "annotation_")
|
||||
{
|
||||
out << "annotation added '"
|
||||
<< after.get (*name)
|
||||
<< "'";
|
||||
}
|
||||
else
|
||||
out << *name
|
||||
<< " set to '"
|
||||
<< renderAttribute (*name, after.get (*name))
|
||||
<< "'\n";
|
||||
}
|
||||
|
||||
foreach (name, beforeAtts)
|
||||
if (*name != "uuid" &&
|
||||
before.get (*name) != after.get (*name))
|
||||
{
|
||||
if (*name == "depends")
|
||||
{
|
||||
std::vector <int> deps_before;
|
||||
before.getDependencies (deps_before);
|
||||
std::string from;
|
||||
join (from, ",", deps_before);
|
||||
|
||||
std::vector <int> deps_after;
|
||||
after.getDependencies (deps_after);
|
||||
std::string to;
|
||||
join (to, ",", deps_after);
|
||||
|
||||
out << *name
|
||||
<< " changed from '"
|
||||
<< from
|
||||
<< "' to '"
|
||||
<< to
|
||||
<< "'\n";
|
||||
}
|
||||
else if (name->substr (0, 11) == "annotation_")
|
||||
{
|
||||
out << "annotation '"
|
||||
<< after.get (*name)
|
||||
<< "'";
|
||||
}
|
||||
else
|
||||
out << *name
|
||||
<< " changed from '"
|
||||
<< renderAttribute (*name, before.get (*name))
|
||||
<< "' to '"
|
||||
<< renderAttribute (*name, after.get (*name))
|
||||
<< "'\n";
|
||||
}
|
||||
|
||||
|
||||
// Shouldn't just say nothing.
|
||||
if (out.str ().length () == 0)
|
||||
out << "No changes made.\n";
|
||||
|
||||
return out.str ();
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
std::string renderAttribute (const std::string& name, const std::string& value)
|
||||
{
|
||||
|
|
|
@ -70,6 +70,7 @@ const std::string uuid ();
|
|||
|
||||
bool taskDiff (const Task&, const Task&);
|
||||
std::string taskDifferences (const Task&, const Task&);
|
||||
std::string taskInfoDifferences (const Task&, const Task&);
|
||||
std::string renderAttribute (const std::string&, const std::string&);
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue