aboutsummaryrefslogtreecommitdiffstats
path: root/lisp
diff options
context:
space:
mode:
authorPaul Eggert2011-04-09 11:42:31 -0700
committerPaul Eggert2011-04-09 11:42:31 -0700
commit762f8d96719ba3e8a0e79d8bb99fe8e119fafb3a (patch)
tree7b2fe40a89bf327ea8b9ad8265a6b6f27cacd2a7 /lisp
parenteb3f1cc8dfe6a96505f1c5f9174b2712998cb52f (diff)
parent8546720e6f25eb988e8215de6678798053031440 (diff)
downloademacs-762f8d96719ba3e8a0e79d8bb99fe8e119fafb3a.tar.gz
emacs-762f8d96719ba3e8a0e79d8bb99fe8e119fafb3a.zip
Merge from mainline.
Diffstat (limited to 'lisp')
-rw-r--r--lisp/ChangeLog118
-rw-r--r--lisp/bs.el4
-rw-r--r--lisp/cus-face.el2
-rw-r--r--lisp/doc-view.el76
-rw-r--r--lisp/emacs-lisp/cconv.el4
-rw-r--r--lisp/emacs-lisp/package.el460
-rw-r--r--lisp/emacs-lisp/tabulated-list.el355
-rw-r--r--lisp/files.el55
-rw-r--r--lisp/follow.el2
-rw-r--r--lisp/gnus/ChangeLog49
-rw-r--r--lisp/gnus/gnus-registry.el196
-rw-r--r--lisp/gnus/gnus-start.el6
-rw-r--r--lisp/gnus/registry.el20
-rw-r--r--lisp/help.el9
-rw-r--r--lisp/ls-lisp.el10
-rw-r--r--lisp/man.el3
-rw-r--r--lisp/net/browse-url.el3
-rw-r--r--lisp/net/rlogin.el70
-rw-r--r--lisp/play/morse.el2
-rw-r--r--lisp/replace.el25
-rw-r--r--lisp/saveplace.el2
-rw-r--r--lisp/simple.el90
-rw-r--r--lisp/vc/log-edit.el17
-rw-r--r--lisp/vc/vc-annotate.el2
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 @@
12011-04-07 Paul Eggert <eggert@cs.ucla.edu> 12011-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
62011-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
132011-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
182011-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
292011-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
342011-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
412011-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
582011-04-07 Aaron S. Hawley <aaron.s.hawley@gmail.com>
59
60 * play/morse.el (denato-region): Handle varying case. (Bug#8386)
61
622011-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
792011-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
1092011-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
62011-04-06 Glenn Morris <rgm@gnu.org> 1202011-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
5782011-03-19 Ralph Schleicher <rs@ralph-schleicher.de> 6922011-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.
717More specifically, this function enlarges image by:
718
719min {(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.
669Should be invoked when the cached images aren't up-to-date." 745Should 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.
1329Letters do not insert themselves; instead, they are commands. 1317Letters 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) 1330If the alist stored in the symbol LISTNAME lacks an entry for a
1343 'face 'fixed-pitch) 1331package PACKAGE with descriptor DESC, add one. The alist is
1344 ;; Set up the column button. 1332keyed with cons cells (PACKAGE . VERSION), where PACKAGE is a
1345 (propertize name 1333symbol 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. 1341Optional argument REMEMBER-POS, if non-nil, means to move point
1354 '((0 . "") 1342to 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'.
1378PKG has the form ((PACKAGE . VERSION) STATUS DOC).
1379Return (KEY [NAME VERSION STATUS DOC]), where KEY is the
1380identifier (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.
1373This function is the `revert-buffer-function' for Package Menu 1415If optional arg BUTTON is non-nil, describe its associated package."
1374buffers. 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."
1464Packages marked for installation are downloaded and installed; 1475Packages marked for installation are downloaded and installed;
1465packages marked for deletion are removed." 1476packages 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.
1552A 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.
1692Optional PACKAGES is a list of names of packages (symbols) to
1693list; 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.
1708Fetches the updated list of packages before displaying. 1567This first fetches the updated list of packages before
1568displaying, unless a prefix argument NO-FETCH is specified.
1709The list is displayed in a buffer named `*Packages*'." 1569The 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*'."
1722Does not fetch the updated list of packages before displaying. 1590Does not fetch the updated list of packages before displaying.
1723The list is displayed in a buffer named `*Packages*'." 1591The 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.
39This 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.
53This should be either a function, or a list.
54If a list, each element has the form (ID [DESC1 ... DESCN]),
55where:
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
67If `tabulated-list-entries' is a function, it is called with no
68arguments 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.
73By default, lines are padded with spaces, but you can use the
74function `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.
79This 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.
83It is called with two arguments, ID and COLS. ID is a Lisp
84object identifying the entry, and COLS is a vector of column
85descriptors, 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.
90If nil, no additional sorting is performed.
91Otherwise, this should be a cons cell (NAME . FLIP).
92NAME 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
95non-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.
100This is an ID object from `tabulated-list-entries', or nil.
101POS, 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.
106TAG should be a string, with length <= `tabulated-list-padding'.
107If 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'.
193It 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.
202This sorts the `tabulated-list-entries' list if sorting is
203specified by `tabulated-list-sort-key'. It then erases the
204buffer and inserts the entries with `tabulated-list-printer'.
205
206Optional argument REMEMBER-POS, if non-nil, means to move point
207to 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.
257This is the default `tabulated-list-printer' function. ID is a
258Lisp object identifying the entry to print, and COLS is a vector
259of 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.
309This mode is usually not used directly; instead, other major
310modes are derived from it, using `define-derived-mode'.
311
312In this major mode, the buffer is divided into multiple columns,
313which are labelled using the header line. Each non-empty line
314belongs to one \"entry\", and the entries can be sorted according
315to their column values.
316
317An 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
328An inheriting mode is usually accompanied by a \"list-FOO\"
329command (e.g. `list-packages', `list-processes'). This command
330creates or switches to a buffer and enables the major mode in
331that buffer. If `tabulated-list-entries' is not a function, the
332command should initialize it to a list of entries for displaying.
333Finally, 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
337printer is `tabulated-list-print-entry', but a mode that keeps
338data in an ewoc may instead specify a printer function (e.g., one
339that calls `ewoc-enter-last'), with `tabulated-list-print-entry'
340as 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
1148Optional 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.
1145The returned file name (created by appending some random characters at the end 1176The 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.
2109Sets buffer mode, parses local variables. 2138Sets buffer mode, parses local variables.
@@ -2111,8 +2140,8 @@ Optional args ERROR, WARN, and NOAUTO: ERROR non-nil means there was an
2111error in reading the file. WARN non-nil means warn if there 2140error in reading the file. WARN non-nil means warn if there
2112exists an auto-save file more recent than the visited file. 2141exists an auto-save file more recent than the visited file.
2113NOAUTO means don't mess with auto-save mode. 2142NOAUTO means don't mess with auto-save mode.
2114Fourth arg AFTER-FIND-FILE-FROM-REVERT-BUFFER non-nil 2143Fourth 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).
2116Fifth arg NOMODES non-nil means don't alter the file's modes. 2145Fifth arg NOMODES non-nil means don't alter the file's modes.
2117Finishes by calling the functions in `find-file-hook' 2146Finishes by calling the functions in `find-file-hook'
2118unless NOMODES is non-nil." 2147unless NOMODES is non-nil."
@@ -5004,6 +5033,10 @@ hook functions.
5004If `revert-buffer-function' is used to override the normal revert 5033If `revert-buffer-function' is used to override the normal revert
5005mechanism, this hook is not used.") 5034mechanism, 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.
5038This 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 @@
12011-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
92011-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
152011-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
202011-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
252011-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
312011-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
12011-04-06 Teodor Zlatanov <tzz@lifelogs.com> 422011-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
151762005-05-30 Reiner Steib <Reiner.Steib@gmx.de> 152192005-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.
489Reduces the list to a single group, or complains if that's not 492Reduces the list to a single group, or complains if that's not
490possible. Uses `gnus-registry-split-strategy'." 493possible. 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.
72If nil, use a pipe (if pipes are supported on the local system). 67If 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."
306Delete 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.
2764If optional argument QUERY-ONLY is non-nil, only processes with
2765the query-on-exit flag set are listed.
2766Any process listed as exited or signaled is actually eliminated
2767after the listing is made.
2768Optional argument BUFFER specifies a buffer to use, instead of
2769\"*Process List\".
2770The 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.
536This simply uses the local CVS/Template file." 545This 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
546can thus take some time." 558can 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.
490If the VC backend supports it, only show the log entry for the revision. 490If the VC backend supports it, only show the log entry for the revision.
491If a *vc-change-log* buffer exists and already shows a log for 491If a *vc-change-log* buffer exists and already shows a log for
492the file in question, search for the log entry required and move point ." 492the 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")