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: Fri, 26 May 2006 12:54:28 -0600
User-agent: Thunderbird 1.5.0.2 (Windows/20060308)

Bill Wohler wrote:
> Richard Stallman <address@hidden> writes:
>> Would people please try it and report if it works?
>
> Sort of, with the following modifications (patch for some appended):
>
> 1. Add find-file-hook (so it will be called). However, do we want to
>    add `update-recent-file' to the hook, or just call it from
>    `basic-save-file' directly?

I think the user should decide whether to take advantage of this
feature, by explicitly calling add-hook in ~/.emacs with find-file-hook
(and perhaps find-file-not-found-functions).

> 2. Don't add the ~/.recently-used file to the list unless the user
>    opened it. The file should be invisible to the user.

Good point!

> 3. Indent the XML to match the existing style of the file.

Your patch doesn't match the existing style, it assumes that each
subelement is indented 4 spaces.  I think the right way to do this would
be to call an indentation function, but do you really think it's worth
changing every occurrence of (insert "\n" "<Foo>") to

(newline-and-indent)
(insert "<Foo>")

> I didn't give much thought to the new names, so please review to check
> for consistency and collisions.

I changed the updating-recent-file variable to match the name of the
function it controls (update-recent-file), and I changed the
add-file-to-recent function to find-file-update-recent-file.

I suppose everything should have a recent-files- prefix, though.

> In addition, the following also has to be done, but I was not readily
> able to do so.
>
> 4. Suppress the "Wrote /home/wohler/.recently-used" message that
>    appears every time you visit a file.

I don't think that message can be prevented, but perhaps the echo area
could be restored after ~/.recently-used is saved.  Does anyone know how
to do that?  Or will a simple (message "") call to clear it suffice?

> 5. Don't add backup files to the list.

That's easy with backup-file-name-p, so I've added that, plus a check
for auto-save files as well.

> The `private' and `groups' parameters aren't used by my hook.
> Shouldn't `update-recent-file' at least set groups to "Emacs" if it
> isn't given?

I've added user options to control that, with defaults to specify both.

Please give the attached version a try.  Thanks,
--
Kevin

(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)

(defvar update-recent-file t)

(defun update-recent-file (file &optional mime-type timestamp private groups)
  "Add or update FILE's entry in `recent-files-name'."
  (when update-recent-file
    (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))
         "application/octet-stream")
     (or timestamp
         (format "%.f" (float-time)))
     private
     groups)))

(defun update-recent-file-item (uri mime-type timestamp
                                    &optional private groups)
  ;; Replace "<", "&", and ">" by "&lt;", "&amp;", and "&gt;" resp.
  ;; in all string arguments (PRIVATE is boolean):
  (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-files-name 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
                      ;; Avoid adding `recent-files-name' to itself:
                      (let ((update-recent-file nil))
                        (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)
            ;; 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 "</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))))))

(defvar find-file-recent-files-private t
  "If set, specify the \"<Private/>\" tag when adding visited files to \
`recent-files-name'.")

(defvar find-file-recent-files-groups '("Emacs")
  "List of group names to add when updating visited files in \
`recent-files-name'.")

(defun find-file-update-recent-file ()
  "Add the visited file to `recent-files-name'.
This function is designed to be added to `find-file-hook' and/or
`find-file-not-found-functions'."
  (unless (or (null buffer-file-name)
              (backup-file-name-p buffer-file-name)
              (auto-save-file-name-p (file-name-nondirectory
                                      buffer-file-name)))
    (update-recent-file buffer-file-name nil nil
                        find-file-recent-files-private
                        find-file-recent-files-groups)))

;; (add-hook 'find-file-hook 'find-file-update-recent-file)
;; (add-hook 'find-file-not-found-functions 'find-file-update-recent-file)

reply via email to

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