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, PHP, HTML, LaTeX).
Insert the content of the INITIALIZATION block (from tokenlist.sl
) or just
require("tokenlist");into your jed.rc (or .jedrc) file (or use the "make_ini" and "home-lib" modes from jedmodes.sf.net). Optionally add some keybindings, e.g.:
setkey("list_routines", "^R"); setkey("occur", "^O");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. Extensions are provided for more modes in the file
tkl-modes.sl
which can be loaded in tokenlist_hook()
which you define in
.jedrc (jed.rc)
:
define tokenlist_hook() { if (expand_jedlib_file("tkl-modes")) require("tkl-modes"); }If you use
require("tokenlist")
to load tokenlist.sl
then you should put the definition of tokenlist_hook()
before
require("tokenlist")
.
You can add more definitions to tkl-modes.sl
but it is better to write a separate file like mytklist.sl
and
change tokenlist_hook()
to:
define tokenlist_hook() { if (expand_jedlib_file("tkl-modes")) require("tkl-modes"); if (expand_jedlib_file("mytklist")) require("mytklist"); }
.jedrc
but it is better to add them to a separate file so they will be loaded only
when needed. Here is a minimal example for mytklist.sl
:
% ----------- mytklist.sl ------ provide("mytklist");Let us now define a special X-TEXT mode where the titles on the first level start with '::', on the second with '==' an and on the third level with '--'. In the result list the titles should be indented depending on the level of the title.
For the new mode to work we have to define the function
x_text_list_routines_setup(opt)
where opt
is a structure
that defines the behaviour of list_routines
. It has the following
fields:
Field | Description | Default |
---|---|---|
mode | The name of the mode. | |
list_regex |
A list of regular expressions to search for. list_routines will
take every item from the list and search for all the occurences in the
active buffer that match the item (regular expression). After an expression
is found, some text is extracted from the buffer with a call to fn_extract .
An item from the list can be a function reference instead of a regular expression.
In this case the function will be called by % Int_Type searc_fn(Int_Type array_index) define searc_fn(idx) { return fsearch("something"); } |
{"^[a-zA-Z].*("}; |
fn_extract |
A reference to a (private) function that extracts some text at the current point in the
active buffer and returns it as a string.
It is called after every match that list_routines finds.
The function takes an integer parameter which is the current
index and looks like this:
% String extract_fn(Int_Type array_index) define extract_fn(idx) { return line_as_string(); } |
&_list_routines_extract
The function is defined in tokenlist and returns the current line (line_as_string). |
onlistcreated |
A reference to a (private) function that is called after all the items from list_regex
have been processed. The active buffer is the list of matches and it is narrowed to the
matches found in the last buffer.
You can use this hook to sort the matched lines or do any other processing of the
buffer. There are two helper functions defined in |
NULL |
Here is the code for the "X-TEXT" mode:
% ----------- mytklist.sl ------ autoload("tkl_sort_by_value", "tokenlist"); autoload("tkl_sort_by_line", "tokenlist"); provide("mytklist"); private define x_text_list_routines_extract(n) { variable chars = [":", "=", "-"]; variable prefix = ["", "..", "...."]; if (n < 3) { bol(); skip_chars(chars[n]); push_mark(); eol(); return (prefix[n] + strtrim(bufsubstr())); } return ""; } define x_text_list_routines_setup(opt) { opt.list_regexp = { '^::', '^==', '^--' }; opt.fn_extract = &x_text_list_routines_extract; opt.onlistcreated = &tkl_sort_by_line; }
If have a buffer TestBufer.xtxt with the content like
::Heading 1 ... ==Heading 2 ... --Heading 3 .. ==Heading 4
list_routines
would generate the following list:
Buffer: TestBufer.xtxt 3 : Heading 1 27 : ..Heading 2 33 : ....Heading 3 43 : ..Heading 4You can see that the list is sorted by line number. This is because we set
opt.onlistcreated
to &tkl_sort_by_line
. If
we set it to NULL
we get the following list:
Buffer: TestBufer.xtxt 3 : Heading 1 27 : ..Heading 2 43 : ..Heading 4 33 : ....Heading 3If we wanted to sort the titles by value, we could use
tkl_sort_by_value
. Unfortunately it would not sort the titles
alphabetically because the titles in the buffer are indented.
Mode writers are encouraged to add _list_routines_setup
definitions to their modes.
#<INITIALIZATION>
in SLang mode. You could change the
function slang_list_routines_setup
in tkl-modes.sl
or copy the
contents from tkl-modes.sl
to mytklist.sl
and change it there. This
would be hard to maintain.
That is why another hook was added to tokenlist:
Void tokenlist_routine_setup_hook(opt)This hook is not defiend by default. You can add it to a file like
mytklist.sl
. In our example we add a new regular expression and
modify the extraction function. We store some values from
the structure opt
for later use.
private variable slang_nregex = NULL; private variable slang_fn_extract = NULL; private variable slang_onlistcreated = NULL; private define my_slang_fn_extract(idx) { if (idx < slang_nregex && slang_fn_extract != NULL) return (@slang_fn_extract)(idx); else return strtrim(line_as_string()); } define tokenlist_routine_setup_hook(opt) { if (opt.mode == "slang") { slang_nregex = length(opt.list_regex); slang_fn_extract = opt.fn_extract; slang_onlistcreated = opt.onlistcreated; list_append(opt.list_regex, "^#\\<[a-zA-Z]"); opt.fn_extract = &my_slang_fn_extract; } }
my_slang_fn_extract
will use the original extraction function for
the original regular expressions and extract the current line for the new
regular expression.
Imagine that you woud like to sometimes list only functions and at other
times only variables. You would define a global variable and prepare the
members of the parameter opt
according to the value of the variable:
% 0 - all; 1 - variables; 2 - macros variable slang_routine_mode = 0; private define my_slang_extract_variable(n) { return(strtrim(line_as_string())); } private 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; } } }
opt
could have more members so tokenlist could
be made extremely configurable: