15. User Macros
Prev |  | Next

## 15. User Macros

This section describes in detail TrEd's support for user macros and is dedicated mainly to programmers.

As was already mentioned, TrEd is itself written in Perl and therefore it is natural that also user macros are written in the Perl language. The details of the Perl language syntax are not described here. You may find them in various literature on programming in Perl as well as in manual pages of Perl language. A large volume of documentation on Perl and many specific Perl modules is collected for example by ActiveState. In this text, we concentrate on the TrEd's macro specifics only.

### 15.1. A Macro

A macro for TrEd is simply a Perl routine defined using the `sub `name` { ... }` construct, e.g.:

    sub my_first_macro {
     print "Hallo World\n";
    }

Macros may be called from other macros in the same way as any other sub-routines in Perl, for example:

    sub my_first_macro {
    	my_second_macro();  # call to another macro
    }

In this case, macros may use the usual Perl mechanisms to pass any number of argumens to the called macro.

To make the macro accessible from TrEd, two more things should be done. First, a special “binding directive” can be added, so that the macro is associated with a keyboard shortcut and/or added to the list of named macros and filed under the Macros menu under a short descriptive name, where users can easily find and invoke it. Second, the macro must be stored in some file and TrEd must be told where to look for the file. This (and more) is discussed in the following sections.

### 15.2. Macro files

On startup, TrEd looks for two files with macros.

1. The default set of macros (described in more detail in Section 15.8, “Public API: pre-defined macros”) `tred.def`

2. The set of extension macros `tred.mac` or any other file given after the `-m` parameter on the command line or a file specified in the TrEd's configuration option `MacroFile`.

Developers of macros should never modify the `tred.def` file directly. In theory, the file `tred.mac` can be modified when preparing a customized installation of TrEd, but it is seldom needed. In fact, in the current development model, the file `tred.mac` plays the role of a testing ground for macros that are supposed to eventually make it into `tred.def` but whose API is not yet guaranteed to remain unchanged. It also creates initial keyboard and menu bindings for the `TredMacro` annotation mode (see Section 15.10, “Using different sets of macros in different situations”).

Instead, the developers of macros are encouraged either to place their macros into an extension package, or to create a subfolder with a `contrib.mac` file in `tredlib/contrib/`, e.g. ``tredlib/contrib/subdir_name`/contrib.mac`, which will be automatically included into `tred.mac` (the standard version of `tred.mac` includes the file `tredlib/contrib/contrib.mac` which in turn does a wildcard include of `*/contrib.mac`, as described below).

One Macro file may be included into other macro file using one of the following `#include` directives where `filename` is supposed to provide a relative or absolute path to the macro file, under the terms described below:

`#include "`filename`"`

  The `filename` must be relative to the directory of the file to which it is included.

`#include <`filename`>`

  The `filename` must be relative to the TrEd's library directory.

`#include "<`wildcard`>"`

  Expands `wildcard` relatively to the directory of the file containing the directive and includes all matching file.

`#include `filename``

  The `filename` may be both absolute or relative. In the latter case the directories are searched in the following order:

  1. Current directory is searched.

  2. The directory of the file where the `#include` directive occured is searched.

  3. TrEd's library directory is searched.

If `#include` fails to find given file, it is a fatal error and TrEd/bTrEd immediatelly stops. You may use `#ifinclude` directive, if you wish `TrEd` to continue (without error or warning) even if the requested file was not found.

### 15.3. Using various character encodings

### Note

This section applies only to TrEd/bTrEd running under Perl 5.8 and higher.

If non-ASCII characters should occur in macro code, it is necessary to indicate the character encoding used. Otherwise TrEd wouldn't be able to translate the non-ASCII characters into an internal Unicode representation. Failing to indicate encoding used in macro code can therefore lead to unexpected behaviour of the code and/or fatal run-time errors.

By default, TrEd expects UTF-8 encoded macro code (unless specified otherwise using the `defaultMacroEncoding` configuration option). Any other character encoding must be indicated using `#encoding` directive, followed by name of the encoding, such as `utf-8`, `iso-8859-1`, `windows-1256`, etc. The encoding indicated by an `#encoding` directive applies on the macro file strating from the line following the directive to the end of the file or to another `#encoding` directive occurence, whichever happens first. Encoding directive does not apply to included macro files.

Example 2. Indicating macro character encoding

      (UTF-8 encoded macro code)

    #encoding iso-8859-2

      (latin-2 encoded macro code)

    #encoding utf-8

      (UTF-8 encoded macro code continues)

### 15.4. Conditional macro code

If macro code is spanned across several files or is shared between TrEd and bTrEd, it may be useful to make some parts of the macro code (such as an `#include` directive) conditional.

For this purpose TrEd, provides similar mechanisms as standard `C` pre-processors using `#define`, `#undefine`, `#ifdef`, `#ifndef`, and `#endif` directives. These directives must appear on the very beginning of line. Any code enclosed within

#ifdef `symbol-name`

and

#endif

directives is included if and only if the symbol ``symbol-name`` was previously defined using a `#define `symbol-name`` directive. Any code enclosed within

#ifndef `symbol-name`

and

#endif

directives is included if and only if the symbol ``symbol-name`` is not defined. A defined symbol can later be undefined with `#undefine `symbol-name``. Unlike `C` macros, symbols in TrEd have no other purpose than this.

Except for symbols defined by a `#define` directive, symbol `TRED` is always initially defined in TrEd, symbol `BTRED` is always initially defined in bTrEd. This may help to simplify sharing macro code with specific parts for TrEd and bTrEd between these two applications.

### 15.5. Associating macros with menu entries and keyboard shortcuts

The last set of directives is used to associate a macro with a keyboard shortcut and to add it to the list of macros and and the Macros menu under a short descriptive name, so that the user can easily find and invoke it.

To connect a macro named `my_first_macro` with a new entries labeled My First Macro in the Macros → List of Macros... dialog and also in the menu Macros → All Modes → `mode`, the following directive should appear in some macro file read by TrEd:

#insert `my_first_macro` as menu `My First Macro`

Actually the words `as` and `menu` may be omitted, so it is possible to write the above directive also as:

#insert `my_first_macro` as `My First Macro`

or even

#insert `my_first_macro` `My First Macro`

Association between a macro and a keyboard shortcut is defined using the directive `#bind`. For example, to “bind” a macro named `my_first_macro` to say Ctrl+Alt+Del keyboard shortcut, the following line should appear somewhere in the macro file:

#bind `my_first_macro` to key `Ctrl+Alt+Del`

Again, the `to` and `key` keywords may be omitted.

### Warning

Using the particular shortcut chosen here as a funny example is a silly idea indeed, since this very shortcut is typicaly used to restart the system. Remember that only shortcuts that are not interpreted by the operating system or the desktop environment can possibly work as expected.

Both a menu item and a keyboard shortcut can be associated with a macro in one step with a directive of the following :

#bind `my_first_macro` to key `Ctrl+Alt+Del` menu `My First Macro`

If more than one keyboard shortcut or menu item are associated with the same macro, any of them may be used to invoke the macro. If more than one macro was associated with the same keyboard shortcut, then the latest binding is used. Also, if two or more macros with the same name appear in the loaded macro files (within the same package), the last one is used, but that holds in general for any Perl subroutine.

#unbind-key `Ctrl+Alt+Del`

#remove-menu `My First Macro`

The first of the directives above removes an existing key-bindning from current annotation mode(s). The second one removes an existing menu entry from the macro menu of the current annotation mode (Macros → All Modes → `annotation mode`). These directives is especially useful for disabling certain functionality and bindings of an incuded macro file.

### 15.6. When macro ends

When an interactively invoked macro returns, TrEd performs the following steps:

- the node referenced in `$this` is activated in the current view (provided it belongs to the current tree)

- all views are redrawn (unless specified otherwise in the variable`$Redraw`), see below.

- unless the value of the variable `$FileChanged` (see Section 15.8, “Public API: pre-defined macros”) is set to 0, the save-status of the current file is turned to `modified` (as indicated by the state of the button).

The variable `$Redraw` may have the following values:

`file` (the default)

  redraw all windows displaying current file

`tree`

  redraw all windows displaying current tree

`win`

  redraw current window

`all`

  redraw all windows

`tie`

  redraw all windows if TrEd windows are tied otherwise redraw only the current one

`none`

  disables redrawing

Because TrEd has no way to identify whether the current file (or in fact any other file) was actually modified by the macro, it always assumes it was. To prevent this and indicate that no actual changes which would require the user to save the file were done to the current file, the macro must explicitly set a special variable named `$FileChanged` to zero. Even better (to prevent accidental collisions between several assignments to this variable), instead of directly assigning to this variable, call the default macro `ChangingFile(0)`.

To make things more complicated, it should be noted, that btred, the off-line variant of TrEd, never saves any processed file unless the variable `$FileChanged` has been explicitely set to `1` or `-S` command-line switch is used. So, conversely, in btred, a macro should indicate making a change worth saving by calling `ChangingFile(1)`.

### Note

If the state of the file was already modified and not saved when a macro was interactively invoked, then any changes to the `$FileChanged` variable made by the macro are ignored. Macro may however force the file status to return to saved by setting the variable `$forceFileSaved` to `1` (typically after an explicit call to `Save()`).

### Note

For historical reasons, there exists an alias for `$FileChanged` named `$FileNotSaved`. These variables are identical.

### 15.7. Accessing tree nodes

A tree in TrEd is represented by its root node. The root node can be distinguished from other nodes by having no parent node. Similarly leaf nodes have no children (see `firstson()` method described bellow).

All tree nodes in TrEd are represented by `Treex::PML::Node` Perl objects. These objects are basically only hash references where the attribute-name/attribute-value information is stored as a key/value pair (except that some hash keys are reserved for representing the tree structure). `Treex::PML::Node` objects provide several basic methods, most of which are related to accessing their neighbouring nodes (i.e. traversing the tree) and modifying the tree structure by means of cut and paste operations.

Macros usually start from the nodes accessible via global variables (these variables are declared in the `TredMacro` package, but exported by default to any other derived package):

`$this`

  is the active node in the current tree. Macros may use this variable to access the active node, its attributes, methods etc. They also may assign to this variable to activate a different node.

`$root`

  is the root of the current tree. Macros may use this variable to access the root of the tree and (by following the tree edges) to access the whole tree. Assigning to this variable has no visible effect.

#### 15.7.1. Node types

Each node may be associated with a PML type (see also Section 16.6.3, “Internal representation of PML data”) dictating e.g. which the attributes the node may or must carry and for each attribute its data type.

### Note

Some older I/O backends do not provide PML-based typing and produce nodes that are untyped. In such a case, the names, types, and roles of the attributes can be obtained from the `Treex::PML::FSFormat` object associated with the document (see below).

The object representation of the data type of a node is returned by the method `$node->type()` (see `Treex::PML::Node`). It may be either from the class `Treex::PML::Schema::Struct` (or derived) if the node is represented in PML by a structure or `Treex::PML::Schema::Container` (or derived) if the node is represented in PML by a container. To get the object representation of the complete PML schema where the node type is declared (`Treex::PML::Schema`), one may call `$node->type()->schema()`, provided `$node->type()` is known to be defined.

#### 15.7.2. Accessing node attributes

Let `$node` be a `Treex::PML::Node` object, i.e. a node of the tree. Typically, nodes are attribute-value structures, so the attribute named ``attrib`` is accessible as `$node->{`attrib`}`. Assigning a different value, say `$val`, to the attribute ``attrib`` is as simple as this:

$node->{`attrib`}=$val;

Attribute values may not always be atomic, i.e. numbers or strings (although for most backends this is the case). They may also be AVS structures (represented as `Treex::PML::Struct` objects, which are basically just Perl hashes), lists (represented as Perl ARRAY references of the `Treex::PML::List` class) and alternatives (represented as Perl ARRAY references of the `Treex::PML::List` class). So let's suppose for a while, that the value of `$node->{`attrib`}` is an AVS structure with attribute `level2-attrib` and its value is a list of structures with an attribute `level3-attrib` whose value (of whatever type it is) we want to get and possibly change. To access the attribute `level3-attrib`, we may either use Perl-only syntax and proceed e.g. as follows:

$node->{attrib}{level2-attrib}[0]{level3-attrib}

Notice, that from the list of structures in `level2-attrib` we have only selected the first one (in Perl, array indexes start with 0). This approach has a non-obvious drawback: if on some level the value is not defined, Perl “auto-creates” an empty structure on that level (this “auto-creation” continues also for all further levels of the expression). Hence, by querying a value, we have actually made a change. This typically is an undesirable effect. There are two ways to avoid it: first would be to follow the nesting of the Perl structures one level at a time and on every step first check that the value on that level is non-empty. This is however makes the code less readable and unnecessarily complex. Second method provides the same functionality with a nice syntax using so called attribute-paths. Attribute path is an expression similar to a directory path or XPath and expresses a path in the nesting of the Perl structures. Using attribute-paths, the expression

    $node->{attrib}{level2-attrib}[0]{level3-attrib}

could be rewritten as

    $node->attr('attrib/level2-attrib/[1]/level3-attrib')

The method `attr` resolves attribute-paths safely, avoiding auto-creation of Perl structures on the way. Note, that in the attribute-path, list and alternative members are indexed starting from 1. In fact, if we want to access the 1st element, we may completely skip the index specification and write:

    $node->attr('attrib/level2-attrib/level3-attrib')

Sometimes it is necessary to iterate over all list members of some attributes. The macro `ListV` (and its cousin macro `AltV` used for alternatives) can be used to produce a list of all values of a given attribute, e.g.

    foreach my $member
    	  (ListV($node->attr('attrib/level2-attrib')))
    	  { # process list member $member print
    	  $member->{level3-attrib},"\n";
    	  }

Values of attributes can be changed by pure Perl assignments, e.g.

    $node->{attrib} = new_value;

or

    $node->{attrib}{level2-attrib}[0]{level3-attrib} = new_value

The previous assign ment may also be achieved using

    $node->set_attr('attrib/level2-attrib/[1]/level3-attrib',new_value);

The macro `List` can be used to construct a new list value. Several other default macros for dealing with list and alternative values exists (see Section 15.8, “Public API: pre-defined macros”).

#### 15.7.3. Accessing neighboring nodes

There is a few methods provided by every `Treex::PML::Node` reference that can be used to access other nodes in the tree. Each of the methods returns either a `Treex::PML::Node` reference pointing to the requested node, or zero if the requested node does not exist. For example, the following code may be used to make the active node's parent node active:

    $this = $this->parent if ($this->parent);

The above code states: activate the parent node of the currently active node in case the currently active node has a parent.

The following table describes some `Treex::PML::Node` methods. For a complete list, refer to the documentation of Treex::PML.pm.

Table 4. `Treex::PML::Node` methods

Method name | Description
--- | ---
`parent` | Return node's parent node.
`firstson` | Return the first child node of the given node (the first node depending on the given node).
`rbrother` | Return the right brother of the given node. However, hence the nodes may be displayed in the order given by the special FS-format numbering attribute `@N`, the returned node need not necessarily be displayed to the right of the given node. This is because the ordering according to the special numbering attribute does not have to correspond to the deep-first structure ordering of the tree.
`lbrother` | Return the left brother of the given node. However, as for the right brother, hence the nodes may be displayed in the order given by the special FS-format numbering attribute `@N`, the returned node need not necessarily be displayed to the left of the given node. This is because the ordering according to the special numbering attribute does not have to correspond to the deep-first structure ordering of the tree.
`following(`top`?)` | Return the next node of the given node in the natural ordering of the tree provided by the tree structure. E.g. if the given node has a child, this child is returned. If the node has no childs but does have a right brother, `Treex::PML::Node` reference to the right brother is returned. If no child and no right brother exists for the given node, the method looks for a right brother of its nearest ancestor, etc. Starting from the root of the tree and calling this method repeatedly on the returned nodes ensures that all the nodes in the trees are accessed during the procedure. If the optional argument `top` contains a `Treex::PML::Node` reference, the searching is limited to the subtree governed by the node of `top`.
`previous(`top`?)` | Return the previous node of the given node in the deep-first ordering of the tree provided by the tree structure (see the above description of the `following` method for more detail on the ordering). If the optional argument `top` contains a `Treex::PML::Node` reference, the searching is limited to the subtree governed by the node of `top`.
`children` | Return a list of all child-nodes of the given node. The nodes in the list are ordered in their structural order starting from the first son of their parent, each node followed by its right brother.

#### 15.7.4. Accessing other trees

For this purpose many default macros exist and we recommend read their documentation first (see Section 15.8, “Public API: pre-defined macros”). In this section we describe more low-level approach that utilizes one of the most fundamental internal structures used by TrEd, namely the “grouping” structure. This structure may be accessed using the `$grp` variable. There is really a lot of things that can be achieved by using this variable in a proper way, but because it is an open gate to TrEd internals, it may also be dangerous. Here, we only pay our attention to a few of the safe features of `$grp`. In most cases, using wrappers over this structure provided by default macros, is still a much safer option.

The current file is accessed via the `CurrentFile()` reference. This reference is a pointer to an object of the `Treex::PML::Document` class. The following methods are provided for the class:

Table 5. `Treex::PML::Document` class methods

Method name | Description
--- | ---
`filename` | Returns current file's name.
`changeFilename(`name`)` | Change current file's name.
`FS` | Return a reference to an associated `Treex::PML::FSFormat` object.
`trees` | Return a list of all trees (i.e. a list of `Treex::PML::Node` object references pointing to the roots of the trees).
`hint` | Return the TrEd's hint pattern associated with the file.
`changeHint(`pattern`)` | Change the TrEd's hint pattern associated with the file.
`pattern(`n`)` | Return the `n`'th attribute pattern associated with the file.
`patterns` | Return a list of all attribute patterns associated with the file.
`pattern_count` | Return the number of display attribute patterns associated with the file.
`changePatterns(`patterns`)` | Change the list of attribute patterns associated with the file.

Actually, some other `Treex::PML::Document` methods exist, but as they are not intended to be used from the macros directly, there is no reason to describe them here.

The most important of the methods above is the `FS` method which may be used to access the `Treex::PML::FSFormat` class object associated with the given file. Similarly as in the case of `Treex::PML::Document` class, only the most importand methods of the `Treex::PML::FSFormat` class are described here.

Table 6. `Treex::PML::FSFormat` class methods

Method name | Description
--- | ---
`order` | Return the name of the special numerical FS attribute responsible for providing the tree order. This attribute is declared in the FS file as `@N`.
`sentord` | Return the name of the special numerical FS attribute responsible for providing the order of the values to form a “sentence”. This attribute is declared in the FS file as `@W`.
`value` | Return the name of the special FS attribute providing a descriptive value of the node used when forming a “sentence”. This attribute is declared in the FS file as `@V`.
`hide` | Return the name of the special FS attribute which can be used for hiding subtrees. This attribute is declared in the FS file as `@H`; a subtree is hidden if its governing node's value for this attribute is `'hide'` or `1`.
`isHidden(`node`)` | Return true if the given `Treex::PML::Node` `node` belongs to a hidden subtree.
`isList(`attr`)` | Return true if the given attribute is of list type with a strictly defined set of possible values. This type of attributes is declared by the `@L` header in the FS format.
`listValues(`attr`)` | Return a list of all possible values for the given attribute `attr`. Empty list is retured in case the attribute is not of the list type.
`color(`attr`)` | Return one of the `Shadow`, `Hilite`, `XHilite` and `normal` values, depending on the color specified in the FS file header. See also UseFSColors configuration option.
`attributes` | Return a list containing names of all the attributes declared in the FS file header.
`atno(`n`)` | Return name of the `n`'th attribute.
`indexOf(`attr`)` | Return index of the attribute named `attr`, according to the order in which attributes are defined in the FS file.
`count` | Return the number of attributes defined in the FS file.
`exists(`attr`)` | Return true if attribute named `attr` exists for the FS file. If it is not the case, false (i.e. zero) is returned.

`make_sentence(`root_node`)`

Return a string forming a “sentence” for the given node's subtree. The sentence is formed in the following way:

1. All the nodes of the `root_node` node's subtree and ordered according to their values for the special numerical FS sentence ordering attribute (see method `sentord` above). The special FS numbering attribute (see method `order` above) is used if no sentence ordering attribute is declared in the FS file.

2. For every such node, its descriptive value (see method `value` above) is taken.

3. The values obtained in this way and order are joined into a single string with fields separated by the value of `separator`.

The methods `sentord`, `order`, `value`, and `hide` described above are useful especially in macros of general purposes, where names of the corresponding attributes are not known in advance

### Note

In PML there is no equivalent of `sentord`, `value` and `hide`. Nodes associated with a PML type implement the methods `$node->get_ordering_member_name()` and `$node->get_order()` to get the name and value of their ordering attribute (i.e. associated with PML role #ORDER).

### Note

Calling the FSFormat methods `sentord`, `order`, `value`, and `hide` (as well as Node methods `get_order` and `get_ordering_member_name` too many times (e.g. in a sort or map operations on a set of nodes) may result in bad performence, so it is recommended to store their return values in local variables. Here is an example:

      my $ord    = FS()->sentord or FS()->order;
      my $value  = FS()->value;
      return join( ' ',
    	       map { $_->{$value} }
    	       sort { $a->{$ord} <=> $b->{$ord} } GetDisplayedNodes() );

If the values of `value`, `sentord` or possibly `order` were evaluated each time the Perl `sort` or `map` function needs to compare or map nodes, the performance of the code would considerably decrease.

### 15.8. Public API: pre-defined macros

The role of a public API available to macros is played by a set of macros defined in the `TredMacro` package in the file named `tred.def`. Most of these pre-defined macros are just safe wrappers for TrEd internal function calls. Pre-defined macros and object methods (namely those of `Treex::PML::Node`, `Treex::PML::Document` and `Treex::PML::FSFormat` should be the only access points used by a macro to interact with TrEd. All other ways of creeping into TrEd's internals are dangerous and should be avoided.

#### 15.8.1. Global variables

`$this`

  Current node (i.e. the active node in TrEd and the node in turn if `-N` or `-H` flag was used in bTrEd). Assigning a different node from the current tree to this variable results in changing the active node in TrEd and continuing processing at that node in bTrEd.

`$root`

  Root of the current tree. If possible, avoid changing this variable in a macro, so that called macros may rely on its value too.

`$FileChanged` (alias `$FileNotSaved` - still valid but obsolete)

  See also `ChangingFile()`.

  If this variable is set to 1, TrEd/bTrEd considers the current file to be modified and in case of bTrEd makes the program to save it before it is closed (in case of TrEd, user is prompted before the file is closed). If the macro does not change this variable, bTrEd does not change the file status, while TrEd still assumes that the file was modified. In other words, set this variable to 1 in bTrEd if you want the file to be saved at last, and set this variable to 0 in TrEd if you are sure you did not make any change to the file that would be worth saving it. As there is a danger that calling one macro from another may result in a mess in the value of `$FileChanged` it is adviced to use the default macro `ChangingFile()` which tries to set the file status only if really intended (see below).

`$Redraw`

  This variable makes sense only in TrEd. You may set it to one of `file`, `tree`, `win`, `all`, `tie` to alter the mechanism of redrawing the screen. The default value is `file` (redraw all windows displaying current file), while `tree` means redraw all windows displaying current tree, `win` means redraw only current window and `tie` means redraw all if windows are tied or (if not) redraw only current window. To disable redrawing set this variable to `none`.

`$forceFileSaved`

  In TrEd, you may wish to set this variable to 0 if you wish to change the status of the file to `saved` (e.g. after saving the file from your macro).

`$libDir`

  This variable contains a path to TrEd library directory.

#### 15.8.2. Navigation

Methods of Treex::PML::Node objects should be used for basic navigation within trees. Here are described means to navigate from one tree to another and a few extra macros for specific navigation in trees.

`GotoTree(n)`

  Display the n'th tree in the current file. The number of the first tree for this function is 1.

`TieGotoTree(n)`

  Go to n'th tree in all tied windows. The number of the first tree for this function is 1.

`TieNextTree()`

  Display the next tree in all tied windows.

`TiePrevTree()`

  Display the previous tree in all tied windows.

`NextTree()`

  Display the next tree in the current file.

`PrevTree()`

  Display the previous tree in the current file.

`GetTrees()`

  Return a list of trees in current Treex::PML::Document. Equivallent to `CurrentFile()->trees`.

`GetSecondaryFiles($fsfile?)`

  Return a list of secondary Treex::PML::Document objects for the given (or current) file. A secondary file is a file required by a file to be loaded along with it; this is typical for files containing some form of a stand-off annotation where one tree is built upon another. Note however, that this does not include so called knitting - an operation where the stand-off annotation is handled by a IO backend and the resulting knitted file appears to btred as a single unit. Only those secondary files that are already open are returned.

`NextNode(node,top?)`

  Return the first displayed node following the given node in the subtree of top. This function behaves in the same manner as the node->following(top) method, except it works only on the nodes which are actually visible according to the state of the View->Show Hidden Nodes menu item.

`PrevNode(node,top?)`

  Return the first displayed node preceding the given node in the subtree of top. This function behaves in the same manner as the node->previous(top) method, except it works only on the nodes which are actually visible according to the state of the View->Show Hidden Nodes menu item.

`NextVisibleNode(node,top?)`

  Return the first visible node following the given node in the subtree of top. This function behaves in the same manner as the `$node->following($top)` method, except that nodes of hidden subtrees are skipped.

`PrevVisibleNode(node,top?)`

  Return the first visible node preceding the given node in the subtree of top. This function behaves in the same manner as the `$node->previous($top)` method, except that nodes of hidden subtrees are skipped.

`IsHidden(node)`

  Return true if the given node is member of a hidden subtree. This macro is only an abbreviation for `FS()->isHidden(node)`

`Hide(node)`

  Hide a given node.

`GetNodes(top?)`

  Get a list of all nodes in the current tree or (if top is given) in the subtree of top (the root of the tree is icluded as well). The list returned is ordered in the depth-first ordering. (This function automatically returns array reference in scalar context.)

`GetVisibleNodes(top?)`

  Return the list of all visible nodes in the subtree of the given top node (or the whole current tree if no top is given). The list returned is ordered in the depth-first ordering and all members of hidden subtrees are skipped.

`GetDisplayedNodes($win?)`

  Return the list of all nodes actually currently displayed in the current window in TrEd (which nodes are actually displayed can be e.g. specified with get_nodelist_hook).

`PrevNodeLinear(node,attribute,top?)`

  Returns nearest node in the tree preceding the given node in linear ordering provided by the given attribute. If top node is present, only a subtree of top is examined.

`NextNodeLinear(node,attribute,top?)`

  Returns nearest node in the tree following the given node in linear ordering provided by the given attribute. If top node is present, only a subtree of top is examined.

`CurrentTreeNumber( $win? )`

  Return current tree number. Note that the number of the first tree if file reported by this function is 0, so you have to add 1 before passing the number to functions like GotoTree. If used in TrEd, optional argument win can be used to specify TrEd window (defaults to the current window).

`GetNodeIndex()`

  Return given node's position in the deep-first tree ordering.

`LocateNode(node?,fsfile?)`

  Return current filename, index of a tree (starting from 1) in the file to which the node belongs (0 if not found) and node's position in the tree in the deep-first tree ordering.

  If `node` is not given, `$this` is assumed. Should the node be from a different file than the current one, the second argument must specify the corresponding Treex::PML::Document object.

`ThisAddress(node?,fsfile?)`

  Return a given node's address string in a form of filename#tree_no.index (tree_no starts from 1 to reflect TrEd's UI convention). If the correct tree number could not be determined (the node does not belong to any top-level tree in the file) and the node has an ID, the address is returned in the form filename#ID.

  If `node` is not given, `$this` is assumed. Should the node be from a different file than the current one, the second argument must specify the corresponding Treex::PML::Document object.

`ThisAddressNTRED(node?,fsfile?)`

  Return a given node's address string in a form of ntred://filename@tree_no#1.index (tree_no starts from 1 to reflect TrEd's UI convention). If the correct tree number could not be determined (the node does not belong to any top-level tree in the file) and the node has an ID, the address is returned in the form ntred://filename#ID.

  The returned address may be opened in TrEd to examine the tree in memory of a remote btred server.

  If `node` is not given, `$this` is assumed. Should the node be from a different file than the current one, the second argument must specify the corresponding Treex::PML::Document object.

`FPosition(node?,fsfile?)`

  Prints the result of `ThisAddress` on stdout.

`NPosition(node?,fsfile?)`

  Prints the result of `ThisAddressNTRED` on stdout.

`ParseNodeAddress(address)`

  Split given address into a filename/URL and a suffix and return these as a two element list.

#### 15.8.3. Tree editing API

`CutPaste(node,new-parent)`

  Cut given node (including its subtree) and paste it to a new parent. This macro is safer than PasteNode since it checks that new-parent is not a descendant of node or node itself. If the check fails, the macro dies with an error before any change is made.

  Note: this macro does not verify node types. Use `$parent->test_child_type($node)` to be sure that type declarations permit the node as a child node of the new parent.

`CutPasteBefore(node,ref_node)`

  Cut given node (including its subtree) nd paste it on ref_node's parent node just before ref_node. This macro is safer than PasteNodeBefore since it checks that new-parent is not a descendant of node or node itself. This macro dies on error before any change is made.

  Note: this macro does not verify node types. Use `$parent->test_child_type($node)` to be sure that type declarations permit the node as a child node of the new parent.

`CutPasteAfter(node,ref_node)`

  Cut given node (including its subtree) and paste it on ref_node's parent node just after ref_node. This macro is safer than PasteNodeBefore since it checks that new-parent is not a descendant of node or node itself. This macro dies on error before any change is made.

  Note: this macro does not verify node types. Use `$parent->test_child_type($node)` to be sure that type declarations permit the node as a child node of the new parent.

`PasteNode(node,new-parent)`

  Paste the subtree of the node under the new-parent. The root of the subtree is placed among other children of new-parent with respect to the numbering attribute.

  Note: this macro does not verify node types. Use `$parent->test_child_type($node)` to be sure that type declarations permit the node as a child node of the new parent.

`PasteNodeBefore(node,ref_node)`

  Cut given node (including its subtree) and paste it on ref_node's parent node just before ref_node.

  Note: this macro does not verify node types. Use `$parent->test_child_type($node)` to be sure that type declarations permit the node as a child node of the new parent.

`PasteNodeAfter(node,ref_node)`

  Cut given node (including its subtree) and paste it on ref_node's parent node just after ref_node.

  Note: this macro does not verify node types. Use `$parent->test_child_type($node)` to be sure that type declarations permit the node as a child node of the new parent.

`CloneSubtree(node)`

  Return an identical copy (except that only declared attributes are preserved) of the given subtree.

`CopyNode(node)`

  Return an identical copy (except that only declared attributes are preserved) of the given node. The input node must belong to the current file.

`CutNode(node)`

  Cut the node's subtree off the tree and return it. By cuttin a subtree we mean disconnecting it from the rest of the tree. Use PasteNode to attach it to some node again.

`NewTree()`

  Create a new tree before the current tree. The new tree consists of exactly one node. This node is activated and a reference to its Treex::PML::Node object is returned.

`NewTreeAfter()`

  Create a new tree after the current tree. The new tree consists of exactly one node. This node is activated and a reference to its Treex::PML::Node object is returned.

`NewRBrother(node)`

  Create a new brother of the given node and recalculate the special FS numbering attribute values in the whole tree so that the new node is the first right sibling of the given node.

  If no node is given, this function operates on `$this` and resets `$this` to the newly created node. If some node is given the value of `$this` is preserved.

`NewLBrother(node)`

  Create a new brother of the given node and recalculate the special FS numbering attribute values in the whole tree so that the new node is the first left sibling of the given node.

  If no node is given, this function operates on `$this` and resets `$this` to the newly created node. If some node is given the value of `$this` is preserved.

`NewSon(parent)`

  Create a new child of the given parent node and recalculate the special FS numbering attribute values in the whole tree so that the new node is the first node right to the given parent.

  If no parent node is given, this function operates on `$this` and resets `$this` to the newly created node. If a parent node is given the value of `$this` is preserved.

`NewParent(node)`

  Create a node between given node and its parent and recalculate the special FS numbering attribute values in the whole tree so that the new node is the first node left to the given node.

  If no node is given, this function operates on `$this` and resets `$this` to the newly created node. If a parent node is given the value of `$this` is preserved.

`DeleteThisNode()`

  Delete the current (`$this`) node and recalculate the special FS numbering attribute values in the whole tree so that there is no gap in the numbering. If the current node is not a leaf or if it is the root of the current tree, this macro does nothing.

`DeleteLeafNode(node)`

  Delete a leaf node and recalculate the special FS numbering attribute values in the whole tree so that there is no gap in the numbering. If a given node is not a leaf, this macro does nothing.

`DeleteSubtree(node)`

  Deletes a whole node's subtree and recalculate the special FS numbering attribute values in the whole tree so that there is no gap in the numbering.

`RemoveTree(n?,fsfile?)`

  Removes n-th tree from a given Treex::PML::Document (trees are numbered starting from 0). If no Treex::PML::Document is specified, uses the current file (see CurrentFile()).

  Calling RemoveTree() without arguments, it is equivalent to

  RemoveTree(CurrentTreeNumber(),CurrentFile())

  Returns the deleted tree. If you do not reattatch the tree to the Treex::PML::Document, use $tree->destroy method on the returned tree to prevent a memory leak.

`DestroyTree(n?,fsfile?)`

  Like RemoveTree but immediatelly destroys the removed tree. Returns 1 on success.

`DetermineNodeType($node)`

  For trees with Treex::PML::Schema-based node typing, try to determine the type of the node from the type of its parent, and associate the node with the type (using $node->set_type). If there are more possibilities, the user is asked to choose the correct type.

`CopyValues()`

  Copy the values of all the attributes except the special FS numbering attribute of the current node to a global hash variable named %ValuesClipboard.

`PasteValues()`

  Replace existing values of the current node's attributes by all values stored in the global hash variable named %ValuesClipboard. The function does not perform any node-type validity checks.

`PlainNewSon(parent)`

  Add a new child node to the given parent and make it the current node (by setting `$this` to point to it).

`PlainDeleteNode()`

  Delete the given node. The node must be a leaf of the tree (may not have any children) and must have a parent (may not be the root of the tree).

`PlainDeleteSubtree(node)`

  Cut a the given node's subtree and destroy all its nodes. This macro does not recalculate ordering attributes.

`NormalizeOrds(listref)`

  Adjusts the special FS numbering attribute of every node of the list referenced by the listref argument so that the value for the attribute corresponds to the order of the node in the list and repaste each node so that the structural order corresponds with this new numbering.

  If no numbering FS numbering attribute is available, all this macro does is to ensure that the structural order of sibling nodes corresponds to their order in the given list.

`SortByOrd(listref)`

  Sort the list of nodes referenced by the listref argumnt according to the values of the special FS numbering attribute.

`RepasteNode(node)`

  Cut the given node and paste it immediately on the same parent so that its structural position between its parent children is brought to correspondence with the values of the special FS numbering attribute.

`ShiftNodeRightSkipHidden(node)`

  Shift the current node in the tree to the right leaping over all hidden subtress by modifying the tree structure and value of the special FS numbering attribute appropriately.

`ShiftNodeLeftSkipHidden(node,min?)`

  Shift the current node in the tree to the left leaping over all hidden subtress by modifying the tree structure and value of the special FS numbering attribute appropriately. The optional argument min may be used to specify the minimum left boundary for the value of the ordering attribute of node.

`ShiftNodeRight(node)`

  Shift the current node in the tree to the right by modifying the tree structure and value of the special FS numbering attribute accordingly.

`ShiftNodeLeft(node)`

  Shift the current node in the tree to the right by modifying the tree structure and value of the special FS numbering attribute appropriately.

`GetNodesExceptSubtree(node)`

  Returns the reference to an array containing the whole tree except the nodes strictly in the subtrees of nodes given in an array referenced by the parameter. (The returned array does contain the nodes passed in the parameter.)

`MoveNode(source-node,target-node)`

  Move the node specified by the first parameter after the node specified by the second parameter in the ordering on nodes.

`MoveSubtree(source-node,target-node)`

  Move the subtree of the node specified by the first parameter after the node specified by the second parameter in the ordering on nodes. The subtree of the first argument is made contiguous in the ordering on nodes, if it happens not to be so. (We use the fact that the technical root node is always first in the ordering.)

#### 15.8.4. Helper macros for attributes with list or alternatives of values

`CloneValue(value)`

  Return an identical deep copy of a given scalar. Useful for copying attribute values (and any value below them), including structured attributes, lists or alternatives.

  Warning: do not apply this macro to an entire Treex::PML::Node since otherwise you might result with a copy of the complete tree, schema, etc.

`IsList(value)`

  Check that a given value is a list, i.e. Treex::PML::List object.

`IsAlt(value)`

  Check that a given value is an alternative, i.e. Treex::PML::Alt object.

`IsSeq(value)`

  Check that a given value is a sequence, i.e. Treex::PML::Seq object.

`List(value,value,...)`

  Return a new list (Treex::PML::List object) populated with given values.

`Alt(value,value,...)`

  Return a new alternative (Treex::PML::Alt object) populated with given values.

`AltV(value)`

  If the value is an alternative (i.e. a Treex::PML::Alt object), return all its values. Otherwise return value.

`ListV(value)`

  If the value is a list (i.e. a Treex::PML::List object), return all its values. Otherwise return empty (Perl) list.

`SeqV(value)`

  If the value is a sequence (i.e. a Treex::PML::Seq object), return all its elements (Treex::PML::Seq::Element objects). Otherwise return empty (Perl) list.

`AddToAlt(node,attr,value,value...)`

  Add given values as alternatives to the current value of `$node->{$attr}`. If only one value is given and `$node->{$attr}` is empty or same as value, the given value is simply assigned to it. If `$node->{$attr}` is a Treex::PML::Alt object, the new values are simply added to it. Otherwise, if `$node->{$attr}` is a simple value, `$node->{$attr}` is set to a new Treex::PML::Alt object containing the original value as well as the given values.

`AddToList(node,attr,value,value,...)`

  Add values to a given attribute. If `$node->attr($attr)` is not defined or empty, a new Treex::PML::List containing given values is created. If `$node->attr($attr)` is a Treex::PML::List object, given values are simply added to it. Error is issued if `$node->attr($attr)` is defined, non-empty, yet not a Treex::PML::List object.

`AddToListUniq(node,attr,value,value,...)`

  Add values to a given attribute, unless already present among the current values. If `$node->attr($attr)` is not defined or empty, a new Treex::PML::List containing given values is created. If `$node->attr($attr)` is a Treex::PML::List object, given values are simply added to it. Error is issued if `$node->attr($attr)` is defined, non-empty, yet not a Treex::PML::List object.

`AddToSeq(node, attr, name =` value, name => value,...)> or `AddToSeq(node, attr, element, ...)`

  Add elements to a given sequence attribute. If `$node->attr($attr)` is not defined or empty, a new Treex::PML::Seq object containing given name-value pairs (Treex::PML::Seq::Element objects) is created. If `$node->attr($attr)` is a Treex::PML::Seq object, given elements are simply added to it. Error is issued if `$node->attr($attr)` is defined, non-empty, yet not a Treex::PML::Seq object.

#### 15.8.5. General-purpose list functions

`Index(array-ref,item)`

  A helper function which returns the index of the first occurence of a given item in an array. Returns nothing (empty list) if the item is not found. Note: 'eq' is used for comparison.

`ListIntersect(array-ref,array-ref,...)`

  Compute intersection of given lists. In scalar context returns an array-ref, in list context returns a list. All duplicities are removed.

`ListSubtract(array-ref, array-ref)`

  Return elements occuring in the first list but not in the second list. In scalar context returns a Treex::PML::List object (array-ref), in list context returns a list. All duplicities are removed.

`ListUnion(array-ref, array-ref, ...)`

  Return union of given lists. In scalar context returns an array-ref, in list context returns a Treex::PML::List object (array-ref). All duplicities are removed.

`ListRegroupElements(array-ref, array-ref, ...)`

  This is rotate-matrix like operation. The input is a list of rows (array-refs each representing a row in a matrix); the output is a list of columns in the matrix (a list of array-refs, each representing a column in the matrix).

#### 15.8.6. GUI-related macros

`GUI()`

  Return a reference if running from TrEd, i.e., GUI is available; otherwise return `undef`. If running from TrEd the returned value is a TrEd::Window object representing the currently focused window.

`CloseGUI()`

  This macro is only available in TrEd. It closes TrEd's main window and exits.

`TrEdWindows()`

  Return a list of TrEd::Window objects representing current TrEd windows.

`CurrentWindow()`

  Return a TrEd::Window object representing the currently focused window.

`SetCurrentWindow(win)`

  Focus a given window.

`SplitWindowHorizontally(\%opts?)`

  Split current window horizontally. Returns an object represening the newly created window.

  An optional HASHref with the following options can be passed as an argument:

  no_focus => 0|1

    do not focus the new view (default value is 1)

  no_init => 0|1

    do not initialize the new view with the file, context, etc. from the current vie (default value is 0)

  no_redraw => 0|1

    do not redraw the new view

  ratio => float

    A float value between 0 and 1 indicating the ratio of the height of the new view to the current height of the active view.

`SplitWindowVertically()`

  Split current window horizontally. Returns an object represening the newly created window.

  An optional HASHref with the following options can be passed as an argument:

  no_focus => 0|1

    do not focus the new view (default value is 1)

  no_init => 0|1

    do not initialize the new view with the file, context, etc. from the current vie (default value is 0)

  no_redraw => 0|1

    do not redraw the new view

  ratio => float

    A float value between 0 and 1 indicating the ratio of the height of the new view to the current height of the active view.

`CloseWindow(win?)`

  Close a given window, unless it is the last window that exists. If no window is given as an argument, try closing the current window. If the closed window was focused, then a next sibling window gets focus.

`CurrentFile(win?)`

  Return a Treex::PML::Document object representing the file currently open in a given TrEd window or in the currently focused window if called without arguments.

`CurrentNodeInOtherWindow(win)`

  Return the node currently active in a given window.

`SetCurrentNodeInOtherWindow(win,node)`

  Set active node for a given window.

`InVerticalMode()`

  Return true if the tree is currently displayed in the vertical mode.

`ToplevelFrame()`

  Returns the Tk::Toplevel object containing the current window.

`PrintDialog(...)`

  See the description in the Printing trees section.

`Redraw($win?.$ignoreThis)`

  Force TrEd to immediately redraw the current (or given) window. Hence TrEd redraws the tree right after an interactively invoked macro finishes, explicit calls to Redraw macro are needed rather rearly (for example from a hook). If the flag $ignoreThis is used, then current value of $this variable will not be used to determine the current node of the window (i.e. $win->{currentNode}).

`Redraw_FSFile()`

  Force TrEd to immediately redraw all windows displaying current file.

`Redraw_FSFile_Tree()`

  Force TrEd to immediately redraw all windows displaying current tree.

`Redraw_All()`

  Force TrEd to immediately redraw all windows.

`RedrawStatusLine()`

  Force TrEd to immediately redraw status line.

`EditAttribute(node,attribute)`

  Open edit attribute GUI.

`Undo()`

  Act as if the user pressed the undo button. Note that this macro also changes $this and $root (since undo replaces the current tree with an in-memory copy).

  WARNING: Be aware that calling Undo() from a hook may conflict with some macros, more specifically, with macros triggering such a hook (indirectly, i.e. via some API call). In a case, changes to $this and $root caused by Undo() do not propagate to the macro, which in turn ends up working with incorrect (already replaced) nodes. Thus, if calling Undo() within a hook, make sure to reset $this from $grp->{currentNode} and $root from $this->root after all calls from your macros which may possibly invoke the hook.

`Redo()`

  Act as if the user pressed the undo button. Note that this macro also changes $this and $root.

`SaveUndo(comment)`

  Save a snapshot of the current tree so that following operations on it can be reverted with Undo. The `comment` argument should provide user-visible one-line diescription of the action following SaveUndo.

`ForgetRedo()`

  Disable redo. This is useful if you programmatically Undo user's action and do not want the user to be able to redo the action with Redo.

`Find()`

  Open the Find Node by Attributes GUI dialog.

`FindNext()`

  Searches for the first node matching the criteria of the previous use of the Find... menu command or FindNode macro usage.

`FindPrev()`

  Searches for the previous node matching the criteria of the previous use of the Find... menu command or FindNode macro usage.

`ErrorMessage(message)`

  In TrEd, show a dialog box containing the given error-message in a text window. In BTrEd print the error message on standard error output.

`InfoMessage(message)`

  In TrEd, show a dialog box containing the given info-message in a text window. In BTrEd print the message on standard output.

`StandardTredFont()`

  Return a string or Tk::Font object representation of the font used in TrEd to label tree-nodes.

`StandardTredValueLineFont()`

  Return a string or Tk::Font object representation of the font used in TrEd to display the "sentence" above the tree.

`CenterOtherWinTo(win,node)`

  Center given window to a given node.

`HiddenVisible(win?)`

  Return true if TrEd displays hidden nodes in a given window (or the currently focused window if called without an argument).

`ToggleHiding($win?)`

  If TrEd displays hidden nodes (or the currently focused window if called without an argument), hide them and vice versa.

#### 15.8.7. Create/modify keyboard shortcuts

`Bind( macro => bind-options,...)`

  This macro can be used to dynamically create keyboard bindings and menu items for user-defined macros in TrEd. The arguments consist of one or more (macro => bind-options ) pairs where macro is a subroutine name or a CODE reference and bind-options is either a keyboard shortcut (e.g. 'Ctrl+a') or a HASH references with the following keys and values (all optional):

  context

    the binding context, e.g. the package in which context the macro is evaluated. Only relevant if the macro is specified by name. If not given, the caller package is used.

  key

    a keyboard binding for the macro (e.g. 'Ctrl+a'); if not given, no keyboard binding is created.

  menu

    a label to be used for a menu-item created for the macro. If not given, no menu-item is created for the macro.

  changing_file

    if the key `changing_file` exists in the bind-options hash and its value is value, a call to the macro `ChangignFile(value)` is made immediatelly after each invocation of the macro via this binding.

`UnbindBuiltin(key-binding)`

  (TrEd only). Remove default TrEd's keybinding for a given key so that custom macro can be bound to that key. E.g. UnbindBuiltin('Ctrl+Home'); Note: use with care. Built-in key-bining once removed cannot be restored (except by restarting TrEd).

`OverrideBuiltinBinding(context,key-binding, binding_spec )`

  (TrEd only). Get or modify default TrEd's keybinding.

  The `binding_spec` argument, if given, must be an array reference with two elements:

  [ sub { ... }, 'description' ]

  WARNING: You have to be very careful when overriding a builtin binding, since your code is not called as a macro or a hook! The routine is called with the following three arguments:

  $tk_window, $grp->{framegroup}, $key

  You may obtain $grp from the second argument using $_[1]->{currentWindow}. You should probably call Tk->break at the end of your code, so that the event does not propagate. There is no `$root` or `$this` available within the callback.

  A safer way (with slower execution, though) is to use a macro wrapped into a MacroCallback() instead of a sub:

  [ MacroCallback(...), 'description' ]

  See `MacroCallback` macro for details. The macro is called with the same arguments (appended to a list of arguments provided in `MacroCallback`). The macro can use all standard macro functions and variables.

  If the `context` argument is a name of a binding context, the binding is only used in the specific context. If `context` is `'*'`, the binding applies to all contexts (except for contexts that specifically overrid it).

  If called without a binding_spec, the current binding_spec is returned, otherwise the previous binding_spec is returned.

  Example (swaps the behavior of normal `left/right` with `Shift+left/right`)

  my @keys = qw(Left Right);
  my %normal = map { $_ => OverrideBuiltinBinding('*',$_) } @keys;
  my %shift = map { $_ => OverrideBuiltinBinding('*',"Shift+$_") } @keys;
  for (@keys) {
  OverrideBuiltinBinding(__PACKAGE__, $_, $shift{$_});
  OverrideBuiltinBinding(__PACKAGE__, "Shift+$_", $normal{$_});
  }

  Here is another example that changes the Up arrow to move to the grand-parent instead of a parent:

  # Using TrEd internals (faster, but prone to changes in the internal API):
  OverrideBuiltinBinding(
  __PACKAGE__,
  'Up',
  [sub { main::currentUp($_[1]) for 1..2 },
  'Move to grand-parent']);
  # Using a macro (slower):
  OverrideBuiltinBinding(
  __PACKAGE__,
  "Up",
  [MacroCallback(sub { $this=$this->parent; $this=$this->parent if $this }),
  'Move to grand-parent']);

`MacroCallback(macro_spec,@args)`

  This macro can be used to safely wrap a given macro into a code that can be used to override a TrEd builtin or passed as a callback to a Tk widget.

  The first argument can take one of the following forms:

  String:
  "macro_name" or "Package->macro_name"
  Anonymous subrutine:
  sub { ...code... }
  Hash reference:
  { -command => sub { ...code... },
  -changing_file => 0 | 1,
  -contex => 'PackageName'
  }
  Array reference:
  [ sub { ..code ...}, arg1, arg2, ...]

  The macro is called with the arguments provided in the macro_spec, followed by the arguments provided in the call to MacroCallback, followed by arguments passed by the caller (e.g. TrEd or the Tk widget).

#### 15.8.8. Stylesheet API

`STYLESHEET_FROM_FILE()`

  This function returns a symbolic name for a virtual stylesheet that is constructed from the patterns and hint specified in the currently displayed file.

`SetStylesheetPatterns(patterns,stylesheet,create)`

  Set TrEd's display patterns for a given stylesheet. If stylesheet is undefined, then the stylesheet currently selected for the active view is used. The patterns argument should either be a string or an array reference. If it is a string, then it should provide all the patterns, each pattern starting on a new line (but possibly spanning across several lines) which starts with a pattern prefix of the form "something:", where "something" is hint for the hint pattern, or "node" for the node pattern, etc.

  Patterns can also be provided as an array reference containing three elements: the first one being a hint text, the second the context pattern (regular expression), and the second one an array reference whose each element is the text of an individual pattern.

  The create flag can be set to 1 in order to create a new stylesheet in case that no stylesheet with the given exists.

  This function returns 1 if success, 0 if failed (i.e. when create is not set and a given stylesheet is not found).

`DeleteStylesheet(stylesheet)`

  Delete given stylesheet. All windows using that stylesheet are switched to the pattern and hint specified in the respective files they display.

`SaveStylesheet(name)`

  Save given TrEd's stylesheet (to ~/.tred.d/stylesheets/name).

`SaveStylesheets()`

  Save all TrEd's stylesheets (to ~/.tred.d/stylesheets/).

`ReloadStylesheet(name,dir?)`

  Reload a given stylesheet. If no dir is specified, the default path "~/.tred.d/stylesheets/" is used.

`ReloadStylesheets(dir?)`

  Reload stylesheets from a given file or directory. If no filename is specified, the default path "~/.tred.d/stylesheets/" is used.

`GetStylesheetPatterns(stylesheet)`

  For a given stylesheet, return it's patterns. In a scalar context, returns a string consisting of all patterns, including the hint. In the array context returns three scalars: the first one containing the text of the hint pattern, the second the context pattern (regexp) and the other a reference to a list containing the stylesheet patterns. Returns empty list in case of failure.

`GetPatternsByPrefix(prefix,stylesheet?)`

  Return all patterns of a given stylesheet starting with a given prefix. If no stylesheet name is given, a current stylesheet is used.

`StylesheetExists(stylesheet)`

  Returns true if stylesheet with a given name exists.

`Stylesheets()`

  Returns a list of TrEd's stylesheet names.

`GetCurrentStylesheet()`

  Returns name of the stylesheet currently selected for the active window.

`SetCurrentStylesheet(stylesheet_name)`

  Set stylesheet for the active window.

`GetSpecialPattern(prefix)` - OBSOLETE!!

  This macro is obsoleted by GetPatternsByPrefix.

`SetDisplayAttrs(pattern,...)` - OBSOLETE!!

  Setup given patterns as a stylesheet of the currently displayed Treex::PML::Document. This does not include a hint pattern.

`SetBalloonPattern(string,...)` - OBSOLETE!!

  Use given strings as a `hint:` pattern for the currently displayed Treex::PML::Document.

`GetDisplayAttrs()` - OBSOLETE!!

  Get patterns of the currently displayed Treex::PML::Document's stylesheet, except for a `hint:` pattern.

`GetBalloonPattern()` - OBSOLETE!!

  Get a `hint:` pattern of the currently displayed Treex::PML::Document's stylesheet.

`CustomColor(name,new-value?)`

  Get or set user defined custom color.

`UserConf(name,new-value?)`

  Get or set value of a user defined configuration option.

`AddStyle(styles,object,key => value,...)`

  Auxiliary funcion: add styles for an object to a given style-hash (can be used e.g. from node_style_hook).

`GetStyles(styles,object,$feature?)`

  Auxiliary funcion: if feature is given, retrieves and returns a feature of a particular object from the given style-hash. If feature is not given or undef, returns a (flat) list of feature => value pairs consisting of the style features of a given type of object obtained from the style-hash.

  This function can be used e.g. from node_style_hook.

#### 15.8.9. Context API

`CurrentContext()`

  Return the name of the current macro context.

`SwitchContext(context)`

  Switch to given macro context.

`CurrentContextForWindow(win)`

  Get a macro context currently selected in a given window.

`SwitchContextForWindow(win,context)`

  Switch given window to given macro context.

#### 15.8.10. Treex::PML::FSFormat API

Here are described for working with Treex::PML::FSFormat objects. Beside these macros, Treex::PML::FSFormat object methods can be used.

`FS()`

  Return Treex::PML::FSFormat object associated with the current Treex::PML::Document.

`GetOrd(node)`

  Return value of the special numbering FS attribute. This macro actually returns the same value as `$node->{FS()->order()}`

`Attributes(node?,normal_fields?)`

  If no node is given or the node is not associated with a type, return a list of names of all attributes declared in the FS-file header or Schema.

  If node is associated with a type and the 2nd attribute is undef or false, return list of paths to all its (possibly nested) atomic-value attributes. This is equivalent to

  $node->type->schema->attributes($node->type)

  If node is associated with a type and the 2nd attribute is true, return only first-level attribute names. This is equivalent to

  $node->type->get_normal_fields()

`SubstituteFSHeader(declarations)`

  Substitute a new FS header for current document. A list of valid FS declarations must be passed to this function.

`AppendFSHeader(declarations)`

  Merge given FS header declarations with the present header of the current document.

`UndeclareAttributes(attribute,...)`

  Remove declarations of given attributes from the FS header

#### 15.8.11. Treex::PML::Document I/O API

See also Treex::PML::Document object methods defined in the Treex::PML module.

`ChangingFile(0|1)`

  If no argument given the default is 1. If `$FileChanged` is already set to 1, does nothing. If `$FileChanged` has not yet been assigned or is zero, sets it to the given value. Returns the resulting value. `ChangingFile(1)` also resets `$forceFileSaved` to 0.

`CurrentFile()`

  Return a Treex::PML::Document object representing the currently processed file.

`Open(filename,flags)`

  Open a given Treex::PML::Document in TrEd. Flags is an optional HASH reference that may contain various flags internally used by TrEd.

`OpenSecondaryFiles($fsfile)`

  Open secondary files for a given Treex::PML::Document in TrEd.

`ReloadCurrentFile()`

  Close and reload current fsfile.

`Resume($fsfile)`

  Resume a previously open fsfile a given window in TrEd.

`CloseFile(file?)`

  Close a given Treex::PML::Document.

`CloseFileInWindow(window?)`

  This macro is for TrEd only. It closes the Treex::PML::Document open in the given or current window. If the file is open in other windows, it is kept among postponed files. If the file is modified, the user is asked to save it.

`Save()`

  Save the current Treex::PML::Document.

`SaveAs({ option=`value,... })>

  NOTE: This macro is currently only available in TrEd.

  Save the current Treex::PML::Document under a new filename. Returns 1 if the file was saved successfully.

  Options:

  filename

    The new-filename. If undefined, the usual "Save As..." dialog prompts the user to select the output filename.

  fsfile

    operate on a given fsfile rather than the current one

  backend

    save using a given I/O backend

  update_refs

    update references from other files to this file. Values can be: 'ask', 'all', an array of Treex::PML::Document objects; all other values mean no update. Default is 'ask'.

  update_filelist

    update references from the current filelist to this file. Values can be: 'ask', 'current' (update only the current position); any other value means no update. Default is 'ask'.

`GetOpenFiles()`

  Return a list of Treex::PML::Document objects currently open in TrEd (including postponed files).

`Backends()`

  Return a list of currently registered I/O backends.

`AddBackend($classname,$before_backend)`

  Register a new I/O backend. Note that the caller is responsible for loading the required module (e.g. by calling Treex::PML::ImportBackends()); If $before_backend is defined, the new backend is added before a given backend. Otherwise the backend is added as a last backend.

`RemoveBackend($classname)`

  Remove (unregister) a given backend.

`AddNewFileList($filelist)`

  This macro is only available in TrEd. Creates a new TrED filelist from a given `Filelist` object.

`RemoveFileList($filelist_object_or_name)`

  This macro is only available in TrEd. It disposes of a given filelist (identified either by a `Filelist` object or by name) by removing it from TrEd's internal list of open filelists.

`GetCurrentFileList($win?)`

  This macro is only available in TrEd. It returns the current file-list (a Filelist object) of this or a given window.

`GetFileList($name)`

  This macro is only available in TrEd. Finds a filelist of a given name in TrEd's internal list open filelists and returns the corresponding `Filelist` object. Returns undef if not found.

`AbsolutizeFileName($relative_path,$base_path)`

  Converts a relative path to an absolute path. The returned value is an absolute path or URI, computed relative to a given base_path (file name or URI). The function is able to strip TrEd position suffixes (##N, ##N.M, and #ID) from the relative path and reattach them to the returned absolute path.

`SetCurrentFileList($name)`

  This macro is only available in TrEd. Selects the filelist of a given name for the current window.

`SetCurrentFileListInWindow($name, $win)`

  This macro is only available in TrEd. Selects the filelist of a given name for the given window.

`TrEdFileLists()`

  This macro is only available in TrEd. It returns all registered filelists.

`GetFileSaveStatus()`

  Return 1 if the document was modified since last save or reload, 0 otherwise.

`SetFileSaveStatus()`

  Use SetFileSaveStatus(1) to declare that some modification was made to the file. Use SetFileSaveStatus(0) after the file was saved from a macro (and TrEd/bTrEd would not notice that).

`DefaultInputEncoding()`

  Return's TrEd's/bTrEd's default IO encoding.

`SetDefaultInputEncoding(encoding)`

  Set TrEd's/bTrEd's default IO encoding.

`FileName()`

  Return current file's name.

`FileMetaData(key,value?)`

  Get or set meta data associated with the current Treex::PML::Document. Key is the meta data key. If value is omitted, current value associated with the key is returned. Otherwise, the given value is associated with the key, overwritting any previous value.

`FileUserData(key,value?)`

  Get or set user data associated with the current Treex::PML::Document. Key is the user data key. If value is omitted, current value associated with the key is returned. Otherwise, the given value is associated with the key, overwritting any previous value.

`FileAppData(key,value?)`

  Get or set application specific data associated with the current Treex::PML::Document. Key is the appData key. If value is omitted, current value associated with the key is returned. Otherwise, the given value is associated with the key, overwritting any previous value.

`GotoFileNo(n)`

  Goto n'th file in the current filelist. The number of the first file in filelist is 0.

`LastFileNo($win?)`

  Return the index of the last file in the current filelist.

`CurrentFileNo($win?)`

  Return the index of the current file in the current filelist.

`SaveAndNextFile()`

  Save the current file and open the next file in the current file-list.

`NextFile()`

  Goto next file in the file-list.

`SaveAndPrevFile()`

  Save the current file and open the previous file in the current file-list.

`PrevFile()`

  Goto previous file in the file-list.

#### 15.8.12. General I/O macros

`ResourcePaths()`

  Return the current list of directories used to search for
  resources.

`SetResourcePaths(dirs)`

  Set given list of directories as a current resource path (discarding the existing values of ResourcePath).

`AddResourcePath(dirs)`

  Add given directories to the end of the current resource path (to be searched last).

`AddToResourcePathAsFirst(dirs)`

  Add given directories to the beginning of the current resource path (to be searched first).

`RemoveResourcePath(dir-paths)`

  Remove given directories from the current resource path (directory paths must exactly match those listed in the resource path).

`FindDirInResources(dirname)`

  If a given dirname is a relative path of a directory found in TrEd's resource directory, return an absolute path for the resource. Otherwise return dirname.

`FindInResources(filename)`

  If a given filename is a relative path of a file found in TrEd's resource directory, return an absolute path for the resource. Otherwise return filename.

`ResolvePath(ref-filename,filename,use_resources?)`

  If a given filename is a relative path, try to find the file in the same directory as ref-filename. In case of success, return a path based on the directory part of ref-filename and filename. If the file cannot be located in this way and use_resources is true, return the value of `FindInResources(filename)`.

`SlurpURI($filename_or_uri,$chomp?)`

  Given a file name or URI of a resource, the macro returns the content of the resource. In array context the return value is a list of lines, in scalar context the value is a scalar. If the chomp flag is true, chomp() is applied to the returned array or scalar.

`writeln(string?,...)`

  Print the arguments to standard output appending a new-line if missing.

`stdout(string?,...)`

  If called without arguments return current standard output filehandle. Otherwise call print the arguments to standard output.

`stderr(string?,...)`

  If called without arguments return current standard error output filehandle. Otherwise call print the arguments to standard output.

`tmpFileName()`

  Returns a temporary filename..

`DirPart($path)`

  Returns directory part of a given path (including volume).

`FilePart($path)`

  Returns file-name part of a given path.

`CallerPath()`

  Return path of the perl module or macro-file that invoked this macro.

`CallerDir($rel_path?)`

  If called without an argument, returns the directory of the perl module or macro-file that invoked this macro.

  If a relative path is given as an argument, a respective absolute path is computed based on the caller's directory and returned.

`FindMacroDir($rel_dir)`

  Searches for a given relative path in directories with user-defined macros and returns an absolute path to the first directory that matches.

#### 15.8.13. Printing trees

`PrintDialog(-option => value,...)`

  Display TrEd's standard print dialog. Possible options providing substitutes for the default values in the print dialog are:

  `-command`

    System command to send the output to (e.g. `lpr` to print on the default printer on UNIX platform).

  `-toFile`

    If set to 1, the output is saved to a file specified in `-filename`.

  `-filename`

    Output filename.

  `-fileExtension`

    Default output file extension.

  `-format`

    One of PS, PDF, EPS, ImageMagick. Default is PS.

  `-imageMagickResolution`

    This value is passed to the command `convert` of the ImageMagick toolkit as `-density`. It specifies the horizontal and vertical resolution in pixels of the image.

  `-noRotate`

    Disable automatic landscape rotation of trees which are wider than taller.

  `-sentenceInfo`

    If set to 1, this command prints also the text associated with the tree. Instead of 0 or 1, an CODE reference (subroutine) may be passed in this parameter. This CODE is then evaluated for every tree to produce the desired text. The CODE obtains two arguments: the current Treex::PML::Document object and an integer position of the tree (starting from 0).

  `-fileInfo`

    If true, print filename and tree number under each tree.

  `-colors`

    Set to 1 for colour output.

`Print(-option => value,...)`

  Print trees given from current file according to given printing options:

  `-range`

    Lists trees to be printed (e.g. `5,-3,9-12,15-` prints trees 5,1,2,3,9,10,11,12,15,16,...)

  `-to`

    Possible values: file (print to file specified by `-filename`), (send output to ImageMagick convert, see `-convert`), pipe (send output to the standard input of command `-command`), string (return output as a string), object (return output as an object - the exact type of the value depends on the output format).

  `-command`

    System command to send the output to (usually default to `lpr` on UNIX platform).

  `-convert`

    Path to ImageMagick 'convert' command.

  `-filename`

    Output filename (only when printing to file).

  `-format`

    One of PS, PDF, EPS, ImageMagick. Default is PS.

  `-noRotate`

    Disable automatic landscape rotation of trees which are wider than taller.

  `-sentenceInfo`

    If set to 1, this command prints also the text associated with the tree. Instead of 0 or 1, a CODE reference (subroutine) may be passed in this parameter. This CODE is then evaluated for every tree to produce the desired text. The CODE obtains two arguments: the current Treex::PML::Document object and an integer position of the tree (starting from 0).

  `-fileInfo`

    If true, print filename and tree number under each tree.

  `-imageMagickResolution`

    This value is passed to the command `convert` of the ImageMagick toolkit as `-density`. It specifies the horizontal and vertical resolution in pixels of the image.

  `-colors`

    Set to 1 for colour output.

  `-hidden`

    Set to 1 to print hidden nodes.

  `-psFontFile`

    Specifies the PostScript font file to be used instead of the default one.

  `--psFontAFMFile`

    Specifies the PostScript ASCII metric font file to be used instead of the default one.

  `-ttFont`

    Specifies the TrueType font file to be used when printing via PDF.

  `-fontSize`

    Font size.

  `-fmtWidth`

    Page width.

  `-fmtHeight`

    Page height.

  `-hMargin`

    The size of the left and right horizontal margins.

  `-vMargin`

    The size of the top and bottom margins.

  `-maximize`

    Expand small trees to fit the whole page size. (Shrinking is done automatically).

  `-psMedia`

    Specifies target given media size (used for PostScript and PDF). Possible values:

    User (dimensions specified in -fmtHeight and -fmtWidth), BBox (bounding box of the tree with only -hMargin and -vMargin added), Letter, LetterSmall, Legal, Statement, Tabloid, Ledger, Folio, Quarto, Executive, A0, A1, A2, A3, A4, A4Small, A5, A6, A7, A8, A9, A10, B0, B1, B2, B3, B4, B5, B6, B7, B8, B9, B10, ISOB0, ISOB1, ISOB2, ISOB3, ISOB4, ISOB5, ISOB6, ISOB7, ISOB8, ISOB9, ISOB10, C0, C1, C2, C3, C4, C5, C6, C7, 7x9, 9x11, 9x12, 10x13, 10x14

  `-stylesheet`

    Name of the stylesheet to use (defaults to the current stylesheet).

  `-toplevel`

    Toplevel window (e.g. ToplevelFrame()) if you wish for graphical progress indicator.

#### 15.8.14. Other macros

`quit()`

  This command acts just like a `die` but without producing any error message at all. It can be used to immediatelly stop execution of the macro code and returning control to TrEd or btred (in which case btred starts processing the next file) but does not propagate through `eval{}`, so it can also be trapped.

  Note that hooks that my follow execution of the macro code (such as file_close_hook or exit_hook in btred) are executed as if the macro ended normally.

#### 15.8.15. Implementation of TredMacro::import

`import(names?)`

  If specified without parameter, exports every symbol to the caller package (except for symbols already (re)defined in the caller package). If parameters are given, exports only names specified by the parameters and the following few variables that every package derived from TredMacro (e.g. a context) must share: `$libDir`, `$grp`, `$root`, `$this` `$_NoSuchTree` `$Redraw`, `$forceFileSaved`, `$FileChanged`, `$FileNotSaved`, `$NodeClipboard`.

#### 15.8.16. XPath extension (slow)

`SetupXPath(function-mapping...)`

  `SetupXPath(
  id => \&find_node_by_id,
  pos => \&node_position,
  attributes => \&node_attributes_hashref,
  name => \&node_name,
  value => \&node_value,
  children => \&node_children,
  parent => \&node_parent,
  lbrother => \&node_left_sibling,
  rbrother => \&node_right_sibling,
  )`

  This macro requires `XML::XPath` module to be installed. It adjusts Treex::PML::Node API to match XPath model based on a given function mapping. By default, 'id' is defined to return nothing, 'pos' returns nodes sentence-ordering position (or depth-first-ordering position if sentord attribute is not defined), 'attributes' returs a hashref of node's attributes (actually a Treex::PML::Node itself), 'name' returns "node", 'value' returns node's value of the special FS value attribute, and 'children', 'parent', 'lbrother', and 'rbrother' all default to the respective Treex::PML::Node methods.

  Usage example:

  `SetupXPath(id => sub { $hashed_ids{ $_[0] } },
  name => sub { $_[0]->{functor} }
  value => sub { $_[0]->{t_lemma} });`

  `foreach ($node->findnodes(q{//ACT/PAT[starts-with(@tag,"N") or .="ano"]})) {
  # process matching nodes
  }`

### 15.9. Hooks: automatically executed macros

There is a special set of macros that was not mentioned yet. These macros, called hooks, are automatically executed by TrEd on certain occasions. By defining such macros a little more of the TrEd's implicit behaviour may be influenced, for example the execution of a planned action may be aborted.

### Warning

Writing hooks correctly is a little bit more difficult than writing simple macros. An incorrectly written hook may result in errorneous behavior of TrEd, which in some cases may even lead to a crash. When in doubt about where exactly is a particular hook called, with what parameters and what it is expected to do, it is best to peek directly into `tred` or `btred` sources. The possibility of doing so is one of the nice advantages of dealing with free software - in the Richard Stallman's sense - the joy of which I feel obliged not to deprive you of.

Hooks differ from other macros in the following aspects:

1. User cannot choose a name for a hook; on the contrary, hook is recognized as a macro having a special name identifying it as being a certain hook.

2. Sometimes parameters are passed to hooks.

3. No modifications of the tree or current node are reflected after the hook returns, i.e. the tree is not redrawn, changes to `$this` variable are not reflected. If necessary, a hook must provide this functionality itself.

4. Unlike macros, hooks are not expected to modify the tree unless they explicitly state that, typically by calling `ChangingFile(1)`.

There is a special class of hooks that may be used to prevent TrEd from finishing a planned action, e.g. enabling the user to modify certain attribute value etc. The value returned by a hook of this class is checked and the action is aborted in case the value equals to “`stop`”.

In the following table the hooks which may be used to prevent TrEd from executing a certain action are marked by `yes` in the column “Stop”.

Table 7. Hooks

Name | Stop | Hook event description
--- | --- | ---
`about_file_hook` | no | Arguments: ``stringref`` This hook is executed before the About window is displayed. The hook takes one argument: a reference to a scalar variable. The hook may populate the referenced variable with any information which is then displayed as a part of the About window message.
`after_autosave_hook` | yes | Arguments: ``output_filename``, ``success`` Executed after TrEd's attempt to auto-save a file. This hook is intended to be used e.g. for post-processing of auto-saved files. The hook obtains the filename of the auto-saved file and a save status (which is 1 in case of success and 0 or undefined if auto-saving failed). Warnings or die messages produced by the hook appear as warnings on the standard output. The hook may return the string `"stop"` to indicate that TrEd should consider auto-saving failed.
`after_edit_attr_hook` | no | Arguments: ``node`,`attr`,`result`` Executed after a node's attribute was edited in the Edit Attribute dialog window. The `result` argument contains `1` if the user pressed Ok button to close the dialog, and it contains `0` if the user closed the dialog with the Close button.
`after_edit_node_hook` | no | Arguments: ``node`,`result`` Executed after a node's attribute values were edited in the Edit Node ... dialog window. The `result` argument contains `1` if the user pressed Ok button to close the dialog, and it contains `0` if the user closed the dialog with the Close button.
`after_redraw_hook` | no | Executed every time a tree is redrawn. The hook gets a TrEd::TreeView object as an argument.
`after_save_hook` | yes | Arguments: ``output_filename``, ``success`` Executed after TrEd's attempt to save a file (but not after auto-saves). This hook is intended to be used e.g. for post-processing of saved files. The hook obtains the filename and a save status (which is 1 in case of success and 0 or undefined if saving failed). Warnings or die messages produced by the hook are presented to the user as warnings. The hook may return the string `"stop"` to indicate that TrEd should abort further actions like opening a next file, etc. The document is however considered to be saved. The hook may return the string `"stop_nonfatal"` to indicate that TrEd should abort further actions like opening a next file, etc, keep the output file but consider the document not saved. Finally, the hook may return the string `"stop_fatal"` to make TrEd revert the output file from a backup and report the save operation as failed; the document is considered not saved.
`allow_switch_context_hook` | yes | Arguments: ``previous`,`next`` Executed in the new annotation mode, but before the annotation mode is actually changed (see Section 15.10, “Using different sets of macros in different situations”) and before `pre_switch_context_hook` is called (in the old-annotation mode). The `previous` argument contains the name of the current annotation mode while `next` contains the name of the target annotation mode.
`attr_choices_hook` | no | Executed when a CDATA attribute value is editied in the attribute editor and may be used to provide a list of values to offer to the user using a list box. The hook gets the following arguments: an attribute path, the node, the `Treex::PML::Schema::Decl` object corresponding to the attribute type, and a reference to the `Tk::TrEdNodeEdit` which is an object derived from `Tk::HList`. The hook may return a reference to a list of strings.
`attr_validate_hook` | no | Executed when the user modifies a CDATA attribute value in the attribute editor. May be used to provide custom validation for attribute values. The hook gets the following arguments: current value of the attribute, an attribute path, the node, the `Treex::PML::Schema::Decl` object corresponding to the attribute type, and a reference to the `Tk::TrEdNodeEdit` which is an object derived from `Tk::HList`. The hook must return a non-zero defined value to indicate that the value is valid or 0 to indicate that the value is invalid. If the hook returns undef, the default `Treex::PML::Schema`-based validation takes place.
`current_node_change_hook` | no | Arguments: ``current_node`,`prev_current_node`` executed when a new active node is selected.
`customize_attrs_hook` | yes | Executed before the dialog for customizing attribute patterns is displayed.
`determine_node_type_hook` | no | Executed when TrEd attempts to determine the node type of a node that has no type associated with it. The hook may be used to set type of the node. Otherwise the user is asked to choose the node type (if ambiguous). Gets the node as an argument.
`do_edit_attr_hook` | yes | Arguments: ``attr`,`node`` Executed before a dialog window for editing an attribute value is displayed (usually when the user double-clicks the displayed attribute value). If `stop` is returned, the dialog is suppressed.
`do_edit_node_hook` | yes | Arguments: ``node`` Executed before the Edit Node dialog is displayed, i.e. when the user double-clicks a node, presses Enter in the main window or issues Node → Edit Node Attributes.... If the hook returns `stop`, the dialog is suppressed.
`enable_attr_hook` | yes | Arguments: ``attr`,`type`,`node`` Executed before any text field for an attribute value modification or list of possible values is created. If the hook returns “`stop`”, the field or list is made read-only. The `type` argument may have one of the following values: `ambiguous` (in case of multiple values or an attribute with a given list of possible values) or `normal`. The argument `node` is the node whose attribute is to be edited. If this hook returns `stop`, the corresponding edit fields in a displayed dialog are disabled (read-only); for a dialog that only displays the particular attribute, this means that the confirmation OK button is removed.
`enable_edit_node_hook` | yes | Arguments: ``node`` Executed before the Edit Node dialog is displayed, i.e. when the user double-clicks a node, presses Enter in the main window or issues Node → Edit Node Attributes..., but after `do_edit_node_hook` was called (and only if it didn't return `stop`). If this hook returns `stop`, the dialog is displayed, but only with a Cancel button, i.e. making it impossible to confirm and save the edits.
`event_hook` | yes | Arguments: ``Tk-XEvent`,`Tk-win`,`shortcuts...`` This is a very low-level hook, executed when a non-predefined keyboard shortcut was issued. It can be used to block certain keyboard events (in which case it should return `stop`) or to provide “on-the-fly” bindings (by returning the name of a macro to be executed). The first argument is an Tk::XEvent object which can be used to obtain a detailed information of the event. The second argument is a Tk::Widget that caught the event and the rest of the arguments are keyboard-binding shortcuts computed from the event (these are the shortcuts that TrEd would try to look up in the current annotation mode bindings if this hook returns no macro name).
`exit_hook` | no | Executed when the main window of TrEd is destroyed, before the user is prompted to save the modified files.
`file_autosave_hook` | yes | Arguments: ``fsfile`` Executed before TrEd attempts to create an auto-save file for the given`fsfile`. Note that this is not necessarily the file displayed in the active view and accessible via the `$grp` variable.
`file_close_hook` | no | Executed before TrEd attempts to close a file (this hook is called even if the file remains open but postponed if the close fails e.g. because the file being closed is required by another open file).
`file_opened_hook` | no | Executed after a file is opened but before the first tree is displayed.
`file_reloaded_hook` | no | Executed after a file has been successfully reloaded during the Reload file action accessible from TrEd's main tollbar. (Note that this is the only hook called during this action, since neither file_opened_hook nor file_resumed_hook are called!)

`guess_context_hook`

no

This hook is defined in the default `tredlib/contrib/contrib.mac` file and there is usually no need to redefine it! Instead, use

    context_guessing { ...callback-code... };

or (for compatibility with older TrEd versions)

    push @TredMacro::AUTO_CONTEXT_GUESSING, sub { ...callback-code... };

where `...callback-code...` is a code that attempts to detect a suitable annotation mode for the current file and return the annotation mode name if successful. If the callback code cannot positively determine a suitable annotation mode, it should return nothing (empty list). The standard `guess_context_hook` will call all registered callbacks one by one (but in no particular order) until it gets a defined value and will then use the value to set a the current annotation mode. The callbacks are supposed to be very reserved, i.e. they should only return some annotation mode name if the file schema, attribute-set or whatever exactly matches the data type for which the particular annotation mode is primarily intended. This will prevent extensions to steal files one from another.

`file_resumed_hook` | no | Executed after an already open (kept) file is resumed.
`file_save_hook` | yes | Arguments: ``output_filename`` Executed before TrEd attempts to save a file.
`get_backends_hook` | no | Arguments: ``backends...`` Executed before a new file is opened. It receives a list of available I/O backends known by TrEd as arguments. It should return a new array-ref consisting of backends that TrEd should actually try to use. This may be used both to add custom backends to the list or to prevent some standard backends from being used (by omitting them in the returned array-ref).
`get_nodelist_hook` | no | Arguments: ``fsfile`,`treeNo`,`recentActiveNode`,`show_hidden`` This hook may be used to supply custom node ordering given a fsfile, treeNo and hidden node visibility state. If used, it should return a two-element array reference with the first element being a array reference to a list of nodes to be displayed (in a left-to-right order) and the second element being a node to be set up as the initial active node.
`get_status_line_hook` | no | Supply status-line content. This hook is responsible for providing the content for a status-line. The value returned from `get_status_line_hook` should have the form `[`field-definitions`, `style-definitions`, ]`. `field-definitions` is an array reference of the form `[`text1`,`tags1`, `text2`,`tags2`,... ]` specifying one or more pieces of textual content of the status-line. Each piece of text is followed by another array reference, containing a list of `tags` associated with the text. Tags may be arbitrary strings. `style-definitions` is an array reference which can map some tags to visual appearance attributes. It has a form `[`tag1`, [`option => value`, `option => value`, ...], `tag2`, [`option => value`, `option => value`, ...], ... ]` where `option` may be one of `-foreground`, `-background` and `-underline`.

`get_value_line_hook`

no

Arguments: ``fsfile`,`treeNo`,`type``

Supply custom value-line content based on given `fsfile`, `treeNo`, and `type`, where type determines the situation in which the hook is used: `value_line` (value is used as the content of the value line, i.e. the text field above tree views), `print` (value used for a label under a printed tree), `sent_list` (value used in the list of sentences), `html` (value used for HTML export).

The value returned from the hook may be either a string or an array reference consisting of a list of array references representing individual nodes. In the later case, the array references representing individual nodes must be of the form `[`text`, `node`,`options...`]` where `text` is a text to be used, `node` is the node represented by the array reference and `options...` is arbitrary set of strings (tags). If these strings are of the form `-option => value` where `option` is one of `foreground`, `background`, `underline`, they are used to alter visual appearance of the corresponding part of the text displayed on the value-line. All other strings are used as tags (`value_line` type only) and are passed to hooks like value_line_doubleclick_hook or value_line_click_hook if the user clicks the corresponding part of the text.

`goto_file_hook` | yes | Executed before the next or previous file in the current file list is opened.
`highlight_value_line_tag_hook` | no | Arguments: ``node`` Invoked every time a node is selected. The hook should return a tag associated with some text in the value line. The text is then highlighted in the value line.
`init_hook` | yes | Executed on start-up, before the first file specified on the command-line is opened (i.e. also before the `start_hook`).
`initialize_bindings_hook` | no | Executed immediatelly after macros are loaded or re-loaded. The hook has no arguments.
`line_click_hook` | no | Arguments: ``node`,`tag`,`button`,`double`,`mod`,`XEvent`` Called when a line (segment of an edge) is clicked or double-clicked. Argument values are as follows: `node` is the node the line pertains to (i.e. the one whose stylesheet specification caused the line to be drawn); `tag` is the part of the stylesheet value `Line-tag` corresponding to the particular segment of the line; `button` is the number of mouse button (1,2,3); `double` is 1 if the event was a double-click and 0 otherwise; `mod` is a keyboard modifier (`Control`, `Shift`, `Alt`, or `Meta`); `XEvent` is a `Tk::XEvent` object which can be used to obtain detailed information of the event (such as position of the mouse pointer, etc.). The hook is responsible for calling `Redraw_FSFile_Tree()` or similar default macro to redraw the tree as well as for setting `$FileChanged=1` if needed.
`macros_reloaded_hook` | no | Executed after macros has been re-loaded (i.e. after the user issued Macros → Reload Macros). At the moment of the call to this hook, the newly loaded macros are already in effect.
`node_click_hook` | no | Arguments: ``node`,`modifier`,`XEvent`` Executed when the user clicks on a node with a mouse button while holding a keyboard modifier (one of Shift, Control, Alt, Meta). The first argument is a node the user clicked on. The second argument is the keyboard modifier to which the suffix `-2` or `-3` has been appended if the user pressed mouse button 2 or 3 respectivelly. The last argument is a raw `Tk::XEvent` object which can be used to obtain details about the event (such as position of the mouse pointer, etc.).
`node_doubleclick_hook` | no | Arguments: ``node`,`mod`` Called when a node is double-clicked while a modifier key was pressed. `mod` is a keyboard modifier string, such as `Control`, `Shift`, `Alt`, or `Meta`. The hook is responsible for calling `Redraw_FSFile_Tree()` or similar default macro to redraw the tree as well as for setting `$FileChanged=1` if needed.
`node_motion_hook` | no | Arguments: ``node`,`modifier`,`XEvent`` Executed repeatedly while the user drags a node while holding a keyboard modifier. Arguments passed to this hook are same as for the `node_click_hook`.
`node_moved_hook` | no | Arguments: ``node`,`old-parent`` called after a node is moved using a mouse
`node_release_hook` | yes | Arguments: ``node`,`target-node`,`mod`` Called when a node is released over another node after a mouse drag. `mod` is a keyboard modifier string, such as `Control`, `Shift`, `Alt`, or `Meta`. It can also be empty. If `mod` is empty, the hook should either result 'stop', to disable the default action of cutting `node` and pasting it on `target-node`, or take no action. In all other cases, the hook may reorganize the tree in arbitrary way, but it should call `Redraw_FSFile_Tree()` and set `$FileChanged=1` if needed.
`node_style_hook` | no | Arguments: ``node`,`syles`` This hook is called for every node of a tree every time the tree is being drawn. It may be used to provide additional styling information on top of the information provided by a current stylesheet. The first argument is the particular node. The second argument is a hash-reference containing current styling information provided by defaults and the current stylesheet. It consists of key - value pairs, where key is a styled object (`Node`,`NodeLabel`, `EdgeLabel`, `Oval`, `Line`, `Text`, `TextBg`, `TextBox`) and values are array-references consisting of feature - value pairs for these objects. The hook may alter this hash-reference and thus the styling of the particular node. It is recommended to take the advantage of the `AddStyle` default macro when altering the content of the `styles` hash-ref.
`open_file_hook` | yes | Executed before TrEd attempts to open a document. The hook gets a filename and a HASH reference containing various flags. The hook may be used for example to redirect to a different filename by calling the `Open()` macro passing it the filename and the hash-reference flags.
`pre_switch_context_hook` | yes | Arguments: ``previous`,`next`,`window`` Executed in the old annotation mode before the annotation mode is changed (see Section 15.10, “Using different sets of macros in different situations”) and when switching to a different view, and when closing a view. The `previous` argument contains the name of the current annotation mode while `next` contains the name of the new annotation mode, or the string '<NONE>' if the current view is being closed. The `window` argument is the next view to be focused. If the annotation mode is changed without focusing a different view, `window` is equal to `$grp`. If the focus moves to a different view with the same annotation mode as in the current view, `previous` and `next` are equal and both contain the name of the annotation mode.
`pre_switch_stylesheet_hook` | yes | Arguments: ``previous`,`next`` Executed when user attempts to switch the current stylesheet from `previous` to `next`.
`preload_hook` | yes | Only used by btred. Executed before a file is preloaded.
`print_tree_filename_hook` | no | Executed when File → Print ... command is invoked in order to obtain a suggestion for the target file-name used when printing to file.
`reload_macros_hook` | no | Executed before macros are re-loaded (i.e. when the user issues Macros → Reload Macros). This macro may be used to do clean-up (e.g. cleanly deallocate non-perl resources, break circular dependences, etc.) before TrEd sweeps away the memory and code currently occupied and used by macros.
`root_style_hook` | no | Arguments: ``root-node`,`syles`` This hook is executed once every time the tree is being drawn before the content of a currently selected stylesheet is applied and before `node_style_hook` is called. The first argument is the root node of the tree and `styles` are as in `node_style_hook` above.
`sort_attrs_hook` | no | Arguments: ``arrayRef`,`baseAttrPath`,`node`` Executed when attributes are to be sorted by name (see `SortAttributes` configuration options). The `arrayRef` parameter passed to the hook is an array reference containing a list of attribute names to sort. The hook may modify this list (in place) by changing the order of its elements or by removing certain elements from the list. If a true value is returned by the hook, the (possibly modified) list is used for displaying purposes without any further reordering. The arguments `baseAttrPath` and `node` contain, respectively, a base attribute path for the given list of attributes and optionally the `Treex::PML::Node` whose attributes are being displayed (optional).
`sort_attr_values_hook` | no | Arguments: ``arrayRef`,`baseAttrPath`,`node`` Executed when values in an attribute value choice are to be ordered (see `SortAttributeValues` configuration options). The `arrayRef` parameter passed to the hook is an array reference containing a list of values to sort. The hook may modify this list (in place) by changing the order of its elements or by removing certain elements from the list. If a true value is returned by the hook, the (possibly modified) list is used for displaying purposes without any further reordering. The arguments `attrPath` and `node` contain, respectively, an attribute path for the attribute whose possible values are being listed and the `Treex::PML::Node` whose attribute is involved (optional).
`start_hook` | yes | Executed on start-up, before the main event loop is entered.
`status_line_click_hook` | no | Arguments: ``tags...`` Called when the user clicks the status-line with the same arguments as `status_line_doubleclick_hook` above.
`status_line_doubleclick_hook` | no | Arguments: ``tags...`` Called when the user double-clicks the status-line. Arguments are the tags associated with the clicked field (see above). Tag may be arbitrary strings and it is up to user's will to set up some useful convention for tagging text of the status-line.
`switch_context_hook` | no | Arguments: ``previous`,`current`` Executed just after an annotation mode is changed (see Section 15.10, “Using different sets of macros in different situations”). The `previous` argument contains the name of the previous annotation mode while `next` contains the name of the new current annotation mode.
`switch_stylesheet_hook` | no | Arguments: ``previous`,`current`` Executed after switching stylesheets. The fist argument is the previous stylesheet. The second argument is the newly selected current stylesheet.
`text_click_hook` | no | Arguments: ``node`,`attribute`,`modifier`,`XEvent`` Executed when the user double-clicks on a node label linked to a particular node attribute. The `modifier` and `XEvent` arguments are as described in `node_click_hook` above.
`text_doubleclick_hook` | no | Arguments: ``node`,`attr`,`mod`` Called when an attribute in a displayed node or edge label is double-clicked while a modifier key was pressed. `mod` is a keyboard modifier string, such as `Control`, `Shift`, `Alt`, or `Meta`. `node` is the Treex::PML::Node object whose attribute was clicked. `attr` is name of the attribute which was clicked. The hook is responsible for calling `Redraw_FSFile_Tree()` or similar default macro to redraw the tree as well as for setting `$FileChanged=1` if needed.
`value_line_click_hook` | no | Arguments: ``$button,$modif,$tags_array_ref`` Called when the user clicks or doubleclicks the text window displayed above the tree with any mouse button and possibly a keyboard modifier. Arguments are: the mouse button (1,2,3), the modifier (Alt, Meta, Control, Shift), and an array-ref consisting of the tags associated with the clicked part of the text. Tag may be arbitrary strings associated with the text in the `value_line_hook` or a serialized form of a node reference if the text is associated with a particular node. (More specifically, the Perl expression `$tag eq $node` is true for one of the tags and the corresponding node, where `$tag` is a simple scalar, i.e. astring. Hence, if necessary, the macro has to iterated through the tree in order to find the corresponding node.) For a double-click with the 1st mouse button, `value_line_doubleclick_hook` is called before this hook.
`value_line_doubleclick_hook` | yes | Arguments: ``@tags`` Called when the user double-clicks the text in the value line, i.e. text field above the tree view. Arguments are the tags associated with the clicked part of the text. Tag may be arbitrary strings associated with the text in the `value_line_hook` or a serialized form of a node reference if the text is associated with a particular node. (More specifically, the Perl expression `$tag eq $node` is true for one of the tags and the corresponding node, where `$tag` is a simple scalar, i.e. astring. Hence, if necessary, the macro has to iterated through the tree in order to find the corresponding node.) The hook may return a node to focus or 'stop' to prevent focusing a node associated with the part of the text that was double-clicked.

### 15.10. Using different sets of macros in different situations

#### Annotation modes

TrEd adopts a mechanism similar e.g. to Emacs major-modes which allow the user to safely create several sets of macros with possibly coliding key and menu bindings, macro names, and other functionality. In TrEd, this mechanism is called annotation mode.

TrEd macros are organized into Perl packages (namespaces). The default package for TrEd macros is called `TredMacro`. Most pre-defined macros are defined within this package. Never use the package `main` or a package starting with `TrEd::` or `Treex::PML::` for your macros.

A new package for a set of TrEd macros named, say `MyPackage`, use the following commands:

    package MyPackage;
    BEGIN { import TredMacro; }

    sub my_first_macro {
      InfoMessage("Hallo from my first macro!")
    }

This also imports the default `TredMacro` package (e.g. the pre-defined macros) so that the macros and global variables defined there can be called used without a package namespace prefix. Finally, it defines a new macro named `my_first_macro` in the new package.

The macro `my_first_macro` from the last example can be called from a different package using its full name:

    MyPackage::my_first_macro();   # call to a macro defined in MyPackage

In the interactive work, packages are used to create so called annotation modes, which usually correspond to macro packages. Only one annotation mode can be active in TrEd at a time. The current annotation mode is displayed on and may be selected from a menu on the right end of the menu bar.

To turn a package into an annotation mode we just need to assign at least one keyboard or menu binding to some of the macros we have defined. (Note that annotation modes are refered to as binding contexts or just contexts in the old TrEd API jargon.) This is done using a special comment-like directives understood by TrEd anywhere in the macro code

#binding-context MyPackage
#bind my_first_macro to key Alt+e
#insert my_first_macro as menu Run My First Macro

First, the `#binding-context` directive says that all subsequent directives should apply to the `MyPackage` annotation mode and also that non-qualified subroutine names are to be assumed to belong to the package named `MyPackage`. Then the `#bind` directive creates a new keyboard shortcut for the macro `my_first_macro` (which upon pressing Alt+e invokes the Perl subroutine as `MyPackage->my_first_macro`). Finally, the `#insert` directive creates a menu entry for the current macro in the Macros menu hierarchy. All directives must start at the beginning of a new line.

An annotation mode may also copy all menu and keyboard bindings from other annotation mode(s) using

#key-binding-adopt `other_mode(s)`

and

#menu-binding-adopt `other_mode(s)`

directives. To remove some of the copied bindings from the current context, use `#unbind-key` and `#remove-menu` directives.

For each annotation mode, a separate submenu with macros is created in the Macros → All Modes menu; the Macros → Current Mode menu provides a short cut to the submenu with macros for the current annotation mode. For annotation modes with a large number of menu bindings it is usually more comfortable to select a macro using Macros → List of Macros.

When a keyboard shortcut is pressed, TrEd first searches for a macro bound to the shortcut within the active annotation mode and if such macro exists, TrEd invokes it. In this case, the macro is supposed to be defined or imported in a package of the same name as is the name of the current annotation mode. If no macro is bound to the shortcut within the active annotation mode, TrEd tries to find a binding in the default `TredMacro` annotation mode. The macro is then supposed to be defined within the `TredMacro` package. If the search fails, no action is taken. The same holds for hooks as well.

The following example shows a mechanism which enables TrEd to automatically decide which annotation mode to use when a file is opened. It is quite similar to the Emacs concept of “auto-modes”, except that content of the file is considered here, not the file-name extension. In the example, the name of a PML schema is used to decide which annotation mode to use. This mechanism is used by the default implementation of the guess_context_hook:

Example 3. Guessing correct annotation modes

    package Conll2009;
    BEGIN { import TredMacro; }

    #binding-context Conll2009
    #bind EditAttributes to space

    use strict;

    # check if this annotation mode applies to the current file
    sub is_conll2009_file {
      return (((PML::SchemaName()||'') eq 'conll2009') ? 1 : 0);
    }

    push @TredMacro::AUTO_CONTEXT_GUESSING, sub {
      my ($hook)=@_;
      my $resuming = ($hook eq 'file_resumed_hook');
      my $current = CurrentContext();
      if (is_conll2009_file()) {
        SetCurrentStylesheet('conll2009') if $resuming;
        return 'Conll2009';
      }
      return;
    };

    # do not use this annotation mode for other files
    sub allow_switch_context_hook {
      return 'stop' if not is_conll2009_file();
    }

    # set correct stylesheet when entering this annotation mode
    sub switch_context_hook {
      SetCurrentStylesheet('conll2009');
      Redraw() if GUI();
    }

Prev |  | Next
14. Command-line options | Home | ToC | 16. I/O backends