Move diff formatting into Task (simple refactor)

The Task class already included two forms of diff. This adds another
two.
This commit is contained in:
Dustin J. Mitchell 2021-11-18 02:18:39 +00:00 committed by Tomas Babej
parent 8d3953183a
commit 70f83b34ef
3 changed files with 217 additions and 188 deletions

View file

@ -1025,203 +1025,24 @@ void TDB2::show_diff (
Color color_red (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.before") : ""); Color color_red (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.before") : "");
Color color_green (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.after") : ""); Color color_green (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.after") : "");
auto before = prior == "" ? Task() : Task(prior);
auto after = Task(current);
if (Context::getContext ().config.get ("undo.style") == "side") if (Context::getContext ().config.get ("undo.style") == "side")
{ {
Table view = before.diffForUndoSide(after);
std::cout << '\n' std::cout << '\n'
<< format ("The last modification was made {1}", lastChange.toString ()) << format ("The last modification was made {1}", lastChange.toString ())
<< '\n'; << '\n'
<< '\n'
// Attributes are all there is, so figure the different attribute names
// between before and after.
Table view;
view.width (Context::getContext ().getWidth ());
view.intraPadding (2);
view.add ("");
view.add ("Prior Values");
view.add ("Current Values");
setHeaderUnderline (view);
Task after (current);
if (prior != "")
{
Task before (prior);
std::vector <std::string> beforeAtts;
for (auto& att : before.data_removeme ())
beforeAtts.push_back (att.first);
std::vector <std::string> afterAtts;
for (auto& att : after.data_removeme ())
afterAtts.push_back (att.first);
std::vector <std::string> beforeOnly;
std::vector <std::string> afterOnly;
listDiff (beforeAtts, afterAtts, beforeOnly, afterOnly);
int row;
for (auto& name : beforeOnly)
{
row = view.addRow ();
view.set (row, 0, name);
view.set (row, 1, renderAttribute (name, before.get (name)), color_red);
}
for (auto& att : before.data_removeme ())
{
std::string priorValue = before.get (att.first);
std::string currentValue = after.get (att.first);
if (currentValue != "")
{
row = view.addRow ();
view.set (row, 0, att.first);
view.set (row, 1, renderAttribute (att.first, priorValue),
(priorValue != currentValue ? color_red : Color ()));
view.set (row, 2, renderAttribute (att.first, currentValue),
(priorValue != currentValue ? color_green : Color ()));
}
}
for (auto& name : afterOnly)
{
row = view.addRow ();
view.set (row, 0, name);
view.set (row, 2, renderAttribute (name, after.get (name)), color_green);
}
}
else
{
int row;
for (auto& att : after.data_removeme ())
{
row = view.addRow ();
view.set (row, 0, att.first);
view.set (row, 2, renderAttribute (att.first, after.get (att.first)), color_green);
}
}
std::cout << '\n'
<< view.render () << view.render ()
<< '\n'; << '\n';
} }
// This style looks like this:
// --- before 2009-07-04 00:00:25.000000000 +0200
// +++ after 2009-07-04 00:00:45.000000000 +0200
//
// - name: old // att deleted
// + name:
//
// - name: old // att changed
// + name: new
//
// - name:
// + name: new // att added
//
else if (Context::getContext ().config.get ("undo.style") == "diff") else if (Context::getContext ().config.get ("undo.style") == "diff")
{ {
// Create reference tasks. Table view = before.diffForUndoPatch(after, lastChange);
Task before;
if (prior != "")
before.parse (prior);
Task after (current);
// Generate table header.
Table view;
view.width (Context::getContext ().getWidth ());
view.intraPadding (2);
view.add ("");
view.add ("");
int row = view.addRow ();
view.set (row, 0, "--- previous state", color_red);
view.set (row, 1, "Undo will restore this state", color_red);
row = view.addRow ();
view.set (row, 0, "+++ current state ", color_green);
view.set (row, 1, format ("Change made {1}",
lastChange.toString (Context::getContext ().config.get ("dateformat"))),
color_green);
view.addRow ();
// Add rows to table showing diffs.
std::vector <std::string> all = Context::getContext ().getColumns ();
// Now factor in the annotation attributes.
for (auto& it : before.data_removeme ())
if (it.first.substr (0, 11) == "annotation_")
all.push_back (it.first);
for (auto& it : after.data_removeme ())
if (it.first.substr (0, 11) == "annotation_")
all.push_back (it.first);
// Now render all the attributes.
std::sort (all.begin (), all.end ());
std::string before_att;
std::string after_att;
std::string last_att;
for (auto& a : all)
{
if (a != last_att) // Skip duplicates.
{
last_att = a;
before_att = before.get (a);
after_att = after.get (a);
// Don't report different uuid.
// Show nothing if values are the unchanged.
if (a == "uuid" ||
before_att == after_att)
{
// Show nothing - no point displaying that which did not change.
// row = view.addRow ();
// view.set (row, 0, *a + ":");
// view.set (row, 1, before_att);
}
// Attribute deleted.
else if (before_att != "" && after_att == "")
{
row = view.addRow ();
view.set (row, 0, '-' + a + ':', color_red);
view.set (row, 1, before_att, color_red);
row = view.addRow ();
view.set (row, 0, '+' + a + ':', color_green);
}
// Attribute added.
else if (before_att == "" && after_att != "")
{
row = view.addRow ();
view.set (row, 0, '-' + a + ':', color_red);
row = view.addRow ();
view.set (row, 0, '+' + a + ':', color_green);
view.set (row, 1, after_att, color_green);
}
// Attribute changed.
else
{
row = view.addRow ();
view.set (row, 0, '-' + a + ':', color_red);
view.set (row, 1, before_att, color_red);
row = view.addRow ();
view.set (row, 0, '+' + a + ':', color_green);
view.set (row, 1, after_att, color_green);
}
}
}
std::cout << '\n' std::cout << '\n'
<< view.render () << view.render ()
<< '\n'; << '\n';

View file

@ -2425,7 +2425,8 @@ void Task::modify (modType type, bool text_required /* = false */)
#endif #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Compare this task to another and summarize the differences for display // Compare this task to another and summarize the differences for display, in
// the future tense ("Foo will be set to ..").
std::string Task::diff (const Task& after) const std::string Task::diff (const Task& after) const
{ {
// Attributes are all there is, so figure the different attribute names // Attributes are all there is, so figure the different attribute names
@ -2670,3 +2671,206 @@ std::string Task::diffForInfo (
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// Similar to diff, but formatted as a side-by-side table for an Undo preview
Table Task::diffForUndoSide (
const Task& after) const
{
// Set the colors.
Color color_red (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.before") : "");
Color color_green (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.after") : "");
// Attributes are all there is, so figure the different attribute names
// between before and after.
Table view;
view.width (Context::getContext ().getWidth ());
view.intraPadding (2);
view.add ("");
view.add ("Prior Values");
view.add ("Current Values");
setHeaderUnderline (view);
if (!is_empty ())
{
const Task &before = *this;
std::vector <std::string> beforeAtts;
for (auto& att : before.data)
beforeAtts.push_back (att.first);
std::vector <std::string> afterAtts;
for (auto& att : after.data)
afterAtts.push_back (att.first);
std::vector <std::string> beforeOnly;
std::vector <std::string> afterOnly;
listDiff (beforeAtts, afterAtts, beforeOnly, afterOnly);
int row;
for (auto& name : beforeOnly)
{
row = view.addRow ();
view.set (row, 0, name);
view.set (row, 1, renderAttribute (name, before.get (name)), color_red);
}
for (auto& att : before.data)
{
std::string priorValue = before.get (att.first);
std::string currentValue = after.get (att.first);
if (currentValue != "")
{
row = view.addRow ();
view.set (row, 0, att.first);
view.set (row, 1, renderAttribute (att.first, priorValue),
(priorValue != currentValue ? color_red : Color ()));
view.set (row, 2, renderAttribute (att.first, currentValue),
(priorValue != currentValue ? color_green : Color ()));
}
}
for (auto& name : afterOnly)
{
row = view.addRow ();
view.set (row, 0, name);
view.set (row, 2, renderAttribute (name, after.get (name)), color_green);
}
}
else
{
int row;
for (auto& att : after.data)
{
row = view.addRow ();
view.set (row, 0, att.first);
view.set (row, 2, renderAttribute (att.first, after.get (att.first)), color_green);
}
}
return view;
}
////////////////////////////////////////////////////////////////////////////////
// Similar to diff, but formatted as a diff for an Undo preview
Table Task::diffForUndoPatch (
const Task& after,
const Datetime& lastChange) const
{
// This style looks like this:
// --- before 2009-07-04 00:00:25.000000000 +0200
// +++ after 2009-07-04 00:00:45.000000000 +0200
//
// - name: old // att deleted
// + name:
//
// - name: old // att changed
// + name: new
//
// - name:
// + name: new // att added
//
// Set the colors.
Color color_red (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.before") : "");
Color color_green (Context::getContext ().color () ? Context::getContext ().config.get ("color.undo.after") : "");
const Task &before = *this;
// Generate table header.
Table view;
view.width (Context::getContext ().getWidth ());
view.intraPadding (2);
view.add ("");
view.add ("");
int row = view.addRow ();
view.set (row, 0, "--- previous state", color_red);
view.set (row, 1, "Undo will restore this state", color_red);
row = view.addRow ();
view.set (row, 0, "+++ current state ", color_green);
view.set (row, 1, format ("Change made {1}",
lastChange.toString (Context::getContext ().config.get ("dateformat"))),
color_green);
view.addRow ();
// Add rows to table showing diffs.
std::vector <std::string> all = Context::getContext ().getColumns ();
// Now factor in the annotation attributes.
for (auto& it : before.data)
if (it.first.substr (0, 11) == "annotation_")
all.push_back (it.first);
for (auto& it : after.data)
if (it.first.substr (0, 11) == "annotation_")
all.push_back (it.first);
// Now render all the attributes.
std::sort (all.begin (), all.end ());
std::string before_att;
std::string after_att;
std::string last_att;
for (auto& a : all)
{
if (a != last_att) // Skip duplicates.
{
last_att = a;
before_att = before.get (a);
after_att = after.get (a);
// Don't report different uuid.
// Show nothing if values are the unchanged.
if (a == "uuid" ||
before_att == after_att)
{
// Show nothing - no point displaying that which did not change.
// row = view.addRow ();
// view.set (row, 0, *a + ":");
// view.set (row, 1, before_att);
}
// Attribute deleted.
else if (before_att != "" && after_att == "")
{
row = view.addRow ();
view.set (row, 0, '-' + a + ':', color_red);
view.set (row, 1, before_att, color_red);
row = view.addRow ();
view.set (row, 0, '+' + a + ':', color_green);
}
// Attribute added.
else if (before_att == "" && after_att != "")
{
row = view.addRow ();
view.set (row, 0, '-' + a + ':', color_red);
row = view.addRow ();
view.set (row, 0, '+' + a + ':', color_green);
view.set (row, 1, after_att, color_green);
}
// Attribute changed.
else
{
row = view.addRow ();
view.set (row, 0, '-' + a + ':', color_red);
view.set (row, 1, before_att, color_red);
row = view.addRow ();
view.set (row, 0, '+' + a + ':', color_green);
view.set (row, 1, after_att, color_green);
}
}
}
return view;
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -33,6 +33,8 @@
#include <stdio.h> #include <stdio.h>
#include <time.h> #include <time.h>
#include <JSON.h> #include <JSON.h>
#include <Table.h>
#include <Datetime.h>
class Task class Task
{ {
@ -173,6 +175,8 @@ public:
std::string diff (const Task& after) const; std::string diff (const Task& after) const;
std::string diffForInfo (const Task& after, const std::string& dateformat, long& last_timestamp, const long current_timestamp) const; std::string diffForInfo (const Task& after, const std::string& dateformat, long& last_timestamp, const long current_timestamp) const;
Table diffForUndoSide (const Task& after) const;
Table diffForUndoPatch (const Task& after, const Datetime& lastChange) const;
private: private:
int determineVersion (const std::string&); int determineVersion (const std::string&);