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