>> >> 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 #<window-configuration>. 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?