Initial Commit
[packages] / xemacs-packages / calc / macedit.el
1 ;; Keyboard macro editor for GNU Emacs.  Version 1.05.
2 ;; Copyright (C) 1990, 1991, 1992, 1993 Free Software Foundation, Inc.
3 ;; Written by Dave Gillespie, daveg@synaptics.com.
4
5 ;; This file is part of GNU Emacs.
6
7 ;; GNU Emacs is distributed in the hope that it will be useful,
8 ;; but WITHOUT ANY WARRANTY.  No author or distributor
9 ;; accepts responsibility to anyone for the consequences of using it
10 ;; or for whether it serves any particular purpose or works at all,
11 ;; unless he says so in writing.  Refer to the GNU Emacs General Public
12 ;; License for full details.
13
14 ;; Everyone is granted permission to copy, modify and redistribute
15 ;; GNU Emacs, but only under the conditions described in the
16 ;; GNU Emacs General Public License.   A copy of this license is
17 ;; supposed to have been given to you along with GNU Emacs so you
18 ;; can know your rights and responsibilities.  It should be in a
19 ;; file named COPYING.  Among other things, the copyright notice
20 ;; and this notice must be preserved on all copies.
21
22 ;; Installation:
23 ;;   (autoload 'edit-kbd-macro "macedit" "Edit a named keyboard macro" t)
24 ;;   (autoload 'edit-last-kbd-macro "macedit" "Edit a keyboard macro" t)
25 ;;   (autoload 'read-kbd-macro "macedit" "Parse region as keyboard macro" t)
26
27 ;; Note: In XEmacs (at least) these functions are defined in
28 ;; `edmacro.el' so as to not pollute the namespace they have been
29 ;; commented out here. youngs@xemacs.org 2002-04-30
30
31 ;; To use, type `M-x edit-last-kbd-macro' to edit the most recently
32 ;; defined keyboard macro.  If you have used `M-x name-last-kbd-macro'
33 ;; to give a keyboard macro a name, type `M-x edit-kbd-macro' to edit
34 ;; the macro by name.  When you are done editing, type `C-c C-c' to
35 ;; record your changes back into the original keyboard macro.
36
37
38
39
40 ;;; The user-level commands for editing macros.
41
42 ;; These functions are all defined in `edmacro.el'. youngs@xemacs.org
43 ;; 2002-04-30
44
45 ;; (defun edit-last-kbd-macro (&optional prefix buffer hook)
46 ;;   "Edit the most recently defined keyboard macro."
47 ;;   (interactive "P")
48 ;;   (MacEdit-edit-macro last-kbd-macro
49 ;;                    (function (lambda (x arg) (setq last-kbd-macro x)))
50 ;;                    prefix buffer hook)
51 ;; )
52
53
54 ;; (defun edit-kbd-macro (cmd &optional prefix buffer hook in-hook out-hook)
55 ;;   "Edit a keyboard macro which has been assigned a name by name-last-kbd-macro.
56 ;; \(See also edit-last-kbd-macro.)"
57 ;;   (interactive "CCommand name: \nP")
58 ;;   (and cmd
59 ;;        (MacEdit-edit-macro (if in-hook
60 ;;                             (funcall in-hook cmd)
61 ;;                           (symbol-function cmd))
62 ;;                         (or out-hook
63 ;;                             (list 'lambda '(x arg)
64 ;;                                   (list 'fset
65 ;;                                         (list 'quote cmd)
66 ;;                                         'x)))
67 ;;                         prefix buffer hook cmd))
68 ;; )
69
70
71 ;; (defun read-kbd-macro (start &optional end)
72 ;;   "Read the region as a keyboard macro definition.
73 ;; The region is interpreted as spelled-out keystrokes, e.g., `M-x abc RET'.
74 ;; The resulting macro is installed as the \"current\" keyboard macro.
75
76 ;; Symbols:  RET, SPC, TAB, DEL, LFD, NUL; C-key; M-key.  (Must be uppercase.)
77 ;;           REM marks the rest of a line as a comment.
78 ;;           Whitespace is ignored; other characters are copied into the macro."
79 ;;   (interactive "r")
80 ;;   (if (stringp start)
81 ;;       (setq last-kbd-macro (MacEdit-parse-keys start))
82 ;;     (setq last-kbd-macro (MacEdit-parse-keys (buffer-substring start end)))
83 ;;     (if (and (string-match "\\`\C-x(" last-kbd-macro)
84 ;;           (string-match "\C-x)\\'" last-kbd-macro))
85 ;;      (setq last-kbd-macro (substring last-kbd-macro 2 -2))))
86 ;; )
87
88
89
90
91 ;;; Formatting a keyboard macro as human-readable text.
92
93 (defun MacEdit-print-macro (macro-str local-map)
94   (let ((save-map (current-local-map))
95         (print-escape-newlines t)
96         key-symbol key-str key-last prefix-arg this-prefix)
97     (unwind-protect
98         (progn
99           (use-local-map local-map)
100           (while (MacEdit-peek-char)
101             (MacEdit-read-key)
102             (setq this-prefix prefix-arg)
103             (or (memq key-symbol '(digit-argument
104                                    negative-argument
105                                    universal-argument))
106                 (null prefix-arg)
107                 (progn
108                   (cond ((consp prefix-arg)
109                          (insert (format "prefix-arg (%d)\n"
110                                          (car prefix-arg))))
111                         ((eq prefix-arg '-)
112                          (insert "prefix-arg -\n"))
113                         ((numberp prefix-arg)
114                          (insert (format "prefix-arg %d\n" prefix-arg))))
115                   (setq prefix-arg nil)))
116             (cond ((null key-symbol)
117                    (insert "type \"")
118                    (MacEdit-insert-string macro-str)
119                    (insert "\"\n")
120                    (setq macro-str ""))
121                   ((stringp key-symbol)   ; key defined by another kbd macro
122                    (insert "type \"")
123                    (MacEdit-insert-string key-symbol)
124                    (insert "\"\n"))
125                   ((eq key-symbol 'digit-argument)
126                    (MacEdit-prefix-arg key-last nil prefix-arg))
127                   ((eq key-symbol 'negative-argument)
128                    (MacEdit-prefix-arg ?- nil prefix-arg))
129                   ((eq key-symbol 'universal-argument)
130                    (let* ((c-u 4) (argstartchar key-last)
131                           (char (MacEdit-read-char)))
132                      (while (= char argstartchar)
133                        (setq c-u (* 4 c-u)
134                              char (MacEdit-read-char)))
135                      (MacEdit-prefix-arg char c-u nil)))
136                   ((eq key-symbol 'self-insert-command)
137                    (insert "insert ")
138                    (if (and (>= key-last 32) (<= key-last 126))
139                        (let ((str ""))
140                          (while (or (and (eq key-symbol
141                                              'self-insert-command)
142                                          (< (length str) 60)
143                                          (>= key-last 32)
144                                          (<= key-last 126))
145                                     (and (memq key-symbol
146                                                '(backward-delete-char
147                                                  delete-backward-char
148                                                  backward-delete-char-untabify))
149                                          (> (length str) 0)))
150                            (if (eq key-symbol 'self-insert-command)
151                                (setq str (concat str
152                                                  (char-to-string key-last)))
153                              (setq str (substring str 0 -1)))
154                            (MacEdit-read-key))
155                          (insert "\"" str "\"\n")
156                          (MacEdit-unread-chars key-str))
157                      (insert "\"")
158                      (MacEdit-insert-string (char-to-string key-last))
159                      (insert "\"\n")))
160                   ((and (eq key-symbol 'quoted-insert)
161                         (MacEdit-peek-char))
162                    (insert "quoted-insert\n")
163                    (let ((ch (MacEdit-read-char))
164                          ch2)
165                      (if (and (>= ch ?0) (<= ch ?7))
166                          (progn
167                            (setq ch (- ch ?0)
168                                  ch2 (MacEdit-read-char))
169                            (if ch2
170                                (if (and (>= ch2 ?0) (<= ch2 ?7))
171                                    (progn
172                                      (setq ch (+ (* ch 8) (- ch2 ?0))
173                                            ch2 (MacEdit-read-char))
174                                      (if ch2
175                                          (if (and (>= ch2 ?0) (<= ch2 ?7))
176                                              (setq ch (+ (* ch 8) (- ch2 ?0)))
177                                            (MacEdit-unread-chars ch2))))
178                                  (MacEdit-unread-chars ch2)))))
179                      (if (or (and (>= ch ?0) (<= ch ?7))
180                              (< ch 32) (> ch 126))
181                          (insert (format "type \"\\%03o\"\n" ch))
182                        (insert "type \"" (char-to-string ch) "\"\n"))))
183                   ((memq key-symbol '(isearch-forward
184                                       isearch-backward
185                                       isearch-forward-regexp
186                                       isearch-backward-regexp))
187                    (insert (symbol-name key-symbol) "\n")
188                    (MacEdit-isearch-argument))
189                   ((eq key-symbol 'execute-extended-command)
190                    (MacEdit-read-argument obarray 'commandp))
191                   (t
192                    (let ((cust (get key-symbol 'MacEdit-print)))
193                      (if cust
194                          (funcall cust)
195                        (insert (symbol-name key-symbol))
196                        (indent-to 30)
197                        (insert " # ")
198                        (MacEdit-insert-string key-str)
199                        (insert "\n")
200                        (let ((int (MacEdit-get-interactive key-symbol)))
201                          (if (string-match "\\`\\*" int)
202                              (setq int (substring int 1)))
203                          (while (> (length int) 0)
204                            (cond ((= (aref int 0) ?a)
205                                   (MacEdit-read-argument
206                                    obarray nil))
207                                  ((memq (aref int 0) '(?b ?B ?D ?f ?F ?n
208                                                           ?s ?S ?x ?X))
209                                   (MacEdit-read-argument))
210                                  ((and (= (aref int 0) ?c)
211                                        (MacEdit-peek-char))
212                                   (insert "type \"")
213                                   (MacEdit-insert-string
214                                    (char-to-string
215                                     (MacEdit-read-char)))
216                                   (insert "\"\n"))
217                                  ((= (aref int 0) ?C)
218                                   (MacEdit-read-argument
219                                    obarray 'commandp))
220                                  ((= (aref int 0) ?k)
221                                   (MacEdit-read-key)
222                                   (if key-symbol
223                                       (progn
224                                         (insert "type \"")
225                                         (MacEdit-insert-string key-str)
226                                         (insert "\"\n"))
227                                     (MacEdit-unread-chars key-str)))
228                                  ((= (aref int 0) ?N)
229                                   (or this-prefix
230                                       (MacEdit-read-argument)))
231                                  ((= (aref int 0) ?v)
232                                   (MacEdit-read-argument
233                                    obarray 'user-variable-p)))
234                            (let ((nl (string-match "\n" int)))
235                              (setq int (if nl
236                                            (substring int (1+ nl))
237                                          "")))))))))))
238       (use-local-map save-map)))
239 )
240
241 (defun MacEdit-prefix-arg (char c-u value)
242   (let ((sign 1))
243     (if (and (numberp value) (< value 0))
244         (setq sign -1 value (- value)))
245     (if (eq value '-)
246         (setq sign -1 value nil))
247     (while (and char (= ?- char))
248       (setq sign (- sign) c-u nil)
249       (setq char (MacEdit-read-char)))
250     (while (and char (>= char ?0) (<= char ?9))
251       (setq value (+ (* (if (numberp value) value 0) 10) (- char ?0)) c-u nil)
252       (setq char (MacEdit-read-char)))
253     (setq prefix-arg
254           (cond (c-u (list c-u))
255                 ((numberp value) (* value sign))
256                 ((= sign -1) '-)))
257     (MacEdit-unread-chars char))
258 )
259
260 (defun MacEdit-insert-string (str)
261   (let ((i 0) j ch)
262     (while (< i (length str))
263       (if (and (> (setq ch (aref str i)) 127)
264                (< ch 160))
265           (progn
266             (setq ch (- ch 128))
267             (insert "\\M-")))
268       (if (< ch 32)
269           (cond ((= ch 8)  (insert "\\b"))
270                 ((= ch 9)  (insert "\\t"))
271                 ((= ch 10) (insert "\\n"))
272                 ((= ch 13) (insert "\\r"))
273                 ((= ch 27) (insert "\\e"))
274                 (t (insert "\\C-" (char-to-string (downcase (+ ch 64))))))
275         (if (< ch 127)
276             (if (or (= ch 34) (= ch 92))
277                 (insert "\\" (char-to-string ch))
278               (setq j i)
279               (while (and (< (setq i (1+ i)) (length str))
280                           (>= (setq ch (aref str i)) 32)
281                           (/= ch 34) (/= ch 92)
282                           (< ch 127)))
283               (insert (substring str j i))
284               (setq i (1- i)))
285           (if (memq ch '(?\177 ?\377))
286               (insert (format "\\%03o" ch))
287             (insert "\\M-" (char-to-string (- ch 128))))))
288       (setq i (1+ i))))
289 )
290
291 (defun MacEdit-lookup-key (map)
292   (let ((loc (and map (lookup-key map macro-str)))
293         (glob (lookup-key (current-global-map) macro-str))
294         (loc-str macro-str)
295         (glob-str macro-str))
296     (and (integerp loc)
297          (setq loc-str (substring macro-str 0 loc)
298                loc (lookup-key map loc-str)))
299     (and (consp loc)
300          (setq loc nil))
301     (or loc
302         (setq loc-str ""))
303     (and (integerp glob)
304          (setq glob-str (substring macro-str 0 glob)
305                glob (lookup-key (current-global-map) glob-str)))
306     (and (consp glob)
307          (setq glob nil))
308     (or glob
309         (setq glob-str ""))
310     (if (> (length glob-str) (length loc-str))
311         (setq key-symbol glob
312               key-str glob-str)
313       (setq key-symbol loc
314             key-str loc-str))
315     (setq key-last (and (> (length key-str) 0)
316                         (logand (aref key-str (1- (length key-str))) 127)))
317     key-symbol)
318 )
319
320 (defun MacEdit-read-argument (&optional obarray pred)   ;; currently ignored
321   (let ((str "")
322         (min-bsp 0)
323         (exec (eq key-symbol 'execute-extended-command))
324         str-base)
325     (while (progn
326              (MacEdit-lookup-key (current-global-map))
327              (or (and (eq key-symbol 'self-insert-command)
328                       (< (length str) 60))
329                  (memq key-symbol
330                             '(backward-delete-char
331                               delete-backward-char
332                               backward-delete-char-untabify))
333                  (eq key-last 9)))
334       (setq macro-str (substring macro-str (length key-str)))
335       (or (and (eq key-last 9)
336                obarray
337                (let ((comp (try-completion str obarray pred)))
338                  (and (stringp comp)
339                       (> (length comp) (length str))
340                       (setq str comp))))
341           (if (or (eq key-symbol 'self-insert-command)
342                   (and (or (eq key-last 9)
343                            (<= (length str) min-bsp))
344                        (setq min-bsp (+ (length str) (length key-str)))))
345               (setq str (concat str key-str))
346             (setq str (substring str 0 -1)))))
347     (setq str-base str
348           str (concat str key-str)
349           macro-str (substring macro-str (length key-str)))
350     (if exec
351         (let ((comp (try-completion str-base obarray pred)))
352           (if (if (stringp comp)
353                   (and (commandp (intern comp))
354                        (setq str-base comp))
355                 (commandp (intern str-base)))
356               (insert str-base "\n")
357             (insert "execute-extended-command\n")
358             (insert "type \"")
359             (MacEdit-insert-string str)
360             (insert "\"\n")))
361       (if (> (length str) 0)
362           (progn
363             (insert "type \"")
364             (MacEdit-insert-string str)
365             (insert "\"\n")))))
366 )
367
368 (defun MacEdit-isearch-argument ()
369   (let ((str "")
370         (min-bsp 0)
371         ch)
372     (while (and (setq ch (MacEdit-read-char))
373                 (or (<= ch 127) (not search-exit-option))
374                 (not (eq ch search-exit-char))
375                 (or (eq ch search-repeat-char)
376                     (eq ch search-reverse-char)
377                     (eq ch search-delete-char)
378                     (eq ch search-yank-word-char)
379                     (eq ch search-yank-line-char)
380                     (eq ch search-quote-char)
381                     (eq ch ?\r)
382                     (eq ch ?\t)
383                     (not search-exit-option)
384                     (and (/= ch 127) (>= ch 32))))
385       (if (and (eq ch search-quote-char)
386                (MacEdit-peek-char))
387           (setq str (concat str (char-to-string ch)
388                             (char-to-string (MacEdit-read-char)))
389                 min-bsp (length str))
390         (if (or (and (< ch 127) (>= ch 32))
391                 (eq ch search-yank-word-char)
392                 (eq ch search-yank-line-char)
393                 (and (or (not (eq ch search-delete-char))
394                          (<= (length str) min-bsp))
395                      (setq min-bsp (1+ (length str)))))
396             (setq str (concat str (char-to-string ch)))
397           (setq str (substring str 0 -1)))))
398     (if (eq ch search-exit-char)
399         (if (= (length str) 0)  ;; non-incremental search
400             (progn
401               (setq str (concat str (char-to-string ch)))
402               (and (eq (MacEdit-peek-char) ?\C-w)
403                    (progn
404                      (setq str (concat str "\C-w"))
405                      (MacEdit-read-char)))
406               (if (> (length str) 0)
407                   (progn
408                     (insert "type \"")
409                     (MacEdit-insert-string str)
410                     (insert "\"\n")))
411               (MacEdit-read-argument)
412               (setq str "")))
413       (MacEdit-unread-chars ch))
414     (if (> (length str) 0)
415         (progn
416           (insert "type \"")
417           (MacEdit-insert-string str)
418           (insert "\\e\"\n"))))
419 )
420
421 ;;; Get the next keystroke-sequence from the input stream.
422 ;;; Sets key-symbol, key-str, and key-last as a side effect.
423 (defun MacEdit-read-key ()
424   (MacEdit-lookup-key (current-local-map))
425   (and key-symbol
426        (setq macro-str (substring macro-str (length key-str))))
427 )
428
429 (defun MacEdit-peek-char ()
430   (and (> (length macro-str) 0)
431        (aref macro-str 0))
432 )
433
434 (defun MacEdit-read-char ()
435   (and (> (length macro-str) 0)
436        (prog1
437            (aref macro-str 0)
438          (setq macro-str (substring macro-str 1))))
439 )
440
441 (defun MacEdit-unread-chars (chars)
442   (and (integerp chars)
443        (setq chars (char-to-string chars)))
444   (and chars
445        (setq macro-str (concat chars macro-str)))
446 )
447
448 (defun MacEdit-dump (mac)
449   (set-mark-command nil)
450   (insert "\n\n")
451   (MacEdit-print-macro mac (current-local-map))
452 )
453
454
455
456 ;;; Parse a string of spelled-out keystrokes, as produced by key-description.
457
458 (defun MacEdit-parse-keys (str)
459   (let ((pos 0)
460         (mac "")
461         part)
462     (while (and (< pos (length str))
463                 (string-match "[^ \t\n]+" str pos))
464       (setq pos (match-end 0)
465             part (substring str (match-beginning 0) (match-end 0))
466             mac (concat mac
467                         (if (and (> (length part) 2)
468                                  (= (aref part 1) ?-)
469                                  (= (aref part 0) ?M))
470                             (progn
471                               (setq part (substring part 2))
472                               "\e")
473                           (if (and (> (length part) 4)
474                                    (= (aref part 0) ?C)
475                                    (= (aref part 1) ?-)
476                                    (= (aref part 2) ?M)
477                                    (= (aref part 3) ?-))
478                               (progn
479                                 (setq part (concat "C-" (substring part 4)))
480                                 "\e")
481                             ""))
482                         (or (cdr (assoc part '( ( "NUL" . "\0" )
483                                                 ( "RET" . "\r" )
484                                                 ( "LFD" . "\n" )
485                                                 ( "TAB" . "\t" )
486                                                 ( "ESC" . "\e" )
487                                                 ( "SPC" . " " )
488                                                 ( "DEL" . "\177" )
489                                                 ( "C-?" . "\177" )
490                                                 ( "C-2" . "\0" )
491                                                 ( "C-SPC" . "\0") )))
492                             (and (equal part "REM")
493                                  (setq pos (or (string-match "\n" str pos)
494                                                (length str)))
495                                  "")
496                             (and (= (length part) 3)
497                                  (= (aref part 0) ?C)
498                                  (= (aref part 1) ?-)
499                                  (char-to-string (logand (aref part 2) 31)))
500                             part))))
501     mac)
502 )
503
504
505
506
507 ;;; Parse a keyboard macro description in MacEdit-print-macro's format.
508
509 (defun MacEdit-read-macro (&optional map)
510   (or map (setq map (current-local-map)))
511   (let ((macro-str ""))
512     (while (not (progn
513                   (skip-chars-forward " \t\n")
514                   (eobp)))
515       (cond ((looking-at "#"))   ;; comment
516             ((looking-at "prefix-arg[ \t]*-[ \t]*\n")
517              (MacEdit-append-chars "\C-u-"))
518             ((looking-at "prefix-arg[ \t]*\\(-?[0-9]+\\)[ \t]*\n")
519              (MacEdit-append-chars (concat "\C-u" (MacEdit-match-string 1))))
520             ((looking-at "prefix-arg[ \t]*(\\([0-9]+\\))[ \t]*\n")
521              (let ((val (string-to-int (MacEdit-match-string 1))))
522                (while (> val 1)
523                  (or (= (% val 4) 0)
524                      (error "Bad prefix argument value"))
525                  (MacEdit-append-chars "\C-u")
526                  (setq val (/ val 4)))))
527             ((looking-at "prefix-arg")
528              (error "Bad prefix argument syntax"))
529             ((looking-at "insert ")
530              (forward-char 7)
531              (MacEdit-append-chars (read (current-buffer)))
532              (if (< (current-column) 7)
533                  (forward-line -1)))
534             ((looking-at "type ")
535              (forward-char 5)
536              (MacEdit-append-chars (read (current-buffer)))
537              (if (< (current-column) 5)
538                  (forward-line -1)))
539             ((looking-at "keys \\(.*\\)\n")
540              (goto-char (1- (match-end 0)))
541              (MacEdit-append-chars (MacEdit-parse-keys
542                                     (buffer-substring (match-beginning 1)
543                                                       (match-end 1)))))
544             ((looking-at "\\([-a-zA-z0-9_]+\\)[ \t]*\\(.*\\)\n")
545              (let* ((func (intern (MacEdit-match-string 1)))
546                     (arg (MacEdit-match-string 2))
547                     (cust (get func 'MacEdit-read)))
548                (if cust
549                    (funcall cust arg)
550                  (or (commandp func)
551                      (error "Not an Emacs command"))
552                  (or (equal arg "")
553                      (string-match "\\`#" arg)
554                      (error "Unexpected argument to command"))
555                  (let ((keys
556                         (or (where-is-internal func map t)
557                             (where-is-internal func (current-global-map) t))))
558                    (if keys
559                        (MacEdit-append-chars keys)
560                      (MacEdit-append-chars (concat "\ex"
561                                                    (symbol-name func)
562                                                    "\n")))))))
563             (t (error "Syntax error")))
564       (forward-line 1))
565     macro-str)
566 )
567
568 (defun MacEdit-append-chars (chars)
569   (setq macro-str (concat macro-str chars))
570 )
571
572 (defun MacEdit-match-string (n)
573   (if (match-beginning n)
574       (buffer-substring (match-beginning n) (match-end n))
575     "")
576 )
577
578
579
580 (defun MacEdit-get-interactive (func)
581   (if (symbolp func)
582       (let ((cust (get func 'MacEdit-interactive)))
583         (if cust
584             cust
585           (MacEdit-get-interactive (symbol-function func))))
586     (or (and (eq (car-safe func) 'lambda)
587              (let ((int (if (consp (nth 2 func))
588                             (nth 2 func)
589                           (nth 3 func))))
590                (and (eq (car-safe int) 'interactive)
591                     (stringp (nth 1 int))
592                     (nth 1 int))))
593         ""))
594 )
595
596 (put 'search-forward           'MacEdit-interactive "s")
597 (put 'search-backward          'MacEdit-interactive "s")
598 (put 'word-search-forward      'MacEdit-interactive "s")
599 (put 'word-search-backward     'MacEdit-interactive "s")
600 (put 're-search-forward        'MacEdit-interactive "s")
601 (put 're-search-backward       'MacEdit-interactive "s")
602 (put 'switch-to-buffer         'MacEdit-interactive "B")
603 (put 'kill-buffer              'MacEdit-interactive "B")
604 (put 'rename-buffer            'MacEdit-interactive "B\nB")
605 (put 'goto-char                'MacEdit-interactive "N")
606 (put 'global-set-key           'MacEdit-interactive "k\nC")
607 (put 'global-unset-key         'MacEdit-interactive "k")
608 (put 'local-set-key            'MacEdit-interactive "k\nC")
609 (put 'local-unset-key          'MacEdit-interactive "k")
610
611 ;;; Think about kbd-macro-query
612
613
614
615 ;;; Edit a keyboard macro in another buffer.
616 ;;; (Prefix argument is currently ignored.)
617
618 (defun MacEdit-edit-macro (mac repl &optional prefix buffer hook arg)
619   (or (stringp mac)
620       (error "Not a keyboard macro"))
621   (let ((oldbuf (current-buffer))
622         (from-calc (and (get-buffer-window "*Calculator*")
623                         (eq (lookup-key (current-global-map) "\e#")
624                             'calc-dispatch)))
625         (local (current-local-map))
626         (buf (get-buffer-create (or buffer "*Edit Macro*"))))
627     (set-buffer buf)
628     (kill-all-local-variables)
629     (use-local-map MacEdit-mode-map)
630     (setq buffer-read-only nil)
631     (setq major-mode 'MacEdit-mode)
632     (setq mode-name "Edit Macro")
633     (make-local-variable 'MacEdit-original-buffer)
634     (setq MacEdit-original-buffer oldbuf)
635     (make-local-variable 'MacEdit-replace-function)
636     (setq MacEdit-replace-function repl)
637     (make-local-variable 'MacEdit-replace-argument)
638     (setq MacEdit-replace-argument arg)
639     (make-local-variable 'MacEdit-finish-hook)
640     (setq MacEdit-finish-hook hook)
641     (erase-buffer)
642     (insert "# Keyboard Macro Editor.  Press "
643             (if from-calc "M-# M-#" "C-c C-c")
644             " to finish; press "
645             (if from-calc "M-# x" "C-x k RET")
646             " to cancel.\n")
647     (insert "# Original keys: " (key-description mac) "\n\n")
648     (message "Formatting keyboard macro...")
649     (MacEdit-print-macro mac local)
650     (switch-to-buffer buf)
651     (goto-char (point-min))
652     (forward-line 3)
653     (recenter '(4))
654     (set-buffer-modified-p nil)
655     (message "Formatting keyboard macro...done")
656     (run-hooks 'MacEdit-format-hook))
657 )
658
659 (defun MacEdit-finish-edit ()
660   (interactive)
661   (or (and (boundp 'MacEdit-original-buffer)
662            (boundp 'MacEdit-replace-function)
663            (boundp 'MacEdit-replace-argument)
664            (boundp 'MacEdit-finish-hook)
665            (eq major-mode 'MacEdit-mode))
666       (error "This command is valid only in buffers created by edit-kbd-macro."))
667   (let ((buf (current-buffer))
668         (str (buffer-string))
669         (func MacEdit-replace-function)
670         (arg MacEdit-replace-argument)
671         (hook MacEdit-finish-hook))
672     (goto-char (point-min))
673     (and (buffer-modified-p)
674          func
675          (progn
676            (message "Compiling keyboard macro...")
677            (run-hooks 'MacEdit-compile-hook)
678            (let ((mac (MacEdit-read-macro
679                        (and (buffer-name MacEdit-original-buffer)
680                             (save-excursion
681                               (set-buffer MacEdit-original-buffer)
682                               (current-local-map))))))
683              (and (buffer-name MacEdit-original-buffer)
684                   (switch-to-buffer MacEdit-original-buffer))
685              (funcall func mac arg))
686            (message "Compiling keyboard macro...done")))
687     (kill-buffer buf)
688     (if hook
689         (funcall hook arg)))
690 )
691
692 (defun MacEdit-cancel-edit ()
693   (interactive)
694   (if (eq major-mode 'MacEdit-mode)
695       (set-buffer-modified-p nil))
696   (MacEdit-finish-edit)
697   (message "(Cancelled)")
698 )
699
700 (defun MacEdit-mode ()
701   "Keyboard Macro Editing mode.  Press C-c C-c to save and exit.
702 To abort the edit, just kill this buffer with C-x k RET.
703
704 The keyboard macro is represented as a series of M-x style command names.
705 Keystrokes which do not correspond to simple M-x commands are written as
706 \"type\" commands.  When you press C-c C-c, MacEdit converts each command
707 back into a suitable keystroke sequence; \"type\" commands are converted
708 directly back into keystrokes."
709   (interactive)
710   (error "This mode can be enabled only by edit-kbd-macro or edit-last-kbd-macro.")
711 )
712 (put 'MacEdit-mode 'mode-class 'special)
713
714 (defvar MacEdit-mode-map nil)
715 (if MacEdit-mode-map
716     ()
717   (setq MacEdit-mode-map (make-sparse-keymap))
718   (define-key MacEdit-mode-map "\C-c\C-c" 'MacEdit-finish-edit)
719 )
720