diff options
| author | Federico Tedin | 2019-09-26 19:18:58 +0200 |
|---|---|---|
| committer | Stefan Kangas | 2019-10-08 19:24:12 +0200 |
| commit | f96b8fd27c382a941c52c2938544b9b0e3a2fb0e (patch) | |
| tree | 22708a866bce395e64ce5c883ac349e415dc2570 | |
| parent | ba57f1a4273cabb53cbae86ad34b0a4bf01e1513 (diff) | |
| download | emacs-f96b8fd27c382a941c52c2938544b9b0e3a2fb0e.tar.gz emacs-f96b8fd27c382a941c52c2938544b9b0e3a2fb0e.zip | |
Filter packages by name in list-packages. (Bug#36981)
* lisp/emacs-lisp/package.el (package-menu-filter-by-name): New
function to filter packages by name.
(package-menu-clear-filter): New function to clear applied filters.
(package-menu-filter-by-keyword): Rename function from
package-menu-filter.
(package-menu--generate): Don't change 'q' binding anymore.
(package-menu-mode-map): Bind '/ n' to package-menu-filter-by-name, '/
k' to package-menu-filter-by-keyword and '/ /' to
package-menu-clear-filter.
(package-menu-mode-menu): Update menu entries for the three functions.
* test/lisp/emacs-lisp/package-tests.el (package-test-list-filter-by-name)
(package-test-list-clear-filter): New tests.
* doc/emacs/package.texi: Document usage of
package-menu-filter-by-name, package-menu-clear-filter and update
reference to package-menu-filter-by-keyword.
* etc/NEWS: Announce changes.
| -rw-r--r-- | doc/emacs/package.texi | 19 | ||||
| -rw-r--r-- | etc/NEWS | 10 | ||||
| -rw-r--r-- | lisp/emacs-lisp/package.el | 47 | ||||
| -rw-r--r-- | test/lisp/emacs-lisp/package-tests.el | 22 |
4 files changed, 81 insertions, 17 deletions
diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi index 2c09ca89024..d97648af1bb 100644 --- a/doc/emacs/package.texi +++ b/doc/emacs/package.texi | |||
| @@ -136,11 +136,20 @@ Refresh the package list (@code{package-menu-refresh}). This fetches | |||
| 136 | the list of available packages from the package archive again, and | 136 | the list of available packages from the package archive again, and |
| 137 | recomputes the package list. | 137 | recomputes the package list. |
| 138 | 138 | ||
| 139 | @item f | 139 | @item / k |
| 140 | Filter the package list (@code{package-menu-filter}). This prompts | 140 | Filter the package list by keyword |
| 141 | for a keyword (e.g., @samp{games}), then shows only the packages | 141 | (@code{package-menu-filter-by-keyword}). This prompts for a keyword |
| 142 | that relate to that keyword. To restore the full package list, | 142 | (e.g., @samp{games}), then shows only the packages that relate to that |
| 143 | type @kbd{q}. | 143 | keyword. |
| 144 | |||
| 145 | @item / n | ||
| 146 | Filter the package list by name (@code{package-menu-filter-by-name}). | ||
| 147 | This prompts for a string, then shows only the packages whose names | ||
| 148 | match a regexp with that value. | ||
| 149 | |||
| 150 | @item / / | ||
| 151 | Clear filter currently applied to the package list | ||
| 152 | (@code{package-menu-clear-filter}). | ||
| 144 | 153 | ||
| 145 | @item H | 154 | @item H |
| 146 | Permanently hide packages that match a regexp | 155 | Permanently hide packages that match a regexp |
| @@ -1006,6 +1006,16 @@ early init file. | |||
| 1006 | 1006 | ||
| 1007 | *** New function 'package-activate-all'. | 1007 | *** New function 'package-activate-all'. |
| 1008 | 1008 | ||
| 1009 | +++ | ||
| 1010 | *** New functions for filtering packages list. | ||
| 1011 | A new function has been added which allows users to filter the | ||
| 1012 | packages list by name: 'package-menu-filter-by-name'. By default, it | ||
| 1013 | is bound to '/ n'. Additionally, the function | ||
| 1014 | 'package-menu-fiter-by-keyword' has been renamed from | ||
| 1015 | 'package-menu-filter'. Its keybinding has also been changed to '/ k' | ||
| 1016 | (from 'f'). To clear any of the two filters, the user can now call | ||
| 1017 | the 'package-menu-clear-filter' function, bound to '/ /' by default. | ||
| 1018 | |||
| 1009 | --- | 1019 | --- |
| 1010 | *** Imenu support has been added to 'package-menu-mode'. | 1020 | *** Imenu support has been added to 'package-menu-mode'. |
| 1011 | 1021 | ||
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 0b2dc24ebb9..20462064afd 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el | |||
| @@ -2685,7 +2685,9 @@ either a full name or nil, and EMAIL is a valid email address." | |||
| 2685 | (define-key map "i" 'package-menu-mark-install) | 2685 | (define-key map "i" 'package-menu-mark-install) |
| 2686 | (define-key map "U" 'package-menu-mark-upgrades) | 2686 | (define-key map "U" 'package-menu-mark-upgrades) |
| 2687 | (define-key map "r" 'package-menu-refresh) | 2687 | (define-key map "r" 'package-menu-refresh) |
| 2688 | (define-key map "f" 'package-menu-filter) | 2688 | (define-key map (kbd "/ k") 'package-menu-filter-by-keyword) |
| 2689 | (define-key map (kbd "/ n") 'package-menu-filter-by-name) | ||
| 2690 | (define-key map (kbd "/ /") 'package-menu-clear-filter) | ||
| 2689 | (define-key map "~" 'package-menu-mark-obsolete-for-deletion) | 2691 | (define-key map "~" 'package-menu-mark-obsolete-for-deletion) |
| 2690 | (define-key map "x" 'package-menu-execute) | 2692 | (define-key map "x" 'package-menu-execute) |
| 2691 | (define-key map "h" 'package-menu-quick-help) | 2693 | (define-key map "h" 'package-menu-quick-help) |
| @@ -2717,7 +2719,11 @@ either a full name or nil, and EMAIL is a valid email address." | |||
| 2717 | ["Unmark" package-menu-mark-unmark :help "Clear any marks on a package and move to the next line"] | 2719 | ["Unmark" package-menu-mark-unmark :help "Clear any marks on a package and move to the next line"] |
| 2718 | 2720 | ||
| 2719 | "--" | 2721 | "--" |
| 2720 | ["Filter Package List" package-menu-filter :help "Filter package selection (q to go back)"] | 2722 | ("Filter Packages" |
| 2723 | ["Filter by Keyword" package-menu-filter-by-keyword :help "Filter packages by keyword"] | ||
| 2724 | ["Filter by Name" package-menu-filter-by-name :help "Filter packages by name"] | ||
| 2725 | ["Clear Filter" package-menu-clear-filter :help "Clear package list filter"]) | ||
| 2726 | |||
| 2721 | ["Hide by Regexp" package-menu-hide-package :help "Permanently hide all packages matching a regexp"] | 2727 | ["Hide by Regexp" package-menu-hide-package :help "Permanently hide all packages matching a regexp"] |
| 2722 | ["Display Older Versions" package-menu-toggle-hiding | 2728 | ["Display Older Versions" package-menu-toggle-hiding |
| 2723 | :style toggle :selected (not package-menu--hide-packages) | 2729 | :style toggle :selected (not package-menu--hide-packages) |
| @@ -3028,9 +3034,6 @@ shown." | |||
| 3028 | (let ((filters (mapconcat #'identity keywords ","))) | 3034 | (let ((filters (mapconcat #'identity keywords ","))) |
| 3029 | (concat "Package[" filters "]")) | 3035 | (concat "Package[" filters "]")) |
| 3030 | "Package")) | 3036 | "Package")) |
| 3031 | (if keywords | ||
| 3032 | (define-key package-menu-mode-map "q" 'package-show-package-list) | ||
| 3033 | (define-key package-menu-mode-map "q" 'quit-window)) | ||
| 3034 | (tabulated-list-init-header) | 3037 | (tabulated-list-init-header) |
| 3035 | (tabulated-list-print remember-pos)) | 3038 | (tabulated-list-print remember-pos)) |
| 3036 | 3039 | ||
| @@ -3660,10 +3663,8 @@ shown." | |||
| 3660 | (select-window win) | 3663 | (select-window win) |
| 3661 | (switch-to-buffer buf)))) | 3664 | (switch-to-buffer buf)))) |
| 3662 | 3665 | ||
| 3663 | ;; package-menu--generate rebinds "q" on the fly, so we have to | 3666 | (defun package-menu-filter-by-keyword (keyword) |
| 3664 | ;; hard-code the binding in the doc-string here. | 3667 | "Filter the \"*Packages*\" buffer by KEYWORD. |
| 3665 | (defun package-menu-filter (keyword) | ||
| 3666 | "Filter the *Packages* buffer. | ||
| 3667 | Show only those items that relate to the specified KEYWORD. | 3668 | Show only those items that relate to the specified KEYWORD. |
| 3668 | 3669 | ||
| 3669 | KEYWORD can be a string or a list of strings. If it is a list, a | 3670 | KEYWORD can be a string or a list of strings. If it is a list, a |
| @@ -3673,9 +3674,7 @@ Interactively, it is a list of strings separated by commas. | |||
| 3673 | KEYWORD can also be used to filter by status or archive name by | 3674 | KEYWORD can also be used to filter by status or archive name by |
| 3674 | using keywords like \"arc:gnu\" and \"status:available\". | 3675 | using keywords like \"arc:gnu\" and \"status:available\". |
| 3675 | Statuses available include \"incompat\", \"available\", | 3676 | Statuses available include \"incompat\", \"available\", |
| 3676 | \"built-in\" and \"installed\". | 3677 | \"built-in\" and \"installed\"." |
| 3677 | |||
| 3678 | To restore the full package list, type `q'." | ||
| 3679 | (interactive | 3678 | (interactive |
| 3680 | (list (completing-read-multiple | 3679 | (list (completing-read-multiple |
| 3681 | "Keywords (comma separated): " (package-all-keywords)))) | 3680 | "Keywords (comma separated): " (package-all-keywords)))) |
| @@ -3683,6 +3682,30 @@ To restore the full package list, type `q'." | |||
| 3683 | (list keyword) | 3682 | (list keyword) |
| 3684 | keyword))) | 3683 | keyword))) |
| 3685 | 3684 | ||
| 3685 | (defun package-menu-filter-by-name (name) | ||
| 3686 | "Filter the \"*Packages*\" buffer by NAME. | ||
| 3687 | Show only those items whose name matches the regular expression | ||
| 3688 | NAME. If NAME is nil or the empty string, show all packages." | ||
| 3689 | (interactive (list (read-from-minibuffer "Filter by name (regexp): "))) | ||
| 3690 | (if (or (not name) (string-empty-p name)) | ||
| 3691 | (package-show-package-list t nil) | ||
| 3692 | ;; Update `tabulated-list-entries' so that it contains all | ||
| 3693 | ;; packages before searching. | ||
| 3694 | (package-menu--refresh t nil) | ||
| 3695 | (let (matched) | ||
| 3696 | (dolist (entry tabulated-list-entries) | ||
| 3697 | (let* ((pkg-name (package-desc-name (car entry)))) | ||
| 3698 | (when (string-match name (symbol-name pkg-name)) | ||
| 3699 | (push pkg-name matched)))) | ||
| 3700 | (if matched | ||
| 3701 | (package-show-package-list matched nil) | ||
| 3702 | (user-error "No packages found"))))) | ||
| 3703 | |||
| 3704 | (defun package-menu-clear-filter () | ||
| 3705 | "Clear any filter currently applied to the \"*Packages*\" buffer." | ||
| 3706 | (interactive) | ||
| 3707 | (package-menu--generate t t)) | ||
| 3708 | |||
| 3686 | (defun package-list-packages-no-fetch () | 3709 | (defun package-list-packages-no-fetch () |
| 3687 | "Display a list of packages. | 3710 | "Display a list of packages. |
| 3688 | Does not fetch the updated list of packages before displaying. | 3711 | Does not fetch the updated list of packages before displaying. |
diff --git a/test/lisp/emacs-lisp/package-tests.el b/test/lisp/emacs-lisp/package-tests.el index 0edb81d6a11..8670e6f3fac 100644 --- a/test/lisp/emacs-lisp/package-tests.el +++ b/test/lisp/emacs-lisp/package-tests.el | |||
| @@ -365,6 +365,28 @@ Must called from within a `tar-mode' buffer." | |||
| 365 | (should-not (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+\\(available\\|new\\)" nil t)) | 365 | (should-not (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+\\(available\\|new\\)" nil t)) |
| 366 | (kill-buffer buf)))) | 366 | (kill-buffer buf)))) |
| 367 | 367 | ||
| 368 | (ert-deftest package-test-list-filter-by-name () | ||
| 369 | "Ensure package list is filtered correctly by package name." | ||
| 370 | (with-package-test () | ||
| 371 | (let ((buf (package-list-packages))) | ||
| 372 | (package-menu-filter-by-name "tetris") | ||
| 373 | (goto-char (point-min)) | ||
| 374 | (should (re-search-forward "^\\s-+tetris" nil t)) | ||
| 375 | (should (= (count-lines (point-min) (point-max)) 1)) | ||
| 376 | (kill-buffer buf)))) | ||
| 377 | |||
| 378 | (ert-deftest package-test-list-clear-filter () | ||
| 379 | "Ensure package list filter is cleared correctly." | ||
| 380 | (with-package-test () | ||
| 381 | (let ((buf (package-list-packages))) | ||
| 382 | (let ((num-packages (count-lines (point-min) (point-max)))) | ||
| 383 | (should (> num-packages 1)) | ||
| 384 | (package-menu-filter-by-name "tetris") | ||
| 385 | (should (= (count-lines (point-min) (point-max)) 1)) | ||
| 386 | (package-menu-clear-filter) | ||
| 387 | (should (= (count-lines (point-min) (point-max)) num-packages))) | ||
| 388 | (kill-buffer buf)))) | ||
| 389 | |||
| 368 | (ert-deftest package-test-update-archives () | 390 | (ert-deftest package-test-update-archives () |
| 369 | "Test updating package archives." | 391 | "Test updating package archives." |
| 370 | (with-package-test () | 392 | (with-package-test () |