[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Monotone-commits-diffs] net.venge.monotone.colored-diff: 3fd6dbdf43313
From: |
code |
Subject: |
[Monotone-commits-diffs] net.venge.monotone.colored-diff: 3fd6dbdf433136f25a57a9043d02020cc4e044ba |
Date: |
Fri, 14 Jan 2011 23:04:19 GMT |
revision: 3fd6dbdf433136f25a57a9043d02020cc4e044ba
date: 2011-01-13T19:39:21
author: Richard Hopkins
branch: net.venge.monotone.colored-diff
changelog:
propagate from branch 'net.venge.monotone' (head
c21a8d05f9dc8d7444416cc47ecf36a3a273c061)
to branch 'net.venge.monotone.colored-diff' (head
86c803294d687290901ebbf1cf2f2196c2faf83d)
manifest:
format_version "1"
new_manifest [d781b37cf34aee864fcd7030b7948cf1799663b9]
old_revision [86c803294d687290901ebbf1cf2f2196c2faf83d]
patch "monotone.texi"
from [be1dd907f6f06074b2c0b4a71fc9f7bca0f345e6]
to [9174c3285ed2ed4b68615cc1e21a041d9e426fb9]
old_revision [c21a8d05f9dc8d7444416cc47ecf36a3a273c061]
add_file "colorizer.cc"
content [c219975b61f0749de94fd6e9a6491022acbde7e3]
add_file "colorizer.hh"
content [acac5ffcef7270972ccd94aa0a671ab27c892450]
patch "Makefile.am"
from [0c1e48ef9dfb72bc9f3ada23437e17c7fca73c18]
to [442ce438b934c521906098ab2e934027a08b0461]
patch "NEWS"
from [f9ce17392993af31e59748c969baa33ab5296c42]
to [d005b48d90eb3b71b743e4696e7625b078660537]
patch "asciik.cc"
from [cf946f9a14ad309615704bc960255c50e12b636a]
to [bdb2253549ec477bf725e9f5ae43c0fa7dff564f]
patch "asciik.hh"
from [592aa966af256f50be9784bfd01c543f54d3447b]
to [3e0dcd90804053a5e558b0ddfa6e5f3dcc462d50]
patch "cmd_diff_log.cc"
from [a3014082674ecb9c3b0617a9603b03452723fec9]
to [9152df5398b88e5d29fc7af0941011c1137e169e]
patch "cmd_files.cc"
from [7e9ffd4a06daeb0ef7ab7557d3a656c6b99ab2ad]
to [8193666bb289537ceb8ce3fd05d85577dada5fe4]
patch "cmd_ws_commit.cc"
from [7b91a53d8eec4e78b062092f85c945bbaaefe23a]
to [cbcbf79937b6a299324b93357770b225d0e6cde2]
patch "diff_output.cc"
from [1e537406208bd9ff6afd2a728389d1c4f34acaf2]
to [9aab77314ce27866f7fee966936480d03fa13220]
patch "diff_output.hh"
from [9125ccd0d0fa725782c9910b5f34e844048d2da8]
to [168281addd27cdade1dc1320ee4814b28070feb8]
patch "monotone.texi"
from [23a45f966060f1b164dd0f7003af4449be8fdb4a]
to [9174c3285ed2ed4b68615cc1e21a041d9e426fb9]
patch "options_list.hh"
from [1985a3326ea833595edf84b75ae5ab9fde487709]
to [6e5020c38127f3e043602673b0c8b12a0dccc9e5]
patch "rev_output.cc"
from [a2c70b893b31296917d1a2b974faa1da46c13f1e]
to [90f5ca2ff78f91bdf512231482d00a2eee37875b]
patch "rev_output.hh"
from [666dd3ed35e16d8b122b4932c2aad05a21a22e25]
to [5879a8268a59545c946583b65f66eda4491b979e]
============================================================
--- monotone.texi be1dd907f6f06074b2c0b4a71fc9f7bca0f345e6
+++ monotone.texi 9174c3285ed2ed4b68615cc1e21a041d9e426fb9
@@ -5263,7 +5263,7 @@ @section Tree
This may be needed when upgrading to a new version of monotone.
@item mtn propagate @var{sourcebranch} @var{destbranch} [--message @var{string}] [--message-file @var{filename}]
-See online help for more options.
+See online help for more options. See @ref{Common Options}.
This command takes a unique head from @var{sourcebranch} and merges it
with a unique head of @var{destbranch}, using the least common
@@ -6635,16 +6635,14 @@ @section Variables
@command{list databases} to work; see @ref{Managed Databases}).
@item mtn set @var{domain} @var{name} @var{value}
-Associates the value @var{value} to @var{name} in domain @var{domain}.
+Associates @var{value} to @var{name} in domain @var{domain}.
See @ref{Vars} for more information.
@item mtn unregister_workspace address@hidden
-Unregisters the given workspace from the current database, so that it
-will no longer show up in the output of @ref{mtn list databases}.
+Unregisters the given workspace (default the current workspace) from
+the current database, so that it will no longer show up in the output
+of @ref{mtn list databases}.
-If no @var{workspace_path} is given, this command defaults to the
-current workspace.
-
@item mtn unset @var{domain} @var{name}
Deletes any value associated with @var{name} in @var{domain}. See
@ref{Vars} for more information.
@@ -6656,21 +6654,18 @@ @section Key and Cert
@section Key and Cert
@ftable @command
address@hidden mtn cert @var{selector} @var{certname}
address@hidden mtn cert @var{selector} @var{certname} @var{certval}
address@hidden mtn cert @var{selector} @var{certname} address@hidden
-These commands create a new certificate with name @var{certname}, for all
-revisions matching @var{selector}. The @var{selector} argument can
-use certs already on the revision, such as @code{h:@var{branchname}}.
+Create a new certificate with name @var{certname}, for all
+revisions matching @var{selector}.
If @var{certval} is provided, it is the value of the certificate.
Otherwise the certificate value is read from @code{stdin}.
@item mtn dropkey @var{keyid}
-This command drops the public and/or private key. If both exist, both
-are dropped, if only one exists, it is dropped. This command should
-be used with caution as changes are irreversible without a backup of
-the key(s) that were dropped.
+Drop the public and/or private key. This command should be used with
+caution as changes are irreversible without a backup of the key(s)
+that were dropped.
@item mtn genkey @var{keyid}
This command generates an @sc{rsa} public/private key pair, using a
@@ -6678,32 +6673,37 @@ @section Key and Cert
the key name @var{keyid.keyhash}. The key's hash is printed out after
the key has been created.
-The private half of the key is stored in an encrypted form, so that anyone
-who can read your keystore cannot extract your private key and use it.
-You must provide a passphrase for your key when it is generated, which is used
-to determine the encryption key. In the future you will need to enter this
-passphrase again each time you sign a certificate, which happens every
-time you @command{commit} to your database. You can tell monotone to
-automatically use a certain passphrase for a given key using the
address@hidden(@var{key_identity})}, but this significantly
-increases the risk of a key compromise on your local computer. Be
-careful using this hook.
+The private half of the key is stored in an encrypted form, so that
+anyone who can read your keystore cannot extract your private key and
+use it. You must provide a passphrase for your key when it is
+generated, which is used to determine the encryption key. In the
+future you will need to enter this passphrase again each time you sign
+a certificate, which happens every time you @command{commit} to your
+database. You can tell monotone to automatically use a certain
+passphrase for a given key using the
address@hidden(@var{key_identity})} (see @ref{get_passphrase}),
+but this significantly increases the risk of a key compromise on your
+local computer. Be careful using this hook.
+Another way to avoid entering the private key passphrase each time it
+is needed is to export it to ssh-agent; see @ref{mtn
+ssh_agent_export}, @ref{mtn ssh_agent_add}.
+
The public key is stored in the database; the public and private keys
are stored in the keystore. This allows copying the database without
copying the private key.
-The location of the keystore is specified by the @option{--keydir}
-option; it defaults to the value stored in @file{_MTN/options} for
-commands executed in a workspace, or to
-the system default (@file{$HOME/.monotone/keys} on Unix and Cygwin,
+The location of the keystore is specified by @option{--keydir}; it
+defaults to the value stored in @file{_MTN/options} for commands
+executed in a workspace, or to the system default
+(@file{$HOME/.monotone/keys} on Unix and Cygwin,
@file{%APPDATA%/monotone/keys} on native Win32).
@item mtn passphrase @var{keyid}
This command lets you change the passphrase of the private half of the
key @var{id}.
address@hidden mtn ssh_agent_add
address@hidden address@hidden mtn ssh_agent_add
This command will add your monotone keys to your current ssh-agent session.
You will be asked for the passphrase for each of your monotone private keys
and they will be added to the ssh-agent. Once this is done you should be able
@@ -6711,6 +6711,10 @@ @section Key and Cert
subsequently use these keys through monotone it will use ssh-agent for signing
without asking your for your passphrase.
+On Windows native, monotone only supports the PuTTY ssh-agent
+implementation. On Windows Cygwin and Unix, any standard ssh-agent
+implementation can be used.
+
This command is mainly for use in a session script as monotone will automatically
add your keys to ssh-agent on first use if it is available. For example the
following two examples are equivalent:
@@ -6735,13 +6739,15 @@ @section Key and Cert
In the second example, monotone automatically added the key to ssh-agent, making
entering the passphrase not needed during the push.
address@hidden mtn ssh_agent_export @var{filename}
address@hidden address@hidden mtn ssh_agent_export address@hidden
+
This command will export your private key in a format that ssh-agent
-can read (PKCS8, PEM). You will be asked for your current key's password
-and a new password to encrypt the key with. The key will be printed to
-stdout. Once you have put this key in a file simply add it to ssh-agent
-and you will only have to enter your key password once as ssh-agent
-will cache the key for you.
+can read (PKCS8, PEM), to @var{filename} (defaults to standard
+output). You will be asked for your current key's monotone password
+and a new password to encrypt the key with (the ssh passphrase). The
+key will be printed to stdout. Once you have put this key in a file
+simply add it to ssh-agent and you will only have to enter your key
+password once as ssh-agent will cache the key for you.
@smallexample
@group
@@ -6778,7 +6784,7 @@ @section Key and Cert
Monotone would trust a cert on that revision with that value signed by
those keys.
-The specified keys mist exist either in your keystore or in the database.
+The specified keys must exist either in your keystore or in the database.
@end ftable
@@ -10244,7 +10250,7 @@ @section Automation
Keyboard interaction is disabled on the server, just as if
@option{--non-interactive} would have been specified on server startup.
Actions which require operations on password-encrypted private keys will
-therefor fail unless a @code{get_passphrase} hook is set up remotely.
+therefor fail unless a @ref{get_passphrase} hook is set up remotely.
@end table
@@ -10293,7 +10299,7 @@ @section Automation
For both, the client and the server, keyboard interaction is disabled,
just as if @option{--non-interactive} is specified. Actions which require
operations on password-encrypted private keys will therefor fail unless the
address@hidden hook is set up locally and / or remotely.
address@hidden hook is set up locally and / or remotely.
@end table
@@ -10952,7 +10958,7 @@ @section Automation
Keyboard interaction is disabled, just as if @option{--non-interactive} is
specified. Actions which require operations on password-encrypted private keys
-will therefor fail unless the @code{get_passphrase} hook is set up locally.
+will therefor fail unless the @ref{get_passphrase} hook is set up locally.
@item Multiple streams
@@ -11711,7 +11717,7 @@ @subsection User Defaults
@end group
@end smallexample
address@hidden get_passphrase (@var{key_identity})
address@hidden@item get_passphrase (@var{key_identity})
Returns a string which is the passphrase used to encrypt the private
half of @var{key_identity} in your key store, using the @sc{TripleDES} symmetric
============================================================
--- Makefile.am 0c1e48ef9dfb72bc9f3ada23437e17c7fca73c18
+++ Makefile.am 442ce438b934c521906098ab2e934027a08b0461
@@ -45,6 +45,7 @@ MOST_SOURCES = \
botan_pipe_cache.hh \
cache_logger.hh cache_logger.cc \
commands.cc commands.hh $(CMD_SOURCES) \
+ colorizer.cc colorizer.hh \
diff_output.cc diff_output.hh \
lua_hooks.cc lua_hooks.hh \
transforms.cc transforms.hh \
============================================================
--- NEWS f9ce17392993af31e59748c969baa33ab5296c42
+++ NEWS d005b48d90eb3b71b743e4696e7625b078660537
@@ -331,6 +331,11 @@ Thu Oct 28 21:07:18 UTC 2010
- New 'k:' selector type to query revisions where at least one
certificate was signed with the given key.
+ - Monotone has a new global '--colorize' option which colors the
+ output of commands like 'diff', 'fdiff' or 'log' for better
+ readability in terminals that support output coloring and
+ formatting.
+
- New automate command 'log' which behaves identical to the
normal 'log' command, except that it only outputs the
revision ids.
============================================================
--- diff_output.cc 1e537406208bd9ff6afd2a728389d1c4f34acaf2
+++ diff_output.cc 9aab77314ce27866f7fee966936480d03fa13220
@@ -17,6 +17,7 @@
#include "simplestring_xform.hh"
#include <ostream>
+#include <sstream>
#include <iterator>
#include <boost/scoped_ptr.hpp>
@@ -25,6 +26,7 @@ using std::string;
using std::ostream;
using std::ostream_iterator;
using std::string;
+using std::stringstream;
using std::vector;
using boost::scoped_ptr;
@@ -45,6 +47,8 @@ struct hunk_consumer
vector<string>::const_reverse_iterator encloser_last_match;
vector<string>::const_reverse_iterator encloser_last_search;
+ colorizer color;
+
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 +59,12 @@ struct hunk_consumer
vector<string> const & b,
size_t ctx,
ostream & ost,
- string const & encloser_pattern)
+ string const & encloser_pattern,
+ colorizer const & color)
: 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()),
+ color(color)
{
if (encloser_pattern != "")
encloser_re.reset(new pcre::regex(encloser_pattern, origin::user));
@@ -170,21 +176,24 @@ struct unidiff_hunk_writer : public hunk
vector<string> const & b,
size_t ctx,
ostream & ost,
- string const & encloser_pattern)
- : hunk_consumer(a, b, ctx, ost, encloser_pattern)
+ string const & encloser_pattern,
+ colorizer const & color)
+ : hunk_consumer(a, b, ctx, ost, encloser_pattern, color)
{}
};
void unidiff_hunk_writer::insert_at(size_t b_pos)
{
b_len++;
- hunk.push_back(string("+") + b[b_pos]);
+ hunk.push_back(color.colorize(string("+") + b[b_pos],
+ colorizer::diff_add));
}
void unidiff_hunk_writer::delete_at(size_t a_pos)
{
a_len++;
- hunk.push_back(string("-") + a[a_pos]);
+ hunk.push_back(color.colorize(string("-") + a[a_pos],
+ colorizer::diff_delete));
}
void unidiff_hunk_writer::flush_hunk(size_t pos)
@@ -201,22 +210,23 @@ void unidiff_hunk_writer::flush_hunk(siz
}
// write hunk to stream
+ stringstream ss;
if (a_len == 0)
- ost << "@@ -0,0";
+ ss << "@@ -0,0";
else
{
- ost << "@@ -" << a_begin+1;
+ ss << "@@ -" << a_begin+1;
if (a_len > 1)
- ost << ',' << a_len;
+ ss << ',' << a_len;
}
-
+
if (b_len == 0)
- ost << " +0,0";
+ ss << " +0,0";
else
{
- ost << " +" << b_begin+1;
+ ss << " +" << b_begin+1;
if (b_len > 1)
- ost << ',' << b_len;
+ ss << ',' << b_len;
}
{
@@ -231,7 +241,11 @@ void unidiff_hunk_writer::flush_hunk(siz
}
find_encloser(a_begin + first_mod, encloser);
- ost << " @@" << encloser << '\n';
+ ss << " @@";
+
+ ost << color.colorize(ss.str(), colorizer::diff_separator);
+ ost << color.colorize(encloser, colorizer::diff_encloser);
+ ost << '\n';
}
copy(hunk.begin(), hunk.end(), ostream_iterator<string>(ost, "\n"));
}
@@ -297,8 +311,9 @@ struct cxtdiff_hunk_writer : public hunk
vector<string> const & b,
size_t ctx,
ostream & ost,
- string const & encloser_pattern)
- : hunk_consumer(a, b, ctx, ost, encloser_pattern),
+ string const & encloser_pattern,
+ colorizer const & colorizer)
+ : hunk_consumer(a, b, ctx, ost, encloser_pattern, colorizer),
have_insertions(false), have_deletions(false)
{}
};
@@ -360,7 +375,8 @@ void cxtdiff_hunk_writer::flush_hunk(siz
find_encloser(a_begin + min(first_insert, first_delete),
encloser);
- ost << "***************" << encloser << '\n';
+ ost << color.colorize("***************", colorizer::diff_separator)
+ << color.colorize(encloser, colorizer::diff_encloser) << '\n';
}
ost << "*** " << (a_begin + 1) << ',' << (a_begin + a_len) << " ****\n";
@@ -394,23 +410,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 "!"
+ colorizer::purpose p = colorizer::normal;
if (inserts.empty() && !deletes.empty())
+ {
prefix = "-";
+ p = colorizer::diff_delete;
+ }
else if (deletes.empty() && !inserts.empty())
+ {
prefix = "+";
+ p = colorizer::diff_add;
+ }
else
+ {
prefix = "!";
+ p = colorizer::diff_change;
+ }
for (vector<size_t>::const_iterator i = deletes.begin();
i != deletes.end(); ++i)
{
- from_file.push_back(prefix + string(" ") + a[*i]);
+ from_file.push_back(color.colorize(prefix + string(" ") + a[*i], p));
a_len++;
}
for (vector<size_t>::const_iterator i = inserts.begin();
i != inserts.end(); ++i)
{
- to_file.push_back(prefix + string(" ") + b[*i]);
+ to_file.push_back(color.colorize(prefix + string(" ") + b[*i], p));
b_len++;
}
@@ -471,16 +497,19 @@ make_diff(string const & filename1,
data const & data2,
ostream & ost,
diff_type type,
- string const & pattern)
+ string const & pattern,
+ colorizer const & color)
{
if (guess_binary(data1()) || guess_binary(data2()))
{
// If a file has been removed, filename2 will be "/dev/null".
// It doesn't make sense to output that.
if (filename2 == "/dev/null")
- ost << "# " << filename1 << " is binary\n";
+ ost << color.colorize(string("# ") + filename1 + " is binary",
+ colorizer::diff_comment) << "\n";
else
- ost << "# " << filename2 << " is binary\n";
+ ost << color.colorize(string("# ") + filename2 + " is binary",
+ colorizer::diff_comment) << "\n";
return;
}
@@ -570,23 +599,23 @@ make_diff(string const & filename1,
{
case unified_diff:
{
- ost << "--- " << filename1 << '\t'
- << id1 << '\n';
- ost << "+++ " << filename2 << '\t'
- << id2 << '\n';
+ ost << color.colorize(string("--- ") + filename1, colorizer::diff_delete)
+ << '\t' << id1 << '\n';
+ ost << color.colorize(string("+++ ") + filename2, colorizer::diff_add)
+ << '\t' << id2 << '\n';
- unidiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern);
+ unidiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern, color);
walk_hunk_consumer(lcs, left_interned, right_interned, hunks);
break;
}
case context_diff:
{
- ost << "*** " << filename1 << '\t'
- << id1 << '\n';
- ost << "--- " << filename2 << '\t'
- << id2 << '\n';
+ ost << color.colorize(string("*** ") + filename1, colorizer::diff_delete)
+ << '\t' << id1 << '\n';
+ ost << color.colorize(string("--- ") + filename2, colorizer::diff_add)
+ << '\t' << id2 << '\n';
- cxtdiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern);
+ cxtdiff_hunk_writer hunks(lines1, lines2, 3, ost, pattern, color);
walk_hunk_consumer(lcs, left_interned, right_interned, hunks);
break;
}
============================================================
--- diff_output.hh 9125ccd0d0fa725782c9910b5f34e844048d2da8
+++ diff_output.hh 168281addd27cdade1dc1320ee4814b28070feb8
@@ -15,6 +15,7 @@
// of GNU-diffutils-like things (diff, diff3, maybe patch..)
#include "vocab.hh"
+#include "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,
+ colorizer const & colorizer);
#endif // __DIFF_PATCH_HH__
============================================================
--- monotone.texi 23a45f966060f1b164dd0f7003af4449be8fdb4a
+++ monotone.texi 9174c3285ed2ed4b68615cc1e21a041d9e426fb9
@@ -6122,7 +6122,7 @@ @section Informative
@code{fa36}. This command is intended to be used by programmable
completion systems, such as those in @command{bash} and @command{zsh}.
address@hidden mtn diff [--unified] [--[no-]show-encloser]
address@hidden mtn diff [--unified] [--[no-]show-encloser] [--[no-]colorize]
@itemx mtn diff --context [--[no-]show-encloser]
@itemx mtn diff --external address@hidden
@itemx mtn diff @var{pathname...}
@@ -6164,7 +6164,7 @@ @section Informative
changed within the current subdirectory of the workspace.
The output format of @command{diff} is controlled by the options
address@hidden, @option{--context}, @option{--no-show-encloser}, and
address@hidden, @option{--context}, @option{--no-show-encloser}, @option{--colorize}, and
@option{--external}. By default, monotone uses its built-in diff
algorithm to produce a listing in ``unified diff'' format (analogous
to running the program @command{diff @option{-u}}); you can also explicitly
@@ -6186,6 +6186,10 @@ @section Informative
@ref{get_encloser_pattern}. For the regular _expression_ syntax, see
@ref{Regexps}.
+Furthermore, when @option{--colorize} is given, monotone tries to print
+colored diff output if the underlying terminal supports it. This works
+in both modes as well.
+
Sometimes, you may want more flexibility in output formats; for these
cases, you can use @option{--external}, which causes monotone to
invoke an external program to generate the actual output. By default,
@@ -6399,7 +6403,7 @@ @section Informative
files to the current subdirectory of the workspace.
@anchor{mtn address@hidden mtn log
address@hidden mtn log address@hidden address@hidden address@hidden [...]] [--clear-from] address@hidden [...]] [--clear-to] address@hidden [...]] [--[no-]brief] [--[no-]merges] [--[no-]files] [--[no-]graph] [--[no-]diffs] address@hidden
address@hidden mtn log address@hidden address@hidden address@hidden [...]] [--clear-from] address@hidden [...]] [--clear-to] address@hidden [...]] [--[no-]brief] [--[no-]merges] [--[no-]files] [--[no-]graph] [--[no-]diffs] [--[no-]colorize] address@hidden
See the online help for more options.
This command prints out a log, in forward ancestry order by default
@@ -6470,8 +6474,11 @@ @section Informative
prefix on log output lines.
Specifying @option{--diffs} causes the log output to include a unified
-diff of the changes in each revision.
+diff of the changes in each revision. If @option{--colorize} is given
+additionally, the diff output is colored if the underlying terminal
+supports that.
+
If one or more files are given, the command will only log the revisions
where those files are changed.
============================================================
--- cmd_diff_log.cc a3014082674ecb9c3b0617a9603b03452723fec9
+++ cmd_diff_log.cc 9152df5398b88e5d29fc7af0941011c1137e169e
@@ -17,6 +17,7 @@
#include "asciik.hh"
#include "charset.hh"
#include "cmd.hh"
+#include "colorizer.hh"
#include "date_format.hh"
#include "diff_output.hh"
#include "file_io.hh"
@@ -70,6 +71,7 @@ dump_diff(lua_hooks & lua,
bool external_diff_args_given,
string external_diff_args,
string const & encloser,
+ colorizer const & colorizer,
ostream & output)
{
if (diff_format == external_diff)
@@ -111,7 +113,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);
}
}
@@ -127,7 +130,8 @@ dump_diffs(lua_hooks & lua,
string external_diff_args,
bool left_from_db,
bool right_from_db,
- bool show_encloser)
+ bool show_encloser,
+ colorizer const & colorizer)
{
parallel::iter<node_map> i(left_roster.all_nodes(), right_roster.all_nodes());
while (i.next())
@@ -163,7 +167,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;
@@ -192,7 +196,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;
@@ -225,7 +229,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;
}
@@ -390,6 +394,7 @@ void dump_header(std::string const & rev
roster_t const & old_roster,
roster_t const & new_roster,
std::ostream & out,
+ colorizer const & colorizer,
bool show_if_empty)
{
cset changes;
@@ -402,19 +407,23 @@ void dump_header(std::string const & rev
vector<string> lines;
split_into_lines(summary(), lines);
- out << "#\n";
+ out << colorizer.colorize("#", colorizer::diff_comment) << "\n";
if (!summary().empty())
{
- out << revs << "#\n";
+ out << colorizer.colorize(revs, colorizer::diff_comment);
+ out << colorizer.colorize("#", colorizer::diff_comment) << "\n";
+
for (vector<string>::iterator i = lines.begin();
i != lines.end(); ++i)
- out << "# " << *i << '\n';
+ out << colorizer.colorize(string("# ") + *i,
+ colorizer::diff_comment) << "\n";
}
else
{
- out << "# " << _("no changes") << '\n';
+ out << colorizer.colorize(string("# ") + _("no changes"),
+ colorizer::diff_comment) << "\n";
}
- out << "#\n";
+ out << colorizer.colorize("#", colorizer::diff_comment) << "\n";
}
CMD_PRESET_OPTIONS(diff)
@@ -445,9 +454,11 @@ CMD(diff, "diff", "di", CMD_REF(informat
prepare_diff(app, db, old_roster, new_roster, args, old_from_db, new_from_db, revs);
+ colorizer colorizer(app.opts.colorize);
+
if (app.opts.with_header)
{
- dump_header(revs, old_roster, new_roster, cout, true);
+ dump_header(revs, old_roster, new_roster, cout, colorizer, true);
}
dump_diffs(app.lua, db, old_roster, new_roster, cout,
@@ -455,7 +466,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,
+ colorizer);
}
@@ -484,16 +496,20 @@ CMD_AUTOMATE(content_diff, N_("[FILE [..
prepare_diff(app, db, old_roster, new_roster, args, old_from_db, new_from_db,
dummy_header);
+ // never colorize the diff output
+ colorizer colorizer(false);
if (app.opts.with_header)
{
- dump_header(dummy_header, old_roster, new_roster, output, false);
+ dump_header(dummy_header, old_roster, new_roster, output, colorizer, false);
}
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,
+ colorizer);
}
@@ -551,27 +567,27 @@ void
rev_cmp> frontier_t;
void
-log_print_rev (app_state & app,
- database & db,
- project_t & project,
- revision_id rid,
- revision_t & rev,
- string date_fmt,
- node_restriction mask,
- ostream & out)
+log_print_rev(app_state & app,
+ database & db,
+ project_t const & project,
+ revision_id const & rid,
+ revision_t const & rev,
+ string const & date_fmt,
+ node_restriction const & mask,
+ colorizer const & color,
+ ostream & out)
{
- cert_name const author_name(author_cert_name);
- cert_name const date_name(date_cert_name);
- cert_name const branch_name(branch_cert_name);
- cert_name const tag_name(tag_cert_name);
- cert_name const changelog_name(changelog_cert_name);
- cert_name const comment_name(comment_cert_name);
vector<cert> certs;
project.get_revision_certs(rid, certs);
if (app.opts.brief)
{
- out << rid;
+ cert_name const author_name(author_cert_name);
+ cert_name const date_name(date_cert_name);
+ cert_name const branch_name(branch_cert_name);
+
+ out << color.colorize(encode_hexenc(rid.inner()(), rid.inner().made_from),
+ colorizer::log_revision);
log_certs(certs, out, author_name);
if (app.opts.no_graph)
log_certs(certs, out, date_name, date_fmt);
@@ -586,7 +602,7 @@ log_print_rev (app_state & app,
else
{
utf8 header;
- revision_header(rid, rev, certs, date_fmt, header);
+ revision_header(rid, rev, certs, date_fmt, color, header);
external header_external;
utf8_to_system_best_effort(header, header_external);
@@ -595,7 +611,7 @@ log_print_rev (app_state & app,
if (!app.opts.no_files)
{
utf8 summary;
- revision_summary(rev, summary);
+ revision_summary(rev, color, summary);
external summary_external;
utf8_to_system_best_effort(summary, summary_external);
out << summary_external;
@@ -627,16 +643,17 @@ 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,
+ color);
}
}
}
void
-log_common (app_state & app,
- args_vector args,
- bool automate,
- std::ostream & output)
+log_common(app_state & app,
+ args_vector args,
+ bool automate,
+ std::ostream & output)
{
database db(app);
project_t project(db);
@@ -846,8 +863,11 @@ log_common (app_state & app,
set<revision_id> seen;
revision_t rev;
+
+ colorizer color(app.opts.colorize && !automate);
// this is instantiated even when not used, but it's lightweight
- asciik graph(output);
+ asciik graph(output, color);
+
while(!frontier.empty() && last != 0 && next != 0)
{
revision_id const & rid = frontier.top().second;
@@ -943,7 +963,7 @@ log_common (app_state & app,
else
{
ostringstream out;
- log_print_rev (app, db, project, rid, rev, date_fmt, mask_diff, out);
+ log_print_rev(app, db, project, rid, rev, date_fmt, mask_diff, color, out);
string out_system;
utf8_to_system_best_effort(utf8(out.str(), origin::internal), out_system);
@@ -991,9 +1011,9 @@ 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 )
{
- log_common (app, args, false, cout);
+ log_common(app, args, false, cout);
}
CMD_AUTOMATE(log, N_("[PATH] ..."),
@@ -1004,7 +1024,7 @@ CMD_AUTOMATE(log, N_("[PATH] ..."),
options::opts::depth | options::opts::exclude |
options::opts::no_merges)
{
- log_common (app, args, true, output);
+ log_common(app, args, true, output);
}
// Local Variables:
============================================================
--- cmd_files.cc 7e9ffd4a06daeb0ef7ab7557d3a656c6b99ab2ad
+++ cmd_files.cc 8193666bb289537ceb8ce3fd05d85577dada5fe4
@@ -14,6 +14,7 @@
#include "annotate.hh"
#include "revision.hh"
#include "cmd.hh"
+#include "colorizer.hh"
#include "diff_output.hh"
#include "merge_content.hh"
#include "file_io.hh"
@@ -132,7 +133,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, colorizer(app.opts.colorize));
}
CMD(annotate, "annotate", "", CMD_REF(informative), N_("PATH"),
============================================================
--- cmd_ws_commit.cc 7b91a53d8eec4e78b062092f85c945bbaaefe23a
+++ cmd_ws_commit.cc cbcbf79937b6a299324b93357770b225d0e6cde2
@@ -259,7 +259,8 @@ get_log_message_interactively(lua_hooks
}
utf8 summary;
- revision_summary(rev, summary);
+ colorizer color(false);
+ revision_summary(rev, color, summary);
utf8 full_message(changelog() + cancel() + instructions() + editable() + ignored() +
notes() + summary(),
@@ -965,10 +966,11 @@ CMD(status, "status", "", CMD_REF(inform
utf8 header;
utf8 summary;
+ colorizer color(app.opts.colorize);
revision_header(rid, rev, author, date_t::now(), app.opts.branch, changelog,
- date_fmt, header);
- revision_summary(rev, summary);
+ date_fmt, color, header);
+ revision_summary(rev, color, summary);
external header_external;
external summary_external;
============================================================
--- options_list.hh 1985a3326ea833595edf84b75ae5ab9fde487709
+++ options_list.hh 6e5020c38127f3e043602673b0c8b12a0dccc9e5
@@ -285,7 +285,8 @@ GROUPED_SIMPLE_OPTION(date_formats, no_f
"no-format-dates", bool,
gettext_noop("print date certs exactly as stored in the database"))
-
+GROUPED_SIMPLE_OPTION(globals, colorize, "colorize/no-colorize", bool,
+ gettext_noop("colorize output"))
OPTVAR(globals, db_type, dbname_type, )
OPTVAR(globals, std::string, dbname_alias, )
OPTVAR(globals, system_path, dbname, )
============================================================
--- asciik.cc cf946f9a14ad309615704bc960255c50e12b636a
+++ asciik.cc bdb2253549ec477bf725e9f5ae43c0fa7dff564f
@@ -135,8 +135,8 @@ static revision_id ghost; // valid but e
static revision_id ghost; // valid but empty revision_id to be used as ghost value
-asciik::asciik(ostream & os, size_t min_width)
- : width(min_width), output(os)
+asciik::asciik(ostream & os, colorizer const & color, size_t min_width)
+ : width(min_width), output(os), color(color)
{
}
@@ -250,10 +250,13 @@ asciik::draw(size_t const curr_items,
// prints it out
//TODO convert line/interline/interline2 from ASCII to system charset
- output << line << " " << lines[0] << '\n';
- output << interline << " " << lines[1] << '\n';
+ output << color.colorize(line, colorizer::log_revision)
+ << " " << lines[0] << '\n';
+ output << color.colorize(interline, colorizer::log_revision)
+ << " " << lines[1] << '\n';
for (int i = 2; i < num_lines; ++i)
- output << interline2 << " " << lines[i] << '\n';
+ output << color.colorize(interline2, colorizer::log_revision)
+ << " " << lines[i] << '\n';
}
bool
@@ -387,7 +390,7 @@ CMD(asciik, "asciik", "", CMD_REF(debug)
toposort(db, revs, sorted);
reverse(sorted.begin(), sorted.end());
- asciik graph(std::cout, 10);
+ asciik graph(std::cout, colorizer(app.opts.colorize), 10);
for (vector<revision_id>::const_iterator rev = sorted.begin();
rev != sorted.end(); ++rev)
============================================================
--- asciik.hh 592aa966af256f50be9784bfd01c543f54d3447b
+++ asciik.hh 3e0dcd90804053a5e558b0ddfa6e5f3dcc462d50
@@ -11,13 +11,14 @@
#define __ASCIIK_HH__
#include <set>
+#include "colorizer.hh"
#include "vector.hh"
#include "vocab.hh"
class asciik
{
public:
- asciik(std::ostream & os, size_t min_width = 0);
+ asciik(std::ostream & os, colorizer const & color, size_t min_width = 0);
// Prints an ASCII-k chunk using the given revisions.
// Multiple lines are supported in annotation (the graph will stretch
// accordingly); empty newlines at the end will be removed.
@@ -41,6 +42,7 @@ private:
// internal state
size_t width;
std::ostream & output;
+ colorizer const & color;
std::vector<revision_id> curr_row;
};
============================================================
--- rev_output.cc a2c70b893b31296917d1a2b974faa1da46c13f1e
+++ rev_output.cc 90f5ca2ff78f91bdf512231482d00a2eee37875b
@@ -31,40 +31,40 @@ revision_header(revision_id const rid, r
revision_header(revision_id const rid, revision_t const & rev,
string const & author, date_t const date,
branch_name const & branch, utf8 const & changelog,
- string const & date_fmt, utf8 & header)
+ string const & date_fmt, colorizer const & color, utf8 & header)
{
vector<cert> certs;
key_id empty_key;
- certs.push_back(cert(rid, author_cert_name,
+ certs.push_back(cert(rid, author_cert_name,
cert_value(author, origin::user), empty_key));
- certs.push_back(cert(rid, date_cert_name,
+ certs.push_back(cert(rid, date_cert_name,
cert_value(date.as_iso_8601_extended(), origin::user),
empty_key));
- certs.push_back(cert(rid, branch_cert_name,
+ certs.push_back(cert(rid, branch_cert_name,
cert_value(branch(), origin::user), empty_key));
if (!changelog().empty())
- certs.push_back(cert(rid, changelog_cert_name,
+ certs.push_back(cert(rid, changelog_cert_name,
cert_value(changelog(), origin::user), empty_key));
- revision_header(rid, rev, certs, date_fmt, header);
+ revision_header(rid, rev, certs, date_fmt, color, header);
}
void
revision_header(revision_id const rid, revision_t const & rev,
vector<cert> const & certs, string const & date_fmt,
- utf8 & header)
+ colorizer const & color, utf8 & header)
{
ostringstream out;
- out << string(70, '-') << '\n'
- << _("Revision: ") << rid << '\n';
+ out << color.colorize(string(70, '-'), colorizer::log_revision) << '\n'
+ << color.colorize(_("Revision: "), colorizer::rev_header) << rid << '\n';
for (edge_map::const_iterator i = rev.edges.begin(); i != rev.edges.end(); ++i)
{
revision_id parent = edge_old_revision(*i);
if (!null_id(parent))
- out << _("Parent: ") << parent << '\n';
+ out << color.colorize(_("Parent: "), colorizer::rev_header) << parent << '\n';
}
cert_name const author(author_cert_name);
@@ -76,34 +76,40 @@ revision_header(revision_id const rid, r
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == author)
- out << _("Author: ") << i->value << '\n';
+ out << color.colorize(_("Author: "), colorizer::rev_header)
+ << i->value << '\n';
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == date)
{
if (date_fmt.empty())
- out << _("Date: ") << i->value << '\n';
+ out << color.colorize(_("Date: "), colorizer::rev_header)
+ << i->value << '\n';
else
{
date_t date(i->value());
- out << _("Date: ") << date.as_formatted_localtime(date_fmt) << '\n';
+ out << color.colorize(_("Date: "), colorizer::rev_header)
+ << date.as_formatted_localtime(date_fmt) << '\n';
}
}
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == branch)
- out << _("Branch: ") << i->value << '\n';
+ out << color.colorize(_("Branch: "), colorizer::rev_header)
+ << i->value << '\n';
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == tag)
- out << _("Tag: ") << i->value << '\n';
+ out << color.colorize(_("Tag: "), colorizer::rev_header)
+ << i->value << '\n';
out << "\n";
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == changelog)
{
- out << _("Changelog: ") << "\n\n" << i->value << '\n';
+ out << color.colorize(_("Changelog: "), colorizer::rev_header) << "\n\n"
+ << i->value << '\n';
if (!i->value().empty() && i->value()[i->value().length()-1] != '\n')
out << '\n';
}
@@ -111,7 +117,8 @@ revision_header(revision_id const rid, r
for (vector<cert>::const_iterator i = certs.begin(); i != certs.end(); ++i)
if (i->name == comment)
{
- out << _("Comments: ") << "\n\n" << i->value << '\n';
+ out << color.colorize(_("Comments: "), colorizer::rev_header) << "\n\n"
+ << i->value << '\n';
if (!i->value().empty() && i->value()[i->value().length()-1] != '\n')
out << '\n';
}
@@ -120,7 +127,7 @@ void
}
void
-revision_summary(revision_t const & rev, utf8 & summary)
+revision_summary(revision_t const & rev, colorizer const & color, utf8 & summary)
{
// We intentionally do not collapse the final \n into the format
// strings here, for consistency with newline conventions used by most
@@ -138,9 +145,9 @@ revision_summary(revision_t const & rev,
// A colon at the end of this string looked nicer, but it made
// double-click copying from terminals annoying.
if (null_id(parent))
- out << _("Changes") << "\n\n";
+ out << color.colorize(_("Changes"), colorizer::rev_header) << "\n\n";
else
- out << _("Changes against parent ") << parent << "\n\n";
+ out << color.colorize(_("Changes against parent "), colorizer::rev_header) << parent << "\n\n";
// presumably a merge rev could have an empty edge if one side won
if (cs.empty())
@@ -179,7 +186,7 @@ revision_summary(revision_t const & rev,
// the cset calls it attrs_cleared
// the command is attr drop
// here it is called unset
- // the revision text uses attr clear
+ // the revision text uses attr clear
for (set<pair<file_path, attr_key> >::const_iterator
i = cs.attrs_cleared.begin(); i != cs.attrs_cleared.end(); ++i)
============================================================
--- rev_output.hh 666dd3ed35e16d8b122b4932c2aad05a21a22e25
+++ rev_output.hh 5879a8268a59545c946583b65f66eda4491b979e
@@ -10,6 +10,7 @@
#ifndef __REV_SUMMARY_HH__
#define __REV_SUMMARY_HH__
+#include "colorizer.hh"
#include "rev_types.hh"
#include "vocab.hh"
@@ -17,18 +18,19 @@ void
struct cert;
void
-revision_header(revision_id const rid, revision_t const & rev,
+revision_header(revision_id const rid, revision_t const & rev,
std::string const & author, date_t const date,
branch_name const & branch, utf8 const & changelog,
- std::string const & date_fmt, utf8 & header);
+ std::string const & date_fmt, colorizer const & color,
+ utf8 & header);
void
-revision_header(revision_id const rid, revision_t const & rev,
+revision_header(revision_id const rid, revision_t const & rev,
std::vector<cert> const & certs, std::string const & date_fmt,
- utf8 & header);
+ colorizer const & color, utf8 & header);
void
-revision_summary(revision_t const & rev, utf8 & summary);
+revision_summary(revision_t const & rev, colorizer const & color, utf8 & summary);
#endif // header guard
============================================================
--- /dev/null
+++ colorizer.cc c219975b61f0749de94fd6e9a6491022acbde7e3
@@ -0,0 +1,52 @@
+// Copyright (C) 2010 Thomas Keller <address@hidden>
+//
+// 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 "colorizer.hh"
+#include "platform.hh"
+
+using std::string;
+using std::map;
+using std::make_pair;
+
+colorizer::colorizer(bool enable)
+{
+ if (!have_smart_terminal())
+ enable = false;
+
+ if (enable)
+ {
+ colormap.insert(std::make_pair(normal, ""));
+ colormap.insert(std::make_pair(reset, "\033[m"));
+ colormap.insert(std::make_pair(diff_encloser, "\033[1;34m"));
+ colormap.insert(std::make_pair(diff_add, "\033[32m"));
+ colormap.insert(std::make_pair(diff_delete, "\033[31m"));
+ colormap.insert(std::make_pair(diff_change, "\033[33m"));
+ colormap.insert(std::make_pair(diff_comment, "\033[36m"));
+ colormap.insert(std::make_pair(diff_separator, "\033[1m"));
+ colormap.insert(std::make_pair(log_revision, "\033[34m"));
+ colormap.insert(std::make_pair(rev_header, "\033[1m"));
+ }
+}
+
+string
+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:
============================================================
--- /dev/null
+++ colorizer.hh acac5ffcef7270972ccd94aa0a671ab27c892450
@@ -0,0 +1,47 @@
+// Copyright (C) 2010 Thomas Keller <address@hidden>
+//
+// 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 __COLORIZER_HH__
+#define __COLORIZER_HH__
+
+#include "vocab.hh"
+#include <map>
+
+struct colorizer {
+
+ typedef enum { normal = 0,
+ reset,
+ diff_encloser,
+ diff_add,
+ diff_delete,
+ diff_change,
+ diff_comment,
+ diff_separator,
+ log_revision,
+ rev_header
+ } purpose;
+
+ colorizer(bool enable);
+
+ std::string
+ colorize(std::string const & in, purpose p = normal) const;
+
+private:
+ std::map<purpose, std::string> colormap;
+};
+
+#endif // __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:
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Monotone-commits-diffs] net.venge.monotone.colored-diff: 3fd6dbdf433136f25a57a9043d02020cc4e044ba,
code <=