diff options
| author | Paul Eggert | 2011-04-09 11:42:31 -0700 |
|---|---|---|
| committer | Paul Eggert | 2011-04-09 11:42:31 -0700 |
| commit | 762f8d96719ba3e8a0e79d8bb99fe8e119fafb3a (patch) | |
| tree | 7b2fe40a89bf327ea8b9ad8265a6b6f27cacd2a7 /lisp | |
| parent | eb3f1cc8dfe6a96505f1c5f9174b2712998cb52f (diff) | |
| parent | 8546720e6f25eb988e8215de6678798053031440 (diff) | |
| download | emacs-762f8d96719ba3e8a0e79d8bb99fe8e119fafb3a.tar.gz emacs-762f8d96719ba3e8a0e79d8bb99fe8e119fafb3a.zip | |
Merge from mainline.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/ChangeLog | 118 | ||||
| -rw-r--r-- | lisp/bs.el | 4 | ||||
| -rw-r--r-- | lisp/cus-face.el | 2 | ||||
| -rw-r--r-- | lisp/doc-view.el | 76 | ||||
| -rw-r--r-- | lisp/emacs-lisp/cconv.el | 4 | ||||
| -rw-r--r-- | lisp/emacs-lisp/package.el | 460 | ||||
| -rw-r--r-- | lisp/emacs-lisp/tabulated-list.el | 355 | ||||
| -rw-r--r-- | lisp/files.el | 55 | ||||
| -rw-r--r-- | lisp/follow.el | 2 | ||||
| -rw-r--r-- | lisp/gnus/ChangeLog | 49 | ||||
| -rw-r--r-- | lisp/gnus/gnus-registry.el | 196 | ||||
| -rw-r--r-- | lisp/gnus/gnus-start.el | 6 | ||||
| -rw-r--r-- | lisp/gnus/registry.el | 20 | ||||
| -rw-r--r-- | lisp/help.el | 9 | ||||
| -rw-r--r-- | lisp/ls-lisp.el | 10 | ||||
| -rw-r--r-- | lisp/man.el | 3 | ||||
| -rw-r--r-- | lisp/net/browse-url.el | 3 | ||||
| -rw-r--r-- | lisp/net/rlogin.el | 70 | ||||
| -rw-r--r-- | lisp/play/morse.el | 2 | ||||
| -rw-r--r-- | lisp/replace.el | 25 | ||||
| -rw-r--r-- | lisp/saveplace.el | 2 | ||||
| -rw-r--r-- | lisp/simple.el | 90 | ||||
| -rw-r--r-- | lisp/vc/log-edit.el | 17 | ||||
| -rw-r--r-- | lisp/vc/vc-annotate.el | 2 |
24 files changed, 1098 insertions, 482 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index a526ca900a7..62dd255cabe 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,8 +1,122 @@ | |||
| 1 | 2011-04-07 Paul Eggert <eggert@cs.ucla.edu> | 1 | 2011-04-09 Paul Eggert <eggert@cs.ucla.edu> |
| 2 | 2 | ||
| 3 | Remove the doprnt implementation, as Emacs now uses vsnprintf. | 3 | Remove the doprnt implementation, as Emacs now uses vsnprintf. |
| 4 | * emacs-lisp/find-gc.el (find-gc-source-files): Remove doprnt.c. | 4 | * emacs-lisp/find-gc.el (find-gc-source-files): Remove doprnt.c. |
| 5 | 5 | ||
| 6 | 2011-04-08 Sho Nakatani <lay.sakura@gmail.com> | ||
| 7 | |||
| 8 | * doc-view.el (doc-view-fit-width-to-window) | ||
| 9 | (doc-view-fit-height-to-window, doc-view-fit-page-to-window): New | ||
| 10 | functions for fitting the shown image to the Emacs window size. | ||
| 11 | (doc-view-mode-map): Add bindings for the new functions. | ||
| 12 | |||
| 13 | 2011-03-24 Juanma Barranquero <lekktu@gmail.com> | ||
| 14 | |||
| 15 | * vc-annotate.el (vc-annotate-show-log-revision-at-line): | ||
| 16 | Fix typo in docstring. | ||
| 17 | |||
| 18 | 2011-04-08 Eli Zaretskii <eliz@gnu.org> | ||
| 19 | |||
| 20 | * files.el (file-size-human-readable): Produce one digit after | ||
| 21 | decimal, like "ls -lh" does. | ||
| 22 | |||
| 23 | * ls-lisp.el (ls-lisp-format-file-size): Allow for 7 characters in | ||
| 24 | the file size representation. | ||
| 25 | |||
| 26 | * simple.el (list-processes): If async subprocesses are not | ||
| 27 | available, error out with a clear error message. | ||
| 28 | |||
| 29 | 2011-04-08 Chong Yidong <cyd@stupidchicken.com> | ||
| 30 | |||
| 31 | * help.el (help-form-show): New function, to be called from C. | ||
| 32 | Put help-form output in a buffer named differently than *Help*. | ||
| 33 | |||
| 34 | 2011-04-08 Eli Zaretskii <eliz@gnu.org> | ||
| 35 | |||
| 36 | * files.el (file-size-human-readable): New function. | ||
| 37 | |||
| 38 | * ls-lisp.el (ls-lisp-format-file-size): Use it, instead of | ||
| 39 | computing the representation inline. Don't require `cl'. | ||
| 40 | |||
| 41 | 2011-04-08 Glenn Morris <rgm@gnu.org> | ||
| 42 | |||
| 43 | * man.el (Man-page-header-regexp): Solaris < 2.6 no longer supported. | ||
| 44 | |||
| 45 | * net/browse-url.el (browse-url-firefox): | ||
| 46 | Test system-type, not system-configuration. | ||
| 47 | |||
| 48 | * vc/log-edit.el (log-edit-empty-buffer-p): New function. | ||
| 49 | (log-edit-insert-cvs-template, log-edit-insert-cvs-rcstemplate): | ||
| 50 | Use log-edit-empty-buffer-p. (Bug#7598) | ||
| 51 | |||
| 52 | * net/rlogin.el (rlogin-process-connection-type): Simplify. | ||
| 53 | (rlogin-mode-map): Initialize in the defvar. | ||
| 54 | (rlogin): Use ignore-errors. | ||
| 55 | |||
| 56 | * replace.el (occur-mode-map): Some fixes for menu items. | ||
| 57 | |||
| 58 | 2011-04-07 Aaron S. Hawley <aaron.s.hawley@gmail.com> | ||
| 59 | |||
| 60 | * play/morse.el (denato-region): Handle varying case. (Bug#8386) | ||
| 61 | |||
| 62 | 2011-04-06 Chong Yidong <cyd@stupidchicken.com> | ||
| 63 | |||
| 64 | * emacs-lisp/cconv.el (cconv--analyse-use): Ignore "ignored" when | ||
| 65 | issuing unused warnings. | ||
| 66 | |||
| 67 | * emacs-lisp/tabulated-list.el (tabulated-list-print): Use lambda | ||
| 68 | macro directly. | ||
| 69 | |||
| 70 | * simple.el: Lisp reimplement of list-processes. Based on an | ||
| 71 | earlier reimplementation by Leo Liu, but using tabulated-list.el. | ||
| 72 | (process-menu-mode): New major mode. | ||
| 73 | (list-processes--refresh, list-processes): | ||
| 74 | (process-menu-visit-buffer): New functions. | ||
| 75 | |||
| 76 | * files.el (save-buffers-kill-emacs): Don't assume any return | ||
| 77 | value of list-processes, which is undocumented anyway. | ||
| 78 | |||
| 79 | 2011-04-06 Chong Yidong <cyd@stupidchicken.com> | ||
| 80 | |||
| 81 | * emacs-lisp/tabulated-list.el: New file. | ||
| 82 | |||
| 83 | * emacs-lisp/package.el: Use Tabulated List mode. | ||
| 84 | (package-menu-mode-map): Inherit from tabulated-list-mode-map. | ||
| 85 | (package-menu-mode): Derive from tabulated-list-mode. Set up the | ||
| 86 | table format using Tabulated List mode variables. | ||
| 87 | (package--push): New macro, replacing package-list-maybe-add. | ||
| 88 | (package-menu--generate): Use package--push. Renamed from | ||
| 89 | package--generate-package-list. | ||
| 90 | (package-menu-refresh, list-packages): Use it. | ||
| 91 | (package-menu--print-info): Renamed from package-print-package. | ||
| 92 | Return insertion data instead of inserting it directly. | ||
| 93 | (package-menu-describe-package, package-menu-execute): Use | ||
| 94 | tabulated-list-get-id. | ||
| 95 | (package-menu-mark-delete, package-menu-mark-install) | ||
| 96 | (package-menu-mark-unmark, package-menu-backup-unmark) | ||
| 97 | (package-menu-mark-obsolete-for-deletion): Use | ||
| 98 | tabulated-list-put-tag. | ||
| 99 | (package--list-packages, package-menu-revert) | ||
| 100 | (package-menu-get-package, package-menu-get-version) | ||
| 101 | (package-menu-sort-by-column): Functions deleted. | ||
| 102 | (package-menu-package-list, package-menu-sort-key): Vars deleted. | ||
| 103 | (package-menu--status-predicate, package-menu--version-predicate) | ||
| 104 | (package-menu--name-predicate) | ||
| 105 | (package-menu--description-predicate): Handle arguments in the | ||
| 106 | Tabulated List format. | ||
| 107 | (package-list-packages-no-fetch): Call list-packages. | ||
| 108 | |||
| 109 | 2011-04-06 Juanma Barranquero <lekktu@gmail.com> | ||
| 110 | |||
| 111 | * files.el (after-find-file-from-revert-buffer): Remove variable. | ||
| 112 | (after-find-file): Dont' bind it. | ||
| 113 | (revert-buffer-in-progress-p): New variable. | ||
| 114 | (revert-buffer): Bind it. | ||
| 115 | Pass nil for `after-find-file-from-revert-buffer'. | ||
| 116 | |||
| 117 | * saveplace.el (save-place-find-file-hook): Use new variable | ||
| 118 | `rever-buffer-in-progress-p', not `after-find-file-from-revert-buffer'. | ||
| 119 | |||
| 6 | 2011-04-06 Glenn Morris <rgm@gnu.org> | 120 | 2011-04-06 Glenn Morris <rgm@gnu.org> |
| 7 | 121 | ||
| 8 | * Makefile.in (AUTOGEN_VCS): New variable. | 122 | * Makefile.in (AUTOGEN_VCS): New variable. |
| @@ -575,7 +689,7 @@ | |||
| 575 | (emerge-protect-metachars): Quote correctly for ms-dos and | 689 | (emerge-protect-metachars): Quote correctly for ms-dos and |
| 576 | windows-nt systems. | 690 | windows-nt systems. |
| 577 | 691 | ||
| 578 | 2011-03-19 Ralph Schleicher <rs@ralph-schleicher.de> | 692 | 2011-03-19 Ralph Schleicher <rs@ralph-schleicher.de> (tiny change) |
| 579 | 693 | ||
| 580 | * info.el (info-initialize): Replace all uses of `:' with | 694 | * info.el (info-initialize): Replace all uses of `:' with |
| 581 | path-separator for compatibility with non-Unix systems. | 695 | path-separator for compatibility with non-Unix systems. |
diff --git a/lisp/bs.el b/lisp/bs.el index 72b3e4c6fef..6965af1368c 100644 --- a/lisp/bs.el +++ b/lisp/bs.el | |||
| @@ -40,7 +40,7 @@ | |||
| 40 | ;; | % vc-hooks.el 43605 Emacs-Lisp /usr/share/emacs/19.34/lisp$| | 40 | ;; | % vc-hooks.el 43605 Emacs-Lisp /usr/share/emacs/19.34/lisp$| |
| 41 | ;; ----------------------------------------------------------------------- | 41 | ;; ----------------------------------------------------------------------- |
| 42 | 42 | ||
| 43 | ;;; Quick Installation und Customization: | 43 | ;;; Quick Installation and Customization: |
| 44 | 44 | ||
| 45 | ;; To display the bs menu, do | 45 | ;; To display the bs menu, do |
| 46 | ;; M-x bs-show | 46 | ;; M-x bs-show |
| @@ -1083,7 +1083,7 @@ configuration." | |||
| 1083 | bs-dont-show-regexp (nth 3 list) | 1083 | bs-dont-show-regexp (nth 3 list) |
| 1084 | bs-dont-show-function (nth 4 list) | 1084 | bs-dont-show-function (nth 4 list) |
| 1085 | bs-buffer-sort-function (nth 5 list)) | 1085 | bs-buffer-sort-function (nth 5 list)) |
| 1086 | ;; for backward compability | 1086 | ;; for backward compatibility |
| 1087 | (funcall (cdr list))) | 1087 | (funcall (cdr list))) |
| 1088 | ;; else | 1088 | ;; else |
| 1089 | (ding) | 1089 | (ding) |
diff --git a/lisp/cus-face.el b/lisp/cus-face.el index 0a48c0fbd68..f813b5b84d1 100644 --- a/lisp/cus-face.el +++ b/lisp/cus-face.el | |||
| @@ -348,7 +348,7 @@ FACE's list property `theme-face' \(using `custom-push-theme')." | |||
| 348 | (put face 'face-override-spec nil) | 348 | (put face 'face-override-spec nil) |
| 349 | (face-spec-set face spec t)))))))) | 349 | (face-spec-set face spec t)))))))) |
| 350 | 350 | ||
| 351 | ;; XEmacs compability function. In XEmacs, when you reset a Custom | 351 | ;; XEmacs compatibility function. In XEmacs, when you reset a Custom |
| 352 | ;; Theme, you have to specify the theme to reset it to. We just apply | 352 | ;; Theme, you have to specify the theme to reset it to. We just apply |
| 353 | ;; the next theme. | 353 | ;; the next theme. |
| 354 | (defun custom-theme-reset-faces (theme &rest args) | 354 | (defun custom-theme-reset-faces (theme &rest args) |
diff --git a/lisp/doc-view.el b/lisp/doc-view.el index 7bead624cc7..ab0d6bf837b 100644 --- a/lisp/doc-view.el +++ b/lisp/doc-view.el | |||
| @@ -328,6 +328,10 @@ Can be `dvi', `pdf', or `ps'.") | |||
| 328 | ;; Zoom in/out. | 328 | ;; Zoom in/out. |
| 329 | (define-key map "+" 'doc-view-enlarge) | 329 | (define-key map "+" 'doc-view-enlarge) |
| 330 | (define-key map "-" 'doc-view-shrink) | 330 | (define-key map "-" 'doc-view-shrink) |
| 331 | ;; Fit the image to the window | ||
| 332 | (define-key map "W" 'doc-view-fit-width-to-window) | ||
| 333 | (define-key map "H" 'doc-view-fit-height-to-window) | ||
| 334 | (define-key map "P" 'doc-view-fit-page-to-window) | ||
| 331 | ;; Killing the buffer (and the process) | 335 | ;; Killing the buffer (and the process) |
| 332 | (define-key map (kbd "k") 'doc-view-kill-proc-and-buffer) | 336 | (define-key map (kbd "k") 'doc-view-kill-proc-and-buffer) |
| 333 | (define-key map (kbd "K") 'doc-view-kill-proc) | 337 | (define-key map (kbd "K") 'doc-view-kill-proc) |
| @@ -664,6 +668,78 @@ OpenDocument format)." | |||
| 664 | (interactive (list doc-view-shrink-factor)) | 668 | (interactive (list doc-view-shrink-factor)) |
| 665 | (doc-view-enlarge (/ 1.0 factor))) | 669 | (doc-view-enlarge (/ 1.0 factor))) |
| 666 | 670 | ||
| 671 | (defun doc-view-fit-width-to-window () | ||
| 672 | "Fit the image width to the window width." | ||
| 673 | (interactive) | ||
| 674 | (let ((win-width (- (nth 2 (window-inside-pixel-edges)) | ||
| 675 | (nth 0 (window-inside-pixel-edges)))) | ||
| 676 | (slice (doc-view-current-slice))) | ||
| 677 | (if (not slice) | ||
| 678 | (let ((img-width (car (image-display-size | ||
| 679 | (image-get-display-property) t)))) | ||
| 680 | (doc-view-enlarge (/ (float win-width) (float img-width)))) | ||
| 681 | |||
| 682 | ;; If slice is set | ||
| 683 | (let* ((slice-width (nth 2 slice)) | ||
| 684 | (scale-factor (/ (float win-width) (float slice-width))) | ||
| 685 | (new-slice (mapcar (lambda (x) (ceiling (* scale-factor x))) slice))) | ||
| 686 | |||
| 687 | (doc-view-enlarge scale-factor) | ||
| 688 | (setf (doc-view-current-slice) new-slice) | ||
| 689 | (doc-view-goto-page (doc-view-current-page)))))) | ||
| 690 | |||
| 691 | (defun doc-view-fit-height-to-window () | ||
| 692 | "Fit the image height to the window height." | ||
| 693 | (interactive) | ||
| 694 | (let ((win-height (- (nth 3 (window-inside-pixel-edges)) | ||
| 695 | (nth 1 (window-inside-pixel-edges)))) | ||
| 696 | (slice (doc-view-current-slice))) | ||
| 697 | (if (not slice) | ||
| 698 | (let ((img-height (cdr (image-display-size | ||
| 699 | (image-get-display-property) t)))) | ||
| 700 | ;; When users call 'doc-view-fit-height-to-window', | ||
| 701 | ;; they might want to go to next page by typing SPC | ||
| 702 | ;; ONLY once. So I used '(- win-height 1)' instead of | ||
| 703 | ;; 'win-height' | ||
| 704 | (doc-view-enlarge (/ (float (- win-height 1)) (float img-height)))) | ||
| 705 | |||
| 706 | ;; If slice is set | ||
| 707 | (let* ((slice-height (nth 3 slice)) | ||
| 708 | (scale-factor (/ (float (- win-height 1)) (float slice-height))) | ||
| 709 | (new-slice (mapcar (lambda (x) (ceiling (* scale-factor x))) slice))) | ||
| 710 | |||
| 711 | (doc-view-enlarge scale-factor) | ||
| 712 | (setf (doc-view-current-slice) new-slice) | ||
| 713 | (doc-view-goto-page (doc-view-current-page)))))) | ||
| 714 | |||
| 715 | (defun doc-view-fit-page-to-window () | ||
| 716 | "Fit the image to the window. | ||
| 717 | More specifically, this function enlarges image by: | ||
| 718 | |||
| 719 | min {(window-width / image-width), (window-height / image-height)} times." | ||
| 720 | (interactive) | ||
| 721 | (let ((win-width (- (nth 2 (window-inside-pixel-edges)) | ||
| 722 | (nth 0 (window-inside-pixel-edges)))) | ||
| 723 | (win-height (- (nth 3 (window-inside-pixel-edges)) | ||
| 724 | (nth 1 (window-inside-pixel-edges)))) | ||
| 725 | (slice (doc-view-current-slice))) | ||
| 726 | (if (not slice) | ||
| 727 | (let ((img-width (car (image-display-size | ||
| 728 | (image-get-display-property) t))) | ||
| 729 | (img-height (cdr (image-display-size | ||
| 730 | (image-get-display-property) t)))) | ||
| 731 | (doc-view-enlarge (min (/ (float win-width) (float img-width)) | ||
| 732 | (/ (float (- win-height 1)) (float img-height))))) | ||
| 733 | ;; If slice is set | ||
| 734 | (let* ((slice-width (nth 2 slice)) | ||
| 735 | (slice-height (nth 3 slice)) | ||
| 736 | (scale-factor (min (/ (float win-width) (float slice-width)) | ||
| 737 | (/ (float (- win-height 1)) (float slice-height)))) | ||
| 738 | (new-slice (mapcar (lambda (x) (ceiling (* scale-factor x))) slice))) | ||
| 739 | (doc-view-enlarge scale-factor) | ||
| 740 | (setf (doc-view-current-slice) new-slice) | ||
| 741 | (doc-view-goto-page (doc-view-current-page)))))) | ||
| 742 | |||
| 667 | (defun doc-view-reconvert-doc () | 743 | (defun doc-view-reconvert-doc () |
| 668 | "Reconvert the current document. | 744 | "Reconvert the current document. |
| 669 | Should be invoked when the cached images aren't up-to-date." | 745 | Should be invoked when the cached images aren't up-to-date." |
diff --git a/lisp/emacs-lisp/cconv.el b/lisp/emacs-lisp/cconv.el index 5cc9ecb4cf7..38584c437b8 100644 --- a/lisp/emacs-lisp/cconv.el +++ b/lisp/emacs-lisp/cconv.el | |||
| @@ -536,7 +536,9 @@ FORM is the parent form that binds this var." | |||
| 536 | ;; it is often non-trivial for the programmer to avoid such | 536 | ;; it is often non-trivial for the programmer to avoid such |
| 537 | ;; unused vars. | 537 | ;; unused vars. |
| 538 | (not (intern-soft var)) | 538 | (not (intern-soft var)) |
| 539 | (eq ?_ (aref (symbol-name var) 0))) | 539 | (eq ?_ (aref (symbol-name var) 0)) |
| 540 | ;; As a special exception, ignore "ignore". | ||
| 541 | (eq var 'ignored)) | ||
| 540 | (byte-compile-log-warning (format "Unused lexical %s `%S'" | 542 | (byte-compile-log-warning (format "Unused lexical %s `%S'" |
| 541 | varkind var)))) | 543 | varkind var)))) |
| 542 | ;; If it's unused, there's no point converting it into a cons-cell, even if | 544 | ;; If it's unused, there's no point converting it into a cons-cell, even if |
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 6aecc3615f3..4ce71b29d70 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el | |||
| @@ -173,6 +173,8 @@ | |||
| 173 | 173 | ||
| 174 | ;;; Code: | 174 | ;;; Code: |
| 175 | 175 | ||
| 176 | (require 'tabulated-list) | ||
| 177 | |||
| 176 | (defgroup package nil | 178 | (defgroup package nil |
| 177 | "Manager for Emacs Lisp packages." | 179 | "Manager for Emacs Lisp packages." |
| 178 | :group 'applications | 180 | :group 'applications |
| @@ -1249,12 +1251,10 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages." | |||
| 1249 | ;;;; Package menu mode. | 1251 | ;;;; Package menu mode. |
| 1250 | 1252 | ||
| 1251 | (defvar package-menu-mode-map | 1253 | (defvar package-menu-mode-map |
| 1252 | (let ((map (copy-keymap special-mode-map)) | 1254 | (let ((map (make-sparse-keymap)) |
| 1253 | (menu-map (make-sparse-keymap "Package"))) | 1255 | (menu-map (make-sparse-keymap "Package"))) |
| 1254 | (set-keymap-parent map button-buffer-map) | 1256 | (set-keymap-parent map tabulated-list-mode-map) |
| 1255 | (define-key map "\C-m" 'package-menu-describe-package) | 1257 | (define-key map "\C-m" 'package-menu-describe-package) |
| 1256 | (define-key map "n" 'next-line) | ||
| 1257 | (define-key map "p" 'previous-line) | ||
| 1258 | (define-key map "u" 'package-menu-mark-unmark) | 1258 | (define-key map "u" 'package-menu-mark-unmark) |
| 1259 | (define-key map "\177" 'package-menu-backup-unmark) | 1259 | (define-key map "\177" 'package-menu-backup-unmark) |
| 1260 | (define-key map "d" 'package-menu-mark-delete) | 1260 | (define-key map "d" 'package-menu-mark-delete) |
| @@ -1264,8 +1264,6 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages." | |||
| 1264 | (define-key map "x" 'package-menu-execute) | 1264 | (define-key map "x" 'package-menu-execute) |
| 1265 | (define-key map "h" 'package-menu-quick-help) | 1265 | (define-key map "h" 'package-menu-quick-help) |
| 1266 | (define-key map "?" 'package-menu-describe-package) | 1266 | (define-key map "?" 'package-menu-describe-package) |
| 1267 | (define-key map [follow-link] 'mouse-face) | ||
| 1268 | (define-key map [mouse-2] 'mouse-select-window) | ||
| 1269 | (define-key map [menu-bar package-menu] (cons "Package" menu-map)) | 1267 | (define-key map [menu-bar package-menu] (cons "Package" menu-map)) |
| 1270 | (define-key menu-map [mq] | 1268 | (define-key menu-map [mq] |
| 1271 | '(menu-item "Quit" quit-window | 1269 | '(menu-item "Quit" quit-window |
| @@ -1314,49 +1312,93 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages." | |||
| 1314 | map) | 1312 | map) |
| 1315 | "Local keymap for `package-menu-mode' buffers.") | 1313 | "Local keymap for `package-menu-mode' buffers.") |
| 1316 | 1314 | ||
| 1317 | (defvar package-menu-sort-button-map | 1315 | (define-derived-mode package-menu-mode tabulated-list-mode "Package Menu" |
| 1318 | (let ((map (make-sparse-keymap))) | ||
| 1319 | (define-key map [header-line mouse-1] 'package-menu-sort-by-column) | ||
| 1320 | (define-key map [header-line mouse-2] 'package-menu-sort-by-column) | ||
| 1321 | (define-key map [follow-link] 'mouse-face) | ||
| 1322 | map) | ||
| 1323 | "Local keymap for package menu sort buttons.") | ||
| 1324 | |||
| 1325 | (put 'package-menu-mode 'mode-class 'special) | ||
| 1326 | |||
| 1327 | (define-derived-mode package-menu-mode special-mode "Package Menu" | ||
| 1328 | "Major mode for browsing a list of packages. | 1316 | "Major mode for browsing a list of packages. |
| 1329 | Letters do not insert themselves; instead, they are commands. | 1317 | Letters do not insert themselves; instead, they are commands. |
| 1330 | \\<package-menu-mode-map> | 1318 | \\<package-menu-mode-map> |
| 1331 | \\{package-menu-mode-map}" | 1319 | \\{package-menu-mode-map}" |
| 1332 | (setq truncate-lines t) | 1320 | (setq tabulated-list-format [("Package" 18 package-menu--name-predicate) |
| 1333 | (setq buffer-read-only t) | 1321 | ("Version" 12 nil) |
| 1334 | (set (make-local-variable 'revert-buffer-function) 'package-menu-revert) | 1322 | ("Status" 10 package-menu--status-predicate) |
| 1335 | (setq header-line-format | 1323 | ("Description" 0 nil)]) |
| 1336 | (mapconcat | 1324 | (setq tabulated-list-padding 2) |
| 1337 | (lambda (pair) | 1325 | (setq tabulated-list-sort-key (cons "Status" nil)) |
| 1338 | (let ((column (car pair)) | 1326 | (tabulated-list-init-header)) |
| 1339 | (name (cdr pair))) | 1327 | |
| 1340 | (concat | 1328 | (defmacro package--push (package desc status listname) |
| 1341 | ;; Insert a space that aligns the button properly. | 1329 | "Convenience macro for `package-menu--generate'. |
| 1342 | (propertize " " 'display (list 'space :align-to column) | 1330 | If the alist stored in the symbol LISTNAME lacks an entry for a |
| 1343 | 'face 'fixed-pitch) | 1331 | package PACKAGE with descriptor DESC, add one. The alist is |
| 1344 | ;; Set up the column button. | 1332 | keyed with cons cells (PACKAGE . VERSION), where PACKAGE is a |
| 1345 | (propertize name | 1333 | symbol and VERSION is a version list." |
| 1346 | 'column-name name | 1334 | `(let* ((version (package-desc-vers ,desc)) |
| 1347 | 'help-echo "mouse-1: sort by column" | 1335 | (key (cons ,package version))) |
| 1348 | 'mouse-face 'highlight | 1336 | (unless (assoc key ,listname) |
| 1349 | 'keymap package-menu-sort-button-map)))) | 1337 | (push (list key ,status (package-desc-doc ,desc)) ,listname)))) |
| 1350 | ;; We take a trick from buff-menu and have a dummy leading | 1338 | |
| 1351 | ;; space to align the header line with the beginning of the | 1339 | (defun package-menu--generate (&optional remember-pos) |
| 1352 | ;; text. This doesn't really work properly on Emacs 21, but | 1340 | "Populate the Package Menu. |
| 1353 | ;; it is close enough. | 1341 | Optional argument REMEMBER-POS, if non-nil, means to move point |
| 1354 | '((0 . "") | 1342 | to the entry as before." |
| 1355 | (2 . "Package") | 1343 | ;; Construct list of ((PACKAGE . VERSION) STATUS DESCRIPTION). |
| 1356 | (20 . "Version") | 1344 | (let (info-list name builtin) |
| 1357 | (32 . "Status") | 1345 | ;; Installed packages: |
| 1358 | (43 . "Description")) | 1346 | (dolist (elt package-alist) |
| 1359 | ""))) | 1347 | (setq name (car elt)) |
| 1348 | (package--push name (cdr elt) | ||
| 1349 | (if (stringp (cadr (assq name package-load-list))) | ||
| 1350 | "held" "installed") | ||
| 1351 | info-list)) | ||
| 1352 | |||
| 1353 | ;; Built-in packages: | ||
| 1354 | (dolist (elt package--builtins) | ||
| 1355 | (setq name (car elt)) | ||
| 1356 | (unless (eq name 'emacs) ; Hide the `emacs' package. | ||
| 1357 | (package--push name (cdr elt) "built-in" info-list))) | ||
| 1358 | |||
| 1359 | ;; Available and disabled packages: | ||
| 1360 | (dolist (elt package-archive-contents) | ||
| 1361 | (setq name (car elt)) | ||
| 1362 | (let ((hold (assq name package-load-list))) | ||
| 1363 | (package--push name (cdr elt) | ||
| 1364 | (if (and hold (null (cadr hold))) "disabled" "available") | ||
| 1365 | info-list))) | ||
| 1366 | |||
| 1367 | ;; Obsolete packages: | ||
| 1368 | (dolist (elt package-obsolete-alist) | ||
| 1369 | (dolist (inner-elt (cdr elt)) | ||
| 1370 | (package--push (car elt) (cdr inner-elt) "obsolete" info-list))) | ||
| 1371 | |||
| 1372 | ;; Print the result. | ||
| 1373 | (setq tabulated-list-entries (mapcar 'package-menu--print-info info-list)) | ||
| 1374 | (tabulated-list-print remember-pos))) | ||
| 1375 | |||
| 1376 | (defun package-menu--print-info (pkg) | ||
| 1377 | "Return a package entry suitable for `tabulated-list-entries'. | ||
| 1378 | PKG has the form ((PACKAGE . VERSION) STATUS DOC). | ||
| 1379 | Return (KEY [NAME VERSION STATUS DOC]), where KEY is the | ||
| 1380 | identifier (NAME . VERSION-LIST)." | ||
| 1381 | (let* ((package (caar pkg)) | ||
| 1382 | (version (cdr (car pkg))) | ||
| 1383 | (status (nth 1 pkg)) | ||
| 1384 | (doc (or (nth 2 pkg) "")) | ||
| 1385 | (face (cond | ||
| 1386 | ((string= status "built-in") 'font-lock-builtin-face) | ||
| 1387 | ((string= status "available") 'default) | ||
| 1388 | ((string= status "held") 'font-lock-constant-face) | ||
| 1389 | ((string= status "disabled") 'font-lock-warning-face) | ||
| 1390 | ((string= status "installed") 'font-lock-comment-face) | ||
| 1391 | (t 'font-lock-warning-face)))) ; obsolete. | ||
| 1392 | (list (cons package version) | ||
| 1393 | (vector (list (symbol-name package) | ||
| 1394 | 'face 'link | ||
| 1395 | 'follow-link t | ||
| 1396 | 'package-symbol package | ||
| 1397 | 'action 'package-menu-describe-package) | ||
| 1398 | (propertize (package-version-join version) | ||
| 1399 | 'font-lock-face face) | ||
| 1400 | (propertize status 'font-lock-face face) | ||
| 1401 | (propertize doc 'font-lock-face face))))) | ||
| 1360 | 1402 | ||
| 1361 | (defun package-menu-refresh () | 1403 | (defun package-menu-refresh () |
| 1362 | "Download the Emacs Lisp package archive. | 1404 | "Download the Emacs Lisp package archive. |
| @@ -1366,59 +1408,42 @@ This fetches the contents of each archive specified in | |||
| 1366 | (unless (eq major-mode 'package-menu-mode) | 1408 | (unless (eq major-mode 'package-menu-mode) |
| 1367 | (error "The current buffer is not a Package Menu")) | 1409 | (error "The current buffer is not a Package Menu")) |
| 1368 | (package-refresh-contents) | 1410 | (package-refresh-contents) |
| 1369 | (package--generate-package-list)) | 1411 | (package-menu--generate t)) |
| 1370 | 1412 | ||
| 1371 | (defun package-menu-revert (&optional arg noconfirm) | 1413 | (defun package-menu-describe-package (&optional button) |
| 1372 | "Update the list of packages. | 1414 | "Describe the current package. |
| 1373 | This function is the `revert-buffer-function' for Package Menu | 1415 | If optional arg BUTTON is non-nil, describe its associated package." |
| 1374 | buffers. The arguments are ignored." | ||
| 1375 | (interactive) | 1416 | (interactive) |
| 1376 | (unless (eq major-mode 'package-menu-mode) | 1417 | (let ((package (if button (button-get button 'package-symbol) |
| 1377 | (error "The current buffer is not a Package Menu")) | 1418 | (car (tabulated-list-get-id))))) |
| 1378 | (package--generate-package-list)) | 1419 | (if package |
| 1379 | 1420 | (describe-package package)))) | |
| 1380 | (defun package-menu-describe-package () | ||
| 1381 | "Describe the package in the current line." | ||
| 1382 | (interactive) | ||
| 1383 | (let ((name (package-menu-get-package))) | ||
| 1384 | (if name | ||
| 1385 | (describe-package (intern name)) | ||
| 1386 | (message "No package on this line")))) | ||
| 1387 | |||
| 1388 | (defun package-menu-mark-internal (what) | ||
| 1389 | (unless (eobp) | ||
| 1390 | (let ((buffer-read-only nil)) | ||
| 1391 | (beginning-of-line) | ||
| 1392 | (delete-char 1) | ||
| 1393 | (insert what) | ||
| 1394 | (forward-line)))) | ||
| 1395 | 1421 | ||
| 1396 | ;; fixme numeric argument | 1422 | ;; fixme numeric argument |
| 1397 | (defun package-menu-mark-delete (num) | 1423 | (defun package-menu-mark-delete (num) |
| 1398 | "Mark a package for deletion and move to the next line." | 1424 | "Mark a package for deletion and move to the next line." |
| 1399 | (interactive "p") | 1425 | (interactive "p") |
| 1400 | (if (string-equal (package-menu-get-status) "installed") | 1426 | (if (string-equal (package-menu-get-status) "installed") |
| 1401 | (package-menu-mark-internal "D") | 1427 | (tabulated-list-put-tag "D" t) |
| 1402 | (forward-line))) | 1428 | (forward-line))) |
| 1403 | 1429 | ||
| 1404 | (defun package-menu-mark-install (num) | 1430 | (defun package-menu-mark-install (num) |
| 1405 | "Mark a package for installation and move to the next line." | 1431 | "Mark a package for installation and move to the next line." |
| 1406 | (interactive "p") | 1432 | (interactive "p") |
| 1407 | (if (string-equal (package-menu-get-status) "available") | 1433 | (if (string-equal (package-menu-get-status) "available") |
| 1408 | (package-menu-mark-internal "I") | 1434 | (tabulated-list-put-tag "I" t) |
| 1409 | (forward-line))) | 1435 | (forward-line))) |
| 1410 | 1436 | ||
| 1411 | (defun package-menu-mark-unmark (num) | 1437 | (defun package-menu-mark-unmark (num) |
| 1412 | "Clear any marks on a package and move to the next line." | 1438 | "Clear any marks on a package and move to the next line." |
| 1413 | (interactive "p") | 1439 | (interactive "p") |
| 1414 | (package-menu-mark-internal " ")) | 1440 | (tabulated-list-put-tag " " t)) |
| 1415 | 1441 | ||
| 1416 | (defun package-menu-backup-unmark () | 1442 | (defun package-menu-backup-unmark () |
| 1417 | "Back up one line and clear any marks on that package." | 1443 | "Back up one line and clear any marks on that package." |
| 1418 | (interactive) | 1444 | (interactive) |
| 1419 | (forward-line -1) | 1445 | (forward-line -1) |
| 1420 | (package-menu-mark-internal " ") | 1446 | (tabulated-list-put-tag " ")) |
| 1421 | (forward-line -1)) | ||
| 1422 | 1447 | ||
| 1423 | (defun package-menu-mark-obsolete-for-deletion () | 1448 | (defun package-menu-mark-obsolete-for-deletion () |
| 1424 | "Mark all obsolete packages for deletion." | 1449 | "Mark all obsolete packages for deletion." |
| @@ -1428,7 +1453,7 @@ buffers. The arguments are ignored." | |||
| 1428 | (forward-line 2) | 1453 | (forward-line 2) |
| 1429 | (while (not (eobp)) | 1454 | (while (not (eobp)) |
| 1430 | (if (looking-at ".*\\s obsolete\\s ") | 1455 | (if (looking-at ".*\\s obsolete\\s ") |
| 1431 | (package-menu-mark-internal "D") | 1456 | (tabulated-list-put-tag "D" t) |
| 1432 | (forward-line 1))))) | 1457 | (forward-line 1))))) |
| 1433 | 1458 | ||
| 1434 | (defun package-menu-quick-help () | 1459 | (defun package-menu-quick-help () |
| @@ -1439,20 +1464,6 @@ buffers. The arguments are ignored." | |||
| 1439 | (define-obsolete-function-alias | 1464 | (define-obsolete-function-alias |
| 1440 | 'package-menu-view-commentary 'package-menu-describe-package "24.1") | 1465 | 'package-menu-view-commentary 'package-menu-describe-package "24.1") |
| 1441 | 1466 | ||
| 1442 | ;; Return the name of the package on the current line. | ||
| 1443 | (defun package-menu-get-package () | ||
| 1444 | (save-excursion | ||
| 1445 | (beginning-of-line) | ||
| 1446 | (if (looking-at ". \\([^ \t]*\\)") | ||
| 1447 | (match-string-no-properties 1)))) | ||
| 1448 | |||
| 1449 | ;; Return the version of the package on the current line. | ||
| 1450 | (defun package-menu-get-version () | ||
| 1451 | (save-excursion | ||
| 1452 | (beginning-of-line) | ||
| 1453 | (if (looking-at ". [^ \t]*[ \t]*\\([0-9.]*\\)") | ||
| 1454 | (match-string 1)))) | ||
| 1455 | |||
| 1456 | (defun package-menu-get-status () | 1467 | (defun package-menu-get-status () |
| 1457 | (save-excursion | 1468 | (save-excursion |
| 1458 | (if (looking-at ". [^ \t]*[ \t]*[^ \t]*[ \t]*\\([^ \t]*\\)") | 1469 | (if (looking-at ". [^ \t]*[ \t]*[^ \t]*[ \t]*\\([^ \t]*\\)") |
| @@ -1464,19 +1475,22 @@ buffers. The arguments are ignored." | |||
| 1464 | Packages marked for installation are downloaded and installed; | 1475 | Packages marked for installation are downloaded and installed; |
| 1465 | packages marked for deletion are removed." | 1476 | packages marked for deletion are removed." |
| 1466 | (interactive) | 1477 | (interactive) |
| 1467 | (let (install-list delete-list cmd) | 1478 | (unless (eq major-mode 'package-menu-mode) |
| 1479 | (error "The current buffer is not in Package Menu mode")) | ||
| 1480 | (let (install-list delete-list cmd id) | ||
| 1468 | (save-excursion | 1481 | (save-excursion |
| 1469 | (goto-char (point-min)) | 1482 | (goto-char (point-min)) |
| 1470 | (while (not (eobp)) | 1483 | (while (not (eobp)) |
| 1471 | (setq cmd (char-after)) | 1484 | (setq cmd (char-after)) |
| 1472 | (cond | 1485 | (unless (eq cmd ?\s) |
| 1473 | ((eq cmd ?\s) t) | 1486 | ;; This is the key (PACKAGE . VERSION-LIST). |
| 1474 | ((eq cmd ?D) | 1487 | (setq id (tabulated-list-get-id)) |
| 1475 | (push (cons (package-menu-get-package) | 1488 | (cond ((eq cmd ?D) |
| 1476 | (package-menu-get-version)) | 1489 | (push (cons (symbol-name (car id)) |
| 1477 | delete-list)) | 1490 | (package-version-join (cdr id))) |
| 1478 | ((eq cmd ?I) | 1491 | delete-list)) |
| 1479 | (push (package-menu-get-package) install-list))) | 1492 | ((eq cmd ?I) |
| 1493 | (push (car id) install-list)))) | ||
| 1480 | (forward-line))) | 1494 | (forward-line))) |
| 1481 | ;; Delete packages, prompting if necessary. | 1495 | ;; Delete packages, prompting if necessary. |
| 1482 | (when delete-list | 1496 | (when delete-list |
| @@ -1502,217 +1516,71 @@ packages marked for deletion are removed." | |||
| 1502 | (format "Install package `%s'? " (car install-list)) | 1516 | (format "Install package `%s'? " (car install-list)) |
| 1503 | (format "Install these %d packages (%s)? " | 1517 | (format "Install these %d packages (%s)? " |
| 1504 | (length install-list) | 1518 | (length install-list) |
| 1505 | (mapconcat 'identity install-list ", ")))) | 1519 | (mapconcat 'symbol-name install-list ", ")))) |
| 1506 | (dolist (elt install-list) | 1520 | (mapc 'package-install install-list))) |
| 1507 | (package-install (intern elt))))) | ||
| 1508 | ;; If we deleted anything, regenerate `package-alist'. This is done | 1521 | ;; If we deleted anything, regenerate `package-alist'. This is done |
| 1509 | ;; automatically if we installed a package. | 1522 | ;; automatically if we installed a package. |
| 1510 | (and delete-list (null install-list) | 1523 | (and delete-list (null install-list) |
| 1511 | (package-initialize)) | 1524 | (package-initialize)) |
| 1512 | (if (or delete-list install-list) | 1525 | (if (or delete-list install-list) |
| 1513 | (package-menu-revert) | 1526 | (package-menu--generate t) |
| 1514 | (message "No operations specified.")))) | 1527 | (message "No operations specified.")))) |
| 1515 | 1528 | ||
| 1516 | (defun package-print-package (package version key desc) | 1529 | (defun package-menu--version-predicate (A B) |
| 1517 | (let ((face | 1530 | (let ((vA (or (aref (cadr A) 1) '(0))) |
| 1518 | (cond ((string= key "built-in") 'font-lock-builtin-face) | 1531 | (vB (or (aref (cadr B) 1) '(0)))) |
| 1519 | ((string= key "available") 'default) | 1532 | (if (version-list-= vA vB) |
| 1520 | ((string= key "held") 'font-lock-constant-face) | 1533 | (package-menu--name-predicate A B) |
| 1521 | ((string= key "disabled") 'font-lock-warning-face) | 1534 | (version-list-< vA vB)))) |
| 1522 | ((string= key "installed") 'font-lock-comment-face) | 1535 | |
| 1523 | (t ; obsolete, but also the default. | 1536 | (defun package-menu--status-predicate (A B) |
| 1524 | 'font-lock-warning-face)))) | 1537 | (let ((sA (aref (cadr A) 2)) |
| 1525 | (insert (propertize " " 'font-lock-face face)) | 1538 | (sB (aref (cadr B) 2))) |
| 1526 | (insert-text-button (symbol-name package) | 1539 | (cond ((string= sA sB) |
| 1527 | 'face 'link | 1540 | (package-menu--name-predicate A B)) |
| 1528 | 'follow-link t | 1541 | ((string= sA "available") t) |
| 1529 | 'package-symbol package | 1542 | ((string= sB "available") nil) |
| 1530 | 'action (lambda (button) | 1543 | ((string= sA "installed") t) |
| 1531 | (describe-package | 1544 | ((string= sB "installed") nil) |
| 1532 | (button-get button 'package-symbol)))) | 1545 | ((string= sA "held") t) |
| 1533 | (indent-to 20 1) | 1546 | ((string= sB "held") nil) |
| 1534 | (insert (propertize (package-version-join version) 'font-lock-face face)) | 1547 | ((string= sA "built-in") t) |
| 1535 | (indent-to 32 1) | 1548 | ((string= sB "built-in") nil) |
| 1536 | (insert (propertize key 'font-lock-face face)) | 1549 | ((string= sA "obsolete") t) |
| 1537 | ;; FIXME: this 'when' is bogus... | 1550 | ((string= sB "obsolete") nil) |
| 1538 | (when desc | 1551 | (t (string< sA sB))))) |
| 1539 | (indent-to 43 1) | 1552 | |
| 1540 | (let ((opoint (point))) | 1553 | (defun package-menu--description-predicate (A B) |
| 1541 | (insert (propertize desc 'font-lock-face face)) | 1554 | (let ((dA (aref (cadr A) 3)) |
| 1542 | (upcase-region opoint (min (point) (1+ opoint))))) | 1555 | (dB (aref (cadr B) 3))) |
| 1543 | (insert "\n"))) | 1556 | (if (string= dA dB) |
| 1544 | 1557 | (package-menu--name-predicate A B) | |
| 1545 | (defun package-list-maybe-add (package version status description result) | 1558 | (string< dA dB)))) |
| 1546 | (unless (assoc (cons package version) result) | 1559 | |
| 1547 | (push (list (cons package version) status description) result)) | 1560 | (defun package-menu--name-predicate (A B) |
| 1548 | result) | 1561 | (string< (symbol-name (caar A)) |
| 1549 | 1562 | (symbol-name (caar B)))) | |
| 1550 | (defvar package-menu-package-list nil | ||
| 1551 | "List of packages to display in the Package Menu buffer. | ||
| 1552 | A value of nil means to display all packages.") | ||
| 1553 | |||
| 1554 | (defvar package-menu-sort-key nil | ||
| 1555 | "Sort key for the current Package Menu buffer.") | ||
| 1556 | |||
| 1557 | (defun package--generate-package-list () | ||
| 1558 | "Populate the current Package Menu buffer." | ||
| 1559 | (let ((inhibit-read-only t) | ||
| 1560 | info-list name desc hold builtin) | ||
| 1561 | (erase-buffer) | ||
| 1562 | ;; List installed packages | ||
| 1563 | (dolist (elt package-alist) | ||
| 1564 | (setq name (car elt)) | ||
| 1565 | (when (or (null package-menu-package-list) | ||
| 1566 | (memq name package-menu-package-list)) | ||
| 1567 | (setq desc (cdr elt) | ||
| 1568 | hold (cadr (assq name package-load-list))) | ||
| 1569 | (setq info-list | ||
| 1570 | (package-list-maybe-add | ||
| 1571 | name (package-desc-vers desc) | ||
| 1572 | ;; FIXME: it turns out to be tricky to see if this | ||
| 1573 | ;; package is presently activated. | ||
| 1574 | (if (stringp hold) "held" "installed") | ||
| 1575 | (package-desc-doc desc) | ||
| 1576 | info-list)))) | ||
| 1577 | |||
| 1578 | ;; List built-in packages | ||
| 1579 | (dolist (elt package--builtins) | ||
| 1580 | (setq name (car elt)) | ||
| 1581 | (when (and (not (eq name 'emacs)) ; Hide the `emacs' package. | ||
| 1582 | (or (null package-menu-package-list) | ||
| 1583 | (memq name package-menu-package-list))) | ||
| 1584 | (setq desc (cdr elt)) | ||
| 1585 | (setq info-list | ||
| 1586 | (package-list-maybe-add | ||
| 1587 | name (package-desc-vers desc) | ||
| 1588 | "built-in" | ||
| 1589 | (package-desc-doc desc) | ||
| 1590 | info-list)))) | ||
| 1591 | |||
| 1592 | ;; List available and disabled packages | ||
| 1593 | (dolist (elt package-archive-contents) | ||
| 1594 | (setq name (car elt) | ||
| 1595 | desc (cdr elt) | ||
| 1596 | hold (assq name package-load-list)) | ||
| 1597 | (when (or (null package-menu-package-list) | ||
| 1598 | (memq name package-menu-package-list)) | ||
| 1599 | (setq info-list | ||
| 1600 | (package-list-maybe-add name | ||
| 1601 | (package-desc-vers desc) | ||
| 1602 | (if (and hold (null (cadr hold))) | ||
| 1603 | "disabled" | ||
| 1604 | "available") | ||
| 1605 | (package-desc-doc (cdr elt)) | ||
| 1606 | info-list)))) | ||
| 1607 | ;; List obsolete packages | ||
| 1608 | (mapc (lambda (elt) | ||
| 1609 | (mapc (lambda (inner-elt) | ||
| 1610 | (setq info-list | ||
| 1611 | (package-list-maybe-add (car elt) | ||
| 1612 | (package-desc-vers | ||
| 1613 | (cdr inner-elt)) | ||
| 1614 | "obsolete" | ||
| 1615 | (package-desc-doc | ||
| 1616 | (cdr inner-elt)) | ||
| 1617 | info-list))) | ||
| 1618 | (cdr elt))) | ||
| 1619 | package-obsolete-alist) | ||
| 1620 | |||
| 1621 | (setq info-list | ||
| 1622 | (sort info-list | ||
| 1623 | (cond ((string= package-menu-sort-key "Package") | ||
| 1624 | 'package-menu--name-predicate) | ||
| 1625 | ((string= package-menu-sort-key "Version") | ||
| 1626 | 'package-menu--version-predicate) | ||
| 1627 | ((string= package-menu-sort-key "Description") | ||
| 1628 | 'package-menu--description-predicate) | ||
| 1629 | (t ; By default, sort by package status | ||
| 1630 | 'package-menu--status-predicate)))) | ||
| 1631 | |||
| 1632 | (dolist (elt info-list) | ||
| 1633 | (package-print-package (car (car elt)) | ||
| 1634 | (cdr (car elt)) | ||
| 1635 | (car (cdr elt)) | ||
| 1636 | (car (cdr (cdr elt))))) | ||
| 1637 | (goto-char (point-min)) | ||
| 1638 | (set-buffer-modified-p nil) | ||
| 1639 | (current-buffer))) | ||
| 1640 | |||
| 1641 | (defun package-menu--version-predicate (left right) | ||
| 1642 | (let ((vleft (or (cdr (car left)) '(0))) | ||
| 1643 | (vright (or (cdr (car right)) '(0)))) | ||
| 1644 | (if (version-list-= vleft vright) | ||
| 1645 | (package-menu--name-predicate left right) | ||
| 1646 | (version-list-< vleft vright)))) | ||
| 1647 | |||
| 1648 | (defun package-menu--status-predicate (left right) | ||
| 1649 | (let ((sleft (cadr left)) | ||
| 1650 | (sright (cadr right))) | ||
| 1651 | (cond ((string= sleft sright) | ||
| 1652 | (package-menu--name-predicate left right)) | ||
| 1653 | ((string= sleft "available") t) | ||
| 1654 | ((string= sright "available") nil) | ||
| 1655 | ((string= sleft "installed") t) | ||
| 1656 | ((string= sright "installed") nil) | ||
| 1657 | ((string= sleft "held") t) | ||
| 1658 | ((string= sright "held") nil) | ||
| 1659 | ((string= sleft "built-in") t) | ||
| 1660 | ((string= sright "built-in") nil) | ||
| 1661 | ((string= sleft "obsolete") t) | ||
| 1662 | ((string= sright "obsolete") nil) | ||
| 1663 | (t (string< sleft sright))))) | ||
| 1664 | |||
| 1665 | (defun package-menu--description-predicate (left right) | ||
| 1666 | (let ((sleft (car (cddr left))) | ||
| 1667 | (sright (car (cddr right)))) | ||
| 1668 | (if (string= sleft sright) | ||
| 1669 | (package-menu--name-predicate left right) | ||
| 1670 | (string< sleft sright)))) | ||
| 1671 | |||
| 1672 | (defun package-menu--name-predicate (left right) | ||
| 1673 | (string< (symbol-name (caar left)) | ||
| 1674 | (symbol-name (caar right)))) | ||
| 1675 | |||
| 1676 | (defun package-menu-sort-by-column (&optional e) | ||
| 1677 | "Sort the package menu by the column of the mouse click E." | ||
| 1678 | (interactive "e") | ||
| 1679 | (let* ((pos (event-start e)) | ||
| 1680 | (obj (posn-object pos)) | ||
| 1681 | (col (if obj | ||
| 1682 | (get-text-property (cdr obj) 'column-name (car obj)) | ||
| 1683 | (get-text-property (posn-point pos) 'column-name))) | ||
| 1684 | (buf (window-buffer (posn-window (event-start e))))) | ||
| 1685 | (with-current-buffer buf | ||
| 1686 | (when (eq major-mode 'package-menu-mode) | ||
| 1687 | (setq package-menu-sort-key col) | ||
| 1688 | (package--generate-package-list))))) | ||
| 1689 | |||
| 1690 | (defun package--list-packages (&optional packages) | ||
| 1691 | "Generate and pop to the *Packages* buffer. | ||
| 1692 | Optional PACKAGES is a list of names of packages (symbols) to | ||
| 1693 | list; the default is to display everything in `package-alist'." | ||
| 1694 | (require 'finder-inf nil t) | ||
| 1695 | (let ((buf (get-buffer-create "*Packages*"))) | ||
| 1696 | (with-current-buffer buf | ||
| 1697 | (package-menu-mode) | ||
| 1698 | (set (make-local-variable 'package-menu-package-list) packages) | ||
| 1699 | (set (make-local-variable 'package-menu-sort-key) nil) | ||
| 1700 | (package--generate-package-list)) | ||
| 1701 | ;; The package menu buffer has keybindings. If the user types | ||
| 1702 | ;; `M-x list-packages', that suggests it should become current. | ||
| 1703 | (switch-to-buffer buf))) | ||
| 1704 | 1563 | ||
| 1705 | ;;;###autoload | 1564 | ;;;###autoload |
| 1706 | (defun list-packages () | 1565 | (defun list-packages (&optional no-fetch) |
| 1707 | "Display a list of packages. | 1566 | "Display a list of packages. |
| 1708 | Fetches the updated list of packages before displaying. | 1567 | This first fetches the updated list of packages before |
| 1568 | displaying, unless a prefix argument NO-FETCH is specified. | ||
| 1709 | The list is displayed in a buffer named `*Packages*'." | 1569 | The list is displayed in a buffer named `*Packages*'." |
| 1710 | (interactive) | 1570 | (interactive "P") |
| 1571 | (require 'finder-inf nil t) | ||
| 1711 | ;; Initialize the package system if necessary. | 1572 | ;; Initialize the package system if necessary. |
| 1712 | (unless package--initialized | 1573 | (unless package--initialized |
| 1713 | (package-initialize t)) | 1574 | (package-initialize t)) |
| 1714 | (package-refresh-contents) | 1575 | (unless no-fetch |
| 1715 | (package--list-packages)) | 1576 | (package-refresh-contents)) |
| 1577 | (let ((buf (get-buffer-create "*Packages*"))) | ||
| 1578 | (with-current-buffer buf | ||
| 1579 | (package-menu-mode) | ||
| 1580 | (package-menu--generate)) | ||
| 1581 | ;; The package menu buffer has keybindings. If the user types | ||
| 1582 | ;; `M-x list-packages', that suggests it should become current. | ||
| 1583 | (switch-to-buffer buf))) | ||
| 1716 | 1584 | ||
| 1717 | ;;;###autoload | 1585 | ;;;###autoload |
| 1718 | (defalias 'package-list-packages 'list-packages) | 1586 | (defalias 'package-list-packages 'list-packages) |
| @@ -1722,7 +1590,7 @@ The list is displayed in a buffer named `*Packages*'." | |||
| 1722 | Does not fetch the updated list of packages before displaying. | 1590 | Does not fetch the updated list of packages before displaying. |
| 1723 | The list is displayed in a buffer named `*Packages*'." | 1591 | The list is displayed in a buffer named `*Packages*'." |
| 1724 | (interactive) | 1592 | (interactive) |
| 1725 | (package--list-packages)) | 1593 | (list-packages t)) |
| 1726 | 1594 | ||
| 1727 | (provide 'package) | 1595 | (provide 'package) |
| 1728 | 1596 | ||
diff --git a/lisp/emacs-lisp/tabulated-list.el b/lisp/emacs-lisp/tabulated-list.el new file mode 100644 index 00000000000..03ee59dd89c --- /dev/null +++ b/lisp/emacs-lisp/tabulated-list.el | |||
| @@ -0,0 +1,355 @@ | |||
| 1 | ;;; tabulated-list.el --- generic major mode for tabulated lists. | ||
| 2 | |||
| 3 | ;; Copyright (C) 2011 Free Software Foundation, Inc. | ||
| 4 | |||
| 5 | ;; Author: Chong Yidong <cyd@stupidchicken.com> | ||
| 6 | ;; Keywords: extensions, lisp | ||
| 7 | |||
| 8 | ;; This file is part of GNU Emacs. | ||
| 9 | |||
| 10 | ;; GNU Emacs 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 3, or (at your option) | ||
| 13 | ;; any later version. | ||
| 14 | |||
| 15 | ;; GNU Emacs 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 GNU Emacs. If not, see <http://www.gnu.org/licenses/>. | ||
| 22 | |||
| 23 | ;;; Commentary: | ||
| 24 | |||
| 25 | ;; This file defines `tabulated-list-mode', a generic major mode for displaying | ||
| 26 | ;; lists of tabulated data, intended for other major modes to inherit from. It | ||
| 27 | ;; provides several utility routines, e.g. for pretty-printing lines of | ||
| 28 | ;; tabulated data to fit into the appropriate columns. | ||
| 29 | |||
| 30 | ;; For usage information, see the documentation of `tabulated-list-mode'. | ||
| 31 | |||
| 32 | ;; This package originated from Tom Tromey's Package Menu mode, extended and | ||
| 33 | ;; generalized to be used by other modes. | ||
| 34 | |||
| 35 | ;;; Code: | ||
| 36 | |||
| 37 | (defvar tabulated-list-format nil | ||
| 38 | "The format of the current Tabulated List mode buffer. | ||
| 39 | This should be a vector of elements (NAME WIDTH SORT), where: | ||
| 40 | - NAME is a string describing the column. | ||
| 41 | - WIDTH is the width to reserve for the column. | ||
| 42 | For the final element, its numerical value is ignored. | ||
| 43 | - SORT specifies how to sort entries by this column. | ||
| 44 | If nil, this column cannot be used for sorting. | ||
| 45 | If t, sort by comparing the string value printed in the column. | ||
| 46 | Otherwise, it should be a predicate function suitable for | ||
| 47 | `sort', accepting arguments with the same form as the elements | ||
| 48 | of `tabulated-list-entries'.") | ||
| 49 | (make-variable-buffer-local 'tabulated-list-format) | ||
| 50 | |||
| 51 | (defvar tabulated-list-entries nil | ||
| 52 | "Entries displayed in the current Tabulated List buffer. | ||
| 53 | This should be either a function, or a list. | ||
| 54 | If a list, each element has the form (ID [DESC1 ... DESCN]), | ||
| 55 | where: | ||
| 56 | - ID is nil, or a Lisp object uniquely identifying this entry, | ||
| 57 | which is used to keep the cursor on the \"same\" entry when | ||
| 58 | rearranging the list. Comparison is done with `equal'. | ||
| 59 | |||
| 60 | - Each DESC is a column descriptor, one for each column | ||
| 61 | specified in `tabulated-list-format'. A descriptor is either | ||
| 62 | a string, which is printed as-is, or a list (LABEL . PROPS), | ||
| 63 | which means to use `insert-text-button' to insert a text | ||
| 64 | button with label LABEL and button properties PROPS. | ||
| 65 | The string, or button label, must not contain any newline. | ||
| 66 | |||
| 67 | If `tabulated-list-entries' is a function, it is called with no | ||
| 68 | arguments and must return a list of the above form.") | ||
| 69 | (make-variable-buffer-local 'tabulated-list-entries) | ||
| 70 | |||
| 71 | (defvar tabulated-list-padding 0 | ||
| 72 | "Number of characters preceding each Tabulated List mode entry. | ||
| 73 | By default, lines are padded with spaces, but you can use the | ||
| 74 | function `tabulated-list-put-tag' to change this.") | ||
| 75 | (make-variable-buffer-local 'tabulated-list-padding) | ||
| 76 | |||
| 77 | (defvar tabulated-list-revert-hook nil | ||
| 78 | "Hook run before reverting a Tabulated List buffer. | ||
| 79 | This is commonly used to recompute `tabulated-list-entries'.") | ||
| 80 | |||
| 81 | (defvar tabulated-list-printer 'tabulated-list-print-entry | ||
| 82 | "Function for inserting a Tabulated List entry at point. | ||
| 83 | It is called with two arguments, ID and COLS. ID is a Lisp | ||
| 84 | object identifying the entry, and COLS is a vector of column | ||
| 85 | descriptors, as documented in `tabulated-list-entries'.") | ||
| 86 | (make-variable-buffer-local 'tabulated-list-printer) | ||
| 87 | |||
| 88 | (defvar tabulated-list-sort-key nil | ||
| 89 | "Sort key for the current Tabulated List mode buffer. | ||
| 90 | If nil, no additional sorting is performed. | ||
| 91 | Otherwise, this should be a cons cell (NAME . FLIP). | ||
| 92 | NAME is a string matching one of the column names in | ||
| 93 | `tabulated-list-format' (the corresponding SORT entry in | ||
| 94 | `tabulated-list-format' then specifies how to sort). FLIP, if | ||
| 95 | non-nil, means to invert the resulting sort.") | ||
| 96 | (make-variable-buffer-local 'tabulated-list-sort-key) | ||
| 97 | |||
| 98 | (defun tabulated-list-get-id (&optional pos) | ||
| 99 | "Obtain the entry ID of the Tabulated List mode entry at POS. | ||
| 100 | This is an ID object from `tabulated-list-entries', or nil. | ||
| 101 | POS, if omitted or nil, defaults to point." | ||
| 102 | (get-text-property (or pos (point)) 'tabulated-list-id)) | ||
| 103 | |||
| 104 | (defun tabulated-list-put-tag (tag &optional advance) | ||
| 105 | "Put TAG in the padding area of the current line. | ||
| 106 | TAG should be a string, with length <= `tabulated-list-padding'. | ||
| 107 | If ADVANCE is non-nil, move forward by one line afterwards." | ||
| 108 | (unless (stringp tag) | ||
| 109 | (error "Invalid argument to `tabulated-list-put-tag'")) | ||
| 110 | (unless (> tabulated-list-padding 0) | ||
| 111 | (error "Unable to tag the current line")) | ||
| 112 | (save-excursion | ||
| 113 | (beginning-of-line) | ||
| 114 | (when (get-text-property (point) 'tabulated-list-id) | ||
| 115 | (let ((beg (point)) | ||
| 116 | (inhibit-read-only t)) | ||
| 117 | (forward-char tabulated-list-padding) | ||
| 118 | (insert-and-inherit | ||
| 119 | (if (<= (length tag) tabulated-list-padding) | ||
| 120 | (concat tag | ||
| 121 | (make-string (- tabulated-list-padding (length tag)) | ||
| 122 | ?\s)) | ||
| 123 | (substring tag 0 tabulated-list-padding))) | ||
| 124 | (delete-region beg (+ beg tabulated-list-padding))))) | ||
| 125 | (if advance | ||
| 126 | (forward-line))) | ||
| 127 | |||
| 128 | (defvar tabulated-list-mode-map | ||
| 129 | (let ((map (copy-keymap special-mode-map))) | ||
| 130 | (set-keymap-parent map button-buffer-map) | ||
| 131 | (define-key map "n" 'next-line) | ||
| 132 | (define-key map "p" 'previous-line) | ||
| 133 | (define-key map [follow-link] 'mouse-face) | ||
| 134 | (define-key map [mouse-2] 'mouse-select-window) | ||
| 135 | map) | ||
| 136 | "Local keymap for `tabulated-list-mode' buffers.") | ||
| 137 | |||
| 138 | (defvar tabulated-list-sort-button-map | ||
| 139 | (let ((map (make-sparse-keymap))) | ||
| 140 | (define-key map [header-line mouse-1] 'tabulated-list-col-sort) | ||
| 141 | (define-key map [header-line mouse-2] 'tabulated-list-col-sort) | ||
| 142 | (define-key map [follow-link] 'mouse-face) | ||
| 143 | map) | ||
| 144 | "Local keymap for `tabulated-list-mode' sort buttons.") | ||
| 145 | |||
| 146 | (defun tabulated-list-init-header () | ||
| 147 | "Set up header line for the Tabulated List buffer." | ||
| 148 | (let ((x tabulated-list-padding) | ||
| 149 | (button-props `(help-echo "Click to sort by column" | ||
| 150 | mouse-face highlight | ||
| 151 | keymap ,tabulated-list-sort-button-map)) | ||
| 152 | (cols nil)) | ||
| 153 | (if (> tabulated-list-padding 0) | ||
| 154 | (push (propertize " " 'display `(space :align-to ,x)) cols)) | ||
| 155 | (dotimes (n (length tabulated-list-format)) | ||
| 156 | (let* ((col (aref tabulated-list-format n)) | ||
| 157 | (width (nth 1 col)) | ||
| 158 | (label (car col))) | ||
| 159 | (setq x (+ x 1 width)) | ||
| 160 | (and (<= tabulated-list-padding 0) | ||
| 161 | (= n 0) | ||
| 162 | (setq label (concat " " label))) | ||
| 163 | (push | ||
| 164 | (cond | ||
| 165 | ;; An unsortable column | ||
| 166 | ((not (nth 2 col)) label) | ||
| 167 | ;; The selected sort column | ||
| 168 | ((equal (car col) (car tabulated-list-sort-key)) | ||
| 169 | (apply 'propertize | ||
| 170 | (concat label | ||
| 171 | (cond | ||
| 172 | ((> (+ 2 (length label)) width) | ||
| 173 | "") | ||
| 174 | ((cdr tabulated-list-sort-key) | ||
| 175 | " â–²") | ||
| 176 | (t " â–¼"))) | ||
| 177 | 'face 'bold | ||
| 178 | 'tabulated-list-column-name (car col) | ||
| 179 | button-props)) | ||
| 180 | ;; Unselected sortable column. | ||
| 181 | (t (apply 'propertize label | ||
| 182 | 'tabulated-list-column-name (car col) | ||
| 183 | button-props))) | ||
| 184 | cols)) | ||
| 185 | (push (propertize " " | ||
| 186 | 'display (list 'space :align-to x) | ||
| 187 | 'face 'fixed-pitch) | ||
| 188 | cols)) | ||
| 189 | (setq header-line-format (mapconcat 'identity (nreverse cols) "")))) | ||
| 190 | |||
| 191 | (defun tabulated-list-revert (&rest ignored) | ||
| 192 | "The `revert-buffer-function' for `tabulated-list-mode'. | ||
| 193 | It runs `tabulated-list-revert-hook', then calls `tabulated-list-print'." | ||
| 194 | (interactive) | ||
| 195 | (unless (derived-mode-p 'tabulated-list-mode) | ||
| 196 | (error "The current buffer is not in Tabulated List mode")) | ||
| 197 | (run-hooks 'tabulated-list-revert-hook) | ||
| 198 | (tabulated-list-print t)) | ||
| 199 | |||
| 200 | (defun tabulated-list-print (&optional remember-pos) | ||
| 201 | "Populate the current Tabulated List mode buffer. | ||
| 202 | This sorts the `tabulated-list-entries' list if sorting is | ||
| 203 | specified by `tabulated-list-sort-key'. It then erases the | ||
| 204 | buffer and inserts the entries with `tabulated-list-printer'. | ||
| 205 | |||
| 206 | Optional argument REMEMBER-POS, if non-nil, means to move point | ||
| 207 | to the entry with the same ID element as the current line." | ||
| 208 | (let ((inhibit-read-only t) | ||
| 209 | (entries (if (functionp 'tabulated-list-entries) | ||
| 210 | (funcall tabulated-list-entries) | ||
| 211 | tabulated-list-entries)) | ||
| 212 | entry-id saved-pt saved-col) | ||
| 213 | (and remember-pos | ||
| 214 | (setq entry-id (tabulated-list-get-id)) | ||
| 215 | (setq saved-col (current-column))) | ||
| 216 | (erase-buffer) | ||
| 217 | ;; Sort the buffers, if necessary. | ||
| 218 | (when tabulated-list-sort-key | ||
| 219 | (let ((sort-column (car tabulated-list-sort-key)) | ||
| 220 | (len (length tabulated-list-format)) | ||
| 221 | (n 0) | ||
| 222 | sorter) | ||
| 223 | ;; Which column is to be sorted? | ||
| 224 | (while (and (< n len) | ||
| 225 | (not (equal (car (aref tabulated-list-format n)) | ||
| 226 | sort-column))) | ||
| 227 | (setq n (1+ n))) | ||
| 228 | (when (< n len) | ||
| 229 | (setq sorter (nth 2 (aref tabulated-list-format n))) | ||
| 230 | (when (eq sorter t) | ||
| 231 | (setq sorter ; Default sorter checks column N: | ||
| 232 | (lambda (A B) | ||
| 233 | (setq A (aref (cadr A) n)) | ||
| 234 | (setq B (aref (cadr B) n)) | ||
| 235 | (string< (if (stringp A) A (car A)) | ||
| 236 | (if (stringp B) B (car B)))))) | ||
| 237 | (setq entries (sort entries sorter)) | ||
| 238 | (if (cdr tabulated-list-sort-key) | ||
| 239 | (setq entries (nreverse entries))) | ||
| 240 | (unless (functionp 'tabulated-list-entries) | ||
| 241 | (setq tabulated-list-entries entries))))) | ||
| 242 | ;; Print the resulting list. | ||
| 243 | (dolist (elt entries) | ||
| 244 | (and entry-id | ||
| 245 | (equal entry-id (car elt)) | ||
| 246 | (setq saved-pt (point))) | ||
| 247 | (apply tabulated-list-printer elt)) | ||
| 248 | (set-buffer-modified-p nil) | ||
| 249 | ;; If REMEMBER-POS was specified, move to the "old" location. | ||
| 250 | (if saved-pt | ||
| 251 | (progn (goto-char saved-pt) | ||
| 252 | (move-to-column saved-col)) | ||
| 253 | (goto-char (point-min))))) | ||
| 254 | |||
| 255 | (defun tabulated-list-print-entry (id cols) | ||
| 256 | "Insert a Tabulated List entry at point. | ||
| 257 | This is the default `tabulated-list-printer' function. ID is a | ||
| 258 | Lisp object identifying the entry to print, and COLS is a vector | ||
| 259 | of column descriptors." | ||
| 260 | (let ((beg (point)) | ||
| 261 | (x (max tabulated-list-padding 0)) | ||
| 262 | (len (length tabulated-list-format))) | ||
| 263 | (if (> tabulated-list-padding 0) | ||
| 264 | (insert (make-string x ?\s))) | ||
| 265 | (dotimes (n len) | ||
| 266 | (let* ((format (aref tabulated-list-format n)) | ||
| 267 | (desc (aref cols n)) | ||
| 268 | (width (nth 1 format)) | ||
| 269 | (label (if (stringp desc) desc (car desc))) | ||
| 270 | (help-echo (concat (car format) ": " label))) | ||
| 271 | ;; Truncate labels if necessary. | ||
| 272 | (and (> width 6) | ||
| 273 | (> (length label) width) | ||
| 274 | (setq label (concat (substring desc 0 (- width 3)) | ||
| 275 | "..."))) | ||
| 276 | (if (stringp desc) | ||
| 277 | (insert (propertize label 'help-echo help-echo)) | ||
| 278 | (apply 'insert-text-button label (cdr desc))) | ||
| 279 | (setq x (+ x 1 width))) | ||
| 280 | ;; No need to append any spaces if this is the last column. | ||
| 281 | (if (< (1+ n) len) | ||
| 282 | (indent-to x 1))) | ||
| 283 | (insert ?\n) | ||
| 284 | (put-text-property beg (point) 'tabulated-list-id id))) | ||
| 285 | |||
| 286 | (defun tabulated-list-col-sort (&optional e) | ||
| 287 | "Sort Tabulated List entries by the column of the mouse click E." | ||
| 288 | (interactive "e") | ||
| 289 | (let* ((pos (event-start e)) | ||
| 290 | (obj (posn-object pos)) | ||
| 291 | (name (get-text-property (if obj (cdr obj) (posn-point pos)) | ||
| 292 | 'tabulated-list-column-name | ||
| 293 | (car obj)))) | ||
| 294 | (with-current-buffer (window-buffer (posn-window pos)) | ||
| 295 | (when (derived-mode-p 'tabulated-list-mode) | ||
| 296 | ;; Flip the sort order on a second click. | ||
| 297 | (if (equal name (car tabulated-list-sort-key)) | ||
| 298 | (setcdr tabulated-list-sort-key | ||
| 299 | (not (cdr tabulated-list-sort-key))) | ||
| 300 | (setq tabulated-list-sort-key (cons name nil))) | ||
| 301 | (tabulated-list-init-header) | ||
| 302 | (tabulated-list-print t))))) | ||
| 303 | |||
| 304 | ;;; The mode definition: | ||
| 305 | |||
| 306 | ;;;###autoload | ||
| 307 | (define-derived-mode tabulated-list-mode special-mode "Tabulated" | ||
| 308 | "Generic major mode for browsing a list of items. | ||
| 309 | This mode is usually not used directly; instead, other major | ||
| 310 | modes are derived from it, using `define-derived-mode'. | ||
| 311 | |||
| 312 | In this major mode, the buffer is divided into multiple columns, | ||
| 313 | which are labelled using the header line. Each non-empty line | ||
| 314 | belongs to one \"entry\", and the entries can be sorted according | ||
| 315 | to their column values. | ||
| 316 | |||
| 317 | An inheriting mode should usually do the following in their body: | ||
| 318 | |||
| 319 | - Set `tabulated-list-format', specifying the column format. | ||
| 320 | - Set `tabulated-list-revert-hook', if the buffer contents need | ||
| 321 | to be specially recomputed prior to `revert-buffer'. | ||
| 322 | - Maybe set a `tabulated-list-entries' function (see below). | ||
| 323 | - Maybe set `tabulated-list-printer' (see below). | ||
| 324 | - Maybe set `tabulated-list-padding'. | ||
| 325 | - Call `tabulated-list-init-header' to initialize `header-line-format' | ||
| 326 | according to `tabulated-list-format'. | ||
| 327 | |||
| 328 | An inheriting mode is usually accompanied by a \"list-FOO\" | ||
| 329 | command (e.g. `list-packages', `list-processes'). This command | ||
| 330 | creates or switches to a buffer and enables the major mode in | ||
| 331 | that buffer. If `tabulated-list-entries' is not a function, the | ||
| 332 | command should initialize it to a list of entries for displaying. | ||
| 333 | Finally, it should call `tabulated-list-print'. | ||
| 334 | |||
| 335 | `tabulated-list-print' calls the printer function specified by | ||
| 336 | `tabulated-list-printer', once for each entry. The default | ||
| 337 | printer is `tabulated-list-print-entry', but a mode that keeps | ||
| 338 | data in an ewoc may instead specify a printer function (e.g., one | ||
| 339 | that calls `ewoc-enter-last'), with `tabulated-list-print-entry' | ||
| 340 | as the ewoc pretty-printer." | ||
| 341 | (setq truncate-lines t) | ||
| 342 | (setq buffer-read-only t) | ||
| 343 | (set (make-local-variable 'revert-buffer-function) | ||
| 344 | 'tabulated-list-revert)) | ||
| 345 | |||
| 346 | (put 'tabulated-list-mode 'mode-class 'special) | ||
| 347 | |||
| 348 | (provide 'tabulated-list) | ||
| 349 | |||
| 350 | ;; Local Variables: | ||
| 351 | ;; coding: utf-8 | ||
| 352 | ;; lexical-binding: t | ||
| 353 | ;; End: | ||
| 354 | |||
| 355 | ;;; tabulated-list.el ends here | ||
diff --git a/lisp/files.el b/lisp/files.el index e87c25f3575..5b29f3790e8 100644 --- a/lisp/files.el +++ b/lisp/files.el | |||
| @@ -1140,6 +1140,37 @@ it means chase no more than that many links and then stop." | |||
| 1140 | (setq count (1+ count)))) | 1140 | (setq count (1+ count)))) |
| 1141 | newname)) | 1141 | newname)) |
| 1142 | 1142 | ||
| 1143 | ;; A handy function to display file sizes in human-readable form. | ||
| 1144 | ;; See http://en.wikipedia.org/wiki/Kibibyte for the reference. | ||
| 1145 | (defun file-size-human-readable (file-size &optional flavor) | ||
| 1146 | "Produce a string showing FILE-SIZE in human-readable form. | ||
| 1147 | |||
| 1148 | Optional second argument FLAVOR controls the units and the display format: | ||
| 1149 | |||
| 1150 | If FLAVOR is nil or omitted, each kilobyte is 1024 bytes and the produced | ||
| 1151 | suffixes are \"k\", \"M\", \"G\", \"T\", etc. | ||
| 1152 | If FLAVOR is `si', each kilobyte is 1000 bytes and the produced suffixes | ||
| 1153 | are \"k\", \"M\", \"G\", \"T\", etc. | ||
| 1154 | If FLAVOR is `iec', each kilobyte is 1024 bytes and the produced suffixes | ||
| 1155 | are \"KiB\", \"MiB\", \"GiB\", \"TiB\", etc." | ||
| 1156 | (let ((power (if (or (null flavor) (eq flavor 'iec)) | ||
| 1157 | 1024.0 | ||
| 1158 | 1000.0)) | ||
| 1159 | (post-fixes | ||
| 1160 | ;; none, kilo, mega, giga, tera, peta, exa, zetta, yotta | ||
| 1161 | (list "" "k" "M" "G" "T" "P" "E" "Z" "Y"))) | ||
| 1162 | (while (and (>= file-size power) (cdr post-fixes)) | ||
| 1163 | (setq file-size (/ file-size power) | ||
| 1164 | post-fixes (cdr post-fixes))) | ||
| 1165 | (format (if (> (mod file-size 1.0) 0.05) | ||
| 1166 | "%.1f%s%s" | ||
| 1167 | "%.0f%s%s") | ||
| 1168 | file-size | ||
| 1169 | (if (and (eq flavor 'iec) (string= (car post-fixes) "k")) | ||
| 1170 | "K" | ||
| 1171 | (car post-fixes)) | ||
| 1172 | (if (eq flavor 'iec) "iB" "")))) | ||
| 1173 | |||
| 1143 | (defun make-temp-file (prefix &optional dir-flag suffix) | 1174 | (defun make-temp-file (prefix &optional dir-flag suffix) |
| 1144 | "Create a temporary file. | 1175 | "Create a temporary file. |
| 1145 | The returned file name (created by appending some random characters at the end | 1176 | The returned file name (created by appending some random characters at the end |
| @@ -2100,10 +2131,8 @@ the file contents into it using `insert-file-contents-literally'." | |||
| 2100 | (confirm-nonexistent-file-or-buffer)))) | 2131 | (confirm-nonexistent-file-or-buffer)))) |
| 2101 | (switch-to-buffer (find-file-noselect filename nil t))) | 2132 | (switch-to-buffer (find-file-noselect filename nil t))) |
| 2102 | 2133 | ||
| 2103 | (defvar after-find-file-from-revert-buffer nil) | ||
| 2104 | |||
| 2105 | (defun after-find-file (&optional error warn noauto | 2134 | (defun after-find-file (&optional error warn noauto |
| 2106 | after-find-file-from-revert-buffer | 2135 | _after-find-file-from-revert-buffer |
| 2107 | nomodes) | 2136 | nomodes) |
| 2108 | "Called after finding a file and by the default revert function. | 2137 | "Called after finding a file and by the default revert function. |
| 2109 | Sets buffer mode, parses local variables. | 2138 | Sets buffer mode, parses local variables. |
| @@ -2111,8 +2140,8 @@ Optional args ERROR, WARN, and NOAUTO: ERROR non-nil means there was an | |||
| 2111 | error in reading the file. WARN non-nil means warn if there | 2140 | error in reading the file. WARN non-nil means warn if there |
| 2112 | exists an auto-save file more recent than the visited file. | 2141 | exists an auto-save file more recent than the visited file. |
| 2113 | NOAUTO means don't mess with auto-save mode. | 2142 | NOAUTO means don't mess with auto-save mode. |
| 2114 | Fourth arg AFTER-FIND-FILE-FROM-REVERT-BUFFER non-nil | 2143 | Fourth arg AFTER-FIND-FILE-FROM-REVERT-BUFFER is ignored |
| 2115 | means this call was from `revert-buffer'. | 2144 | \(see `revert-buffer-in-progress-p' for similar functionality). |
| 2116 | Fifth arg NOMODES non-nil means don't alter the file's modes. | 2145 | Fifth arg NOMODES non-nil means don't alter the file's modes. |
| 2117 | Finishes by calling the functions in `find-file-hook' | 2146 | Finishes by calling the functions in `find-file-hook' |
| 2118 | unless NOMODES is non-nil." | 2147 | unless NOMODES is non-nil." |
| @@ -5004,6 +5033,10 @@ hook functions. | |||
| 5004 | If `revert-buffer-function' is used to override the normal revert | 5033 | If `revert-buffer-function' is used to override the normal revert |
| 5005 | mechanism, this hook is not used.") | 5034 | mechanism, this hook is not used.") |
| 5006 | 5035 | ||
| 5036 | (defvar revert-buffer-in-progress-p nil | ||
| 5037 | "Non-nil if a `revert-buffer' operation is in progress, nil otherwise. | ||
| 5038 | This is true even if a `revert-buffer-function' is being used.") | ||
| 5039 | |||
| 5007 | (defvar revert-buffer-internal-hook) | 5040 | (defvar revert-buffer-internal-hook) |
| 5008 | 5041 | ||
| 5009 | (defun revert-buffer (&optional ignore-auto noconfirm preserve-modes) | 5042 | (defun revert-buffer (&optional ignore-auto noconfirm preserve-modes) |
| @@ -5046,10 +5079,12 @@ non-nil, it is called instead of rereading visited file contents." | |||
| 5046 | ;; interface, but leaving the programmatic interface the same. | 5079 | ;; interface, but leaving the programmatic interface the same. |
| 5047 | (interactive (list (not current-prefix-arg))) | 5080 | (interactive (list (not current-prefix-arg))) |
| 5048 | (if revert-buffer-function | 5081 | (if revert-buffer-function |
| 5049 | (funcall revert-buffer-function ignore-auto noconfirm) | 5082 | (let ((revert-buffer-in-progress-p t)) |
| 5083 | (funcall revert-buffer-function ignore-auto noconfirm)) | ||
| 5050 | (with-current-buffer (or (buffer-base-buffer (current-buffer)) | 5084 | (with-current-buffer (or (buffer-base-buffer (current-buffer)) |
| 5051 | (current-buffer)) | 5085 | (current-buffer)) |
| 5052 | (let* ((auto-save-p (and (not ignore-auto) | 5086 | (let* ((revert-buffer-in-progress-p t) |
| 5087 | (auto-save-p (and (not ignore-auto) | ||
| 5053 | (recent-auto-save-p) | 5088 | (recent-auto-save-p) |
| 5054 | buffer-auto-save-file-name | 5089 | buffer-auto-save-file-name |
| 5055 | (file-readable-p buffer-auto-save-file-name) | 5090 | (file-readable-p buffer-auto-save-file-name) |
| @@ -5140,7 +5175,7 @@ non-nil, it is called instead of rereading visited file contents." | |||
| 5140 | ;; have changed the truename. | 5175 | ;; have changed the truename. |
| 5141 | (setq buffer-file-truename | 5176 | (setq buffer-file-truename |
| 5142 | (abbreviate-file-name (file-truename buffer-file-name))) | 5177 | (abbreviate-file-name (file-truename buffer-file-name))) |
| 5143 | (after-find-file nil nil t t preserve-modes) | 5178 | (after-find-file nil nil t nil preserve-modes) |
| 5144 | ;; Run after-revert-hook as it was before we reverted. | 5179 | ;; Run after-revert-hook as it was before we reverted. |
| 5145 | (setq-default revert-buffer-internal-hook global-hook) | 5180 | (setq-default revert-buffer-internal-hook global-hook) |
| 5146 | (if local-hook | 5181 | (if local-hook |
| @@ -6142,8 +6177,8 @@ With prefix ARG, silently save all file-visiting buffers, then kill." | |||
| 6142 | (setq active t)) | 6177 | (setq active t)) |
| 6143 | (setq processes (cdr processes))) | 6178 | (setq processes (cdr processes))) |
| 6144 | (or (not active) | 6179 | (or (not active) |
| 6145 | (list-processes t) | 6180 | (progn (list-processes t) |
| 6146 | (yes-or-no-p "Active processes exist; kill them and exit anyway? ")))) | 6181 | (yes-or-no-p "Active processes exist; kill them and exit anyway? "))))) |
| 6147 | ;; Query the user for other things, perhaps. | 6182 | ;; Query the user for other things, perhaps. |
| 6148 | (run-hook-with-args-until-failure 'kill-emacs-query-functions) | 6183 | (run-hook-with-args-until-failure 'kill-emacs-query-functions) |
| 6149 | (or (null confirm-kill-emacs) | 6184 | (or (null confirm-kill-emacs) |
diff --git a/lisp/follow.el b/lisp/follow.el index 7f4093dd442..c76085f6dcb 100644 --- a/lisp/follow.el +++ b/lisp/follow.el | |||
| @@ -1061,7 +1061,7 @@ Return the selected window." | |||
| 1061 | ;; it wasn't just moved here. (i.e. M-> shall not unconditionally place | 1061 | ;; it wasn't just moved here. (i.e. M-> shall not unconditionally place |
| 1062 | ;; the point in the selected window.) | 1062 | ;; the point in the selected window.) |
| 1063 | ;; | 1063 | ;; |
| 1064 | ;; (Compability cludge: in Emacs `window-end' is equal to `point-max'; | 1064 | ;; (Compatibility cludge: in Emacs `window-end' is equal to `point-max'; |
| 1065 | ;; in XEmacs, it is equal to `point-max + 1'. Should I really bother | 1065 | ;; in XEmacs, it is equal to `point-max + 1'. Should I really bother |
| 1066 | ;; checking `window-end' now when I check `end-of-buffer' explicitly?) | 1066 | ;; checking `window-end' now when I check `end-of-buffer' explicitly?) |
| 1067 | 1067 | ||
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index b79a5de55e1..baabe5f65b9 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,10 +1,53 @@ | |||
| 1 | 2011-04-07 Teodor Zlatanov <tzz@lifelogs.com> | ||
| 2 | |||
| 3 | * gnus-registry.el (gnus-registry-handle-action): More debugging. | ||
| 4 | |||
| 5 | * gnus-start.el (gnus-gnus-to-newsrc-format): Add a way to run | ||
| 6 | interactively so the newsrc file can contain foreign groups too. | ||
| 7 | Useful for debugging but not much for users. | ||
| 8 | |||
| 9 | 2011-04-07 David Engster <dengste@eml.cc> | ||
| 10 | |||
| 11 | * registry.el (registry-usage-test): Only do | ||
| 12 | `registry-lookup-breaks-before-lexbind' testing for Emacs24 with | ||
| 13 | lexical binding. | ||
| 14 | |||
| 15 | 2011-04-06 David Engster <dengste@eml.cc> | ||
| 16 | |||
| 17 | * registry.el, gnus-registry.el: Use `ignore-errors' instead of third | ||
| 18 | argument NOERROR for `require', since XEmacs 21.4 does not support it. | ||
| 19 | |||
| 20 | 2011-04-06 David Engster <dengste@eml.cc> | ||
| 21 | |||
| 22 | * registry.el (initialize-instance): Change :after to :AFTER to be | ||
| 23 | compatible with old EIEIO version in XEmacs. | ||
| 24 | |||
| 25 | 2011-04-06 Teodor Zlatanov <tzz@lifelogs.com> | ||
| 26 | |||
| 27 | * gnus-registry.el (gnus-registry-post-process-groups) | ||
| 28 | (gnus-registry--split-fancy-with-parent-internal): Fix splitting bugs | ||
| 29 | and provide better messaging. | ||
| 30 | |||
| 31 | 2011-04-06 David Engster <dengste@eml.cc> | ||
| 32 | |||
| 33 | * Makefile.in (fail-on-warning): New rule to compile with warnings as | ||
| 34 | errors. | ||
| 35 | |||
| 36 | * dgnushack.el (dgnushack-compile-error-on-warn): New function to call | ||
| 37 | dgnushack-compile with error-on-warn enabled, and to signal an error if | ||
| 38 | clean compilation failed. | ||
| 39 | (dgnushack-compile): New argument 'error-on-warn'. If non-nil, compile | ||
| 40 | with `byte-compile-error-on-warn'. Return nil if errors occured. | ||
| 41 | |||
| 1 | 2011-04-06 Teodor Zlatanov <tzz@lifelogs.com> | 42 | 2011-04-06 Teodor Zlatanov <tzz@lifelogs.com> |
| 2 | 43 | ||
| 3 | * gnus-registry.el: Don't use ERT if it's not available. | 44 | * gnus-registry.el: Don't use ERT if it's not available. Load it |
| 45 | unconditionally anyway, discarding errors. | ||
| 4 | (gnus-registry-delete-entries): New convenience function. | 46 | (gnus-registry-delete-entries): New convenience function. |
| 5 | (gnus-registry-import-eld): Import from old .eld registry. | 47 | (gnus-registry-import-eld): Import from old .eld registry. |
| 6 | 48 | ||
| 7 | * registry.el: Don't use ERT if it's not available. | 49 | * registry.el: Don't use ERT if it's not available. Load it |
| 50 | unconditionally anyway, discarding errors. | ||
| 8 | 51 | ||
| 9 | * proto-stream.el (gnutls-negotiate): Revert inadvertent commit of the | 52 | * proto-stream.el (gnutls-negotiate): Revert inadvertent commit of the |
| 10 | version from the Claudio Bley GnuTLS patch (extra optional parameters | 53 | version from the Claudio Bley GnuTLS patch (extra optional parameters |
| @@ -15171,7 +15214,7 @@ | |||
| 15171 | * smime-ldap.el (smime-ldap-search): Add compatibility for XEmacs. | 15214 | * smime-ldap.el (smime-ldap-search): Add compatibility for XEmacs. |
| 15172 | 15215 | ||
| 15173 | * smime.el (smime-cert-by-ldap-1): Handle certificates distributed | 15216 | * smime.el (smime-cert-by-ldap-1): Handle certificates distributed |
| 15174 | in PEM format. Adjust to the XEmacs compability. | 15217 | in PEM format. Adjust to the XEmacs compatibility. |
| 15175 | 15218 | ||
| 15176 | 2005-05-30 Reiner Steib <Reiner.Steib@gmx.de> | 15219 | 2005-05-30 Reiner Steib <Reiner.Steib@gmx.de> |
| 15177 | 15220 | ||
diff --git a/lisp/gnus/gnus-registry.el b/lisp/gnus/gnus-registry.el index 511012df577..9824fc26f16 100644 --- a/lisp/gnus/gnus-registry.el +++ b/lisp/gnus/gnus-registry.el | |||
| @@ -58,9 +58,11 @@ | |||
| 58 | (eval-when-compile (require 'cl)) | 58 | (eval-when-compile (require 'cl)) |
| 59 | 59 | ||
| 60 | (eval-when-compile | 60 | (eval-when-compile |
| 61 | (when (null (require 'ert nil t)) | 61 | (when (null (ignore-errors (require 'ert))) |
| 62 | (defmacro* ert-deftest (name () &body docstring-keys-and-body)))) | 62 | (defmacro* ert-deftest (name () &body docstring-keys-and-body)))) |
| 63 | 63 | ||
| 64 | (ignore-errors | ||
| 65 | (require 'ert)) | ||
| 64 | (require 'gnus) | 66 | (require 'gnus) |
| 65 | (require 'gnus-int) | 67 | (require 'gnus-int) |
| 66 | (require 'gnus-sum) | 68 | (require 'gnus-sum) |
| @@ -319,6 +321,9 @@ This is not required after changing `gnus-registry-cache-file'." | |||
| 319 | (gnus-registry-handle-action id nil to subject sender))) | 321 | (gnus-registry-handle-action id nil to subject sender))) |
| 320 | 322 | ||
| 321 | (defun gnus-registry-handle-action (id from to subject sender) | 323 | (defun gnus-registry-handle-action (id from to subject sender) |
| 324 | (gnus-message | ||
| 325 | 10 | ||
| 326 | "gnus-registry-handle-action %S" (list id from to subject sender)) | ||
| 322 | (let ((db gnus-registry-db) | 327 | (let ((db gnus-registry-db) |
| 323 | ;; safe if not found | 328 | ;; safe if not found |
| 324 | (entry (gnus-registry-get-or-make-entry id))) | 329 | (entry (gnus-registry-get-or-make-entry id))) |
| @@ -394,85 +399,83 @@ See the Info node `(gnus)Fancy Mail Splitting' for more details." | |||
| 394 | &allow-other-keys) | 399 | &allow-other-keys) |
| 395 | (gnus-message | 400 | (gnus-message |
| 396 | 10 | 401 | 10 |
| 397 | "gnus-registry--split-fancy-with-parent-internal: %S" spec) | 402 | "gnus-registry--split-fancy-with-parent-internal %S" spec) |
| 398 | (let ((db gnus-registry-db) | 403 | (let ((db gnus-registry-db) |
| 399 | found) | 404 | found) |
| 400 | ;; this is a big if-else statement. it uses | 405 | ;; this is a big chain of statements. it uses |
| 401 | ;; gnus-registry-post-process-groups to filter the results after | 406 | ;; gnus-registry-post-process-groups to filter the results after |
| 402 | ;; every step. | 407 | ;; every step. |
| 403 | (cond | 408 | ;; the references string must be valid and parse to valid references |
| 404 | ;; the references string must be valid and parse to valid references | 409 | (when references |
| 405 | (references | 410 | (gnus-message |
| 411 | 9 | ||
| 412 | "%s is tracing references %s" | ||
| 413 | log-agent refstr) | ||
| 406 | (dolist (reference (nreverse references)) | 414 | (dolist (reference (nreverse references)) |
| 407 | (gnus-message | 415 | (gnus-message 9 "%s is looking up %s" log-agent reference) |
| 408 | 9 | 416 | (loop for group in (gnus-registry-get-id-key reference 'group) |
| 409 | "%s is looking for matches for reference %s from [%s]" | 417 | when (gnus-registry-follow-group-p group) |
| 410 | log-agent reference refstr) | 418 | do (gnus-message 7 "%s traced %s to %s" log-agent reference group) |
| 411 | (setq found | 419 | do (push group found))) |
| 412 | (loop for group in (gnus-registry-get-id-key reference 'group) | ||
| 413 | when (gnus-registry-follow-group-p group) | ||
| 414 | do (gnus-message | ||
| 415 | 7 | ||
| 416 | "%s traced the reference %s from [%s] to group %s" | ||
| 417 | log-agent reference refstr group) | ||
| 418 | collect group))) | ||
| 419 | ;; filter the found groups and return them | 420 | ;; filter the found groups and return them |
| 420 | ;; the found groups are the full groups | 421 | ;; the found groups are the full groups |
| 421 | (setq found (gnus-registry-post-process-groups | 422 | (setq found (gnus-registry-post-process-groups |
| 422 | "references" refstr found))) | 423 | "references" refstr found))) |
| 423 | 424 | ||
| 424 | ;; else: there were no matches, try the extra tracking by sender | 425 | ;; else: there were no matches, try the extra tracking by sender |
| 425 | ((and (memq 'sender gnus-registry-track-extra) | 426 | (when (and (null found) |
| 426 | sender | 427 | (memq 'sender gnus-registry-track-extra) |
| 427 | (gnus-grep-in-list | 428 | sender |
| 428 | sender | 429 | (gnus-grep-in-list |
| 429 | gnus-registry-unfollowed-addresses)) | 430 | sender |
| 430 | (let ((groups (apply | 431 | gnus-registry-unfollowed-addresses)) |
| 431 | 'append | 432 | (let ((groups (apply |
| 432 | (mapcar | 433 | 'append |
| 433 | (lambda (reference) | 434 | (mapcar |
| 434 | (gnus-registry-get-id-key reference 'group)) | 435 | (lambda (reference) |
| 435 | (registry-lookup-secondary-value db 'sender sender))))) | 436 | (gnus-registry-get-id-key reference 'group)) |
| 436 | (setq found | 437 | (registry-lookup-secondary-value db 'sender sender))))) |
| 437 | (loop for group in groups | 438 | (setq found |
| 438 | when (gnus-registry-follow-group-p group) | 439 | (loop for group in groups |
| 439 | do (gnus-message | 440 | when (gnus-registry-follow-group-p group) |
| 440 | ;; raise level of messaging if gnus-registry-track-extra | 441 | do (gnus-message |
| 441 | (if gnus-registry-track-extra 7 9) | 442 | ;; warn more if gnus-registry-track-extra |
| 442 | "%s (extra tracking) traced sender '%s' to groups %s" | 443 | (if gnus-registry-track-extra 7 9) |
| 443 | log-agent sender found) | 444 | "%s (extra tracking) traced sender '%s' to %s" |
| 444 | collect group))) | 445 | log-agent sender group) |
| 445 | 446 | collect group))) | |
| 446 | ;; filter the found groups and return them | 447 | |
| 447 | ;; the found groups are NOT the full groups | 448 | ;; filter the found groups and return them |
| 448 | (setq found (gnus-registry-post-process-groups | 449 | ;; the found groups are NOT the full groups |
| 449 | "sender" sender found))) | 450 | (setq found (gnus-registry-post-process-groups |
| 451 | "sender" sender found))) | ||
| 450 | 452 | ||
| 451 | ;; else: there were no matches, now try the extra tracking by subject | 453 | ;; else: there were no matches, now try the extra tracking by subject |
| 452 | ((and (memq 'subject gnus-registry-track-extra) | 454 | (when (and (null found) |
| 453 | subject | 455 | (memq 'subject gnus-registry-track-extra) |
| 454 | (< gnus-registry-minimum-subject-length (length subject))) | 456 | subject |
| 455 | (let ((groups (apply | 457 | (< gnus-registry-minimum-subject-length (length subject))) |
| 456 | 'append | 458 | (let ((groups (apply |
| 457 | (mapcar | 459 | 'append |
| 458 | (lambda (reference) | 460 | (mapcar |
| 459 | (gnus-registry-get-id-key reference 'group)) | 461 | (lambda (reference) |
| 460 | (registry-lookup-secondary-value db 'subject subject))))) | 462 | (gnus-registry-get-id-key reference 'group)) |
| 461 | (setq found | 463 | (registry-lookup-secondary-value db 'subject subject))))) |
| 462 | (loop for group in groups | 464 | (setq found |
| 463 | when (gnus-registry-follow-group-p group) | 465 | (loop for group in groups |
| 464 | do (gnus-message | 466 | when (gnus-registry-follow-group-p group) |
| 465 | ;; raise level of messaging if gnus-registry-track-extra | 467 | do (gnus-message |
| 466 | (if gnus-registry-track-extra 7 9) | 468 | ;; warn more if gnus-registry-track-extra |
| 467 | "%s (extra tracking) traced subject '%s' to groups %s" | 469 | (if gnus-registry-track-extra 7 9) |
| 468 | log-agent subject found) | 470 | "%s (extra tracking) traced subject '%s' to %s" |
| 469 | collect group)) | 471 | log-agent subject group) |
| 470 | ;; filter the found groups and return them | 472 | collect group)) |
| 471 | ;; the found groups are NOT the full groups | 473 | ;; filter the found groups and return them |
| 472 | (setq found (gnus-registry-post-process-groups | 474 | ;; the found groups are NOT the full groups |
| 473 | "subject" subject found))))) | 475 | (setq found (gnus-registry-post-process-groups |
| 474 | ;; after the (cond) we extract the actual value safely | 476 | "subject" subject found)))) |
| 475 | (car-safe found))) | 477 | ;; after the (cond) we extract the actual value safely |
| 478 | (car-safe found))) | ||
| 476 | 479 | ||
| 477 | (defun gnus-registry-post-process-groups (mode key groups) | 480 | (defun gnus-registry-post-process-groups (mode key groups) |
| 478 | "Inspects GROUPS found by MODE for KEY to determine which ones to follow. | 481 | "Inspects GROUPS found by MODE for KEY to determine which ones to follow. |
| @@ -489,25 +492,48 @@ Foreign methods are not supported so they are rejected. | |||
| 489 | Reduces the list to a single group, or complains if that's not | 492 | Reduces the list to a single group, or complains if that's not |
| 490 | possible. Uses `gnus-registry-split-strategy'." | 493 | possible. Uses `gnus-registry-split-strategy'." |
| 491 | (let ((log-agent "gnus-registry-post-process-group") | 494 | (let ((log-agent "gnus-registry-post-process-group") |
| 492 | out) | 495 | (desc (format "%d groups" (length groups))) |
| 493 | 496 | out chosen) | |
| 494 | ;; the strategy can be nil, in which case groups is nil | 497 | ;; the strategy can be nil, in which case chosen is nil |
| 495 | (setq groups | 498 | (setq chosen |
| 496 | (case gnus-registry-split-strategy | 499 | (case gnus-registry-split-strategy |
| 497 | ;; first strategy | 500 | ;; default, take only one-element lists into chosen |
| 501 | ((nil) | ||
| 502 | (and (= (length groups) 1) | ||
| 503 | (car-safe groups))) | ||
| 504 | |||
| 498 | ((first) | 505 | ((first) |
| 499 | (and groups (list (car-safe groups)))) | 506 | (car-safe groups)) |
| 500 | 507 | ||
| 501 | ((majority) | 508 | ((majority) |
| 502 | (let ((freq (make-hash-table | 509 | (let ((freq (make-hash-table |
| 503 | :size 256 | 510 | :size 256 |
| 504 | :test 'equal))) | 511 | :test 'equal))) |
| 505 | (mapc (lambda (x) (puthash x (1+ (gethash x freq 0)) freq)) | 512 | (mapc (lambda (x) (let ((x (gnus-group-short-name x))) |
| 513 | (puthash x (1+ (gethash x freq 0)) freq))) | ||
| 506 | groups) | 514 | groups) |
| 507 | (list (car-safe | 515 | (setq desc (format "%d groups, %d unique" |
| 508 | (sort groups (lambda (a b) | 516 | (length groups) |
| 509 | (> (gethash a freq 0) | 517 | (hash-table-count freq))) |
| 510 | (gethash b freq 0)))))))))) | 518 | (car-safe |
| 519 | (sort groups | ||
| 520 | (lambda (a b) | ||
| 521 | (> (gethash (gnus-group-short-name a) freq 0) | ||
| 522 | (gethash (gnus-group-short-name b) freq 0))))))))) | ||
| 523 | |||
| 524 | (if chosen | ||
| 525 | (gnus-message | ||
| 526 | 9 | ||
| 527 | "%s: strategy %s on %s produced %s" | ||
| 528 | log-agent gnus-registry-split-strategy desc chosen) | ||
| 529 | (gnus-message | ||
| 530 | 9 | ||
| 531 | "%s: strategy %s on %s did not produce an answer" | ||
| 532 | log-agent | ||
| 533 | (or gnus-registry-split-strategy "default") | ||
| 534 | desc)) | ||
| 535 | |||
| 536 | (setq groups (and chosen (list chosen))) | ||
| 511 | 537 | ||
| 512 | (dolist (group groups) | 538 | (dolist (group groups) |
| 513 | (let ((m1 (gnus-find-method-for-group group)) | 539 | (let ((m1 (gnus-find-method-for-group group)) |
| @@ -517,18 +543,20 @@ possible. Uses `gnus-registry-split-strategy'." | |||
| 517 | (if (gnus-methods-equal-p m1 m2) | 543 | (if (gnus-methods-equal-p m1 m2) |
| 518 | (progn | 544 | (progn |
| 519 | ;; this is REALLY just for debugging | 545 | ;; this is REALLY just for debugging |
| 520 | (gnus-message | 546 | (when (not (equal group short-name)) |
| 521 | 10 | 547 | (gnus-message |
| 522 | "%s stripped group %s to %s" | 548 | 10 |
| 523 | log-agent group short-name) | 549 | "%s: stripped group %s to %s" |
| 550 | log-agent group short-name)) | ||
| 524 | (add-to-list 'out short-name)) | 551 | (add-to-list 'out short-name)) |
| 525 | ;; else... | 552 | ;; else... |
| 526 | (gnus-message | 553 | (gnus-message |
| 527 | 7 | 554 | 7 |
| 528 | "%s ignored foreign group %s" | 555 | "%s: ignored foreign group %s" |
| 529 | log-agent group)))) | 556 | log-agent group)))) |
| 530 | 557 | ||
| 531 | ;; is there just one group? | 558 | (setq out (delq nil out)) |
| 559 | |||
| 532 | (cond | 560 | (cond |
| 533 | ((= (length out) 1) out) | 561 | ((= (length out) 1) out) |
| 534 | ((null out) | 562 | ((null out) |
diff --git a/lisp/gnus/gnus-start.el b/lisp/gnus/gnus-start.el index fa582c58aee..d9d218c6cba 100644 --- a/lisp/gnus/gnus-start.el +++ b/lisp/gnus/gnus-start.el | |||
| @@ -2873,7 +2873,8 @@ If FORCE is non-nil, the .newsrc file is read." | |||
| 2873 | (pop list)) | 2873 | (pop list)) |
| 2874 | (nreverse olist))) | 2874 | (nreverse olist))) |
| 2875 | 2875 | ||
| 2876 | (defun gnus-gnus-to-newsrc-format () | 2876 | (defun gnus-gnus-to-newsrc-format (&optional foreign-ok) |
| 2877 | (interactive (list (gnus-y-or-n-p "write foreign groups too? "))) | ||
| 2877 | ;; Generate and save the .newsrc file. | 2878 | ;; Generate and save the .newsrc file. |
| 2878 | (with-current-buffer (create-file-buffer gnus-current-startup-file) | 2879 | (with-current-buffer (create-file-buffer gnus-current-startup-file) |
| 2879 | (let ((newsrc (cdr gnus-newsrc-alist)) | 2880 | (let ((newsrc (cdr gnus-newsrc-alist)) |
| @@ -2895,7 +2896,8 @@ If FORCE is non-nil, the .newsrc file is read." | |||
| 2895 | ;; Don't write foreign groups to .newsrc. | 2896 | ;; Don't write foreign groups to .newsrc. |
| 2896 | (when (or (null (setq method (gnus-info-method info))) | 2897 | (when (or (null (setq method (gnus-info-method info))) |
| 2897 | (equal method "native") | 2898 | (equal method "native") |
| 2898 | (inline (gnus-server-equal method gnus-select-method))) | 2899 | (inline (gnus-server-equal method gnus-select-method)) |
| 2900 | foreign-ok) | ||
| 2899 | (insert (gnus-info-group info) | 2901 | (insert (gnus-info-group info) |
| 2900 | (if (> (gnus-info-level info) gnus-level-subscribed) | 2902 | (if (> (gnus-info-level info) gnus-level-subscribed) |
| 2901 | "!" ":")) | 2903 | "!" ":")) |
diff --git a/lisp/gnus/registry.el b/lisp/gnus/registry.el index cc03b20662d..3c402cb361a 100644 --- a/lisp/gnus/registry.el +++ b/lisp/gnus/registry.el | |||
| @@ -78,9 +78,12 @@ | |||
| 78 | ;;; Code: | 78 | ;;; Code: |
| 79 | 79 | ||
| 80 | (eval-when-compile | 80 | (eval-when-compile |
| 81 | (when (null (require 'ert nil t)) | 81 | (when (null (ignore-errors (require 'ert))) |
| 82 | (defmacro* ert-deftest (name () &body docstring-keys-and-body)))) | 82 | (defmacro* ert-deftest (name () &body docstring-keys-and-body)))) |
| 83 | 83 | ||
| 84 | (ignore-errors | ||
| 85 | (require 'ert)) | ||
| 86 | |||
| 84 | (eval-when-compile (require 'cl)) | 87 | (eval-when-compile (require 'cl)) |
| 85 | (eval-and-compile | 88 | (eval-and-compile |
| 86 | (or (ignore-errors (progn | 89 | (or (ignore-errors (progn |
| @@ -128,7 +131,7 @@ | |||
| 128 | :type hash-table | 131 | :type hash-table |
| 129 | :documentation "The data hashtable."))) | 132 | :documentation "The data hashtable."))) |
| 130 | 133 | ||
| 131 | (defmethod initialize-instance :after ((this registry-db) slots) | 134 | (defmethod initialize-instance :AFTER ((this registry-db) slots) |
| 132 | "Set value of data slot of THIS after initialization." | 135 | "Set value of data slot of THIS after initialization." |
| 133 | (with-slots (data tracker) this | 136 | (with-slots (data tracker) this |
| 134 | (unless (member :data slots) | 137 | (unless (member :data slots) |
| @@ -354,12 +357,13 @@ Removes only entries without the :precious keys." | |||
| 354 | (should (= 58 (caadr (registry-lookup db '(1 58 99))))) | 357 | (should (= 58 (caadr (registry-lookup db '(1 58 99))))) |
| 355 | (message "Grouped individual lookup") | 358 | (message "Grouped individual lookup") |
| 356 | (should (= 3 (length (registry-lookup db '(1 58 99))))) | 359 | (should (= 3 (length (registry-lookup db '(1 58 99))))) |
| 357 | (message "Individual lookup (breaks before lexbind)") | 360 | (when (boundp 'lexical-binding) |
| 358 | (should (= 58 | 361 | (message "Individual lookup (breaks before lexbind)") |
| 359 | (caadr (registry-lookup-breaks-before-lexbind db '(1 58 99))))) | 362 | (should (= 58 |
| 360 | (message "Grouped individual lookup (breaks before lexbind)") | 363 | (caadr (registry-lookup-breaks-before-lexbind db '(1 58 99))))) |
| 361 | (should (= 3 | 364 | (message "Grouped individual lookup (breaks before lexbind)") |
| 362 | (length (registry-lookup-breaks-before-lexbind db '(1 58 99))))) | 365 | (should (= 3 |
| 366 | (length (registry-lookup-breaks-before-lexbind db '(1 58 99)))))) | ||
| 363 | (message "Search") | 367 | (message "Search") |
| 364 | (should (= n (length (registry-search db :all t)))) | 368 | (should (= n (length (registry-search db :all t)))) |
| 365 | (should (= n (length (registry-search db :member '((sender "me")))))) | 369 | (should (= n (length (registry-search db :member '((sender "me")))))) |
diff --git a/lisp/help.el b/lisp/help.el index e148e5ef6ab..b7f46a02155 100644 --- a/lisp/help.el +++ b/lisp/help.el | |||
| @@ -1256,6 +1256,15 @@ Select help window if the actual value of the user option | |||
| 1256 | ;; Reset `help-window' to nil to avoid confusing future calls of | 1256 | ;; Reset `help-window' to nil to avoid confusing future calls of |
| 1257 | ;; `help-mode-finish' with plain `with-output-to-temp-buffer'. | 1257 | ;; `help-mode-finish' with plain `with-output-to-temp-buffer'. |
| 1258 | (setq help-window nil)))) | 1258 | (setq help-window nil)))) |
| 1259 | |||
| 1260 | ;; Called from C, on encountering `help-char' when reading a char. | ||
| 1261 | ;; Don't print to *Help*; that would clobber Help history. | ||
| 1262 | (defun help-form-show () | ||
| 1263 | "Display the output of a non-nil `help-form'." | ||
| 1264 | (let ((msg (eval help-form))) | ||
| 1265 | (if (stringp msg) | ||
| 1266 | (with-output-to-temp-buffer " *Char Help*" | ||
| 1267 | (princ msg))))) | ||
| 1259 | 1268 | ||
| 1260 | (provide 'help) | 1269 | (provide 'help) |
| 1261 | 1270 | ||
diff --git a/lisp/ls-lisp.el b/lisp/ls-lisp.el index 55ec835831a..9314f934dc1 100644 --- a/lisp/ls-lisp.el +++ b/lisp/ls-lisp.el | |||
| @@ -62,8 +62,6 @@ | |||
| 62 | 62 | ||
| 63 | ;;; Code: | 63 | ;;; Code: |
| 64 | 64 | ||
| 65 | (eval-when-compile (require 'cl)) | ||
| 66 | |||
| 67 | (defgroup ls-lisp nil | 65 | (defgroup ls-lisp nil |
| 68 | "Emulate the ls program completely in Emacs Lisp." | 66 | "Emulate the ls program completely in Emacs Lisp." |
| 69 | :version "21.1" | 67 | :version "21.1" |
| @@ -726,13 +724,7 @@ All ls time options, namely c, t and u, are handled." | |||
| 726 | ls-lisp-filesize-f-fmt | 724 | ls-lisp-filesize-f-fmt |
| 727 | ls-lisp-filesize-d-fmt) | 725 | ls-lisp-filesize-d-fmt) |
| 728 | file-size) | 726 | file-size) |
| 729 | (if (< file-size 1024) | 727 | (format " %7s" (file-size-human-readable file-size)))) |
| 730 | (format " %4d" file-size) | ||
| 731 | (do ((file-size (/ file-size 1024.0) (/ file-size 1024.0)) | ||
| 732 | ;; kilo, mega, giga, tera, peta, exa | ||
| 733 | (post-fixes (list "k" "M" "G" "T" "P" "E") (cdr post-fixes))) | ||
| 734 | ((< file-size 1024) | ||
| 735 | (format " %3.0f%s" file-size (car post-fixes))))))) | ||
| 736 | 728 | ||
| 737 | (provide 'ls-lisp) | 729 | (provide 'ls-lisp) |
| 738 | 730 | ||
diff --git a/lisp/man.el b/lisp/man.el index c8c2f8653e2..7a9e6e3cca5 100644 --- a/lisp/man.el +++ b/lisp/man.el | |||
| @@ -254,8 +254,7 @@ Used in `bookmark-set' to get the default bookmark name." | |||
| 254 | "Regular expression describing a manpage section within parentheses.") | 254 | "Regular expression describing a manpage section within parentheses.") |
| 255 | 255 | ||
| 256 | (defvar Man-page-header-regexp | 256 | (defvar Man-page-header-regexp |
| 257 | (if (and (string-match "-solaris2\\." system-configuration) | 257 | (if (string-match "-solaris2\\." system-configuration) |
| 258 | (not (string-match "-solaris2\\.[123435]$" system-configuration))) | ||
| 259 | (concat "^[-A-Za-z0-9_].*[ \t]\\(" Man-name-regexp | 258 | (concat "^[-A-Za-z0-9_].*[ \t]\\(" Man-name-regexp |
| 260 | "(\\(" Man-section-regexp "\\))\\)$") | 259 | "(\\(" Man-section-regexp "\\))\\)$") |
| 261 | (concat "^[ \t]*\\(" Man-name-regexp | 260 | (concat "^[ \t]*\\(" Man-name-regexp |
diff --git a/lisp/net/browse-url.el b/lisp/net/browse-url.el index 24dbfc0c30a..8f91fbb26b1 100644 --- a/lisp/net/browse-url.el +++ b/lisp/net/browse-url.el | |||
| @@ -1111,8 +1111,7 @@ URL in a new window." | |||
| 1111 | browse-url-firefox-program | 1111 | browse-url-firefox-program |
| 1112 | (append | 1112 | (append |
| 1113 | browse-url-firefox-arguments | 1113 | browse-url-firefox-arguments |
| 1114 | (if (or (featurep 'dos-w32) | 1114 | (if (memq system-type '(windows-nt ms-dos)) |
| 1115 | (string-match "win32" system-configuration)) | ||
| 1116 | (list url) | 1115 | (list url) |
| 1117 | (list "-remote" | 1116 | (list "-remote" |
| 1118 | (concat "openURL(" | 1117 | (concat "openURL(" |
diff --git a/lisp/net/rlogin.el b/lisp/net/rlogin.el index 91b4aa7d72e..e2619e3bf79 100644 --- a/lisp/net/rlogin.el +++ b/lisp/net/rlogin.el | |||
| @@ -60,14 +60,9 @@ | |||
| 60 | :group 'rlogin) | 60 | :group 'rlogin) |
| 61 | 61 | ||
| 62 | (defcustom rlogin-process-connection-type | 62 | (defcustom rlogin-process-connection-type |
| 63 | (save-match-data | 63 | ;; Solaris 2.x `rlogin' will spew a bunch of ioctl error messages if |
| 64 | ;; Solaris 2.x `rlogin' will spew a bunch of ioctl error messages if | 64 | ;; stdin isn't a tty. |
| 65 | ;; stdin isn't a tty. | 65 | (and (string-match-p "-solaris2" system-configuration) t) |
| 66 | (cond ((and (boundp 'system-configuration) | ||
| 67 | (stringp system-configuration) | ||
| 68 | (string-match "-solaris2" system-configuration)) | ||
| 69 | t) | ||
| 70 | (t nil))) | ||
| 71 | "If non-nil, use a pty for the local rlogin process. | 66 | "If non-nil, use a pty for the local rlogin process. |
| 72 | If nil, use a pipe (if pipes are supported on the local system). | 67 | If nil, use a pipe (if pipes are supported on the local system). |
| 73 | 68 | ||
| @@ -115,19 +110,19 @@ this variable is set from that." | |||
| 115 | :type '(choice (const nil) string) | 110 | :type '(choice (const nil) string) |
| 116 | :group 'rlogin) | 111 | :group 'rlogin) |
| 117 | 112 | ||
| 118 | ;; Initialize rlogin mode map. | 113 | (defvar rlogin-mode-map |
| 119 | (defvar rlogin-mode-map '()) | 114 | (let ((map (if (consp shell-mode-map) |
| 120 | (cond | 115 | (cons 'keymap shell-mode-map) |
| 121 | ((null rlogin-mode-map) | 116 | (copy-keymap shell-mode-map)))) |
| 122 | (setq rlogin-mode-map (if (consp shell-mode-map) | 117 | (define-key rlogin-mode-map "\C-c\C-c" 'rlogin-send-Ctrl-C) |
| 123 | (cons 'keymap shell-mode-map) | 118 | (define-key rlogin-mode-map "\C-c\C-d" 'rlogin-send-Ctrl-D) |
| 124 | (copy-keymap shell-mode-map))) | 119 | (define-key rlogin-mode-map "\C-c\C-z" 'rlogin-send-Ctrl-Z) |
| 125 | (define-key rlogin-mode-map "\C-c\C-c" 'rlogin-send-Ctrl-C) | 120 | (define-key rlogin-mode-map "\C-c\C-\\" 'rlogin-send-Ctrl-backslash) |
| 126 | (define-key rlogin-mode-map "\C-c\C-d" 'rlogin-send-Ctrl-D) | 121 | (define-key rlogin-mode-map "\C-d" 'rlogin-delchar-or-send-Ctrl-D) |
| 127 | (define-key rlogin-mode-map "\C-c\C-z" 'rlogin-send-Ctrl-Z) | 122 | (define-key rlogin-mode-map "\C-i" 'rlogin-tab-or-complete) |
| 128 | (define-key rlogin-mode-map "\C-c\C-\\" 'rlogin-send-Ctrl-backslash) | 123 | map) |
| 129 | (define-key rlogin-mode-map "\C-d" 'rlogin-delchar-or-send-Ctrl-D) | 124 | "Keymap for `rlogin-mode'.") |
| 130 | (define-key rlogin-mode-map "\C-i" 'rlogin-tab-or-complete))) | 125 | |
| 131 | 126 | ||
| 132 | 127 | ||
| 133 | ;;;###autoload (add-hook 'same-window-regexps (purecopy "^\\*rlogin-.*\\*\\(\\|<[0-9]+>\\)")) | 128 | ;;;###autoload (add-hook 'same-window-regexps (purecopy "^\\*rlogin-.*\\*\\(\\|<[0-9]+>\\)")) |
| @@ -175,7 +170,6 @@ variable." | |||
| 175 | (read-from-minibuffer "rlogin arguments (hostname first): " | 170 | (read-from-minibuffer "rlogin arguments (hostname first): " |
| 176 | nil nil nil 'rlogin-history) | 171 | nil nil nil 'rlogin-history) |
| 177 | current-prefix-arg)) | 172 | current-prefix-arg)) |
| 178 | |||
| 179 | (let* ((process-connection-type rlogin-process-connection-type) | 173 | (let* ((process-connection-type rlogin-process-connection-type) |
| 180 | (args (if rlogin-explicit-args | 174 | (args (if rlogin-explicit-args |
| 181 | (append (split-string input-args) | 175 | (append (split-string input-args) |
| @@ -192,7 +186,6 @@ variable." | |||
| 192 | (buffer-name (if (string= user (user-login-name)) | 186 | (buffer-name (if (string= user (user-login-name)) |
| 193 | (format "*rlogin-%s*" host) | 187 | (format "*rlogin-%s*" host) |
| 194 | (format "*rlogin-%s@%s*" user host)))) | 188 | (format "*rlogin-%s@%s*" user host)))) |
| 195 | |||
| 196 | (cond ((null buffer)) | 189 | (cond ((null buffer)) |
| 197 | ((stringp buffer) | 190 | ((stringp buffer) |
| 198 | (setq buffer-name buffer)) | 191 | (setq buffer-name buffer)) |
| @@ -202,32 +195,26 @@ variable." | |||
| 202 | (setq buffer-name (format "%s<%d>" buffer-name buffer))) | 195 | (setq buffer-name (format "%s<%d>" buffer-name buffer))) |
| 203 | (t | 196 | (t |
| 204 | (setq buffer-name (generate-new-buffer-name buffer-name)))) | 197 | (setq buffer-name (generate-new-buffer-name buffer-name)))) |
| 205 | |||
| 206 | (setq buffer (get-buffer-create buffer-name)) | 198 | (setq buffer (get-buffer-create buffer-name)) |
| 207 | (pop-to-buffer buffer-name) | 199 | (pop-to-buffer buffer-name) |
| 208 | |||
| 209 | (unless (comint-check-proc buffer-name) | 200 | (unless (comint-check-proc buffer-name) |
| 210 | (comint-exec buffer buffer-name rlogin-program nil args) | 201 | (comint-exec buffer buffer-name rlogin-program nil args) |
| 211 | |||
| 212 | (rlogin-mode) | 202 | (rlogin-mode) |
| 213 | |||
| 214 | (make-local-variable 'rlogin-host) | 203 | (make-local-variable 'rlogin-host) |
| 215 | (setq rlogin-host host) | 204 | (setq rlogin-host host) |
| 216 | (make-local-variable 'rlogin-remote-user) | 205 | (make-local-variable 'rlogin-remote-user) |
| 217 | (setq rlogin-remote-user user) | 206 | (setq rlogin-remote-user user) |
| 218 | 207 | (ignore-errors | |
| 219 | (condition-case () | 208 | (cond ((eq rlogin-directory-tracking-mode t) |
| 220 | (cond ((eq rlogin-directory-tracking-mode t) | 209 | ;; Do this here, rather than calling the tracking mode |
| 221 | ;; Do this here, rather than calling the tracking mode | 210 | ;; function, to avoid a gratuitous resync check; the default |
| 222 | ;; function, to avoid a gratuitous resync check; the default | 211 | ;; should be the user's home directory, be it local or remote. |
| 223 | ;; should be the user's home directory, be it local or remote. | 212 | (setq comint-file-name-prefix |
| 224 | (setq comint-file-name-prefix | 213 | (concat "/" rlogin-remote-user "@" rlogin-host ":")) |
| 225 | (concat "/" rlogin-remote-user "@" rlogin-host ":")) | 214 | (cd-absolute comint-file-name-prefix)) |
| 226 | (cd-absolute comint-file-name-prefix)) | 215 | ((null rlogin-directory-tracking-mode)) |
| 227 | ((null rlogin-directory-tracking-mode)) | 216 | (t |
| 228 | (t | 217 | (cd-absolute (concat comint-file-name-prefix "~/")))))))) |
| 229 | (cd-absolute (concat comint-file-name-prefix "~/")))) | ||
| 230 | (error nil))))) | ||
| 231 | 218 | ||
| 232 | (put 'rlogin-mode 'mode-class 'special) | 219 | (put 'rlogin-mode 'mode-class 'special) |
| 233 | 220 | ||
| @@ -302,8 +289,7 @@ local one share the same directories (e.g. through NFS)." | |||
| 302 | (process-send-string nil "\C-\\")) | 289 | (process-send-string nil "\C-\\")) |
| 303 | 290 | ||
| 304 | (defun rlogin-delchar-or-send-Ctrl-D (arg) | 291 | (defun rlogin-delchar-or-send-Ctrl-D (arg) |
| 305 | "\ | 292 | "Delete ARG characters forward, or send a C-d to process if at end of buffer." |
| 306 | Delete ARG characters forward, or send a C-d to process if at end of buffer." | ||
| 307 | (interactive "p") | 293 | (interactive "p") |
| 308 | (if (eobp) | 294 | (if (eobp) |
| 309 | (rlogin-send-Ctrl-D) | 295 | (rlogin-send-Ctrl-D) |
diff --git a/lisp/play/morse.el b/lisp/play/morse.el index b88f1b264cb..fa0887c0ac5 100644 --- a/lisp/play/morse.el +++ b/lisp/play/morse.el | |||
| @@ -231,7 +231,7 @@ Geospatial-Intelligence Agency at http://www.nga.mil/") | |||
| 231 | (if (null (looking-at "[a-z]+")) | 231 | (if (null (looking-at "[a-z]+")) |
| 232 | (forward-char 1) | 232 | (forward-char 1) |
| 233 | (setq str (buffer-substring (match-beginning 0) (match-end 0))) | 233 | (setq str (buffer-substring (match-beginning 0) (match-end 0))) |
| 234 | (if (null (setq nato (rassoc str nato-alphabet))) | 234 | (if (null (setq nato (rassoc (capitalize str) nato-alphabet))) |
| 235 | (goto-char (match-end 0)) | 235 | (goto-char (match-end 0)) |
| 236 | (replace-match | 236 | (replace-match |
| 237 | (if (string-equal "(" (car nato)) | 237 | (if (string-equal "(" (car nato)) |
diff --git a/lisp/replace.el b/lisp/replace.el index 928c3170c65..0ed716966ed 100644 --- a/lisp/replace.el +++ b/lisp/replace.el | |||
| @@ -772,26 +772,29 @@ a previously found match." | |||
| 772 | (define-key map "\C-c\C-f" 'next-error-follow-minor-mode) | 772 | (define-key map "\C-c\C-f" 'next-error-follow-minor-mode) |
| 773 | (define-key map [menu-bar] (make-sparse-keymap)) | 773 | (define-key map [menu-bar] (make-sparse-keymap)) |
| 774 | (define-key map [menu-bar occur] | 774 | (define-key map [menu-bar occur] |
| 775 | `(cons ,(purecopy "Occur") map)) | 775 | (cons (purecopy "Occur") map)) |
| 776 | (define-key map [next-error-follow-minor-mode] | 776 | (define-key map [next-error-follow-minor-mode] |
| 777 | (menu-bar-make-mm-toggle next-error-follow-minor-mode | 777 | `(menu-item ,(purecopy "Auto Occurrence Display") |
| 778 | "Auto Occurrence Display" | 778 | next-error-follow-minor-mode |
| 779 | "Display another occurrence when moving the cursor")) | 779 | :help ,(purecopy |
| 780 | "Display another occurrence when moving the cursor") | ||
| 781 | :button (:toggle . (and (boundp 'next-error-follow-minor-mode) | ||
| 782 | next-error-follow-minor-mode)))) | ||
| 780 | (define-key map [separator-1] menu-bar-separator) | 783 | (define-key map [separator-1] menu-bar-separator) |
| 781 | (define-key map [kill-this-buffer] | 784 | (define-key map [kill-this-buffer] |
| 782 | `(menu-item ,(purecopy "Kill occur buffer") kill-this-buffer | 785 | `(menu-item ,(purecopy "Kill Occur Buffer") kill-this-buffer |
| 783 | :help ,(purecopy "Kill the current *Occur* buffer"))) | 786 | :help ,(purecopy "Kill the current *Occur* buffer"))) |
| 784 | (define-key map [quit-window] | 787 | (define-key map [quit-window] |
| 785 | `(menu-item ,(purecopy "Quit occur window") quit-window | 788 | `(menu-item ,(purecopy "Quit Occur Window") quit-window |
| 786 | :help ,(purecopy "Quit the current *Occur* buffer. Bury it, and maybe delete the selected frame"))) | 789 | :help ,(purecopy "Quit the current *Occur* buffer. Bury it, and maybe delete the selected frame"))) |
| 787 | (define-key map [revert-buffer] | 790 | (define-key map [revert-buffer] |
| 788 | `(menu-item ,(purecopy "Revert occur buffer") revert-buffer | 791 | `(menu-item ,(purecopy "Revert Occur Buffer") revert-buffer |
| 789 | :help ,(purecopy "Replace the text in the *Occur* buffer with the results of rerunning occur"))) | 792 | :help ,(purecopy "Replace the text in the *Occur* buffer with the results of rerunning occur"))) |
| 790 | (define-key map [clone-buffer] | 793 | (define-key map [clone-buffer] |
| 791 | `(menu-item ,(purecopy "Clone occur buffer") clone-buffer | 794 | `(menu-item ,(purecopy "Clone Occur Buffer") clone-buffer |
| 792 | :help ,(purecopy "Create and return a twin copy of the current *Occur* buffer"))) | 795 | :help ,(purecopy "Create and return a twin copy of the current *Occur* buffer"))) |
| 793 | (define-key map [occur-rename-buffer] | 796 | (define-key map [occur-rename-buffer] |
| 794 | `(menu-item ,(purecopy "Rename occur buffer") occur-rename-buffer | 797 | `(menu-item ,(purecopy "Rename Occur Buffer") occur-rename-buffer |
| 795 | :help ,(purecopy "Rename the current *Occur* buffer to *Occur: original-buffer-name*."))) | 798 | :help ,(purecopy "Rename the current *Occur* buffer to *Occur: original-buffer-name*."))) |
| 796 | (define-key map [separator-2] menu-bar-separator) | 799 | (define-key map [separator-2] menu-bar-separator) |
| 797 | (define-key map [occur-mode-goto-occurrence-other-window] | 800 | (define-key map [occur-mode-goto-occurrence-other-window] |
| @@ -804,10 +807,10 @@ a previously found match." | |||
| 804 | `(menu-item ,(purecopy "Display Occurrence") occur-mode-display-occurrence | 807 | `(menu-item ,(purecopy "Display Occurrence") occur-mode-display-occurrence |
| 805 | :help ,(purecopy "Display in another window the occurrence the current line describes"))) | 808 | :help ,(purecopy "Display in another window the occurrence the current line describes"))) |
| 806 | (define-key map [occur-next] | 809 | (define-key map [occur-next] |
| 807 | `(menu-item ,(purecopy "Move to next match") occur-next | 810 | `(menu-item ,(purecopy "Move to Next Match") occur-next |
| 808 | :help ,(purecopy "Move to the Nth (default 1) next match in an Occur mode buffer"))) | 811 | :help ,(purecopy "Move to the Nth (default 1) next match in an Occur mode buffer"))) |
| 809 | (define-key map [occur-prev] | 812 | (define-key map [occur-prev] |
| 810 | `(menu-item ,(purecopy "Move to previous match") occur-prev | 813 | `(menu-item ,(purecopy "Move to Previous Match") occur-prev |
| 811 | :help ,(purecopy "Move to the Nth (default 1) previous match in an Occur mode buffer"))) | 814 | :help ,(purecopy "Move to the Nth (default 1) previous match in an Occur mode buffer"))) |
| 812 | map) | 815 | map) |
| 813 | "Keymap for `occur-mode'.") | 816 | "Keymap for `occur-mode'.") |
diff --git a/lisp/saveplace.el b/lisp/saveplace.el index c10b5cbb7ec..2d1586d895a 100644 --- a/lisp/saveplace.el +++ b/lisp/saveplace.el | |||
| @@ -285,7 +285,7 @@ may have changed\) back to `save-place-alist'." | |||
| 285 | (let ((cell (assoc buffer-file-name save-place-alist))) | 285 | (let ((cell (assoc buffer-file-name save-place-alist))) |
| 286 | (if cell | 286 | (if cell |
| 287 | (progn | 287 | (progn |
| 288 | (or after-find-file-from-revert-buffer | 288 | (or revert-buffer-in-progress-p |
| 289 | (goto-char (cdr cell))) | 289 | (goto-char (cdr cell))) |
| 290 | ;; and make sure it will be saved again for later | 290 | ;; and make sure it will be saved again for later |
| 291 | (setq save-place t))))) | 291 | (setq save-place t))))) |
diff --git a/lisp/simple.el b/lisp/simple.el index a414fc77a39..f0560c48a3b 100644 --- a/lisp/simple.el +++ b/lisp/simple.el | |||
| @@ -2690,7 +2690,95 @@ support pty association, if PROGRAM is nil." | |||
| 2690 | (let ((fh (find-file-name-handler default-directory 'start-file-process))) | 2690 | (let ((fh (find-file-name-handler default-directory 'start-file-process))) |
| 2691 | (if fh (apply fh 'start-file-process name buffer program program-args) | 2691 | (if fh (apply fh 'start-file-process name buffer program program-args) |
| 2692 | (apply 'start-process name buffer program program-args)))) | 2692 | (apply 'start-process name buffer program program-args)))) |
| 2693 | 2693 | ||
| 2694 | ;;;; Process menu | ||
| 2695 | |||
| 2696 | (defvar tabulated-list-format) | ||
| 2697 | (defvar tabulated-list-entries) | ||
| 2698 | (defvar tabulated-list-sort-key) | ||
| 2699 | (declare-function tabulated-list-init-header "tabulated-list" ()) | ||
| 2700 | (declare-function tabulated-list-print "tabulated-list" ()) | ||
| 2701 | |||
| 2702 | (defvar process-menu-query-only nil) | ||
| 2703 | |||
| 2704 | (define-derived-mode process-menu-mode tabulated-list-mode "Process Menu" | ||
| 2705 | "Major mode for listing the processes called by Emacs." | ||
| 2706 | (setq tabulated-list-format [("Process" 15 t) | ||
| 2707 | ("Status" 7 t) | ||
| 2708 | ("Buffer" 15 t) | ||
| 2709 | ("TTY" 12 t) | ||
| 2710 | ("Command" 0 t)]) | ||
| 2711 | (make-local-variable 'process-menu-query-only) | ||
| 2712 | (setq tabulated-list-sort-key (cons "Process" nil)) | ||
| 2713 | (add-hook 'tabulated-list-revert-hook 'list-processes--refresh nil t) | ||
| 2714 | (tabulated-list-init-header)) | ||
| 2715 | |||
| 2716 | (defun list-processes--refresh () | ||
| 2717 | "Recompute the list of processes for the Process List buffer." | ||
| 2718 | (setq tabulated-list-entries nil) | ||
| 2719 | (dolist (p (process-list)) | ||
| 2720 | (when (or (not process-menu-query-only) | ||
| 2721 | (process-query-on-exit-flag p)) | ||
| 2722 | (let* ((buf (process-buffer p)) | ||
| 2723 | (type (process-type p)) | ||
| 2724 | (name (process-name p)) | ||
| 2725 | (status (symbol-name (process-status p))) | ||
| 2726 | (buf-label (if (buffer-live-p buf) | ||
| 2727 | `(,(buffer-name buf) | ||
| 2728 | face link | ||
| 2729 | help-echo ,(concat "Visit buffer `" | ||
| 2730 | (buffer-name buf) "'") | ||
| 2731 | follow-link t | ||
| 2732 | process-buffer ,buf | ||
| 2733 | action process-menu-visit-buffer) | ||
| 2734 | "--")) | ||
| 2735 | (tty (or (process-tty-name p) "--")) | ||
| 2736 | (cmd | ||
| 2737 | (if (memq type '(network serial)) | ||
| 2738 | (let ((contact (process-contact p t))) | ||
| 2739 | (if (eq type 'network) | ||
| 2740 | (format "(%s %s)" | ||
| 2741 | (if (plist-get contact :type) | ||
| 2742 | "datagram" | ||
| 2743 | "network") | ||
| 2744 | (if (plist-get contact :server) | ||
| 2745 | (format "server on %s" | ||
| 2746 | (plist-get contact :server)) | ||
| 2747 | (format "connection to %s" | ||
| 2748 | (plist-get contact :host)))) | ||
| 2749 | (format "(serial port %s%s)" | ||
| 2750 | (or (plist-get contact :port) "?") | ||
| 2751 | (let ((speed (plist-get contact :speed))) | ||
| 2752 | (if speed | ||
| 2753 | (format " at %s b/s" speed) | ||
| 2754 | ""))))) | ||
| 2755 | (mapconcat 'identity (process-command p) " ")))) | ||
| 2756 | (push (list p (vector name status buf-label tty cmd)) | ||
| 2757 | tabulated-list-entries))))) | ||
| 2758 | |||
| 2759 | (defun process-menu-visit-buffer (button) | ||
| 2760 | (display-buffer (button-get button 'process-buffer))) | ||
| 2761 | |||
| 2762 | (defun list-processes (&optional query-only buffer) | ||
| 2763 | "Display a list of all processes. | ||
| 2764 | If optional argument QUERY-ONLY is non-nil, only processes with | ||
| 2765 | the query-on-exit flag set are listed. | ||
| 2766 | Any process listed as exited or signaled is actually eliminated | ||
| 2767 | after the listing is made. | ||
| 2768 | Optional argument BUFFER specifies a buffer to use, instead of | ||
| 2769 | \"*Process List\". | ||
| 2770 | The return value is always nil." | ||
| 2771 | (interactive) | ||
| 2772 | (or (fboundp 'process-list) | ||
| 2773 | (error "Asynchronous subprocesses are not supported on this system")) | ||
| 2774 | (unless (bufferp buffer) | ||
| 2775 | (setq buffer (get-buffer-create "*Process List*"))) | ||
| 2776 | (with-current-buffer buffer | ||
| 2777 | (process-menu-mode) | ||
| 2778 | (setq process-menu-query-only query-only) | ||
| 2779 | (list-processes--refresh) | ||
| 2780 | (tabulated-list-print)) | ||
| 2781 | (display-buffer buffer)) | ||
| 2694 | 2782 | ||
| 2695 | (defvar universal-argument-map | 2783 | (defvar universal-argument-map |
| 2696 | (let ((map (make-sparse-keymap))) | 2784 | (let ((map (make-sparse-keymap))) |
diff --git a/lisp/vc/log-edit.el b/lisp/vc/log-edit.el index 54a2cb4f196..b3f5cfb78f7 100644 --- a/lisp/vc/log-edit.el +++ b/lisp/vc/log-edit.el | |||
| @@ -531,13 +531,25 @@ If you want to abort the commit, simply delete the buffer." | |||
| 531 | (shrink-window-if-larger-than-buffer) | 531 | (shrink-window-if-larger-than-buffer) |
| 532 | (selected-window))))) | 532 | (selected-window))))) |
| 533 | 533 | ||
| 534 | (defun log-edit-empty-buffer-p () | ||
| 535 | "Return non-nil if the buffer is \"empty\"." | ||
| 536 | (or (= (point-min) (point-max)) | ||
| 537 | (save-excursion | ||
| 538 | (goto-char (point-min)) | ||
| 539 | (while (and (looking-at "^\\(Summary: \\)?$") | ||
| 540 | (zerop (forward-line 1)))) | ||
| 541 | (eobp)))) | ||
| 542 | |||
| 534 | (defun log-edit-insert-cvs-template () | 543 | (defun log-edit-insert-cvs-template () |
| 535 | "Insert the template specified by the CVS administrator, if any. | 544 | "Insert the template specified by the CVS administrator, if any. |
| 536 | This simply uses the local CVS/Template file." | 545 | This simply uses the local CVS/Template file." |
| 537 | (interactive) | 546 | (interactive) |
| 538 | (when (or (called-interactively-p 'interactive) | 547 | (when (or (called-interactively-p 'interactive) |
| 539 | (= (point-min) (point-max))) | 548 | (log-edit-empty-buffer-p)) |
| 549 | ;; Should the template take precedence over an empty Summary:, | ||
| 550 | ;; ie should we first erase the buffer? | ||
| 540 | (when (file-readable-p "CVS/Template") | 551 | (when (file-readable-p "CVS/Template") |
| 552 | (goto-char (point-max)) | ||
| 541 | (insert-file-contents "CVS/Template")))) | 553 | (insert-file-contents "CVS/Template")))) |
| 542 | 554 | ||
| 543 | (defun log-edit-insert-cvs-rcstemplate () | 555 | (defun log-edit-insert-cvs-rcstemplate () |
| @@ -546,8 +558,9 @@ This contacts the repository to get the rcstemplate file and | |||
| 546 | can thus take some time." | 558 | can thus take some time." |
| 547 | (interactive) | 559 | (interactive) |
| 548 | (when (or (called-interactively-p 'interactive) | 560 | (when (or (called-interactively-p 'interactive) |
| 549 | (= (point-min) (point-max))) | 561 | (log-edit-empty-buffer-p)) |
| 550 | (when (file-readable-p "CVS/Root") | 562 | (when (file-readable-p "CVS/Root") |
| 563 | (goto-char (point-max)) | ||
| 551 | ;; Ignore the stderr stuff, even if it's an error. | 564 | ;; Ignore the stderr stuff, even if it's an error. |
| 552 | (call-process "cvs" nil '(t nil) nil | 565 | (call-process "cvs" nil '(t nil) nil |
| 553 | "checkout" "-p" "CVSROOT/rcstemplate")))) | 566 | "checkout" "-p" "CVSROOT/rcstemplate")))) |
diff --git a/lisp/vc/vc-annotate.el b/lisp/vc/vc-annotate.el index 479dbb5caea..271fce12429 100644 --- a/lisp/vc/vc-annotate.el +++ b/lisp/vc/vc-annotate.el | |||
| @@ -489,7 +489,7 @@ Return a cons (REV . FILENAME)." | |||
| 489 | "Visit the log of the revision at line. | 489 | "Visit the log of the revision at line. |
| 490 | If the VC backend supports it, only show the log entry for the revision. | 490 | If the VC backend supports it, only show the log entry for the revision. |
| 491 | If a *vc-change-log* buffer exists and already shows a log for | 491 | If a *vc-change-log* buffer exists and already shows a log for |
| 492 | the file in question, search for the log entry required and move point ." | 492 | the file in question, search for the log entry required and move point." |
| 493 | (interactive) | 493 | (interactive) |
| 494 | (if (not (equal major-mode 'vc-annotate-mode)) | 494 | (if (not (equal major-mode 'vc-annotate-mode)) |
| 495 | (message "Cannot be invoked outside of a vc annotate buffer") | 495 | (message "Cannot be invoked outside of a vc annotate buffer") |