branch: master
commit b941c5f995c2036c2b9cb1edb4154ad3abd09791
Author: Steven Allen <[email protected]>
Commit: Steven Allen <[email protected]>

    Add back the linux application cache.
    
    * counsel.el (counsel-linux-apps-list, counsel-linux-apps-parse,
      counsel-linux-apps-list-desktop-files): Cache parsed desktop files and
      invalidate the entire cache whenever any desktop file changes. This 
becomes
      important on machines with many (~500) desktop entries.
---
 counsel.el | 69 +++++++++++++++++++++++++++++++++++++++++++++-----------------
 1 file changed, 50 insertions(+), 19 deletions(-)

diff --git a/counsel.el b/counsel.el
index a5fe1b9..718eda0 100644
--- a/counsel.el
+++ b/counsel.el
@@ -2726,37 +2726,51 @@ And insert it into the minibuffer. Useful during
 (defvar counsel-linux-apps-faulty nil
   "List of faulty desktop files.")
 
+(defvar counsel--linux-apps-cache nil
+  "Cache of desktop files data.")
+
+(defvar counsel--linux-apps-cached-files nil
+  "List of cached desktop files.")
+
+(defvar counsel--linux-apps-cache-timestamp nil
+  "Time when we last updated the cached application list.")
+
 (defun counsel-linux-apps-list-desktop-files ()
-  "Returns an alist of ~(desktop-name . desktop-file)~ pairs for all Linux 
applications."
+  "Returns an alist of ~(desktop-name . desktop-file)~ pairs for all Linux 
applications.
+
+   This function always returns it's elements in a stable order."
   (let ((hash (make-hash-table :test #'equal))
         result)
-    (dolist (dir (reverse counsel-linux-apps-directories))
+    (dolist (dir counsel-linux-apps-directories)
       (when (file-exists-p dir)
         (let ((dir (file-name-as-directory dir)))
           (dolist (file (directory-files-recursively dir ".*\\.desktop$"))
-            (puthash
-             (subst-char-in-string ?/ ?- (file-relative-name file dir))
-             file
-             hash)))))
-    (maphash (lambda (key value)
-               (push (cons key value) result))
-             hash)
+            (let ((id (subst-char-in-string ?/ ?- (file-relative-name file 
dir))))
+              (unless (gethash id hash)
+                (push (cons id file) result)
+                (puthash id file hash)))))))
     result))
 
-(defun counsel-linux-apps-list ()
-  (let ((files (counsel-linux-apps-list-desktop-files)) result)
-    (dolist (file files result)
-      (unless (member (cdr file) counsel-linux-apps-faulty)
+(defun counsel-linux-apps-parse (desktop-entries-alist)
+  "Parse the given alist of desktop entries (~(id . file-name)~).
+
+   Any desktop entries that fail to parse are recorded in 
~counsel-linux-apps-faulty~."
+
+  (let (result)
+    (setq counsel-linux-apps-faulty nil)
+    (dolist (entry desktop-entries-alist result)
+      (let ((id (car entry))
+            (file (cdr entry)))
         (with-temp-buffer
-          (insert-file-contents (cdr file))
+          (insert-file-contents file)
           (goto-char (point-min))
           (let ((start (re-search-forward "^\\[Desktop Entry\\] *$" nil t))
                 (end (re-search-forward "^\\[" nil t))
                 name comment exec)
             (catch 'break
               (unless start
-                (push (cdr file) counsel-linux-apps-faulty)
-                (message "Warning: File %s has no [Desktop Entry] group" (cdr 
file))
+                (push file counsel-linux-apps-faulty)
+                (message "Warning: File %s has no [Desktop Entry] group" file)
                 (throw 'break nil))
 
               (goto-char start)
@@ -2771,8 +2785,8 @@ And insert it into the minibuffer. Useful during
 
               (goto-char start)
               (unless (re-search-forward "^Name *= *\\(.+\\)$" end t)
-                (push (cdr file) counsel-linux-apps-faulty)
-                (message "Warning: File %s has no Name" (cdr file))
+                (push file counsel-linux-apps-faulty)
+                (message "Warning: File %s has no Name" file)
                 (throw 'break nil))
               (setq name (match-string 1))
 
@@ -2799,9 +2813,26 @@ And insert it into the minibuffer. Useful during
                              (if comment
                                  (concat " - " comment)
                                ""))
-                     (car file))
+                     id)
                result))))))))
 
+(defun counsel-linux-apps-list ()
+  (let* ((new-desktop-alist (counsel-linux-apps-list-desktop-files))
+         (new-files (mapcar 'cdr new-desktop-alist)))
+    (unless (and
+             (equal new-files counsel--linux-apps-cached-files)
+             (null (cl-find-if
+                    (lambda (file)
+                      (time-less-p
+                       counsel--linux-apps-cache-timestamp
+                       (file-attribute-modification-time (file-attributes 
file))))
+                    new-files)))
+      (setq counsel--linux-apps-cache (counsel-linux-apps-parse 
new-desktop-alist)
+            counsel--linux-apps-cache-timestamp (current-time)
+            counsel--linux-apps-cached-files new-files)))
+  counsel--linux-apps-cache)
+
+
 (defun counsel-linux-app-action-default (desktop-shortcut)
   "Launch DESKTOP-SHORTCUT."
   (setq desktop-shortcut (cdr desktop-shortcut))

Reply via email to