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: Wed, 8 Dec 2010 10:14:01 +0200 Message-ID: References: NNTP-Posting-Host: lo.gmane.org Mime-Version: 1.0 Content-Type: multipart/alternative; boundary=0016364efa4c30ff5d0496e1b488 X-Trace: dough.gmane.org 1291796139 31859 80.91.229.12 (8 Dec 2010 08:15:39 GMT) X-Complaints-To: usenet@dough.gmane.org NNTP-Posting-Date: Wed, 8 Dec 2010 08:15:39 +0000 (UTC) Cc: Emacs Dev To: Stefan Monnier Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane.org@gnu.org Wed Dec 08 09:15:34 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 1PQFAO-0008SK-57 for ged-emacs-devel@m.gmane.org; Wed, 08 Dec 2010 09:15:33 +0100 Original-Received: from localhost ([127.0.0.1]:47957 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PQFAN-0003qf-Go for ged-emacs-devel@m.gmane.org; Wed, 08 Dec 2010 03:14:23 -0500 Original-Received: from [140.186.70.92] (port=57857 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1PQFAB-0003pM-6B for emacs-devel@gnu.org; Wed, 08 Dec 2010 03:14:17 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1PQFA3-0002EY-Oj for emacs-devel@gnu.org; Wed, 08 Dec 2010 03:14:11 -0500 Original-Received: from mail-ww0-f49.google.com ([74.125.82.49]:65156) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1PQFA3-0002Cz-Cx for emacs-devel@gnu.org; Wed, 08 Dec 2010 03:14:03 -0500 Original-Received: by wwb17 with SMTP id 17so847189wwb.30 for ; Wed, 08 Dec 2010 00:14:01 -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=yUfwTyiOFePPmUpC9yvYIz2r6rGJkPs8wSNcLPRInGo=; b=SRchmhvMpXSJjHvNtUdtTiHpydHgvjuUEIFa99oztiHZe/v5uA98hu2OXA8RwQkWSC 8i51Uj7UHwRpL/u0kUV1htng8jai7MNAlHpyyu7Q0kJiBuMz11dEhL6turtAo1bGwzn0 MF1N2v2l4IOjhNuCWQ3BDTmD5lkU3b38aDEmI= 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=qqNUtYZ+OwRBtJA+qFjvFOsG+kuX82RaBU+5jsanlQ1wCmiM57ADnZ+YQSViJ+MXqY yvgT0XukSIL/0NTIxuIY4GOFGhJ8aKGTG+NezFFkm1Z8syFtXaoMRd/vkfbz1/tQHjTf MNzeYPhYwX5jxizkqguq1rMMsdUDNqzLM3qV4= Original-Received: by 10.227.144.9 with SMTP id x9mr8537734wbu.76.1291796041760; Wed, 08 Dec 2010 00:14:01 -0800 (PST) Original-Received: by 10.227.55.67 with HTTP; Wed, 8 Dec 2010 00:14:01 -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:133531 Archived-At: --0016364efa4c30ff5d0496e1b488 Content-Type: text/plain; charset=UTF-8 > >> > The idea is that I added to struct frame a list of tabs. > >> 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? > I defined the tabs inside the struct frame, because I thought that their names are displayed on the upperside of a frame. Despite this, they have nothing in common with a frame. tab_bar_items is a list of tabs, so it looks like this: ( ( (:name "tab1") (:init-code (lambda () ... code) ) (:activate-code (lambda() ... code) ) (:deactivate-code ... ) (:environment list-of-symbols) ) ( (:name "tab2") (:init-code (lambda () ... code) ) (:activate-code (lambda() ... code) ) (:deactivate-code ... ) (:environment list-of-symbols) ) ) So far it is accesible via frame-parameters, but in my code this access is not useful/used. I could separate all tabs parameters into a struct tab, and keep inside struct frame only 3 fields. struct frame { bool subscribe_to_tabs; int tab_bar_lines; char *regexp; } when f->subscribe_to_tabs is true, then it is displayed on `tab_bar_lines' the tabs that match regexp for example. It is not required to keep a fixed number of parameters for a tab, like :activate-code, :init-code, etc. One can add a parameter (:kill-buffer-xyz (lambda () ... )) that is called when an event, like kill-buffer of a buffer named "xyz" produces. But for now we can suppose the number is fixed. > > >> > A tab is an alist of > >> > >> > ( > >> > (:name "string-name") > >> > (:init-code (lambda () ... code) ) > >> > (:activate-code (lambda() ... code) ) > >> > (:deactivate-code ... ) > >> > (:environment list-of-symbols) > >> > ) > >> > >> What's the init-code for? > > > The init code is executed only when the tab is created. In my script it > is > > used to memorize the current window config into a variable 'sym. The > > variable sym must be tab-local during the tab existence. > > Who creates such a tab and how, then? If the tab is created from Elisp > code, then that code can run the init-code without any special support in > the > tabs code. So why is there such a special init-code? > > Oh, I think maybe I see: the tab creation is done in C and it calls this > init-code to setup the new tab. I.e. when you wrote "a tab is an > alist", what you really meant was "a tabbar is an alist", is that right? > Yes, like this. Or the :initcode is executed from (make-tab, like in my example, and for my example there is no reason to keep it memorized as a parameter in tab's alist parameters, because in this example it is not useful any more). But the :initcode can be very useful, because a tab should be re-initialized sometimes. Yes, I keep a tab as an alist, and all tabs as list of tabs. > > >> I suspect activate is run when you click on the tab and deactivate is > >> run when you click on some other tab. > >> What's environment and how is it used? > > An environment keeps tab-local variables. > > I'm trying to move away from the "foo-local variable" business, so let's > not introduce new ones. > OK > > > For example , every tabmust know about the window-configuration when > > it was created , and extract from its own environment the value of > > that win config. > > But the :environment is shared by all tabs of the same tabbar, isn't it? > Rather than "environment" I'd rather use some other word, not > associated with variables. It's basically just some data specific to > the activate/deactivate code, so we could call it "aux data" or "private > data", tho of course, this all still depends on whether that data is > tab-specific or tabbar-specific. > Every tab to me has a parameter :environment, and after it the symbols from that env. Evaluating the first symbol, I got the value of the tab-configuration, and pass it to set-win-config. > > >> > This is the function that defines a tab. It initialize a symbol sym > >> > with the value of current-window-config. The symbol 'sym is passed > >> > to (make-terminal-frame), that creates the tab. > >> I don't understand this "symbol sym" business. > > I have just explained. It is not interned in the main obarray, and it is > > passed to the environment of the tab. > > No you haven't because you haven't explained why you need *variables*. > You explained what you need to store some auxiliary data, but usually > that's stored in a data-structure, not in a variable. Yes, one can store private data, but if we need more private data than a variable, we need to name every stored value. A stored value can be stored - using a plist - using an alist -using a list of symbols with values (as I did) - using an actor - probably more > > >> > ;; this is a definition of a tab as a window configuration > >> > (defun make-wc-tab (parms) > >> > ;; save curent win config > >> > (setq sym (make-symbol "winconfig")) > >> > >> Here, you're setting a global variable, which is wrong. It's also very > >> unclear why you want a symbol here. > > It is not global. It is not interned, and it becomes tab-local. > > Yes, the symbol `sym' assigned by `setq' above is a global variable. > It is assigned a value which is itself a symbol and that symbol is > indeed uninterned, but I'm talking about the symbol `sym' not about the > value stored into its value cell. > This is a mistake in my code, it should not be . I forgot to call a (make-unbound 'sym) > > >> How do "tab:activate" and friends relate to the > >> previous :activate-code thingies? > > Via tab-local variables. > > That doesn't really answer my question, because we're not understanding > each other. > So from your answer I understand that they are indeed different things > (rather than typos, for example), but that doesn't tell me how they > relate: you described a tab(bar?) as having :activate-code but in the > example code you show you use tab:activate instead: does one somehow > ya, in my code I called the symbols tab:activate, and in messages I wrote :activate. Sorry. > morph into the other, or are the two completely independent and if so > how/where/when does the other appear in code? > The same > > > But if I want to be able to re-initialize a tab, then a function to > operate > > on tab's environment is required. > > I'm beginning to think that the init-code should return a value (the > tab's private data), which is then passed to the > (de)activate functions. > This is a good idea. > 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. > > >> I don't understand the above call to `make-terminal-frame': does it > >> create a new frame, or just a new tab? If the first, then I don't > >> understand how it works, and if the second, it's wrong because adding > >> a tab should have nothing to do with frame creation. > > The fact that make-tab calls directly make-terminal-frame is just a > legacy > > of the old code, when a tab used to be just a frame. > > 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. > > > Imagine that emacs had lexical binding. > > Elisp offers plenty of ways to do what one would do with lexical > bindings. So please, just assume that lexical binding is available and > don't add weird things to try to work around its absence. E.g. You can > simulate it with `(lambda () ... ,foo ...) or with `lexical-let' or with > `apply-partially', plus many many other ways (plus Emacs-24 will offer > true lexical binding, if all goes as planned). > OK. I will try to use it > > > Then we woud not need a tab environment, > > Then, please throw it away. > > > Note that inside my implementation of make-tab, the variable 'winconfig > has > > a different value for every tab. When :activatecode is called , > > That's really nasty for the programmer: there is no variable `winconfig' > in your code. There's only a symbol `winconfig' whose value cell you > use as a place holder. You could just as well replace > true. I did not write look-for-variable function; I did not insert it within an obarray, as Alyssa Hacker, Ben Bitdiddle or Louis Reasoner would have done. > > (setq sym (make-symbol "winconfig")) > (set sym (current-window-configuration)) > ... > ...(eval (cdr (assoc 'tab:env (frame-parameters)))) > > with > > (let ((dataholder (list nil))) > (setcar dataholder (current-window-configuration)) > ... > ...(car (cdr (assoc 'tab:env (frame-parameters)))) > > and that would work just as well: `winconfig' is not a variable, but > a "box" data structure. > true. > At least, if I've understood your code correctly. > > It would be very well to agree, before I start completing the code. Alin. --0016364efa4c30ff5d0496e1b488 Content-Type: text/html; charset=UTF-8 Content-Transfer-Encoding: quoted-printable

>> > The idea is that I added to s= truct frame a list of tabs.
>> Where is it? =C2=A0In the frame's parameters? =C2=A0Or is it a= ccessed 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_parameter= s))
> =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 accessible f= rom Elisp?

I defined the tabs inside the struct fr= ame, because I thought that their names are displayed on the upperside of a= frame. Despite this, they have nothing in common with a frame.

tab_bar_items is a list of tabs, so it looks like this:


(
=C2=A0(
=C2=A0=C2=A0 (:name "tab1")
=C2=A0=C2=A0 (:ini= t-code (lambda () ... code) )
=C2=A0=C2=A0 (:activate-code (lambda() ...= code) )
=C2=A0=C2=A0 (:deactivate-code ... )
=C2=A0=C2=A0 (:environment list-of-symbols)
=C2=A0)


=C2=A0(=C2=A0=C2=A0 (:name "tab2")
=C2=A0=C2=A0 (:init-code (lambda= () ... code) )
=C2=A0=C2=A0 (:activate-code (lambda() ... code) )
= =C2=A0=C2=A0 (:deactivate-code ... )
=C2=A0=C2=A0 (:environment list-of-= symbols)
=C2=A0)

)

So far it is accesible via frame-parameters, but in= my code this access is not useful/used.

I could separate all tabs p= arameters into a struct tab, and keep inside struct frame only 3 fields.
struct frame
{

=C2=A0=C2=A0 bool subscribe_to_tabs;
=C2=A0= =C2=A0 int tab_bar_lines;
=C2=A0=C2=A0 char *regexp;
}

when f-= >subscribe_to_tabs is true, then it is displayed on `tab_bar_lines' = the tabs that match regexp for example.

It is not required to keep a fixed number of parameters for a tab, like= :activate-code, :init-code, etc. One can add a parameter (:kill-buffer-xyz= (lambda () ... )) that is called when an event, like kill-buffer of a buff= er named "xyz" produces.

But for now we can suppose the number is fixed.
=C2=A0

>> > A tab is an alist of
>>
>> > (
>> > =C2=A0 (:name "string-name")
>> > =C2=A0 (:init-code (lambda () ... code) )
>> > =C2=A0 (:activate-code (lambda() ... code) )
>> > =C2=A0 (:deactivate-code ... )
>> > =C2=A0 (:environment list-of-symbols)
>> > )
>>
>> What's the init-code for?

> The init code is executed only when the tab is created. In my script i= t is
> used to memorize the current window config into a variable 'sym. T= he
> variable sym must be tab-local during the tab existence.

Who creates such a tab and how, then? =C2=A0If the tab is created fro= m Elisp
code, then that code can run the init-code without any special support in t= he
tabs code. =C2=A0So why is there such a special init-code?

Oh, I think maybe I see: the tab creation is done in C and it calls this init-code to setup the new tab. =C2=A0I.e. when you wrote "a tab is an=
alist", what you really meant was "a tabbar is an alist", is= that right?

Yes, like this. Or the :initcode is e= xecuted from (make-tab, like in my example, and for my example there is no = reason to keep it memorized as a parameter in tab's alist parameters, b= ecause in this example it is not useful any more).

But the :initcode can be very useful, because a tab should be re-initia= lized sometimes.

Yes, I keep a tab as an alist, and all tabs as list= of tabs.

=C2=A0

>> I suspect activate is run when you click on the tab and deactivate= is
>> run when you click on some other tab.
>> What's environment and how is it used?
> An environment keeps tab-local variables.

I'm trying to move away from the "foo-local variable" b= usiness, so let's
not introduce new ones.

OK
=C2=A0

> For example , every tabmust know about the window-configuration when > it was created , and extract from its own environment the value of
> that win config.

But the :environment is shared by all tabs of the same tabbar, isn= 9;t it?
Rather than "environment" I'd rather use some other word, not=
associated with variables. =C2=A0It's basically just some data specific= to
the activate/deactivate code, so we could call it "aux data" or &= quot;private
data", tho of course, this all still depends on whether that data is tab-specific or tabbar-specific.

Every tab to me h= as a parameter :environment, and after it the symbols from that env. Evalua= ting the first symbol, I got the value of the tab-configuration, and pass i= t to set-win-config.

=C2=A0

>> > This is the function that defines a tab. It initialize a symb= ol sym
>> > with the value of current-window-config. The symbol 'sym = is passed
>> > to (make-terminal-frame), that creates the tab.
>> I don't understand this "symbol sym" business.
> I have just explained. It is not interned in the main obarray, and it = is
> passed to the environment of the tab.

No you haven't because you haven't explained why you need *va= riables*.
You explained what you need to store some auxiliary data, but usually
that's stored in a data-structure, not in a variable.
=
Yes, one can store private data, but if we need more private data than = a variable, we need to name every stored value.

A stored value can b= e stored

- using a plist
- using an alist
-using a list of symbols with va= lues (as I did)
- using an actor
- probably more

=C2=A0
<= blockquote class=3D"gmail_quote" style=3D"margin: 0pt 0pt 0pt 0.8ex; border= -left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">
=C2=A0
>> > ;; this is a definition of a tab as a window configuration >> > (defun make-wc-tab (parms)
>> > =C2=A0 ;; save curent win config
>> > =C2=A0 (setq sym (make-symbol "winconfig"))
>>
>> Here, you're setting a global variable, which is wrong. =C2=A0= It's also very
>> unclear why you want a symbol here.
> It is not global. It is not interned, and it becomes tab-local.

Yes, the symbol `sym' assigned by `setq' above is a global va= riable.
It is assigned a value which is itself a symbol and that symbol is
indeed uninterned, but I'm talking about the symbol `sym' not about= the
value stored into its value cell.

This is a mistak= e in my code, it should not be . I forgot to call=C2=A0 a (make-unbound = 9;sym)

=C2=A0

>> How do "tab:activate" and friends relate to the
>> previous :activate-code thingies?
> Via tab-local variables.

That doesn't really answer my question, because we're not und= erstanding
each other.
So from your answer I understand that they are indeed different things
(rather than typos, for example), but that doesn't tell me how they
relate: you described a tab(bar?) as having :activate-code but in the
example code you show you use tab:activate instead: does one somehow

ya, in my code I called the symbols tab:activate, and in= messages I wrote :activate. Sorry.

=C2=A0
morph into the other, or are the two completely independent and if so
how/where/when does the other appear in code?

The = same
=C2=A0

> But if I want to be able to re-initialize a tab, then a function to op= erate
> on tab's environment is required.

I'm beginning to think that the init-code should return a value (= the
tab's private data), which is then passed to the
(de)activate functions.=C2=A0

This is a good idea= .
=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)activate functio= ns 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 on= ly 1 value, we know that it is on the first position of private-data list, = and can access it via cadr.

=C2=A0

>> I don't understand the above call to `make-terminal-frame'= : does it
>> create a new frame, or just a new tab? =C2=A0If the first, then I = don't
>> understand how it works, and if the second, it's wrong because= adding
>> a tab should have nothing to do with frame creation.
> The fact that make-tab calls directly make-terminal-frame is just a le= gacy
> of the old code, when a tab used to be just a frame.

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.

A frame/window can subscr= ibe to tabs, and show them when it is activated/etc.

=C2=A0

> Imagine that emacs had lexical binding.

Elisp offers plenty of ways to do what one would do with lexical
bindings. =C2=A0So please, just assume that lexical binding is available an= d
don't add weird things to try to work around its absence. =C2=A0E.g. Yo= u can
simulate it with `(lambda () ... ,foo ...) or with `lexical-let' or wit= h
`apply-partially', plus many many other ways (plus Emacs-24 will offer<= br> true lexical binding, if all goes as planned).

OK.= I will try to use it

=C2=A0

> Then we woud not need a tab environment,

Then, please throw it away.

> Note that inside my implementation of make-tab, the variable 'winc= onfig has
> a different value for every tab. When :activatecode is called ,

That's really nasty for the programmer: there is no variable `win= config'
in your code. =C2=A0There's only a symbol `winconfig' whose value c= ell you
use as a place holder. =C2=A0You could just as well replace

true. I did not write look-for-variable function; I did not inser= t it within an obarray, as Alyssa Hacker, Ben Bitdiddle or Louis Reasoner w= ould have done.

=C2=A0

=C2=A0 (setq sym (make-symbol "winconfig"))
=C2=A0 (set sym (current-window-configuration))
=C2=A0 ...
=C2=A0 ...(eval (cdr (assoc 'tab:env (frame-parameters))))

with

=C2=A0 (let ((dataholder (list nil)))
=C2=A0 =C2=A0 (setcar dataholder (current-window-configuration))
=C2=A0 =C2=A0 ...
=C2=A0 =C2=A0 ...(car (cdr (assoc 'tab:env (frame-parameters))))

and that would work just as well: `winconfig' is not a variable, but a "box" data structure.

true.
=C2=A0<= /div>
At least, if I've understood your code correctly.


It would be very well to agree, before I start c= ompleting the code.



Alin.


--0016364efa4c30ff5d0496e1b488--