diff options
Diffstat (limited to 'lisp/subr.el')
| -rw-r--r-- | lisp/subr.el | 319 |
1 files changed, 183 insertions, 136 deletions
diff --git a/lisp/subr.el b/lisp/subr.el index e5a967310d5..eb4577b1a8d 100644 --- a/lisp/subr.el +++ b/lisp/subr.el | |||
| @@ -367,15 +367,6 @@ but optional second arg NODIGITS non-nil treats them like other chars." | |||
| 367 | (define-key map (char-to-string loop) 'digit-argument) | 367 | (define-key map (char-to-string loop) 'digit-argument) |
| 368 | (setq loop (1+ loop)))))) | 368 | (setq loop (1+ loop)))))) |
| 369 | 369 | ||
| 370 | ;Moved to keymap.c | ||
| 371 | ;(defun copy-keymap (keymap) | ||
| 372 | ; "Return a copy of KEYMAP" | ||
| 373 | ; (while (not (keymapp keymap)) | ||
| 374 | ; (setq keymap (signal 'wrong-type-argument (list 'keymapp keymap)))) | ||
| 375 | ; (if (vectorp keymap) | ||
| 376 | ; (copy-sequence keymap) | ||
| 377 | ; (copy-alist keymap))) | ||
| 378 | |||
| 379 | (defvar key-substitution-in-progress nil | 370 | (defvar key-substitution-in-progress nil |
| 380 | "Used internally by substitute-key-definition.") | 371 | "Used internally by substitute-key-definition.") |
| 381 | 372 | ||
| @@ -383,7 +374,10 @@ but optional second arg NODIGITS non-nil treats them like other chars." | |||
| 383 | "Replace OLDDEF with NEWDEF for any keys in KEYMAP now defined as OLDDEF. | 374 | "Replace OLDDEF with NEWDEF for any keys in KEYMAP now defined as OLDDEF. |
| 384 | In other words, OLDDEF is replaced with NEWDEF where ever it appears. | 375 | In other words, OLDDEF is replaced with NEWDEF where ever it appears. |
| 385 | Alternatively, if optional fourth argument OLDMAP is specified, we redefine | 376 | Alternatively, if optional fourth argument OLDMAP is specified, we redefine |
| 386 | in KEYMAP as NEWDEF those keys which are defined as OLDDEF in OLDMAP." | 377 | in KEYMAP as NEWDEF those keys which are defined as OLDDEF in OLDMAP. |
| 378 | |||
| 379 | For most uses, it is simpler and safer to use command remappping like this: | ||
| 380 | \(define-key KEYMAP [remap OLDDEF] NEWDEF)" | ||
| 387 | ;; Don't document PREFIX in the doc string because we don't want to | 381 | ;; Don't document PREFIX in the doc string because we don't want to |
| 388 | ;; advertise it. It's meant for recursive calls only. Here's its | 382 | ;; advertise it. It's meant for recursive calls only. Here's its |
| 389 | ;; meaning | 383 | ;; meaning |
| @@ -393,126 +387,54 @@ in KEYMAP as NEWDEF those keys which are defined as OLDDEF in OLDMAP." | |||
| 393 | ;; original key, with PREFIX added at the front. | 387 | ;; original key, with PREFIX added at the front. |
| 394 | (or prefix (setq prefix "")) | 388 | (or prefix (setq prefix "")) |
| 395 | (let* ((scan (or oldmap keymap)) | 389 | (let* ((scan (or oldmap keymap)) |
| 396 | (vec1 (vector nil)) | 390 | (prefix1 (vconcat prefix [nil])) |
| 397 | (prefix1 (vconcat prefix vec1)) | ||
| 398 | (key-substitution-in-progress | 391 | (key-substitution-in-progress |
| 399 | (cons scan key-substitution-in-progress))) | 392 | (cons scan key-substitution-in-progress))) |
| 400 | ;; Scan OLDMAP, finding each char or event-symbol that | 393 | ;; Scan OLDMAP, finding each char or event-symbol that |
| 401 | ;; has any definition, and act on it with hack-key. | 394 | ;; has any definition, and act on it with hack-key. |
| 402 | (while (consp scan) | 395 | (map-keymap |
| 403 | (if (consp (car scan)) | 396 | (lambda (char defn) |
| 404 | (let ((char (car (car scan))) | 397 | (aset prefix1 (length prefix) char) |
| 405 | (defn (cdr (car scan)))) | 398 | (substitute-key-definition-key defn olddef newdef prefix1 keymap)) |
| 406 | ;; The inside of this let duplicates exactly | 399 | scan))) |
| 407 | ;; the inside of the following let that handles array elements. | 400 | |
| 408 | (aset vec1 0 char) | 401 | (defun substitute-key-definition-key (defn olddef newdef prefix keymap) |
| 409 | (aset prefix1 (length prefix) char) | 402 | (let (inner-def skipped menu-item) |
| 410 | (let (inner-def skipped) | 403 | ;; Find the actual command name within the binding. |
| 411 | ;; Skip past menu-prompt. | 404 | (if (eq (car-safe defn) 'menu-item) |
| 412 | (while (stringp (car-safe defn)) | 405 | (setq menu-item defn defn (nth 2 defn)) |
| 413 | (setq skipped (cons (car defn) skipped)) | 406 | ;; Skip past menu-prompt. |
| 414 | (setq defn (cdr defn))) | 407 | (while (stringp (car-safe defn)) |
| 415 | ;; Skip past cached key-equivalence data for menu items. | 408 | (push (pop defn) skipped)) |
| 416 | (and (consp defn) (consp (car defn)) | 409 | ;; Skip past cached key-equivalence data for menu items. |
| 417 | (setq defn (cdr defn))) | 410 | (if (consp (car-safe defn)) |
| 418 | (setq inner-def defn) | 411 | (setq defn (cdr defn)))) |
| 419 | ;; Look past a symbol that names a keymap. | 412 | (if (or (eq defn olddef) |
| 420 | (while (and (symbolp inner-def) | 413 | ;; Compare with equal if definition is a key sequence. |
| 421 | (fboundp inner-def)) | 414 | ;; That is useful for operating on function-key-map. |
| 422 | (setq inner-def (symbol-function inner-def))) | 415 | (and (or (stringp defn) (vectorp defn)) |
| 423 | (if (or (eq defn olddef) | 416 | (equal defn olddef))) |
| 424 | ;; Compare with equal if definition is a key sequence. | 417 | (define-key keymap prefix |
| 425 | ;; That is useful for operating on function-key-map. | 418 | (if menu-item |
| 426 | (and (or (stringp defn) (vectorp defn)) | 419 | (let ((copy (copy-sequence menu-item))) |
| 427 | (equal defn olddef))) | 420 | (setcar (nthcdr 2 copy) newdef) |
| 428 | (define-key keymap prefix1 (nconc (nreverse skipped) newdef)) | 421 | copy) |
| 429 | (if (and (keymapp defn) | 422 | (nconc (nreverse skipped) newdef))) |
| 430 | ;; Avoid recursively scanning | 423 | ;; Look past a symbol that names a keymap. |
| 431 | ;; where KEYMAP does not have a submap. | 424 | (setq inner-def |
| 432 | (let ((elt (lookup-key keymap prefix1))) | 425 | (condition-case nil (indirect-function defn) (error defn))) |
| 433 | (or (null elt) | 426 | ;; For nested keymaps, we use `inner-def' rather than `defn' so as to |
| 434 | (keymapp elt))) | 427 | ;; avoid autoloading a keymap. This is mostly done to preserve the |
| 435 | ;; Avoid recursively rescanning keymap being scanned. | 428 | ;; original non-autoloading behavior of pre-map-keymap times. |
| 436 | (not (memq inner-def | 429 | (if (and (keymapp inner-def) |
| 437 | key-substitution-in-progress))) | 430 | ;; Avoid recursively scanning |
| 438 | ;; If this one isn't being scanned already, | 431 | ;; where KEYMAP does not have a submap. |
| 439 | ;; scan it now. | 432 | (let ((elt (lookup-key keymap prefix))) |
| 440 | (substitute-key-definition olddef newdef keymap | 433 | (or (null elt) (natnump elt) (keymapp elt))) |
| 441 | inner-def | 434 | ;; Avoid recursively rescanning keymap being scanned. |
| 442 | prefix1))))) | 435 | (not (memq inner-def key-substitution-in-progress))) |
| 443 | (if (vectorp (car scan)) | 436 | ;; If this one isn't being scanned already, scan it now. |
| 444 | (let* ((array (car scan)) | 437 | (substitute-key-definition olddef newdef keymap inner-def prefix))))) |
| 445 | (len (length array)) | ||
| 446 | (i 0)) | ||
| 447 | (while (< i len) | ||
| 448 | (let ((char i) (defn (aref array i))) | ||
| 449 | ;; The inside of this let duplicates exactly | ||
| 450 | ;; the inside of the previous let. | ||
| 451 | (aset vec1 0 char) | ||
| 452 | (aset prefix1 (length prefix) char) | ||
| 453 | (let (inner-def skipped) | ||
| 454 | ;; Skip past menu-prompt. | ||
| 455 | (while (stringp (car-safe defn)) | ||
| 456 | (setq skipped (cons (car defn) skipped)) | ||
| 457 | (setq defn (cdr defn))) | ||
| 458 | (and (consp defn) (consp (car defn)) | ||
| 459 | (setq defn (cdr defn))) | ||
| 460 | (setq inner-def defn) | ||
| 461 | (while (and (symbolp inner-def) | ||
| 462 | (fboundp inner-def)) | ||
| 463 | (setq inner-def (symbol-function inner-def))) | ||
| 464 | (if (or (eq defn olddef) | ||
| 465 | (and (or (stringp defn) (vectorp defn)) | ||
| 466 | (equal defn olddef))) | ||
| 467 | (define-key keymap prefix1 | ||
| 468 | (nconc (nreverse skipped) newdef)) | ||
| 469 | (if (and (keymapp defn) | ||
| 470 | (let ((elt (lookup-key keymap prefix1))) | ||
| 471 | (or (null elt) | ||
| 472 | (keymapp elt))) | ||
| 473 | (not (memq inner-def | ||
| 474 | key-substitution-in-progress))) | ||
| 475 | (substitute-key-definition olddef newdef keymap | ||
| 476 | inner-def | ||
| 477 | prefix1))))) | ||
| 478 | (setq i (1+ i)))) | ||
| 479 | (if (char-table-p (car scan)) | ||
| 480 | (map-char-table | ||
| 481 | (function (lambda (char defn) | ||
| 482 | (let () | ||
| 483 | ;; The inside of this let duplicates exactly | ||
| 484 | ;; the inside of the previous let, | ||
| 485 | ;; except that it uses set-char-table-range | ||
| 486 | ;; instead of define-key. | ||
| 487 | (aset vec1 0 char) | ||
| 488 | (aset prefix1 (length prefix) char) | ||
| 489 | (let (inner-def skipped) | ||
| 490 | ;; Skip past menu-prompt. | ||
| 491 | (while (stringp (car-safe defn)) | ||
| 492 | (setq skipped (cons (car defn) skipped)) | ||
| 493 | (setq defn (cdr defn))) | ||
| 494 | (and (consp defn) (consp (car defn)) | ||
| 495 | (setq defn (cdr defn))) | ||
| 496 | (setq inner-def defn) | ||
| 497 | (while (and (symbolp inner-def) | ||
| 498 | (fboundp inner-def)) | ||
| 499 | (setq inner-def (symbol-function inner-def))) | ||
| 500 | (if (or (eq defn olddef) | ||
| 501 | (and (or (stringp defn) (vectorp defn)) | ||
| 502 | (equal defn olddef))) | ||
| 503 | (define-key keymap prefix1 | ||
| 504 | (nconc (nreverse skipped) newdef)) | ||
| 505 | (if (and (keymapp defn) | ||
| 506 | (let ((elt (lookup-key keymap prefix1))) | ||
| 507 | (or (null elt) | ||
| 508 | (keymapp elt))) | ||
| 509 | (not (memq inner-def | ||
| 510 | key-substitution-in-progress))) | ||
| 511 | (substitute-key-definition olddef newdef keymap | ||
| 512 | inner-def | ||
| 513 | prefix1))))))) | ||
| 514 | (car scan))))) | ||
| 515 | (setq scan (cdr scan))))) | ||
| 516 | 438 | ||
| 517 | (defun define-key-after (keymap key definition &optional after) | 439 | (defun define-key-after (keymap key definition &optional after) |
| 518 | "Add binding in KEYMAP for KEY => DEFINITION, right after AFTER's binding. | 440 | "Add binding in KEYMAP for KEY => DEFINITION, right after AFTER's binding. |
| @@ -658,19 +580,19 @@ even when EVENT actually has modifiers." | |||
| 658 | (char (logand type (lognot (logior ?\M-\^@ ?\C-\^@ ?\S-\^@ | 580 | (char (logand type (lognot (logior ?\M-\^@ ?\C-\^@ ?\S-\^@ |
| 659 | ?\H-\^@ ?\s-\^@ ?\A-\^@))))) | 581 | ?\H-\^@ ?\s-\^@ ?\A-\^@))))) |
| 660 | (if (not (zerop (logand type ?\M-\^@))) | 582 | (if (not (zerop (logand type ?\M-\^@))) |
| 661 | (setq list (cons 'meta list))) | 583 | (push 'meta list)) |
| 662 | (if (or (not (zerop (logand type ?\C-\^@))) | 584 | (if (or (not (zerop (logand type ?\C-\^@))) |
| 663 | (< char 32)) | 585 | (< char 32)) |
| 664 | (setq list (cons 'control list))) | 586 | (push 'control list)) |
| 665 | (if (or (not (zerop (logand type ?\S-\^@))) | 587 | (if (or (not (zerop (logand type ?\S-\^@))) |
| 666 | (/= char (downcase char))) | 588 | (/= char (downcase char))) |
| 667 | (setq list (cons 'shift list))) | 589 | (push 'shift list)) |
| 668 | (or (zerop (logand type ?\H-\^@)) | 590 | (or (zerop (logand type ?\H-\^@)) |
| 669 | (setq list (cons 'hyper list))) | 591 | (push 'hyper list)) |
| 670 | (or (zerop (logand type ?\s-\^@)) | 592 | (or (zerop (logand type ?\s-\^@)) |
| 671 | (setq list (cons 'super list))) | 593 | (push 'super list)) |
| 672 | (or (zerop (logand type ?\A-\^@)) | 594 | (or (zerop (logand type ?\A-\^@)) |
| 673 | (setq list (cons 'alt list))) | 595 | (push 'alt list)) |
| 674 | list)))) | 596 | list)))) |
| 675 | 597 | ||
| 676 | (defun event-basic-type (event) | 598 | (defun event-basic-type (event) |
| @@ -688,8 +610,7 @@ in the current Emacs session, then this function may return nil." | |||
| 688 | 610 | ||
| 689 | (defsubst mouse-movement-p (object) | 611 | (defsubst mouse-movement-p (object) |
| 690 | "Return non-nil if OBJECT is a mouse movement event." | 612 | "Return non-nil if OBJECT is a mouse movement event." |
| 691 | (and (consp object) | 613 | (eq (car-safe object) 'mouse-movement)) |
| 692 | (eq (car object) 'mouse-movement))) | ||
| 693 | 614 | ||
| 694 | (defsubst event-start (event) | 615 | (defsubst event-start (event) |
| 695 | "Return the starting position of EVENT. | 616 | "Return the starting position of EVENT. |
| @@ -1880,8 +1801,7 @@ Use a MESSAGE of \"\" to temporarily clear the echo area." | |||
| 1880 | See also `with-temp-file' and `with-output-to-string'." | 1801 | See also `with-temp-file' and `with-output-to-string'." |
| 1881 | (declare (indent 0) (debug t)) | 1802 | (declare (indent 0) (debug t)) |
| 1882 | (let ((temp-buffer (make-symbol "temp-buffer"))) | 1803 | (let ((temp-buffer (make-symbol "temp-buffer"))) |
| 1883 | `(let ((,temp-buffer | 1804 | `(let ((,temp-buffer (generate-new-buffer " *temp*"))) |
| 1884 | (get-buffer-create (generate-new-buffer-name " *temp*")))) | ||
| 1885 | (unwind-protect | 1805 | (unwind-protect |
| 1886 | (with-current-buffer ,temp-buffer | 1806 | (with-current-buffer ,temp-buffer |
| 1887 | ,@body) | 1807 | ,@body) |
| @@ -2652,5 +2572,132 @@ The properties used on SYMBOL are `composefunc', `sendfunc', | |||
| 2652 | (put symbol 'abortfunc (or abortfunc 'kill-buffer)) | 2572 | (put symbol 'abortfunc (or abortfunc 'kill-buffer)) |
| 2653 | (put symbol 'hookvar (or hookvar 'mail-send-hook))) | 2573 | (put symbol 'hookvar (or hookvar 'mail-send-hook))) |
| 2654 | 2574 | ||
| 2575 | ;; Standardized progress reporting | ||
| 2576 | |||
| 2577 | ;; Progress reporter has the following structure: | ||
| 2578 | ;; | ||
| 2579 | ;; (NEXT-UPDATE-VALUE . [NEXT-UPDATE-TIME | ||
| 2580 | ;; MIN-VALUE | ||
| 2581 | ;; MAX-VALUE | ||
| 2582 | ;; MESSAGE | ||
| 2583 | ;; MIN-CHANGE | ||
| 2584 | ;; MIN-TIME]) | ||
| 2585 | ;; | ||
| 2586 | ;; This weirdeness is for optimization reasons: we want | ||
| 2587 | ;; `progress-reporter-update' to be as fast as possible, so | ||
| 2588 | ;; `(car reporter)' is better than `(aref reporter 0)'. | ||
| 2589 | ;; | ||
| 2590 | ;; NEXT-UPDATE-TIME is a float. While `float-time' loses a couple | ||
| 2591 | ;; digits of precision, it doesn't really matter here. On the other | ||
| 2592 | ;; hand, it greatly simplifies the code. | ||
| 2593 | |||
| 2594 | (defsubst progress-reporter-update (reporter value) | ||
| 2595 | "Report progress of an operation in the echo area. | ||
| 2596 | However, if the change since last echo area update is too small | ||
| 2597 | or not enough time has passed, then do nothing (see | ||
| 2598 | `make-progress-reporter' for details). | ||
| 2599 | |||
| 2600 | First parameter, REPORTER, should be the result of a call to | ||
| 2601 | `make-progress-reporter'. Second, VALUE, determines the actual | ||
| 2602 | progress of operation; it must be between MIN-VALUE and MAX-VALUE | ||
| 2603 | as passed to `make-progress-reporter'. | ||
| 2604 | |||
| 2605 | This function is very inexpensive, you may not bother how often | ||
| 2606 | you call it." | ||
| 2607 | (when (>= value (car reporter)) | ||
| 2608 | (progress-reporter-do-update reporter value))) | ||
| 2609 | |||
| 2610 | (defun make-progress-reporter (message min-value max-value | ||
| 2611 | &optional current-value | ||
| 2612 | min-change min-time) | ||
| 2613 | "Return progress reporter object usage with `progress-reporter-update'. | ||
| 2614 | |||
| 2615 | MESSAGE is shown in the echo area. When at least 1% of operation | ||
| 2616 | is complete, the exact percentage will be appended to the | ||
| 2617 | MESSAGE. When you call `progress-reporter-done', word \"done\" | ||
| 2618 | is printed after the MESSAGE. You can change MESSAGE of an | ||
| 2619 | existing progress reporter with `progress-reporter-force-update'. | ||
| 2620 | |||
| 2621 | MIN-VALUE and MAX-VALUE designate starting (0% complete) and | ||
| 2622 | final (100% complete) states of operation. The latter should be | ||
| 2623 | larger; if this is not the case, then simply negate all values. | ||
| 2624 | Optional CURRENT-VALUE specifies the progress by the moment you | ||
| 2625 | call this function. You should omit it or set it to nil in most | ||
| 2626 | cases since it defaults to MIN-VALUE. | ||
| 2627 | |||
| 2628 | Optional MIN-CHANGE determines the minimal change in percents to | ||
| 2629 | report (default is 1%.) Optional MIN-TIME specifies the minimal | ||
| 2630 | time before echo area updates (default is 0.2 seconds.) If | ||
| 2631 | `float-time' function is not present, then time is not tracked | ||
| 2632 | at all. If OS is not capable of measuring fractions of seconds, | ||
| 2633 | then this parameter is effectively rounded up." | ||
| 2634 | |||
| 2635 | (unless min-time | ||
| 2636 | (setq min-time 0.2)) | ||
| 2637 | (let ((reporter | ||
| 2638 | (cons min-value ;; Force a call to `message' now | ||
| 2639 | (vector (if (and (fboundp 'float-time) | ||
| 2640 | (>= min-time 0.02)) | ||
| 2641 | (float-time) nil) | ||
| 2642 | min-value | ||
| 2643 | max-value | ||
| 2644 | message | ||
| 2645 | (if min-change (max (min min-change 50) 1) 1) | ||
| 2646 | min-time)))) | ||
| 2647 | (progress-reporter-update reporter (or current-value min-value)) | ||
| 2648 | reporter)) | ||
| 2649 | |||
| 2650 | (defun progress-reporter-force-update (reporter value &optional new-message) | ||
| 2651 | "Report progress of an operation in the echo area unconditionally. | ||
| 2652 | |||
| 2653 | First two parameters are the same as for | ||
| 2654 | `progress-reporter-update'. Optional NEW-MESSAGE allows you to | ||
| 2655 | change the displayed message." | ||
| 2656 | (let ((parameters (cdr reporter))) | ||
| 2657 | (when new-message | ||
| 2658 | (aset parameters 3 new-message)) | ||
| 2659 | (when (aref parameters 0) | ||
| 2660 | (aset parameters 0 (float-time))) | ||
| 2661 | (progress-reporter-do-update reporter value))) | ||
| 2662 | |||
| 2663 | (defun progress-reporter-do-update (reporter value) | ||
| 2664 | (let* ((parameters (cdr reporter)) | ||
| 2665 | (min-value (aref parameters 1)) | ||
| 2666 | (max-value (aref parameters 2)) | ||
| 2667 | (one-percent (/ (- max-value min-value) 100.0)) | ||
| 2668 | (percentage (truncate (/ (- value min-value) one-percent))) | ||
| 2669 | (update-time (aref parameters 0)) | ||
| 2670 | (current-time (float-time)) | ||
| 2671 | (enough-time-passed | ||
| 2672 | ;; See if enough time has passed since the last update. | ||
| 2673 | (or (not update-time) | ||
| 2674 | (when (>= current-time update-time) | ||
| 2675 | ;; Calculate time for the next update | ||
| 2676 | (aset parameters 0 (+ update-time (aref parameters 5))))))) | ||
| 2677 | ;; | ||
| 2678 | ;; Calculate NEXT-UPDATE-VALUE. If we are not going to print | ||
| 2679 | ;; message this time because not enough time has passed, then use | ||
| 2680 | ;; 1 instead of MIN-CHANGE. This makes delays between echo area | ||
| 2681 | ;; updates closer to MIN-TIME. | ||
| 2682 | (setcar reporter | ||
| 2683 | (min (+ min-value (* (+ percentage | ||
| 2684 | (if enough-time-passed | ||
| 2685 | (aref parameters 4) ;; MIN-CHANGE | ||
| 2686 | 1)) | ||
| 2687 | one-percent)) | ||
| 2688 | max-value)) | ||
| 2689 | (when (integerp value) | ||
| 2690 | (setcar reporter (ceiling (car reporter)))) | ||
| 2691 | ;; | ||
| 2692 | ;; Only print message if enough time has passed | ||
| 2693 | (when enough-time-passed | ||
| 2694 | (if (> percentage 0) | ||
| 2695 | (message "%s%d%%" (aref parameters 3) percentage) | ||
| 2696 | (message "%s" (aref parameters 3)))))) | ||
| 2697 | |||
| 2698 | (defun progress-reporter-done (reporter) | ||
| 2699 | "Print reporter's message followed by word \"done\" in echo area." | ||
| 2700 | (message "%sdone" (aref (cdr reporter) 3))) | ||
| 2701 | |||
| 2655 | ;; arch-tag: f7e0e6e5-70aa-4897-ae72-7a3511ec40bc | 2702 | ;; arch-tag: f7e0e6e5-70aa-4897-ae72-7a3511ec40bc |
| 2656 | ;;; subr.el ends here | 2703 | ;;; subr.el ends here |