atomontage / xterm-color

ANSI & xterm-256 color text property translator for Emacs
BSD 2-Clause "Simplified" License
214 stars 20 forks source link

Support bold colors #17

Closed jgkamat closed 5 years ago

jgkamat commented 6 years ago

Currently, eshell with xterm-color enabled per the readme does not support bold colors.

With an emacs -Q

/bin/echo -e "text \033[1mbold\033[0m text"

prints out some bold text, but after enabling xterm-color, this is no longer the case.

atomontage commented 6 years ago

If you run M-x xterm-color-test you'll see all the rendering attributes that xterm-color supports. Bold text is not one of them, since I prefer to render SGR 1 as high intensity color (which is allowed by the specification, and something a lot of terminal emulators do) rather than switch to a bold font. I may implement an alternate rendering path for SGR 1 as bold in the future but I don't have a lot of time at the moment and it is not something I would use myself as I prefer high intensity colors.

Another thing to note is that echo in eshell is implemented in Emacs Lisp and will not process ANSI escapes. I can't get echo -e to to work with eshell inside Emacs -Q. It works fine in M-x shell though. So let's use printf rather than echo, which works fine in eshell/shell for the following example.

If we tweak your example a little bit and specify a foreground color (blue) together with SGR 1 (bold or high intensity) we get:

printf "text \033[34;1mbold-or-high-intensity\033[0m \033[34mnormal-intensity\033[0m text\n"

This should render fine on eshell/shell and show you two different colors: normal blue and bright blue. These can be customized.

So the gist of it is:

I'll turn this into a feature request and keep it open.

lionel- commented 5 years ago

@atomontage If the following patch makes sense to you, I'm happy to send a pull request:

diff --git a/xterm-color.el b/xterm-color.el
index d8b742e..093490f 100644
--- a/xterm-color.el
+++ b/xterm-color.el
@@ -181,6 +181,10 @@
   :type '(vector string string string string string string string string)
   :group 'xterm-color)

+(defcustom xterm-color-add-weight nil
+  "Whether to add the `weight' face property."
+  :type 'boolean)
+
 ;;
 ;; Buffer locals, used by state machine
 ;;
@@ -491,6 +495,9 @@ Once that happens, we generate a single text property for the entire string.")
         (push `(:overline t) ret))
       (when (is-set? +xterm-color--frame+)
         (push `(:box t) ret))
+      (when (and xterm-color-add-weight
+                 (is-set? +xterm-color--bright+))
+        (push '(:weight bold) ret))
       (when fg
         (push `(:foreground ,(if (stringp fg)
                                  fg
lionel- commented 5 years ago

Actually this doesn't work well because the applications I use assume bright colours and boldness are distinct features. This works better in that respect:

diff --git a/xterm-color.el b/xterm-color.el
index d8b742e..dbe1b93 100644
--- a/xterm-color.el
+++ b/xterm-color.el
@@ -181,6 +181,11 @@
   :type '(vector string string string string string string string string)
   :group 'xterm-color)

+(defcustom xterm-color-use-bold nil
+  "Whether to add the `weight' face property.
+When nil, bright colors are used to simulate boldness."
+  :type 'boolean)
+
 ;;
 ;; Buffer locals, used by state machine
 ;;
@@ -239,6 +244,7 @@ Once that happens, we generate a single text property for the entire string.")
 (defconst +xterm-color--negative+  16)
 (defconst +xterm-color--frame+     32)
 (defconst +xterm-color--overline+  64)
+(defconst +xterm-color--bold+      128)

 ;;
 ;; Functions
@@ -311,7 +317,9 @@ Once that happens, we generate a single text property for the entire string.")
     ((= 1 elem)
      (setq xterm-color--attributes
            (logior xterm-color--attributes
-                   +xterm-color--bright+))
+                   (if xterm-color-use-bold
+                       +xterm-color--bold+
+                     +xterm-color--bright+)))
      (setq elems (cdr elems)))
     ;; Faint color, emulated as normal intensity
     ((= 2 elem)
@@ -347,7 +355,8 @@ Once that happens, we generate a single text property for the entire string.")
     ((= 22 elem)
      (setq xterm-color--attributes
            (logand xterm-color--attributes
-                   (lognot +xterm-color--bright+)))
+                   (lognot +xterm-color--bright+)
+                   (lognot +xterm-color--bold+)))
      (setq elems (cdr elems)))
     ;; No italic
     ((= 23 elem)
@@ -491,6 +500,9 @@ Once that happens, we generate a single text property for the entire string.")
         (push `(:overline t) ret))
       (when (is-set? +xterm-color--frame+)
         (push `(:box t) ret))
+      (when (and xterm-color-use-bold
+                 (is-set? +xterm-color--bold+))
+        (push '(:weight bold) ret))
       (when fg
         (push `(:foreground ,(if (stringp fg)
                                  fg
jgkamat commented 5 years ago

@lionel- could you set up a branch with the above and the fix in #23 please? These issues were preventing me from using xterm-color, and I guess if they're fixed I can try to give it another shot (if it really is faster)

lionel- commented 5 years ago

Sure! I'm travelling atm but I'll do that once I'm back home.

lionel- commented 5 years ago

Actually here it is: https://github.com/lionel-/xterm-color/tree/patches

atomontage commented 5 years ago

This isn't the right way to do it since it doesn't interact very well with AIXTERM hi-intensity color -- mixes the two conceps (bold and hi-intensity color) together -- and there are more cases that you don't take into account. If you want to give this another shot, you should ideally go through the ECMA-48 spec (https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf, http://invisible-island.net/xterm/ctlseqs/ctlseqs.html) or at the very least see how other terminal emulators deal with same issues.

I still have this on my TODO pile but I'll need free time to work on it.

atomontage commented 5 years ago

I did this properly in 51c9b80d881457cf5a8f8a7338296c2d91fb7b66. Configurable via xterm-color-use-bold-as-bright.

Your Emacs font needs to have a bold variant, otherwise you will neither bold nor bright.

lionel- commented 2 years ago

Hi @atomontage. Thanks for working on this.

It turns out that I can't use this setting for the type of colour markup that we use (see https://github.com/r-lib/crayon) because we need the full interaction of boldness and brightness.

I think what's needed is what you alluded to here:

I may implement an alternate rendering path for SGR 1 as bold in the future but I don't have a lot of time at the moment and it is not something I would use myself as I prefer high intensity colors.

Would you consider a patch that goes in that direction (assuming I find time for it)?