Patchwork [1,of,3] color: allow for user-configurable terminfo codes for effects

login
register
mail settings
Submitter Danek Duvall
Date Oct. 13, 2016, 8:27 p.m.
Message ID <61e74a19770c2ce80c0c.1476390453@smelly>
Download mbox | patch
Permalink /patch/17070/
State Accepted
Headers show

Comments

Danek Duvall - Oct. 13, 2016, 8:27 p.m.
# HG changeset patch
# User Danek Duvall <danek.duvall@oracle.com>
# Date 1476384497 25200
#      Thu Oct 13 11:48:17 2016 -0700
# Node ID 61e74a19770c2ce80c0cedc429915112261e5c1b
# Parent  4d93d73b8aecb2436bbfe9248cdfe0ef21582baf
color: allow for user-configurable terminfo codes for effects

If the entry in the terminfo database for your terminal is missing some
attributes, it should be possible to create them on the fly without
resorting to just making them a color.  This change allows you to have

    [color]
    terminfo.<effect> = <code>

where <effect> might be something like "dim" or "bold", and <code> is the
escape sequence that would otherwise have come from a call to tigetstr().
If an escape character is needed, use "\E".  Any such settings will
override attributes that are present in the terminfo database.
Yuya Nishihara - Oct. 15, 2016, 1:57 p.m.
On Thu, 13 Oct 2016 13:27:33 -0700, danek.duvall@oracle.com wrote:
> # HG changeset patch
> # User Danek Duvall <danek.duvall@oracle.com>
> # Date 1476384497 25200
> #      Thu Oct 13 11:48:17 2016 -0700
> # Node ID 61e74a19770c2ce80c0cedc429915112261e5c1b
> # Parent  4d93d73b8aecb2436bbfe9248cdfe0ef21582baf
> color: allow for user-configurable terminfo codes for effects

The series looks good to me. Queued, thanks.

> If the entry in the terminfo database for your terminal is missing some
> attributes, it should be possible to create them on the fly without
> resorting to just making them a color.  This change allows you to have
> 
>     [color]
>     terminfo.<effect> = <code>
> 
> where <effect> might be something like "dim" or "bold", and <code> is the
> escape sequence that would otherwise have come from a call to tigetstr().
> If an escape character is needed, use "\E".  Any such settings will
> override attributes that are present in the terminfo database.

Can you update the doc as a follow-up?
Danek Duvall - Oct. 15, 2016, 10:07 p.m.
Yuya Nishihara wrote:

> On Thu, 13 Oct 2016 13:27:33 -0700, danek.duvall@oracle.com wrote:
> > # HG changeset patch
> > # User Danek Duvall <danek.duvall@oracle.com>
> > # Date 1476384497 25200
> > #      Thu Oct 13 11:48:17 2016 -0700
> > # Node ID 61e74a19770c2ce80c0cedc429915112261e5c1b
> > # Parent  4d93d73b8aecb2436bbfe9248cdfe0ef21582baf
> > color: allow for user-configurable terminfo codes for effects
> 
> The series looks good to me. Queued, thanks.

Thanks!

> > If the entry in the terminfo database for your terminal is missing some
> > attributes, it should be possible to create them on the fly without
> > resorting to just making them a color.  This change allows you to have
> > 
> >     [color]
> >     terminfo.<effect> = <code>
> > 
> > where <effect> might be something like "dim" or "bold", and <code> is the
> > escape sequence that would otherwise have come from a call to tigetstr().
> > If an escape character is needed, use "\E".  Any such settings will
> > override attributes that are present in the terminfo database.
> 
> Can you update the doc as a follow-up?

Patch should be on its way.

Thanks,
Danek

Patch

diff --git a/hgext/color.py b/hgext/color.py
--- a/hgext/color.py
+++ b/hgext/color.py
@@ -187,9 +187,12 @@  def _terminfosetup(ui, mode):
     if mode not in ('auto', 'terminfo'):
         return
 
-    _terminfo_params.update((key[6:], (False, int(val)))
+    _terminfo_params.update((key[6:], (False, int(val), ''))
         for key, val in ui.configitems('color')
         if key.startswith('color.'))
+    _terminfo_params.update((key[9:], (True, '', val.replace('\\E', '\x1b')))
+        for key, val in ui.configitems('color')
+        if key.startswith('terminfo.'))
 
     try:
         curses.setupterm()
@@ -197,10 +200,10 @@  def _terminfosetup(ui, mode):
         _terminfo_params = {}
         return
 
-    for key, (b, e) in _terminfo_params.items():
+    for key, (b, e, c) in _terminfo_params.items():
         if not b:
             continue
-        if not curses.tigetstr(e):
+        if not c and not curses.tigetstr(e):
             # Most terminals don't support dim, invis, etc, so don't be
             # noisy and use ui.debug().
             ui.debug("no terminfo entry for %s\n" % e)
@@ -281,26 +284,26 @@  def _modesetup(ui, coloropt):
 
 try:
     import curses
-    # Mapping from effect name to terminfo attribute name or color number.
-    # This will also force-load the curses module.
-    _terminfo_params = {'none': (True, 'sgr0'),
-                        'standout': (True, 'smso'),
-                        'underline': (True, 'smul'),
-                        'reverse': (True, 'rev'),
-                        'inverse': (True, 'rev'),
-                        'blink': (True, 'blink'),
-                        'dim': (True, 'dim'),
-                        'bold': (True, 'bold'),
-                        'invisible': (True, 'invis'),
-                        'italic': (True, 'sitm'),
-                        'black': (False, curses.COLOR_BLACK),
-                        'red': (False, curses.COLOR_RED),
-                        'green': (False, curses.COLOR_GREEN),
-                        'yellow': (False, curses.COLOR_YELLOW),
-                        'blue': (False, curses.COLOR_BLUE),
-                        'magenta': (False, curses.COLOR_MAGENTA),
-                        'cyan': (False, curses.COLOR_CYAN),
-                        'white': (False, curses.COLOR_WHITE)}
+    # Mapping from effect name to terminfo attribute name (or raw code) or
+    # color number.  This will also force-load the curses module.
+    _terminfo_params = {'none': (True, 'sgr0', ''),
+                        'standout': (True, 'smso', ''),
+                        'underline': (True, 'smul', ''),
+                        'reverse': (True, 'rev', ''),
+                        'inverse': (True, 'rev', ''),
+                        'blink': (True, 'blink', ''),
+                        'dim': (True, 'dim', ''),
+                        'bold': (True, 'bold', ''),
+                        'invisible': (True, 'invis', ''),
+                        'italic': (True, 'sitm', ''),
+                        'black': (False, curses.COLOR_BLACK, ''),
+                        'red': (False, curses.COLOR_RED, ''),
+                        'green': (False, curses.COLOR_GREEN, ''),
+                        'yellow': (False, curses.COLOR_YELLOW, ''),
+                        'blue': (False, curses.COLOR_BLUE, ''),
+                        'magenta': (False, curses.COLOR_MAGENTA, ''),
+                        'cyan': (False, curses.COLOR_CYAN, ''),
+                        'white': (False, curses.COLOR_WHITE, '')}
 except ImportError:
     _terminfo_params = {}
 
@@ -366,9 +369,12 @@  def _effect_str(effect):
     if effect.endswith('_background'):
         bg = True
         effect = effect[:-11]
-    attr, val = _terminfo_params[effect]
+    attr, val, termcode = _terminfo_params[effect]
     if attr:
-        return curses.tigetstr(val)
+        if termcode:
+            return termcode
+        else:
+            return curses.tigetstr(val)
     elif bg:
         return curses.tparm(curses.tigetstr('setab'), val)
     else:
@@ -403,7 +409,7 @@  def valideffect(effect):
 
 def configstyles(ui):
     for status, cfgeffects in ui.configitems('color'):
-        if '.' not in status or status.startswith('color.'):
+        if '.' not in status or status.startswith(('color.', 'terminfo.')):
             continue
         cfgeffects = ui.configlist('color', status)
         if cfgeffects:
diff --git a/tests/test-status-color.t b/tests/test-status-color.t
--- a/tests/test-status-color.t
+++ b/tests/test-status-color.t
@@ -233,6 +233,25 @@  hg status -A (with terminfo color):
   \x1b[30m\x1b[30mC \x1b[30m\x1b[30m\x1b[30m.hgignore\x1b[30m (esc)
   \x1b[30m\x1b[30mC \x1b[30m\x1b[30m\x1b[30mmodified\x1b[30m (esc)
 
+The user can define effects with raw terminfo codes:
+
+  $ cat <<EOF >> $HGRCPATH
+  > # Completely bogus code for dim
+  > terminfo.dim = \E[88m
+  > # We can override what's in the terminfo database, too
+  > terminfo.bold = \E[2m
+  > EOF
+  $ TERM=hgterm TERMINFO="$TESTTMP/terminfo" hg status --config color.mode=terminfo --config color.status.clean=dim --color=always -A
+  \x1b[30m\x1b[32m\x1b[2mA \x1b[30m\x1b[30m\x1b[32m\x1b[2madded\x1b[30m (esc)
+  \x1b[30m\x1b[32m\x1b[2mA \x1b[30m\x1b[30m\x1b[32m\x1b[2mcopied\x1b[30m (esc)
+  \x1b[30m\x1b[30m  modified\x1b[30m (esc)
+  \x1b[30m\x1b[31m\x1b[2mR \x1b[30m\x1b[30m\x1b[31m\x1b[2mremoved\x1b[30m (esc)
+  \x1b[30m\x1b[36m\x1b[2m\x1b[4m! \x1b[30m\x1b[30m\x1b[36m\x1b[2m\x1b[4mdeleted\x1b[30m (esc)
+  \x1b[30m\x1b[35m\x1b[2m\x1b[4m? \x1b[30m\x1b[30m\x1b[35m\x1b[2m\x1b[4munknown\x1b[30m (esc)
+  \x1b[30m\x1b[30m\x1b[2mI \x1b[30m\x1b[30m\x1b[30m\x1b[2mignored\x1b[30m (esc)
+  \x1b[30m\x1b[88mC \x1b[30m\x1b[30m\x1b[88m.hgignore\x1b[30m (esc)
+  \x1b[30m\x1b[88mC \x1b[30m\x1b[30m\x1b[88mmodified\x1b[30m (esc)
+
 #endif