4 Commits 28a9b0a36c ... f3a137628e

Author SHA1 Message Date
  Alex Kost f3a137628e examples/buffers: Use default filters 4 years ago
  Joe Bloggs ab62fcefc3 core: Add interactive filters 4 years ago
  Alex Kost ed3f2c8b26 core: Add 'bui-current-params' 4 years ago
  Jonas Bernoulli 9a2321b322 Fix typo 4 years ago
3 changed files with 94 additions and 9 deletions
  1. 39 2
      bui-core.el
  2. 48 1
      bui-utils.el
  3. 7 6
      examples/buffers.el

+ 39 - 2
bui-core.el

@@ -1,6 +1,7 @@
 ;;; bui-core.el --- Core functionality for BUI  -*- lexical-binding: t -*-
 ;;; bui-core.el --- Core functionality for BUI  -*- lexical-binding: t -*-
 
 
-;; Copyright © 2014–2017 Alex Kost <alezost@gmail.com>
+;; Copyright © 2014–2017, 2021 Alex Kost <alezost@gmail.com>
+;; Copyright © 2020 Joe Bloggs <vapniks@yahoo.com>
 
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; it under the terms of the GNU General Public License as published by
@@ -181,7 +182,8 @@ See `bui-define-current-args-accessor' for details."
   "Hint with the default keys for filtering.
   "Hint with the default keys for filtering.
 See `bui-hint' for details.")
 See `bui-hint' for details.")
 
 
-(defcustom bui-filter-predicates nil
+(defcustom bui-filter-predicates
+  '(bui-filter-by-regexp bui-filter-by-sexp)
   "List of available filter predicates.
   "List of available filter predicates.
 These predicates are used as completions for
 These predicates are used as completions for
 '\\[bui-enable-filter]' command to hide entries. See
 '\\[bui-enable-filter]' command to hide entries. See
@@ -214,6 +216,33 @@ If PREDICATES are not specified, display all entries."
                     (bui-current-entry-type)
                     (bui-current-entry-type)
                     (bui-current-buffer-type)))
                     (bui-current-buffer-type)))
 
 
+(defun bui-filter-by-regexp (entry param regexp)
+  "Filter the current entries by regexp.
+Return non-nil, if ENTRY's parameter PARAM matches REGEXP.
+Interactively, prompt for PARAM and REGEXP."
+  (interactive
+   (list '<>
+         (intern
+          (completing-read "Parameter: "
+		           (mapcar #'symbol-name (bui-current-params))))
+	 (read-regexp "Regexp: ")))
+  (string-match-p regexp
+                  (bui-get-string (bui-assq-value entry param))))
+
+(defun bui-filter-by-sexp (entry sexp)
+  "Filter the current entries using sexp.
+Evaluate SEXP and return its value.
+SEXP can use the ENTRY's parameters as symbols, e.g.:
+
+  '(or (string-match-p \"foo\" name)
+       (string-match-p \"bar\" synopsis))
+"
+  (interactive (list '<> (read--expression "sexp: ")))
+  (dolist (param (bui-current-params))
+    (setq sexp (cl-subst (bui-assq-value entry param)
+                         param sexp)))
+  (eval sexp))
+
 (defun bui-enable-filter (predicate &optional single?)
 (defun bui-enable-filter (predicate &optional single?)
   "Apply filter PREDICATE to the current entries.
   "Apply filter PREDICATE to the current entries.
 Interactively, prompt for PREDICATE, choosing candidates from the
 Interactively, prompt for PREDICATE, choosing candidates from the
@@ -235,6 +264,7 @@ only active one (remove the other active predicates)."
              current-prefix-arg))))
              current-prefix-arg))))
   (or (functionp predicate)
   (or (functionp predicate)
       (error "Wrong filter predicate: %S" predicate))
       (error "Wrong filter predicate: %S" predicate))
+  (setq predicate (bui-apply-interactive predicate))
   (if (if single?
   (if (if single?
           (equal (list predicate) bui-active-filter-predicates)
           (equal (list predicate) bui-active-filter-predicates)
         (memq predicate bui-active-filter-predicates))
         (memq predicate bui-active-filter-predicates))
@@ -586,6 +616,13 @@ Use '\\[bui-disable-filters]' to remove filters")))))
   "Return non-nil if PARAM for ENTRY-TYPE/BUFFER-TYPE is boolean."
   "Return non-nil if PARAM for ENTRY-TYPE/BUFFER-TYPE is boolean."
   (memq param (bui-symbol-value entry-type buffer-type 'boolean-params)))
   (memq param (bui-symbol-value entry-type buffer-type 'boolean-params)))
 
 
+(defun bui-current-params ()
+  "Return parameter names of the current buffer."
+  (mapcar #'car
+          (bui-symbol-value (bui-current-entry-type)
+                            (bui-current-buffer-type)
+                            'format)))
+
 
 
 ;;; Displaying entries
 ;;; Displaying entries
 
 

+ 48 - 1
bui-utils.el

@@ -1,6 +1,7 @@
 ;;; bui-utils.el --- General utility functions  -*- lexical-binding: t -*-
 ;;; bui-utils.el --- General utility functions  -*- lexical-binding: t -*-
 
 
-;; Copyright © 2014–2017 Alex Kost <alezost@gmail.com>
+;; Copyright © 2014–2017, 2021 Alex Kost <alezost@gmail.com>
+;; Copyright © 2020 Joe Bloggs <vapniks@yahoo.com>
 
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; it under the terms of the GNU General Public License as published by
@@ -431,6 +432,52 @@ return `defcustom' clause instead."
            :group ',group)
            :group ',group)
       `(defvar ,symbol ,val ,doc))))
       `(defvar ,symbol ,val ,doc))))
 
 
+(defun bui-apply-interactive (function)
+  "Call the interactive form of FUNCTION to (partially) apply arguments.
+Return FUNCTION, if it has no `interactive' form.  Otherwise,
+return a new function that does the same as FUNCTION, except its
+arguments are fixed to the values obtained interactively during
+this FUNCTION call.
+
+Any `<>' symbols returned by the `interactive' form of FUNCTION will be
+used as the place holders for arguments of the returned function.
+Also, if the `interactive' form returns a '&rest symbol, this will
+be used in the arglist of the returned function.
+
+For example, the following call:
+
+ (bui-apply-interactive
+  (lambda (x y &rest z)
+    (interactive (list (read-number \"Factor: \")
+		       '<> '&rest '<>))
+    (* x (apply '+ y z))))
+
+will prompt for a number, x, and return a function that takes any
+number of arguments, adds them together and multiplies the result
+by x."
+  (let ((interact (interactive-form function)))
+    (if interact
+	(let* ((args  (eval `(call-interactively
+			      (lambda (&rest args) ,interact args))))
+	       (args2 (mapcar (lambda (x) (if (eq x '<>) (gensym) x))
+			      (cl-remove-if-not
+                               (lambda (y) (memq y '(<> &rest)))
+			       args)))
+	       (args3 (remove '&rest args))
+	       (args4 (remove '&rest args2))
+	       (restp (memq '&rest args2)))
+	  ;; Use `eval' rather than `macroexpand' so that the function
+	  ;; can be called with `funcall'.
+	  (eval `(lambda ,args2
+		   (,@(if restp `(apply ,function) `(,function))
+		    ,@(mapcar
+		       (lambda (x) (if (eq x '<>) (pop args4)
+				     (if (or (symbolp x) (listp x))
+					 (list 'quote x)
+				       x)))
+		       args3)))))
+      function)))
+
 (provide 'bui-utils)
 (provide 'bui-utils)
 
 
 ;;; bui-utils.el ends here
 ;;; bui-utils.el ends here

+ 7 - 6
examples/buffers.el

@@ -1,6 +1,6 @@
 ;;; buffers.el --- List of buffers and buffer info
 ;;; buffers.el --- List of buffers and buffer info
 
 
-;; Copyright © 2016–2017 Alex Kost <alezost@gmail.com>
+;; Copyright © 2016–2017, 2021 Alex Kost <alezost@gmail.com>
 
 
 ;; This program is free software; you can redistribute it and/or modify
 ;; This program is free software; you can redistribute it and/or modify
 ;; it under the terms of the GNU General Public License as published by
 ;; it under the terms of the GNU General Public License as published by
@@ -25,7 +25,7 @@
 ;; To try it, load this file (for example, with "M-x load-file"), and
 ;; To try it, load this file (for example, with "M-x load-file"), and
 ;; run "M-x buffers" command.  There you can mark several buffers (with
 ;; run "M-x buffers" command.  There you can mark several buffers (with
 ;; "m") and press "i" to display the info buffer; press "f f" to enable
 ;; "m") and press "i" to display the info buffer; press "f f" to enable
-;; fiters, etc.  Press "h" to look at the "hint" (available keys).
+;; filters, etc.  Press "h" to look at the "hint" (available keys).
 
 
 ;;; Code:
 ;;; Code:
 
 
@@ -75,10 +75,11 @@
   :titles '((mod-time . "Modification Time"))
   :titles '((mod-time . "Modification Time"))
   :get-entries-function #'buffers-get-entries
   :get-entries-function #'buffers-get-entries
   :filter-predicates
   :filter-predicates
-  '(buffers-buffer-ephemeral?
-    buffers-buffer-non-ephemeral?
-    buffers-buffer-visiting-file?
-    buffers-buffer-not-visiting-file?))
+  (append bui-filter-predicates
+          '(buffers-buffer-ephemeral?
+            buffers-buffer-non-ephemeral?
+            buffers-buffer-visiting-file?
+            buffers-buffer-not-visiting-file?)))
 
 
 (defun buffers-describe-mode-function (button)
 (defun buffers-describe-mode-function (button)
   (describe-function (intern (button-label button))))
   (describe-function (intern (button-label button))))