diff options
| author | Chong Yidong | 2011-04-06 16:33:30 -0400 |
|---|---|---|
| committer | Chong Yidong | 2011-04-06 16:33:30 -0400 |
| commit | e91a96fefdc732b857532bfa827439efe520c47f (patch) | |
| tree | 5aee0ed310810e9aa46a1ccb62c27f6493f4f1e6 | |
| parent | a83ec3c99a6536a248c4806fbbafbc47c2047bc6 (diff) | |
| download | emacs-e91a96fefdc732b857532bfa827439efe520c47f.tar.gz emacs-e91a96fefdc732b857532bfa827439efe520c47f.zip | |
Make Package Menu a child of Tabulated List mode.
* emacs-lisp/package.el: Use Tabulated List mode.
(package-menu-mode-map): Inherit from tabulated-list-mode-map.
(package-menu-mode): Derive from tabulated-list-mode. Set up the
table format using Tabulated List mode variables.
(package--push): New macro, replacing package-list-maybe-add.
(package-menu--generate): Use package--push. Renamed from
package--generate-package-list.
(package-menu-refresh, list-packages): Use it.
(package-menu--print-info): Renamed from package-print-package.
Return insertion data instead of inserting it directly.
(package-menu-describe-package, package-menu-execute): Use
tabulated-list-get-id.
(package-menu-mark-delete, package-menu-mark-install)
(package-menu-mark-unmark, package-menu-backup-unmark)
(package-menu-mark-obsolete-for-deletion): Use
tabulated-list-put-tag.
(package--list-packages, package-menu-revert)
(package-menu-get-package, package-menu-get-version)
(package-menu-sort-by-column): Functions deleted.
(package-menu-package-list, package-menu-sort-key): Vars deleted.
(package-menu--status-predicate, package-menu--version-predicate)
(package-menu--name-predicate)
(package-menu--description-predicate): Handle arguments in the
Tabulated List format.
(package-list-packages-no-fetch): Call list-packages.
| -rw-r--r-- | lisp/ChangeLog | 26 | ||||
| -rw-r--r-- | lisp/emacs-lisp/package.el | 460 |
2 files changed, 190 insertions, 296 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 133bf70d482..313b2e94a30 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -2,6 +2,32 @@ | |||
| 2 | 2 | ||
| 3 | * emacs-lisp/tabulated-list.el: New file. | 3 | * emacs-lisp/tabulated-list.el: New file. |
| 4 | 4 | ||
| 5 | * emacs-lisp/package.el: Use Tabulated List mode. | ||
| 6 | (package-menu-mode-map): Inherit from tabulated-list-mode-map. | ||
| 7 | (package-menu-mode): Derive from tabulated-list-mode. Set up the | ||
| 8 | table format using Tabulated List mode variables. | ||
| 9 | (package--push): New macro, replacing package-list-maybe-add. | ||
| 10 | (package-menu--generate): Use package--push. Renamed from | ||
| 11 | package--generate-package-list. | ||
| 12 | (package-menu-refresh, list-packages): Use it. | ||
| 13 | (package-menu--print-info): Renamed from package-print-package. | ||
| 14 | Return insertion data instead of inserting it directly. | ||
| 15 | (package-menu-describe-package, package-menu-execute): Use | ||
| 16 | tabulated-list-get-id. | ||
| 17 | (package-menu-mark-delete, package-menu-mark-install) | ||
| 18 | (package-menu-mark-unmark, package-menu-backup-unmark) | ||
| 19 | (package-menu-mark-obsolete-for-deletion): Use | ||
| 20 | tabulated-list-put-tag. | ||
| 21 | (package--list-packages, package-menu-revert) | ||
| 22 | (package-menu-get-package, package-menu-get-version) | ||
| 23 | (package-menu-sort-by-column): Functions deleted. | ||
| 24 | (package-menu-package-list, package-menu-sort-key): Vars deleted. | ||
| 25 | (package-menu--status-predicate, package-menu--version-predicate) | ||
| 26 | (package-menu--name-predicate) | ||
| 27 | (package-menu--description-predicate): Handle arguments in the | ||
| 28 | Tabulated List format. | ||
| 29 | (package-list-packages-no-fetch): Call list-packages. | ||
| 30 | |||
| 5 | 2011-04-06 Juanma Barranquero <lekktu@gmail.com> | 31 | 2011-04-06 Juanma Barranquero <lekktu@gmail.com> |
| 6 | 32 | ||
| 7 | * files.el (after-find-file-from-revert-buffer): Remove variable. | 33 | * files.el (after-find-file-from-revert-buffer): Remove variable. |
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 6aecc3615f3..4ce71b29d70 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el | |||
| @@ -173,6 +173,8 @@ | |||
| 173 | 173 | ||
| 174 | ;;; Code: | 174 | ;;; Code: |
| 175 | 175 | ||
| 176 | (require 'tabulated-list) | ||
| 177 | |||
| 176 | (defgroup package nil | 178 | (defgroup package nil |
| 177 | "Manager for Emacs Lisp packages." | 179 | "Manager for Emacs Lisp packages." |
| 178 | :group 'applications | 180 | :group 'applications |
| @@ -1249,12 +1251,10 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages." | |||
| 1249 | ;;;; Package menu mode. | 1251 | ;;;; Package menu mode. |
| 1250 | 1252 | ||
| 1251 | (defvar package-menu-mode-map | 1253 | (defvar package-menu-mode-map |
| 1252 | (let ((map (copy-keymap special-mode-map)) | 1254 | (let ((map (make-sparse-keymap)) |
| 1253 | (menu-map (make-sparse-keymap "Package"))) | 1255 | (menu-map (make-sparse-keymap "Package"))) |
| 1254 | (set-keymap-parent map button-buffer-map) | 1256 | (set-keymap-parent map tabulated-list-mode-map) |
| 1255 | (define-key map "\C-m" 'package-menu-describe-package) | 1257 | (define-key map "\C-m" 'package-menu-describe-package) |
| 1256 | (define-key map "n" 'next-line) | ||
| 1257 | (define-key map "p" 'previous-line) | ||
| 1258 | (define-key map "u" 'package-menu-mark-unmark) | 1258 | (define-key map "u" 'package-menu-mark-unmark) |
| 1259 | (define-key map "\177" 'package-menu-backup-unmark) | 1259 | (define-key map "\177" 'package-menu-backup-unmark) |
| 1260 | (define-key map "d" 'package-menu-mark-delete) | 1260 | (define-key map "d" 'package-menu-mark-delete) |
| @@ -1264,8 +1264,6 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages." | |||
| 1264 | (define-key map "x" 'package-menu-execute) | 1264 | (define-key map "x" 'package-menu-execute) |
| 1265 | (define-key map "h" 'package-menu-quick-help) | 1265 | (define-key map "h" 'package-menu-quick-help) |
| 1266 | (define-key map "?" 'package-menu-describe-package) | 1266 | (define-key map "?" 'package-menu-describe-package) |
| 1267 | (define-key map [follow-link] 'mouse-face) | ||
| 1268 | (define-key map [mouse-2] 'mouse-select-window) | ||
| 1269 | (define-key map [menu-bar package-menu] (cons "Package" menu-map)) | 1267 | (define-key map [menu-bar package-menu] (cons "Package" menu-map)) |
| 1270 | (define-key menu-map [mq] | 1268 | (define-key menu-map [mq] |
| 1271 | '(menu-item "Quit" quit-window | 1269 | '(menu-item "Quit" quit-window |
| @@ -1314,49 +1312,93 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages." | |||
| 1314 | map) | 1312 | map) |
| 1315 | "Local keymap for `package-menu-mode' buffers.") | 1313 | "Local keymap for `package-menu-mode' buffers.") |
| 1316 | 1314 | ||
| 1317 | (defvar package-menu-sort-button-map | 1315 | (define-derived-mode package-menu-mode tabulated-list-mode "Package Menu" |
| 1318 | (let ((map (make-sparse-keymap))) | ||
| 1319 | (define-key map [header-line mouse-1] 'package-menu-sort-by-column) | ||
| 1320 | (define-key map [header-line mouse-2] 'package-menu-sort-by-column) | ||
| 1321 | (define-key map [follow-link] 'mouse-face) | ||
| 1322 | map) | ||
| 1323 | "Local keymap for package menu sort buttons.") | ||
| 1324 | |||
| 1325 | (put 'package-menu-mode 'mode-class 'special) | ||
| 1326 | |||
| 1327 | (define-derived-mode package-menu-mode special-mode "Package Menu" | ||
| 1328 | "Major mode for browsing a list of packages. | 1316 | "Major mode for browsing a list of packages. |
| 1329 | Letters do not insert themselves; instead, they are commands. | 1317 | Letters do not insert themselves; instead, they are commands. |
| 1330 | \\<package-menu-mode-map> | 1318 | \\<package-menu-mode-map> |
| 1331 | \\{package-menu-mode-map}" | 1319 | \\{package-menu-mode-map}" |
| 1332 | (setq truncate-lines t) | 1320 | (setq tabulated-list-format [("Package" 18 package-menu--name-predicate) |
| 1333 | (setq buffer-read-only t) | 1321 | ("Version" 12 nil) |
| 1334 | (set (make-local-variable 'revert-buffer-function) 'package-menu-revert) | 1322 | ("Status" 10 package-menu--status-predicate) |
| 1335 | (setq header-line-format | 1323 | ("Description" 0 nil)]) |
| 1336 | (mapconcat | 1324 | (setq tabulated-list-padding 2) |
| 1337 | (lambda (pair) | 1325 | (setq tabulated-list-sort-key (cons "Status" nil)) |
| 1338 | (let ((column (car pair)) | 1326 | (tabulated-list-init-header)) |
| 1339 | (name (cdr pair))) | 1327 | |
| 1340 | (concat | 1328 | (defmacro package--push (package desc status listname) |
| 1341 | ;; Insert a space that aligns the button properly. | 1329 | "Convenience macro for `package-menu--generate'. |
| 1342 | (propertize " " 'display (list 'space :align-to column) | 1330 | If the alist stored in the symbol LISTNAME lacks an entry for a |
| 1343 | 'face 'fixed-pitch) | 1331 | package PACKAGE with descriptor DESC, add one. The alist is |
| 1344 | ;; Set up the column button. | 1332 | keyed with cons cells (PACKAGE . VERSION), where PACKAGE is a |
| 1345 | (propertize name | 1333 | symbol and VERSION is a version list." |
| 1346 | 'column-name name | 1334 | `(let* ((version (package-desc-vers ,desc)) |
| 1347 | 'help-echo "mouse-1: sort by column" | 1335 | (key (cons ,package version))) |
| 1348 | 'mouse-face 'highlight | 1336 | (unless (assoc key ,listname) |
| 1349 | 'keymap package-menu-sort-button-map)))) | 1337 | (push (list key ,status (package-desc-doc ,desc)) ,listname)))) |
| 1350 | ;; We take a trick from buff-menu and have a dummy leading | 1338 | |
| 1351 | ;; space to align the header line with the beginning of the | 1339 | (defun package-menu--generate (&optional remember-pos) |
| 1352 | ;; text. This doesn't really work properly on Emacs 21, but | 1340 | "Populate the Package Menu. |
| 1353 | ;; it is close enough. | 1341 | Optional argument REMEMBER-POS, if non-nil, means to move point |
| 1354 | '((0 . "") | 1342 | to the entry as before." |
| 1355 | (2 . "Package") | 1343 | ;; Construct list of ((PACKAGE . VERSION) STATUS DESCRIPTION). |
| 1356 | (20 . "Version") | 1344 | (let (info-list name builtin) |
| 1357 | (32 . "Status") | 1345 | ;; Installed packages: |
| 1358 | (43 . "Description")) | 1346 | (dolist (elt package-alist) |
| 1359 | ""))) | 1347 | (setq name (car elt)) |
| 1348 | (package--push name (cdr elt) | ||
| 1349 | (if (stringp (cadr (assq name package-load-list))) | ||
| 1350 | "held" "installed") | ||
| 1351 | info-list)) | ||
| 1352 | |||
| 1353 | ;; Built-in packages: | ||
| 1354 | (dolist (elt package--builtins) | ||
| 1355 | (setq name (car elt)) | ||
| 1356 | (unless (eq name 'emacs) ; Hide the `emacs' package. | ||
| 1357 | (package--push name (cdr elt) "built-in" info-list))) | ||
| 1358 | |||
| 1359 | ;; Available and disabled packages: | ||
| 1360 | (dolist (elt package-archive-contents) | ||
| 1361 | (setq name (car elt)) | ||
| 1362 | (let ((hold (assq name package-load-list))) | ||
| 1363 | (package--push name (cdr elt) | ||
| 1364 | (if (and hold (null (cadr hold))) "disabled" "available") | ||
| 1365 | info-list))) | ||
| 1366 | |||
| 1367 | ;; Obsolete packages: | ||
| 1368 | (dolist (elt package-obsolete-alist) | ||
| 1369 | (dolist (inner-elt (cdr elt)) | ||
| 1370 | (package--push (car elt) (cdr inner-elt) "obsolete" info-list))) | ||
| 1371 | |||
| 1372 | ;; Print the result. | ||
| 1373 | (setq tabulated-list-entries (mapcar 'package-menu--print-info info-list)) | ||
| 1374 | (tabulated-list-print remember-pos))) | ||
| 1375 | |||
| 1376 | (defun package-menu--print-info (pkg) | ||
| 1377 | "Return a package entry suitable for `tabulated-list-entries'. | ||
| 1378 | PKG has the form ((PACKAGE . VERSION) STATUS DOC). | ||
| 1379 | Return (KEY [NAME VERSION STATUS DOC]), where KEY is the | ||
| 1380 | identifier (NAME . VERSION-LIST)." | ||
| 1381 | (let* ((package (caar pkg)) | ||
| 1382 | (version (cdr (car pkg))) | ||
| 1383 | (status (nth 1 pkg)) | ||
| 1384 | (doc (or (nth 2 pkg) "")) | ||
| 1385 | (face (cond | ||
| 1386 | ((string= status "built-in") 'font-lock-builtin-face) | ||
| 1387 | ((string= status "available") 'default) | ||
| 1388 | ((string= status "held") 'font-lock-constant-face) | ||
| 1389 | ((string= status "disabled") 'font-lock-warning-face) | ||
| 1390 | ((string= status "installed") 'font-lock-comment-face) | ||
| 1391 | (t 'font-lock-warning-face)))) ; obsolete. | ||
| 1392 | (list (cons package version) | ||
| 1393 | (vector (list (symbol-name package) | ||
| 1394 | 'face 'link | ||
| 1395 | 'follow-link t | ||
| 1396 | 'package-symbol package | ||
| 1397 | 'action 'package-menu-describe-package) | ||
| 1398 | (propertize (package-version-join version) | ||
| 1399 | 'font-lock-face face) | ||
| 1400 | (propertize status 'font-lock-face face) | ||
| 1401 | (propertize doc 'font-lock-face face))))) | ||
| 1360 | 1402 | ||
| 1361 | (defun package-menu-refresh () | 1403 | (defun package-menu-refresh () |
| 1362 | "Download the Emacs Lisp package archive. | 1404 | "Download the Emacs Lisp package archive. |
| @@ -1366,59 +1408,42 @@ This fetches the contents of each archive specified in | |||
| 1366 | (unless (eq major-mode 'package-menu-mode) | 1408 | (unless (eq major-mode 'package-menu-mode) |
| 1367 | (error "The current buffer is not a Package Menu")) | 1409 | (error "The current buffer is not a Package Menu")) |
| 1368 | (package-refresh-contents) | 1410 | (package-refresh-contents) |
| 1369 | (package--generate-package-list)) | 1411 | (package-menu--generate t)) |
| 1370 | 1412 | ||
| 1371 | (defun package-menu-revert (&optional arg noconfirm) | 1413 | (defun package-menu-describe-package (&optional button) |
| 1372 | "Update the list of packages. | 1414 | "Describe the current package. |
| 1373 | This function is the `revert-buffer-function' for Package Menu | 1415 | If optional arg BUTTON is non-nil, describe its associated package." |
| 1374 | buffers. The arguments are ignored." | ||
| 1375 | (interactive) | 1416 | (interactive) |
| 1376 | (unless (eq major-mode 'package-menu-mode) | 1417 | (let ((package (if button (button-get button 'package-symbol) |
| 1377 | (error "The current buffer is not a Package Menu")) | 1418 | (car (tabulated-list-get-id))))) |
| 1378 | (package--generate-package-list)) | 1419 | (if package |
| 1379 | 1420 | (describe-package package)))) | |
| 1380 | (defun package-menu-describe-package () | ||
| 1381 | "Describe the package in the current line." | ||
| 1382 | (interactive) | ||
| 1383 | (let ((name (package-menu-get-package))) | ||
| 1384 | (if name | ||
| 1385 | (describe-package (intern name)) | ||
| 1386 | (message "No package on this line")))) | ||
| 1387 | |||
| 1388 | (defun package-menu-mark-internal (what) | ||
| 1389 | (unless (eobp) | ||
| 1390 | (let ((buffer-read-only nil)) | ||
| 1391 | (beginning-of-line) | ||
| 1392 | (delete-char 1) | ||
| 1393 | (insert what) | ||
| 1394 | (forward-line)))) | ||
| 1395 | 1421 | ||
| 1396 | ;; fixme numeric argument | 1422 | ;; fixme numeric argument |
| 1397 | (defun package-menu-mark-delete (num) | 1423 | (defun package-menu-mark-delete (num) |
| 1398 | "Mark a package for deletion and move to the next line." | 1424 | "Mark a package for deletion and move to the next line." |
| 1399 | (interactive "p") | 1425 | (interactive "p") |
| 1400 | (if (string-equal (package-menu-get-status) "installed") | 1426 | (if (string-equal (package-menu-get-status) "installed") |
| 1401 | (package-menu-mark-internal "D") | 1427 | (tabulated-list-put-tag "D" t) |
| 1402 | (forward-line))) | 1428 | (forward-line))) |
| 1403 | 1429 | ||
| 1404 | (defun package-menu-mark-install (num) | 1430 | (defun package-menu-mark-install (num) |
| 1405 | "Mark a package for installation and move to the next line." | 1431 | "Mark a package for installation and move to the next line." |
| 1406 | (interactive "p") | 1432 | (interactive "p") |
| 1407 | (if (string-equal (package-menu-get-status) "available") | 1433 | (if (string-equal (package-menu-get-status) "available") |
| 1408 | (package-menu-mark-internal "I") | 1434 | (tabulated-list-put-tag "I" t) |
| 1409 | (forward-line))) | 1435 | (forward-line))) |
| 1410 | 1436 | ||
| 1411 | (defun package-menu-mark-unmark (num) | 1437 | (defun package-menu-mark-unmark (num) |
| 1412 | "Clear any marks on a package and move to the next line." | 1438 | "Clear any marks on a package and move to the next line." |
| 1413 | (interactive "p") | 1439 | (interactive "p") |
| 1414 | (package-menu-mark-internal " ")) | 1440 | (tabulated-list-put-tag " " t)) |
| 1415 | 1441 | ||
| 1416 | (defun package-menu-backup-unmark () | 1442 | (defun package-menu-backup-unmark () |
| 1417 | "Back up one line and clear any marks on that package." | 1443 | "Back up one line and clear any marks on that package." |
| 1418 | (interactive) | 1444 | (interactive) |
| 1419 | (forward-line -1) | 1445 | (forward-line -1) |
| 1420 | (package-menu-mark-internal " ") | 1446 | (tabulated-list-put-tag " ")) |
| 1421 | (forward-line -1)) | ||
| 1422 | 1447 | ||
| 1423 | (defun package-menu-mark-obsolete-for-deletion () | 1448 | (defun package-menu-mark-obsolete-for-deletion () |
| 1424 | "Mark all obsolete packages for deletion." | 1449 | "Mark all obsolete packages for deletion." |
| @@ -1428,7 +1453,7 @@ buffers. The arguments are ignored." | |||
| 1428 | (forward-line 2) | 1453 | (forward-line 2) |
| 1429 | (while (not (eobp)) | 1454 | (while (not (eobp)) |
| 1430 | (if (looking-at ".*\\s obsolete\\s ") | 1455 | (if (looking-at ".*\\s obsolete\\s ") |
| 1431 | (package-menu-mark-internal "D") | 1456 | (tabulated-list-put-tag "D" t) |
| 1432 | (forward-line 1))))) | 1457 | (forward-line 1))))) |
| 1433 | 1458 | ||
| 1434 | (defun package-menu-quick-help () | 1459 | (defun package-menu-quick-help () |
| @@ -1439,20 +1464,6 @@ buffers. The arguments are ignored." | |||
| 1439 | (define-obsolete-function-alias | 1464 | (define-obsolete-function-alias |
| 1440 | 'package-menu-view-commentary 'package-menu-describe-package "24.1") | 1465 | 'package-menu-view-commentary 'package-menu-describe-package "24.1") |
| 1441 | 1466 | ||
| 1442 | ;; Return the name of the package on the current line. | ||
| 1443 | (defun package-menu-get-package () | ||
| 1444 | (save-excursion | ||
| 1445 | (beginning-of-line) | ||
| 1446 | (if (looking-at ". \\([^ \t]*\\)") | ||
| 1447 | (match-string-no-properties 1)))) | ||
| 1448 | |||
| 1449 | ;; Return the version of the package on the current line. | ||
| 1450 | (defun package-menu-get-version () | ||
| 1451 | (save-excursion | ||
| 1452 | (beginning-of-line) | ||
| 1453 | (if (looking-at ". [^ \t]*[ \t]*\\([0-9.]*\\)") | ||
| 1454 | (match-string 1)))) | ||
| 1455 | |||
| 1456 | (defun package-menu-get-status () | 1467 | (defun package-menu-get-status () |
| 1457 | (save-excursion | 1468 | (save-excursion |
| 1458 | (if (looking-at ". [^ \t]*[ \t]*[^ \t]*[ \t]*\\([^ \t]*\\)") | 1469 | (if (looking-at ". [^ \t]*[ \t]*[^ \t]*[ \t]*\\([^ \t]*\\)") |
| @@ -1464,19 +1475,22 @@ buffers. The arguments are ignored." | |||
| 1464 | Packages marked for installation are downloaded and installed; | 1475 | Packages marked for installation are downloaded and installed; |
| 1465 | packages marked for deletion are removed." | 1476 | packages marked for deletion are removed." |
| 1466 | (interactive) | 1477 | (interactive) |
| 1467 | (let (install-list delete-list cmd) | 1478 | (unless (eq major-mode 'package-menu-mode) |
| 1479 | (error "The current buffer is not in Package Menu mode")) | ||
| 1480 | (let (install-list delete-list cmd id) | ||
| 1468 | (save-excursion | 1481 | (save-excursion |
| 1469 | (goto-char (point-min)) | 1482 | (goto-char (point-min)) |
| 1470 | (while (not (eobp)) | 1483 | (while (not (eobp)) |
| 1471 | (setq cmd (char-after)) | 1484 | (setq cmd (char-after)) |
| 1472 | (cond | 1485 | (unless (eq cmd ?\s) |
| 1473 | ((eq cmd ?\s) t) | 1486 | ;; This is the key (PACKAGE . VERSION-LIST). |
| 1474 | ((eq cmd ?D) | 1487 | (setq id (tabulated-list-get-id)) |
| 1475 | (push (cons (package-menu-get-package) | 1488 | (cond ((eq cmd ?D) |
| 1476 | (package-menu-get-version)) | 1489 | (push (cons (symbol-name (car id)) |
| 1477 | delete-list)) | 1490 | (package-version-join (cdr id))) |
| 1478 | ((eq cmd ?I) | 1491 | delete-list)) |
| 1479 | (push (package-menu-get-package) install-list))) | 1492 | ((eq cmd ?I) |
| 1493 | (push (car id) install-list)))) | ||
| 1480 | (forward-line))) | 1494 | (forward-line))) |
| 1481 | ;; Delete packages, prompting if necessary. | 1495 | ;; Delete packages, prompting if necessary. |
| 1482 | (when delete-list | 1496 | (when delete-list |
| @@ -1502,217 +1516,71 @@ packages marked for deletion are removed." | |||
| 1502 | (format "Install package `%s'? " (car install-list)) | 1516 | (format "Install package `%s'? " (car install-list)) |
| 1503 | (format "Install these %d packages (%s)? " | 1517 | (format "Install these %d packages (%s)? " |
| 1504 | (length install-list) | 1518 | (length install-list) |
| 1505 | (mapconcat 'identity install-list ", ")))) | 1519 | (mapconcat 'symbol-name install-list ", ")))) |
| 1506 | (dolist (elt install-list) | 1520 | (mapc 'package-install install-list))) |
| 1507 | (package-install (intern elt))))) | ||
| 1508 | ;; If we deleted anything, regenerate `package-alist'. This is done | 1521 | ;; If we deleted anything, regenerate `package-alist'. This is done |
| 1509 | ;; automatically if we installed a package. | 1522 | ;; automatically if we installed a package. |
| 1510 | (and delete-list (null install-list) | 1523 | (and delete-list (null install-list) |
| 1511 | (package-initialize)) | 1524 | (package-initialize)) |
| 1512 | (if (or delete-list install-list) | 1525 | (if (or delete-list install-list) |
| 1513 | (package-menu-revert) | 1526 | (package-menu--generate t) |
| 1514 | (message "No operations specified.")))) | 1527 | (message "No operations specified.")))) |
| 1515 | 1528 | ||
| 1516 | (defun package-print-package (package version key desc) | 1529 | (defun package-menu--version-predicate (A B) |
| 1517 | (let ((face | 1530 | (let ((vA (or (aref (cadr A) 1) '(0))) |
| 1518 | (cond ((string= key "built-in") 'font-lock-builtin-face) | 1531 | (vB (or (aref (cadr B) 1) '(0)))) |
| 1519 | ((string= key "available") 'default) | 1532 | (if (version-list-= vA vB) |
| 1520 | ((string= key "held") 'font-lock-constant-face) | 1533 | (package-menu--name-predicate A B) |
| 1521 | ((string= key "disabled") 'font-lock-warning-face) | 1534 | (version-list-< vA vB)))) |
| 1522 | ((string= key "installed") 'font-lock-comment-face) | 1535 | |
| 1523 | (t ; obsolete, but also the default. | 1536 | (defun package-menu--status-predicate (A B) |
| 1524 | 'font-lock-warning-face)))) | 1537 | (let ((sA (aref (cadr A) 2)) |
| 1525 | (insert (propertize " " 'font-lock-face face)) | 1538 | (sB (aref (cadr B) 2))) |
| 1526 | (insert-text-button (symbol-name package) | 1539 | (cond ((string= sA sB) |
| 1527 | 'face 'link | 1540 | (package-menu--name-predicate A B)) |
| 1528 | 'follow-link t | 1541 | ((string= sA "available") t) |
| 1529 | 'package-symbol package | 1542 | ((string= sB "available") nil) |
| 1530 | 'action (lambda (button) | 1543 | ((string= sA "installed") t) |
| 1531 | (describe-package | 1544 | ((string= sB "installed") nil) |
| 1532 | (button-get button 'package-symbol)))) | 1545 | ((string= sA "held") t) |
| 1533 | (indent-to 20 1) | 1546 | ((string= sB "held") nil) |
| 1534 | (insert (propertize (package-version-join version) 'font-lock-face face)) | 1547 | ((string= sA "built-in") t) |
| 1535 | (indent-to 32 1) | 1548 | ((string= sB "built-in") nil) |
| 1536 | (insert (propertize key 'font-lock-face face)) | 1549 | ((string= sA "obsolete") t) |
| 1537 | ;; FIXME: this 'when' is bogus... | 1550 | ((string= sB "obsolete") nil) |
| 1538 | (when desc | 1551 | (t (string< sA sB))))) |
| 1539 | (indent-to 43 1) | 1552 | |
| 1540 | (let ((opoint (point))) | 1553 | (defun package-menu--description-predicate (A B) |
| 1541 | (insert (propertize desc 'font-lock-face face)) | 1554 | (let ((dA (aref (cadr A) 3)) |
| 1542 | (upcase-region opoint (min (point) (1+ opoint))))) | 1555 | (dB (aref (cadr B) 3))) |
| 1543 | (insert "\n"))) | 1556 | (if (string= dA dB) |
| 1544 | 1557 | (package-menu--name-predicate A B) | |
| 1545 | (defun package-list-maybe-add (package version status description result) | 1558 | (string< dA dB)))) |
| 1546 | (unless (assoc (cons package version) result) | 1559 | |
| 1547 | (push (list (cons package version) status description) result)) | 1560 | (defun package-menu--name-predicate (A B) |
| 1548 | result) | 1561 | (string< (symbol-name (caar A)) |
| 1549 | 1562 | (symbol-name (caar B)))) | |
| 1550 | (defvar package-menu-package-list nil | ||
| 1551 | "List of packages to display in the Package Menu buffer. | ||
| 1552 | A value of nil means to display all packages.") | ||
| 1553 | |||
| 1554 | (defvar package-menu-sort-key nil | ||
| 1555 | "Sort key for the current Package Menu buffer.") | ||
| 1556 | |||
| 1557 | (defun package--generate-package-list () | ||
| 1558 | "Populate the current Package Menu buffer." | ||
| 1559 | (let ((inhibit-read-only t) | ||
| 1560 | info-list name desc hold builtin) | ||
| 1561 | (erase-buffer) | ||
| 1562 | ;; List installed packages | ||
| 1563 | (dolist (elt package-alist) | ||
| 1564 | (setq name (car elt)) | ||
| 1565 | (when (or (null package-menu-package-list) | ||
| 1566 | (memq name package-menu-package-list)) | ||
| 1567 | (setq desc (cdr elt) | ||
| 1568 | hold (cadr (assq name package-load-list))) | ||
| 1569 | (setq info-list | ||
| 1570 | (package-list-maybe-add | ||
| 1571 | name (package-desc-vers desc) | ||
| 1572 | ;; FIXME: it turns out to be tricky to see if this | ||
| 1573 | ;; package is presently activated. | ||
| 1574 | (if (stringp hold) "held" "installed") | ||
| 1575 | (package-desc-doc desc) | ||
| 1576 | info-list)))) | ||
| 1577 | |||
| 1578 | ;; List built-in packages | ||
| 1579 | (dolist (elt package--builtins) | ||
| 1580 | (setq name (car elt)) | ||
| 1581 | (when (and (not (eq name 'emacs)) ; Hide the `emacs' package. | ||
| 1582 | (or (null package-menu-package-list) | ||
| 1583 | (memq name package-menu-package-list))) | ||
| 1584 | (setq desc (cdr elt)) | ||
| 1585 | (setq info-list | ||
| 1586 | (package-list-maybe-add | ||
| 1587 | name (package-desc-vers desc) | ||
| 1588 | "built-in" | ||
| 1589 | (package-desc-doc desc) | ||
| 1590 | info-list)))) | ||
| 1591 | |||
| 1592 | ;; List available and disabled packages | ||
| 1593 | (dolist (elt package-archive-contents) | ||
| 1594 | (setq name (car elt) | ||
| 1595 | desc (cdr elt) | ||
| 1596 | hold (assq name package-load-list)) | ||
| 1597 | (when (or (null package-menu-package-list) | ||
| 1598 | (memq name package-menu-package-list)) | ||
| 1599 | (setq info-list | ||
| 1600 | (package-list-maybe-add name | ||
| 1601 | (package-desc-vers desc) | ||
| 1602 | (if (and hold (null (cadr hold))) | ||
| 1603 | "disabled" | ||
| 1604 | "available") | ||
| 1605 | (package-desc-doc (cdr elt)) | ||
| 1606 | info-list)))) | ||
| 1607 | ;; List obsolete packages | ||
| 1608 | (mapc (lambda (elt) | ||
| 1609 | (mapc (lambda (inner-elt) | ||
| 1610 | (setq info-list | ||
| 1611 | (package-list-maybe-add (car elt) | ||
| 1612 | (package-desc-vers | ||
| 1613 | (cdr inner-elt)) | ||
| 1614 | "obsolete" | ||
| 1615 | (package-desc-doc | ||
| 1616 | (cdr inner-elt)) | ||
| 1617 | info-list))) | ||
| 1618 | (cdr elt))) | ||
| 1619 | package-obsolete-alist) | ||
| 1620 | |||
| 1621 | (setq info-list | ||
| 1622 | (sort info-list | ||
| 1623 | (cond ((string= package-menu-sort-key "Package") | ||
| 1624 | 'package-menu--name-predicate) | ||
| 1625 | ((string= package-menu-sort-key "Version") | ||
| 1626 | 'package-menu--version-predicate) | ||
| 1627 | ((string= package-menu-sort-key "Description") | ||
| 1628 | 'package-menu--description-predicate) | ||
| 1629 | (t ; By default, sort by package status | ||
| 1630 | 'package-menu--status-predicate)))) | ||
| 1631 | |||
| 1632 | (dolist (elt info-list) | ||
| 1633 | (package-print-package (car (car elt)) | ||
| 1634 | (cdr (car elt)) | ||
| 1635 | (car (cdr elt)) | ||
| 1636 | (car (cdr (cdr elt))))) | ||
| 1637 | (goto-char (point-min)) | ||
| 1638 | (set-buffer-modified-p nil) | ||
| 1639 | (current-buffer))) | ||
| 1640 | |||
| 1641 | (defun package-menu--version-predicate (left right) | ||
| 1642 | (let ((vleft (or (cdr (car left)) '(0))) | ||
| 1643 | (vright (or (cdr (car right)) '(0)))) | ||
| 1644 | (if (version-list-= vleft vright) | ||
| 1645 | (package-menu--name-predicate left right) | ||
| 1646 | (version-list-< vleft vright)))) | ||
| 1647 | |||
| 1648 | (defun package-menu--status-predicate (left right) | ||
| 1649 | (let ((sleft (cadr left)) | ||
| 1650 | (sright (cadr right))) | ||
| 1651 | (cond ((string= sleft sright) | ||
| 1652 | (package-menu--name-predicate left right)) | ||
| 1653 | ((string= sleft "available") t) | ||
| 1654 | ((string= sright "available") nil) | ||
| 1655 | ((string= sleft "installed") t) | ||
| 1656 | ((string= sright "installed") nil) | ||
| 1657 | ((string= sleft "held") t) | ||
| 1658 | ((string= sright "held") nil) | ||
| 1659 | ((string= sleft "built-in") t) | ||
| 1660 | ((string= sright "built-in") nil) | ||
| 1661 | ((string= sleft "obsolete") t) | ||
| 1662 | ((string= sright "obsolete") nil) | ||
| 1663 | (t (string< sleft sright))))) | ||
| 1664 | |||
| 1665 | (defun package-menu--description-predicate (left right) | ||
| 1666 | (let ((sleft (car (cddr left))) | ||
| 1667 | (sright (car (cddr right)))) | ||
| 1668 | (if (string= sleft sright) | ||
| 1669 | (package-menu--name-predicate left right) | ||
| 1670 | (string< sleft sright)))) | ||
| 1671 | |||
| 1672 | (defun package-menu--name-predicate (left right) | ||
| 1673 | (string< (symbol-name (caar left)) | ||
| 1674 | (symbol-name (caar right)))) | ||
| 1675 | |||
| 1676 | (defun package-menu-sort-by-column (&optional e) | ||
| 1677 | "Sort the package menu by the column of the mouse click E." | ||
| 1678 | (interactive "e") | ||
| 1679 | (let* ((pos (event-start e)) | ||
| 1680 | (obj (posn-object pos)) | ||
| 1681 | (col (if obj | ||
| 1682 | (get-text-property (cdr obj) 'column-name (car obj)) | ||
| 1683 | (get-text-property (posn-point pos) 'column-name))) | ||
| 1684 | (buf (window-buffer (posn-window (event-start e))))) | ||
| 1685 | (with-current-buffer buf | ||
| 1686 | (when (eq major-mode 'package-menu-mode) | ||
| 1687 | (setq package-menu-sort-key col) | ||
| 1688 | (package--generate-package-list))))) | ||
| 1689 | |||
| 1690 | (defun package--list-packages (&optional packages) | ||
| 1691 | "Generate and pop to the *Packages* buffer. | ||
| 1692 | Optional PACKAGES is a list of names of packages (symbols) to | ||
| 1693 | list; the default is to display everything in `package-alist'." | ||
| 1694 | (require 'finder-inf nil t) | ||
| 1695 | (let ((buf (get-buffer-create "*Packages*"))) | ||
| 1696 | (with-current-buffer buf | ||
| 1697 | (package-menu-mode) | ||
| 1698 | (set (make-local-variable 'package-menu-package-list) packages) | ||
| 1699 | (set (make-local-variable 'package-menu-sort-key) nil) | ||
| 1700 | (package--generate-package-list)) | ||
| 1701 | ;; The package menu buffer has keybindings. If the user types | ||
| 1702 | ;; `M-x list-packages', that suggests it should become current. | ||
| 1703 | (switch-to-buffer buf))) | ||
| 1704 | 1563 | ||
| 1705 | ;;;###autoload | 1564 | ;;;###autoload |
| 1706 | (defun list-packages () | 1565 | (defun list-packages (&optional no-fetch) |
| 1707 | "Display a list of packages. | 1566 | "Display a list of packages. |
| 1708 | Fetches the updated list of packages before displaying. | 1567 | This first fetches the updated list of packages before |
| 1568 | displaying, unless a prefix argument NO-FETCH is specified. | ||
| 1709 | The list is displayed in a buffer named `*Packages*'." | 1569 | The list is displayed in a buffer named `*Packages*'." |
| 1710 | (interactive) | 1570 | (interactive "P") |
| 1571 | (require 'finder-inf nil t) | ||
| 1711 | ;; Initialize the package system if necessary. | 1572 | ;; Initialize the package system if necessary. |
| 1712 | (unless package--initialized | 1573 | (unless package--initialized |
| 1713 | (package-initialize t)) | 1574 | (package-initialize t)) |
| 1714 | (package-refresh-contents) | 1575 | (unless no-fetch |
| 1715 | (package--list-packages)) | 1576 | (package-refresh-contents)) |
| 1577 | (let ((buf (get-buffer-create "*Packages*"))) | ||
| 1578 | (with-current-buffer buf | ||
| 1579 | (package-menu-mode) | ||
| 1580 | (package-menu--generate)) | ||
| 1581 | ;; The package menu buffer has keybindings. If the user types | ||
| 1582 | ;; `M-x list-packages', that suggests it should become current. | ||
| 1583 | (switch-to-buffer buf))) | ||
| 1716 | 1584 | ||
| 1717 | ;;;###autoload | 1585 | ;;;###autoload |
| 1718 | (defalias 'package-list-packages 'list-packages) | 1586 | (defalias 'package-list-packages 'list-packages) |
| @@ -1722,7 +1590,7 @@ The list is displayed in a buffer named `*Packages*'." | |||
| 1722 | Does not fetch the updated list of packages before displaying. | 1590 | Does not fetch the updated list of packages before displaying. |
| 1723 | The list is displayed in a buffer named `*Packages*'." | 1591 | The list is displayed in a buffer named `*Packages*'." |
| 1724 | (interactive) | 1592 | (interactive) |
| 1725 | (package--list-packages)) | 1593 | (list-packages t)) |
| 1726 | 1594 | ||
| 1727 | (provide 'package) | 1595 | (provide 'package) |
| 1728 | 1596 | ||