Commit | Line | Data |
---|---|---|
5d5fa02f | 1 | ;;; crisp.el --- CRiSP/Brief Emacs emulator |
d21b2085 | 2 | |
d59c3137 | 3 | ;; Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003, 2004, |
8b72699e | 4 | ;; 2005, 2006, 2007, 2008 Free Software Foundation, Inc. |
5e33ba39 | 5 | |
da061c5e | 6 | ;; Author: Gary D. Foster <Gary.Foster@Corp.Sun.COM> |
7aa5f6cf | 7 | ;; Keywords: emulations brief crisp |
5e33ba39 RS |
8 | |
9 | ;; This file is part of GNU Emacs. | |
10 | ||
ed0f493f | 11 | ;; GNU Emacs is free software: you can redistribute it and/or modify |
5e33ba39 | 12 | ;; it under the terms of the GNU General Public License as published by |
ed0f493f GM |
13 | ;; the Free Software Foundation, either version 3 of the License, or |
14 | ;; (at your option) any later version. | |
5e33ba39 RS |
15 | |
16 | ;; GNU Emacs 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 | |
ed0f493f | 22 | ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. |
5e33ba39 RS |
23 | |
24 | ;;; Commentary: | |
25 | ||
7aa5f6cf KH |
26 | ;; Keybindings and minor functions to duplicate the functionality and |
27 | ;; finger-feel of the CRiSP/Brief editor. This package is designed to | |
28 | ;; facilitate transitioning from Brief to (XE|E)macs with a minimum | |
29 | ;; amount of hassles. | |
5e33ba39 | 30 | |
7aa5f6cf KH |
31 | ;; Enable this package by putting (require 'crisp) in your .emacs and |
32 | ;; use M-x crisp-mode to toggle it on or off. | |
5e33ba39 | 33 | |
7aa5f6cf KH |
34 | ;; This package will automatically load the scroll-all.el package if |
35 | ;; you put (setq crisp-load-scroll-all t) in your .emacs before | |
36 | ;; loading this package. If this feature is enabled, it will bind | |
37 | ;; meta-f1 to the scroll-all mode toggle. The scroll-all package | |
38 | ;; duplicates the scroll-alling feature in CRiSP. | |
5e33ba39 | 39 | |
7aa5f6cf KH |
40 | ;; Also, the default keybindings for brief/CRiSP override the M-x |
41 | ;; key to exit the editor. If you don't like this functionality, you | |
42 | ;; can prevent this behavior (or redefine it dynamically) by setting | |
43 | ;; the value of `crisp-override-meta-x' either in your .emacs or | |
3da6cc26 RS |
44 | ;; interactively. The default setting is t, which means that M-x will |
45 | ;; by default run `save-buffers-kill-emacs' instead of the command | |
46 | ;; `execute-extended-command'. | |
5e33ba39 | 47 | |
d21b2085 RS |
48 | ;; Finally, if you want to change the string displayed in the modeline |
49 | ;; when this mode is in effect, override the definition of | |
50 | ;; `crisp-mode-modeline-string' in your .emacs. The default value is | |
51 | ;; " *Crisp*" which may be a bit lengthy if you have a lot of things | |
52 | ;; being displayed there. | |
53 | ||
5e33ba39 RS |
54 | ;; All these overrides should go *before* the (require 'crisp) statement. |
55 | ||
5d5fa02f | 56 | ;;; Code: |
7aa5f6cf | 57 | |
7aa5f6cf KH |
58 | ;; local variables |
59 | ||
0b5bb3ec SE |
60 | (defgroup crisp nil |
61 | "Emulator for CRiSP and Brief key bindings." | |
62 | :prefix "crisp-" | |
63 | :group 'emulations) | |
64 | ||
7aa5f6cf | 65 | (defvar crisp-mode-map (let ((map (make-sparse-keymap))) |
7aa5f6cf | 66 | map) |
d21b2085 | 67 | "Local keymap for CRiSP emulation mode. |
7aa5f6cf KH |
68 | All the bindings are done here instead of globally to try and be |
69 | nice to the world.") | |
5e33ba39 | 70 | |
0b5bb3ec | 71 | (defcustom crisp-mode-modeline-string " *CRiSP*" |
7aa5f6cf | 72 | "*String to display in the modeline when CRiSP emulation mode is enabled." |
0b5bb3ec SE |
73 | :type 'string |
74 | :group 'crisp) | |
d21b2085 | 75 | |
3da6cc26 RS |
76 | ;;;###autoload |
77 | (defcustom crisp-mode nil | |
d21b2085 RS |
78 | "Track status of CRiSP emulation mode. |
79 | A value of nil means CRiSP mode is not enabled. A value of t | |
3da6cc26 RS |
80 | indicates CRiSP mode is enabled. |
81 | ||
82 | Setting this variable directly does not take effect; | |
83 | use either M-x customize or the function `crisp-mode'." | |
84 | :set (lambda (symbol value) (crisp-mode (if value 1 0))) | |
6110ea0a | 85 | :initialize 'custom-initialize-default |
3da6cc26 RS |
86 | :require 'crisp |
87 | :version "20.4" | |
0b5bb3ec SE |
88 | :type 'boolean |
89 | :group 'crisp) | |
d21b2085 | 90 | |
0b5bb3ec | 91 | (defcustom crisp-override-meta-x t |
7aa5f6cf | 92 | "*Controls overriding the normal Emacs M-x key binding in the CRiSP emulator. |
28085971 | 93 | Normally the CRiSP emulator rebinds M-x to `save-buffers-exit-emacs', and |
7aa5f6cf KH |
94 | provides the usual M-x functionality on the F10 key. If this variable |
95 | is non-nil, M-x will exit Emacs." | |
0b5bb3ec SE |
96 | :type 'boolean |
97 | :group 'crisp) | |
5e33ba39 | 98 | |
7aa5f6cf KH |
99 | (defcustom crisp-load-scroll-all nil |
100 | "Controls loading of the Scroll Lock in the CRiSP emulator. | |
101 | Its default behavior is to load and enable the Scroll Lock minor mode | |
5e33ba39 RS |
102 | package when enabling the CRiSP emulator. |
103 | ||
104 | If this variable is nil when you start the CRiSP emulator, it | |
7aa5f6cf | 105 | does not load the scroll-all package." |
0b5bb3ec SE |
106 | :type 'boolean |
107 | :group 'crisp) | |
5e33ba39 | 108 | |
0b5bb3ec | 109 | (defcustom crisp-load-hook nil |
7aa5f6cf | 110 | "Hooks to run after loading the CRiSP emulator package." |
0b5bb3ec SE |
111 | :type 'hook |
112 | :group 'crisp) | |
d21b2085 | 113 | |
3da6cc26 RS |
114 | (defcustom crisp-mode-hook nil |
115 | "Hook run by the function `crisp-mode'." | |
116 | :type 'hook | |
117 | :group 'crisp) | |
118 | ||
119 | (defconst crisp-version "1.34" | |
7aa5f6cf | 120 | "The version of the CRiSP emulator.") |
d21b2085 | 121 | |
7aa5f6cf KH |
122 | (defconst crisp-mode-help-address "gfoster@suzieq.ml.org" |
123 | "The email address of the CRiSP mode author/maintainer.") | |
f4ff0fb4 | 124 | |
7aa5f6cf KH |
125 | ;; Silence the byte-compiler. |
126 | (defvar crisp-last-last-command nil | |
28085971 | 127 | "The previous value of `last-command'.") |
7aa5f6cf KH |
128 | |
129 | ;; The cut and paste routines are different between XEmacs and Emacs | |
130 | ;; so we need to set up aliases for the functions. | |
131 | ||
28085971 RS |
132 | (defalias 'crisp-set-clipboard |
133 | (if (fboundp 'clipboard-kill-ring-save) | |
134 | 'clipboard-kill-ring-save | |
135 | 'copy-primary-selection)) | |
136 | ||
137 | (defalias 'crisp-kill-region | |
138 | (if (fboundp 'clipboard-kill-region) | |
139 | 'clipboard-kill-region | |
140 | 'kill-primary-selection)) | |
141 | ||
142 | (defalias 'crisp-yank-clipboard | |
143 | (if (fboundp 'clipboard-yank) | |
144 | 'clipboard-yank | |
145 | 'yank-clipboard-selection)) | |
7aa5f6cf | 146 | |
28085971 | 147 | (defun crisp-region-active () |
7aa5f6cf | 148 | "Compatibility function to test for an active region." |
a445370f | 149 | (if (featurep 'xemacs) |
7aa5f6cf KH |
150 | zmacs-region-active-p |
151 | mark-active)) | |
5e33ba39 RS |
152 | |
153 | ;; and now the keymap defines | |
154 | ||
155 | (define-key crisp-mode-map [(f1)] 'other-window) | |
156 | ||
157 | (define-key crisp-mode-map [(f2) (down)] 'enlarge-window) | |
158 | (define-key crisp-mode-map [(f2) (left)] 'shrink-window-horizontally) | |
159 | (define-key crisp-mode-map [(f2) (right)] 'enlarge-window-horizontally) | |
160 | (define-key crisp-mode-map [(f2) (up)] 'shrink-window) | |
161 | (define-key crisp-mode-map [(f3) (down)] 'split-window-vertically) | |
162 | (define-key crisp-mode-map [(f3) (right)] 'split-window-horizontally) | |
163 | ||
164 | (define-key crisp-mode-map [(f4)] 'delete-window) | |
165 | (define-key crisp-mode-map [(control f4)] 'delete-other-windows) | |
166 | ||
167 | (define-key crisp-mode-map [(f5)] 'search-forward-regexp) | |
168 | (define-key crisp-mode-map [(f19)] 'search-forward-regexp) | |
7aa5f6cf | 169 | (define-key crisp-mode-map [(meta f5)] 'search-backward-regexp) |
5e33ba39 RS |
170 | |
171 | (define-key crisp-mode-map [(f6)] 'query-replace) | |
172 | ||
173 | (define-key crisp-mode-map [(f7)] 'start-kbd-macro) | |
7aa5f6cf | 174 | (define-key crisp-mode-map [(meta f7)] 'end-kbd-macro) |
5e33ba39 RS |
175 | |
176 | (define-key crisp-mode-map [(f8)] 'call-last-kbd-macro) | |
177 | (define-key crisp-mode-map [(meta f8)] 'save-kbd-macro) | |
178 | ||
179 | (define-key crisp-mode-map [(f9)] 'find-file) | |
7aa5f6cf | 180 | (define-key crisp-mode-map [(meta f9)] 'load-library) |
5e33ba39 RS |
181 | |
182 | (define-key crisp-mode-map [(f10)] 'execute-extended-command) | |
7aa5f6cf KH |
183 | (define-key crisp-mode-map [(meta f10)] 'compile) |
184 | ||
185 | (define-key crisp-mode-map [(SunF37)] 'kill-buffer) | |
186 | (define-key crisp-mode-map [(kp-add)] 'crisp-copy-line) | |
187 | (define-key crisp-mode-map [(kp-subtract)] 'crisp-kill-line) | |
188 | ;; just to cover all the bases (GNU Emacs, for instance) | |
189 | (define-key crisp-mode-map [(f24)] 'crisp-kill-line) | |
28085971 RS |
190 | (define-key crisp-mode-map [(insert)] 'crisp-yank-clipboard) |
191 | (define-key crisp-mode-map [(f16)] 'crisp-set-clipboard) ; copy on Sun5 kbd | |
3da6cc26 | 192 | (define-key crisp-mode-map [(f20)] 'crisp-kill-region) ; cut on Sun5 kbd |
28085971 | 193 | (define-key crisp-mode-map [(f18)] 'crisp-yank-clipboard) ; paste on Sun5 kbd |
7aa5f6cf KH |
194 | |
195 | (define-key crisp-mode-map [(control f)] 'fill-paragraph-or-region) | |
196 | (define-key crisp-mode-map [(meta d)] (lambda () | |
197 | (interactive) | |
198 | (beginning-of-line) (kill-line))) | |
5e33ba39 RS |
199 | (define-key crisp-mode-map [(meta e)] 'find-file) |
200 | (define-key crisp-mode-map [(meta g)] 'goto-line) | |
201 | (define-key crisp-mode-map [(meta h)] 'help) | |
202 | (define-key crisp-mode-map [(meta i)] 'overwrite-mode) | |
d21b2085 | 203 | (define-key crisp-mode-map [(meta j)] 'bookmark-jump) |
7aa5f6cf KH |
204 | (define-key crisp-mode-map [(meta l)] 'crisp-mark-line) |
205 | (define-key crisp-mode-map [(meta m)] 'set-mark-command) | |
206 | (define-key crisp-mode-map [(meta n)] 'bury-buffer) | |
207 | (define-key crisp-mode-map [(meta p)] 'crisp-unbury-buffer) | |
5e33ba39 RS |
208 | (define-key crisp-mode-map [(meta u)] 'advertised-undo) |
209 | (define-key crisp-mode-map [(f14)] 'advertised-undo) | |
210 | (define-key crisp-mode-map [(meta w)] 'save-buffer) | |
7aa5f6cf KH |
211 | (define-key crisp-mode-map [(meta x)] 'crisp-meta-x-wrapper) |
212 | (define-key crisp-mode-map [(meta ?0)] (lambda () | |
213 | (interactive) | |
214 | (bookmark-set "0"))) | |
215 | (define-key crisp-mode-map [(meta ?1)] (lambda () | |
216 | (interactive) | |
217 | (bookmark-set "1"))) | |
218 | (define-key crisp-mode-map [(meta ?2)] (lambda () | |
219 | (interactive) | |
220 | (bookmark-set "2"))) | |
221 | (define-key crisp-mode-map [(meta ?3)] (lambda () | |
222 | (interactive) | |
223 | (bookmark-set "3"))) | |
224 | (define-key crisp-mode-map [(meta ?4)] (lambda () | |
225 | (interactive) | |
226 | (bookmark-set "4"))) | |
227 | (define-key crisp-mode-map [(meta ?5)] (lambda () | |
228 | (interactive) | |
229 | (bookmark-set "5"))) | |
230 | (define-key crisp-mode-map [(meta ?6)] (lambda () | |
231 | (interactive) | |
232 | (bookmark-set "6"))) | |
233 | (define-key crisp-mode-map [(meta ?7)] (lambda () | |
234 | (interactive) | |
235 | (bookmark-set "7"))) | |
236 | (define-key crisp-mode-map [(meta ?8)] (lambda () | |
237 | (interactive) | |
238 | (bookmark-set "8"))) | |
239 | (define-key crisp-mode-map [(meta ?9)] (lambda () | |
240 | (interactive) | |
241 | (bookmark-set "9"))) | |
242 | ||
243 | (define-key crisp-mode-map [(shift delete)] 'kill-word) | |
5e33ba39 | 244 | (define-key crisp-mode-map [(shift backspace)] 'backward-kill-word) |
7aa5f6cf KH |
245 | (define-key crisp-mode-map [(control left)] 'backward-word) |
246 | (define-key crisp-mode-map [(control right)] 'forward-word) | |
247 | ||
248 | (define-key crisp-mode-map [(home)] 'crisp-home) | |
249 | (define-key crisp-mode-map [(control home)] (lambda () | |
250 | (interactive) | |
251 | (move-to-window-line 0))) | |
252 | (define-key crisp-mode-map [(meta home)] 'beginning-of-line) | |
253 | (define-key crisp-mode-map [(end)] 'crisp-end) | |
254 | (define-key crisp-mode-map [(control end)] (lambda () | |
255 | (interactive) | |
256 | (move-to-window-line -1))) | |
257 | (define-key crisp-mode-map [(meta end)] 'end-of-line) | |
258 | ||
7aa5f6cf KH |
259 | (defun crisp-version (&optional arg) |
260 | "Version number of the CRiSP emulator package. | |
261 | If ARG, insert results at point." | |
262 | (interactive "P") | |
263 | (let ((foo (concat "CRiSP version " crisp-version))) | |
264 | (if arg | |
265 | (insert (message foo)) | |
266 | (message foo)))) | |
267 | ||
268 | (defun crisp-mark-line (arg) | |
3da6cc26 RS |
269 | "Set mark at the end of the line. |
270 | Arg works as in `end-of-line'." | |
7aa5f6cf | 271 | (interactive "p") |
79b65a08 RS |
272 | (let (newmark) |
273 | (save-excursion | |
28085971 | 274 | (end-of-line arg) |
79b65a08 RS |
275 | (setq newmark (point))) |
276 | (push-mark newmark nil t))) | |
7aa5f6cf KH |
277 | |
278 | (defun crisp-kill-line (arg) | |
279 | "Mark and kill line(s). | |
280 | Marks from point to end of the current line (honoring prefix arguments), | |
281 | copies the region to the kill ring and clipboard, and then deletes it." | |
282 | (interactive "*p") | |
28085971 RS |
283 | (if (crisp-region-active) |
284 | (call-interactively 'crisp-kill-region) | |
7aa5f6cf | 285 | (crisp-mark-line arg) |
28085971 | 286 | (call-interactively 'crisp-kill-region))) |
7aa5f6cf KH |
287 | |
288 | (defun crisp-copy-line (arg) | |
289 | "Mark and copy line(s). | |
290 | Marks from point to end of the current line (honoring prefix arguments), | |
291 | copies the region to the kill ring and clipboard, and then deactivates | |
292 | the region." | |
293 | (interactive "*p") | |
28085971 RS |
294 | (if (crisp-region-active) |
295 | (call-interactively 'crisp-set-clipboard) | |
7aa5f6cf | 296 | (crisp-mark-line arg) |
28085971 | 297 | (call-interactively 'crisp-set-clipboard)) |
7aa5f6cf KH |
298 | ;; clear the region after the operation is complete |
299 | ;; XEmacs does this automagically, Emacs doesn't. | |
300 | (if (boundp 'mark-active) | |
301 | (setq mark-active nil))) | |
5e33ba39 | 302 | |
5e33ba39 | 303 | (defun crisp-home () |
7aa5f6cf | 304 | "\"Home\" the point, the way CRiSP would do it. |
5e33ba39 RS |
305 | The first use moves point to beginning of the line. Second |
306 | consecutive use moves point to beginning of the screen. Third | |
307 | consecutive use moves point to the beginning of the buffer." | |
308 | (interactive nil) | |
309 | (cond | |
f4ff0fb4 RS |
310 | ((and (eq last-command 'crisp-home) |
311 | (eq crisp-last-last-command 'crisp-home)) | |
d21b2085 | 312 | (goto-char (point-min))) |
5e33ba39 | 313 | ((eq last-command 'crisp-home) |
d21b2085 | 314 | (move-to-window-line 0)) |
5e33ba39 | 315 | (t |
d21b2085 | 316 | (beginning-of-line))) |
f4ff0fb4 | 317 | (setq crisp-last-last-command last-command)) |
5e33ba39 RS |
318 | |
319 | (defun crisp-end () | |
7aa5f6cf | 320 | "\"End\" the point, the way CRiSP would do it. |
5e33ba39 RS |
321 | The first use moves point to end of the line. Second |
322 | consecutive use moves point to the end of the screen. Third | |
323 | consecutive use moves point to the end of the buffer." | |
324 | (interactive nil) | |
325 | (cond | |
7aa5f6cf KH |
326 | ((and (eq last-command 'crisp-end) |
327 | (eq crisp-last-last-command 'crisp-end)) | |
d21b2085 | 328 | (goto-char (point-max))) |
5e33ba39 RS |
329 | ((eq last-command 'crisp-end) |
330 | (move-to-window-line -1) | |
d21b2085 | 331 | (end-of-line)) |
5e33ba39 | 332 | (t |
d21b2085 | 333 | (end-of-line))) |
f4ff0fb4 | 334 | (setq crisp-last-last-command last-command)) |
5e33ba39 | 335 | |
7aa5f6cf | 336 | (defun crisp-unbury-buffer () |
3da6cc26 | 337 | "Go back one buffer." |
7aa5f6cf KH |
338 | (interactive) |
339 | (switch-to-buffer (car (last (buffer-list))))) | |
a1506d29 | 340 | |
7aa5f6cf KH |
341 | (defun crisp-meta-x-wrapper () |
342 | "Wrapper function to conditionally override the normal M-x bindings. | |
343 | When `crisp-override-meta-x' is non-nil, M-x will exit Emacs (the | |
344 | normal CRiSP binding) and when it is nil M-x will run | |
345 | `execute-extended-command' (the normal Emacs binding)." | |
346 | (interactive) | |
347 | (if crisp-override-meta-x | |
348 | (save-buffers-kill-emacs) | |
349 | (call-interactively 'execute-extended-command))) | |
350 | ||
3da6cc26 | 351 | ;;;###autoload |
7aa5f6cf | 352 | (defun crisp-mode (&optional arg) |
4e968343 | 353 | "Toggle CRiSP/Brief emulation minor mode. |
7aa5f6cf KH |
354 | With ARG, turn CRiSP mode on if ARG is positive, off otherwise." |
355 | (interactive "P") | |
3da6cc26 RS |
356 | (setq crisp-mode (if (null arg) |
357 | (not crisp-mode) | |
358 | (> (prefix-numeric-value arg) 0))) | |
359 | (when crisp-mode | |
6110ea0a KH |
360 | ;; Force transient-mark-mode, so that the marking routines work as |
361 | ;; expected. If the user turns off transient mark mode, most | |
362 | ;; things will still work fine except the crisp-(copy|kill) | |
363 | ;; functions won't work quite as nicely when regions are marked | |
364 | ;; differently and could really confuse people. Caveat emptor. | |
365 | (if (fboundp 'transient-mark-mode) | |
366 | (transient-mark-mode t)) | |
a06e220d RS |
367 | (if crisp-load-scroll-all |
368 | (require 'scroll-all)) | |
369 | (if (featurep 'scroll-all) | |
370 | (define-key crisp-mode-map [(meta f1)] 'scroll-all-mode)) | |
6110ea0a | 371 | (run-hooks 'crisp-mode-hook))) |
5e33ba39 | 372 | |
4e968343 DL |
373 | ;; People might use Apropos on `brief'. |
374 | ;;;###autoload | |
375 | (defalias 'brief-mode 'crisp-mode) | |
376 | ||
7aa5f6cf | 377 | (if (fboundp 'add-minor-mode) |
3da6cc26 RS |
378 | (add-minor-mode 'crisp-mode 'crisp-mode-modeline-string |
379 | crisp-mode-map nil 'crisp-mode) | |
380 | (or (assq 'crisp-mode minor-mode-alist) | |
7aa5f6cf | 381 | (setq minor-mode-alist |
3da6cc26 RS |
382 | (cons '(crisp-mode crisp-mode-modeline-string) minor-mode-alist))) |
383 | (or (assq 'crisp-mode minor-mode-map-alist) | |
384 | (setq minor-mode-map-alist (cons (cons 'crisp-mode crisp-mode-map) | |
385 | minor-mode-map-alist)))) | |
7aa5f6cf | 386 | |
504feff5 | 387 | ;; Interaction with other packages. |
34e99b2e KS |
388 | (put 'crisp-home 'CUA 'move) |
389 | (put 'crisp-end 'CUA 'move) | |
504feff5 | 390 | |
6110ea0a | 391 | (run-hooks 'crisp-load-hook) |
5e33ba39 RS |
392 | (provide 'crisp) |
393 | ||
cbee283d | 394 | ;; arch-tag: e5369375-fafb-4240-b7ae-4cb460ef05ee |
8c7d9baf | 395 | ;;; crisp.el ends here |