diff options
| author | Richard M. Stallman | 1997-06-22 20:08:32 +0000 |
|---|---|---|
| committer | Richard M. Stallman | 1997-06-22 20:08:32 +0000 |
| commit | 6b2797406826346ad2f3dfaeb1837d602e844bb9 (patch) | |
| tree | 2c45d2407ab7434ec053407b944ebb00d29a1264 | |
| parent | 326e87d25cab2a13ff23191635388fb4c9b2ea74 (diff) | |
| download | emacs-6b2797406826346ad2f3dfaeb1837d602e844bb9.tar.gz emacs-6b2797406826346ad2f3dfaeb1837d602e844bb9.zip | |
Initial revision
| -rw-r--r-- | lisp/battery.el | 279 | ||||
| -rw-r--r-- | lisp/emacs-lisp/easy-mmode.el | 169 | ||||
| -rw-r--r-- | lisp/filecache.el | 666 | ||||
| -rw-r--r-- | lisp/progmodes/meta-mode.el | 1099 | ||||
| -rw-r--r-- | src/m/news-r6.h | 65 | ||||
| -rw-r--r-- | src/s/newsos6.h | 6 |
6 files changed, 2284 insertions, 0 deletions
diff --git a/lisp/battery.el b/lisp/battery.el new file mode 100644 index 00000000000..b04b6af369f --- /dev/null +++ b/lisp/battery.el | |||
| @@ -0,0 +1,279 @@ | |||
| 1 | ;;; battery.el --- display battery status information. | ||
| 2 | |||
| 3 | ;; Copyright (C) 1997 Ralph Schleicher | ||
| 4 | |||
| 5 | ;; Author: Ralph Schleicher <rs@purple.UL.BaWue.DE> | ||
| 6 | ;; Keywords: local hardware | ||
| 7 | |||
| 8 | ;; This file is not part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; This program is free software; you can redistribute it and/or modify | ||
| 11 | ;; it under the terms of the GNU General Public License as published by | ||
| 12 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 13 | ;; any later version. | ||
| 14 | |||
| 15 | ;; This program is distributed in the hope that it will be useful, | ||
| 16 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | ;; GNU General Public License for more details. | ||
| 19 | |||
| 20 | ;; You should have received a copy of the GNU General Public License | ||
| 21 | ;; along with this program; see the file COPYING. If not, write to | ||
| 22 | ;; the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 23 | ;; Boston, MA 02111-1307, USA. | ||
| 24 | |||
| 25 | ;;; Commentary: | ||
| 26 | |||
| 27 | ;; There is at present only a function interpreting the new `/proc/apm' | ||
| 28 | ;; file format of Linux version 1.3.58 or newer. That is, what a lucky | ||
| 29 | ;; coincidence, exactly the interface provided by the author's labtop. | ||
| 30 | |||
| 31 | ;;; Code: | ||
| 32 | |||
| 33 | (require 'timer) | ||
| 34 | |||
| 35 | |||
| 36 | (defvar battery-status-function | ||
| 37 | (cond ((and (eq system-type 'gnu/linux) | ||
| 38 | (file-readable-p "/proc/apm")) | ||
| 39 | 'battery-linux-proc-apm)) | ||
| 40 | "*Function for getting battery status information. | ||
| 41 | The function have to return an alist of conversion definitions. | ||
| 42 | Cons cells are of the form | ||
| 43 | |||
| 44 | (CONVERSION . REPLACEMENT-TEXT) | ||
| 45 | |||
| 46 | CONVERSION is the character code of a \"conversion specification\" | ||
| 47 | introduced by a `%' character in a control string.") | ||
| 48 | |||
| 49 | (defvar battery-echo-area-format | ||
| 50 | (cond ((eq battery-status-function 'battery-linux-proc-apm) | ||
| 51 | "Power %L, battery %B (%p%% load, remaining time %t)")) | ||
| 52 | "*Control string formatting the string to display in the echo area. | ||
| 53 | Ordinary characters in the control string are printed as-is, while | ||
| 54 | conversion specifications introduced by a `%' character in the control | ||
| 55 | string are substituted as defined by the current value of the variable | ||
| 56 | `battery-status-function'.") | ||
| 57 | |||
| 58 | (defvar battery-mode-line-string nil | ||
| 59 | "String to display in the mode line.") | ||
| 60 | |||
| 61 | (defvar battery-mode-line-format | ||
| 62 | (cond ((eq battery-status-function 'battery-linux-proc-apm) | ||
| 63 | " [%b%p%%]")) | ||
| 64 | "*Control string formatting the string to display in the mode line. | ||
| 65 | Ordinary characters in the control string are printed as-is, while | ||
| 66 | conversion specifications introduced by a `%' character in the control | ||
| 67 | string are substituted as defined by the current value of the variable | ||
| 68 | `battery-status-function'.") | ||
| 69 | |||
| 70 | (defvar battery-update-interval 60 | ||
| 71 | "*Seconds after which the battery status will be updated.") | ||
| 72 | |||
| 73 | (defvar battery-update-timer nil | ||
| 74 | "Interval timer object.") | ||
| 75 | |||
| 76 | ;;;### autoload | ||
| 77 | (defun battery () | ||
| 78 | "Display battery status information in the echo area. | ||
| 79 | The text beeing displayed in the echo area is controlled by the variables | ||
| 80 | `battery-echo-area-format' and `battery-status-function'." | ||
| 81 | (interactive) | ||
| 82 | (message "%s" (if (and battery-echo-area-format battery-status-function) | ||
| 83 | (battery-format battery-echo-area-format | ||
| 84 | (funcall battery-status-function)) | ||
| 85 | "Battery status not available"))) | ||
| 86 | |||
| 87 | ;;;### autoload | ||
| 88 | (defun display-battery () | ||
| 89 | "Display battery status information in the mode line. | ||
| 90 | The text beeing displayed in the mode line is controlled by the variables | ||
| 91 | `battery-mode-line-format' and `battery-status-function'. | ||
| 92 | The mode line will be updated automatically every `battery-update-interval' | ||
| 93 | seconds." | ||
| 94 | (interactive) | ||
| 95 | (setq battery-mode-line-string "") | ||
| 96 | (or global-mode-string (setq global-mode-string '(""))) | ||
| 97 | (or (memq 'battery-mode-line-string global-mode-string) | ||
| 98 | (setq global-mode-string (append global-mode-string | ||
| 99 | '(battery-mode-line-string)))) | ||
| 100 | (and battery-update-timer (cancel-timer battery-update-timer)) | ||
| 101 | (setq battery-update-timer (run-at-time nil battery-update-interval | ||
| 102 | 'battery-update-handler)) | ||
| 103 | (battery-update)) | ||
| 104 | |||
| 105 | (defun battery-update-handler () | ||
| 106 | (battery-update) | ||
| 107 | (sit-for 0)) | ||
| 108 | |||
| 109 | (defun battery-update () | ||
| 110 | "Update battery status information in the mode line." | ||
| 111 | (setq battery-mode-line-string (if (and battery-mode-line-format | ||
| 112 | battery-status-function) | ||
| 113 | (battery-format | ||
| 114 | battery-mode-line-format | ||
| 115 | (funcall battery-status-function)) | ||
| 116 | "")) | ||
| 117 | (force-mode-line-update)) | ||
| 118 | |||
| 119 | |||
| 120 | ;;; `/proc/apm' interface for Linux. | ||
| 121 | |||
| 122 | (defconst battery-linux-proc-apm-regexp | ||
| 123 | (concat "^\\([^ ]+\\)" ; Driver version. | ||
| 124 | " \\([^ ]+\\)" ; APM BIOS version. | ||
| 125 | " 0x\\([0-9a-f]+\\)" ; APM BIOS flags. | ||
| 126 | " 0x\\([0-9a-f]+\\)" ; AC line status. | ||
| 127 | " 0x\\([0-9a-f]+\\)" ; Battery status. | ||
| 128 | " 0x\\([0-9a-f]+\\)" ; Battery flags. | ||
| 129 | " \\([0-9]+\\)%" ; Load percentage. | ||
| 130 | " \\([0-9]+\\)" ; Remaining time. | ||
| 131 | " \\(.*\\)" ; Time unit. | ||
| 132 | "$") | ||
| 133 | "Regular expression matching contents of `/proc/apm'.") | ||
| 134 | |||
| 135 | (defun battery-linux-proc-apm () | ||
| 136 | "Get APM status information from Linux kernel. | ||
| 137 | This function works only with the new `/proc/apm' format introduced | ||
| 138 | in Linux version 1.3.58. | ||
| 139 | |||
| 140 | The following %-sequences are provided: | ||
| 141 | %v Linux driver version | ||
| 142 | %V APM BIOS version | ||
| 143 | %I APM BIOS status (verbose) | ||
| 144 | %L AC line status (verbose) | ||
| 145 | %B Battery status (verbose) | ||
| 146 | %b Battery status, empty means high, `-' means low, | ||
| 147 | `!' means critical, and `+' means charging | ||
| 148 | %p battery load percentage | ||
| 149 | %s Remaining time in seconds | ||
| 150 | %m Remaining time in minutes | ||
| 151 | %h Remaining time in hours | ||
| 152 | %t Remaining time in the form `h:min'" | ||
| 153 | (let (driver-version bios-version bios-interface line-status | ||
| 154 | battery-status battery-status-symbol load-percentage | ||
| 155 | seconds minutes hours remaining-time buffer tem) | ||
| 156 | (unwind-protect | ||
| 157 | (save-excursion | ||
| 158 | (setq buffer (generate-new-buffer " *battery*")) | ||
| 159 | (buffer-disable-undo buffer) | ||
| 160 | (set-buffer buffer) | ||
| 161 | (battery-insert-file-contents "/proc/apm") | ||
| 162 | (re-search-forward battery-linux-proc-apm-regexp) | ||
| 163 | (setq driver-version (match-string 1)) | ||
| 164 | (setq bios-version (match-string 2)) | ||
| 165 | (setq tem (battery-hex-to-int-2 (match-string 3))) | ||
| 166 | (if (not (logand tem 2)) | ||
| 167 | (setq bios-interface "not supported") | ||
| 168 | (setq bios-interface "enabled") | ||
| 169 | (cond ((logand tem 16) (setq bios-interface "disabled")) | ||
| 170 | ((logand tem 32) (setq bios-interface "disengaged"))) | ||
| 171 | (setq tem (battery-hex-to-int-2 (match-string 4))) | ||
| 172 | (cond ((= tem 0) (setq line-status "off-line")) | ||
| 173 | ((= tem 1) (setq line-status "on-line")) | ||
| 174 | ((= tem 2) (setq line-status "on backup"))) | ||
| 175 | (setq tem (battery-hex-to-int-2 (match-string 6))) | ||
| 176 | (if (= tem 255) | ||
| 177 | (setq battery-status "N/A") | ||
| 178 | (setq tem (battery-hex-to-int-2 (match-string 5))) | ||
| 179 | (cond ((= tem 0) (setq battery-status "high" | ||
| 180 | battery-status-symbol "")) | ||
| 181 | ((= tem 1) (setq battery-status "low" | ||
| 182 | battery-status-symbol "-")) | ||
| 183 | ((= tem 2) (setq battery-status "critical" | ||
| 184 | battery-status-symbol "!")) | ||
| 185 | ((= tem 3) (setq battery-status "charging" | ||
| 186 | battery-status-symbol "+"))) | ||
| 187 | (setq load-percentage (match-string 7)) | ||
| 188 | (setq seconds (string-to-number (match-string 8))) | ||
| 189 | (and (string-equal (match-string 9) "min") | ||
| 190 | (setq seconds (* 60 seconds))) | ||
| 191 | (setq minutes (/ seconds 60) | ||
| 192 | hours (/ seconds 3600)) | ||
| 193 | (setq remaining-time | ||
| 194 | (format "%d:%02d" hours (- minutes (* 60 hours))))))) | ||
| 195 | (and buffer (kill-buffer buffer))) | ||
| 196 | (list (cons ?v driver-version) | ||
| 197 | (cons ?V bios-version) | ||
| 198 | (cons ?I bios-interface) | ||
| 199 | (cons ?L line-status) | ||
| 200 | (cons ?B battery-status) | ||
| 201 | (cons ?b battery-status-symbol) | ||
| 202 | (cons ?p load-percentage) | ||
| 203 | (cons ?s (and seconds (number-to-string seconds))) | ||
| 204 | (cons ?m (and minutes (number-to-string minutes))) | ||
| 205 | (cons ?h (and hours (number-to-string hours))) | ||
| 206 | (cons ?t remaining-time)))) | ||
| 207 | |||
| 208 | |||
| 209 | ;;; Private functions. | ||
| 210 | |||
| 211 | (defun battery-format (format alist) | ||
| 212 | "Substitute %-sequences in FORMAT." | ||
| 213 | (let ((index 0) | ||
| 214 | (length (length format)) | ||
| 215 | (result "") | ||
| 216 | char flag elem) | ||
| 217 | (while (< index length) | ||
| 218 | (setq char (aref format index)) | ||
| 219 | (if (not flag) | ||
| 220 | (if (char-equal char ?%) | ||
| 221 | (setq flag t) | ||
| 222 | (setq result (concat result (char-to-string char)))) | ||
| 223 | (cond ((char-equal char ?%) | ||
| 224 | (setq result (concat result "%"))) | ||
| 225 | ((setq elem (assoc char alist)) | ||
| 226 | (setq result (concat result (cdr elem))))) | ||
| 227 | (setq flag nil)) | ||
| 228 | (setq index (1+ index))) | ||
| 229 | (or (null flag) | ||
| 230 | (setq result (concat result "%"))) | ||
| 231 | result)) | ||
| 232 | |||
| 233 | (defun battery-insert-file-contents (file-name) | ||
| 234 | "Insert contents of file FILE-NAME after point. | ||
| 235 | FILE-NAME can be a non-ordinary file, for example, a named pipe. | ||
| 236 | Return t if file exists." | ||
| 237 | (let ((load-read-function 'battery-read-function) | ||
| 238 | (load-path '(".")) | ||
| 239 | (load-history nil)) | ||
| 240 | (save-excursion | ||
| 241 | (load file-name nil t t)))) | ||
| 242 | |||
| 243 | (defun battery-read-function (&optional stream) | ||
| 244 | "Function for reading expressions from STREAM. | ||
| 245 | Value is always nil." | ||
| 246 | (let (char) | ||
| 247 | (while (not (< (setq char (get-file-char)) 0)) | ||
| 248 | (insert char)))) | ||
| 249 | |||
| 250 | (defconst battery-hex-map '((?0 . 0) (?1 . 1) (?2 . 2) (?3 . 3) | ||
| 251 | (?4 . 4) (?5 . 5) (?6 . 6) (?7 . 7) | ||
| 252 | (?8 . 8) (?9 . 9) (?a . 10) (?b . 11) | ||
| 253 | (?c . 12) (?d . 13) (?e . 14) (?f . 15))) | ||
| 254 | |||
| 255 | (defun battery-hex-to-int (string) | ||
| 256 | "Convert a hexadecimal number (a string) into a number." | ||
| 257 | (save-match-data | ||
| 258 | (and (string-match "^[ \t]+" string) | ||
| 259 | (setq string (substring string (match-end 0)))) | ||
| 260 | (and (string-match "^0[xX]" string) | ||
| 261 | (setq string (substring string (match-end 0))))) | ||
| 262 | (battery-hex-to-int-2 string)) | ||
| 263 | |||
| 264 | (defun battery-hex-to-int-2 (string) | ||
| 265 | (let ((index 0) | ||
| 266 | (length (length string)) | ||
| 267 | (value 0) | ||
| 268 | (elem nil)) | ||
| 269 | (while (and (< index length) | ||
| 270 | (setq elem (assoc (downcase (aref string index)) | ||
| 271 | battery-hex-map))) | ||
| 272 | (setq value (+ (* 16 value) (cdr elem)) | ||
| 273 | index (1+ index))) | ||
| 274 | value)) | ||
| 275 | |||
| 276 | |||
| 277 | (provide 'battery) | ||
| 278 | |||
| 279 | ;;; battery.el ends here | ||
diff --git a/lisp/emacs-lisp/easy-mmode.el b/lisp/emacs-lisp/easy-mmode.el new file mode 100644 index 00000000000..866b32ccc8f --- /dev/null +++ b/lisp/emacs-lisp/easy-mmode.el | |||
| @@ -0,0 +1,169 @@ | |||
| 1 | ;;; easy-mmode.el --- easy definition of minor modes. | ||
| 2 | |||
| 3 | ;; Copyright (C) 1997 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Georges Brun-Cottan <Georges.Brun-Cottan@inria.fr> | ||
| 6 | |||
| 7 | ;; This file is part of GNU Emacs. | ||
| 8 | |||
| 9 | ;; GNU Emacs is free software; you can redistribute it and/or modify | ||
| 10 | ;; it under the terms of the GNU General Public License as published by | ||
| 11 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 12 | ;; any later version. | ||
| 13 | |||
| 14 | ;; GNU Emacs is distributed in the hope that it will be useful, | ||
| 15 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | ;; GNU General Public License for more details. | ||
| 18 | |||
| 19 | ;; You should have received a copy of the GNU General Public License | ||
| 20 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 21 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 22 | ;; Boston, MA 02111-1307, USA. | ||
| 23 | |||
| 24 | ;;; Commentary: | ||
| 25 | |||
| 26 | ;; Minor modes are useful and common. This package makes defining a | ||
| 27 | ;; minor mode easy, by focusing on the writing of the minor mode | ||
| 28 | ;; functionalities themselves. Moreover, this package enforces a | ||
| 29 | ;; conventional naming of user interface primitives, making things | ||
| 30 | ;; natural for the minor-mode end-users. | ||
| 31 | |||
| 32 | ;; For each mode, easy-mmode defines the following: | ||
| 33 | ;; <mode> : The minor mode predicate. A buffer-local variable. | ||
| 34 | ;; <mode>-map : The keymap possibly associated to <mode>. | ||
| 35 | ;; <mode>-hook,<mode>-on-hook,<mode>-off-hook and <mode>-mode: | ||
| 36 | ;; see `easy-mmode-define-minor-mode' documentation | ||
| 37 | ;; | ||
| 38 | ;; eval | ||
| 39 | ;; (pp (macroexpand '(easy-mmode-define-minor-mode <your-mode> <doc>))) | ||
| 40 | ;; to check the result before using it. | ||
| 41 | |||
| 42 | ;; The order in which minor modes are installed is important. Keymap | ||
| 43 | ;; lookup proceeds down minor-mode-map-alist, and the order there | ||
| 44 | ;; tends to be the reverse of the order in which the modes were | ||
| 45 | ;; installed. Perhaps there should be a feature to let you specify | ||
| 46 | ;; orderings. | ||
| 47 | |||
| 48 | ;;; Code: | ||
| 49 | |||
| 50 | (defun easy-mmode-define-keymap (keymap-alist &optional menu-name) | ||
| 51 | "Return a keymap builded from KEYMAP-ALIST. | ||
| 52 | KEYMAP-ALIST must be a list of (KEYBINDING . BINDING) where | ||
| 53 | KEYBINDING and BINDINGS are suited as for define-key. | ||
| 54 | optional MENU-NAME is passed to `make-sparse-keymap'." | ||
| 55 | (let ((keymap (make-sparse-keymap menu-name))) | ||
| 56 | (mapcar | ||
| 57 | (function (lambda (bind) | ||
| 58 | (define-key keymap | ||
| 59 | (car bind) (cdr bind)))) | ||
| 60 | keymap-alist) | ||
| 61 | keymap)) | ||
| 62 | |||
| 63 | (defmacro easy-mmode-define-toggle (mode &optional doc) | ||
| 64 | "Define a one arg toggle mode MODE function and associated hooks. | ||
| 65 | MODE-mode is the so defined function that toggle the mode. | ||
| 66 | optional DOC is its associated documentation. | ||
| 67 | |||
| 68 | Hooks are checked for run, each time MODE-mode is called. | ||
| 69 | They run under the followings conditions: | ||
| 70 | MODE-hook: if the mode is toggled. | ||
| 71 | MODE-on-hook: if the mode is on. | ||
| 72 | MODE-off-hook: if the mode is off. | ||
| 73 | |||
| 74 | When the mode is effectively toggled, two hooks may run. | ||
| 75 | If so MODE-hook is guaranteed to be the first. | ||
| 76 | |||
| 77 | \(defmacro easy-mmode-define-toggle (MODE &optional DOC)" | ||
| 78 | (let* ((mode-name | ||
| 79 | (if (string-match "-mode\\'" (symbol-name mode)) | ||
| 80 | (symbol-name mode) | ||
| 81 | (concat (symbol-name mode) "-mode"))) | ||
| 82 | (hook (intern (concat mode-name "-hook"))) | ||
| 83 | (hook-on (intern (concat mode-name "-on-hook"))) | ||
| 84 | (hook-off (intern (concat mode-name "-off-hook"))) | ||
| 85 | (toggle (intern mode-name)) | ||
| 86 | (mode toggle) | ||
| 87 | (toggle-doc (or doc | ||
| 88 | (format "With no argument, toggle %s mode. | ||
| 89 | With arg turn mode on. | ||
| 90 | With zero or negative arg turn mode off" | ||
| 91 | mode-name)))) | ||
| 92 | `(progn | ||
| 93 | (defvar ,hook nil | ||
| 94 | ,(format "Hook called when %s mode is toggled" mode-name)) | ||
| 95 | |||
| 96 | (defvar ,hook-on nil | ||
| 97 | ,(format "Hook called when %s mode is turned on" mode-name)) | ||
| 98 | |||
| 99 | (defvar ,hook-off nil | ||
| 100 | ,(format "Hook called when %s mode is turned off" mode-name)) | ||
| 101 | |||
| 102 | (defun ,toggle (&optional arg) | ||
| 103 | ,toggle-doc | ||
| 104 | (interactive "P") | ||
| 105 | (let ((old-mode ,mode)) | ||
| 106 | (setq ,mode | ||
| 107 | (if arg | ||
| 108 | (or (listp arg);; C-u alone | ||
| 109 | (> (prefix-numeric-value arg) 0)) | ||
| 110 | (not ,mode))) | ||
| 111 | (and ,hook | ||
| 112 | (not (equal old-mode ,mode)) | ||
| 113 | (run-hooks ',hook)) | ||
| 114 | (and ,hook-on | ||
| 115 | ,mode | ||
| 116 | (run-hooks ',hook-on)) | ||
| 117 | (and ,hook-off | ||
| 118 | (not ,mode) | ||
| 119 | (run-hooks ',hook-off))))))) | ||
| 120 | |||
| 121 | ;;;###autoload | ||
| 122 | (defmacro easy-mmode-define-minor-mode | ||
| 123 | (mode doc &optional init-value &optional lighter &optional keymap) | ||
| 124 | "Define a new minor mode MODE. | ||
| 125 | This function defines the associated control variable, keymap, | ||
| 126 | toggle command, and hooks (see `easy-mmode-define-toggle'). | ||
| 127 | |||
| 128 | DOC is the documentation for the mode toggle command. | ||
| 129 | Optional LIGHTER is displayed in the mode-bar when the mode is on. | ||
| 130 | Optional KEYMAP is the default (defvar) keymap bound to the mode keymap. | ||
| 131 | If it is a list, it is passed to `easy-mmode-define-keymap' | ||
| 132 | in order to build a valid keymap. | ||
| 133 | |||
| 134 | \(defmacro easy-mmode-define-minor-mode | ||
| 135 | (MODE DOC &optional INIT-VALUE &optional LIGHTER &optional KEYMAP)...\)" | ||
| 136 | (let* ((mode-name (symbol-name mode)) | ||
| 137 | (mode-doc (format "%s mode control switch." mode-name)) | ||
| 138 | (keymap-name (concat mode-name "-map")) | ||
| 139 | (keymap-doc (format "Keymap activated when %s mode is on." mode-name))) | ||
| 140 | `(progn | ||
| 141 | ;; define the switch | ||
| 142 | (defvar ,mode ,init-value ,mode-doc) | ||
| 143 | (make-variable-buffer-local ',mode) | ||
| 144 | |||
| 145 | ;; define the minor-mode keymap | ||
| 146 | (defvar ,(intern keymap-name) | ||
| 147 | (cond ((and ,keymap (keymapp ,keymap)) | ||
| 148 | ,keymap) | ||
| 149 | ((listp ,keymap) | ||
| 150 | (easy-mmode-define-keymap ,keymap)) | ||
| 151 | (t (error "Invalid keymap %S" ,keymap))) | ||
| 152 | ,keymap-doc) | ||
| 153 | |||
| 154 | ;; define the toggle and the hooks | ||
| 155 | ,(macroexpand `(easy-mmode-define-toggle ,mode ,doc)) ; toggle and hooks | ||
| 156 | |||
| 157 | ;; update the mode-bar | ||
| 158 | (or (assq ',mode minor-mode-alist) | ||
| 159 | (setq minor-mode-alist | ||
| 160 | (cons (list ',mode ,lighter) minor-mode-alist))) | ||
| 161 | |||
| 162 | ;; update the minor-mode-map | ||
| 163 | (or (assq ',mode minor-mode-map-alist) | ||
| 164 | (setq minor-mode-map-alist | ||
| 165 | (cons (cons ',mode ,(intern keymap-name)) minor-mode-map-alist)))) )) | ||
| 166 | |||
| 167 | (provide 'easy-mmode) | ||
| 168 | |||
| 169 | ;;; easy-mmode.el ends here | ||
diff --git a/lisp/filecache.el b/lisp/filecache.el new file mode 100644 index 00000000000..e8a55ac1645 --- /dev/null +++ b/lisp/filecache.el | |||
| @@ -0,0 +1,666 @@ | |||
| 1 | ;;; filecache.el --- Find files using a pre-loaded cache | ||
| 2 | ;; | ||
| 3 | ;; Author: Peter Breton | ||
| 4 | ;; Created: Sun Nov 10 1996 | ||
| 5 | ;; Version: $Id: filecache.el,v 1.13 1997/02/07 22:27:51 pbreton Exp $ | ||
| 6 | ;; Keywords: | ||
| 7 | ;; Time-stamp: <97/02/07 17:26:54 peter> | ||
| 8 | ;; | ||
| 9 | ;; Copyright (C) Peter Breton Thu Dec 12 1996 | ||
| 10 | ;; | ||
| 11 | ;; This is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 14 | ;; any later version. | ||
| 15 | ;; | ||
| 16 | ;; filecache.el is distributed in the hope that it will be useful, | ||
| 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 19 | ;; General Public License for more details. | ||
| 20 | ;; | ||
| 21 | ;; You should have received a copy of the GNU General Public License | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to | ||
| 23 | ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 24 | ;; | ||
| 25 | ;; LCD Archive Entry: | ||
| 26 | ;; filecache.el|Peter Breton|pbreton@i-kinetics.com| | ||
| 27 | ;; Find files using a pre-loaded cache| | ||
| 28 | ;; Thu Dec 12 1996|1.0|~/misc/filecache.el.gz| | ||
| 29 | ;; | ||
| 30 | ;; Purpose: | ||
| 31 | ;; | ||
| 32 | ;; Find files using a pre-loaded cache | ||
| 33 | ;; | ||
| 34 | ;;; Commentary: | ||
| 35 | ;; | ||
| 36 | ;; The file-cache package is an attempt to make it easy to locate files | ||
| 37 | ;; by name, without having to remember exactly where they are located. | ||
| 38 | ;; This is very handy when working with source trees. You can also add | ||
| 39 | ;; frequently used files to the cache to create a hotlist effect. | ||
| 40 | ;; The cache can be used with any interactive command which takes a | ||
| 41 | ;; filename as an argument. | ||
| 42 | ;; | ||
| 43 | ;; It is worth noting that this package works best when most of the files | ||
| 44 | ;; in the cache have unique names, or (if they have the same name) exist in | ||
| 45 | ;; only a few directories. The worst case is many files all with | ||
| 46 | ;; the same name and in different directories, for example a big source tree | ||
| 47 | ;; with a Makefile in each directory. In such a case, you should probably | ||
| 48 | ;; use an alternate strategy to find the files. | ||
| 49 | ;; | ||
| 50 | ;; ADDING FILES TO THE CACHE: | ||
| 51 | ;; | ||
| 52 | ;; Use the following functions to add items to the file cache: | ||
| 53 | ;; | ||
| 54 | ;; * `file-cache-add-file': Adds a single file to the cache | ||
| 55 | ;; | ||
| 56 | ;; * `file-cache-add-file-list': Adds a list of files to the cache | ||
| 57 | ;; | ||
| 58 | ;; The following functions use the regular expressions in | ||
| 59 | ;; `file-cache-delete-regexps' to eliminate unwanted files: | ||
| 60 | ;; | ||
| 61 | ;; * `file-cache-add-directory': Adds the files in a directory to the | ||
| 62 | ;; cache. You can also specify a regular expression to match the files | ||
| 63 | ;; which should be added. | ||
| 64 | ;; | ||
| 65 | ;; * `file-cache-add-directory-list': Same as above, but acts on a list | ||
| 66 | ;; of directories. You can use `load-path', `exec-path' and the like. | ||
| 67 | ;; | ||
| 68 | ;; * `file-cache-add-directory-using-find': Uses the `find' command to | ||
| 69 | ;; add a directory tree to the cache. | ||
| 70 | ;; | ||
| 71 | ;; * `file-cache-add-directory-using-locate': Uses the `locate' command to | ||
| 72 | ;; add files matching a pattern to the cache. | ||
| 73 | ;; | ||
| 74 | ;; Use the function `file-cache-clear-cache' to remove all items from the | ||
| 75 | ;; cache. There are a number of `file-cache-delete' functions provided | ||
| 76 | ;; as well, but in general it is probably better to not worry too much | ||
| 77 | ;; about extra files in the cache. | ||
| 78 | ;; | ||
| 79 | ;; The most convenient way to initialize the cache is with an | ||
| 80 | ;; `eval-after-load' function, as noted in the INSTALLATION section. | ||
| 81 | ;; | ||
| 82 | ;; FINDING FILES USING THE CACHE: | ||
| 83 | ;; | ||
| 84 | ;; You can use the file-cache with any function that expects a filename as | ||
| 85 | ;; an argument. For example: | ||
| 86 | ;; | ||
| 87 | ;; 1) Invoke a function which expects a filename as an argument: | ||
| 88 | ;; M-x find-file | ||
| 89 | ;; | ||
| 90 | ;; 2) Begin typing a file name. | ||
| 91 | ;; | ||
| 92 | ;; 3) Invoke `file-cache-minibuffer-complete' (bound by default to | ||
| 93 | ;; C-TAB) to complete on the filename using the cache. | ||
| 94 | ;; | ||
| 95 | ;; 4) When you have found a unique completion, the minibuffer contents | ||
| 96 | ;; will change to the full name of that file. | ||
| 97 | ;; | ||
| 98 | ;; If there are a number of directories which contain the completion, | ||
| 99 | ;; invoking `file-cache-minibuffer-complete' repeatedly will cycle through | ||
| 100 | ;; them. | ||
| 101 | ;; | ||
| 102 | ;; 5) You can then edit the minibuffer contents, or press RETURN. | ||
| 103 | ;; | ||
| 104 | ;; It is much easier to simply try it than trying to explain it :) | ||
| 105 | ;; | ||
| 106 | ;;; INSTALLATION | ||
| 107 | ;; | ||
| 108 | ;; Insert the following into your .emacs: | ||
| 109 | ;; | ||
| 110 | ;; (autoload 'file-cache-minibuffer-complete "filecache" nil t) | ||
| 111 | ;; | ||
| 112 | ;; For maximum utility, you should probably define an `eval-after-load' | ||
| 113 | ;; form which loads your favorite files: | ||
| 114 | ;; | ||
| 115 | ;; (eval-after-load | ||
| 116 | ;; "filecache" | ||
| 117 | ;; '(progn | ||
| 118 | ;; (message "Loading file cache...") | ||
| 119 | ;; (file-cache-add-directory-using-find "~/projects") | ||
| 120 | ;; (file-cache-add-directory-list load-path) | ||
| 121 | ;; (file-cache-add-directory "~/") | ||
| 122 | ;; (file-cache-add-file-list (list "~/foo/bar" "~/baz/bar")) | ||
| 123 | ;; )) | ||
| 124 | ;; | ||
| 125 | ;; If you clear and reload the cache frequently, it is probably easiest | ||
| 126 | ;; to put your initializations in a function: | ||
| 127 | ;; | ||
| 128 | ;; (eval-after-load | ||
| 129 | ;; "filecache" | ||
| 130 | ;; '(my-file-cache-initialize)) | ||
| 131 | ;; | ||
| 132 | ;; (defun my-file-cache-initialize () | ||
| 133 | ;; (interactive) | ||
| 134 | ;; (message "Loading file cache...") | ||
| 135 | ;; (file-cache-add-directory-using-find "~/projects") | ||
| 136 | ;; (file-cache-add-directory-list load-path) | ||
| 137 | ;; (file-cache-add-directory "~/") | ||
| 138 | ;; (file-cache-add-file-list (list "~/foo/bar" "~/baz/bar")) | ||
| 139 | ;; )) | ||
| 140 | ;; | ||
| 141 | ;; Of course, you can still add files to the cache afterwards, via | ||
| 142 | ;; Lisp functions. | ||
| 143 | ;; | ||
| 144 | ;; RELATED WORK: | ||
| 145 | ;; | ||
| 146 | ;; This package is a distant relative of Noah Friedman's fff utilities. | ||
| 147 | ;; Our goal is pretty similar, but the implementation strategies are | ||
| 148 | ;; different. | ||
| 149 | ;; | ||
| 150 | ;;; Change log: | ||
| 151 | ;; $Log: filecache.el,v $ | ||
| 152 | ;; Revision 1.13 1997/02/07 22:27:51 pbreton | ||
| 153 | ;; Keybindings use autoload cookies instead of variable | ||
| 154 | ;; | ||
| 155 | ;; Revision 1.12 1997/02/07 22:02:29 pbreton | ||
| 156 | ;; Added small changes suggested by RMS: | ||
| 157 | ;; Revamped the doc strings | ||
| 158 | ;; Added keybindings (using `file-cache-default-minibuffer-key' variable) | ||
| 159 | ;; | ||
| 160 | ;; Revision 1.11 1997/02/01 16:44:47 pbreton | ||
| 161 | ;; Changed `file-cache-directory-name' function. Instead of using a | ||
| 162 | ;; completing-read, it cycles through the directory list. | ||
| 163 | ;; | ||
| 164 | ;; Eliminated bug where file-cache-file-name was called twice per completion. | ||
| 165 | ;; | ||
| 166 | ;; Revision 1.10 1997/01/26 05:44:24 pbreton | ||
| 167 | ;; Added file-cache-delete functions | ||
| 168 | ;; Added file-cache-completions-buffer variable | ||
| 169 | ;; Added file-cache-completions-keymap variable | ||
| 170 | ;; Changed file-cache-completion-setup-function to use | ||
| 171 | ;; file-cache-completions-keymap | ||
| 172 | ;; Added file-cache-choose-completion and file-cache-mouse-choose-completion. | ||
| 173 | ;; These rely on a patch to 'simple.el' | ||
| 174 | ;; Added file-cache-debug-read-from-minibuffer function | ||
| 175 | ;; | ||
| 176 | ;; Revision 1.9 1997/01/17 17:54:24 pbreton | ||
| 177 | ;; File names are no longer case-insensitive; this was tolerable on NT but | ||
| 178 | ;; not on Unix. Instead, file-cache-minibuffer-complete checks to see if the | ||
| 179 | ;; last command was itself, and if the same string is in the minibuffer. If so, | ||
| 180 | ;; this string is used for completion. | ||
| 181 | ;; | ||
| 182 | ;; Added some functions to delete from the file-cache | ||
| 183 | ;; | ||
| 184 | ;; Completing-read of directories requires temporary binding of | ||
| 185 | ;; enable-recursive-minibuffers variable. | ||
| 186 | ;; | ||
| 187 | ;; Revision 1.8 1997/01/17 14:01:08 pbreton | ||
| 188 | ;; Changed file-cache-minibuffer-complete so that it operates in the | ||
| 189 | ;; minibuffer instead of as a recursive minibuffer call. | ||
| 190 | ;; | ||
| 191 | ;; File-cache-alist now expects a filename and a list of directories (there | ||
| 192 | ;; should be at least one). If the list has only one element, that element | ||
| 193 | ;; is used; if it has multiple directories, the user is prompted to choose | ||
| 194 | ;; one. | ||
| 195 | ;; | ||
| 196 | ;; File names in the cache are now canonicalized to lowercase, to resolve a | ||
| 197 | ;; problem which occurs when the cache has files like README and readme. | ||
| 198 | ;; | ||
| 199 | ;; Removed a lot of the extra completion functions which weren't used. | ||
| 200 | ;; | ||
| 201 | ;; Revision 1.7 1996/12/29 15:48:28 pbreton | ||
| 202 | ;; Added functions: | ||
| 203 | ;; `file-cache-minibuffer-complete-using-suffix' | ||
| 204 | ;; `file-cache-minibuffer-complete-with-directory-filter' | ||
| 205 | ;; `file-cache-minibuffer-complete-with-filename-filter' | ||
| 206 | ;; Added documentation for these functions | ||
| 207 | ;; | ||
| 208 | ;; Revision 1.6 1996/12/24 20:27:56 pbreton | ||
| 209 | ;; Added predicate functions to `file-cache-minibuffer-complete' | ||
| 210 | ;; | ||
| 211 | ;; Revision 1.5 1996/12/14 18:05:11 pbreton | ||
| 212 | ;; Fixed uniquify bug by using `member' instead of `memq' | ||
| 213 | ;; Made file-cache-add-* prompts more descriptive | ||
| 214 | ;; More documentation | ||
| 215 | ;; | ||
| 216 | ;; Revision 1.4 1996/12/13 14:42:37 pbreton | ||
| 217 | ;; Removed `file-cache-top-directory' variable | ||
| 218 | ;; Changed file-cache-initialize to file-cache-add-from-file-cache-buffer | ||
| 219 | ;; Regexp to match files in file-cache-buffer is now a variable | ||
| 220 | ;; | ||
| 221 | ;; Revision 1.3 1996/12/12 06:01:27 peter | ||
| 222 | ;; Added `file-cache-add-file' and `file-cache-add-file-list' functions | ||
| 223 | ;; | ||
| 224 | ;; Revision 1.2 1996/12/12 05:47:49 peter | ||
| 225 | ;; Fixed uniquifying bug | ||
| 226 | ;; Added directory functions | ||
| 227 | ;; `file-cache-find-file' now uses file-cache-file-name | ||
| 228 | ;; `file-cache-minibuffer-complete' handles string completion correctly. | ||
| 229 | ;; It also prepends `file-cache-minibuffer-prompt' to the normal prompt | ||
| 230 | ;; | ||
| 231 | ;; Revision 1.1 1996/11/26 12:12:43 peter | ||
| 232 | ;; Initial revision | ||
| 233 | ;; | ||
| 234 | ;;; Code: | ||
| 235 | |||
| 236 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 237 | ;; Variables | ||
| 238 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 239 | |||
| 240 | ;; User-modifiable variables | ||
| 241 | (defvar file-cache-filter-regexps | ||
| 242 | (list "~$" "\\.o$" "\\.exe$" "\\.a$" "\\.elc$" ",v$" "\\.output$" | ||
| 243 | "\\.$" "#$") | ||
| 244 | "*List of regular expressions used as filters by the file cache. | ||
| 245 | File names which match these expressions will not be added to the cache. | ||
| 246 | Note that the functions `file-cache-add-file' and `file-cache-add-file-list' | ||
| 247 | do not use this variable.") | ||
| 248 | |||
| 249 | (defvar file-cache-find-command "find" | ||
| 250 | "*External program used by `file-cache-add-directory-using-find'.") | ||
| 251 | |||
| 252 | (defvar file-cache-locate-command "locate" | ||
| 253 | "*External program used by `file-cache-add-directory-using-locate'.") | ||
| 254 | |||
| 255 | ;; Minibuffer messages | ||
| 256 | (defvar file-cache-no-match-message " [File Cache: No match]" | ||
| 257 | "Message to display when there is no completion.") | ||
| 258 | |||
| 259 | (defvar file-cache-sole-match-message " [File Cache: sole completion]" | ||
| 260 | "Message to display when there is only one completion.") | ||
| 261 | |||
| 262 | (defvar file-cache-non-unique-message " [File Cache: complete but not unique]" | ||
| 263 | "Message to display when there is a non-unique completion.") | ||
| 264 | |||
| 265 | (defvar file-cache-multiple-directory-message nil) | ||
| 266 | |||
| 267 | ;; Internal variables | ||
| 268 | ;; This should be named *Completions* because that's what the function | ||
| 269 | ;; switch-to-completions in simple.el expects | ||
| 270 | (defvar file-cache-completions-buffer "*Completions*" | ||
| 271 | "Buffer to display completions when using the file cache.") | ||
| 272 | |||
| 273 | (defvar file-cache-buffer "*File Cache*" | ||
| 274 | "Buffer to hold the cache of file names.") | ||
| 275 | |||
| 276 | (defvar file-cache-buffer-default-regexp "^.+$" | ||
| 277 | "Regexp to match files in `file-cache-buffer'.") | ||
| 278 | |||
| 279 | (defvar file-cache-last-completion nil) | ||
| 280 | |||
| 281 | (defvar file-cache-alist nil | ||
| 282 | "Internal data structure to hold cache of file names.") | ||
| 283 | |||
| 284 | (defvar file-cache-completions-keymap nil | ||
| 285 | "Keymap for file cache completions buffer.") | ||
| 286 | |||
| 287 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 288 | ;; Functions to add files to the cache | ||
| 289 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 290 | |||
| 291 | (defun file-cache-add-directory (directory &optional regexp) | ||
| 292 | "Add DIRECTORY to the file cache. | ||
| 293 | If the optional REGEXP argument is non-nil, only files which match it will | ||
| 294 | be added to the cache." | ||
| 295 | (interactive "DAdd files from directory: ") | ||
| 296 | (let* ((dir (expand-file-name directory)) | ||
| 297 | (dir-files (directory-files dir t regexp)) | ||
| 298 | ) | ||
| 299 | ;; Filter out files we don't want to see | ||
| 300 | (mapcar | ||
| 301 | '(lambda (file) | ||
| 302 | (mapcar | ||
| 303 | '(lambda (regexp) | ||
| 304 | (if (string-match regexp file) | ||
| 305 | (setq dir-files (delq file dir-files)))) | ||
| 306 | file-cache-filter-regexps)) | ||
| 307 | dir-files) | ||
| 308 | (file-cache-add-file-list dir-files))) | ||
| 309 | |||
| 310 | (defun file-cache-add-directory-list (directory-list &optional regexp) | ||
| 311 | "Add DIRECTORY-LIST (a list of directory names) to the file cache. | ||
| 312 | If the optional REGEXP argument is non-nil, only files which match it | ||
| 313 | will be added to the cache. Note that the REGEXP is applied to the files | ||
| 314 | in each directory, not to the directory list itself." | ||
| 315 | (interactive "XAdd files from directory list: ") | ||
| 316 | (mapcar | ||
| 317 | '(lambda (dir) (file-cache-add-directory dir regexp)) | ||
| 318 | directory-list)) | ||
| 319 | |||
| 320 | (defun file-cache-add-file-list (file-list) | ||
| 321 | "Add FILE-LIST (a list of files names) to the file cache." | ||
| 322 | (interactive "XFile List: ") | ||
| 323 | (mapcar 'file-cache-add-file file-list)) | ||
| 324 | |||
| 325 | ;; Workhorse function | ||
| 326 | (defun file-cache-add-file (file) | ||
| 327 | "Add FILE to the file cache." | ||
| 328 | (interactive "fAdd File: ") | ||
| 329 | (let* ((file-name (file-name-nondirectory file)) | ||
| 330 | (dir-name (file-name-directory file)) | ||
| 331 | (the-entry (assoc file-name file-cache-alist)) | ||
| 332 | ) | ||
| 333 | ;; Does the entry exist already? | ||
| 334 | (if the-entry | ||
| 335 | (if (or (and (stringp (cdr the-entry)) | ||
| 336 | (string= dir-name (cdr the-entry))) | ||
| 337 | (and (listp (cdr the-entry)) | ||
| 338 | (member dir-name (cdr the-entry)))) | ||
| 339 | nil | ||
| 340 | (setcdr the-entry (append (list dir-name) (cdr the-entry))) | ||
| 341 | ) | ||
| 342 | ;; If not, add it to the cache | ||
| 343 | (setq file-cache-alist | ||
| 344 | (cons (cons file-name (list dir-name)) | ||
| 345 | file-cache-alist))) | ||
| 346 | )) | ||
| 347 | |||
| 348 | (defun file-cache-add-directory-using-find (directory) | ||
| 349 | "Use the `find' command to add files to the file cache. | ||
| 350 | Find is run in DIRECTORY." | ||
| 351 | (interactive "DAdd files under directory: ") | ||
| 352 | (let ((dir (expand-file-name directory))) | ||
| 353 | (set-buffer (get-buffer-create file-cache-buffer)) | ||
| 354 | (erase-buffer) | ||
| 355 | (call-process file-cache-find-command nil | ||
| 356 | (get-buffer file-cache-buffer) nil | ||
| 357 | dir "-name" | ||
| 358 | (if (memq system-type | ||
| 359 | (list 'windows-nt 'ms-dos)) "'*'" "*") | ||
| 360 | "-print") | ||
| 361 | (file-cache-add-from-file-cache-buffer))) | ||
| 362 | |||
| 363 | (defun file-cache-add-directory-using-locate (string) | ||
| 364 | "Use the `locate' command to add files to the file cache. | ||
| 365 | STRING is passed as an argument to the locate command." | ||
| 366 | (interactive "sAdd files using locate string: ") | ||
| 367 | (set-buffer (get-buffer-create file-cache-buffer)) | ||
| 368 | (erase-buffer) | ||
| 369 | (call-process file-cache-locate-command nil | ||
| 370 | (get-buffer file-cache-buffer) nil | ||
| 371 | string) | ||
| 372 | (file-cache-add-from-file-cache-buffer)) | ||
| 373 | |||
| 374 | (defun file-cache-add-from-file-cache-buffer (&optional regexp) | ||
| 375 | "Add any entries found in the file cache buffer. | ||
| 376 | Each entry matches the regular expression `file-cache-buffer-default-regexp' | ||
| 377 | or the optional REGEXP argument." | ||
| 378 | (set-buffer file-cache-buffer) | ||
| 379 | (mapcar | ||
| 380 | (function (lambda (elt) | ||
| 381 | (goto-char (point-min)) | ||
| 382 | (delete-matching-lines elt))) | ||
| 383 | file-cache-filter-regexps) | ||
| 384 | (goto-char (point-min)) | ||
| 385 | (let ((full-filename)) | ||
| 386 | (while (re-search-forward | ||
| 387 | (or regexp file-cache-buffer-default-regexp) | ||
| 388 | (point-max) t) | ||
| 389 | (setq full-filename (buffer-substring-no-properties | ||
| 390 | (match-beginning 0) (match-end 0))) | ||
| 391 | (file-cache-add-file full-filename)))) | ||
| 392 | |||
| 393 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 394 | ;; Functions to delete from the cache | ||
| 395 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 396 | |||
| 397 | (defun file-cache-clear-cache () | ||
| 398 | "Clear the file cache." | ||
| 399 | (interactive) | ||
| 400 | (setq file-cache-alist nil)) | ||
| 401 | |||
| 402 | ;; This clears *all* files with the given name | ||
| 403 | (defun file-cache-delete-file (file) | ||
| 404 | "Delete FILE from the file cache." | ||
| 405 | (interactive | ||
| 406 | (list (completing-read "Delete file from cache: " file-cache-alist))) | ||
| 407 | (setq file-cache-alist | ||
| 408 | (delq (assoc file file-cache-alist) file-cache-alist))) | ||
| 409 | |||
| 410 | (defun file-cache-delete-file-list (file-list) | ||
| 411 | "Delete FILE-LIST (a list of files) from the file cache." | ||
| 412 | (interactive "XFile List: ") | ||
| 413 | (mapcar 'file-cache-delete-file file-list)) | ||
| 414 | |||
| 415 | (defun file-cache-delete-file-regexp (regexp) | ||
| 416 | "Delete files matching REGEXP from the file cache." | ||
| 417 | (interactive "sRegexp: ") | ||
| 418 | (let ((delete-list)) | ||
| 419 | (mapcar '(lambda (elt) | ||
| 420 | (and (string-match regexp (car elt)) | ||
| 421 | (setq delete-list (cons (car elt) delete-list)))) | ||
| 422 | file-cache-alist) | ||
| 423 | (file-cache-delete-file-list delete-list) | ||
| 424 | (message "Deleted %d files from file cache" (length delete-list)))) | ||
| 425 | |||
| 426 | (defun file-cache-delete-directory (directory) | ||
| 427 | "Delete DIRECTORY from the file cache." | ||
| 428 | (interactive "DDelete directory from file cache: ") | ||
| 429 | (let ((dir (expand-file-name directory)) | ||
| 430 | (result 0)) | ||
| 431 | (mapcar | ||
| 432 | '(lambda (entry) | ||
| 433 | (if (file-cache-do-delete-directory dir entry) | ||
| 434 | (setq result (1+ result)))) | ||
| 435 | file-cache-alist) | ||
| 436 | (if (zerop result) | ||
| 437 | (error "No entries containing %s found in cache" directory) | ||
| 438 | (message "Deleted %d entries" result)))) | ||
| 439 | |||
| 440 | (defun file-cache-do-delete-directory (dir entry) | ||
| 441 | (let ((directory-list (cdr entry)) | ||
| 442 | (directory (file-cache-canonical-directory dir)) | ||
| 443 | ) | ||
| 444 | (and (member directory directory-list) | ||
| 445 | (if (equal 1 (length directory-list)) | ||
| 446 | (setq file-cache-alist | ||
| 447 | (delq entry file-cache-alist)) | ||
| 448 | (setcdr entry (delete directory directory-list))) | ||
| 449 | ) | ||
| 450 | )) | ||
| 451 | |||
| 452 | (defun file-cache-delete-directory-list (directory-list) | ||
| 453 | "Delete DIRECTORY-LIST (a list of directories) from the file cache." | ||
| 454 | (interactive "XDirectory List: ") | ||
| 455 | (mapcar 'file-cache-delete-directory directory-list)) | ||
| 456 | |||
| 457 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 458 | ;; Utility functions | ||
| 459 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 460 | |||
| 461 | ;; Returns the name of a directory for a file in the cache | ||
| 462 | (defun file-cache-directory-name (file) | ||
| 463 | (let* ((directory-list (cdr (assoc file file-cache-alist))) | ||
| 464 | (len (length directory-list)) | ||
| 465 | (directory) | ||
| 466 | (num) | ||
| 467 | ) | ||
| 468 | (if (not (listp directory-list)) | ||
| 469 | (error "Unknown type in file-cache-alist for key %s" file)) | ||
| 470 | (cond | ||
| 471 | ;; Single element | ||
| 472 | ((eq 1 len) | ||
| 473 | (setq directory (elt directory-list 0))) | ||
| 474 | ;; No elements | ||
| 475 | ((eq 0 len) | ||
| 476 | (error "No directory found for key %s" file)) | ||
| 477 | ;; Multiple elements | ||
| 478 | (t | ||
| 479 | (let* ((minibuffer-dir (file-name-directory (buffer-string))) | ||
| 480 | (dir-list (member minibuffer-dir directory-list)) | ||
| 481 | ) | ||
| 482 | (setq directory | ||
| 483 | ;; If the directory is in the list, return the next element | ||
| 484 | ;; Otherwise, return the first element | ||
| 485 | (if dir-list | ||
| 486 | (or (elt directory-list | ||
| 487 | (setq num (1+ (- len (length dir-list))))) | ||
| 488 | (elt directory-list (setq num 0))) | ||
| 489 | (elt directory-list (setq num 0)))) | ||
| 490 | ) | ||
| 491 | ) | ||
| 492 | ) | ||
| 493 | ;; If there were multiple directories, set up a minibuffer message | ||
| 494 | (setq file-cache-multiple-directory-message | ||
| 495 | (and num (format " [%d of %d]" (1+ num) len))) | ||
| 496 | directory)) | ||
| 497 | |||
| 498 | ;; Returns the name of a file in the cache | ||
| 499 | (defun file-cache-file-name (file) | ||
| 500 | (let ((directory (file-cache-directory-name file))) | ||
| 501 | (concat directory file))) | ||
| 502 | |||
| 503 | ;; Return a canonical directory for comparison purposes. | ||
| 504 | ;; Such a directory ends with a forward slash. | ||
| 505 | (defun file-cache-canonical-directory (dir) | ||
| 506 | (let ((directory dir)) | ||
| 507 | (if (not (char-equal ?/ (string-to-char (substring directory -1)))) | ||
| 508 | (concat directory "/") | ||
| 509 | directory))) | ||
| 510 | |||
| 511 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 512 | ;; Minibuffer functions | ||
| 513 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 514 | |||
| 515 | ;;;###autoload | ||
| 516 | (defun file-cache-minibuffer-complete () | ||
| 517 | "Complete a filename in the minibuffer using a preloaded cache." | ||
| 518 | (interactive) | ||
| 519 | (let* | ||
| 520 | ( | ||
| 521 | (completion-ignore-case nil) | ||
| 522 | (case-fold-search nil) | ||
| 523 | (string (file-name-nondirectory (buffer-string))) | ||
| 524 | (completion-string (try-completion string file-cache-alist)) | ||
| 525 | (completion-list) | ||
| 526 | (len) | ||
| 527 | (file-cache-string) | ||
| 528 | ) | ||
| 529 | (cond | ||
| 530 | ;; If it's the longest match, insert it | ||
| 531 | ((stringp completion-string) | ||
| 532 | ;; If we've already inserted a unique string, see if the user | ||
| 533 | ;; wants to use that one | ||
| 534 | (if (and (string= string completion-string) | ||
| 535 | (assoc string file-cache-alist)) | ||
| 536 | (if (and (eq last-command this-command) | ||
| 537 | (string= file-cache-last-completion completion-string)) | ||
| 538 | (progn | ||
| 539 | (erase-buffer) | ||
| 540 | (insert-string (file-cache-file-name completion-string)) | ||
| 541 | (setq file-cache-last-completion nil) | ||
| 542 | ) | ||
| 543 | (file-cache-temp-minibuffer-message file-cache-non-unique-message) | ||
| 544 | (setq file-cache-last-completion string) | ||
| 545 | ) | ||
| 546 | (setq file-cache-last-completion string) | ||
| 547 | (setq completion-list (all-completions string file-cache-alist) | ||
| 548 | len (length completion-list)) | ||
| 549 | (if (> len 1) | ||
| 550 | (progn | ||
| 551 | (goto-char (point-max)) | ||
| 552 | (insert-string | ||
| 553 | (substring completion-string (length string))) | ||
| 554 | ;; Add our own setup function to the Completions Buffer | ||
| 555 | (let ((completion-setup-hook | ||
| 556 | (reverse | ||
| 557 | (append (list 'file-cache-completion-setup-function) | ||
| 558 | completion-setup-hook))) | ||
| 559 | ) | ||
| 560 | (with-output-to-temp-buffer file-cache-completions-buffer | ||
| 561 | (display-completion-list completion-list)) | ||
| 562 | ) | ||
| 563 | ) | ||
| 564 | (setq file-cache-string (file-cache-file-name completion-string)) | ||
| 565 | (if (string= file-cache-string (buffer-string)) | ||
| 566 | (file-cache-temp-minibuffer-message file-cache-sole-match-message) | ||
| 567 | (erase-buffer) | ||
| 568 | (insert-string file-cache-string) | ||
| 569 | (if file-cache-multiple-directory-message | ||
| 570 | (file-cache-temp-minibuffer-message | ||
| 571 | file-cache-multiple-directory-message))) | ||
| 572 | ))) | ||
| 573 | |||
| 574 | ;; If it's the only match, replace the original contents | ||
| 575 | ((eq completion-string t) | ||
| 576 | (setq file-cache-string (file-cache-file-name string)) | ||
| 577 | (if (string= file-cache-string (buffer-string)) | ||
| 578 | (file-cache-temp-minibuffer-message file-cache-sole-match-message) | ||
| 579 | (erase-buffer) | ||
| 580 | (insert-string file-cache-string) | ||
| 581 | (if file-cache-multiple-directory-message | ||
| 582 | (file-cache-temp-minibuffer-message | ||
| 583 | file-cache-multiple-directory-message)) | ||
| 584 | )) | ||
| 585 | |||
| 586 | ;; No match | ||
| 587 | ((eq completion-string nil) | ||
| 588 | (file-cache-temp-minibuffer-message file-cache-no-match-message)) | ||
| 589 | ) | ||
| 590 | )) | ||
| 591 | |||
| 592 | ;; Lifted from "complete.el" | ||
| 593 | (defun file-cache-temp-minibuffer-message (msg) | ||
| 594 | "A Lisp version of `temp_minibuffer_message' from minibuf.c." | ||
| 595 | (let ((savemax (point-max))) | ||
| 596 | (save-excursion | ||
| 597 | (goto-char (point-max)) | ||
| 598 | (insert msg)) | ||
| 599 | (let ((inhibit-quit t)) | ||
| 600 | (sit-for 2) | ||
| 601 | (delete-region savemax (point-max)) | ||
| 602 | (if quit-flag | ||
| 603 | (setq quit-flag nil | ||
| 604 | unread-command-events (list 7)))))) | ||
| 605 | |||
| 606 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 607 | ;; Completion functions | ||
| 608 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 609 | |||
| 610 | (defun file-cache-completion-setup-function () | ||
| 611 | (set-buffer file-cache-completions-buffer) | ||
| 612 | |||
| 613 | (if file-cache-completions-keymap | ||
| 614 | nil | ||
| 615 | (setq file-cache-completions-keymap | ||
| 616 | (copy-keymap completion-list-mode-map)) | ||
| 617 | (define-key file-cache-completions-keymap [mouse-2] | ||
| 618 | 'file-cache-mouse-choose-completion) | ||
| 619 | (define-key file-cache-completions-keymap "\C-m" | ||
| 620 | 'file-cache-choose-completion)) | ||
| 621 | |||
| 622 | (use-local-map file-cache-completions-keymap) | ||
| 623 | ) | ||
| 624 | |||
| 625 | (defun file-cache-choose-completion () | ||
| 626 | "Choose a completion in the `*Completions*' buffer." | ||
| 627 | (interactive) | ||
| 628 | (let ((completion-no-auto-exit t)) | ||
| 629 | (choose-completion) | ||
| 630 | (select-window (active-minibuffer-window)) | ||
| 631 | (file-cache-minibuffer-complete) | ||
| 632 | ) | ||
| 633 | ) | ||
| 634 | |||
| 635 | (defun file-cache-mouse-choose-completion (event) | ||
| 636 | "Choose a completion with the mouse." | ||
| 637 | (interactive "e") | ||
| 638 | (let ((completion-no-auto-exit t)) | ||
| 639 | (mouse-choose-completion event) | ||
| 640 | (select-window (active-minibuffer-window)) | ||
| 641 | (file-cache-minibuffer-complete) | ||
| 642 | ) | ||
| 643 | ) | ||
| 644 | |||
| 645 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 646 | ;; Debugging functions | ||
| 647 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 648 | |||
| 649 | (defun file-cache-debug-read-from-minibuffer (file) | ||
| 650 | "Debugging function." | ||
| 651 | (interactive | ||
| 652 | (list (completing-read "File Cache: " file-cache-alist))) | ||
| 653 | (message "%s" (assoc file file-cache-alist)) | ||
| 654 | ) | ||
| 655 | |||
| 656 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 657 | ;; Keybindings | ||
| 658 | ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | ||
| 659 | |||
| 660 | ;;;###autoload (define-key minibuffer-local-completion-map [C-tab] 'file-cache-minibuffer-complete) | ||
| 661 | ;;;###autoload (define-key minibuffer-local-map [C-tab] 'file-cache-minibuffer-complete) | ||
| 662 | ;;;###autoload (define-key minibuffer-local-must-match-map [C-tab] 'file-cache-minibuffer-complete) | ||
| 663 | |||
| 664 | (provide 'filecache) | ||
| 665 | |||
| 666 | ;;; filecache.el ends here | ||
diff --git a/lisp/progmodes/meta-mode.el b/lisp/progmodes/meta-mode.el new file mode 100644 index 00000000000..b615862cc52 --- /dev/null +++ b/lisp/progmodes/meta-mode.el | |||
| @@ -0,0 +1,1099 @@ | |||
| 1 | ;;; meta-mode.el --- major mode for editing Metafont or MetaPost sources. | ||
| 2 | |||
| 3 | ;; Copyright (C) 1997 by Ulrik Vieth. | ||
| 4 | |||
| 5 | ;; Author: Ulrik Vieth <vieth@thphy.uni-duesseldorf.de> | ||
| 6 | ;; Version: 1.0 | ||
| 7 | ;; Keywords: Metafont, MetaPost, tex, languages | ||
| 8 | |||
| 9 | ;;; This file is *not* part of GNU Emacs. | ||
| 10 | |||
| 11 | ;; This program is free software; you can redistribute it and/or modify | ||
| 12 | ;; it under the terms of the GNU General Public License as published by | ||
| 13 | ;; the Free Software Foundation; either version 2, or (at your option) | ||
| 14 | ;; any later version. | ||
| 15 | |||
| 16 | ;; This program is distributed in the hope that it will be useful, | ||
| 17 | ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 18 | ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 19 | ;; GNU General Public License for more details. | ||
| 20 | |||
| 21 | ;; You should have received a copy of the GNU General Public License | ||
| 22 | ;; along with GNU Emacs; see the file COPYING. If not, write to the | ||
| 23 | ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330, | ||
| 24 | ;; Boston, MA 02111-1307, USA. | ||
| 25 | |||
| 26 | ;;; Commentary: | ||
| 27 | |||
| 28 | ;; Description: | ||
| 29 | ;; | ||
| 30 | ;; This Emacs Lisp package provides a major mode for editing Metafont | ||
| 31 | ;; or MetaPost sources. It includes all the necessary code to set up | ||
| 32 | ;; a major mode including an approriate syntax table, keymap, and a | ||
| 33 | ;; mode-specific pull-down menu. It also provides a sophisticated set | ||
| 34 | ;; of font-lock patterns, a fancy indentation function adapted from | ||
| 35 | ;; AUC-TeX's latex.el, and some basic mode-specific editing functions | ||
| 36 | ;; such as functions to move to the beginning or end of the enclosing | ||
| 37 | ;; environment, or to mark, re-indent, or comment-out environments. | ||
| 38 | ;; On the other hand, it doesn't yet provide any functionality for | ||
| 39 | ;; running Metafont or MetaPost in a shell buffer form within Emacs, | ||
| 40 | ;; but such functionality might be added later, either as part of this | ||
| 41 | ;; package or as a separate Emacs Lisp package. | ||
| 42 | |||
| 43 | ;; Installation: | ||
| 44 | ;; | ||
| 45 | ;; Install this file (meta-mode.el) in your personal or system-wide | ||
| 46 | ;; Emacs Lisp directory and add these lines to your startup files: | ||
| 47 | ;; | ||
| 48 | ;; (autoload 'metafont-mode "meta-mode" "Metafont editing mode." t) | ||
| 49 | ;; (autoload 'metapost-mode "meta-mode" "MetaPost editing mode." t) | ||
| 50 | ;; | ||
| 51 | ;; (setq auto-mode-alist | ||
| 52 | ;; (append '(("\\.mf\\'" . metafont-mode) | ||
| 53 | ;; ("\\.mp\\'" . metapost-mode)) auto-mode-alist)) | ||
| 54 | ;; | ||
| 55 | ;; An interface to running Metafont or MetaPost as a shell process | ||
| 56 | ;; from within Emacs is currently under development as a separate | ||
| 57 | ;; Emacs Lisp package (meta-buf.el). In order to have that package | ||
| 58 | ;; loaded automatically when first entering Metafont or MetaPost mode, | ||
| 59 | ;; you might use the load-hook provided in this package by adding | ||
| 60 | ;; these lines to your startup file: | ||
| 61 | ;; | ||
| 62 | ;; (add-hook 'meta-mode-load-hook | ||
| 63 | ;; '(lambda () (require 'meta-buf))) | ||
| 64 | ;; | ||
| 65 | ;; The add-on package loaded this way may in turn make use of the | ||
| 66 | ;; mode-hooks provided in this package to activate additional features | ||
| 67 | ;; when entering Metafont or MetaPost mode. | ||
| 68 | |||
| 69 | ;; Font Lock Support: | ||
| 70 | ;; | ||
| 71 | ;; If you are using global-font-lock-mode (introduced in Emacs 19.31), | ||
| 72 | ;; fontification in Metafont and/or MetaPost mode will be activated | ||
| 73 | ;; automatically. To speed up fontification for the rather complex | ||
| 74 | ;; patterns used in these modes, it may be a good idea to activate | ||
| 75 | ;; lazy-lock as a font-lock-support-mode (introduced in Emacs 19.32) | ||
| 76 | ;; by adding these lines to your startup file: | ||
| 77 | ;; | ||
| 78 | ;; (global-font-lock-mode t) | ||
| 79 | ;; (setq font-lock-support-mode 'lazy-lock-mode) | ||
| 80 | ;; | ||
| 81 | ;; If you are using an older version of Emacs, which doesn't provide | ||
| 82 | ;; global-font-lock-mode or font-lock-support-mode, you can also | ||
| 83 | ;; activate fontification in Metafont and/or MetaPost mode by adding | ||
| 84 | ;; the following lines to your startup file: | ||
| 85 | ;; | ||
| 86 | ;; (add-hook 'meta-common-mode-hook 'turn-on-font-lock) | ||
| 87 | ;; (add-hook 'meta-common-mode-hook 'turn-on-lazy-lock) | ||
| 88 | |||
| 89 | ;; Customization: | ||
| 90 | ;; | ||
| 91 | ;; Following the usual Emacs Lisp coding conventions, the major modes | ||
| 92 | ;; defined in this package provide several hook variables to allow for | ||
| 93 | ;; local customization when entering the modes. In particular, there | ||
| 94 | ;; is a `meta-common-mode-hook' which applies to both modes as well as | ||
| 95 | ;; `metafont-mode-hook' and `metapost-mode-hook' which apply to the | ||
| 96 | ;; individual modes. In addition, there are several variables and | ||
| 97 | ;; regexps controlling e.g. the behavior of the indentation function, | ||
| 98 | ;; which may be customized via `edit-options'. Please refer to the | ||
| 99 | ;; docstrings in the code below for details. | ||
| 100 | |||
| 101 | ;; Availability: | ||
| 102 | ;; | ||
| 103 | ;; This package is currently available via my "TeX Software" WWW page: | ||
| 104 | ;; | ||
| 105 | ;; http://www.thphy.uni-duesseldorf.de/~vieth/subjects/tex/software.html | ||
| 106 | ;; | ||
| 107 | ;; As of this version 1.0, this package will be uploaded to CTAN | ||
| 108 | ;; archives, where it shall find a permanent home, presumably in | ||
| 109 | ;; tex-archive/support/emacs-modes. It will also be submitted for | ||
| 110 | ;; integration into the GNU Emacs distribution at that time. | ||
| 111 | ;; | ||
| 112 | ;; History: | ||
| 113 | ;; | ||
| 114 | ;; v 0.0 -- 1997/02/01 UV Started writing meta-mode.el. | ||
| 115 | ;; v 0.1 -- 1997/02/02 UV Added preliminary set of font-lock patterns. | ||
| 116 | ;; v 0.2 -- 1997/02/03 UV Improved and debugged font-lock patterns. | ||
| 117 | ;; Added indent-line-function for TAB. | ||
| 118 | ;; v 0.3 -- 1997/02/17 UV Improved font-lock patterns and syntax table. | ||
| 119 | ;; Improved and debbuged indentation function. | ||
| 120 | ;; v 0.4 -- 1997/02/18 UV Added functions to indent regions for M-C-q, | ||
| 121 | ;; also added a preliminary mode-specific menu. | ||
| 122 | ;; v 0.5 -- 1997/02/19 UV Added functions to skip to next or previous | ||
| 123 | ;; defun and to re-indent or comment-out defuns. | ||
| 124 | ;; v 0.6 -- 1997/02/20 UV More debugging, testing and clean-up. | ||
| 125 | ;; v 0.7 -- 1997/02/22 UV Use easymenu to define mode-specific menu. | ||
| 126 | ;; v 0.8 -- 1997/02/24 UV Added completion function for M-TAB. | ||
| 127 | ;; v 0.9 -- 1997/03/08 UV Added fill-paragraph function for comments. | ||
| 128 | ;; Also fixed a few remaining font-lock problems. | ||
| 129 | ;; Added meta-mode-load-hook to load meta-buf.el. | ||
| 130 | ;; v 1.0 -- 1997/04/07 UV Cleanup for official public release. | ||
| 131 | ;; | ||
| 132 | ;; Historical Footnote: | ||
| 133 | ;; | ||
| 134 | ;; This package was begun on February 1, 1997, exactly 20 years after | ||
| 135 | ;; the genesis of TeX took place according to Don Knuth's own account | ||
| 136 | ;; (cf. ``The Errors of TeX'', reprinted in ``Literate Programming'', | ||
| 137 | ;; Chapter 10, p. 249). What better date could there be to choose? | ||
| 138 | ;; | ||
| 139 | |||
| 140 | |||
| 141 | ;;; Code: | ||
| 142 | |||
| 143 | (require 'easymenu) | ||
| 144 | |||
| 145 | ;;; Fontification. | ||
| 146 | |||
| 147 | (defvar meta-font-lock-keywords | ||
| 148 | (let ((input-keywords | ||
| 149 | "\\(input\\|generate\\)") | ||
| 150 | (begin-keywords | ||
| 151 | (concat "\\(begin\\(char\\|fig\\|graph\\|logochar\\)\\|" | ||
| 152 | "\\cmchar\\|dcchar\\|ecchar\\)")) | ||
| 153 | (end-keywords | ||
| 154 | "\\(end\\(char\\|fig\\|graph\\)\\)") | ||
| 155 | (macro-keywords-1 | ||
| 156 | "\\(def\\|let\\|mode_def\\|vardef\\)") | ||
| 157 | (macro-keywords-2 | ||
| 158 | "\\(primarydef\\|secondarydef\\|tertiarydef\\)") | ||
| 159 | ;(make-regexp | ||
| 160 | ; '("expr" "suffix" "text" "primary" "secondary" "tertiary") t) | ||
| 161 | (args-keywords | ||
| 162 | (concat "\\(expr\\|primary\\|s\\(econdary\\|uffix\\)\\|" | ||
| 163 | "te\\(rtiary\\|xt\\)\\)")) | ||
| 164 | ;(make-regexp | ||
| 165 | ; '("boolean" "color" "numeric" "pair" "path" "pen" "picture" | ||
| 166 | ; "string" "transform" "newinternal") t) | ||
| 167 | (type-keywords | ||
| 168 | (concat "\\(boolean\\|color\\|n\\(ewinternal\\|umeric\\)\\|" | ||
| 169 | "p\\(a\\(ir\\|th\\)\\|en\\|icture\\)\\|string\\|" | ||
| 170 | "transform\\)")) | ||
| 171 | ;(make-regexp | ||
| 172 | ; '("for" "forever" "forsuffixes" "endfor" | ||
| 173 | ; "step" "until" "upto" "downto" "thru" "within" | ||
| 174 | ; "iff" "if" "elseif" "else" "fi" "exitif" "exitunless" | ||
| 175 | ; "let" "def" "vardef" "enddef" "mode_def" | ||
| 176 | ; "true" "false" "known" "unknown" "and" "or" "not" | ||
| 177 | ; "save" "interim" "inner" "outer" "relax" | ||
| 178 | ; "begingroup" "endgroup" "expandafter" "scantokens" | ||
| 179 | ; "generate" "input" "endinput" "end" "bye" | ||
| 180 | ; "message" "errmessage" "errhelp" "special" "numspecial" | ||
| 181 | ; "readstring" "readfrom" "write") t) | ||
| 182 | (syntactic-keywords | ||
| 183 | (concat "\\(and\\|b\\(egingroup\\|ye\\)\\|" | ||
| 184 | "d\\(ef\\|ownto\\)\\|e\\(lse\\(\\|if\\)" | ||
| 185 | "\\|nd\\(\\|def\\|for\\|group\\|input\\)" | ||
| 186 | "\\|rr\\(help\\|message\\)" | ||
| 187 | "\\|x\\(it\\(if\\|unless\\)\\|pandafter\\)\\)\\|" | ||
| 188 | "f\\(alse\\|i\\|or\\(\\|ever\\|suffixes\\)\\)\\|" | ||
| 189 | "generate\\|i\\(ff?\\|n\\(ner\\|put\\|terim\\)\\)\\|" | ||
| 190 | "known\\|let\\|m\\(essage\\|ode_def\\)\\|" | ||
| 191 | "n\\(ot\\|umspecial\\)\\|o\\(r\\|uter\\)\\|" | ||
| 192 | "re\\(ad\\(from\\|string\\)\\|lax\\)\\|" | ||
| 193 | "s\\(ave\\|cantokens\\|pecial\\|tep\\)\\|" | ||
| 194 | "t\\(hru\\|rue\\)\\|" | ||
| 195 | "u\\(n\\(known\\|til\\)\\|pto\\)\\|" | ||
| 196 | "vardef\\|w\\(ithin\\|rite\\)\\)")) | ||
| 197 | ) | ||
| 198 | (list | ||
| 199 | ;; embedded TeX code in btex ... etex | ||
| 200 | (cons (concat "\\(btex\\|verbatimtex\\)" | ||
| 201 | "[ \t]+\\(.*\\)[ \t]+" | ||
| 202 | "\\(etex\\)") | ||
| 203 | '((1 font-lock-keyword-face) | ||
| 204 | (2 font-lock-string-face) | ||
| 205 | (3 font-lock-keyword-face))) | ||
| 206 | ;; unary macro definitions: def, vardef, let | ||
| 207 | (cons (concat "\\<" macro-keywords-1 "\\>" | ||
| 208 | "[ \t]+\\(\\sw+\\|\\s_+\\|\\s.+\\)") | ||
| 209 | '((1 font-lock-keyword-face) | ||
| 210 | (2 font-lock-function-name-face))) | ||
| 211 | ;; binary macro defintions: <leveldef> x operator y | ||
| 212 | (cons (concat "\\<" macro-keywords-2 "\\>" | ||
| 213 | "[ \t]+\\(\\sw+\\)" | ||
| 214 | "[ \t]*\\(\\sw+\\|\\s.+\\)" | ||
| 215 | "[ \t]*\\(\\sw+\\)") | ||
| 216 | '((1 font-lock-keyword-face) | ||
| 217 | (2 font-lock-variable-name-face nil t) | ||
| 218 | (3 font-lock-function-name-face nil t) | ||
| 219 | (4 font-lock-variable-name-face nil t))) | ||
| 220 | ;; variable declarations: numeric, pair, color, ... | ||
| 221 | (cons (concat "\\<" type-keywords "\\>" | ||
| 222 | "\\([ \t]+\\(\\sw+\\)\\)*") | ||
| 223 | '((1 font-lock-type-face) | ||
| 224 | (font-lock-match-meta-declaration-item-and-skip-to-next | ||
| 225 | (goto-char (match-end 1)) nil | ||
| 226 | (1 font-lock-variable-name-face nil t)))) | ||
| 227 | ;; argument declarations: expr, suffix, text, ... | ||
| 228 | (cons (concat "\\<" args-keywords "\\>" | ||
| 229 | "\\([ \t]+\\(\\sw+\\|\\s_+\\)\\)*") | ||
| 230 | '((1 font-lock-type-face) | ||
| 231 | (font-lock-match-meta-declaration-item-and-skip-to-next | ||
| 232 | (goto-char (match-end 1)) nil | ||
| 233 | (1 font-lock-variable-name-face nil t)))) | ||
| 234 | ;; special case of arguments: expr x of y | ||
| 235 | (cons (concat "\\(expr\\)[ \t]+\\(\\sw+\\)" | ||
| 236 | "[ \t]+\\(of\\)[ \t]+\\(\\sw+\\)") | ||
| 237 | '((1 font-lock-type-face) | ||
| 238 | (2 font-lock-variable-name-face) | ||
| 239 | (3 font-lock-keyword-face nil t) | ||
| 240 | (4 font-lock-variable-name-face nil t))) | ||
| 241 | ;; syntactic keywords | ||
| 242 | (cons (concat "\\<" syntactic-keywords "\\>") | ||
| 243 | 'font-lock-keyword-face) | ||
| 244 | ;; beginchar, beginfig | ||
| 245 | (cons (concat "\\<" begin-keywords "\\>") | ||
| 246 | 'font-lock-keyword-face) | ||
| 247 | ;; endchar, endfig | ||
| 248 | (cons (concat "\\<" end-keywords "\\>") | ||
| 249 | 'font-lock-keyword-face) | ||
| 250 | ;; input, generate | ||
| 251 | (cons (concat "\\<" input-keywords "\\>" | ||
| 252 | "[ \t]+\\(\\sw+\\)") | ||
| 253 | '((1 font-lock-keyword-face) | ||
| 254 | (2 font-lock-reference-face))) | ||
| 255 | ;; embedded Metafont/MetaPost code in comments | ||
| 256 | (cons "|\\([^|]+\\)|" | ||
| 257 | '(1 font-lock-reference-face t)) | ||
| 258 | )) | ||
| 259 | "Default expressions to highlight in Metafont or MetaPost mode.") | ||
| 260 | |||
| 261 | |||
| 262 | (defun font-lock-match-meta-declaration-item-and-skip-to-next (limit) | ||
| 263 | ;; Match and move over Metafont/MetaPost declaration item after point. | ||
| 264 | ;; | ||
| 265 | ;; The expected syntax of an item is either "word" or "symbol", | ||
| 266 | ;; possibly ending with optional whitespace. Everything following | ||
| 267 | ;; the item (but belonging to it) is expected to by skipable by | ||
| 268 | ;; `forward-sexp'. The list of items is expected to be separated | ||
| 269 | ;; by commas and terminated by semicolons or equals signs. | ||
| 270 | ;; | ||
| 271 | (if (looking-at "[ \t]*\\(\\sw+\\|\\s_+\\)") | ||
| 272 | (save-match-data | ||
| 273 | (condition-case nil | ||
| 274 | (save-restriction | ||
| 275 | ;; Restrict to end of line, currently guaranteed to be LIMIT. | ||
| 276 | (narrow-to-region (point-min) limit) | ||
| 277 | (goto-char (match-end 1)) | ||
| 278 | ;; Move over any item value, etc., to the next item. | ||
| 279 | (while (not (looking-at "[ \t]*\\(\\(,\\)\\|;\\|=\\|$\\)")) | ||
| 280 | (goto-char (or (scan-sexps (point) 1) (point-max)))) | ||
| 281 | (goto-char (match-end 2))) | ||
| 282 | (error t))))) | ||
| 283 | |||
| 284 | |||
| 285 | |||
| 286 | ;;; Completion. | ||
| 287 | |||
| 288 | ;; The data used to prepare the following lists of primitives and | ||
| 289 | ;; standard macros available in Metafont or MetaPost was extracted | ||
| 290 | ;; from the original sources like this: | ||
| 291 | ;; | ||
| 292 | ;; grep '^primitive' texk-7.0/web2c/{mf,mp}.web |\ | ||
| 293 | ;; sed 's/primitive(\("[a-zA-Z]*"\).*/\1/' > {mf,mp}_prim.list | ||
| 294 | ;; | ||
| 295 | ;; grep '\(let\|def\|vardef\|primarydef\|secondarydef\|tertiarydef\)' | ||
| 296 | ;; texmf/meta{font,post}/plain.{mf,mp} > {mf,mp}_plain.list | ||
| 297 | |||
| 298 | (defconst meta-common-primitives-list | ||
| 299 | '("ASCII" "addto" "also" "and" "angle" "atleast" "batchmode" | ||
| 300 | "begingroup" "boolean" "boundarychar" "char" "charcode" "chardp" | ||
| 301 | "charexists" "charext" "charht" "charic" "charlist" "charwd" | ||
| 302 | "contour" "controls" "cosd" "curl" "cycle" "day" "decimal" "def" | ||
| 303 | "delimiters" "designsize" "directiontime" "doublepath" "dump" "else" | ||
| 304 | "elseif" "end" "enddef" "endfor" "endgroup" "endinput" "errhelp" | ||
| 305 | "errmessage" "errorstopmode" "everyjob" "exitif" "expandafter" | ||
| 306 | "expr" "extensible" "false" "fi" "floor" "fontdimen" "fontmaking" | ||
| 307 | "for" "forever" "forsuffixes" "headerbyte" "hex" "if" "inner" | ||
| 308 | "input" "interim" "intersectiontimes" "jobname" "kern" "known" | ||
| 309 | "length" "let" "ligtable" "makepath" "makepen" "message" "mexp" | ||
| 310 | "mlog" "month" "newinternal" "nonstopmode" "normaldeviate" "not" | ||
| 311 | "nullpen" "nullpicture" "numeric" "oct" "odd" "of" "or" "outer" | ||
| 312 | "pair" "path" "pausing" "pen" "pencircle" "penoffset" "picture" | ||
| 313 | "point" "postcontrol" "precontrol" "primary" "primarydef" "quote" | ||
| 314 | "randomseed" "readstring" "reverse" "rotated" "save" "scaled" | ||
| 315 | "scantokens" "scrollmode" "secondary" "secondarydef" "shifted" | ||
| 316 | "shipout" "show" "showdependencies" "showstats" "showstopping" | ||
| 317 | "showtoken" "showvariable" "sind" "skipto" "slanted" "special" | ||
| 318 | "sqrt" "step" "str" "string" "subpath" "substring" "suffix" | ||
| 319 | "tension" "tertiary" "tertiarydef" "text" "time" "to" | ||
| 320 | "tracingcapsules" "tracingchoices" "tracingcommands" | ||
| 321 | "tracingequations" "tracingmacros" "tracingonline" "tracingoutput" | ||
| 322 | "tracingrestores" "tracingspecs" "tracingstats" "tracingtitles" | ||
| 323 | "transform" "transformed" "true" "turningnumber" "uniformdeviate" | ||
| 324 | "unknown" "until" "vardef" "warningcheck" "withpen" "xpart" | ||
| 325 | "xscaled" "xxpart" "xypart" "year" "ypart" "yscaled" "yxpart" | ||
| 326 | "yypart" "zscaled") | ||
| 327 | "List of primitives common to Metafont and MetaPost.") | ||
| 328 | |||
| 329 | (defconst metafont-primitives-list | ||
| 330 | '("at" "autorounding" "chardx" "chardy" "cull" "display" | ||
| 331 | "dropping" "fillin" "from" "granularity" "hppp" "inwindow" | ||
| 332 | "keeping" "numspecial" "openwindow" "proofing" "smoothing" | ||
| 333 | "totalweight" "tracingedges" "tracingpens" "turningcheck" "vppp" | ||
| 334 | "withweight" "xoffset" "yoffset") | ||
| 335 | "List of primitives only defined in Metafont.") | ||
| 336 | |||
| 337 | (defconst metapost-primitives-list | ||
| 338 | '("arclength" "arctime" "bluepart" "bounded" "btex" "clip" | ||
| 339 | "clipped" "color" "dashed" "dashpart" "etex" "filled" "fontpart" | ||
| 340 | "fontsize" "greenpart" "infont" "linecap" "linejoin" "llcorner" | ||
| 341 | "lrcorner" "miterlimit" "mpxbreak" "pathpart" "penpart" | ||
| 342 | "prologues" "readfrom" "redpart" "setbounds" "stroked" "textpart" | ||
| 343 | "textual" "tracinglostchars" "truecorners" "ulcorner" "urcorner" | ||
| 344 | "verbatimtex" "withcolor" "within" "write") | ||
| 345 | "List of primitives only defined in MetaPost.") | ||
| 346 | |||
| 347 | (defconst meta-common-plain-macros-list | ||
| 348 | '( "abs" "bot" "bye" "byte" "ceiling" "clear_pen_memory" | ||
| 349 | "clearit" "clearpen" "clearxy" "counterclockwise" "cutdraw" "decr" | ||
| 350 | "dir" "direction" "directionpoint" "div" "dotprod" "downto" "draw" | ||
| 351 | "drawdot" "erase" "exitunless" "fill" "filldraw" "flex" "gobble" | ||
| 352 | "hide" "incr" "interact" "interpath" "intersectionpoint" "inverse" | ||
| 353 | "label" "labels" "lft" "loggingall" "magstep" "makelabel" "max" | ||
| 354 | "min" "mod" "numtok" "penlabels" "penpos" "penstroke" "pickup" | ||
| 355 | "range" "reflectedabout" "relax" "rotatedabout" "rotatedaround" | ||
| 356 | "round" "rt" "savepen" "shipit" "softjoin" "solve" "stop" | ||
| 357 | "superellipse" "takepower" "tensepath" "thru" "top" "tracingall" | ||
| 358 | "tracingnone" "undraw" "undrawdot" "unfill" "unfilldraw" | ||
| 359 | "unitvector" "upto" "whatever") | ||
| 360 | "List of macros common to plain Metafont and MetaPost.") | ||
| 361 | |||
| 362 | (defconst metafont-plain-macros-list | ||
| 363 | '("beginchar" "change_width" "culldraw" "cullit" "cutoff" | ||
| 364 | "define_blacker_pixels" "define_corrected_pixels" | ||
| 365 | "define_good_x_pixels" "define_good_y_pixels" | ||
| 366 | "define_horizontal_corrected_pixels" "define_pixels" | ||
| 367 | "define_whole_blacker_pixels" "define_whole_pixels" | ||
| 368 | "define_whole_vertical_blacker_pixels" | ||
| 369 | "define_whole_vertical_pixels" "endchar" "fix_units" | ||
| 370 | "font_coding_scheme" "font_extra_space" "font_identifier" | ||
| 371 | "font_normal_shrink" "font_normal_space" "font_normal_stretch" | ||
| 372 | "font_quad" "font_size" "font_slant" "font_x_height" "gfcorners" | ||
| 373 | "good.bot" "good.lft" "good.rt" "good.top" "good.x" "good.y" | ||
| 374 | "grayfont" "hround" "imagerules" "italcorr" "labelfont" | ||
| 375 | "lowres_fix" "makebox" "makegrid" "maketicks" "mode_lowres" | ||
| 376 | "mode_proof" "mode_setup" "mode_smoke" "nodisplays" "notransforms" | ||
| 377 | "openit" "penrazor" "pensquare" "proofoffset" "proofrule" | ||
| 378 | "proofrulethickness" "screenchars" "screenrule" "screenstrokes" | ||
| 379 | "showit" "slantfont" "smode" "titlefont" "vround") | ||
| 380 | "List of macros only defined in plain Metafont.") | ||
| 381 | |||
| 382 | (defconst metapost-plain-macros-list | ||
| 383 | '("arrowhead" "bbox" "beginfig" "buildcycle" "center" "cutafter" | ||
| 384 | "cutbefore" "dashpattern" "dotlabel" "dotlabels" "drawarrow" | ||
| 385 | "drawdblarrow" "drawoptions" "endfig" "image" "label" "off" "on" | ||
| 386 | "thelabel") | ||
| 387 | "List of macros only defined in plain MetaPost.") | ||
| 388 | |||
| 389 | (defconst metapost-graph-macros-list | ||
| 390 | '("augment" "auto.x" "auto.y" "autogrid" "begingraph" "endgraph" | ||
| 391 | "format" "frame" "gdata" "gdotlabel" "gdraw" "gdrawarrow" | ||
| 392 | "gdrawdblarrow" "gfill" "glabel" "grid" "itick" "otick" "plot" | ||
| 393 | "setcoords" "setrange") | ||
| 394 | "List of macros only defined in MetaPost \"graph\" package.") | ||
| 395 | |||
| 396 | (defconst metapost-boxes-macros-list | ||
| 397 | '("boxit" "boxjoin" "bpath" "circleit" "drawboxed" "drawboxes" | ||
| 398 | "drawunboxed" "fixpos" "fixsize" "pic" "rboxit") | ||
| 399 | "List of macros only defined in MetaPost \"boxes\" package.") | ||
| 400 | |||
| 401 | |||
| 402 | (defvar metafont-symbol-list | ||
| 403 | (append meta-common-primitives-list | ||
| 404 | metafont-primitives-list | ||
| 405 | meta-common-plain-macros-list | ||
| 406 | metafont-plain-macros-list) | ||
| 407 | "List of known symbols to complete in Metafont mode.") | ||
| 408 | |||
| 409 | (defvar metapost-symbol-list | ||
| 410 | (append meta-common-primitives-list | ||
| 411 | metapost-primitives-list | ||
| 412 | meta-common-plain-macros-list | ||
| 413 | metapost-plain-macros-list | ||
| 414 | metapost-graph-macros-list | ||
| 415 | metapost-boxes-macros-list) | ||
| 416 | "List of known symbols to complete in MetaPost mode.") | ||
| 417 | |||
| 418 | |||
| 419 | (defvar meta-symbol-list nil | ||
| 420 | "List of known symbols to complete in Metafont or MetaPost mode.") | ||
| 421 | |||
| 422 | (defvar meta-symbol-changed nil | ||
| 423 | "Flag indicating whether `meta-symbol-list' has been initialized.") | ||
| 424 | |||
| 425 | (defvar meta-complete-list nil | ||
| 426 | ; (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list) | ||
| 427 | ; (list "" 'ispell-complete-word)) | ||
| 428 | "List of ways to perform completion in Metafont or MetaPost mode. | ||
| 429 | |||
| 430 | Each entry is a list with the following elements: | ||
| 431 | 1. Regexp matching the preceding text. | ||
| 432 | 2. A number indicating the subgroup in the regexp containing the text. | ||
| 433 | 3. A function returning an alist of possible completions. | ||
| 434 | 4. Text to append after a succesful completion (if any). | ||
| 435 | |||
| 436 | Or alternatively: | ||
| 437 | 1. Regexp matching the preceding text. | ||
| 438 | 2. Function to do the actual completion.") | ||
| 439 | |||
| 440 | |||
| 441 | (defun meta-add-symbols (&rest entries) | ||
| 442 | "Add entries to list of known symbols in Metafont or MetaPost mode." | ||
| 443 | (if meta-symbol-changed | ||
| 444 | (setq meta-symbol-list (cons entries meta-symbol-list)) | ||
| 445 | (setq meta-symbol-changed t) | ||
| 446 | (setq meta-symbol-list (cons entries meta-symbol-list)))) | ||
| 447 | |||
| 448 | (defun meta-symbol-list () | ||
| 449 | "Return value of list of known symbols in Metafont or MetaPost mode. | ||
| 450 | If the list was changed, sort the list and remove duplicates first." | ||
| 451 | (if (not meta-symbol-changed) | ||
| 452 | () | ||
| 453 | (setq meta-symbol-changed nil) | ||
| 454 | (message "Preparing completion list...") | ||
| 455 | ;; sort list of symbols | ||
| 456 | (setq meta-symbol-list | ||
| 457 | (sort (mapcar 'meta-listify (apply 'append meta-symbol-list)) | ||
| 458 | 'meta-car-string-lessp)) | ||
| 459 | ;; remove duplicates | ||
| 460 | (let ((entry meta-symbol-list)) | ||
| 461 | (while (and entry (cdr entry)) | ||
| 462 | (let ((this (car entry)) | ||
| 463 | (next (car (cdr entry)))) | ||
| 464 | (if (not (string-equal (car this) (car next))) | ||
| 465 | (setq entry (cdr entry)) | ||
| 466 | (if (> (length next) (length this)) | ||
| 467 | (setcdr this (cdr next))) | ||
| 468 | (setcdr entry (cdr (cdr entry))))))) | ||
| 469 | (message "Preparing completion list... done")) | ||
| 470 | meta-symbol-list) | ||
| 471 | |||
| 472 | (defun meta-listify (a) | ||
| 473 | ;; utility function used in `meta-add-symbols' | ||
| 474 | (if (listp a) a (list a))) | ||
| 475 | |||
| 476 | (defun meta-car-string-lessp (a b) | ||
| 477 | ;; utility function used in `meta-add-symbols' | ||
| 478 | (string-lessp (car a) (car b))) | ||
| 479 | |||
| 480 | |||
| 481 | (defun meta-complete-symbol () | ||
| 482 | "Perform completion on Metafont or MetaPost symbol preceding point." | ||
| 483 | (interactive "*") | ||
| 484 | (let ((list meta-complete-list) | ||
| 485 | entry) | ||
| 486 | (while list | ||
| 487 | (setq entry (car list) | ||
| 488 | list (cdr list)) | ||
| 489 | (if (meta-looking-at-backward (car entry) 200) | ||
| 490 | (setq list nil))) | ||
| 491 | (if (numberp (nth 1 entry)) | ||
| 492 | (let* ((sub (nth 1 entry)) | ||
| 493 | (close (nth 3 entry)) | ||
| 494 | (begin (match-beginning sub)) | ||
| 495 | (end (match-end sub)) | ||
| 496 | (pattern (meta-match-buffer 0)) | ||
| 497 | (symbol (buffer-substring begin end)) | ||
| 498 | (list (funcall (nth 2 entry))) | ||
| 499 | (completion (try-completion symbol list))) | ||
| 500 | (cond ((eq completion t) | ||
| 501 | (and close | ||
| 502 | (not (looking-at (regexp-quote close))) | ||
| 503 | (insert close))) | ||
| 504 | ((null completion) | ||
| 505 | (error "Can't find completion for \"%s\"" pattern)) | ||
| 506 | ((not (string-equal symbol completion)) | ||
| 507 | (delete-region begin end) | ||
| 508 | (insert completion) | ||
| 509 | (and close | ||
| 510 | (eq (try-completion completion list) t) | ||
| 511 | (not (looking-at (regexp-quote close))) | ||
| 512 | (insert close))) | ||
| 513 | (t | ||
| 514 | (message "Making completion list...") | ||
| 515 | (let ((list (all-completions symbol list nil))) | ||
| 516 | (with-output-to-temp-buffer "*Completions*" | ||
| 517 | (display-completion-list list))) | ||
| 518 | (message "Making completion list... done")))) | ||
| 519 | (funcall (nth 1 entry))))) | ||
| 520 | |||
| 521 | |||
| 522 | (defun meta-looking-at-backward (regexp &optional limit) | ||
| 523 | ;; utility function used in `meta-complete-symbol' | ||
| 524 | (let ((pos (point))) | ||
| 525 | (save-excursion | ||
| 526 | (and (re-search-backward | ||
| 527 | regexp (if limit (max (point-min) (- (point) limit))) t) | ||
| 528 | (eq (match-end 0) pos))))) | ||
| 529 | |||
| 530 | (defun meta-match-buffer (n) | ||
| 531 | ;; utility function used in `meta-complete-symbol' | ||
| 532 | (if (match-beginning n) | ||
| 533 | (let ((str (buffer-substring (match-beginning n) (match-end n)))) | ||
| 534 | (set-text-properties 0 (length str) nil str) | ||
| 535 | (copy-sequence str)) | ||
| 536 | "")) | ||
| 537 | |||
| 538 | |||
| 539 | |||
| 540 | ;;; Indentation. | ||
| 541 | |||
| 542 | (defvar meta-indent-level 2 | ||
| 543 | "*Indentation of begin-end blocks in Metafont or MetaPost mode.") | ||
| 544 | |||
| 545 | |||
| 546 | (defvar meta-left-comment-regexp "%%+" | ||
| 547 | "*Regexp matching comments that should be placed on the left margin.") | ||
| 548 | |||
| 549 | (defvar meta-right-comment-regexp nil | ||
| 550 | "*Regexp matching comments that should be placed to the right margin.") | ||
| 551 | |||
| 552 | (defvar meta-ignore-comment-regexp "%[^%]" | ||
| 553 | "*Regexp matching comments that whose indentation should not be touched.") | ||
| 554 | |||
| 555 | |||
| 556 | (defvar meta-begin-environment-regexp | ||
| 557 | (concat "\\(begin\\(char\\|fig\\|gr\\(aph\\|oup\\)\\|logochar\\)\\|" | ||
| 558 | "def\\|for\\(\\|ever\\|suffixes\\)\\|if\\|mode_def\\|" | ||
| 559 | "primarydef\\|secondarydef\\|tertiarydef\\|vardef\\)") | ||
| 560 | "*Regexp matching the beginning of environments to be indented.") | ||
| 561 | |||
| 562 | (defvar meta-end-environment-regexp | ||
| 563 | (concat "\\(end\\(char\\|def\\|f\\(ig\\|or\\)\\|gr\\(aph\\|oup\\)\\)" | ||
| 564 | "\\|fi\\)") | ||
| 565 | "*Regexp matching the end of environments to be indented.") | ||
| 566 | |||
| 567 | (defvar meta-within-environment-regexp | ||
| 568 | ; (concat "\\(e\\(lse\\(\\|if\\)\\|xit\\(if\\|unless\\)\\)\\)") | ||
| 569 | (concat "\\(else\\(\\|if\\)\\)") | ||
| 570 | "*Regexp matching keywords within environments not to be indented.") | ||
| 571 | |||
| 572 | |||
| 573 | (defun meta-comment-indent () | ||
| 574 | "Return the indentation for a comment in Metafont or MetaPost mode." | ||
| 575 | (if (and meta-left-comment-regexp | ||
| 576 | (looking-at meta-left-comment-regexp)) | ||
| 577 | (current-column) | ||
| 578 | (skip-chars-backward "\t ") | ||
| 579 | (max (if (bolp) 0 (1+ (current-column))) | ||
| 580 | comment-column))) | ||
| 581 | |||
| 582 | (defun meta-indent-line () | ||
| 583 | "Indent the line containing point as Metafont or MetaPost source." | ||
| 584 | (interactive) | ||
| 585 | (let ((indent (meta-indent-calculate))) | ||
| 586 | (save-excursion | ||
| 587 | (if (/= (current-indentation) indent) | ||
| 588 | (let ((beg (progn (beginning-of-line) (point))) | ||
| 589 | (end (progn (back-to-indentation) (point)))) | ||
| 590 | (delete-region beg end) | ||
| 591 | (indent-to indent)))) | ||
| 592 | (if (< (current-column) indent) | ||
| 593 | (back-to-indentation)))) | ||
| 594 | |||
| 595 | (defun meta-indent-calculate () | ||
| 596 | "Return the indentation of current line of Metafont or MetaPost source." | ||
| 597 | (save-excursion | ||
| 598 | (back-to-indentation) | ||
| 599 | (cond | ||
| 600 | ;; Comments to the left margin. | ||
| 601 | ((and meta-left-comment-regexp | ||
| 602 | (looking-at meta-left-comment-regexp)) | ||
| 603 | 0) | ||
| 604 | ;; Comments to the right margin. | ||
| 605 | ((and meta-right-comment-regexp | ||
| 606 | (looking-at meta-right-comment-regexp)) | ||
| 607 | comment-column) | ||
| 608 | ;; Comments best left alone. | ||
| 609 | ((and meta-ignore-comment-regexp | ||
| 610 | (looking-at meta-ignore-comment-regexp)) | ||
| 611 | (current-indentation)) | ||
| 612 | ;; Backindent at end of environments. | ||
| 613 | ((looking-at | ||
| 614 | (concat "\\<" meta-end-environment-regexp "\\>")) | ||
| 615 | (- (meta-indent-calculate-last) meta-indent-level)) | ||
| 616 | ;; Backindent at keywords within environments. | ||
| 617 | ((looking-at | ||
| 618 | (concat "\\<" meta-within-environment-regexp "\\>")) | ||
| 619 | (- (meta-indent-calculate-last) meta-indent-level)) | ||
| 620 | (t (meta-indent-calculate-last))))) | ||
| 621 | |||
| 622 | (defun meta-indent-calculate-last () | ||
| 623 | "Return the indentation of previous line of Metafont or MetaPost source." | ||
| 624 | (save-restriction | ||
| 625 | (widen) | ||
| 626 | (skip-chars-backward "\n\t ") | ||
| 627 | (move-to-column (current-indentation)) | ||
| 628 | ;; Ignore comments. | ||
| 629 | (while (and (looking-at comment-start) (not (bobp))) | ||
| 630 | (skip-chars-backward "\n\t ") | ||
| 631 | (if (not (bobp)) | ||
| 632 | (move-to-column (current-indentation)))) | ||
| 633 | (cond | ||
| 634 | ((bobp) 0) | ||
| 635 | (t (+ (current-indentation) | ||
| 636 | (meta-indent-level-count) | ||
| 637 | (cond | ||
| 638 | ;; Compensate for backindent at end of environments. | ||
| 639 | ((looking-at | ||
| 640 | (concat "\\<"meta-end-environment-regexp "\\>")) | ||
| 641 | meta-indent-level) | ||
| 642 | ;; Compensate for backindent within environments. | ||
| 643 | ((looking-at | ||
| 644 | (concat "\\<" meta-within-environment-regexp "\\>")) | ||
| 645 | meta-indent-level) | ||
| 646 | (t 0))))) | ||
| 647 | )) | ||
| 648 | |||
| 649 | (defun meta-indent-level-count () | ||
| 650 | "Count indentation change for begin-end commands in the current line." | ||
| 651 | (save-excursion | ||
| 652 | (save-restriction | ||
| 653 | (let ((count 0)) | ||
| 654 | (narrow-to-region | ||
| 655 | (point) (save-excursion | ||
| 656 | (re-search-forward "[^\\\\\"]%\\|\n\\|\\'" nil t) | ||
| 657 | (backward-char) (point))) | ||
| 658 | (while (re-search-forward "\\<\\sw+\\>\\|(\\|)" nil t) | ||
| 659 | (save-excursion | ||
| 660 | (goto-char (match-beginning 0)) | ||
| 661 | (cond | ||
| 662 | ;; Count number of begin-end keywords within line. | ||
| 663 | ((looking-at | ||
| 664 | (concat "\\<" meta-begin-environment-regexp "\\>")) | ||
| 665 | (setq count (+ count meta-indent-level))) | ||
| 666 | ((looking-at | ||
| 667 | (concat "\\<" meta-end-environment-regexp "\\>")) | ||
| 668 | (setq count (- count meta-indent-level))) | ||
| 669 | ;; Count number of open-close parentheses within line. | ||
| 670 | ((looking-at "(") | ||
| 671 | (setq count (+ count meta-indent-level))) | ||
| 672 | ((looking-at ")") | ||
| 673 | (setq count (- count meta-indent-level))) | ||
| 674 | ))) | ||
| 675 | count)))) | ||
| 676 | |||
| 677 | |||
| 678 | |||
| 679 | ;;; Filling paragraphs. | ||
| 680 | |||
| 681 | (defun meta-fill-paragraph (&optional justify) | ||
| 682 | "Like \\[fill-paragraph], but handle Metafont or MetaPost comments. | ||
| 683 | If any part of the current line is a comment, fill the comment or the | ||
| 684 | paragraph of it that point is in, preserving the comment's indentation | ||
| 685 | and initial semicolons." | ||
| 686 | (interactive "P") | ||
| 687 | (let (has-comment ; Non-nil if line contains a comment. | ||
| 688 | has-code-and-comment ; Non-nil if line contains code and a comment. | ||
| 689 | comment-fill-prefix ; If has-comment, fill-prefix for the comment. | ||
| 690 | ) | ||
| 691 | ;; Figure out what kind of comment we are looking at. | ||
| 692 | (save-excursion | ||
| 693 | (beginning-of-line) | ||
| 694 | (cond | ||
| 695 | ;; A line with nothing but a comment on it? | ||
| 696 | ((looking-at (concat "[ \t]*" comment-start-skip)) | ||
| 697 | (setq has-comment t) | ||
| 698 | (setq comment-fill-prefix | ||
| 699 | (buffer-substring (match-beginning 0) (match-end 0)))) | ||
| 700 | ;; A line with some code, followed by a comment? | ||
| 701 | ((condition-case nil | ||
| 702 | (save-restriction | ||
| 703 | (narrow-to-region (point-min) | ||
| 704 | (save-excursion (end-of-line) (point))) | ||
| 705 | (while (not (looking-at (concat comment-start "\\|$"))) | ||
| 706 | (skip-chars-forward (concat "^" comment-start "\n\"\\\\")) | ||
| 707 | (cond | ||
| 708 | ((eq (char-after (point)) ?\\) (forward-char 2)) | ||
| 709 | ((eq (char-after (point)) ?\") (forward-sexp 1)))) | ||
| 710 | (looking-at comment-start-skip)) | ||
| 711 | (error nil)) | ||
| 712 | (setq has-comment t | ||
| 713 | has-code-and-comment t) | ||
| 714 | (setq comment-fill-prefix | ||
| 715 | (concat (make-string (/ (current-column) 8) ?\t) | ||
| 716 | (make-string (% (current-column) 8) ?\ ) | ||
| 717 | (buffer-substring (match-beginning 0) (match-end 0))))) | ||
| 718 | )) | ||
| 719 | (if (not has-comment) | ||
| 720 | (fill-paragraph justify) | ||
| 721 | ;; Narrow to include only the comment, and then fill the region. | ||
| 722 | (save-excursion | ||
| 723 | (save-restriction | ||
| 724 | (beginning-of-line) | ||
| 725 | (narrow-to-region | ||
| 726 | ;; Find the first line we should include in the region to fill. | ||
| 727 | (save-excursion | ||
| 728 | (while (and (zerop (forward-line -1)) | ||
| 729 | (looking-at (concat "^[ \t]*" comment-start)))) | ||
| 730 | (or (looking-at (concat ".*" comment-start)) | ||
| 731 | (forward-line 1)) | ||
| 732 | (point)) | ||
| 733 | ;; Find the beginning of the first line past the region to fill. | ||
| 734 | (save-excursion | ||
| 735 | (while (progn (forward-line 1) | ||
| 736 | (looking-at (concat "^[ \t]*" comment-start)))) | ||
| 737 | (point))) | ||
| 738 | (let* ((paragraph-start | ||
| 739 | (concat paragraph-start "\\|[ \t%]*$")) | ||
| 740 | (paragraph-separate | ||
| 741 | (concat paragraph-start "\\|[ \t%]*$")) | ||
| 742 | (paragraph-ignore-fill-prefix nil) | ||
| 743 | (fill-prefix comment-fill-prefix) | ||
| 744 | (after-line (if has-code-and-comment | ||
| 745 | (save-excursion (forward-line 1) (point)))) | ||
| 746 | (end (progn (forward-paragraph) | ||
| 747 | (or (bolp) (newline 1)) | ||
| 748 | (point))) | ||
| 749 | (beg (progn (backward-paragraph) | ||
| 750 | (if (eq (point) after-line) (forward-line -1)) | ||
| 751 | (point))) | ||
| 752 | (after-pos (save-excursion | ||
| 753 | (goto-char beg) | ||
| 754 | (if (not (looking-at fill-prefix)) | ||
| 755 | (progn | ||
| 756 | (re-search-forward comment-start-skip) | ||
| 757 | (point))))) | ||
| 758 | ) | ||
| 759 | (fill-region-as-paragraph beg end justify nil after-pos)) | ||
| 760 | ))) | ||
| 761 | t)) | ||
| 762 | |||
| 763 | |||
| 764 | |||
| 765 | ;;; Editing commands. | ||
| 766 | |||
| 767 | (defvar meta-begin-defun-regexp | ||
| 768 | (concat "\\(begin\\(char\\|fig\\|logochar\\)\\|def\\|mode_def\\|" | ||
| 769 | "primarydef\\|secondarydef\\|tertiarydef\\|vardef\\)") | ||
| 770 | "*Regexp matching beginning of defuns in Metafont or MetaPost mode.") | ||
| 771 | |||
| 772 | (defvar meta-end-defun-regexp | ||
| 773 | (concat "\\(end\\(char\\|def\\|fig\\)\\)") | ||
| 774 | "*Regexp matching the end of defuns in Metafont or MetaPost mode.") | ||
| 775 | |||
| 776 | |||
| 777 | (defun meta-beginning-of-defun (&optional arg) | ||
| 778 | "Move backward to beginnning of a defun in Metafont or MetaPost code. | ||
| 779 | With numeric argument, do it that many times. | ||
| 780 | Negative arg -N means move forward to Nth following beginning of defun. | ||
| 781 | Returns t unless search stops due to beginning or end of buffer." | ||
| 782 | (interactive "p") | ||
| 783 | (if (or (null arg) (= 0 arg)) (setq arg 1)) | ||
| 784 | (and arg (< arg 0) (not (eobp)) (forward-char 1)) | ||
| 785 | (and (re-search-backward | ||
| 786 | (concat "\\<" meta-begin-defun-regexp "\\>") nil t arg) | ||
| 787 | (progn (goto-char (match-beginning 0)) | ||
| 788 | (skip-chars-backward "%") | ||
| 789 | (skip-chars-backward " \t") t))) | ||
| 790 | |||
| 791 | (defun meta-end-of-defun (&optional arg) | ||
| 792 | "Move forward to end of a defun in Metafont or MetaPost code. | ||
| 793 | With numeric argument, do it that many times. | ||
| 794 | Negative argument -N means move back to Nth preceding end of defun. | ||
| 795 | Returns t unless search stops due to beginning or end of buffer." | ||
| 796 | (interactive "p") | ||
| 797 | (if (or (null arg) (= 0 arg)) (setq arg 1)) | ||
| 798 | (and (< arg 0) (not (bobp)) (forward-line -1)) | ||
| 799 | (and (re-search-forward | ||
| 800 | (concat "\\<" meta-end-defun-regexp "\\>") nil t arg) | ||
| 801 | (progn (goto-char (match-end 0)) | ||
| 802 | (skip-chars-forward ";") | ||
| 803 | (skip-chars-forward " \t") | ||
| 804 | (if (looking-at "\n") (forward-line 1)) t))) | ||
| 805 | |||
| 806 | |||
| 807 | (defun meta-comment-region (beg end &optional arg) | ||
| 808 | "Comment out active region as Metafont or MetaPost source." | ||
| 809 | (interactive "r") | ||
| 810 | (comment-region beg end arg)) | ||
| 811 | |||
| 812 | (defun meta-uncomment-region (beg end) | ||
| 813 | "Uncomment active region as Metafont or MetaPost source." | ||
| 814 | (interactive "r") | ||
| 815 | (comment-region beg end -1)) | ||
| 816 | |||
| 817 | (defun meta-comment-defun (&optional arg) | ||
| 818 | "Comment out current environment as Metafont or MetaPost source. | ||
| 819 | With prefix argument, uncomment the environment. | ||
| 820 | The environment used is the one that contains point or follows point." | ||
| 821 | (interactive "P") | ||
| 822 | (save-excursion | ||
| 823 | (let* ((end (if (meta-end-of-defun) (point) (point-max))) | ||
| 824 | (beg (if (meta-beginning-of-defun) (point) (point-min)))) | ||
| 825 | (comment-region beg end arg)))) | ||
| 826 | |||
| 827 | (defun meta-uncomment-defun () | ||
| 828 | "Uncomment current environment as Metafont or MetaPost source." | ||
| 829 | (interactive) | ||
| 830 | (meta-comment-defun -1)) | ||
| 831 | |||
| 832 | |||
| 833 | (defun meta-indent-region (beg end) | ||
| 834 | "Indent the active region as Metafont or MetaPost source." | ||
| 835 | (interactive "r") | ||
| 836 | (indent-region beg end nil)) | ||
| 837 | |||
| 838 | (defun meta-indent-buffer () | ||
| 839 | "Indent the whole buffer contents as Metafont or MetaPost source." | ||
| 840 | (interactive) | ||
| 841 | (save-excursion | ||
| 842 | (indent-region (point-min) (point-max) nil))) | ||
| 843 | |||
| 844 | (defun meta-indent-defun () | ||
| 845 | "Indent the current environment as Metafont or MetaPost source. | ||
| 846 | The environment indented is the one that contains point or follows point." | ||
| 847 | (interactive) | ||
| 848 | (save-excursion | ||
| 849 | (let* ((end (if (meta-end-of-defun) (point) (point-max))) | ||
| 850 | (beg (if (meta-beginning-of-defun) (point) (point-min)))) | ||
| 851 | (indent-region beg end nil)))) | ||
| 852 | |||
| 853 | |||
| 854 | (defun meta-mark-defun () | ||
| 855 | "Put mark at end of the environment, point at the beginning. | ||
| 856 | The environment marked is the one that contains point or follows point." | ||
| 857 | (interactive) | ||
| 858 | (push-mark (point)) | ||
| 859 | (meta-end-of-defun) | ||
| 860 | (push-mark (point) nil t) | ||
| 861 | (meta-beginning-of-defun)) | ||
| 862 | |||
| 863 | |||
| 864 | |||
| 865 | ;;; Syntax table, keymap and menu. | ||
| 866 | |||
| 867 | (defvar meta-mode-abbrev-table nil | ||
| 868 | "Abbrev table used in Metafont or MetaPost mode.") | ||
| 869 | (define-abbrev-table 'meta-mode-abbrev-table ()) | ||
| 870 | |||
| 871 | (defvar meta-mode-syntax-table nil | ||
| 872 | "Syntax table used in Metafont or MetaPost mode.") | ||
| 873 | (if meta-mode-syntax-table | ||
| 874 | () | ||
| 875 | (setq meta-mode-syntax-table (make-syntax-table)) | ||
| 876 | ;; underscores are word constituents | ||
| 877 | (modify-syntax-entry ?_ "w" meta-mode-syntax-table) | ||
| 878 | ;; miscellaneous non-word symbols | ||
| 879 | (modify-syntax-entry ?# "_" meta-mode-syntax-table) | ||
| 880 | (modify-syntax-entry ?@ "_" meta-mode-syntax-table) | ||
| 881 | (modify-syntax-entry ?$ "_" meta-mode-syntax-table) | ||
| 882 | (modify-syntax-entry ?? "_" meta-mode-syntax-table) | ||
| 883 | (modify-syntax-entry ?! "_" meta-mode-syntax-table) | ||
| 884 | ;; binary operators | ||
| 885 | (modify-syntax-entry ?& "." meta-mode-syntax-table) | ||
| 886 | (modify-syntax-entry ?+ "." meta-mode-syntax-table) | ||
| 887 | (modify-syntax-entry ?- "." meta-mode-syntax-table) | ||
| 888 | (modify-syntax-entry ?/ "." meta-mode-syntax-table) | ||
| 889 | (modify-syntax-entry ?* "." meta-mode-syntax-table) | ||
| 890 | (modify-syntax-entry ?. "." meta-mode-syntax-table) | ||
| 891 | (modify-syntax-entry ?: "." meta-mode-syntax-table) | ||
| 892 | (modify-syntax-entry ?= "." meta-mode-syntax-table) | ||
| 893 | (modify-syntax-entry ?< "." meta-mode-syntax-table) | ||
| 894 | (modify-syntax-entry ?> "." meta-mode-syntax-table) | ||
| 895 | (modify-syntax-entry ?| "." meta-mode-syntax-table) | ||
| 896 | ;; opening and closing delimiters | ||
| 897 | (modify-syntax-entry ?\( "()" meta-mode-syntax-table) | ||
| 898 | (modify-syntax-entry ?\) ")(" meta-mode-syntax-table) | ||
| 899 | (modify-syntax-entry ?\[ "(]" meta-mode-syntax-table) | ||
| 900 | (modify-syntax-entry ?\] ")[" meta-mode-syntax-table) | ||
| 901 | (modify-syntax-entry ?\{ "(}" meta-mode-syntax-table) | ||
| 902 | (modify-syntax-entry ?\} "){" meta-mode-syntax-table) | ||
| 903 | ;; comment character | ||
| 904 | (modify-syntax-entry ?% "<" meta-mode-syntax-table) | ||
| 905 | (modify-syntax-entry ?\n ">" meta-mode-syntax-table) | ||
| 906 | ;; escape character, needed for embedded TeX code | ||
| 907 | (modify-syntax-entry ?\\ "\\" meta-mode-syntax-table) | ||
| 908 | ) | ||
| 909 | |||
| 910 | (defvar meta-mode-map nil | ||
| 911 | "Keymap used in Metafont or MetaPost mode.") | ||
| 912 | (if meta-mode-map | ||
| 913 | () | ||
| 914 | (setq meta-mode-map (make-sparse-keymap)) | ||
| 915 | (define-key meta-mode-map "\t" 'meta-indent-line) | ||
| 916 | (define-key meta-mode-map "\C-m" 'reindent-then-newline-and-indent) | ||
| 917 | ;; Comment Paragraphs: | ||
| 918 | ; (define-key meta-mode-map "\M-a" 'backward-sentence) | ||
| 919 | ; (define-key meta-mode-map "\M-e" 'forward-sentence) | ||
| 920 | ; (define-key meta-mode-map "\M-h" 'mark-paragraph) | ||
| 921 | ; (define-key meta-mode-map "\M-q" 'fill-paragraph) | ||
| 922 | ;; Navigation: | ||
| 923 | (define-key meta-mode-map "\M-\C-a" 'meta-beginning-of-defun) | ||
| 924 | (define-key meta-mode-map "\M-\C-e" 'meta-end-of-defun) | ||
| 925 | (define-key meta-mode-map "\M-\C-h" 'meta-mark-defun) | ||
| 926 | ;; Indentation: | ||
| 927 | (define-key meta-mode-map "\M-\C-q" 'meta-indent-defun) | ||
| 928 | (define-key meta-mode-map "\C-c\C-qe" 'meta-indent-defun) | ||
| 929 | (define-key meta-mode-map "\C-c\C-qr" 'meta-indent-region) | ||
| 930 | (define-key meta-mode-map "\C-c\C-qb" 'meta-indent-buffer) | ||
| 931 | ;; Commenting Out: | ||
| 932 | (define-key meta-mode-map "\C-c%" 'meta-comment-defun) | ||
| 933 | ; (define-key meta-mode-map "\C-uC-c%" 'meta-uncomment-defun) | ||
| 934 | (define-key meta-mode-map "\C-c;" 'meta-comment-region) | ||
| 935 | (define-key meta-mode-map "\C-c:" 'meta-uncomment-region) | ||
| 936 | ;; Symbol Completion: | ||
| 937 | (define-key meta-mode-map "\M-\t" 'meta-complete-symbol) | ||
| 938 | ;; Shell Commands: | ||
| 939 | ; (define-key meta-mode-map "\C-c\C-c" 'meta-command-file) | ||
| 940 | ; (define-key meta-mode-map "\C-c\C-k" 'meta-kill-job) | ||
| 941 | ; (define-key meta-mode-map "\C-c\C-l" 'meta-recenter-output) | ||
| 942 | ) | ||
| 943 | |||
| 944 | (easy-menu-define | ||
| 945 | meta-mode-menu meta-mode-map | ||
| 946 | "Menu used in Metafont or MetaPost mode." | ||
| 947 | (list "Meta" | ||
| 948 | ["Forward Environment" meta-beginning-of-defun t] | ||
| 949 | ["Backward Environment" meta-end-of-defun t] | ||
| 950 | "--" | ||
| 951 | ["Indent Line" meta-indent-line t] | ||
| 952 | ["Indent Environment" meta-indent-defun t] | ||
| 953 | ["Indent Region" meta-indent-region | ||
| 954 | :active (meta-mark-active)] | ||
| 955 | ["Indent Buffer" meta-indent-buffer t] | ||
| 956 | "--" | ||
| 957 | ["Comment Out Environment" meta-comment-defun t] | ||
| 958 | ["Uncomment Environment" meta-uncomment-defun t] | ||
| 959 | ["Comment Out Region" meta-comment-region | ||
| 960 | :active (meta-mark-active)] | ||
| 961 | ["Uncomment Region" meta-uncomment-region | ||
| 962 | :active (meta-mark-active)] | ||
| 963 | "--" | ||
| 964 | ["Complete Symbol" meta-complete-symbol t] | ||
| 965 | ; "--" | ||
| 966 | ; ["Command on Buffer" meta-command-file t] | ||
| 967 | ; ["Kill Job" meta-kill-job t] | ||
| 968 | ; ["Recenter Output Buffer" meta-recenter-output-buffer t] | ||
| 969 | )) | ||
| 970 | |||
| 971 | ;; Compatibility: XEmacs doesn't have the `mark-active' variable. | ||
| 972 | (defun meta-mark-active () | ||
| 973 | "Return whether the mark and region are currently active in this buffer." | ||
| 974 | (or (and (boundp 'mark-active) mark-active) (mark))) | ||
| 975 | |||
| 976 | |||
| 977 | |||
| 978 | ;;; Hook variables. | ||
| 979 | |||
| 980 | (defvar meta-mode-load-hook nil | ||
| 981 | "*Hook evaluated when first loading Metafont or MetaPost mode.") | ||
| 982 | |||
| 983 | (defvar meta-common-mode-hook nil | ||
| 984 | "*Hook evaluated by both `metafont-mode' and `metapost-mode'.") | ||
| 985 | |||
| 986 | (defvar metafont-mode-hook nil | ||
| 987 | "*Hook evaluated by `metafont-mode' after `meta-common-mode-hook'.") | ||
| 988 | (defvar metapost-mode-hook nil | ||
| 989 | "*Hook evaluated by `metapost-mode' after `meta-common-mode-hook'.") | ||
| 990 | |||
| 991 | |||
| 992 | |||
| 993 | ;;; Initialization. | ||
| 994 | |||
| 995 | (defun meta-common-initialization () | ||
| 996 | "Common initialization for Metafont or MetaPost mode." | ||
| 997 | (kill-all-local-variables) | ||
| 998 | |||
| 999 | (make-local-variable 'paragraph-start) | ||
| 1000 | (make-local-variable 'paragraph-separate) | ||
| 1001 | (setq paragraph-start | ||
| 1002 | (concat page-delimiter "\\|$")) | ||
| 1003 | (setq paragraph-separate | ||
| 1004 | (concat page-delimiter "\\|$")) | ||
| 1005 | |||
| 1006 | (make-local-variable 'paragraph-ignore-fill-prefix) | ||
| 1007 | (setq paragraph-ignore-fill-prefix t) | ||
| 1008 | |||
| 1009 | (make-local-variable 'comment-start-skip) | ||
| 1010 | (make-local-variable 'comment-start) | ||
| 1011 | (make-local-variable 'comment-end) | ||
| 1012 | (make-local-variable 'comment-multi-line) | ||
| 1013 | (setq comment-start-skip "%+[ \t]*") | ||
| 1014 | (setq comment-start "%") | ||
| 1015 | (setq comment-end "") | ||
| 1016 | (setq comment-multi-line nil) | ||
| 1017 | |||
| 1018 | (make-local-variable 'parse-sexp-ignore-comments) | ||
| 1019 | (setq parse-sexp-ignore-comments t) | ||
| 1020 | |||
| 1021 | (make-local-variable 'comment-indent-function) | ||
| 1022 | (setq comment-indent-function 'meta-comment-indent) | ||
| 1023 | (make-local-variable 'fill-paragraph-function) | ||
| 1024 | (setq fill-paragraph-function 'meta-fill-paragraph) | ||
| 1025 | (make-local-variable 'indent-line-function) | ||
| 1026 | (setq indent-line-function 'meta-indent-line) | ||
| 1027 | ;; No need to define a mode-specific 'indent-region-function. | ||
| 1028 | ;; Simply use the generic 'indent-region and 'comment-region. | ||
| 1029 | |||
| 1030 | ;; Set defaults for font-lock mode. | ||
| 1031 | (make-local-variable 'font-lock-defaults) | ||
| 1032 | (setq font-lock-defaults | ||
| 1033 | '(meta-font-lock-keywords | ||
| 1034 | nil nil ((?_ . "w")) nil | ||
| 1035 | (font-lock-comment-start-regexp . "%"))) | ||
| 1036 | |||
| 1037 | ;; Activate syntax table, keymap and menu. | ||
| 1038 | (setq local-abbrev-table meta-mode-abbrev-table) | ||
| 1039 | (set-syntax-table meta-mode-syntax-table) | ||
| 1040 | (use-local-map meta-mode-map) | ||
| 1041 | (easy-menu-add meta-mode-menu) | ||
| 1042 | ) | ||
| 1043 | |||
| 1044 | |||
| 1045 | (defun metafont-mode () | ||
| 1046 | "Major mode for editing Metafont sources. | ||
| 1047 | Special commands: | ||
| 1048 | \\{meta-mode-map} | ||
| 1049 | |||
| 1050 | Turning on Metafont mode calls the value of the variables | ||
| 1051 | `meta-common-mode-hook' and `metafont-mode-hook'." | ||
| 1052 | (interactive) | ||
| 1053 | (meta-common-initialization) | ||
| 1054 | (setq mode-name "Metafont") | ||
| 1055 | (setq major-mode 'metafont-mode) | ||
| 1056 | |||
| 1057 | ;; Set defaults for completion function. | ||
| 1058 | (make-local-variable 'meta-symbol-list) | ||
| 1059 | (make-local-variable 'meta-symbol-changed) | ||
| 1060 | (make-local-variable 'meta-complete-list) | ||
| 1061 | (setq meta-symbol-list nil) | ||
| 1062 | (setq meta-symbol-changed nil) | ||
| 1063 | (apply 'meta-add-symbols metafont-symbol-list) | ||
| 1064 | (setq meta-complete-list | ||
| 1065 | (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list) | ||
| 1066 | (list "" 'ispell-complete-word))) | ||
| 1067 | (run-hooks 'meta-common-mode-hook 'metafont-mode-hook)) | ||
| 1068 | |||
| 1069 | (defun metapost-mode () | ||
| 1070 | "Major mode for editing MetaPost sources. | ||
| 1071 | Special commands: | ||
| 1072 | \\{meta-mode-map} | ||
| 1073 | |||
| 1074 | Turning on MetaPost mode calls the value of the variable | ||
| 1075 | `meta-common-mode-hook' and `metafont-mode-hook'." | ||
| 1076 | (interactive) | ||
| 1077 | (meta-common-initialization) | ||
| 1078 | (setq mode-name "MetaPost") | ||
| 1079 | (setq major-mode 'metapost-mode) | ||
| 1080 | |||
| 1081 | ;; Set defaults for completion function. | ||
| 1082 | (make-local-variable 'meta-symbol-list) | ||
| 1083 | (make-local-variable 'meta-symbol-changed) | ||
| 1084 | (make-local-variable 'meta-complete-list) | ||
| 1085 | (setq meta-symbol-list nil) | ||
| 1086 | (setq meta-symbol-changed nil) | ||
| 1087 | (apply 'meta-add-symbols metapost-symbol-list) | ||
| 1088 | (setq meta-complete-list | ||
| 1089 | (list (list "\\<\\(\\sw+\\)" 1 'meta-symbol-list) | ||
| 1090 | (list "" 'ispell-complete-word))) | ||
| 1091 | (run-hooks 'meta-common-mode-hook 'metapost-mode-hook)) | ||
| 1092 | |||
| 1093 | |||
| 1094 | ;;; Just in case ... | ||
| 1095 | |||
| 1096 | (provide 'meta-mode) | ||
| 1097 | (run-hooks 'meta-mode-load-hook) | ||
| 1098 | |||
| 1099 | ;;; meta-mode.el ends here | ||
diff --git a/src/m/news-r6.h b/src/m/news-r6.h new file mode 100644 index 00000000000..dbdb66c287c --- /dev/null +++ b/src/m/news-r6.h | |||
| @@ -0,0 +1,65 @@ | |||
| 1 | /* news-risc6.h is for the "RISC News", OS version 6. */ | ||
| 2 | /* This is in the public domain. */ | ||
| 3 | |||
| 4 | /* Define NO_ARG_ARRAY if you cannot take the address of the first of a | ||
| 5 | * group of arguments and treat it as an array of the arguments. */ | ||
| 6 | |||
| 7 | #define NO_ARG_ARRAY | ||
| 8 | |||
| 9 | /* Use type int rather than a union, to represent Lisp_Object */ | ||
| 10 | /* This is desirable for most machines. */ | ||
| 11 | |||
| 12 | #define NO_UNION_TYPE | ||
| 13 | |||
| 14 | /* Data type of load average, as read out of kmem. */ | ||
| 15 | |||
| 16 | #define LOAD_AVE_TYPE long | ||
| 17 | |||
| 18 | /* Convert that into an integer that is 100 for a load average of 1.0 */ | ||
| 19 | |||
| 20 | #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / 256.0) | ||
| 21 | |||
| 22 | /* Define C_ALLOCA if this machine does not support a true alloca | ||
| 23 | and the one written in C should be used instead. | ||
| 24 | Define HAVE_ALLOCA to say that the system provides a properly | ||
| 25 | working alloca function and it should be used. | ||
| 26 | Define neither one if an assembler-language alloca | ||
| 27 | in the file alloca.s should be used. */ | ||
| 28 | |||
| 29 | #define HAVE_ALLOCA | ||
| 30 | |||
| 31 | /* Define NO_REMAP if memory segmentation makes it not work well | ||
| 32 | to change the boundary between the text section and data section | ||
| 33 | when Emacs is dumped. If you define this, the preloaded Lisp | ||
| 34 | code will not be sharable; but that's better than failing completely. */ | ||
| 35 | |||
| 36 | #define NO_REMAP | ||
| 37 | |||
| 38 | /* Alter some of the options used when linking. */ | ||
| 39 | |||
| 40 | /*#define C_DEBUG_SWITCH -g*/ | ||
| 41 | #define C_DEBUG_SWITCH -O -Olimit 2000 | ||
| 42 | #ifdef __GNUC__ | ||
| 43 | #define C_OPTIMIZE_SWITCH -O | ||
| 44 | #define LD_SWITCH_MACHINE -g -Xlinker -D -Xlinker 800000 | ||
| 45 | #else /* !__GNUC__ */ | ||
| 46 | /*#define LD_SWITCH_MACHINE -D 800000 -g*/ | ||
| 47 | #define LD_SWITCH_MACHINE -D 800000 | ||
| 48 | #endif /* !__GNUC__ */ | ||
| 49 | #define LIBS_MACHINE -lmld | ||
| 50 | #define LIBS_TERMCAP -lcurses | ||
| 51 | |||
| 52 | /* The standard definitions of these macros would work ok, | ||
| 53 | but these are faster because the constants are short. */ | ||
| 54 | |||
| 55 | #define XUINT(a) (((unsigned)(a) << (BITS_PER_INT-VALBITS)) >> (BITS_PER_INT-VALBITS)) | ||
| 56 | |||
| 57 | #define XSET(var, type, ptr) \ | ||
| 58 | ((var) = \ | ||
| 59 | ((int)(type) << VALBITS) \ | ||
| 60 | + (((unsigned) (ptr) << (BITS_PER_INT-VALBITS)) >> (BITS_PER_INT-VALBITS))) | ||
| 61 | |||
| 62 | #define XUNMARK(a) \ | ||
| 63 | ((a) = \ | ||
| 64 | (((unsigned)(a) << (BITS_PER_INT-GCTYPEBITS-VALBITS)) \ | ||
| 65 | >> (BITS_PER_INT-GCTYPEBITS-VALBITS))) | ||
diff --git a/src/s/newsos6.h b/src/s/newsos6.h new file mode 100644 index 00000000000..d4e67f7e4cf --- /dev/null +++ b/src/s/newsos6.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | /* Definitions file for GNU Emacs running on Sony's NEWS-OS 6.x */ | ||
| 2 | |||
| 3 | #include "usg5-4-2.h" | ||
| 4 | |||
| 5 | #define NEWSOS6 | ||
| 6 | #define HAVE_TEXT_START | ||