>From c38a35406a9c76d5bf5479d01aee169a056a254c Mon Sep 17 00:00:00 2001 From: Federico Tedin Date: Thu, 26 Sep 2019 19:18:58 +0200 Subject: [PATCH 1/1] 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): Add a test for package-menu-filter-by-name. (package-test-list-clear-filter): Add a test for package-menu-clear-filter. * 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. --- doc/emacs/package.texi | 19 ++++++++---- etc/NEWS | 16 ++++++++++ lisp/emacs-lisp/package.el | 43 ++++++++++++++++++++------- test/lisp/emacs-lisp/package-tests.el | 24 ++++++++++++++- 4 files changed, 85 insertions(+), 17 deletions(-) diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi index 2c09ca8902..f7ff4f01a1 100644 --- a/doc/emacs/package.texi +++ b/doc/emacs/package.texi @@ -136,11 +136,20 @@ Package Menu the list of available packages from the package archive again, and recomputes the package list. -@item f -Filter the package list (@code{package-menu-filter}). This prompts -for a keyword (e.g., @samp{games}), then shows only the packages -that relate to that keyword. To restore the full package list, -type @kbd{q}. +@item / k +Filter the package list by keyword +(@code{package-menu-filter-by-keyword}). This prompts for a keyword +(e.g., @samp{games}), then shows only the packages that relate to that +keyword. + +@item / s +Filter the package list by name (@code{package-menu-filter-by-name}). +This prompts for a string, then shows only the packages whose names +match a regexp with that value. + +@item / / +Clear filter currently applied to the package list +(@code{package-menu-clear-filter}). @item H Permanently hide packages that match a regexp diff --git a/etc/NEWS b/etc/NEWS index 09394432aa..75b01f7372 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -974,6 +974,22 @@ early init file. *** New function 'package-activate-all'. ++++ +*** New function 'package-menu-filter-by-name'. +Allows users to filter packages by name on the packages list. By +default, it is bound to '/ n'. To clear the filter, use '/ /'. + ++++ +*** Function 'package-menu-fiter-by-keyword' has been renamed +from 'package-menu-filter'. Its keybinding has also been changed to +'/ k' (from 'f'). To clear the filter, '/ /' must now be used instead +of 'q'. + ++++ +*** New function 'package-menu-clear-filter' +Allows users to clear a filter applied with 'package-menu-filter-by-name' or +'package-menu-filter-by-keyword'. + --- *** Imenu support has been added to 'package-menu-mode'. diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index a8362cb205..ef3da5298c 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -2667,7 +2667,9 @@ package-menu-mode-map (define-key map "i" 'package-menu-mark-install) (define-key map "U" 'package-menu-mark-upgrades) (define-key map "r" 'package-menu-refresh) - (define-key map "f" 'package-menu-filter) + (define-key map (kbd "/ k") 'package-menu-filter-by-keyword) + (define-key map (kbd "/ n") 'package-menu-filter-by-name) + (define-key map (kbd "/ /") 'package-menu-clear-filter) (define-key map "~" 'package-menu-mark-obsolete-for-deletion) (define-key map "x" 'package-menu-execute) (define-key map "h" 'package-menu-quick-help) @@ -2699,7 +2701,9 @@ package-menu-mode-map ["Unmark" package-menu-mark-unmark :help "Clear any marks on a package and move to the next line"] "--" - ["Filter Package List" package-menu-filter :help "Filter package selection (q to go back)"] + ["Filter Packages by Keyword" package-menu-filter-by-keyword :help "Filter packages by keyword"] + ["Filter Packages by Name" package-menu-filter-by-name :help "Filter packages by name"] + ["Clear Packages Filter" package-menu-clear-filter :help "Clear package list filter"] ["Hide by Regexp" package-menu-hide-package :help "Permanently hide all packages matching a regexp"] ["Display Older Versions" package-menu-toggle-hiding :style toggle :selected (not package-menu--hide-packages) @@ -3010,9 +3014,6 @@ package-menu--generate (let ((filters (mapconcat #'identity keywords ","))) (concat "Package[" filters "]")) "Package")) - (if keywords - (define-key package-menu-mode-map "q" 'package-show-package-list) - (define-key package-menu-mode-map "q" 'quit-window)) (tabulated-list-init-header) (tabulated-list-print remember-pos)) @@ -3627,9 +3628,7 @@ package-show-package-list (select-window win) (switch-to-buffer buf)))) -;; package-menu--generate rebinds "q" on the fly, so we have to -;; hard-code the binding in the doc-string here. -(defun package-menu-filter (keyword) +(defun package-menu-filter-by-keyword (keyword) "Filter the *Packages* buffer. Show only those items that relate to the specified KEYWORD. @@ -3640,9 +3639,7 @@ package-menu-filter KEYWORD can also be used to filter by status or archive name by using keywords like \"arc:gnu\" and \"status:available\". Statuses available include \"incompat\", \"available\", -\"built-in\" and \"installed\". - -To restore the full package list, type `q'." +\"built-in\" and \"installed\"." (interactive (list (completing-read-multiple "Keywords (comma separated): " (package-all-keywords)))) @@ -3650,6 +3647,30 @@ package-menu-filter (list keyword) keyword))) +(defun package-menu-filter-by-name (name) + "Filter the *Packages* buffer by NAME. +Show only those items whose name matches the regular expression +NAME. If NAME is nil or the empty string, show all packages." + (interactive (list (read-from-minibuffer "Filter by name (regexp): "))) + (if (or (not name) (string-empty-p name)) + (package-show-package-list t nil) + ;; Update `tabulated-list-entries' so that it contains all + ;; packages before searching. + (package-menu--refresh t nil) + (let (matched) + (dolist (entry tabulated-list-entries) + (let* ((pkg-name (package-desc-name (car entry)))) + (when (string-match name (symbol-name pkg-name)) + (push pkg-name matched)))) + (if matched + (package-show-package-list matched nil) + (user-error "No packages found"))))) + +(defun package-menu-clear-filter () + "Clear any filter currently applied to the *Packages* buffer." + (interactive) + (package-menu--generate t t)) + (defun package-list-packages-no-fetch () "Display a list of packages. 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 c757bccf67..a2ee9f06b1 100644 --- a/test/lisp/emacs-lisp/package-tests.el +++ b/test/lisp/emacs-lisp/package-tests.el @@ -28,7 +28,7 @@ ;; Run this in a clean Emacs session using: ;; -;; $ emacs -Q --batch -L . -l package-test.el -l ert -f ert-run-tests-batch-and-exit +;; $ emacs -Q --batch -L . -l package-tests.el -l ert -f ert-run-tests-batch-and-exit ;;; Code: @@ -360,6 +360,28 @@ package-test--compatible-p (should-not (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+\\(available\\|new\\)" nil t)) (kill-buffer buf)))) +(ert-deftest package-test-list-filter-by-name () + "Ensure package list is filtered correctly by package name." + (with-package-test () + (let ((buf (package-list-packages))) + (package-menu-filter-by-name "tetris") + (goto-char (point-min)) + (should (re-search-forward "^\\s-+tetris" nil t)) + (should (= (count-lines (point-min) (point-max)) 1)) + (kill-buffer buf)))) + +(ert-deftest package-test-list-clear-filter () + "Ensure package list filter is cleared correctly." + (with-package-test () + (let ((buf (package-list-packages))) + (let ((num-packages (count-lines (point-min) (point-max)))) + (should (> num-packages 1)) + (package-menu-filter-by-name "tetris") + (should (= (count-lines (point-min) (point-max)) 1)) + (package-menu-clear-filter) + (should (= (count-lines (point-min) (point-max)) num-packages))) + (kill-buffer buf)))) + (ert-deftest package-test-update-archives () "Test updating package archives." (with-package-test () -- 2.17.1