emacs-devel
[Top][All Lists]
Advanced

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

Re: Recent documents: Emacs and GNOME integration


From: Kevin Rodgers
Subject: Re: Recent documents: Emacs and GNOME integration
Date: Wed, 24 May 2006 12:52:25 -0600
User-agent: Thunderbird 1.5.0.2 (Windows/20060308)

Richard Stallman wrote:
If the structure of the recent files list is simple enough,
maybe it is easy to edit it correctly even without having the
sophistication to parse xml.  Would someone like to take a look
and try to write this?

I believe you are correct, but the spec is terribly imprecise:
there is no DTD or schema, no formal specification of the various
elements' content, numerous occurrences of "should", etc.  I sent
a message to the address@hidden mailing list asking for
clarification, but it never even showed up in the archive
(http://lists.freedesktop.org/archives/xdg/).

So here's what I came up with based on the example in the spec:

(provide 'recent-files)

;; See http://standards.freedesktop.org/recent-file-spec/recent-file-spec-0.2.html#storage
(defconst recent-files-encoding "UTF-8")
(defconst recent-files-name "~/.recently-used")
(defconst recent-files-limit 500)

(require 'url-util)
(require 'mailcap)

(defun update-recent-file (file &optional mime-type timestamp private
                                &rest groups)
  "Add or update FILE's entry in `recent-files-name'."
  (apply 'update-recent-file-item
         (concat "file://" (mapconcat 'url-hexify-string
                                      (split-string (expand-file-name file) "/")
                                      "/"))
         (or mime-type
             (cdr (assoc (file-name-extension file t) mailcap-mime-extensions)))
         (or timestamp
             (format "%.f" (float-time)))
         private
         groups))                       ; (cons "Emacs" groups)

(defun update-recent-file-item (uri mime-type timestamp
                                    &optional private &rest groups)
  ;; Replace "<", "&", and ">" by "&lt;", "&amp;", and "&gt;" resp.
  ;; in all string arguments (URI, MIME-TYPE, TIMESTAMP, and GROUPS)
  ;; but not the boolean argument (PRIVATE):
  (setq uri (url-insert-entities-in-string uri)
        mime-type (url-insert-entities-in-string mime-type)
        timestamp (url-insert-entities-in-string timestamp)
        groups (mapcar 'url-insert-entities-in-string groups))
  ;; Make sure recent-file is opened and saved in the correct encoding:
  (let* ((coding-system-for-read (intern (downcase recent-files-encoding)))
         (coding-system-for-write coding-system-for-read)
         (coding-system-require-warning t)
         (recent-buffer (get-file-buffer recent-files-name)))
    (save-excursion
(set-buffer (or recent-buffer (find-file-noselect recent-files-name)))
      (save-restriction
        (widen)
        (when (= (buffer-size) 0)
          (goto-char (point-min))
          (insert "<?xml version=\"1.0\" encoding=\""
                  recent-files-encoding
                  "\"?>")
          (insert "\n" "<RecentFiles>")
          (insert "\n" "</RecentFiles>"))
        (goto-char (point-min))
        (if (search-forward-regexp (concat "<URI>" (regexp-quote uri) "</URI>")
                                   nil t)
            ;; then: Per the spec, only update the timestamp and add new groups:
            (progn
              (search-forward-regexp "<Timestamp>\\(.*\\)</Timestamp>")
              (replace-match timestamp t t nil 1)
              (goto-char (match-end 0)) ; end-of-line
              (when groups
                (let (group-start group-end)
                  (if (looking-at "\n*<Groups>")
                      (progn
                        (setq group-start (match-end 0))
                        (setq group-end (search-forward-regexp "</Groups>")))
                    (insert "\n" "<Groups>")
                    (setq group-start (point))
                    (insert "\n" "</Groups>")
                    (setq group-end (point-marker)))
                  (goto-char group-start)
                  (mapc (lambda (group)
                          (unless (save-excursion
                                    (search-forward-regexp
                                     (concat "<Group>"
                                             (regexp-quote group)
                                             "</Group>")
                                     nil group-end))
                            (insert "\n" "<Group>" group "</Group>")))
                        groups))))
          ;; else: Insert the new item:
          (search-forward "</RecentFiles>")
          (goto-char (match-beginning 0))
          (insert "<RecentItem>")
          (insert "\n" "<URI>" uri "</URI>"
                  "\n" "<Mime-Type>" mime-type "</Mime-Type>"
                  "\n" "<Timestamp>" timestamp "</Timestamp>")
          (when groups
            (insert "\n" "<Groups>")
            (mapc (lambda (group)
                    (insert "\n" "<Group>" group "</Group>"))
                  groups)
            (insert "\n" "</Groups>"))
          (when private
            (insert "\n" "<Private/>"))
          (insert "\n" "</RecentItem>" "\n"))
        (save-buffer))
      (or recent-buffer (kill-buffer (current-buffer))))))

--
Kevin





reply via email to

[Prev in Thread] Current Thread [Next in Thread]