Tokenlist installation

First you have to copy 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:

  1. add a list of regular expressions to search for (<mode>_list_routines_regexp)
  2. add a function that will extrat what was found (<mode>_list_routines_extract)
  3. 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: