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

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

clone buffer that is visiting a file


From: xraysmalevich
Subject: clone buffer that is visiting a file
Date: Thu, 4 Sep 2008 05:55:49 -0700 (PDT)
User-agent: G2/1.0

If you try to run clone-buffer on a file-visiting buffer, it won't
happen, and you get the error message "Cannot clone a file-visiting
buffer."

I think I understand why -- if you clone a file-visiting buffer, both
buffers are visiting the same file -- and this is more a situation for
an indirect buffer. Is this correct?

But what about situations where you want the entire text of the file-
visiting buffer, the same major mode, but not have it be visiting a
file? Is there any easier way to do this other than copying the entire
buffer and starting from scratch?

I poked around in the the internals of clone-buffer, and it seems to
be happy with copying file-visiting buffers if I turn off the file-
visiting checks AND disable copying local variables. Is this safe? Are
there any reason why I might NOT want to do this?

below is my modified clone-buffer code, with mooning internal
commentary on my suspicious changes:

(defun clone-this-buffer (&optional newname display-flag)
  "Create and return a twin copy of the current buffer.
Unlike an indirect buffer, the new buffer can be edited
independently of the old one (if it is not read-only).
NEWNAME is the name of the new buffer.  It may be modified by
adding or incrementing <N> at the end as necessary to create a
unique buffer name.  If nil, it defaults to the name of the
current buffer, with the proper suffix.  If DISPLAY-FLAG is
non-nil, the new buffer is shown with `pop-to-buffer'.  Trying to
clone a file-visiting buffer, results in a buffer not tied to a file.

hopefully.

Interactively, DISPLAY-FLAG is t and NEWNAME is the name of the
current buffer with appropriate suffix.  However, if a prefix
argument is given, then the command prompts for NEWNAME in the
minibuffer.

This runs the normal hook `clone-buffer-hook' in the new buffer
after it has been set up properly in other respects."
  (interactive
   (progn
     (if (get major-mode 'no-clone)
         (error "Cannot clone a buffer in %s mode" mode-name))
     (list (if current-prefix-arg
               (read-buffer "Name of new cloned buffer: " (current-buffer)))
           t)))
  (if (get major-mode 'no-clone)
      (error "Cannot clone a buffer in %s mode" mode-name))
  (setq newname (or newname (buffer-name)))
  (if (string-match "<[0-9]+>\\'" newname)
      (setq newname (substring newname 0 (match-beginning 0))))
  (let ((buf (current-buffer))
        (ptmin (point-min))
        (ptmax (point-max))
        (pt (point))
        (mk (if mark-active (mark t)))
        (modified (buffer-modified-p))
        (mode major-mode)
        (lvars (buffer-local-variables))
        (process (get-buffer-process (current-buffer)))
        (new (generate-new-buffer (or newname (buffer-name)))))
    (save-restriction
      (widen)
      (with-current-buffer new
        (insert-buffer-substring buf)))
    (with-current-buffer new
      (narrow-to-region ptmin ptmax)
      (goto-char pt)
      (if mk (set-mark mk))
      (set-buffer-modified-p modified)

      ;; Clone the old buffer's process, if any.
      ;; commented-out to avoid file-visiting issues
      ;; may not be related
      ;;(when process (clone-process process))

      ;; Now set up the major mode.
      (funcall mode)

      ;; Set up other local variables.
      ;;; NOT copying local-vars seems to kill the associations to a
visited file.
      ;; I think
      ;;       (mapc (lambda (v)
      ;;              (condition-case ()        ;in case var is read-only
      ;;                  (if (symbolp v)
      ;;                      (makunbound v)
      ;;                    (set (make-local-variable (car v)) (cdr v)))
      ;;                (error nil)))
      ;;            lvars)

      ;; Run any hooks (typically set up by the major mode
      ;; for cloning to work properly).
      (run-hooks 'clone-buffer-hook))
    (if display-flag
        ;; Presumably the current buffer is shown in the selected
frame, so
        ;; we want to display the clone elsewhere.
        (let ((same-window-regexps nil)
              (same-window-buffer-names))
          (pop-to-buffer new)))
    new))


--the Other michael


reply via email to

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