JED Macro: temabbrv.sl

## temabbrv.sl

provides a function that takes the word before the cursor and expands it if that word is defined in a template file. It works much like dabbrev. The function can be bound to any key. For example when you type

       if

at end of line and press TAB (and the function `temabbrev` is bound to that key), the result is

       if (_) {
       }

and it is correctly indented (_ marks the position of the cursor).

## JED temabbrv mode

This mode provides a function that takes the word before the cursor and expands it if that word is defined in a template file. It works much like dabbrev. The function can be bound to any key. For example when you type

       if

at end of line and press TAB (and the function `temabbrev` is bound to that key), the result is

       if (_) {
       }

and it is correctly indented (_ marks the position of the cursor).

In this case the word if was defined in a template file:

    @@[if]
    if ($_) {
    }
    @@:I+

where `$_` denotes the position of the cursor after expansion.

The same word can have multiple definitions. When you press TAB again, `temabbrev` searches for the next definition of if and you get:

       if ($_) {
       }
       else
       {
       }

The whole template file looks like this:

    @@[if]
    if ($_) {
    }
    @@:I+

    @@[if]
    if ($_) {
    }
    else
    {
    }
    @@:I+

You can also add parameters (`$1` - `$9` and `$_`) to macros:

    @@[class]
    class $1$_
    {
    private:
    protected:
    public:
      $1 ();
      ~$1 ();
    };
    @@:I+,$1 Class name

In this case when you press TAB (at eol after word `class`), `temabbrev` displays

    class $1$_
    {
    private:
    protected:
    public:
      $1 ();
      ~$1 ();
    };

and waits for 5 seconds for te user to press '!' or any other key. If the user presses '!', `temabbrev` asks for the value of each parameter and replaces its tag with its definition. In the former case `temabbrev` would display (in minibuffer):

    $1 Class name:

If the user enters CMyClass, the overall result is:

    class CMyClass_
    {
    private:
    protected:
    public:
      CMyClass ();
      ~CMyClass ();
    };

If the user does not press '!', `temabbrev` leaves the inserted text as displayed or finds another expansion for `class` if the user pressed TAB.

## Templates

A template is defined with an opening tag (`@@[...]`) and a closing tag (`@@:`). Both tags must be at the beginning of line. The opening tag contains the word to be expanded:

    @@[if]

The closing tag may contain a comma separated list of flags and prompts for parameter replacement:

    @@:I+,$1 Class name

Possible flags:

- `I+` Indent all lines after inserting the expansion
- `I-` Do not Indent lines after inserting the expansion (default)

Each prompt for parameter replacement must contain the tag of the parameter to be replaced. An expansion may have up to 9 different parameters with tags `$1` - `$9`:

    $1 Class name

means: Read the value of paramater $1 from minibuffer with prompt string "Class name".

You can put arbitrary text between the opening/closing tags. You can use the following 'macros' in the body:

`$1 - $9` | Replace with the value of parameter $N
`$_` | Leave the cursor at this position after expansion
`$(varname)` | Replace with the value of SLang variable or with '?' if the variable is not defined

`$(varname)` also works for functions without parameters that leave a value on the stack.

## Template files

A template file can contain any number of templates. A template file can include another template file with the `@@#INCLUDE` directive.

    @@#INCLUDE cslang.inc

The template file for a certain mode must have the same name as the mode that uses it with all characters in lower-case and with '.tem' suffix. For example in "SLang" mode `temabbrev` will search for the file named "slang.tem".

An included file can have an arbitrary name.

### Locations for template files

By default, template files are stored in a directory named 'template' which is in any directory in `get_jed_library_path()` or in the Jed home directory (variable `Jed_Home_Directory`).

You can add more directories with `tem_add_template_dir()` in your .jedrc.

For example, if the following are the default directories:

       get_jed_library_path():         '/usr/local/jed/lib'
       Jed_Home_Directory:             '~/jed'

and you put this code in .jedrc:

       tem_add_template_dir('~/mytemplates/jed')

the resulting list of directories to search for template files will be:

      '~/mytemplates/jed'
      '~/jed/template'
      '/usr/local/jed/lib/template'

When `temabbrev` searches for the mode template file it will stop searching at the first file it finds. The order of direcories to search is:

1. directories added with `tem_add_template_dir()`, in reverse order
2. Jed_Home_Directory
3. directories from `get_jed_library_path()`

The same is true for the files that you include with the `@@#INCLUDE` directive, if the filename does not include any path specifications. You can also include files with realtive and absolute paths and you can also use environment variables to secify the root path. Examples:

>     @@#INCLUDE cslang.inc

> will search all the directories for the first occurence of `cslang.inc`,

>     @@#INCLUDE .\cslang.inc

> will search for `cslang.inc` in the directory of the file that includes it,

>     @@#INCLUDE ~/jed/template/cslang.inc

> will search for `~/jed/template/cslang.inc`, and

>     @@#INCLUDE $JED_ROOT/lib/template/slang.tem

> will search for `/usr/local/jed/lib/template/slang.tem` if the environment variable `JED_ROOT` is `'/usr/local/jed'`. This way you can put your own templates for SLang in a template file in your home directory, and still use the templates that are defined in `/usr/local/jed/lib/template/slang.tem`.