February, 2015 |
It would be a much appreciated feature to have a keyboard shortcut to
cycle through all open buffers in a TeXmacs session. Of course, there
is the
Well, we would very much like it. And at least one of us wants to learn how to improve his coding skills and get to know TeXmacs. So here it is. (Because we can is another valid motivation).
We proceed in five steps:
Add the information on when buffers were opened to the internal data structure representing them.
Implement a
Export (a.k.a. “glue”) this function to the
Actually implement the feature “go to next/previous buffer”.
Add shortcuts [and menu items] to use this feature.
We first need to add a routine to TeXmacs which returns the time at
which a buffer was opened. This is going to be the default ordering of
the buffers in our swapping list and serves the purpose of
consistently sorting it regardless of recent activity, as opposed to
what is currently done in the
First we need to save this information. In the file src/Texmacs/Data/new_buffer.hpp add the following (~line 31):
time_t open_time; // time that the buffer was opened
We want that the timestamp is added (as metadata) to the buffer when
the buffer is created so we need to modify the last line of the
constructor
last_visit (texmacs_time ()), open_time (texmacs_time()) {}
We now add the declaration of the method which will return the data we just initialized. Define (~line 90):
double buffer_open_time (url name);
This function is made mimicking
double buffer_open_time (url name) { tm_buffer buf= concrete_buffer (name); if (is_nil (buf)) return (double) 0; return (double) buf->buf->open_time; }
All these files and places within files were found by searching for occurrences of last_visited.
The following part is some auto-magic: we use a script to export our
Now that we have the infrastructure, we may add it to the
“glue”, that is, we export it to the
(buffer-open-time buffer_open_time (double url))
Now go to src/Scheme/Glue and do the following:
./build-glue build-glue-basic.scm glue_basic.cpp
For this section we will be looking for inspiration in file-menu.scm,
which we found investigating how the menu
The first thing we need is to be able to order the buffers from the oldest to the newest, hence we start with the routine ordering them.
(define (buffer-first-opened? b1 b2)
(>= (buffer-open-time b1)
(buffer-open-time b2)))
Scheme]
Here we used the routine
(define (buffer-sorted-list)
(with l (list-filter (buffer-list) buffer-in-menu?)
(list-sort l buffer-first-opened?)))
Scheme]
Now we have to cycle through the list looking for our buffer (the
current one) and returning the next one. We will create an auxiliary
function
(define (find-next* l first what)
(cond ((null? l) first)
((== what (car l)) (if (nnull? (cdr l)) (cadr l)
first))
(else (find-next* (cdr l) first what))))
Scheme]
(define (find-next l what)
(if (null? l) "" (find-next* l (car l) what)))
Scheme]
Now, if we want to move forwards then we cycle the list of current buffers starting from the current one, otherwise we revert the list and we cycle in the same way. Do not forget the last line, telling the function what to do with the buffer it gets.
(define (buffer-cycle forwards?)
(with b (current-buffer)
(with next
(if forwards?
(find-next (buffer-sorted-list) b)
(find-next (reverse (buffer-sorted-list)) b))
(switch-to-buffer next))))
Scheme]
(buffer-cycle #f)
Scheme]
Finally we actually define the shortcuts.
(kbd-map
("M-A-left" (buffer-cycle #f))
("M-A-right" (buffer-cycle #t)))
Scheme]