chiark / gitweb /
@@@ tty mess
[mLib] / test / tvec-output.c
index 014423e0a831defd07a54ae0be9398ec322f430e..40ab769868fa396730301b3afa45f86f2cd25eb3 100644 (file)
@@ -44,6 +44,7 @@
 #include "macros.h"
 #include "quis.h"
 #include "report.h"
+#include "tty.h"
 #include "ttycolour.h"
 
 #include "tvec.h"
@@ -80,7 +81,7 @@ static const char *regdisp(unsigned disp)
  *             @const char *what, ...@ = format string describing where the
  *                     setting came from
  *
- * Returns:    @0@ if the string, or variable,  is set to something
+ * Returns:    @0@ if the string, or variable, is set to something
  *             falseish, @1@ if it's set to something truish, or @dflt@
  *             otherwise.
  */
@@ -481,15 +482,57 @@ static int layout_string(struct layout *lyt, const char *p, size_t sz)
 
 /*----- Human-readable output ---------------------------------------------*/
 
+#define GENATTR(want, attrs, fgspc, fgcol, bgspc, bgcol)               \
+  { (want), (want),                                                    \
+    { ((fgspc) << TTAF_FGSPCSHIFT) |                                   \
+      ((bgspc) << TTAF_BGSPCSHIFT) | (attrs),                          \
+      0, (fgcol), (bgcol) } }
+
+#define FGBG(want, attrs, fgcol, bgcol)                                        \
+  GENATTR(want | TTACF_FG | TTACF_BG, attrs,                           \
+         TTCSPC_1BPCBR, TTCOL_##fgcol, TTCSPC_1BPCBR, TTCOL_##bgcol)
+#define FG(want, attrs, fgcol)                                         \
+  GENATTR(want | TTACF_FG, attrs,                                      \
+         TTCSPC_1BPCBR, TTCOL_##fgcol, TTCSPC_NONE, 0)
+#define BG(want, attrs, bgcol)                                         \
+  GENATTR(want | TTACF_BG, attrs,                                      \
+         TTCSPC_NONE, 0, TTCSPC_1BPCBR, TTCOL_##bgcol)
+#define ATTR(want, attrs)                                              \
+  GENATTR(want, attrs, TTCSPC_NONE, 0, TTCSPC_NONE, 0)
+
+#define BOLD (TTWT_BOLD << TTAF_WTSHIFT)
+
+static const struct tty_attrlist
+  loc_attrs[] = { FG(0, 0, CYN), TTY_ATTRLIST_CLEAR },
+  locsep_attrs[] = { FG(0, 0, BRBLU), TTY_ATTRLIST_CLEAR },
+  note_attrs[] = { FG(0, 0, YLW), TTY_ATTRLIST_CLEAR },
+  err_attrs[] = { FG(0, BOLD, MGN), TTY_ATTRLIST_CLEAR },
+  unklv_attrs[] = { FGBG(0, BOLD, BRWHT, BRRED), ATTR(0, TTAF_INVV) },
+  vfound_attrs[] = { FG(0, 0, RED), TTY_ATTRLIST_CLEAR },
+  vexpect_attrs[] = { FG(0, 0, GRN), TTY_ATTRLIST_CLEAR },
+  vunset_attrs[] = { FG(0, 0, YLW), TTY_ATTRLIST_CLEAR },
+  lose_attrs[] = { FG(0, BOLD, RED), ATTR(0, BOLD | TTAF_INVV) },
+  skip_attrs[] = { FG(0, 0, YLW), TTY_ATTRLIST_CLEAR },
+  xfail_attrs[] = { FG(0, BOLD, BLU), ATTR(0, BOLD) },
+  win_attrs[] = { FG(0, 0, GRN), TTY_ATTRLIST_CLEAR },
+  sblose_attrs[] = { FG(0, BOLD, RED), ATTR(0, BOLD) };
+
+#undef GENATTR
+#undef FGBG
+#undef FG
+#undef BG
+#undef ATTR
+#undef BOLD
+
 /* Predefined attributes. */
 #define HIGHLIGHTS(_st, _)                                             \
-  _(_st, LOCFN,           "lf", TC_FG(CYAN))   /* location filename */         \
-  _(_st, LOCLN,           "ln", TC_FG(CYAN))   /* location line number */      \
-  _(_st, LOCSEP,   "ls", TC_FG(BRBLUE))        /* location separator `:' */    \
+  _(_st, LOCFN,           "lf", loc_attrs)     /* location filename */         \
+  _(_st, LOCLN,           "ln", loc_attrs)     /* location line number */      \
+  _(_st, LOCSEP,   "ls", locsep_attrs) /* location separator `:' */    \
   _(_st, INFO,    "mi", 0)             /* information */               \
-  _(_st, NOTE,    "mn", TC_FG(YELLOW)) /* notices */                   \
-  _(_st, ERR,     "me", TC_FG(MAGENTA) | TCAF_BOLD) /* error messages */       \
-  _(_st, UNKLEV,   "mu", TC_FG(WHITE) | TC_BG(RED) | TCAF_BOLD)                \
+  _(_st, NOTE,    "mn", note_attrs)    /* notices */                   \
+  _(_st, ERR,     "me", err_attrs)     /* error messages */            \
+  _(_st, UNKLV,           "mu", unklv_attrs)   /* unknown-level messages */    \
   _(_st, DSINPUT,  "di", 0)            /* disposition for input value */ \
   _(_st, DSOUTPUT, "do", 0)            /* ... unsolicited output */    \
   _(_st, DSMATCH,  "dm", 0)            /* ... matching output */       \
@@ -503,16 +546,16 @@ static int layout_string(struct layout *lyt, const char *p, size_t sz)
   _(_st, VINPUT,   "vi", 0)            /* input value */               \
   _(_st, VOUTPUT,  "vo", 0)            /* unsolicited output value */  \
   _(_st, VMATCH,   "vm", 0)            /* matching output value */     \
-  _(_st, VFOUND,   "vf", TC_FG(BRRED)) /* incorrect output value */    \
-  _(_st, VEXPECT,  "vx", TC_FG(GREEN)) /* reference output value */    \
-  _(_st, VUNSET,   "vu", TC_FG(YELLOW))        /* register not set */          \
-  _(_st, LOSE,    "ol", TC_FG(RED) | TCAF_BOLD) /* report failure */   \
-  _(_st, SKIP,    "os", TC_FG(YELLOW)) /* report a skipped test/group */ \
-  _(_st, XFAIL,           "ox", TC_FG(BLUE) | TCAF_BOLD) /* report expected fail */ \
-  _(_st, WIN,     "ow", TC_FG(GREEN))  /* report success */            \
-  _(_st, SBLOSE,   "sl", TC_FG(RED) | TCAF_BOLD) /* scoreboard failure */      \
-  _(_st, SBSKIP,   "ss", TC_FG(YELLOW))        /* scoreboard skipped test */   \
-  _(_st, SBXFAIL,  "sx", TC_FG(BLUE) | TCAF_BOLD) /* scoreboard xfail */       \
+  _(_st, VFOUND,   "vf", vfound_attrs) /* incorrect output value */    \
+  _(_st, VEXPECT,  "vx", vexpect_attrs)        /* reference output value */    \
+  _(_st, VUNSET,   "vu", vunset_attrs) /* register not set */          \
+  _(_st, LOSE,    "ol", lose_attrs)    /* report failure */            \
+  _(_st, SKIP,    "os", skip_attrs)    /* report a skipped test/group */ \
+  _(_st, XFAIL,           "ox", xfail_attrs)   /* report expected fail */      \
+  _(_st, WIN,     "ow", win_attrs)     /* report success */            \
+  _(_st, SBLOSE,   "sl", sblose_attrs) /* scoreboard failure */        \
+  _(_st, SBSKIP,   "ss", skip_attrs)   /* scoreboard skipped test */   \
+  _(_st, SBXFAIL,  "sx", xfail_attrs)  /* scoreboard xfail */          \
   _(_st, SBWIN,           "sw", 0)             /* scoreboard success */
 
 TTYCOLOUR_DEFENUM(HIGHLIGHTS, HL_);
@@ -525,11 +568,11 @@ struct human_output {
   struct tvec_output _o;               /* output base class */
   struct tvec_state *tv;               /* stashed testing state */
   arena *a;                            /* arena for memory allocation */
+  struct tty *tty;                     /* output terminal, or null */
   struct layout lyt;                   /* output layout */
   char *outbuf; size_t outsz;          /* buffer for formatted output */
   dstr scoreboard;                     /* history of test group results */
-  unsigned short attr[HL__LIMIT];      /* highlight attribute map */
-  struct ttycolour_state tc;           /* terminal colour state */
+  struct tty_attr attr[HL__LIMIT];     /* highlight attribute map */
   int maxlen;                          /* longest register name */
   unsigned f;                          /* flags */
                                        /*   bits 0--7 from @TVHF_...@ */
@@ -552,7 +595,7 @@ static void setattr_common(struct human_output *h,
                           const struct gprintf_ops *gops, void *go, int hl)
 {
   if (h->f&TVHF_COLOUR)
-    ttycolour_setattr(gops, go, &h->tc, hl < 0 ? 0 : h->attr[hl]);
+    tty_setattrg(h->tty, gops, go, hl >= 0 ? &h->attr[hl] : 0);
 }
 
 static void setattr(struct human_output *h, int hl)
@@ -1018,7 +1061,7 @@ static void human_etest(struct tvec_output *o, unsigned outcome)
  *
  * Arguments:  @struct tvec_output *o@ = output sink, secretly a
  *                      @struct human_output@
- *             @unsigned level@ = message level (@TVLEV_...@)
+ *             @unsigned level@ = message level (@TVLV_...@)
  *             @const char *msg@, @va_list *ap@ = format string and
  *                     arguments
  *
@@ -1045,9 +1088,9 @@ static void human_report(struct tvec_output *o, unsigned level,
 
   switch (level) {
 #define CASE(tag, name, val)                                           \
-    case TVLEV_##tag: levstr = name; levhl = HL_##tag; break;
+    case TVLV_##tag: levstr = name; levhl = HL_##tag; break;
     TVEC_LEVELS(CASE)
-    default: levstr = "??"; levhl = HL_UNKLEV; break;
+    default: levstr = "??"; levhl = HL_UNKLV; break;
   }
 
   if (h->f&HOF_PROGRESS) { clear_progress(h); f |= f_progress; }
@@ -1157,6 +1200,7 @@ static void human_destroy(struct tvec_output *o)
 {
   struct human_output *h = (struct human_output *)o;
 
+  tty_close(h->tty);
   destroy_layout(&h->lyt,
                 h->lyt.fp == stdout || h->lyt.fp == stderr ? 0 : DLF_CLOSE);
   dstr_destroy(&h->scoreboard);
@@ -1205,7 +1249,6 @@ static const struct tvec_outops human_ops = {
 struct tvec_output *tvec_humanoutput(FILE *fp, unsigned f, unsigned m)
 {
   struct human_output *h;
-  const char *p;
   struct stat st_out, st_err;
   int rc_out, rc_err;
 
@@ -1215,7 +1258,7 @@ struct tvec_output *tvec_humanoutput(FILE *fp, unsigned f, unsigned m)
   assert(!(f&~m));
 
   if (!(m&TVHF_TTY))
-    switch (getenv_boolean("TVEC_TTY", -1)) {
+    switch (getenv_boolean("MLIB_TVEC_TTY", -1)) {
       case 1: f |= TVHF_TTY; break;
       case 0: break;
       default:
@@ -1223,14 +1266,12 @@ struct tvec_output *tvec_humanoutput(FILE *fp, unsigned f, unsigned m)
        break;
     }
   if (!(m&TVHF_COLOUR))
-    switch (getenv_boolean("TVEC_COLOUR", -1)) {
+    switch (getenv_boolean("MLIB_TVEC_COLOUR", -1)) {
       case 1: f |= TVHF_COLOUR; break;
       case 0: break;
       default:
-       if (f&TVHF_TTY) {
-         p = getenv("TERM");
-         if (p && STRCMP(p, !=, "dumb")) f |= TVHF_COLOUR;
-       }
+       if (ttycolour_enablep((f&TVHF_TTY ? TCEF_TTY : 0) | TCEF_DFLT))
+         f |= TVHF_COLOUR;
        break;
     }
 
@@ -1252,10 +1293,15 @@ struct tvec_output *tvec_humanoutput(FILE *fp, unsigned f, unsigned m)
   h->f = f;
 
   /* Initialize the colour tables. */
-  if (h->f&TVHF_COLOUR) {
-    ttycolour_config(h->attr, "TVEC_COLOURS", TCIF_GETENV | TCIF_REPORT,
-                    hltab);
-    ttycolour_init(&h->tc);
+  if (!(h->f&TVHF_COLOUR))
+    h->tty = 0;
+  else {
+    h->tty = tty_open(fp, TTF_BORROW, 0);
+    if (!h->tty)
+      h->f &= ~TVHF_COLOUR;
+    else
+      ttycolour_config(h->attr, "MLIB_TVEC_COLOURS",
+                      TCIF_GETENV | TCIF_REPORT, h->tty, hltab);
   }
 
   init_layout(&h->lyt, fp, 0);
@@ -1672,7 +1718,7 @@ static void machine_etest(struct tvec_output *o, unsigned outcome)
  *
  * Arguments:  @struct tvec_output *o@ = output sink, secretly a
  *                      @struct machine_output@
- *             @unsigned level@ = message level (@TVLEV_...@)
+ *             @unsigned level@ = message level (@TVLV_...@)
  *             @const char *msg@, @va_list *ap@ = format string and
  *                     arguments
  *
@@ -2123,7 +2169,7 @@ static void tap_etest(struct tvec_output *o, unsigned outcome)
  *
  * Arguments:  @struct tvec_output *o@ = output sink, secretly a
  *                      @struct tap_output@
- *             @unsigned level@ = message level (@TVLEV_...@)
+ *             @unsigned level@ = message level (@TVLV_...@)
  *             @const char *msg@, @va_list *ap@ = format string and
  *                     arguments
  *
@@ -2504,7 +2550,7 @@ static void am_etest(struct tvec_output *o, unsigned outcome)
  *
  * Arguments:  @struct tvec_output *o@ = output sink, secretly a
  *                      @struct automake_output@
- *             @unsigned level@ = message level (@TVLEV_...@)
+ *             @unsigned level@ = message level (@TVLV_...@)
  *             @const char *msg@, @va_list *ap@ = format string and
  *                     arguments
  *
@@ -2664,10 +2710,10 @@ struct tvec_output *tvec_amoutput(const struct tvec_amargs *a)
 
 struct tvec_output *tvec_dfltoutput(FILE *fp)
 {
-  int ttyp = getenv_boolean("TVEC_TTY", -1);
+  int ttyp = getenv_boolean("MLIB_TVEC_TTY", -1);
 
   if (ttyp == -1) ttyp = isatty(fileno(fp));
-  if (ttyp) return (tvec_humanoutput(fp, 0, 0));
+  if (ttyp) return (tvec_humanoutput(fp, TVHF_TTY, TVHF_TTY));
   else return (tvec_machineoutput(fp));
 }