unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [PATCH] Window-groups
@ 2008-06-22 19:07 joakim
  2008-06-23 14:14 ` Richard M Stallman
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: joakim @ 2008-06-22 19:07 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 554 bytes --]

Heres a patch to implement Window-groups in Emacs, which I submit for
review.  Theres comments in the patch to explain what Window-groups are
in practice. In brief, the aim is to create Emacs primitives useful to ECB
like frameworks. 

The code builds on top of the already comitted window-properties code.
The patch has C level changes and an elisp interface.

To understand the design rationale, please read previous rather
long-winded window group threads. The patch is a joint effort between
me, Stefan Monnier, Chong Yidong, and Martin Rudalics.




[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: emacs-winprop.diff --]
[-- Type: text/x-patch, Size: 8389 bytes --]

=== modified file 'lisp/window.el'
--- lisp/window.el	2008-06-17 22:33:06 +0000
+++ lisp/window.el	2008-06-22 12:25:44 +0000
@@ -1625,5 +1625,77 @@
 (define-key ctl-x-map "+" 'balance-windows)
 (define-key ctl-x-4-map "0" 'kill-buffer-and-window)
 
+
+;; Below are functions for managing window-groups.  Window
+;; groups allow windows in a frame a degree of separation from other
+;; windows in the same frame, similar to the way windows in different
+;; frames are separated from each other.
+
+;; Here's some examples.
+
+;; Make a new frame and split it vertically:
+;;    (split-window-horizontally)
+;; Call the left side the  "Context Area" and the left one the "Edit Area".
+;; Now make the "Context Area" into a group:
+;;    (window-group-create (selected-window))
+;; Theres actually two groups now, the "Context Area" and the default "Edit Area".
+;; Now try "c-x o". Notice that you dont go to the "Edit Area".
+;; Now try splitting the "Context Area" with "c-x 2", and switch buffers a bit 
+;; Now try removing windows with "c-x 0". Notice that only windows in the
+;; current group are affected.
+;; To return the state as it was:
+;;    (window-group-dissolve (window-group (selected-window)))
+
+
+(defun window-group (window)
+  "Return the window group object that WINDOW belongs to.
+Return nil if WINDOW is not in a window group."
+  (window-parameter window 'group))
+
+(defun window-group-member-p (window group)
+  "Non nil if WINDOW is a member of GROUP."
+  (eq group (window-group window)))
+
+(defun window-group-members (group)
+  "Return all windows in GROUP.
+Must be in selected frame."
+  (let ((group-windows ()))
+    (walk-windows
+     (lambda (w)
+       (when (window-group-member-p w group )
+         (push w group-windows))))
+    group-windows))
+
+(defvar window-group--counter 0
+  "An internal variable to keep track of window groups.")
+
+(defun window-group-create (window)
+  "Return a window group object with WINDOW as its only member.
+An error is signalled if WINDOW is not visible or already part of
+a group."
+  (if (window-group window)
+      (error "Window %s is already part of group %s"
+             ;;TODO check that the resulting error is not nonsensical
+             window (window-group window)))
+  ;;TODO we should now test for window visibility
+  (setq window-group--counter (1+ window-group--counter))
+  (let* ((name (concat "group-" (number-to-string window-group--counter)))
+         (group (make-symbol name)))
+    (set-window-parameter window 'group group)
+    group))
+
+(defun window-group-dissolve (group)
+  "Dissolve the window group object GROUP.
+The windows in the group are not deleted."
+  (let ((group-windows (window-group-members group)))
+    (if (null group-windows)
+        (error "No group %s on current frame" group)
+      ;;TODO I think the group id is not suitable for printing!
+      (dolist (win group-windows)
+        (set-window-parameter win 'group nil)))))
+
+(provide 'window-group)
+
+
 ;; arch-tag: b508dfcc-c353-4c37-89fa-e773fe10cea9
 ;;; window.el ends here

=== modified file 'src/window.c'
--- src/window.c	2008-06-10 22:08:42 +0000
+++ src/window.c	2008-06-19 13:25:41 +0000
@@ -54,6 +54,7 @@
 Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
 Lisp_Object Qdisplay_buffer;
 Lisp_Object Qscroll_up, Qscroll_down;
+Lisp_Object Qgroup;
 Lisp_Object Qwindow_size_fixed;
 
 extern Lisp_Object Qleft_margin, Qright_margin;
@@ -82,7 +83,8 @@
 					 Lisp_Object *));
 static int foreach_window_1 P_ ((struct window *,
 				 int (* fn) (struct window *, void *),
-				 void *));
+				 void *,
+                                 int));
 static Lisp_Object window_list_1 P_ ((Lisp_Object, Lisp_Object, Lisp_Object));
 
 /* This is the window in which the terminal's cursor should
@@ -1041,7 +1043,7 @@
 
   window = Qnil;
   cw.window = &window, cw.x = &x, cw.y = &y; cw.part = part;
-  foreach_window (f, check_window_containing, &cw);
+  foreach_window (f, check_window_containing, &cw, 1);
 
   /* If not found above, see if it's in the tool bar window, if a tool
      bar exists.  */
@@ -1733,7 +1735,8 @@
 static Lisp_Object
 window_list ()
 {
-  if (!CONSP (Vwindow_list))
+  //if(!CONSP (Vwindow_list))
+  if (1) //never cache the window list for now FIXME
     {
       Lisp_Object tail;
 
@@ -1746,7 +1749,7 @@
 	     new windows at the front of args[1], which means we
 	     have to reverse this list at the end.  */
 	  args[1] = Qnil;
-	  foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1]);
+	  foreach_window (XFRAME (XCAR (tail)), add_window_to_list, &args[1], 0);
 	  args[0] = Vwindow_list;
 	  args[1] = Fnreverse (args[1]);
 	  Vwindow_list = Fnconc (2, args);
@@ -2213,7 +2216,7 @@
 	    break;
 
 	  case DELETE_OTHER_WINDOWS:
-	    if (!EQ (window, obj))
+            if (!EQ (window, obj) )
 	      Fdelete_window (window);
 	    break;
 
@@ -3882,6 +3885,12 @@
   adjust_glyphs (fo);
 
   Fset_window_buffer (new, o->buffer, Qt);
+  /* make the new window inherit group properties.  We
+     inherit only those atm, because its not obvious that all
+     properties should be inherited
+   */
+  if(!NILP(Fwindow_parameter(window, Qgroup)))
+    Fset_window_parameter(new, Qgroup, Fwindow_parameter(window, Qgroup));
   return new;
 }
 \f
@@ -6826,17 +6835,20 @@
 \f
 /* Call FN for all leaf windows on frame F.  FN is called with the
    first argument being a pointer to the leaf window, and with
-   additional argument USER_DATA.  Stops when FN returns 0.  */
+   additional argument USER_DATA.  Stops when FN returns 0.
+   ALLWINDOWS 1 means iterate every window, else only the group of the selected window
+*/
 
 void
-foreach_window (f, fn, user_data)
+foreach_window (f, fn, user_data, allwindows)
      struct frame *f;
      int (* fn) P_ ((struct window *, void *));
      void *user_data;
+     int allwindows;
 {
   /* Fdelete_frame may set FRAME_ROOT_WINDOW (f) to Qnil.  */
   if (WINDOWP (FRAME_ROOT_WINDOW (f)))
-    foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data);
+    foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data,allwindows);
 }
 
 
@@ -6846,22 +6858,31 @@
    Stop when FN returns 0.  Value is 0 if stopped by FN.  */
 
 static int
-foreach_window_1 (w, fn, user_data)
+foreach_window_1 (w, fn, user_data, allwindows)
      struct window *w;
      int (* fn) P_ ((struct window *, void *));
      void *user_data;
+     int allwindows;
 {
   int cont;
-
+  struct window *current_window=XWINDOW(selected_window);
+  register Lisp_Object group = Fcdr(Fassq(Qgroup, current_window->window_parameters));
+  Lisp_Object group2;
   for (cont = 1; w && cont;)
     {
       if (!NILP (w->hchild))
- 	cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data);
+ 	cont = foreach_window_1 (XWINDOW (w->hchild), fn, user_data,allwindows);
       else if (!NILP (w->vchild))
- 	cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data);
-      else
-	cont = fn (w, user_data);
-
+ 	cont = foreach_window_1 (XWINDOW (w->vchild), fn, user_data,allwindows);
+      else{
+        //only call fn if the group of the frames selected window 
+        //is the same as the group of the current window in the loop.
+        group2=Fcdr(Fassq(Qgroup,w->window_parameters));
+        debug_print(group);
+        debug_print(group2);
+        if (allwindows || EQ(group ,  group2  ))
+          cont = fn (w, user_data);
+      }
       w = NILP (w->next) ? 0 : XWINDOW (w->next);
     }
 
@@ -6900,7 +6921,7 @@
      struct frame *f;
      int freeze_p;
 {
-  foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0));
+  foreach_window (f, freeze_window_start, (void *) (freeze_p ? f : 0),1);
 }
 
 \f
@@ -7061,6 +7082,10 @@
 void
 syms_of_window ()
 {
+
+  Qgroup = intern ("group");
+  staticpro (&Qgroup);
+
   Qscroll_up = intern ("scroll-up");
   staticpro (&Qscroll_up);
 

=== modified file 'src/window.h'
--- src/window.h	2008-06-06 00:00:29 +0000
+++ src/window.h	2008-06-07 22:28:47 +0000
@@ -784,7 +784,8 @@
 extern void freeze_window_starts P_ ((struct frame *, int));
 extern void foreach_window P_ ((struct frame *,
 				int (* fn) (struct window *, void *),
-				void *));
+				void *,
+                                int allwindows));
 extern void grow_mini_window P_ ((struct window *, int));
 extern void shrink_mini_window P_ ((struct window *));
 


[-- Attachment #3: Type: text/plain, Size: 20 bytes --]



-- 
Joakim Verona

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Window-groups
  2008-06-22 19:07 [PATCH] Window-groups joakim
@ 2008-06-23 14:14 ` Richard M Stallman
  2008-06-23 14:14 ` Richard M Stallman
  2008-06-23 14:14 ` Richard M Stallman
  2 siblings, 0 replies; 5+ messages in thread
From: Richard M Stallman @ 2008-06-23 14:14 UTC (permalink / raw)
  To: joakim; +Cc: emacs-devel

    +(defun window-group-create (window)
    +  "Return a window group object with WINDOW as its only member.
    +An error is signalled if WINDOW is not visible or already part of
    +a group."

That's ambiguous -- it is not clear whether "not" covers the second
disjunct.  I suggest "...is not visible or if it is already..."

Also, "An error is signalled" is passive.  Please try to stick to the
active voice whenever that isn't difficult to do.

    +The windows in the group are not deleted."

More passive voice.  It will be clearer if you make it active.

    +;; Here's some examples.

"Here are".

    +(defun window-group-members (group)
    +  "Return all windows in GROUP.
    +Must be in selected frame."

That last sentence is very vague.




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Window-groups
  2008-06-22 19:07 [PATCH] Window-groups joakim
  2008-06-23 14:14 ` Richard M Stallman
@ 2008-06-23 14:14 ` Richard M Stallman
  2008-06-23 14:14 ` Richard M Stallman
  2 siblings, 0 replies; 5+ messages in thread
From: Richard M Stallman @ 2008-06-23 14:14 UTC (permalink / raw)
  To: joakim; +Cc: emacs-devel

    +  (let* ((name (concat "group-" (number-to-string window-group--counter)))
    +         (group (make-symbol name)))

I think the name should be given by the caller, not constructed.




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Window-groups
  2008-06-22 19:07 [PATCH] Window-groups joakim
  2008-06-23 14:14 ` Richard M Stallman
  2008-06-23 14:14 ` Richard M Stallman
@ 2008-06-23 14:14 ` Richard M Stallman
  2008-06-23 14:29   ` joakim
  2 siblings, 1 reply; 5+ messages in thread
From: Richard M Stallman @ 2008-06-23 14:14 UTC (permalink / raw)
  To: joakim; +Cc: emacs-devel

Please stick to our coding style.  Please follow the conventions of
spacing and indentation that are used throughout the code.

	      case DELETE_OTHER_WINDOWS:
    -	    if (!EQ (window, obj))
    +            if (!EQ (window, obj) )

There shouldn't be a space between two closeparens.

    +  if(!NILP(Fwindow_parameter(window, Qgroup)))

Please put spaces before all those openparens.  Likewise in the many
similar cases.  The only time an openparen should have no preceding
space is when it follows another openparen or an openbracket or a
unary operator.

    +    foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data,allwindows);

Please put a space after every comma.

    +      else{

Please put the open brace on a separate line.


Please do not mess up the code by introducing variation in these style
questions.  Please don't leave it to someone else to fix these things.




^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] Window-groups
  2008-06-23 14:14 ` Richard M Stallman
@ 2008-06-23 14:29   ` joakim
  0 siblings, 0 replies; 5+ messages in thread
From: joakim @ 2008-06-23 14:29 UTC (permalink / raw)
  To: rms; +Cc: emacs-devel

Richard M Stallman <rms@gnu.org> writes:

> Please stick to our coding style.  Please follow the conventions of
> spacing and indentation that are used throughout the code.
>
> 	      case DELETE_OTHER_WINDOWS:
>     -	    if (!EQ (window, obj))
>     +            if (!EQ (window, obj) )
>
> There shouldn't be a space between two closeparens.
>
>     +  if(!NILP(Fwindow_parameter(window, Qgroup)))
>
> Please put spaces before all those openparens.  Likewise in the many
> similar cases.  The only time an openparen should have no preceding
> space is when it follows another openparen or an openbracket or a
> unary operator.
>
>     +    foreach_window_1 (XWINDOW (FRAME_ROOT_WINDOW (f)), fn, user_data,allwindows);
>
> Please put a space after every comma.
>
>     +      else{
>
> Please put the open brace on a separate line.
>
>
> Please do not mess up the code by introducing variation in these style
> questions.  Please don't leave it to someone else to fix these things.

These concerns will be addressed in the next version of the patch.

-- 
Joakim Verona




^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2008-06-23 14:29 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-06-22 19:07 [PATCH] Window-groups joakim
2008-06-23 14:14 ` Richard M Stallman
2008-06-23 14:14 ` Richard M Stallman
2008-06-23 14:14 ` Richard M Stallman
2008-06-23 14:29   ` joakim

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).