aboutsummaryrefslogtreecommitdiffstats
path: root/lisp/subr.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/subr.el')
-rw-r--r--lisp/subr.el319
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.
384In other words, OLDDEF is replaced with NEWDEF where ever it appears. 375In other words, OLDDEF is replaced with NEWDEF where ever it appears.
385Alternatively, if optional fourth argument OLDMAP is specified, we redefine 376Alternatively, if optional fourth argument OLDMAP is specified, we redefine
386in KEYMAP as NEWDEF those keys which are defined as OLDDEF in OLDMAP." 377in KEYMAP as NEWDEF those keys which are defined as OLDDEF in OLDMAP.
378
379For 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."
1880See also `with-temp-file' and `with-output-to-string'." 1801See 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.
2596However, if the change since last echo area update is too small
2597or not enough time has passed, then do nothing (see
2598`make-progress-reporter' for details).
2599
2600First parameter, REPORTER, should be the result of a call to
2601`make-progress-reporter'. Second, VALUE, determines the actual
2602progress of operation; it must be between MIN-VALUE and MAX-VALUE
2603as passed to `make-progress-reporter'.
2604
2605This function is very inexpensive, you may not bother how often
2606you 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
2615MESSAGE is shown in the echo area. When at least 1% of operation
2616is complete, the exact percentage will be appended to the
2617MESSAGE. When you call `progress-reporter-done', word \"done\"
2618is printed after the MESSAGE. You can change MESSAGE of an
2619existing progress reporter with `progress-reporter-force-update'.
2620
2621MIN-VALUE and MAX-VALUE designate starting (0% complete) and
2622final (100% complete) states of operation. The latter should be
2623larger; if this is not the case, then simply negate all values.
2624Optional CURRENT-VALUE specifies the progress by the moment you
2625call this function. You should omit it or set it to nil in most
2626cases since it defaults to MIN-VALUE.
2627
2628Optional MIN-CHANGE determines the minimal change in percents to
2629report (default is 1%.) Optional MIN-TIME specifies the minimal
2630time before echo area updates (default is 0.2 seconds.) If
2631`float-time' function is not present, then time is not tracked
2632at all. If OS is not capable of measuring fractions of seconds,
2633then 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
2653First two parameters are the same as for
2654`progress-reporter-update'. Optional NEW-MESSAGE allows you to
2655change 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