(require 'cl) ;; for `copy-list'
(let* ((frame-list (frame-list))
(current-frame (selected-frame))
(result
(delq nil
(mapcar
(lambda (frame)
(with-selected-frame frame
(when (one-window-p)
(with-current-buffer (car (buffer-list frame))
(if (and buffer-file-name (file-exists-p buffer-file-name))
(list frame buffer-file-name))))))
frame-list)))
(destructable-result (copy-list result)))
(mapc
(lambda (x)
(setq destructable-result (delq x destructable-result))
(mapc
(lambda (y)
(when (equal (cdr x) (cdr y))
(if (eq (car x) current-frame)
(when (frame-live-p (car y))
(delete-frame (car y))
(setq destructable-result (delq y destructable-result)))
(when (frame-live-p (car x))
(delete-frame (car x))))))
destructable-result))
result))
SHOW YOUR WORK: One of the concerns @lawlist had while creating the above-mentioned solution was whether altering destructable-result
during an ongoing mapc
loop that uses the previous value for SEQUENCE
(i.e., prior to its altercation) would throw an error. The following example demonstrates that this is a non-issue.
(let ((my-list '(0 1 2 3 4 5 6 7 8 9)))
(mapc
(lambda (x)
(when my-list
(setq my-list nil))
(message "x: %s | my-list: %s" x my-list))
my-list))
duplicate
? The lisp object is different.delete-frame
will delete a frame. The following snippet demonstrates that the frames are not the same:(let ((a (make-frame)) (b (make-frame))) (message "a: %s | b: %s | eq?: %s" a b (eq a b)))
delete-frame
has two optional arguments: FRAME and FORCE. The prior must be a lisp object. Drew has a nice library to help identify/manage frames that have a specific name, and you may enjoy naming them and dealing with specially named frames to help see the difference and for organizational purposes: emacswiki.org/emacs/frame-fns.el E.g., a frame for email, a frame for org, a frame for calendar, a frame for documents, etc. You can associate buffers with frames to have frame-local buffer association with Alp Aker'sframe-bufs
library.clone
or something else. If I modify one of them, the other one is also modified. Please do not hesitate to suggest the correct term.delete-frame
, and then you will need to choose which frame should be deleted -- e.g., either the frame that has focus and do not use the optional argument FRAME, or keep the selected frame that has focus and delete the other frame using the the optional argument for FRAME and pass it the appropriate lisp object as the argument.(let ((a (make-frame '((name . "TODAY")))) (b (make-frame '((name . "TOMORROW"))))) (message "a: %s | b: %s | eq?: %s" a b (eq a b)))
The top of the frame will display the special name assigned to each frame. Each frame might display the same buffers, and each frame might display the same window layout -- however, each frame is different and can display any buffer and have any window layout -- they can even have differentdefault
faces and the list goes on.