tokenlist.sl
somewhere on your jed_library_path.
Optionally you can also copy tkl-modes.sl
if you will use the
default settings for some modes (SLang, C, python).
Then you activate it in your .jedrc (or jed.rc):
autoload("list_routines", "tokenlist");
autoload("occur", "tokenlist");
The function list_routines is very simple in its default implementation
and is conditionally useful for C and SLang mode. To extend its capabilities you
have to add some macros to search for routines and extract them into the
list-buffer. The easyest way is to add
require("tkl-modes");
to your .jedrc (jed.rc)
. This will add support for SLang, C, Python,
HTML(H1-H9, TABLE, FORM) and LaTeX (section, subsection). If you are not
satisfied with the default implementation or need additional modes, you
should write a separate file (for example myroutines.sl
) and add
autoload("tokenlist_routine_setup_hook", "myroutines");
to .jedrc (jed.rc)
, instead of require
.
Defining your own routine-search
You can write the macros for routine-search directly into .jedrc but it is
much better to add them to a separate file so they will be loaded only
when needed. Here is a minimal example for myroutines.sl
:
% ----------- myroutines.sl ------
define tokenlist_routine_setup_hook(opt)
{
}
% --------------------------------
The above code does not add anything new to the editor.
In this case tokenlist_routine_setup_hook
works just as a
placeholder to load myroutines.sl
. A minimal implementation
that does add something is:
% ----------- myroutines.sl ------
require("tkl-modes");
define tokenlist_routine_setup_hook(opt)
{
}
% --------------------------------
This is the same as putting the require
statement directly into
.jedrc
. The advantage is that tkl-modes.sl
will be
loaded only when needed and this will improve the startup time of jed.
If you have decided that you need to search for routines in a different
manner, you have to do the following:
- add a list of regular expressions to search for
(
<mode>_list_routines_regexp
)
- add a function that will extrat what was found
(
<mode>_list_routines_extract
)
- optionally add a function that will execute when the list is
populated (
<mode>_list_routines_done
)
Here is an example for X-TEXT mode where the titles on the first level
start with '::', on the second with '==' an and on the third level with
'--':
% ----------- myroutines.sl ------
require("tkl-modes");
define tokenlist_routine_setup_hook(opt)
{
}
variable x_text_list_routines_regexp = {
'^::',
'^==',
'^--'
};
define x_text_list_routines_extract(n)
{
if (n == 0) {
bol();
skip_chars(":");
push_mark();
eol;
return (strtrim(bufsubstr()));
}
if (n == 1) {
bol();
skip_chars("=");
push_mark();
eol;
return (".." + strtrim(bufsubstr()));
}
if (n == 2) {
bol();
skip_chars("-");
push_mark();
eol;
return ("...." + strtrim(bufsubstr()));
}
return "";
}
% --------------------------------
The function x_text_list_routines_extract
accepts a parameter
n
which tells what regular expression is currently being used
so we can act accordingly. In our case we indent the title depending on
the active regular expression.
The result of the search would be a list of titles indented depending on
the title level. A buffer like
::Heading 1
...
==Heading 2
...
--Heading 3
..
==Heading 4
would generate a list of 'routines' like
Buffer: TestBufer.xtxt
3 : Heading 1
27 : ..Heading 2
43 : ..Heading 4
33 : ....Heading 3
As you can see the list is not sorted nor by line neither by heading name.
But if you look closer, you can see that the results are in the order the
search was performed: for each regular expression the whole buffer was
searched from top to bottom.
To fix this we also have to write x_text_list_routines_done
that
will sort the titles by line number:
define x_text_list_routines_done()
{
tkl_sort_by_line();
}
The list would now look like
Buffer: TestBufer.xtxt
3 : Heading 1
27 : ..Heading 2
33 : ....Heading 3
43 : ..Heading 4
If we wanted to sort the titles by value, we could use
tkl_sort_by_value
. Unfortunately it would not sort the titles
aphabetically because the titles in the buffer are indented.
Mode writers are encouraged to add _list_routines_
definitions to their modes.
Advanced use
In the beginning we defined the function
tokenlist_routine_setup_hook(opt)
but we didn't use it yet.
What I will present here is still experimental and might change in the
future.
Imagine that you woud like to sometimes list only functions and at other
times only variables. You woud define a global variable
% 0 - all; 1 - variables; 2 - macros
variable slang_routine_mode = 0;
and in slang_list_routines_extract do something
define slang_list_routines_extract(n)
{
...
if (n == 0) { % variables
if (slang_routine_mode != 0 and slang_routine_mode != 1) return '';
...
}
if (n == 1) { % macros
if (slang_routine_mode != 0 and slang_routine_mode != 2) return '';
...
}
}
Alternatively you could use the parameter opt
which is a
structure type defined in tokenlist.sl
.
define my_slang_extract_variable(n)
{
return(strtrim(line_as_string()));
}
define my_slang_extract_macro(n)
{
return(strtrim(line_as_string()));
}
define tokenlist_routine_setup_hook(opt)
{
if (opt.mode == "slang")
{
if (slang_routine_mode == 1)
{
opt.list_regex = { "^variable[ \t]" };
opt.fn_extract = &my_slang_extract_variable;
}
if (slang_routine_mode == 2)
{
opt.list_regex = { "^define[ \t]" };
opt.fn_extract = &my_slang_extract_macro;
}
}
}
The structure opt
could have more members so tokenlist could
be made extremely configurable:
- what to do when user presses Enter (replacing tkl_goto_token)
- what to do when user presses Space (replacing tkl_display_token)
- what other keybindings do we want in the list
- what to do when the current line is changed in the list (extending
the tkl_update_token_hook)
- ...