3

I am an Emacs newbie and trying to work out how to implement custom colors.

Currently I have a conditional statement and a while statement which both use the same face (font-lock-keyword-face). Is it possible to create my own face for the while statement which uses custom colors?

Drew
  • 75,699
  • 9
  • 109
  • 225
Us3rname
  • 83
  • 1
  • 8
  • 1
    Please show your code. We should not need to guess what you are trying to describe. And say what you mean by "implement custom colors" (or even "custom colors"). Thx. – Drew Jun 21 '17 at 01:32
  • @Drew Any python-example code with `if` and `while` in it will do. So I think the question is quite clear in its current form. – Tobias Jun 21 '17 at 08:05

1 Answers1

5

If you have a look into the python library (M-x find-library RET python RET) you see that the python-font-lock-keywords are constructed by the rx macro:

(defvar python-font-lock-keywords
    ;; Keywords
    `(,(rx symbol-start
         (or
          "and" "del" "from" "not" "while" "as" "elif" "global" "or" "with"
          "assert" "else" "if" "pass" "yield" "break" "except" "import" "class"
          "in" "raise" "continue" "finally" "is" "return" "def" "for" "lambda"
          "try"
          ;; Python 2:
          "print" "exec"
          ;; Python 3:
          ;; False, None, and True are listed as keywords on the Python 3
          ;; documentation, but since they also qualify as constants they are
          ;; fontified like that in order to keep font-lock consistent between
          ;; Python versions.
          "nonlocal"
          ;; Python 3.5+ PEP492
          (and "async" (+ space) (or "def" "for" "with"))
          "await"
          ;; Extra:
          "self")
         symbol-end)
    ;; Functions
    ...

There is while included in the list argument to rx. You can replace this list without while in it:

(setcar python-font-lock-keywords
        (rx symbol-start
         (or
          "and" "del" "from" "not" "as" "elif" "global" "or" "with"
          "assert" "else" "if" "pass" "yield" "break" "except" "import" "class"
          "in" "raise" "continue" "finally" "is" "return" "def" "for" "lambda"
          "try"
          ;; Python 2:
          "print" "exec"
          ;; Python 3:
          ;; False, None, and True are listed as keywords on the Python 3
          ;; documentation, but since they also qualify as constants they are
          ;; fontified like that in order to keep font-lock consistent between
          ;; Python versions.
          "nonlocal"
          ;; Python 3.5+ PEP492
          (and "async" (+ space) (or "def" "for" "with"))
          "await"
          ;; Extra:
          "self")
         symbol-end))

You can define your own face with

(defface python-while-face
  '((((class grayscale) (background light)) :foreground "Gray90" :weight bold)
    (((class grayscale) (background dark))  :foreground "DimGray" :weight bold)
    (((class color) (min-colors 88) (background light)) :foreground "Red")
    (((class color) (min-colors 88) (background dark))  :foreground "Red")
    (((class color) (min-colors 16) (background light)) :foreground "Red")
    (((class color) (min-colors 16) (background dark))  :foreground "Red")
    (((class color) (min-colors 8)) :foreground "green")
    (t :weight bold :underline t))
  "Font Lock mode face used to highlight type and classes."
  :group 'python-faces)
(defcustom python-while-face 'python-while-face
"Face for the while keyword"
  :group 'python
  :type 'face)

Now you can associate the keyword while with this face (at the position 1 of python-font-lock-keywords):

(setcdr python-font-lock-keywords (cons '("\\_<while\\_>" (0 python-while-face)) (cdr python-font-lock-keywords)))

Now you need to re-initialize python-mode again for your test file. Just run M-x normal-mode RET in the python buffer.

Some example python code for testing:

import time
import win32com.client
import win32ui

sim = win32com.client.Dispatch("iti.simx38")
doc = sim.ActiveDocument

if doc:
    for b in range(0, 11):
        doc.Parameters("damper1.b").Value = b
        doc.Reset()
        doc.Start()

        while doc.SolutionState != simStopped:
            time.sleep(0.1)

After executing all the lisp-forms from this answer the python text is displayed by emacs as shown in the next Figure. As you see the while keyword is shown in red.

Python test file with customized face for <code>while</code>.

Let us finally collect all the lisp forms from above such that they are usable in the init file:

(defface python-while-face
  '((((class grayscale) (background light)) :foreground "Gray90" :weight bold)
    (((class grayscale) (background dark))  :foreground "DimGray" :weight bold)
    (((class color) (min-colors 88) (background light)) :foreground "Red")
    (((class color) (min-colors 88) (background dark))  :foreground "Red")
    (((class color) (min-colors 16) (background light)) :foreground "Red")
    (((class color) (min-colors 16) (background dark))  :foreground "Red")
    (((class color) (min-colors 8)) :foreground "green")
    (t :weight bold :underline t))
  "Font Lock mode face used to highlight type and classes."
  :group 'python-faces)
(defcustom python-while-face 'python-while-face
"Face for the while keyword"
  :group 'python
  :type 'face)

(eval-after-load "python"
  '(progn
     (setcar python-font-lock-keywords
             (rx symbol-start
                 (or
                  "and" "del" "from" "not" "as" "elif" "global" "or" "with"
                  "assert" "else" "if" "pass" "yield" "break" "except" "import" "class"
                  "in" "raise" "continue" "finally" "is" "return" "def" "for" "lambda"
                  "try"
                  ;; Python 2:
                  "print" "exec"
                  ;; Python 3:
                  ;; False, None, and True are listed as keywords on the Python 3
                  ;; documentation, but since they also qualify as constants they are
                  ;; fontified like that in order to keep font-lock consistent between
                  ;; Python versions.
                  "nonlocal"
                  ;; Python 3.5+ PEP492
                  (and "async" (+ space) (or "def" "for" "with"))
                  "await"
                  ;; Extra:
                  "self")
                 symbol-end))
     (setcdr python-font-lock-keywords (cons '("\\_<while\\_>" (0 python-while-face)) (cdr python-font-lock-keywords)))))
Tobias
  • 32,569
  • 1
  • 34
  • 75
  • This solution removes the color for `Exection` keyword. Also can we apply this solution for the `Builtin Exceptions`, where I want a additional Exception names? – alper Jan 24 '23 at 20:47