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