diff options
| -rw-r--r-- | lisp/emacs-lisp/easy-mmode.el | 98 |
1 files changed, 87 insertions, 11 deletions
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el index 8f8fcf49184..72b64a4a881 100644 --- a/lisp/emacs-lisp/easy-mmode.el +++ b/lisp/emacs-lisp/easy-mmode.el | |||
| @@ -51,6 +51,8 @@ | |||
| 51 | 51 | ||
| 52 | ;;; Code: | 52 | ;;; Code: |
| 53 | 53 | ||
| 54 | (eval-when-compile (require 'cl)) | ||
| 55 | |||
| 54 | (defun easy-mmode-pretty-mode-name (mode &optional lighter) | 56 | (defun easy-mmode-pretty-mode-name (mode &optional lighter) |
| 55 | "Turn the symbol MODE into a string intended for the user. | 57 | "Turn the symbol MODE into a string intended for the user. |
| 56 | If provided LIGHTER will be used to help choose capitalization." | 58 | If provided LIGHTER will be used to help choose capitalization." |
| @@ -87,7 +89,9 @@ BODY contains code that will be executed each time the mode is (dis)activated. | |||
| 87 | (pretty-name (easy-mmode-pretty-mode-name mode lighter)) | 89 | (pretty-name (easy-mmode-pretty-mode-name mode lighter)) |
| 88 | (globalp nil) | 90 | (globalp nil) |
| 89 | ;; We might as well provide a best-guess default group. | 91 | ;; We might as well provide a best-guess default group. |
| 90 | (group (intern (replace-regexp-in-string "-mode\\'" "" mode-name))) | 92 | (group |
| 93 | (list 'quote | ||
| 94 | (intern (replace-regexp-in-string "-mode\\'" "" mode-name)))) | ||
| 91 | (keymap-sym (intern (concat mode-name "-map"))) | 95 | (keymap-sym (intern (concat mode-name "-map"))) |
| 92 | (hook (intern (concat mode-name "-hook"))) | 96 | (hook (intern (concat mode-name "-hook"))) |
| 93 | (hook-on (intern (concat mode-name "-on-hook"))) | 97 | (hook-on (intern (concat mode-name "-on-hook"))) |
| @@ -98,10 +102,11 @@ BODY contains code that will be executed each time the mode is (dis)activated. | |||
| 98 | (setq init-value (cdr init-value) globalp t)) | 102 | (setq init-value (cdr init-value) globalp t)) |
| 99 | 103 | ||
| 100 | ;; Check keys. | 104 | ;; Check keys. |
| 101 | (while | 105 | (while (keywordp (car body)) |
| 102 | (case (car body) | 106 | (case (pop body) |
| 103 | (:global (setq body (cdr body)) (setq globalp (pop body))) | 107 | (:global (setq globalp (pop body))) |
| 104 | (:group (setq body (cdr body)) (setq group (pop body))))) | 108 | (:group (setq group (pop body))) |
| 109 | (t (setq body (cdr body))))) | ||
| 105 | 110 | ||
| 106 | ;; Add default properties to LIGHTER. | 111 | ;; Add default properties to LIGHTER. |
| 107 | (unless (or (not (stringp lighter)) (get-text-property 0 'local-map lighter) | 112 | (unless (or (not (stringp lighter)) (get-text-property 0 'local-map lighter) |
| @@ -116,6 +121,8 @@ BODY contains code that will be executed each time the mode is (dis)activated. | |||
| 116 | `(progn | 121 | `(progn |
| 117 | ;; Define the variable to enable or disable the mode. | 122 | ;; Define the variable to enable or disable the mode. |
| 118 | ,(if globalp | 123 | ,(if globalp |
| 124 | ;; BEWARE! autoload.el depends on this `defcustom' coming | ||
| 125 | ;; as the first element after progn. | ||
| 119 | `(defcustom ,mode ,init-value | 126 | `(defcustom ,mode ,init-value |
| 120 | ,(format "Toggle %s. | 127 | ,(format "Toggle %s. |
| 121 | Setting this variable directly does not take effect; | 128 | Setting this variable directly does not take effect; |
| @@ -123,7 +130,7 @@ use either \\[customize] or the function `%s'." | |||
| 123 | pretty-name mode) | 130 | pretty-name mode) |
| 124 | :set (lambda (symbol value) (funcall symbol (or value 0))) | 131 | :set (lambda (symbol value) (funcall symbol (or value 0))) |
| 125 | :initialize 'custom-initialize-default | 132 | :initialize 'custom-initialize-default |
| 126 | :group ',group | 133 | :group ,group |
| 127 | :type 'boolean) | 134 | :type 'boolean) |
| 128 | `(progn | 135 | `(progn |
| 129 | (defvar ,mode ,init-value ,(format "Non-nil if %s is enabled. | 136 | (defvar ,mode ,init-value ,(format "Non-nil if %s is enabled. |
| @@ -143,7 +150,7 @@ Use the function `%s' to change this variable." pretty-name mode)) | |||
| 143 | ;; The toggle's hook. | 150 | ;; The toggle's hook. |
| 144 | (defcustom ,hook nil | 151 | (defcustom ,hook nil |
| 145 | ,(format "Hook run at the end of function `%s'." mode-name) | 152 | ,(format "Hook run at the end of function `%s'." mode-name) |
| 146 | :group ',group | 153 | :group ,group |
| 147 | :type 'hook) | 154 | :type 'hook) |
| 148 | 155 | ||
| 149 | ;; The actual function. | 156 | ;; The actual function. |
| @@ -174,6 +181,75 @@ With zero or negative ARG turn mode off. | |||
| 174 | ,(if globalp `(if ,mode (,mode 1)))))) | 181 | ,(if globalp `(if ,mode (,mode 1)))))) |
| 175 | 182 | ||
| 176 | ;;; | 183 | ;;; |
| 184 | ;;; make global minor mode | ||
| 185 | ;;; | ||
| 186 | |||
| 187 | (defmacro easy-mmode-define-global-mode (global-mode mode turn-on | ||
| 188 | &rest keys) | ||
| 189 | "Make GLOBAL-MODE out of the MODE buffer-local minor mode. | ||
| 190 | TURN-ON is a function that will be called with no args in every buffer | ||
| 191 | and that should try to turn MODE on if applicable for that buffer. | ||
| 192 | KEYS is a list of CL-style keyword arguments: | ||
| 193 | :group to specify the custom group." | ||
| 194 | (let* ((mode-name (symbol-name mode)) | ||
| 195 | (global-mode-name (symbol-name global-mode)) | ||
| 196 | (pretty-name (easy-mmode-pretty-mode-name mode)) | ||
| 197 | (pretty-global-name (easy-mmode-pretty-mode-name global-mode)) | ||
| 198 | ;; We might as well provide a best-guess default group. | ||
| 199 | (group | ||
| 200 | (list 'quote | ||
| 201 | (intern (replace-regexp-in-string "-mode\\'" "" mode-name)))) | ||
| 202 | (buffers (intern (concat global-mode-name "-buffers"))) | ||
| 203 | (cmmh (intern (concat global-mode-name "-cmmh")))) | ||
| 204 | |||
| 205 | ;; Check keys. | ||
| 206 | (while (keywordp (car keys)) | ||
| 207 | (case (pop keys) | ||
| 208 | (:group (setq group (pop keys))) | ||
| 209 | (t (setq keys (cdr keys))))) | ||
| 210 | |||
| 211 | `(progn | ||
| 212 | ;; BEWARE! autoload.el depends on `define-minor-mode' coming | ||
| 213 | ;; as the first element after progn. | ||
| 214 | |||
| 215 | ;; The actual global minor-mode | ||
| 216 | (define-minor-mode ,global-mode | ||
| 217 | ,(format "Toggle %s in every buffer. | ||
| 218 | With prefix ARG, turn %s on if and only if ARG is positive. | ||
| 219 | %s is actually not turned on in every buffer but only in those | ||
| 220 | in which `%s' turns it on." | ||
| 221 | pretty-name pretty-global-name pretty-name turn-on) | ||
| 222 | nil nil nil :global t :group ,group | ||
| 223 | |||
| 224 | ;; Setup hook to handle future mode changes and new buffers. | ||
| 225 | (if ,global-mode | ||
| 226 | (add-hook 'change-major-mode-hook ',cmmh) | ||
| 227 | (remove-hook 'change-major-mode-hook ',cmmh)) | ||
| 228 | |||
| 229 | ;; Go through existing buffers. | ||
| 230 | (dolist (buf (buffer-list)) | ||
| 231 | (with-current-buffer buf | ||
| 232 | (if ,global-mode (,turn-on) (,mode -1))))) | ||
| 233 | |||
| 234 | ;; List of buffers left to process. | ||
| 235 | (defvar ,buffers nil) | ||
| 236 | |||
| 237 | ;; The function that calls TURN-ON in each buffer. | ||
| 238 | (defun ,buffers () | ||
| 239 | (while ,buffers | ||
| 240 | (when (buffer-name (car ,buffers)) | ||
| 241 | (with-current-buffer (pop ,buffers) | ||
| 242 | (,turn-on)))) | ||
| 243 | (remove-hook 'post-command-hook ',buffers) | ||
| 244 | (remove-hook 'after-find-file ',buffers)) | ||
| 245 | |||
| 246 | ;; The function that catches kill-all-local-variables. | ||
| 247 | (defun ,cmmh () | ||
| 248 | (add-to-list ',buffers (current-buffer)) | ||
| 249 | (add-hook 'post-command-hook ',buffers) | ||
| 250 | (add-hook 'after-find-file ',buffers))))) | ||
| 251 | |||
| 252 | ;;; | ||
| 177 | ;;; easy-mmode-defmap | 253 | ;;; easy-mmode-defmap |
| 178 | ;;; | 254 | ;;; |
| 179 | 255 | ||
| @@ -200,10 +276,10 @@ ARGS is a list of additional arguments." | |||
| 200 | (while args | 276 | (while args |
| 201 | (let ((key (pop args)) | 277 | (let ((key (pop args)) |
| 202 | (val (pop args))) | 278 | (val (pop args))) |
| 203 | (cond | 279 | (case key |
| 204 | ((eq key :dense) (setq dense val)) | 280 | (:dense (setq dense val)) |
| 205 | ((eq key :inherit) (setq inherit val)) | 281 | (:inherit (setq inherit val)) |
| 206 | ((eq key :group) ) | 282 | (:group) |
| 207 | ;;((eq key :suppress) (setq suppress val)) | 283 | ;;((eq key :suppress) (setq suppress val)) |
| 208 | (t (message "Unknown argument %s in defmap" key))))) | 284 | (t (message "Unknown argument %s in defmap" key))))) |
| 209 | (unless (keymapp m) | 285 | (unless (keymapp m) |