aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Zlatanov2013-12-14 14:55:19 -0500
committerTed Zlatanov2013-12-14 14:55:19 -0500
commit5ae811ddef14ea1989088c259a9ed2d14d5332b4 (patch)
treecbe7a4ec4c082f4f8d1e9f0a959632b28d9e0ca5
parent2897da4d7be9f0082e88140ef2de2c463d62fea7 (diff)
downloademacs-5ae811ddef14ea1989088c259a9ed2d14d5332b4.tar.gz
emacs-5ae811ddef14ea1989088c259a9ed2d14d5332b4.zip
Support filtering by keywords in package listings.
* emacs-lisp/package.el (package-built-in-p): Support both built-in and the package.el converted package descriptions. (package-show-package-list): Allow keywords. (package-keyword-button-action): Use it instead of `finder-list-matches'. (package-menu-filter-interactive): Interactive filtering (by keyword) function. (package-menu--generate): Support keywords and change keymappings and headers when they are given. (package--has-keyword-p): Helper function. (package-menu--refresh): Use it. (package--mapc): Helper function. (package-all-keywords): Use it. (package-menu-mode-map): Set up menu items and keybindings to provide a filtering UI.
-rw-r--r--lisp/ChangeLog18
-rw-r--r--lisp/emacs-lisp/package.el126
2 files changed, 124 insertions, 20 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 246b7ae5b5f..0eabdf86ffa 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,5 +1,23 @@
12013-12-14 Teodor Zlatanov <tzz@lifelogs.com> 12013-12-14 Teodor Zlatanov <tzz@lifelogs.com>
2 2
3 * emacs-lisp/package.el (package-built-in-p): Support both
4 built-in and the package.el converted package descriptions.
5 (package-show-package-list): Allow keywords.
6 (package-keyword-button-action): Use it instead of
7 `finder-list-matches'.
8 (package-menu-filter-interactive): Interactive filtering (by
9 keyword) function.
10 (package-menu--generate): Support keywords and change keymappings
11 and headers when they are given.
12 (package--has-keyword-p): Helper function.
13 (package-menu--refresh): Use it.
14 (package--mapc): Helper function.
15 (package-all-keywords): Use it.
16 (package-menu-mode-map): Set up menu items and keybindings to
17 provide a filtering UI.
18
192013-12-14 Teodor Zlatanov <tzz@lifelogs.com>
20
3 * net/gnutls.el (gnutls-verify-error): New defcustom to control 21 * net/gnutls.el (gnutls-verify-error): New defcustom to control
4 the behavior when a certificate fails validation. Defaults to 22 the behavior when a certificate fails validation. Defaults to
5 old behavior: never abort, just warn. 23 old behavior: never abort, just warn.
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el
index b8c21e0386b..407b277fa9f 100644
--- a/lisp/emacs-lisp/package.el
+++ b/lisp/emacs-lisp/package.el
@@ -524,13 +524,15 @@ Return the max version (as a string) if the package is held at a lower version."
524 "Return true if PACKAGE is built-in to Emacs. 524 "Return true if PACKAGE is built-in to Emacs.
525Optional arg MIN-VERSION, if non-nil, should be a version list 525Optional arg MIN-VERSION, if non-nil, should be a version list
526specifying the minimum acceptable version." 526specifying the minimum acceptable version."
527 (let ((bi (assq package package--builtin-versions))) 527 (if (package-desc-p package) ;; was built-in and then was converted
528 (cond 528 (eq 'builtin (package-desc-dir package))
529 (bi (version-list-<= min-version (cdr bi))) 529 (let ((bi (assq package package--builtin-versions)))
530 (min-version nil) 530 (cond
531 (t 531 (bi (version-list-<= min-version (cdr bi)))
532 (require 'finder-inf nil t) ; For `package--builtins'. 532 (min-version nil)
533 (assq package package--builtins))))) 533 (t
534 (require 'finder-inf nil t) ; For `package--builtins'.
535 (assq package package--builtins))))))
534 536
535(defun package--from-builtin (bi-desc) 537(defun package--from-builtin (bi-desc)
536 (package-desc-create :name (pop bi-desc) 538 (package-desc-create :name (pop bi-desc)
@@ -1528,10 +1530,9 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1528 (revert-buffer nil t) 1530 (revert-buffer nil t)
1529 (goto-char (point-min))))) 1531 (goto-char (point-min)))))
1530 1532
1531(autoload 'finder-list-matches "finder")
1532(defun package-keyword-button-action (button) 1533(defun package-keyword-button-action (button)
1533 (let ((pkg-keyword (button-get button 'package-keyword))) 1534 (let ((pkg-keyword (button-get button 'package-keyword)))
1534 (finder-list-matches pkg-keyword))) 1535 (package-show-package-list t (list pkg-keyword))))
1535 1536
1536(defun package-make-button (text &rest props) 1537(defun package-make-button (text &rest props)
1537 (let ((button-text (if (display-graphic-p) text (concat "[" text "]"))) 1538 (let ((button-text (if (display-graphic-p) text (concat "[" text "]")))
@@ -1557,6 +1558,7 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1557 (define-key map "i" 'package-menu-mark-install) 1558 (define-key map "i" 'package-menu-mark-install)
1558 (define-key map "U" 'package-menu-mark-upgrades) 1559 (define-key map "U" 'package-menu-mark-upgrades)
1559 (define-key map "r" 'package-menu-refresh) 1560 (define-key map "r" 'package-menu-refresh)
1561 (define-key map "f" 'package-menu-filter-interactive)
1560 (define-key map "~" 'package-menu-mark-obsolete-for-deletion) 1562 (define-key map "~" 'package-menu-mark-obsolete-for-deletion)
1561 (define-key map "x" 'package-menu-execute) 1563 (define-key map "x" 'package-menu-execute)
1562 (define-key map "h" 'package-menu-quick-help) 1564 (define-key map "h" 'package-menu-quick-help)
@@ -1565,6 +1567,9 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages."
1565 (define-key menu-map [mq] 1567 (define-key menu-map [mq]
1566 '(menu-item "Quit" quit-window 1568 '(menu-item "Quit" quit-window
1567 :help "Quit package selection")) 1569 :help "Quit package selection"))
1570 (define-key menu-map [mf]
1571 '(menu-item "Filter" package-menu-filter-interactive
1572 :help "Filter package selection (q to go back)"))
1568 (define-key menu-map [s1] '("--")) 1573 (define-key menu-map [s1] '("--"))
1569 (define-key menu-map [mn] 1574 (define-key menu-map [mn]
1570 '(menu-item "Next" next-line 1575 '(menu-item "Next" next-line
@@ -1677,9 +1682,10 @@ package PKG-DESC, add one. The alist is keyed with PKG-DESC."
1677 "installed" 1682 "installed"
1678 "unsigned")))))))) 1683 "unsigned"))))))))
1679 1684
1680(defun package-menu--refresh (&optional packages) 1685(defun package-menu--refresh (&optional packages keywords)
1681 "Re-populate the `tabulated-list-entries'. 1686 "Re-populate the `tabulated-list-entries'.
1682PACKAGES should be nil or t, which means to display all known packages." 1687PACKAGES should be nil or t, which means to display all known packages.
1688KEYWORDS should be nil or a list of keywords."
1683 ;; Construct list of (PKG-DESC . STATUS). 1689 ;; Construct list of (PKG-DESC . STATUS).
1684 (unless packages (setq packages t)) 1690 (unless packages (setq packages t))
1685 (let (info-list name) 1691 (let (info-list name)
@@ -1688,12 +1694,14 @@ PACKAGES should be nil or t, which means to display all known packages."
1688 (setq name (car elt)) 1694 (setq name (car elt))
1689 (when (or (eq packages t) (memq name packages)) 1695 (when (or (eq packages t) (memq name packages))
1690 (dolist (pkg (cdr elt)) 1696 (dolist (pkg (cdr elt))
1691 (package--push pkg (package-desc-status pkg) info-list)))) 1697 (when (package--has-keyword-p pkg keywords)
1698 (package--push pkg (package-desc-status pkg) info-list)))))
1692 1699
1693 ;; Built-in packages: 1700 ;; Built-in packages:
1694 (dolist (elt package--builtins) 1701 (dolist (elt package--builtins)
1695 (setq name (car elt)) 1702 (setq name (car elt))
1696 (when (and (not (eq name 'emacs)) ; Hide the `emacs' package. 1703 (when (and (not (eq name 'emacs)) ; Hide the `emacs' package.
1704 (package--has-keyword-p (package--from-builtin elt) keywords)
1697 (or package-list-unversioned 1705 (or package-list-unversioned
1698 (package--bi-desc-version (cdr elt))) 1706 (package--bi-desc-version (cdr elt)))
1699 (or (eq packages t) (memq name packages))) 1707 (or (eq packages t) (memq name packages)))
@@ -1705,20 +1713,89 @@ PACKAGES should be nil or t, which means to display all known packages."
1705 (when (or (eq packages t) (memq name packages)) 1713 (when (or (eq packages t) (memq name packages))
1706 (dolist (pkg (cdr elt)) 1714 (dolist (pkg (cdr elt))
1707 ;; Hide obsolete packages. 1715 ;; Hide obsolete packages.
1708 (unless (package-installed-p (package-desc-name pkg) 1716 (when (and (not (package-installed-p (package-desc-name pkg)
1709 (package-desc-version pkg)) 1717 (package-desc-version pkg)))
1718 (package--has-keyword-p pkg keywords))
1710 (package--push pkg (package-desc-status pkg) info-list))))) 1719 (package--push pkg (package-desc-status pkg) info-list)))))
1711 1720
1712 ;; Print the result. 1721 ;; Print the result.
1713 (setq tabulated-list-entries 1722 (setq tabulated-list-entries
1714 (mapcar #'package-menu--print-info info-list)))) 1723 (mapcar #'package-menu--print-info info-list))))
1715 1724
1716(defun package-menu--generate (remember-pos packages) 1725(defun package-all-keywords ()
1726 "Collect all package keywords"
1727 (let (keywords)
1728 (package--mapc (lambda (desc)
1729 (let* ((extras (and desc (package-desc-extras desc)))
1730 (desc-keywords (cdr (assoc :keywords extras))))
1731 (setq keywords (append keywords desc-keywords)))))
1732 keywords))
1733
1734(defun package--mapc (function &optional packages)
1735 "Call FUNCTION for all known PACKAGES.
1736PACKAGES can be nil or t, which means to display all known
1737packages, or a list of packages.
1738
1739Built-in packages are converted with `package--from-builtin'."
1740 (unless packages (setq packages t))
1741 (let (name)
1742 ;; Installed packages:
1743 (dolist (elt package-alist)
1744 (setq name (car elt))
1745 (when (or (eq packages t) (memq name packages))
1746 (mapc function (cdr elt))))
1747
1748 ;; Built-in packages:
1749 (dolist (elt package--builtins)
1750 (setq name (car elt))
1751 (when (and (not (eq name 'emacs)) ; Hide the `emacs' package.
1752 (or package-list-unversioned
1753 (package--bi-desc-version (cdr elt)))
1754 (or (eq packages t) (memq name packages)))
1755 (funcall function (package--from-builtin elt))))
1756
1757 ;; Available and disabled packages:
1758 (dolist (elt package-archive-contents)
1759 (setq name (car elt))
1760 (when (or (eq packages t) (memq name packages))
1761 (dolist (pkg (cdr elt))
1762 ;; Hide obsolete packages.
1763 (unless (package-installed-p (package-desc-name pkg)
1764 (package-desc-version pkg))
1765 (funcall function pkg)))))))
1766
1767(defun package--has-keyword-p (desc &optional keywords)
1768 "Test if package DESC has any of the given KEYWORDS.
1769When none are given, the package matches."
1770 (if keywords
1771 (let* ((extras (and desc (package-desc-extras desc)))
1772 (desc-keywords (cdr (assoc :keywords extras)))
1773 found)
1774 (dolist (k keywords)
1775 (when (and (not found)
1776 (member k desc-keywords))
1777 (setq found t)))
1778 found)
1779 t))
1780
1781(defun package-menu--generate (remember-pos packages &optional keywords)
1717 "Populate the Package Menu. 1782 "Populate the Package Menu.
1718 If REMEMBER-POS is non-nil, keep point on the same entry. 1783 If REMEMBER-POS is non-nil, keep point on the same entry.
1719PACKAGES should be t, which means to display all known packages, 1784PACKAGES should be t, which means to display all known packages,
1720or a list of package names (symbols) to display." 1785or a list of package names (symbols) to display.
1721 (package-menu--refresh packages) 1786
1787With KEYWORDS given, only packages with those keywords are
1788shown."
1789 (package-menu--refresh packages keywords)
1790 (setf (car (aref tabulated-list-format 0))
1791 (if keywords
1792 (let ((filters (mapconcat 'identity keywords ",")))
1793 (concat "Package[" filters "]"))
1794 "Package"))
1795 (if keywords
1796 (define-key package-menu-mode-map "q" 'package-show-package-list)
1797 (define-key package-menu-mode-map "q" 'quit-window))
1798 (tabulated-list-init-header)
1722 (tabulated-list-print remember-pos)) 1799 (tabulated-list-print remember-pos))
1723 1800
1724(defun package-menu--print-info (pkg) 1801(defun package-menu--print-info (pkg)
@@ -2014,18 +2091,27 @@ The list is displayed in a buffer named `*Packages*'."
2014(defalias 'package-list-packages 'list-packages) 2091(defalias 'package-list-packages 'list-packages)
2015 2092
2016;; Used in finder.el 2093;; Used in finder.el
2017(defun package-show-package-list (packages) 2094(defun package-show-package-list (&optional packages keywords)
2018 "Display PACKAGES in a *Packages* buffer. 2095 "Display PACKAGES in a *Packages* buffer.
2019This is similar to `list-packages', but it does not fetch the 2096This is similar to `list-packages', but it does not fetch the
2020updated list of packages, and it only displays packages with 2097updated list of packages, and it only displays packages with
2021names in PACKAGES (which should be a list of symbols)." 2098names in PACKAGES (which should be a list of symbols).
2099
2100When KEYWORDS are given, only packages with those KEYWORDS are
2101shown."
2102 (interactive)
2022 (require 'finder-inf nil t) 2103 (require 'finder-inf nil t)
2023 (let ((buf (get-buffer-create "*Packages*"))) 2104 (let ((buf (get-buffer-create "*Packages*")))
2024 (with-current-buffer buf 2105 (with-current-buffer buf
2025 (package-menu-mode) 2106 (package-menu-mode)
2026 (package-menu--generate nil packages)) 2107 (package-menu--generate nil packages keywords))
2027 (switch-to-buffer buf))) 2108 (switch-to-buffer buf)))
2028 2109
2110(defun package-menu-filter-interactive (keyword)
2111 "Filter the *Packages* buffer."
2112 (interactive (list (completing-read "Keyword: " (package-all-keywords))))
2113 (package-show-package-list t (list keyword)))
2114
2029(defun package-list-packages-no-fetch () 2115(defun package-list-packages-no-fetch ()
2030 "Display a list of packages. 2116 "Display a list of packages.
2031Does not fetch the updated list of packages before displaying. 2117Does not fetch the updated list of packages before displaying.