[Patch] apps-menu filtering



Jeremy Hankins <nowan nowan org> writes:

>
> Another way would be to be able to specify a predicate function to do
> the filtering.  The function would be passed a record and would return
> true or false to indicate whether or not to include it in the menu.  You
> could define a couple of standard functions (which would be able to be
> called from within user-provided functions) to do common things (e.g.,
> to do the sort of filtering that t or nil would do).  That way the
> apps-menu-display-all would be simple to use for novices (it could still
> take options like t and nil) but if its value is a function (or even a
> lisp form?) instead of t or nil that would be the predicate used.  If
> you wanted, you could even get a bit fancier, and allow the function to
> modify the record (i.e., the function would return the record, possibly
> modified, or nil indicating not to include it).  That way a power user
> could, e.g., rename certain entries or maybe even categories easily.
>
> Just an idea; I don't know how easy it would be to work this into your
> current system.

OK, I'm not sure if it's exactly as you describe, but it seems to be
working here.

`apps-menu-display-all is replaced by `apps-menu-filter which can be
'default, 'some, a pre-defined function or a lambda.

For example:

To make a games filter:

(define (games-filter fdol)
  (if (not (string-match "[Gg]ame" (cdr (assoc "Categories" fdol))))
     fdol))

(setq apps-menu-filter games-filter)

or,

(setq apps-menu-filter (lambda (x) 
			 (if (not (string-match 
				   "[Gg]ame" 
				   (cdr (assoc "Categories" x)))) 
			     x)))

To use a pre-defined filter in your own filters:

(define (my-filter fdol)
  (if (not (string-match "[Gg]ame" (cdr (assoc "Categories" fdol))))
      (fdo-hidden-filter (fdo-nodisplay-filter fdol))))

or,

(define (my-filter fdol)
  (games-filter (fdo-hidden-filter (fdo-nodisplay-filter fdol))))

(setq apps-menu-filter my-filter)

If the users function throws an error for some reason, the record will 
be returned for display in the menu.

Any function can be used as an 'apps-menu-filter if it will either
return a desktop-file list or '().  So you can change the records as
they go through with the filter before the menu is generated.

For example:

A filter to change the category of Emacs to "Utility"

(define (my-filter fdol)
  (when fdol
    (let ((fdo-name (cdr (assoc "Name" fdol))))
      (if (string-match "[Ee]macs" fdo-name)
	  (rplacd (assoc "Categories" fdol) "Utility"))
      fdol)))

One could define as many filters as they like and link them all together
by using the output of one as the input of the next.  A users function
should return '() if the input is also '().

`(fdo-filter-record) and `(parse-desktop-file) are also now exported and
can be used to test filters.

For example:

(setq test-d (parse-desktop-file 
	      "/usr/share/applications/emacs.desktop"))

(fdo-filter-record fdol my-filter)
==>
("Desktop Entry"
 ("Name" . "Emacs")
 ("GenericName" . "Text Editor")
 ("Comment" . "Edit text")
 ("Exec" . "emacs %F")
 ("Icon" . "emacs")
 ("Type" . "Application")
 ("Terminal" . "false")
 ("Categories" . "Utility")
 ("StartupWMClass" . "Emacs"))

This patch includes an update to sawfish.texi

Cheers,

diff --git a/lisp/sawfish/wm/ext/apps-menu.jl b/lisp/sawfish/wm/ext/apps-menu.jl
index 5dc7405..0a6f962 100644
--- a/lisp/sawfish/wm/ext/apps-menu.jl
+++ b/lisp/sawfish/wm/ext/apps-menu.jl
@@ -39,7 +39,13 @@
 
     (export generate-apps-menu
 	    init-apps-menu
-	    update-apps-menu)
+	    update-apps-menu
+	    parse-desktop-file
+	    fdo-filter-record
+	    fdo-nodisplay-filter
+	    fdo-hidden-filter
+	    fdo-onlyshowin-filter
+	    fdo-notshowin-filter)
 
     (open rep
 	  rep.io.files
@@ -62,11 +68,14 @@ and *.desktop files. If you set `apps-menu', then it won't happen anyway.")
     "Your own applications menu entries. It is followed by auto generated
 applications menu.")
 
-  (defvar apps-menu-show-all nil
-    "Some entries are hidden from the menu, especially GNOME Apps like
-eog, nautilus or evince. If you want to have them added to your menu,
-set this to non-nil.")
-  
+  (defvar apps-menu-filter 'default
+    "The filter to use while generating the `apps-menu'. The default filters
+include `fdo-nodisplay-filter' `fdo-hidden-filter' `fdo-onlyshowin-filter'
+and `fdo-notshowin-filter'.  Can also be set with 'default or 'some, both
+of which are combinations of the default filters, 'default uses them all
+and 'some only uses `fdo-notshowin-filter' and `fdo-onlyshowin-filter'.
+This can be set to 'nil or '() to perform no filtering on the `apps-menu'.")
+
   (defvar desktop-directory '("/usr/share/applications")
     "List of directories to look for *.desktop files.")
 
@@ -81,7 +90,6 @@ set this to non-nil.")
   (define name-string "Name[")
 
   ;; fdo-desktop-file-parsing
-
   (define (desktop-skip-line-p instring)
     (or (eq (aref instring 0) ?#)
 	(eq (aref instring 0) ?\n)))
@@ -127,8 +135,9 @@ set this to non-nil.")
 	(parse-desktop-file-line infile))))
 
   (define (parse-desktop-file infile)
-    (let ((d-file (open-file infile 'read)))
-      (parse-desktop-file-line d-file)))
+    (when (desktop-file-p infile)
+      (let ((d-file (open-file infile 'read)))
+	(parse-desktop-file-line d-file))))
 
   ;; generic functions
 
@@ -333,55 +342,68 @@ exile it."
 	    (concat (trim-percent (cdr (assoc "Exec" fdo-list)))
 		    " &"))))
 
-  (define (desk-file->fdo-list desk-file)
-    (when (desktop-file-p desk-file)
-       (let ((fdo-list (fdo-check-exile (parse-desktop-file desk-file))))
-	 (let ((a (assoc "NoDisplay" fdo-list))
-	       (b (assoc "OnlyShowIn" fdo-list))
-	       (c (assoc "NotShowIn" fdo-list))
-	       (d (assoc "Hidden" fdo-list)))
-	   ;; 't
-	   (setq fdo-list (append fdo-list (cons (cons "apps-menu-display?" "true"))))
-	   ;; 'maybe
-	   (when (eq apps-menu-show-all 'maybe)
-	     (when b
-	       (if (string-match (concat (quote-regexp desktop-environment) "*")
-				 (string-downcase (cdr b)))
-		   (rplacd (assoc "apps-menu-display?" fdo-list) "true")
-		 (rplacd (assoc "apps-menu-display?" fdo-list) "false")))
-	     (when c
-	       (if (string-match (concat (quote-regexp desktop-environment) "*")
-				 (string-downcase (cdr c)))
-		   (rplacd (assoc "apps-menu-display?" fdo-list) "false")
-		 (rplacd (assoc "apps-menu-display?" fdo-list) "true"))))
-	   ;; 'nil
-	   (when (or (eq apps-menu-show-all 'nil) (not apps-menu-show-all))
-	     (when a
-	       (if (string-match "[Ff]" (cdr a))
-		   (rplacd (assoc "apps-menu-display?" fdo-list) "true")
-		 (rplacd (assoc "apps-menu-display?" fdo-list) "false")))
-	     (when d
-	       (if (string-match "[Ff]" (cdr d))
-		   (rplacd (assoc "apps-menu-display?" fdo-list) "true")
-		 (rplacd (assoc "apps-menu-display?" fdo-list) "false")))
-	     (when b
-	       (if (string-match (concat (quote-regexp desktop-environment) "*")
-				 (string-downcase (cdr b)))
-		   (rplacd (assoc "apps-menu-display?" fdo-list) "true")
-		 (rplacd (assoc "apps-menu-display?" fdo-list) "false")))
-	     (when c
-	       (if (string-match (concat (quote-regexp desktop-environment) "*")
-				 (string-downcase (cdr c)))
-		   (rplacd (assoc "apps-menu-display?" fdo-list) "false")
-		 (rplacd (assoc "apps-menu-display?" fdo-list) "true")))))
-	   fdo-list)))
+  ;; Apps-Menu Filtering
+
+  (define (fdo-nodisplay-filter fdol)
+    "Return the desktop-file-list if NoDisplay is False, or if NoDisplay is
+not present in the desktop-file-list"
+    (if (assoc "NoDisplay" fdol)
+	(if (string-match "[Ff]" (cdr (assoc "NoDisplay" fdol)))
+	    fdol)
+      fdol))
+  
+  (define (fdo-hidden-filter fdol)
+    "Return the desktop-file-list if Hidden is False, or if Hidden is
+not present in the desktop-file-list"
+    (if (assoc "Hidden" fdol)
+	(if (string-match "[Ff]" (string-downcase (cdr (assoc "OnlyShowIn" fdol))))
+	    fdol)
+      fdol))
+
+  (define (fdo-onlyshowin-filter fdol)
+    "Return the desktop-file-list if OnlyShowIn matches `desktop-environment', 
+or if OnlyShowIn is not present in the desktop-file-list"
+    (if (assoc "OnlyShowIn" fdol)
+	(if (string-match desktop-environment (string-downcase (cdr (assoc "OnlyShowIn" fdol))))
+	    fdol)
+      fdol))
+
+  (define (fdo-notshowin-filter fdol)
+    "Return the desktop-file-list if NotShowIn does not match `desktop-environment', 
+or if NotShowIn is not present in the desktop-file-list"
+    (if (assoc "NotShowIn" fdol)
+	(if (not (string-match desktop-environment (string-downcase (cdr (assoc "NotShowIn" fdol)))))
+	    fdol)
+      fdol))  
+
+  (define (fdo-filter-record fdol display-test)
+    "Return the result of `display-test' which can be a pre-set filter,
+such as `default' or `some' or it can be a pre-defined function of
+your choosing, which should either return the desktop-file-list or '(). 
+If `display-test' is not defined, will return the input desktop-file-list."
+    (cond 
+     ((eq display-test 'default)
+      (fdo-hidden-filter 
+       (fdo-notshowin-filter 
+	(fdo-onlyshowin-filter 
+	 (fdo-nodisplay-filter fdol)))))
+     ((eq display-test 'some)
+      (fdo-notshowin-filter 
+       (fdo-onlyshowin-filter fdol)))
+     ((functionp display-test)
+      (condition-case nil
+	  (display-test fdol)
+	(error fdol)))
+     ((not display-test)
+      fdol)
+     (t
+      fdol)))
 
   ;; generate a sawfish menu entry from a .desktop file
   (define (generate-menu-entry fdo-list)
     "Generate a menu entry to run the program specified in the the
 desktop file `desk-file'."
-    (when (and fdo-list
-	       (string= (cdr (assoc "apps-menu-display?" fdo-list)) "true"))
+    (when fdo-list
       (list
        (determine-desktop-category
 	(cdr (assoc "Categories" fdo-list)))
@@ -395,9 +417,14 @@ desktop file `desk-file'."
     (setq local-menu nil)
     (let ((desk-files (flatten (map-dir-files desktop-directory))))
       (mapc (lambda (x)
-	      (setq local-menu
+	      (setq local-menu 
 		    (append local-menu
-			    (list (generate-menu-entry (desk-file->fdo-list x)))))) desk-files)
+			    (list (generate-menu-entry 
+				   (fdo-filter-record
+				    (fdo-check-exile 
+				     (parse-desktop-file x)) 
+				    apps-menu-filter))))))
+	      desk-files)
       (if apps-menu-alphabetize
 	  (alphabetize-entries (fix-cats desktop-cat-alist))
 	(fix-cats desktop-cat-alist))))
diff --git a/man/sawfish.texi b/man/sawfish.texi
index c7ba16e..e2c5388 100644
--- a/man/sawfish.texi
+++ b/man/sawfish.texi
@@ -5173,14 +5173,19 @@ Your own application menu entries. It is followed by auto generated
 applications menu.
 @end defvar
 
- defvar apps-menu-ignore-no-display
-Some entries are hidden from the menu, especially GNOME Apps like
-eog, nautilus or evince. If you want to have them added to your menu,
-set this to non-nil. Default is @code{nil}.
+ defvar apps-menu-filter
+The filter to use while generating the @code{apps-menu}. The default filters
+include @code{fdo-nodisplay-filter} @code{fdo-hidden-filter} @code{fdo-onlyshowin-filter}
+and @code{fdo-notshowin-filter}.  Can also be set with @code{'default} or @code{'some}, 
+both of which are combinations of the default filters, @code{'default} uses them all
+and @code{some} only uses @code{fdo-notshowin-filter} and @code{fdo-onlyshowin-filter}.
+This can be set to @code{nil} or @code{()} to perform no filtering on the @code{apps-menu}.
+This can also be set to any pre-defined function that can return a desktop-file list or nil.
+Default is @code{default}.
 @end defvar
 
 @defvar desktop-directory
-List of directories to look for *.desktop files. Default is
+List of directories to look for @file{*.desktop} files. Default is
 @code{'("/usr/share/applications")}.
 @end defvar
 
-- 
mrl


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]