branch: externals/ivy-hydra
commit e3a72a5fcf83ab991c09b7341eebb06b6acbceab
Author: dude <[email protected]>
Commit: Oleh Krehel <[email protected]>

    Add XDG recent files to counsel-recentf.
    
    - Include option to turn on or off as "counsel-recentf-include-xdg-list".
    - Create function "counsel-recentf-candidates" to return recentf 
candidates. Use
      this function in counsel-recentf and counsel-buffer-or-recentf-candidates.
      - This function is where it is decided to include the XDG listed files.
    - Because this feature uses the library "dom.el", it only works for Emacs
      > 25. Therefore, the XDG files list is gotten using a macro, to prevent 
the
      evaluation/compilation of functions that might not exist.
      - This new macro, "counsel--recentf-get-xdg-recent-files", uses "(require
        'dom)" after checking the version of Emacs.
    
    Recently used files are located within the file "recently-used.xbel", 
located in
    the directory specified in the environment variable "XDG_DATA_HOME" or in
    "$HOME/.local/share". Emacs produces this directory by the function
    "xdg-data-home".
    
    The file is an XML file following the XBEL format, which is parsed using
    "libxml-parse-xml-region" and traversed using functions provided in the 
Emacs
    library "dom.el".
    
    The standard from FreeDesktop.org (a.k.a. "fd.o" or "xdg") is described in 
the
    following website:
    
    https://www.freedesktop.org/wiki/Specifications/desktop-bookmark-spec/
    
    Fixes #2403
---
 counsel.el | 46 ++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 44 insertions(+), 2 deletions(-)

diff --git a/counsel.el b/counsel.el
index 9efe54c..2616b71 100644
--- a/counsel.el
+++ b/counsel.el
@@ -2224,13 +2224,18 @@ When INITIAL-INPUT is non-nil, use it in the minibuffer 
during completion."
 (defvar recentf-list)
 (declare-function recentf-mode "recentf")
 
+(defcustom counsel-recentf-include-xdg-list nil
+  "Include recently used files listed by XDG-compliant environments, e.g. 
GNOME and KDE.
+https://www.freedesktop.org/wiki/Specifications/desktop-bookmark-spec/.";
+  :type 'boolean)
+
 ;;;###autoload
 (defun counsel-recentf ()
   "Find a file on `recentf-list'."
   (interactive)
   (require 'recentf)
   (recentf-mode)
-  (ivy-read "Recentf: " (mapcar #'substring-no-properties recentf-list)
+  (ivy-read "Recentf: " (counsel-recentf-candidates)
             :action (lambda (f)
                       (with-ivy-window
                         (find-file f)))
@@ -2242,6 +2247,43 @@ When INITIAL-INPUT is non-nil, use it in the minibuffer 
during completion."
    ("f" find-file-other-frame "other frame")
    ("x" counsel-find-file-extern "open externally")))
 
+(defun counsel-recentf-candidates ()
+  "Return candidates for `counsel-recentf'."
+  (append (mapcar #'substring-no-properties recentf-list)
+          (and counsel-recentf-include-xdg-list
+               (version< "25" emacs-version)
+               (counsel--recentf-get-xdg-recent-files))))
+
+(defun counsel--recentf-get-xdg-recent-files ()
+
+  "Get recent files as listed by XDG compliant programs.
+
+Requires Emacs 25.
+
+It searches for the file \"recently-used.xbel\" which lists files
+and directories, in the directory returned by the function
+`xdg-data-home'. This file is processed using functionality
+provided by the libxml2 bindings and the \"dom\" library."
+  (require 'dom)
+  (let ((file-of-recent-files
+         (expand-file-name "recently-used.xbel" (xdg-data-home))))
+    (if (not (file-readable-p file-of-recent-files))
+        (user-error "List of XDG recent files not found.")
+      (delq
+       nil
+       (mapcar
+        (lambda (bookmark-node)
+          (let ((full-file-name (url-unhex-string
+                                 (substring (dom-attr bookmark-node 'href)
+                                            7)))) ; Strip "file://"
+            (when (file-exists-p full-file-name)
+              full-file-name)))
+        (nreverse (dom-by-tag (with-temp-buffer
+                                (insert-file-contents file-of-recent-files)
+                                (libxml-parse-xml-region (point-min)
+                                                         (point-max)))
+                              'bookmark)))))))
+
 (defun counsel-buffer-or-recentf-candidates ()
   "Return candidates for `counsel-buffer-or-recentf'."
   (require 'recentf)
@@ -2255,7 +2297,7 @@ When INITIAL-INPUT is non-nil, use it in the minibuffer 
during completion."
     (append
      buffers
      (cl-remove-if (lambda (f) (member f buffers))
-                   (mapcar #'substring-no-properties recentf-list)))))
+                   (counsel-recentf-candidates)))))
 
 ;;;###autoload
 (defun counsel-buffer-or-recentf ()

Reply via email to