dotemacs

My Emacs configuration
git clone git://git.entf.net/dotemacs
Log | Files | Refs | LICENSE

highlight-function-calls.el (5448B)


      1 ;;; highlight-function-calls.el --- Highlight function/macro calls  -*- lexical-binding: t; -*-
      2 
      3 ;; Author: Adam Porter <adam@alphapapa.net>
      4 ;; Url: http://github.com/alphapapa/highlight-function-calls
      5 ;; Version: 0.2-pre
      6 ;; Package-Requires: ((emacs "24.4"))
      7 ;; Keywords: faces, highlighting
      8 
      9 ;;; Commentary:
     10 
     11 ;; This package highlights function symbols in function calls.  This
     12 ;; makes them stand out from other symbols, which makes it easy to see
     13 ;; where calls to other functions are.  Optionally, macros and special
     14 ;; forms can be highlighted as well.  Also, a list of symbols can be
     15 ;; excluded from highlighting; by default, ones like +/-, </>, error,
     16 ;; require, etc. are excluded.  Finally, the `not' function can be
     17 ;; highlighted specially.
     18 
     19 ;; Just run `highlight-function-calls-mode' to activate, or you can
     20 ;; add that to your `emacs-lisp-mode-hook' to do it automatically.
     21 
     22 ;;; License:
     23 
     24 ;; This program is free software; you can redistribute it and/or modify
     25 ;; it under the terms of the GNU General Public License as published by
     26 ;; the Free Software Foundation, either version 3 of the License, or
     27 ;; (at your option) any later version.
     28 
     29 ;; This program is distributed in the hope that it will be useful,
     30 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     31 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     32 ;; GNU General Public License for more details.
     33 
     34 ;; You should have received a copy of the GNU General Public License
     35 ;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
     36 
     37 ;;; Code:
     38 
     39 (defgroup highlight-function-calls nil
     40   "Options for highlighting function/macro calls and special forms."
     41   :group 'faces)
     42 
     43 (defface highlight-function-calls-face
     44   '((t (:underline t)))
     45   "Face for highlighting function calls."
     46   :group 'highlight-function-calls)
     47 
     48 (defface highlight-function-calls--not-face
     49   '((t (:inherit font-lock-negation-char-face)))
     50   "Face for highlighting `not'."
     51   :group 'highlight-function-calls)
     52 
     53 (defcustom highlight-function-calls-exclude-symbols
     54   '( = + - / * < > <= >=
     55      debug  ; Not intended as an interactive function
     56      error provide require signal throw user-error)
     57   "List of symbols to not highlight."
     58   :type '(repeat symbol))
     59 
     60 (defcustom highlight-function-calls-macro-calls nil
     61   "Whether to highlight macro calls."
     62   :type 'boolean)
     63 
     64 (defcustom highlight-function-calls-special-forms nil
     65   "Whether to highlight special-forms calls."
     66   :type 'boolean)
     67 
     68 (defcustom highlight-function-calls-not nil
     69   "Whether to highlight `not'."
     70   :type 'boolean)
     71 
     72 (defconst highlight-function-calls--keywords
     73   `((;; (MATCHER . ANCHORED-HIGHLIGHTER):
     74 
     75      ;; MATCHER
     76      ;; First we match an opening paren, which prevents matching
     77      ;; function names as arguments.  We also avoid matching opening
     78      ;; parens immediately after quotes (but we can't do the same for
     79      ;; deeper levels).
     80      ,(rx (or bol (one-or-more space) ",") "("
     81           (group symbol-start (1+ (not blank)) symbol-end))
     82 
     83      (;; ANCHORED-HIGHLIGHTER:
     84       ;; FUNCTION
     85       highlight-function-calls--matcher
     86       ;; PRE-FORM
     87       nil
     88       ;; POST-FORM
     89       nil
     90       ;; SUBEXP-HIGHLIGHTER
     91       (1 highlight-function-calls--face-name prepend)))
     92     (;; (MATCHER . ANCHORED-HIGHLIGHTER):
     93      ;; MATCHER
     94      ,(rx "#'" symbol-start (group (1+ (not blank))) symbol-end)
     95      ;; ANCHORED-HIGHLIGHTER:
     96      ;; FUNCTION
     97      highlight-function-calls--matcher
     98      ;; PRE-FORM
     99      nil
    100      ;; POST-FORM
    101      nil
    102      ;; SUBEXP-HIGHLIGHTER
    103      (0 highlight-function-calls--face-name prepend)))
    104   "Keywords argument for `font-lock-add-keywords'.")
    105 
    106 (defvar highlight-function-calls--face-name nil)
    107 
    108 (defun highlight-function-calls--matcher (end)
    109   "Match function symbols up to END.
    110 The match function to be used by font lock mode."
    111   (catch 'highlight-function-calls--matcher
    112     (when (not (nth 5 (syntax-ppss)))
    113       (let ((match (intern-soft (match-string 1))))
    114         (when (and (or (functionp match)
    115                        (when highlight-function-calls-macro-calls
    116                          (macrop match))
    117                        (when highlight-function-calls-special-forms
    118                          (special-form-p match)))
    119                    (not (member match highlight-function-calls-exclude-symbols)))
    120           (setq highlight-function-calls--face-name
    121                 (pcase match
    122                   ((and (or 'not 'null) (guard highlight-function-calls-not)) 'highlight-function-calls--not-face)
    123                   (_ 'highlight-function-calls-face)))
    124           (goto-char end)
    125           (throw 'highlight-function-calls--matcher t))))
    126     nil))
    127 
    128 ;;;###autoload
    129 (define-minor-mode highlight-function-calls-mode
    130   "Highlight function calls.
    131 
    132 Toggle highlighting of function calls on or off.
    133 
    134 With a prefix argument ARG, enable if ARG is positive, and
    135 disable it otherwise.  If called from Lisp, enable the mode if
    136 ARG is omitted or nil, and toggle it if ARG is `toggle'."
    137   :init-value nil :lighter nil :keymap nil
    138   (let ((keywords highlight-function-calls--keywords))
    139     (font-lock-remove-keywords nil keywords)
    140     (when highlight-function-calls-mode
    141       (font-lock-add-keywords nil keywords 'append)))
    142   ;; Refresh font locking.
    143   (when font-lock-mode
    144     (if (fboundp 'font-lock-flush)
    145         (font-lock-flush)
    146       (with-no-warnings (font-lock-fontify-buffer)))))
    147 
    148 (provide 'highlight-function-calls)
    149 
    150 ;;; highlight-function-calls.el ends here