[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: Buffer listing in multiple frames/ttys
From: |
Károly Lőrentey |
Subject: |
Re: Buffer listing in multiple frames/ttys |
Date: |
Wed, 07 Dec 2005 15:51:14 +0100 |
User-agent: |
Gnus/5.110004 (No Gnus v0.4) Emacs/22.0.52 (gnu/linux) |
Juri Linkov <address@hidden> writes:
>> I note that `bury-buffer' removes the buffer from the frame-local
>> buffer lists of all frames, not just the selected one. This is an
>> unwanted side-effect in this case, as we want the effects of
>> `next-buffer' to remain frame-local. I propose to add an optional
>> parameter to `bury-buffer' to support this.
>
> I think this change should be made for all invocations of
> `bury-buffer', not only from `next-buffer'. [...] And so there is no
> need for a new optional parameter.
That's fine by me.
> Also I think recoding a buffer to the new frame parameter should be
> made in `bury-buffer' instead of `next-buffer'. Some commands call
> `bury-buffer'
> directly, and it would be good to record their buffers in the
> frame-local parameter.
Ah, good idea. I implemented this in the patch at the end of this
message. It involves adding a new element to the frame struct, and
changing switch-to-buffer, bury-buffer and kill-buffer etc. to
maintain the list.
> Instead of introducing a new frame parameter `previous-buffer-list'
> what do you think about reusing the existing frame parameter `buffer-list'?
> It could have a special marker delimiting a list of frame's "next" visited
> buffers and "previous" visited buffers. A nil value could serve as
> such special marker. So for example, (frame-parameter nil 'buffer-list)
> could contain:
>
> (#<buffer *b+1*> #<buffer *b+2*> nil #<buffer *b-2*> #<buffer *b-1*>)
I thought of this as well, but it would be an incompatible change that
is not strictly necessary. The 'buffer-list frame parameter has been
in Emacs since (I think) 1997; some external packages may rely on its
current contents. Also, using a special marker seems a bit less clean
to me than using a separate parameter. (It is also less efficient.)
The below patch also renames `prev-buffer' to `previous-buffer', and
extends it to support the buffer-predicate frame parameter. It
incorporates all fixes that have been suggested in this thread, except
for the customization option for disabling frame-local behaviour.
(`other-buffer' has been unconditionally using the frame-local buffer
list for years; I don't see a point in making it configurable for
next-buffer/previous-buffer either.)
If there are no objections, I will document the changes and install
them in CVS.
Index: lisp/bindings.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/bindings.el,v
retrieving revision 1.154
diff -u -3 -p -r1.154 bindings.el
*** lisp/bindings.el 28 Oct 2005 16:19:16 -0000 1.154
--- lisp/bindings.el 7 Dec 2005 14:46:48 -0000
***************
*** 338,364 ****
(defvar mode-line-buffer-identification-keymap nil "\
Keymap for what is displayed by `mode-line-buffer-identification'.")
! (defun last-buffer () "\
! Return the last non-hidden buffer in the buffer list."
! ;; This logic is more or less copied from bury-buffer,
! ;; except that we reverse the buffer list.
! (let ((list (nreverse (buffer-list (selected-frame))))
! (pred (frame-parameter nil 'buffer-predicate))
! found notsogood)
! (while (and list (not found))
! (unless (or (eq (aref (buffer-name (car list)) 0) ? )
! ;; If the selected frame has a buffer_predicate,
! ;; disregard buffers that don't fit the predicate.
! (and pred (not (funcall pred (car list)))))
! (if (get-buffer-window (car list) 'visible)
! (or notsogood (eq (car list) (current-buffer)))
! (setq found (car list))))
! (pop list))
! (or found notsogood
! (get-buffer "*scratch*")
(progn
! (set-buffer-major-mode
! (get-buffer-create "*scratch*"))
(get-buffer "*scratch*")))))
(defun unbury-buffer () "\
--- 338,372 ----
(defvar mode-line-buffer-identification-keymap nil "\
Keymap for what is displayed by `mode-line-buffer-identification'.")
! (defun last-buffer (&optional buffer visible-ok frame) "\
! Return the last non-hidden buffer in the buffer list.
! If BUFFER is non-nil, last-buffer will ignore that buffer.
! Buffers not visible in windows are preferred to visible buffers,
! unless optional argument VISIBLE-OK is non-nil.
! If the optional third argument FRAME is non-nil, use that frame's
! buffer list instead of the selected frame's buffer list.
! If no other buffer exists, the buffer `*scratch*' is returned."
! (setq frame (or frame (selected-frame)))
! ;; This logic is more or less copied from other-buffer.
! (let ((search-list
! #'(lambda (list)
! "Search LIST for a valid buffer to display."
! (let ((pred (frame-parameter frame 'buffer-predicate))
! found buf)
! (while (and (not found) list)
! (setq buf (car list))
! (if (and (not (eq buffer buf))
! (buffer-live-p buf)
! (or (null pred) (funcall pred buf))
! (not (eq (aref (buffer-name buf) 0) ?\s))
! (or visible-ok (null (get-buffer-window buf
'visible))))
! (setq found buf)
! (setq list (cdr list))))
! list))))
! (or (car (funcall search-list (frame-parameter frame
'buried-buffer-list)))
! (car (funcall search-list (nreverse (buffer-list frame))))
(progn
! (set-buffer-major-mode (get-buffer-create "*scratch*"))
(get-buffer "*scratch*")))))
(defun unbury-buffer () "\
***************
*** 673,680 ****
(define-key global-map [?\C-x right] 'next-buffer)
(define-key global-map [?\C-x C-right] 'next-buffer)
! (define-key global-map [?\C-x left] 'prev-buffer)
! (define-key global-map [?\C-x C-left] 'prev-buffer)
(let ((map minibuffer-local-map))
(define-key map "\en" 'next-history-element)
--- 681,688 ----
(define-key global-map [?\C-x right] 'next-buffer)
(define-key global-map [?\C-x C-right] 'next-buffer)
! (define-key global-map [?\C-x left] 'previous-buffer)
! (define-key global-map [?\C-x C-left] 'previous-buffer)
(let ((map minibuffer-local-map))
(define-key map "\en" 'next-history-element)
Index: lisp/menu-bar.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/menu-bar.el,v
retrieving revision 1.282
diff -u -3 -p -r1.282 menu-bar.el
*** lisp/menu-bar.el 19 Nov 2005 11:23:04 -0000 1.282
--- lisp/menu-bar.el 7 Dec 2005 14:46:48 -0000
***************
*** 1662,1671 ****
"Next Buffer"
'next-buffer
:help "Switch to the \"next\" buffer in a cyclic
order")
! (list 'prev-buffer
'menu-item
"Previous Buffer"
! 'prev-buffer
:help "Switch to the \"previous\" buffer in a
cyclic order")
(list 'select-named-buffer
'menu-item
--- 1662,1671 ----
"Next Buffer"
'next-buffer
:help "Switch to the \"next\" buffer in a cyclic
order")
! (list 'previous-buffer
'menu-item
"Previous Buffer"
! 'previous-buffer
:help "Switch to the \"previous\" buffer in a
cyclic order")
(list 'select-named-buffer
'menu-item
Index: lisp/simple.el
===================================================================
RCS file: /cvsroot/emacs/emacs/lisp/simple.el,v
retrieving revision 1.777
diff -u -3 -p -r1.777 simple.el
*** lisp/simple.el 4 Dec 2005 02:42:29 -0000 1.777
--- lisp/simple.el 7 Dec 2005 14:46:48 -0000
***************
*** 56,76 ****
"Switch to the next buffer in cyclic order."
(interactive)
(let ((buffer (current-buffer)))
! (switch-to-buffer (other-buffer buffer))
(bury-buffer buffer)))
! (defun prev-buffer ()
"Switch to the previous buffer in cyclic order."
(interactive)
! (let ((list (nreverse (buffer-list)))
! found)
! (while (and (not found) list)
! (let ((buffer (car list)))
! (if (and (not (get-buffer-window buffer))
! (not (string-match "\\` " (buffer-name buffer))))
! (setq found buffer)))
! (setq list (cdr list)))
! (switch-to-buffer found)))
;;; next-error support framework
--- 56,69 ----
"Switch to the next buffer in cyclic order."
(interactive)
(let ((buffer (current-buffer)))
! (switch-to-buffer (other-buffer buffer t))
(bury-buffer buffer)))
! (defun previous-buffer ()
"Switch to the previous buffer in cyclic order."
(interactive)
! (switch-to-buffer (last-buffer (current-buffer) t)))
!
;;; next-error support framework
Index: src/alloc.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/alloc.c,v
retrieving revision 1.384
diff -u -3 -p -r1.384 alloc.c
*** src/alloc.c 30 Nov 2005 00:04:51 -0000 1.384
--- src/alloc.c 7 Dec 2005 14:46:48 -0000
***************
*** 5370,5375 ****
--- 5370,5376 ----
mark_object (ptr->menu_bar_vector);
mark_object (ptr->buffer_predicate);
mark_object (ptr->buffer_list);
+ mark_object (ptr->buried_buffer_list);
mark_object (ptr->menu_bar_window);
mark_object (ptr->tool_bar_window);
mark_face_cache (ptr->face_cache);
Index: src/buffer.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/buffer.c,v
retrieving revision 1.496
diff -u -3 -p -r1.496 buffer.c
*** src/buffer.c 6 Dec 2005 07:37:47 -0000 1.496
--- src/buffer.c 7 Dec 2005 14:46:48 -0000
***************
*** 212,236 ****
(frame)
Lisp_Object frame;
{
! Lisp_Object framelist, general;
general = Fmapcar (Qcdr, Vbuffer_alist);
if (FRAMEP (frame))
{
! Lisp_Object tail;
CHECK_FRAME (frame);
framelist = Fcopy_sequence (XFRAME (frame)->buffer_list);
! /* Remove from GENERAL any buffer that duplicates one in FRAMELIST. */
tail = framelist;
! while (! NILP (tail))
{
general = Fdelq (XCAR (tail), general);
tail = XCDR (tail);
}
! return nconc2 (framelist, general);
}
return general;
--- 212,249 ----
(frame)
Lisp_Object frame;
{
! Lisp_Object general;
general = Fmapcar (Qcdr, Vbuffer_alist);
if (FRAMEP (frame))
{
! Lisp_Object framelist, prevlist, tail;
! Lisp_Object args[3];
CHECK_FRAME (frame);
framelist = Fcopy_sequence (XFRAME (frame)->buffer_list);
+ prevlist = Fcopy_sequence (XFRAME (frame)->buried_buffer_list);
! /* Remove from GENERAL any buffer that duplicates one in
! FRAMELIST or PREVLIST. */
tail = framelist;
! while (CONSP (tail))
{
general = Fdelq (XCAR (tail), general);
tail = XCDR (tail);
}
! tail = prevlist;
! while (CONSP (tail))
! {
! general = Fdelq (XCAR (tail), general);
! tail = XCDR (tail);
! }
!
! args[0] = framelist;
! args[1] = general;
! args[2] = prevlist;
! return Fnconc (3, args);
}
return general;
***************
*** 1545,1550 ****
--- 1558,1580 ----
XSETCDR (link, Vbuffer_alist);
Vbuffer_alist = link;
+ /* Effectively do a delq on buried_buffer_list. */
+
+ prev = Qnil;
+ for (link = XFRAME (frame)->buried_buffer_list; CONSP (link);
+ link = XCDR (link))
+ {
+ if (EQ (XCAR (link), buf))
+ {
+ if (NILP (prev))
+ XFRAME (frame)->buried_buffer_list = XCDR (link);
+ else
+ XSETCDR (prev, XCDR (XCDR (prev)));
+ break;
+ }
+ prev = link;
+ }
+
/* Now move this buffer to the front of frame_buffer_list also. */
prev = Qnil;
***************
*** 2016,2025 ****
XSETCDR (link, Qnil);
Vbuffer_alist = nconc2 (Vbuffer_alist, link);
! /* Removing BUFFER from frame-specific lists
! has the effect of putting BUFFER at the end
! of the combined list in each frame. */
! frames_discard_buffer (buffer);
}
return Qnil;
--- 2046,2055 ----
XSETCDR (link, Qnil);
Vbuffer_alist = nconc2 (Vbuffer_alist, link);
! XFRAME (selected_frame)->buffer_list
! = Fdelq (buffer, XFRAME (selected_frame)->buffer_list);
! XFRAME (selected_frame)->buried_buffer_list
! = Fcons (buffer, XFRAME (selected_frame)->buried_buffer_list);
}
return Qnil;
Index: src/frame.c
===================================================================
RCS file: /cvsroot/emacs/emacs/src/frame.c,v
retrieving revision 1.322
diff -u -3 -p -r1.322 frame.c
*** src/frame.c 10 Oct 2005 14:52:50 -0000 1.322
--- src/frame.c 7 Dec 2005 14:46:48 -0000
***************
*** 104,110 ****
Lisp_Object Qunsplittable;
Lisp_Object Qmenu_bar_lines, Qtool_bar_lines;
Lisp_Object Qleft_fringe, Qright_fringe;
! Lisp_Object Qbuffer_predicate, Qbuffer_list;
Lisp_Object Qtty_color_mode;
Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
--- 104,110 ----
Lisp_Object Qunsplittable;
Lisp_Object Qmenu_bar_lines, Qtool_bar_lines;
Lisp_Object Qleft_fringe, Qright_fringe;
! Lisp_Object Qbuffer_predicate, Qbuffer_list, Qburied_buffer_list;
Lisp_Object Qtty_color_mode;
Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth;
***************
*** 276,281 ****
--- 276,282 ----
f->menu_bar_items_used = 0;
f->buffer_predicate = Qnil;
f->buffer_list = Qnil;
+ f->buried_buffer_list = Qnil;
#ifdef MULTI_KBOARD
f->kboard = initial_kboard;
#endif
***************
*** 1900,1906 ****
XFRAME (frame)->buffer_list = list;
}
! /* Discard BUFFER from the buffer-list of each frame. */
void
frames_discard_buffer (buffer)
--- 1901,1907 ----
XFRAME (frame)->buffer_list = list;
}
! /* Discard BUFFER from the buffer-list and buried-buffer-list of each frame.
*/
void
frames_discard_buffer (buffer)
***************
*** 1912,1917 ****
--- 1913,1920 ----
{
XFRAME (frame)->buffer_list
= Fdelq (buffer, XFRAME (frame)->buffer_list);
+ XFRAME (frame)->buried_buffer_list
+ = Fdelq (buffer, XFRAME (frame)->buried_buffer_list);
}
}
***************
*** 1999,2011 ****
{
register Lisp_Object old_alist_elt;
! /* The buffer-alist parameter is stored in a special place and is
! not in the alist. */
if (EQ (prop, Qbuffer_list))
{
f->buffer_list = val;
return;
}
/* If PROP is a symbol which is supposed to have frame-local values,
and it is set up based on this frame, switch to the global
--- 2002,2019 ----
{
register Lisp_Object old_alist_elt;
! /* The buffer-list parameters are stored in a special place and not
! in the alist. */
if (EQ (prop, Qbuffer_list))
{
f->buffer_list = val;
return;
}
+ if (EQ (prop, Qburied_buffer_list))
+ {
+ f->buried_buffer_list = val;
+ return;
+ }
/* If PROP is a symbol which is supposed to have frame-local values,
and it is set up based on this frame, switch to the global
***************
*** 2145,2150 ****
--- 2153,2159 ----
: FRAME_MINIBUF_WINDOW (f)));
store_in_alist (&alist, Qunsplittable, (FRAME_NO_SPLIT_P (f) ? Qt : Qnil));
store_in_alist (&alist, Qbuffer_list, frame_buffer_list (frame));
+ store_in_alist (&alist, Qburied_buffer_list, XFRAME
(frame)->buried_buffer_list);
/* I think this should be done with a hook. */
#ifdef HAVE_WINDOW_SYSTEM
***************
*** 3965,3970 ****
--- 3974,3981 ----
staticpro (&Qbuffer_predicate);
Qbuffer_list = intern ("buffer-list");
staticpro (&Qbuffer_list);
+ Qburied_buffer_list = intern ("buried-buffer-list");
+ staticpro (&Qburied_buffer_list);
Qdisplay_type = intern ("display-type");
staticpro (&Qdisplay_type);
Qbackground_mode = intern ("background-mode");
Index: src/frame.h
===================================================================
RCS file: /cvsroot/emacs/emacs/src/frame.h,v
retrieving revision 1.112
diff -u -3 -p -r1.112 frame.h
*** src/frame.h 8 Sep 2005 22:30:08 -0000 1.112
--- src/frame.h 7 Dec 2005 14:46:48 -0000
***************
*** 182,187 ****
--- 182,191 ----
/* List of buffers viewed in this frame, for other-buffer. */
Lisp_Object buffer_list;
+ /* List of buffers that were viewed, then buried in this frame. The
+ most recently buried buffer is first. For previous-buffer. */
+ Lisp_Object buried_buffer_list;
+
/* A dummy window used to display menu bars under X when no X
toolkit support is available. */
Lisp_Object menu_bar_window;
***************
*** 994,1000 ****
extern Lisp_Object Qauto_raise, Qauto_lower;
extern Lisp_Object Qborder_color, Qborder_width;
! extern Lisp_Object Qbuffer_predicate, Qbuffer_list;
extern Lisp_Object Qcursor_color, Qcursor_type;
extern Lisp_Object Qfont;
extern Lisp_Object Qbackground_color, Qforeground_color;
--- 998,1004 ----
extern Lisp_Object Qauto_raise, Qauto_lower;
extern Lisp_Object Qborder_color, Qborder_width;
! extern Lisp_Object Qbuffer_predicate, Qbuffer_list, Qburied_buffer_list;
extern Lisp_Object Qcursor_color, Qcursor_type;
extern Lisp_Object Qfont;
extern Lisp_Object Qbackground_color, Qforeground_color;
--
Károly
pgp2TwRPmkyRq.pgp
Description: PGP signature
- Re: Buffer listing in multiple frames/ttys, (continued)
- Re: Buffer listing in multiple frames/ttys, Richard M. Stallman, 2005/12/05
- Re: Buffer listing in multiple frames/ttys, Károly Lőrentey, 2005/12/05
- Re: Buffer listing in multiple frames/ttys, Juri Linkov, 2005/12/05
- Re: Buffer listing in multiple frames/ttys, Richard M. Stallman, 2005/12/06
- Re: Buffer listing in multiple frames/ttys, Richard M. Stallman, 2005/12/05
- Re: Buffer listing in multiple frames/ttys, Károly Lőrentey, 2005/12/06
- Re: Buffer listing in multiple frames/ttys, Juri Linkov, 2005/12/06
- Re: Buffer listing in multiple frames/ttys,
Károly Lőrentey <=
- Re: Buffer listing in multiple frames/ttys, Juri Linkov, 2005/12/07
- Re: Buffer listing in multiple frames/ttys, Juri Linkov, 2005/12/08
- Re: Buffer listing in multiple frames/ttys, Lőrentey Károly, 2005/12/08
- Re: Buffer listing in multiple frames/ttys, Richard M. Stallman, 2005/12/08
- Re: Buffer listing in multiple frames/ttys, Juri Linkov, 2005/12/08
- Re: Buffer listing in multiple frames/ttys, Richard M. Stallman, 2005/12/09
- Re: Buffer listing in multiple frames/ttys, Lőrentey Károly, 2005/12/09
- Re: Buffer listing in multiple frames/ttys, Juri Linkov, 2005/12/09
- Re: Buffer listing in multiple frames/ttys, Richard M. Stallman, 2005/12/10
- Re: Buffer listing in multiple frames/ttys, Juri Linkov, 2005/12/10