emacs-devel
[Top][All Lists]
Advanced

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

Re: Fwd: Tabs for console.


From: Alin Soare
Subject: Re: Fwd: Tabs for console.
Date: Wed, 8 Dec 2010 10:14:01 +0200


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



reply via email to

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