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

Reply via email to