Add a command line option to control whether the program output should
be coloured using SGR escape sequences.
---
TODO | 2 --
src/Makefile.am | 8 +++---
src/common.h | 2 ++
src/main.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++
src/main_p.h | 1 +
src/mbsync.1.in | 6 +++++
src/util.c | 69 +++++++++++++++++++++++++++++++++++++++++++++----
7 files changed, 146 insertions(+), 11 deletions(-)
diff --git a/TODO b/TODO
index 43f0c0da2ded..4e2d2588bb76 100644
--- a/TODO
+++ b/TODO
@@ -75,8 +75,6 @@ matters.
some error messages are unhelpful in non-verbose mode due to missing context.
-possibly use ^[[1m to highlight error messages.
-
consider alternative approach to trashing: instead of the current trash-before-
expunge done by mbsync, let MUAs do the trashing (as modern ones typically do).
mbsync wouldn't do any trashing by itself, but should track the moves for
diff --git a/src/Makefile.am b/src/Makefile.am
index 6354452cd8fb..519944e1ca70 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -35,17 +35,17 @@ bin_PROGRAMS = mbsync $(mdconvert_prog)
# don't forget to update AC_CONFIG_FILES in configure.ac!
man_MANS = mbsync.1 $(mdconvert_man)
-tst_imap_msgs_SOURCES = tst_imap_msgs.c imap_msgs.c util.c
+tst_imap_msgs_SOURCES = tst_imap_msgs.c imap_msgs.c util.c display.c
-tst_imap_utf7_SOURCES = tst_imap_utf7.c imap_utf7.c util.c
+tst_imap_utf7_SOURCES = tst_imap_utf7.c imap_utf7.c util.c display.c
-tst_msg_cvt_SOURCES = tst_msg_cvt.c sync_msg_cvt.c util.c
+tst_msg_cvt_SOURCES = tst_msg_cvt.c sync_msg_cvt.c util.c display.c
tst_msg_cvt_CFLAGS = -DQPRINTF_BUFF=10000
check_PROGRAMS = tst_imap_msgs tst_imap_utf7 tst_msg_cvt
TESTS = $(check_PROGRAMS)
-tst_timers_SOURCES = tst_timers.c util.c
+tst_timers_SOURCES = tst_timers.c util.c display.c
EXTRA_PROGRAMS = tst_timers
diff --git a/src/common.h b/src/common.h
index 38521b685bc3..561100658b55 100644
--- a/src/common.h
+++ b/src/common.h
@@ -178,6 +178,8 @@ extern int Verbosity;
extern int DFlags;
extern int JLimit, JCount;
extern int UseFSync;
+extern int ColourOut;
+extern int ColourErr;
// Global constants (inited by main())
extern int Pid;
diff --git a/src/main.c b/src/main.c
index 8581b0cf6c72..866f0dd9ccc9 100644
--- a/src/main.c
+++ b/src/main.c
@@ -50,6 +50,7 @@ PACKAGE " " VERSION " - mailbox synchronizer\n"
" -e, --ext-exit return extended exit code\n"
" -V, --verbose display what is happening\n"
" -q, --quiet don't display progress counters\n"
+" --colo[u]r=WHEN do or do not colour the output\n"
" -v, --version display version\n"
" -h, --help display this help message\n"
"\nIf neither --pull nor --push are specified, both are active.\n"
@@ -163,14 +164,70 @@ countStep( void )
exit( 100 );
}
+static void
+init_colour( int argc, char **argv )
+{
+ int found = 0;
+
+ for (int i = 1; i < argc; i++) {
+ const char *opt = argv[i];
+ if (opt[0] != '-' || (opt[1] == '-' && !opt[2]))
+ break;
+ if (opt[1] != '-') {
+ for (int j = 1; opt[j]; j++) {
+ if (opt[j] == 'c')
+ i++; // Skip config files
+ }
+ continue;
+ }
+
+ opt += 2;
+ if (!strcmp( opt, "color" ) || !strcmp( opt, "colour" )) {
+ ColourOut = 1;
+ ColourErr = 1;
+ found = 1;
+ continue;
+ }
+ if (starts_with( opt, -1, "color=", 6 )) {
+ opt += 6;
+ goto opt_eq;
+ }
+ if (starts_with( opt, -1, "colour=", 7 )) {
+ opt += 7;
+ opt_eq:
+ if (!strcmp( opt, "on" )) {
+ ColourOut = 1;
+ ColourErr = 1;
+ } else if (!strcmp( opt, "off" )) {
+ ColourOut = 0;
+ ColourErr = 0;
+ } else if (!strcmp( opt, "auto")) {
+ ColourOut = detect_display_attrs( STDOUT_FILENO
);
+ ColourErr = detect_display_attrs( STDERR_FILENO
);
+ }
+ found = 1;
+ continue;
+ }
+
+ if (!strcmp( opt, "config" ))
+ i++; // Skip config file
+ }
+
+ if (!found) {
+ ColourOut = detect_display_attrs( STDOUT_FILENO );
+ ColourErr = detect_display_attrs( STDERR_FILENO );
+ }
+}
+
int
main( int argc, char **argv )
{
core_vars_t mvars[1];
char *config = NULL, *opt, *ochar;
int oind, cops = 0, op, ms_warn = 0, renew_warn = 0, delete_warn = 0;
tzset();
+ init_colour( argc, argv ); // Must call before calling
error()/warn()/etc.
init_timers();
gethostname( Hostname, sizeof(Hostname) );
if ((ochar = strchr( Hostname, '.' )))
@@ -202,6 +259,18 @@ main( int argc, char **argv )
config = argv[oind++];
} else if (starts_with( opt, -1, "config=", 7
)) {
config = opt + 7;
+ } else if (!strcmp( opt, "color" )
+ || !strcmp( opt, "colour" )) {
+ // Stub - configured in init_colour()
+ } else if (starts_with( opt, -1, "color=", 6 ))
{
+ opt += 6;
+ goto colour_opt;
+ } else if (starts_with( opt, -1, "colour=", 7
)) {
+ opt += 7;
+ colour_opt:
+ if (strcmp( opt, "on" ) && strcmp( opt,
"off" )
+ && strcmp( opt, "auto"
))
+ goto badopt;
} else if (!strcmp( opt, "all" )) {
mvars->all = 1;
} else if (!strcmp( opt, "list" )) {
diff --git a/src/main_p.h b/src/main_p.h
index 6aa5fe2ba201..dbdb5c957e33 100644
--- a/src/main_p.h
+++ b/src/main_p.h
@@ -9,6 +9,7 @@
#define DEBUG_FLAG DEBUG_MAIN
+#include "display.h"
#include "sync.h"
typedef struct {
diff --git a/src/mbsync.1.in b/src/mbsync.1.in
index 1a15b10a2606..2e0fe801c9ad 100644
--- a/src/mbsync.1.in
+++ b/src/mbsync.1.in
@@ -119,6 +119,12 @@ .SH OPTIONS
Suppress progress counters (this is implicit if stdout is no TTY,
or any debugging categories are enabled), notices, and the summary.
If specified twice, suppress warning messages as well.
+.TP
+\fB--colo\fR[\fBu\fR]\fBr\fR[\fB=\fR{\fBon\fR|\fBoff\fR|\fBauto\fR}]
+If \fBon\fR or \fBoff\fR, output is or isn't coloured, respectively.
+If \fBauto\fR, output is coloured iff supported by the TTY (the default).
+If \fBon\fR/\fBoff\fR/\fBauto\fR is not specified, \fBon\fR is assumed.
+If given multiple times, the last one takes effect.
.
.SH CONFIGURATION
The configuration file is mandatory; \fBmbsync\fR will not run without it.
diff --git a/src/util.c b/src/util.c
index c110188d4fac..b453af310b8f 100644
--- a/src/util.c
+++ b/src/util.c
@@ -6,6 +6,7 @@
*/
#include "common.h"
+#include "display.h"
#include <fcntl.h>
#include <sys/stat.h>
@@ -18,6 +19,8 @@ int Verbosity = TERSE;
int DFlags;
int JLimit, JCount;
int UseFSync = 1;
+int ColourOut;
+int ColourErr;
int Pid;
char Hostname[256];
@@ -101,14 +104,28 @@ nvprint( const char *msg, va_list va )
vprint( msg, va );
}
+static void ATTR_PRINTFLIKE(1, 0)
+vinfo( const char *msg, va_list va )
+{
+ char *clr_msg = NULL;
+
+ if (ColourOut) {
+ clr_msg = wrap_msg( msg, DS_FG_GREEN );
+ msg = clr_msg;
+ }
+
+ nvprint( msg, va );
+ free( clr_msg );
+}
+
void
info( const char *msg, ... )
{
va_list va;
if (Verbosity >= VERBOSE) {
va_start( va, msg );
- nvprint( msg, va );
+ vinfo( msg, va );
va_end( va );
}
}
@@ -120,45 +137,87 @@ infon( const char *msg, ... )
if (Verbosity >= VERBOSE) {
va_start( va, msg );
- nvprint( msg, va );
+ vinfo( msg, va );
va_end( va );
need_nl = 1;
}
}
+static void ATTR_PRINTFLIKE(1, 0)
+vnotice( const char *msg, va_list va )
+{
+ char *clr_msg = NULL;
+
+ if (ColourOut) {
+ clr_msg = wrap_msg( msg, DS_BOLD );
+ msg = clr_msg;
+ }
+
+ nvprint( msg, va );
+ free( clr_msg );
+}
+
void
notice( const char *msg, ... )
{
va_list va;
if (Verbosity >= TERSE) {
va_start( va, msg );
- nvprint( msg, va );
+ vnotice( msg, va );
va_end( va );
}
}
+static void ATTR_PRINTFLIKE(1, 0)
+vwarn( const char *msg, va_list va )
+{
+ char *clr_msg = NULL;
+
+ if (ColourErr) {
+ clr_msg = wrap_msg( msg, DS_FG_RED );
+ msg = clr_msg;
+ }
+
+ vfprintf( stderr, msg, va );
+ free( clr_msg );
+}
+
void
warn( const char *msg, ... )
{
va_list va;
if (Verbosity >= QUIET) {
flushn();
va_start( va, msg );
- vfprintf( stderr, msg, va );
+ vwarn( msg, va );
va_end( va );
}
}
+static void ATTR_PRINTFLIKE(1, 0)
+verror( const char *msg, va_list va )
+{
+ char *clr_msg = NULL;
+
+ if (ColourErr) {
+ clr_msg = wrap_msg( msg, DS_BOLD | DS_FG_RED | DS_BG_BLACK );
+ msg = clr_msg;
+ }
+
+ vfprintf( stderr, msg, va );
+ free( clr_msg );
+}
+
void
error( const char *msg, ... )
{
va_list va;
flushn();
va_start( va, msg );
- vfprintf( stderr, msg, va );
+ verror( msg, va );
va_end( va );
}
--
2.47.3
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel