bug-gnu-emacs
[Top][All Lists]
Advanced

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

I have a couple of fixes for elisp code.


From: Nathan Bullock
Subject: I have a couple of fixes for elisp code.
Date: Mon, 27 May 2002 08:49:55 -0600

GNU emacs maintainers:

Small bug, but very nasty for what I was trying to do, in files.el.
(I recently downloaded version 21.2 of emacs so I do have a current
version.)

Function: find-file-noselect{-1} is supposed to open a file, start up it's
major mode, and then return the buffer which the file resides. Problem
exists if the major mode kills the file (I realize that this isn't a common
situation but I have major modes which do this), then the function returns
some other buffer. This was very annoying until I tracked down the problem.
Anyway here is the fixed version:


;; This file is from files.el
(defun find-file-noselect-1 (buf filename nowarn rawfile truename number)
  (let ((inhibit-read-only t)
        error)
    (with-current-buffer buf
      (kill-local-variable 'find-file-literally)
      ;; Needed in case we are re-visiting the file with a different
      ;; text representation.
      (kill-local-variable 'buffer-file-coding-system)
      (erase-buffer)
      (and (default-value 'enable-multibyte-characters)
           (not rawfile)
           (set-buffer-multibyte t))
      (if rawfile
          (condition-case ()
              (insert-file-contents-literally filename t)
            (file-error
             (when (and (file-exists-p filename)
                        (not (file-readable-p filename)))
               (kill-buffer buf)
               (signal 'file-error (list "File is not readable"
                                         filename)))
             ;; Unconditionally set error
             (setq error t)))
        (condition-case ()
            (insert-file-contents filename t)
          (file-error
           (when (and (file-exists-p filename)
                      (not (file-readable-p filename)))
             (kill-buffer buf)
             (signal 'file-error (list "File is not readable"
                                       filename)))
           ;; Run find-file-not-found-hooks until one returns non-nil.
           (or (run-hook-with-args-until-success
'find-file-not-found-hooks)
               ;; If they fail too, set error.
               (setq error t)))))
      ;; Record the file's truename, and maybe use that as visited name.
      (if (equal filename buffer-file-name)
          (setq buffer-file-truename truename)
        (setq buffer-file-truename
              (abbreviate-file-name (file-truename buffer-file-name))))
      (setq buffer-file-number number)
      ;; On VMS, we may want to remember which directory in a search list
      ;; the file was found in.
      (and (eq system-type 'vax-vms)
           (let (logical)
             (if (string-match ":" (file-name-directory filename))
                 (setq logical (substring (file-name-directory filename)
                                          0 (match-beginning 0))))
             (not (member logical find-file-not-true-dirname-list)))
           (setq buffer-file-name buffer-file-truename))
      (if find-file-visit-truename
          (setq buffer-file-name
                (setq filename
                      (expand-file-name buffer-file-truename))))
      ;; Set buffer's default directory to that of the file.
      (setq default-directory (file-name-directory buffer-file-name))
      ;; Turn off backup files for certain file names.  Since
      ;; this is a permanent local, the major mode won't eliminate it.
      (and (not (funcall backup-enable-predicate buffer-file-name))
           (progn
             (make-local-variable 'backup-inhibited)
             (setq backup-inhibited t)))
;; NATHAN: need to remember which the current-buffer is since
;;  (after-find-file) could potentially see it get killed and
;;  we need to return it at the end of the function.
      (setq buf (current-buffer))
      (if rawfile
          (progn
            (set-buffer-multibyte nil)
            (setq buffer-file-coding-system 'no-conversion)
            (make-local-variable 'find-file-literally)
            (setq find-file-literally t))
        (after-find-file error (not nowarn)))
;; NATHAN: Return proper buffer, not just the current one.
      buf)))


I only changed two lines both preceded by a comment with the word NATHAN.

Second bug is in server.el, fixing previous problem allowed this one to
show up.

(defun server-visit-files (files client &optional nowait)
  "Finds FILES and returns the list CLIENT with the buffers nconc'd.
FILES is an alist whose elements are (FILENAME LINENUMBER COLUMNNUMBER).
NOWAIT non-nil means this client is not waiting for the results,
so don't mark these buffers specially, just visit them normally."
  ;; Bind last-nonmenu-event to force use of keyboard, not mouse, for
queries.
  (let (client-record live (last-nonmenu-event t) (obuf (current-buffer)))
    ;; Restore the current buffer afterward, but not using save-excursion,
    ;; because we don't want to save point in this buffer
    ;; if it happens to be one of those specified by the server.
    (unwind-protect
        (while files
          ;; If there is an existing buffer modified or the file is
          ;; modified, revert it.  If there is an existing buffer with
          ;; deleted file, offer to write it.
          (let* ((filen (car (car files)))
                 (obuf (get-file-buffer filen)))
            (push filen file-name-history)
            (if (and obuf (set-buffer obuf))
                (progn
                  (cond ((file-exists-p filen)
                         (if (or (not (verify-visited-file-modtime obuf))
                                 (buffer-modified-p obuf))
                             (revert-buffer t nil)))
                        (t
                         (if (y-or-n-p
                              (concat "File no longer exists: "
                                      filen
                                      ", write buffer to file? "))
                             (write-file filen))))
                  (setq server-existing-buffer t)
                  (goto-line (nth 1 (car files))))
              (setq obuf (find-file-noselect filen))
              (setq live (buffer-live-p obuf))
              (when live
                (set-buffer obuf)
                (goto-line (nth 1 (car files)))
                (let ((column-number (nth 2 (car files))))
                  (when (> column-number 0)
                    (move-to-column (1- column-number))))
                (run-hooks 'server-visit-hook)))
            (if (not nowait)
                (if live
                    (setq server-buffer-clients
                          (cons (car client) server-buffer-clients)))))
          (if live
              (setq client-record (cons (current-buffer) client-record)))
          (setq files (cdr files)))
      (set-buffer obuf))
    (nconc client client-record)))

This fix is much less clean, if you want the changed cleanly commented I
can do that. If you want the code cleaned up a bit I can probably do that
as well. The problem was that find-file-noselect was sometimes returning
buffers which no longer existed and then was later trying to make the
buffer active, which returned an error. Now when the buffer is dead it
doesn't append it to the client-record list.

Hope these are useful, please reply if so.

Nathan Bullock



reply via email to

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