Better Emacs shell: Part II

by oleksandrmanzyuk

Today I would like to talk about how to change colors in Emacs shell. The default color theme of Emacs shell is, if I am not mistaken, the default color theme of the rxvt terminal. It is, in my opinion, rather ugly and hard to read. I personally prefer Tango, the default color theme of gnome-terminal. You may have different preferences. Furthermore, I have observed that unlike genuine terminals, which display bold text in slightly brighter colors, Emacs shell uses the same color both for normal and bold text. Also, ansi-color doesn’t support high intensity colors corresponding to ESC [ <code> m escape sequence for the values of <code> between 90 and 109, which some console applications use.

Fortunately, as with pretty much everything in Emacs, it is possible to fix these problems. I am posting a snippet from my init.el with the hope that somebody may find it useful and so that I can point people to this blog entry when they ask me about my Emacs shell colors.

(setq color0  "#000000"
      color1  "#CC0000"
      color2  "#4E9A06"
      color3  "#C4A000"
      color4  "#3465A4"
      color5  "#75507B"
      color6  "#06989A"
      color7  "#D3D7CF"
      color8  "#555753"
      color9  "#ef2929"
      color10 "#8ae234"
      color11 "#fce94f"
      color12 "#729fcf"
      color13 "#ad7fa8"
      color14 "#34e2e2"
      color15 "#eeeeec")

(setq ansi-color-black        color0
      ansi-color-bold-black   color8
      ansi-color-red          color1
      ansi-color-bold-red     color9
      ansi-color-green        color2
      ansi-color-bold-green   color10
      ansi-color-yellow       color3
      ansi-color-bold-yellow  color11
      ansi-color-blue         color4
      ansi-color-bold-blue    color12
      ansi-color-magenta      color5
      ansi-color-bold-magenta color13
      ansi-color-cyan         color6
      ansi-color-bold-cyan    color14
      ansi-color-white        color7
      ansi-color-bold-white   color15)

(setq ansi-color-names-vector
      (vector ansi-color-black
              ansi-color-red
              ansi-color-green
              ansi-color-yellow
              ansi-color-blue
              ansi-color-magenta
              ansi-color-cyan
              ansi-color-white))

(setq ansi-color-bold-colors
      `((,ansi-color-black   . ,ansi-color-bold-black  )
        (,ansi-color-red     . ,ansi-color-bold-red    )
        (,ansi-color-green   . ,ansi-color-bold-green  )
        (,ansi-color-yellow  . ,ansi-color-bold-yellow )
        (,ansi-color-blue    . ,ansi-color-bold-blue   )
        (,ansi-color-magenta . ,ansi-color-bold-magenta)
        (,ansi-color-cyan    . ,ansi-color-bold-cyan   )
        (,ansi-color-white   . ,ansi-color-bold-white  )))

(defun ansi-color-get-bold-color (color)
  (or (cdr (assoc color ansi-color-bold-colors))
      color))

(defun ansi-color-boldify-face (face)
  (if (consp face)
      (let* ((property   (car face))
             (color      (cdr face))
             (bold-color (ansi-color-get-bold-color color)))
        (ansi-color-make-face property bold-color))
    face))

(eval-after-load "ansi-color"
  '(progn
     ;; Copied from `ansi-color.el' and modified to display
     ;; bold faces using slighly different, brigher colors.
     (defun ansi-color-get-face (escape-seq)
       (let ((i 0)
             f val)
         (while (string-match ansi-color-parameter-regexp
                              escape-seq i)
           (setq i   (match-end 0)
                 val (ansi-color-get-face-1
                      (string-to-number
                       (match-string 1 escape-seq) 10)))
           (cond ((not val))
                 ((eq val 'default)
                  (setq f (list val)))
                 (t
                  (unless (member val f)
                    (push val f)))))
         ;; Use brighter colors for bold faces.
         (when (member 'bold f)
           (setq f (mapcar 'ansi-color-boldify-face f)))
         f))
     ;; Copied from `ansi-color.el' and modified to support
     ;; so called high intensity colors.
     (defun ansi-color-make-color-map ()
       (let ((ansi-color-map (make-vector 110 nil))
             (index 0))
         ;; miscellaneous attributes
         (mapc
          (function (lambda (e)
                      (aset ansi-color-map index e)
                      (setq index (1+ index)) ))
          ansi-color-faces-vector)
         ;; foreground attributes
         (setq index 30)
         (mapc
          (function
           (lambda (e)
             (aset ansi-color-map index
                   (ansi-color-make-face 'foreground e))
             (setq index (1+ index)) ))
          ansi-color-names-vector)
         ;; background attributes
         (setq index 40)
         (mapc
          (function
           (lambda (e)
             (aset ansi-color-map index
                   (ansi-color-make-face 'background e))
             (setq index (1+ index)) ))
          ansi-color-names-vector)
         ;; foreground attributes -- high intensity
         (setq index 90)
         (mapc
          (function
           (lambda (e)
             (aset ansi-color-map index
                   (ansi-color-make-face 'foreground e))
             (setq index (1+ index)) ))
          ansi-color-names-vector)
         ;; background attributes -- high intensity
         (setq index 100)
         (mapc
          (function
           (lambda (e)
             (aset ansi-color-map index
                   (ansi-color-make-face 'background e))
             (setq index (1+ index)) ))
          ansi-color-names-vector)
         ansi-color-map))))

(defun ansi-color-generate-color-map ()
  (setq ansi-color-map (ansi-color-make-color-map)))

(add-hook 'shell-mode-hook 'ansi-color-for-comint-mode-on)
(add-hook 'shell-mode-hook 'ansi-color-generate-color-map)
Advertisements