# # # add_file "diff_colorizer.cc" # content [517669de6f3104480f3df75c463c15a4b93257d0] # # add_file "diff_colorizer.hh" # content [fa6402717dc47a53e79fabda1d94bb4a9cda655f] # # patch "Makefile.am" # from [f782372bdf843356251f455a1ad1559cb464326f] # to [ad74b99b817f166a80650aef587a4d65edecd482] # # patch "cmd_diff_log.cc" # from [bd1b283c47bb14e7f561d1fae2d479cedc365ee2] # to [7ab2f84093a7130644a11f740eae685a192b3db7] # # patch "cmd_files.cc" # from [0e0f670c8b91d458f67261ddd56c7623bde50d71] # to [c259141b2dfdf62efb777b1c33e3ba84f10e4ddf] # # patch "diff_output.cc" # from [746af1eeaa7fee943bf1264dc88ddd6e218c7866] # to [0bc645fe55f2baa35d8e77c6a8be521a8347248b] # # patch "diff_output.hh" # from [9125ccd0d0fa725782c9910b5f34e844048d2da8] # to [47ea2a783e32e6183fe07204e957269cd02c6677] # # patch "options_list.hh" # from [8a5da3dc9c861616ba52de164348285ea902e432] # to [78f2f099c82e0e175a3aa64c0e44865be32b2a2a] # ============================================================ --- diff_colorizer.cc 517669de6f3104480f3df75c463c15a4b93257d0 +++ diff_colorizer.cc 517669de6f3104480f3df75c463c15a4b93257d0 @@ -0,0 +1,48 @@ +// Copyright (C) 2010 Thomas Keller +// +// This program is made available under the GNU GPL version 2.0 or +// greater. See the accompanying file COPYING for details. +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. + +#include "base.hh" +#include "diff_colorizer.hh" +#include "platform.hh" + +using std::string; +using std::map; +using std::make_pair; + +diff_colorizer::diff_colorizer(bool enable) +{ + if (!have_smart_terminal()) + enable = false; + + if (enable) + { + colormap.insert(std::make_pair(normal, "")); + colormap.insert(std::make_pair(encloser, "\033[36m")); + colormap.insert(std::make_pair(add, "\033[32m")); + colormap.insert(std::make_pair(del, "\033[31m")); + colormap.insert(std::make_pair(change, "\033[33m")); + colormap.insert(std::make_pair(reset, "\033[m")); + } +} + +string +diff_colorizer::colorize(string const & in, purpose p) const +{ + if (colormap.find(p) == colormap.end()) + return in; + return colormap.find(p)->second + in + colormap.find(reset)->second; +} + +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: ============================================================ --- diff_colorizer.hh fa6402717dc47a53e79fabda1d94bb4a9cda655f +++ diff_colorizer.hh fa6402717dc47a53e79fabda1d94bb4a9cda655f @@ -0,0 +1,37 @@ +// Copyright (C) 2010 Thomas Keller +// +// This program is made available under the GNU GPL version 2.0 or +// greater. See the accompanying file COPYING for details. +// +// This program is distributed WITHOUT ANY WARRANTY; without even the +// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR +// PURPOSE. + +#ifndef __DIFF_COLORIZER_HH__ +#define __DIFF_COLORIZER_HH__ + +#include "vocab.hh" +#include + +struct diff_colorizer { + + typedef enum { normal = 0, encloser, add, del, change, reset } purpose; + + diff_colorizer(bool enable); + + std::string + colorize(std::string const & in, purpose p = normal) const; + +private: + std::map colormap; +}; + +#endif // __DIFF_COLORIZER_HH__ + +// Local Variables: +// mode: C++ +// fill-column: 76 +// c-file-style: "gnu" +// indent-tabs-mode: nil +// End: +// vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s: ============================================================ --- Makefile.am f782372bdf843356251f455a1ad1559cb464326f +++ Makefile.am ad74b99b817f166a80650aef587a4d65edecd482 @@ -44,6 +44,7 @@ MOST_SOURCES = \ botan_pipe_cache.hh \ cache_logger.hh cache_logger.cc \ commands.cc commands.hh $(CMD_SOURCES) \ + diff_colorizer.cc diff_colorizer.hh \ diff_output.cc diff_output.hh \ lua_hooks.cc lua_hooks.hh \ transforms.cc transforms.hh \ ============================================================ --- cmd_diff_log.cc bd1b283c47bb14e7f561d1fae2d479cedc365ee2 +++ cmd_diff_log.cc 7ab2f84093a7130644a11f740eae685a192b3db7 @@ -17,6 +17,7 @@ #include "asciik.hh" #include "charset.hh" #include "cmd.hh" +#include "diff_colorizer.hh" #include "diff_output.hh" #include "file_io.hh" #include "parallel_iter.hh" @@ -69,6 +70,7 @@ dump_diff(lua_hooks & lua, bool external_diff_args_given, string external_diff_args, string const & encloser, + diff_colorizer const & colorizer, ostream & output) { if (diff_format == external_diff) @@ -110,7 +112,8 @@ dump_diff(lua_hooks & lua, make_diff(left, right, left_id, right_id, left_data, right_data, - output, diff_format, encloser); + output, diff_format, + encloser, colorizer); } } @@ -126,7 +129,8 @@ dump_diffs(lua_hooks & lua, string external_diff_args, bool left_from_db, bool right_from_db, - bool show_encloser) + bool show_encloser, + diff_colorizer const & colorizer) { parallel::iter i(left_roster.all_nodes(), right_roster.all_nodes()); while (i.next()) @@ -162,7 +166,7 @@ dump_diffs(lua_hooks & lua, left_id, right_id, left_data, right_data, diff_format, external_diff_args_given, external_diff_args, - encloser, output); + encloser, colorizer, output); } break; @@ -191,7 +195,7 @@ dump_diffs(lua_hooks & lua, left_id, right_id, left_data, right_data, diff_format, external_diff_args_given, external_diff_args, - encloser, output); + encloser, colorizer, output); } break; @@ -224,7 +228,7 @@ dump_diffs(lua_hooks & lua, left_id, right_id, left_data, right_data, diff_format, external_diff_args_given, external_diff_args, - encloser, output); + encloser, colorizer, output); } break; } @@ -425,7 +429,7 @@ CMD(diff, "diff", "di", CMD_REF(informat "between them is given. If no format is specified, unified is " "used by default."), options::opts::revision | options::opts::depth | options::opts::exclude | - options::opts::diff_options) + options::opts::diff_options | options::opts::colorize) { if (app.opts.external_diff_args_given) E(app.opts.diff_format == external_diff, origin::user, @@ -450,7 +454,8 @@ CMD(diff, "diff", "di", CMD_REF(informat app.opts.external_diff_args_given, app.opts.external_diff_args, old_from_db, new_from_db, - !app.opts.no_show_encloser); + !app.opts.no_show_encloser, + diff_colorizer(app.opts.colorize)); } @@ -488,7 +493,9 @@ CMD_AUTOMATE(content_diff, N_("[FILE [.. dump_diffs(app.lua, db, old_roster, new_roster, output, app.opts.diff_format, app.opts.external_diff_args_given, app.opts.external_diff_args, - old_from_db, new_from_db, !app.opts.no_show_encloser); + old_from_db, new_from_db, + !app.opts.no_show_encloser, + diff_colorizer(false)); // never colorize the diff output } @@ -622,7 +629,8 @@ log_print_rev (app_state & app, app.opts.external_diff_args_given, app.opts.external_diff_args, true, true, - !app.opts.no_show_encloser); + !app.opts.no_show_encloser, + diff_colorizer(app.opts.colorize)); } } } @@ -993,7 +1001,7 @@ CMD(log, "log", "", CMD_REF(informative) options::opts::brief | options::opts::diffs | options::opts::depth | options::opts::exclude | options::opts::no_merges | options::opts::no_files | - options::opts::no_graph) + options::opts::no_graph | options::opts::colorize ) { log_common (app, args, false, cout); } ============================================================ --- cmd_files.cc 0e0f670c8b91d458f67261ddd56c7623bde50d71 +++ cmd_files.cc c259141b2dfdf62efb777b1c33e3ba84f10e4ddf @@ -14,6 +14,7 @@ #include "annotate.hh" #include "revision.hh" #include "cmd.hh" +#include "diff_colorizer.hh" #include "diff_output.hh" #include "merge_content.hh" #include "file_io.hh" @@ -95,7 +96,7 @@ CMD(fdiff, "fdiff", "", CMD_REF(debug), CMD(fdiff, "fdiff", "", CMD_REF(debug), N_("SRCNAME DESTNAME SRCID DESTID"), N_("Differences 2 files and outputs the result"), "", - options::opts::diff_options) + options::opts::diff_options | options::opts::colorize) { if (args.size() != 4) throw usage(execid); @@ -129,7 +130,8 @@ CMD(fdiff, "fdiff", "", CMD_REF(debug), make_diff(src_name, dst_name, src_id, dst_id, src.inner(), dst.inner(), - cout, app.opts.diff_format, pattern); + cout, app.opts.diff_format, + pattern, diff_colorizer(app.opts.colorize)); } CMD(annotate, "annotate", "", CMD_REF(informative), N_("PATH"), ============================================================ --- diff_output.cc 746af1eeaa7fee943bf1264dc88ddd6e218c7866 +++ diff_output.cc 0bc645fe55f2baa35d8e77c6a8be521a8347248b @@ -45,6 +45,8 @@ struct hunk_consumer vector::const_reverse_iterator encloser_last_match; vector::const_reverse_iterator encloser_last_search; + diff_colorizer colorizer; + virtual void flush_hunk(size_t pos) = 0; virtual void advance_to(size_t newpos) = 0; virtual void insert_at(size_t b_pos) = 0; @@ -55,10 +57,12 @@ struct hunk_consumer vector const & b, size_t ctx, ostream & ost, - string const & encloser_pattern) + string const & encloser_pattern, + diff_colorizer const & colorizer) : a(a), b(b), ctx(ctx), ost(ost), encloser_re(0), a_begin(0), b_begin(0), a_len(0), b_len(0), skew(0), - encloser_last_match(a.rend()), encloser_last_search(a.rend()) + encloser_last_match(a.rend()), encloser_last_search(a.rend()), + colorizer(colorizer) { if (encloser_pattern != "") encloser_re.reset(new pcre::regex(encloser_pattern, origin::user)); @@ -170,21 +174,24 @@ struct unidiff_hunk_writer : public hunk vector const & b, size_t ctx, ostream & ost, - string const & encloser_pattern) - : hunk_consumer(a, b, ctx, ost, encloser_pattern) + string const & encloser_pattern, + diff_colorizer const & colorizer) + : hunk_consumer(a, b, ctx, ost, encloser_pattern, colorizer) {} }; void unidiff_hunk_writer::insert_at(size_t b_pos) { b_len++; - hunk.push_back(string("+") + b[b_pos]); + hunk.push_back(colorizer.colorize(string("+") + b[b_pos], + diff_colorizer::add)); } void unidiff_hunk_writer::delete_at(size_t a_pos) { a_len++; - hunk.push_back(string("-") + a[a_pos]); + hunk.push_back(colorizer.colorize(string("-") + a[a_pos], + diff_colorizer::del)); } void unidiff_hunk_writer::flush_hunk(size_t pos) @@ -231,7 +238,8 @@ void unidiff_hunk_writer::flush_hunk(siz } find_encloser(a_begin + first_mod, encloser); - ost << " @@" << encloser << '\n'; + ost << " @@" << colorizer.colorize(encloser, + diff_colorizer::encloser) << '\n'; } copy(hunk.begin(), hunk.end(), ostream_iterator(ost, "\n")); } @@ -297,8 +305,9 @@ struct cxtdiff_hunk_writer : public hunk vector const & b, size_t ctx, ostream & ost, - string const & encloser_pattern) - : hunk_consumer(a, b, ctx, ost, encloser_pattern), + string const & encloser_pattern, + diff_colorizer const & colorizer) + : hunk_consumer(a, b, ctx, ost, encloser_pattern, colorizer), have_insertions(false), have_deletions(false) {} }; @@ -360,7 +369,8 @@ void cxtdiff_hunk_writer::flush_hunk(siz find_encloser(a_begin + min(first_insert, first_delete), encloser); - ost << "***************" << encloser << '\n'; + ost << "***************" << colorizer.colorize(encloser, + diff_colorizer::encloser) << '\n'; } ost << "*** " << (a_begin + 1) << ',' << (a_begin + a_len) << " ****\n"; @@ -394,23 +404,33 @@ void cxtdiff_hunk_writer::flush_pending_ // if we have just insertions to flush, prefix them with "+"; if // just deletions, prefix with "-"; if both, prefix with "!" + diff_colorizer::purpose p = diff_colorizer::normal; if (inserts.empty() && !deletes.empty()) + { prefix = "-"; + p = diff_colorizer::del; + } else if (deletes.empty() && !inserts.empty()) + { prefix = "+"; + p = diff_colorizer::add; + } else + { prefix = "!"; + p = diff_colorizer::change; + } for (vector::const_iterator i = deletes.begin(); i != deletes.end(); ++i) { - from_file.push_back(prefix + string(" ") + a[*i]); + from_file.push_back(colorizer.colorize(prefix + string(" ") + a[*i], p)); a_len++; } for (vector::const_iterator i = inserts.begin(); i != inserts.end(); ++i) { - to_file.push_back(prefix + string(" ") + b[*i]); + to_file.push_back(colorizer.colorize(prefix + string(" ") + b[*i], p)); b_len++; } @@ -471,7 +491,8 @@ make_diff(string const & filename1, data const & data2, ostream & ost, diff_type type, - string const & pattern) + string const & pattern, + diff_colorizer const & colorizer) { if (guess_binary(data1()) || guess_binary(data2())) { @@ -566,23 +587,25 @@ make_diff(string const & filename1, { case unified_diff: { - ost << "--- " << filename1 << '\t' - << id1 << '\n'; - ost << "+++ " << filename2 << '\t' - << id2 << '\n'; + ost << colorizer.colorize(string("--- ") + filename1, diff_colorizer::del) + << '\t' << id1 << '\n'; + ost << colorizer.colorize(string("+++ ") + filename2, diff_colorizer::add) + << '\t' << id2 << '\n'; - unidiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern); + unidiff_hunk_writer hunks(lines1, lines2, 3, ost, + pattern, colorizer); walk_hunk_consumer(lcs, left_interned, right_interned, hunks); break; } case context_diff: { - ost << "*** " << filename1 << '\t' - << id1 << '\n'; - ost << "--- " << filename2 << '\t' - << id2 << '\n'; + ost << colorizer.colorize(string("*** ") + filename1, diff_colorizer::del) + << '\t' << id1 << '\n'; + ost << colorizer.colorize(string("--- ") + filename2, diff_colorizer::add) + << '\t' << id2 << '\n'; - cxtdiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern); + cxtdiff_hunk_writer hunks(lines1, lines2, 3, ost, + pattern, colorizer); walk_hunk_consumer(lcs, left_interned, right_interned, hunks); break; } ============================================================ --- diff_output.hh 9125ccd0d0fa725782c9910b5f34e844048d2da8 +++ diff_output.hh 47ea2a783e32e6183fe07204e957269cd02c6677 @@ -15,6 +15,7 @@ // of GNU-diffutils-like things (diff, diff3, maybe patch..) #include "vocab.hh" +#include "diff_colorizer.hh" void make_diff(std::string const & filename1, std::string const & filename2, @@ -24,7 +25,8 @@ void make_diff(std::string const & filen data const & data2, std::ostream & ost, diff_type type, - std::string const & pattern); + std::string const & pattern, + diff_colorizer const & colorizer); #endif // __DIFF_PATCH_HH__ ============================================================ --- options_list.hh 8a5da3dc9c861616ba52de164348285ea902e432 +++ options_list.hh 78f2f099c82e0e175a3aa64c0e44865be32b2a2a @@ -370,6 +370,14 @@ OPT(diffs, "diffs", bool, false, gettext } #endif + +OPT(colorize, "colorize", bool, false, gettext_noop("colorize diff output")) +#ifdef option_bodies +{ + colorize = true; +} +#endif + OPTVAR(drop_attr, std::set, attrs_to_drop, ) OPTION(drop_attr, drop_attr, true, "drop-attr", gettext_noop("when rosterifying, drop attrs entries with the given key"))