From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!not-for-mail From: Alin Soare Newsgroups: gmane.emacs.devel Subject: Re: Fwd: Tabs for console. Date: Thu, 9 Dec 2010 10:26:10 +0200 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=0016364efa4c77c2df0496f5fd8f X-Trace: dough.gmane.org 1291909538 25559 80.91.229.12 (9 Dec 2010 15:45:38 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Thu, 9 Dec 2010 15:45:38 +0000 (UTC) Cc: Emacs Dev To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Thu Dec 09 16:45:33 2010 Return-path: Envelope-to: ged-emacs-devel@m.gmane.org Original-Received: from lists.gnu.org ([199.232.76.165]) by lo.gmane.org with esmtp (Exim 4.69) (envelope-from ) id 1PQigR-0002WQ-2I for ged-emacs-devel@m.gmane.org; Thu, 09 Dec 2010 16:45:29 +0100 Original-Received: from localhost ([127.0.0.1]:46508 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PQigO-0008Iu-QT for ged-emacs-devel@m.gmane.org; Thu, 09 Dec 2010 10:45:24 -0500 Original-Received: from [140.186.70.92] (port=48775 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PQbpU-0006zI-Ay for emacs-devel@gnu.org; Thu, 09 Dec 2010 03:26:26 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PQbpN-0000mI-Ap for emacs-devel@gnu.org; Thu, 09 Dec 2010 03:26:20 -0500 Original-Received: from mail-wy0-f169.google.com ([74.125.82.169]:50944) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PQbpM-0000lk-Us for emacs-devel@gnu.org; Thu, 09 Dec 2010 03:26:13 -0500 Original-Received: by wyj26 with SMTP id 26so2130128wyj.0 for ; Thu, 09 Dec 2010 00:26:11 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:mime-version:received:received:in-reply-to :references:date:message-id:subject:from:to:cc:content-type; bh=xlKUyNT+KwxkplPf/dgASb83jCHxpocD6FXjgMZa9mE=; b=EDzeHdB92H5jF2sm93h/NI6Z1nMswyKhgKWRtq53WUl5UrW5ak2LbhTg/m0G4c0LfE CRHnWQVXFhbNtsCX5aIEp0ZE9dVyzwocVFn5RD4wjaxjlYdPxhu9jeHLpUERb/DMLzuD SkmHdz3EY1mnNROuLCGg3c872YSQ0JlTdk6AQ= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; b=Lo2y488B96qvKl4LqW+hGwy7xG8VlJ0VVUIZW4A7Jn6vY89FPyZLKHTW1xT5utlmwJ 4glI7s6hupY3rV3wPBK9m3JGzG5tqf+Si27LwvhSmBESmjc/FfFU3QW2Gs5PtCAD7XKY r78+GRo91hA3u3qS6gg+5k2oIGaXdP9M2GwXg= Original-Received: by 10.227.144.9 with SMTP id x9mr10107572wbu.76.1291883170480; Thu, 09 Dec 2010 00:26:10 -0800 (PST) Original-Received: by 10.227.38.162 with HTTP; Thu, 9 Dec 2010 00:26:10 -0800 (PST) In-Reply-To: X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.6 (newer, 2) X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Xref: news.gmane.org gmane.emacs.devel:133546 Archived-At: --0016364efa4c77c2df0496f5fd8f Content-Type: text/plain; charset=UTF-8 >> >> Where is it? In the frame's parameters? Or is it accessed via a new > >> >> frame-tabs and set-frame-tabs? > >> >> > >> >> struct frame > >> > { > >> > ... > >> > /* > >> > * an alist of the form ((alist_tab_parameters)) > >> > */ > >> > Lisp_Object tab_bar_items; > >> > ... > >> > } > >> > >> So it's not in the frame's parameters: how is it accessible from Elisp? > [...] > > So far it is accesible via frame-parameters, but in my code this access > is > > not useful/used. > > IIUC it is also (write-) accessible via `make-tab', right? > No. I'm still very far from understanding what you mean. > So here's how I imagine things working: > > - some function to add/control/create a tabbar. > (make-tab-bar PLACE) > IIUC this function also accepts an INIT-CODE argument, which is run > when the user presses the "+" button on the tab-bar. > - some function to add a tab to a tabbar > (make-tab TABBAR ACTIVATE-FUNCTION DEACTIVATE-FUNCTION) > - probably also some function to delete a tab (delete-tab TABBAR TAB) > - probably also some deletion-hook in case the user presses the "X" > button to delete a tab. > > Now, all of ACTIVATE-FUNCTION, DEACTIVATE-FUNCTION, and DELETION-HOOK > could either be specified in make-tab or in make-tab-bar, depending on > whether we want to impose a uniform behavior. > > If the ACTIVATE-FUNCTION is shared by all tabs, we'll also need each tab > to have a DATA argument, which is the equivalent of your environment. > This is a good idea, to clarify first the elisp interface. * TAB BAR ** (make-tab-bar PLACE) for now, suppose that PLACE can be a frame. In what I did, PLACE is only a frame. * TAB ** A TAB can be defined in many ways. All tabs have in common a :NAME , and an :ID. :NAME is a string that is displayed on the display on the upperside of a frame, and :ID is a number that allows to user to easyly access it. Forget about :ID for now. ** A TAB also have an :INIT-CODE, a :ACTIVATE-FUNCTION, a :DEACTIVATE-FUNCTION, :CLOSE-FUNCTION:, hooks, and probably more. :INIT-CODE must be run to get some values that are useful for :ACTIVATE-FUNCTION, :DEACTIVATE-FUNCTION, etc. These values are not useful for other tabs. For example: *** EXAMPLE1 If I want a tab that keeps a window-configuration, than we need only 1 such variable: a #. This is used by :ACTIVATE-FUNCTION, when one switched to that tab. *** EXAMPLE2 If I want to create a tab, which divides the frame in 2 windows: the upper window switches to buffer "xyz", and the second window switches to buffer "*scratch". Then the INIT-CODE for THIS KIND OF TAB must ask you the name of buffer1, the name of buffer2, and keep these values into a place where these values are accessed ONLY BY :ACTIVATE-FUNCTION, and all other functions of this tab. So the :ACTIVATE-FUNCTION of the next tab (that probably keeps a window-configuration) MUST NOT SEE the values kept by this tab. The :ACTIVATE-FUNCTION of this kind of tab must do something like (lambda () ( delete-other-windows ) (split-window-vertically) (balance-windows) (let ((buffer1 (get-variable "buffer1")) (buffer1 (get-variable "buffer2")) (switch-to-buffer buffer1) (other-window) (switch-to-buffer buffer2) (other-window) ) Ben Bitdiddle would say you so: Please note the function get-variable, that expects to find the value of a variable named "buffer1" INSIDE an environment private to tab1. Alyssa Hacker would say: :INIT-CODE must read the name of the first buffer and store it into a variable "buffer1" of an environment private to the tab that it initializes. It also gets the value of a second buffer, and keeps it in buffer2, etc. These values must be accessed by :ACT-CODE , etc. Note that a variable like "buffer1" is not useful for next tab. It is like in Mozilla: when you press C-k to go to search bar, you can chose the kind of search (google, ebay, wikipedia, and you can add other kind of searches). The search bar is for me the tab-bar, and every kind of search is a tab. ** On the TAB BAR there is a "+" button, but here you did not understand what it is. When pressed, it allows you to chose some kind of tab, and to create such a tab. ** the HOOKS are very useful. *** EXAMPLE: **** Consider a tab that does the following: :INIT-CODE looks like so: (lambda () (delete-other-windows) (read-variable "buffer") (switch-to-buffer (get-variable "buffer")) ) Alyssa Hacker would say: Note that I did write (switch-to-buffer (get-variable "buffer")), and not (switch-to-buffer buffer), because in this case the eval would look for bufferin main obarray, but I need to look in tab's environment. :ACTIVATE-CODE is so: (lambda () (delete-other-windows) (switch-to-buffer (get-variable "buffer")) ) Here (get-variable "buffer")) looks in tabs' environment, and finds exactly the value it needs. **** Now, suppose that the tab is deactivated, but you want to see when the contest of the buffer named (get-variable "buffer") (in tab's environment) changes. In this case you want to see the color of the tab changes , or you want to see on the tab an asterisk, that notifies you that the buffer changed. In this case one can add another function like :CHANGE-FUNCTION. For now, I do not show any code, because it is too advanced, and first of all one must clarify the basics tags, like :INIT-CODE, :ACTIVATE-CODE, etc. > > > But the :initcode can be very useful, because a tab should be > > re-initialized sometimes. > > That sounds odd. When would that be? > It is very useful. Consider that you have a tab (like in EXAMPLE2). You keep in the upper window the buffer "xyz", and in down window the buffer "*scratch*" But 1 hour later, you need to keep in upper window the buffer "abc" and down "*scratch*". You need to re-initialize the tab, and the :INIT-FUNCTION will read again the value of "buffer1" and buffer2. Instead of deleting the tab, and creating a new tab of the same type (that switches to a buffer), you simply re-initialize the tab. > > > Yes, one can store private data, but if we need more private data than a > > variable, we need to name every stored value. > > That doesn't matter to the tabbar code: the tab only ever needs 1 chunk of > private data passed to the activate-function. That chunk can be > anything the activate-function needs: a struct, a list, an alist, you > name it: the tabbar code has no business looking inside. > It is still a problem to clarify how to pass arguments to :INIT-FUNCTION, :ACTIVATION-FUNCTION, :CLOSE-FUNCTION, etc. > > This is a mistake in my code, it should not be . I forgot to call a > > (make-unbound 'sym) > > That doesn't solve the problem: it still affects the global variable > `sym'. > Do not consider it , it's not important, forget about. It was my implementation, that is not the best one, but it is minimal and it works. My purpose was to make tabs that keeps window-configurations. > >> The tabbar code doesn't need to care about what that value is, it just > >> needs to store it and pass it along; the init-code and (de)activate > >> functions will decide what to do with it. > >> It can be a window-config or anything else. That should make your > >> environment business unnecessary. > > Yes, if it is only 1 value, we know that it is on the first position of > > private-data list, and can access it via cadr. > > "we" here would be the activate-function, right? > No. Forget about this. > > >> So it will need to change. But does `make-tab' create a new tab or > >> a tabbar? If a tab, then I don't understand any more why the init-code > >> is needed. > > > Yes, tabs must be separate from frames, and keep indepedent of every > > other thing. A frame/window can subscribe to tabs, and show them when > > it is activated/etc. > > That doesn't answer my question: does `make-tab' create a new tab or > a tabbar? > Your idea of (make-tab-bar PLACE) was very good. The tab bar existed without initialization inside a frame. --0016364efa4c77c2df0496f5fd8f Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

>> >> Where is it? =C2=A0I= n the frame's parameters? =C2=A0Or is it accessed via a new
>> >> frame-tabs and set-frame-tabs?
>> >>
>> >> struct frame
>> > {
>> > ...
>> > =C2=A0 =C2=A0 /*
>> > =C2=A0 =C2=A0 =C2=A0* an alist =C2=A0of the form ((alist_tab_= parameters))
>> > =C2=A0 =C2=A0 =C2=A0*/
>> > =C2=A0 =C2=A0 Lisp_Object tab_bar_items;
>> > ...
>> > }
>>
>> So it's not in the frame's parameters: how is it accessibl= e from Elisp?
[...]
> So far it is accesible via frame-parameters, but in = my code this access is
> not useful/used.

IIUC it is also (write-) accessible via `make-tab', right?

No.

I'm still very far from understanding what you mean.<= br>
So here's how I imagine things working:

- some function to add/control/create a tabbar.
=C2=A0(make-tab-bar PLACE)
=C2=A0IIUC this function also accepts an INIT-CODE argument, which is run<= br> =C2=A0when the user presses the "+" button on the tab-bar.
- some function to add a tab to a tabbar
=C2=A0(make-tab TABBAR ACTIVATE-FUNCTION DEACTIVATE-FUNCTION)
- probably also some function to delete a tab (delete-tab TABBAR TAB)
- probably also some deletion-hook in case the user presses the "X&quo= t;
=C2=A0button to delete a tab.

Now, all of ACTIVATE-FUNCTION, DEACTIVATE-FUNCTION, and DELETION-HOOK
could either be specified in make-tab or in make-tab-bar, depending on
whether we want to impose a uniform behavior.

If the ACTIVATE-FUNCTION is shared by all tabs, we'll also need each ta= b
to have a DATA argument, which is the equivalent of your environment.


This is a good idea, to clarify first the elisp int= erface.

* TAB BAR

**=C2=A0 (make-tab-bar PLACE)

for no= w, suppose that PLACE can be a frame. In what I did, PLACE is only a frame.=

* TAB

** A TAB can be defined in many ways. All tabs have in com= mon a :NAME , and an :ID. :NAME is a string that is displayed on the displa= y on the upperside of a frame, and :ID is a number that allows to user to e= asyly access it. Forget about :ID for now.

** A TAB also have an :INIT-CODE, a :ACTIVATE-FUNCTION, a :DEACTIVATE-F= UNCTION, :CLOSE-FUNCTION:, hooks, and probably more.

:INIT-CODE must= be run to get some values that are useful for :ACTIVATE-FUNCTION, :DEACTI= VATE-FUNCTION, etc.

These values are not useful for other tabs. For example:

*** EXA= MPLE1=C2=A0 If I want a tab that keeps a window-configuration, than we need= only 1 such variable: a #<window-configuration>. This is used by :AC= TIVATE-FUNCTION, when one switched to that tab.

*** EXAMPLE2 If I want to create a tab, which divides the frame in 2 wi= ndows: the upper window switches to buffer "xyz", and the second = window switches to buffer "*scratch". Then the INIT-CODE for THIS= KIND OF TAB must ask you the name of buffer1, the name of buffer2, and kee= p these values into a place where these values are accessed ONLY BY :ACTIVA= TE-FUNCTION, and all other functions of this tab. So the :ACTIVATE-FUNCTION= of the next tab (that probably keeps a window-configuration) MUST NOT SEE = the=C2=A0 values kept by this tab. The :ACTIVATE-FUNCTION of this kind of t= ab must do something like

(lambda ()
=C2=A0( delete-other-windows )
=C2=A0(split-window-ver= tically)
=C2=A0(balance-windows)
=C2=A0(let ((buffer1 (get-variable &= quot;buffer1"))
=C2=A0 =C2=A0 =C2=A0 =C2=A0=C2=A0(buffer1 (get-vari= able "buffer2"))
=C2=A0(switch-to-buffer buffer1)
=C2=A0(other-window)
=C2=A0(switch-to-buffer buffer2)
=C2=A0(other-wi= ndow) )

Ben Bitdiddle would say you so:

Please note the funct= ion get-variable, that expects to find the value of a variable named "= buffer1" INSIDE an environment private to tab1.

Alyssa Hacker would say: :INIT-CODE must read the name of the first buf= fer and store it into a variable "buffer1" of an environment priv= ate to the tab that it initializes. It also gets the value of a second buff= er, and keeps it in buffer2, etc. These values must be accessed by :ACT-COD= E , etc.

Note that a variable like "buffer1" is not useful for next ta= b.

It is like in Mozilla: when you press C-k to go to search bar, yo= u can chose the kind of search (google, ebay, wikipedia, and you can add ot= her kind of searches). The search bar is for me the tab-bar, and every kind= of search is a tab.


** On the TAB BAR there is a "+" button, but here you did= not understand what it is. When pressed, it allows you to chose some kind = of tab, and to create such a tab.


** the HOOKS are very useful.<= br>
*** EXAMPLE:

**** Consider a tab that does the following:
:INIT-CODE looks like so:

(lambda ()
=C2=A0(delete-other-windows= )
=C2=A0(read-variable "buffer")
=C2=A0(switch-to-buffer (g= et-variable "buffer"))
=C2=A0)

Alyssa Hacker would say: Note that I did write (switch-to-bu= ffer (get-variable "buffer")), and not
(switch-to-buffer buffe= r), because in this case the eval would look for bufferin main obarray, but= I need to look in tab's environment.

:ACTIVATE-CODE is so:

(lambda ()
=C2=A0(delete-other-windows)
=C2=A0(switch-to-buffer (get-variable "buffer"))
=C2=A0)

Here (get-variable "buffer")) looks in tabs' = environment, and finds exactly the value it needs.

**** Now, suppose= that the tab is deactivated, but you want to see when the contest of the b= uffer named (get-variable "buffer") (in tab's environment) ch= anges. In this case you want to see the color of the tab changes , or you w= ant to see on the tab an asterisk, that notifies you that the buffer change= d.

In this case one can add another function like :CHANGE-FUNCTION. For no= w, I do not show any code, because it is too advanced, and first of all one= must clarify the basics tags, like :INIT-CODE, :ACTIVATE-CODE, etc.


=C2=A0

> But the :initcode can be very useful, because a tab should be
> re-initialized sometimes.

That sounds odd. =C2=A0When would that be?

I= t is very useful. Consider that you have a tab (like in EXAMPLE2).

Y= ou keep in the upper window the buffer "xyz", and in down window = the buffer "*scratch*"

But 1 hour later, you need to keep in upper window the buffer "abc= " and down "*scratch*". You need to re-initialize the tab, a= nd the :INIT-FUNCTION will read again the value of "buffer1" and = buffer2.

Instead of deleting the tab, and creating a new tab of the same type (t= hat switches to a buffer), you simply re-initialize the tab.
=C2=A0

> Yes, one can store private data, but if we need more private data than= a
> variable, we need to name every stored value.

That doesn't matter to the tabbar code: the tab only ever needs 1= chunk of
private data passed to the activate-function. =C2=A0That chunk can be
anything the activate-function needs: a struct, a list, an alist, you
name it: the tabbar code has no business looking inside.

It is still a problem to clarify how to pass arguments to :INIT-FUNC= TION, :ACTIVATION-FUNCTION, :CLOSE-FUNCTION, etc.


> This is a mistake in my code, it should not be . I forgot to call =C2= =A0a
> (make-unbound 'sym)

That doesn't solve the problem: it still affects the global varia= ble
`sym'.

Do not consider it , it's not impor= tant, forget about. It was my implementation, that is not the best one, but= it is minimal and it works. My purpose was to make tabs that keeps window-= configurations.

=C2=A0
>> The tabbar code doesn't need to care about what that value is,= it just
>> needs to store it and pass it along; the init-code and (de)activat= e
>> functions will decide what to do with it.
>> It can be a window-config or anything else. =C2=A0That should make= your
>> environment business unnecessary.
> Yes, if it is only 1 value, we know that it is on the first position o= f
> private-data list, and can access it via cadr.

"we" here would be the activate-function, right?

No. Forget about this.
=C2=A0

>> So it will need to change. =C2=A0But does `make-tab' create a = new tab or
>> a tabbar? =C2=A0If a tab, then I don't understand any more why= the init-code
>> is needed.

> Yes, tabs must be separate from frames, and keep indepedent of every > other thing. =C2=A0A frame/window can subscribe to tabs, and show them= when
> it is activated/etc.

That doesn't answer my question: does `make-tab' create a new= tab or
a tabbar?

Your idea of (make-tab-bar PLACE) was v= ery good. The tab bar existed without initialization inside a frame.




--0016364efa4c77c2df0496f5fd8f--