0

In python-mode, Exception keyword has font-lock-type-face for coloring.

Example output of the coloring:

enter image description here

If possible, I want to add custom keywords into Builtin Exceptions such as QuietExit, Terminate to color them as Exception.

I have tried:

(require 'python)

;; https://emacs.stackexchange.com/a/55186/18414
(setq python-font-lock-keywords
      (append python-font-lock-keywords
          '(;; this is the full string.
        ;; group 1 is the quote type and a closing quote is matched
        ;; group 2 is the string part
        ("f\\(['\"]\\{1,3\\}\\)\\(.+?\\)\\1"
         ;; these are the {keywords}
         ("{[^}]*?}"
          ;; Pre-match form
          (progn (goto-char (match-beginning 0)) (match-end 0))
          ;; Post-match form
          (goto-char (match-end 0))
          ;; face for this match
          (0 font-lock-variable-name-face t))))))

(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 "#bd93f9")
    (((class color) (min-colors 88) (background dark))  :foreground "#bd93f9")
    (((class color) (min-colors 16) (background light)) :foreground "#bd93f9")
    (((class color) (min-colors 16) (background dark))  :foreground "#bd93f9")
    (((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" "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"
                  ;; 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 '("\\_<QuietExit\\_>" (0 python-while-face)) (cdr python-font-lock-keywords)))
    (setcdr python-font-lock-keywords (cons '("\\_<Terminate\\_>" (0 python-while-face)) (cdr python-font-lock-keywords)))
    ))

But now this solution uncolors Exception keyword.

Related: Python mode - custom syntax highlighting

alper
  • 1,238
  • 11
  • 30

1 Answers1

1

By studying the details of how font lock works, you might be able to find a more elegant solution, but otherwise I would go for the most straightforward solution, which is to lookup how python-mode sets the value of python-font-lock-keywords-maximum-decoration. Then you could just use that method to redefine the regexp for the errors as follows:

(with-eval-after-load 'python
    (setf (nth 7 python-font-lock-keywords-maximum-decoration)
       `(,(rx symbol-start
              (or
               ;; Python 2 and 3:
               "ArithmeticError" "AssertionError" "AttributeError" "BaseException"
               "BufferError" "BytesWarning" "DeprecationWarning" "EOFError"
               "EnvironmentError" "Exception" "FloatingPointError" "FutureWarning"
               "GeneratorExit" "IOError" "ImportError" "ImportWarning"
               "IndentationError" "IndexError" "KeyError" "KeyboardInterrupt"
               "LookupError" "MemoryError" "NameError" "NotImplementedError"
               "OSError" "OverflowError" "PendingDeprecationWarning"
               "ReferenceError" "RuntimeError" "RuntimeWarning" "StopIteration"
               "SyntaxError" "SyntaxWarning" "SystemError" "SystemExit" "TabError"
               "TypeError" "UnboundLocalError" "UnicodeDecodeError"
               "UnicodeEncodeError" "UnicodeError" "UnicodeTranslateError"
               "UnicodeWarning" "UserWarning" "ValueError" "Warning"
               "ZeroDivisionError"
               ;; Python 2:
               "StandardError"
               ;; Python 3:
               "BlockingIOError" "BrokenPipeError" "ChildProcessError"
               "ConnectionAbortedError" "ConnectionError" "ConnectionRefusedError"
               "ConnectionResetError" "FileExistsError" "FileNotFoundError"
               "InterruptedError" "IsADirectoryError" "NotADirectoryError"
               "PermissionError" "ProcessLookupError" "RecursionError"
               "ResourceWarning" "StopAsyncIteration" "TimeoutError"
               ;; OS specific
               "VMSError" "WindowsError"
               ;; Custom
               "QuietExit"
               )
              symbol-end)
         . font-lock-type-face)))

You can find that here I've added the QuietExit 'custom keyword' to the end of the list.

To use it, just add the above code to your init file (and load it/restart Emacs).

dalanicolai
  • 6,108
  • 7
  • 23