emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Fwd: Tabs for console.


From: Stefan Monnier
Subject: Re: Fwd: Tabs for console.
Date: Tue, 07 Dec 2010 12:06:29 -0500
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (gnu/linux)

>> > 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?

>> > 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?

>> 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.

> 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.

>> > 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.

>> > ;; 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.

>> 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
morph into the other, or are the two completely independent and if so
how/where/when does the other appear in code?

> 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.  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.

>> 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.

> 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).

> 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

   (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.
At least, if I've understood your code correctly.
     

        Stefan



reply via email to

[Prev in Thread] Current Thread [Next in Thread]