TeXmacs plug-ins

1.The TeXmacs plug-in system

There are many ways in which TeXmacs can be customized or extended: users may define their own style files, customize the user interface, or write links with extern programs. The plug-in system provides a universal mechanism to combine one or several such extensions in a single package. Plug-ins are both easy to install by other users and easy to write and maintain.

1.Installing and using a plug-in

From the user's point of view, a plug-in myplugin will usually be distributed on some web-site as a binary tarball with the name

    myplugin-version-architecture.tar.gz

If you installed TeXmacs yourself in the directory $TEXMACS_PATH, then you should unpack this tarball in the directory $TEXMACS_PATH/plugins, using

    tar -zxvf myplugin-version-architecture.tar.gz

This will create a myplugin subdirectory in $TEXMACS_PATH/plugins. As soon as you restart TeXmacs, the plug-in should be automatically recognized. If not, then click on ToolsUpdatePlugins and relaunch TeXmacs. Please read the documentation which comes with your plug-in in order to learn using it.

Remark 1. If you did not install TeXmacs yourself, or if you do not have write access to $TEXMACS_PATH, then you may also unpack the tarball in $TEXMACS_HOME_PATH/plugins. Here we recall that $TEXMACS_HOME_PATH defaults to $HOME/.TeXmacs. When starting TeXmacs, your plug-in should again be automatically recognized.

Remark 2. If the plug-in is distributed as a source tarball like myplugin-version-src.tar.gz, then you should first compile the source code before relaunching TeXmacs. Depending on the plug-in (read the instructions), this is usually done using

    cd myplugin; make

or

    cd myplugin; ./configure; make

Remark 3. In order to upgrade a plug-in, just remove the old version in $TEXMACS_PATH/plugins or $TEXMACS_HOME_PATH/plugins using

    rm -rf myplugin

and reinstall as explained above.

2.Writing your own plug-ins

In order to write a plug-in myplugin, you should start by creating a directory

    $TEXMACS_HOME_PATH/plugins/myplugin

where to put all your files (recall that $TEXMACS_HOME_PATH defaults to $HOME/.TeXmacs). In addition, you may create the following subdirectories (when needed):

bin

For binary files.

doc

For documentation (not yet supported).

langs

For language related files, such as dictionaries (not yet supported).

lib

For libraries.

packages

For style packages.

progs

For Scheme programs.

src

For source files.

styles

For style files.

As a general rule, files which are present in these subdirectories will be automatically recognized by TeXmacs at startup. For instance, if you provide a bin subdirectory, then

    $TEXMACS_HOME_PATH/plugins/myplugin/bin

will be automatically added to the PATH environment variable at startup. Notice that the subdirectory structure of a plug-in is very similar to the subdirectory structure of $TEXMACS_PATH.

Example 4. The easiest type of plug-in only consists of data files, such as a collection of style files and packages. In order to create such a plug-in, it suffices to create directories

    $TEXMACS_HOME_PATH/plugins/myplugin
    $TEXMACS_HOME_PATH/plugins/myplugin/styles
    $TEXMACS_HOME_PATH/plugins/myplugin/packages

and to put your style files and packages in the last two directories. After restarting TeXmacs, your style files and packages will automatically appear in the DocumentStyle and DocumentUse package menus.

For more complex plug-ins, such as plug-ins with additional Scheme or C++ code, one usually has to provide a Scheme configuration file

    $TEXMACS_HOME_PATH/plugins/myplugin/progs/init-myplugin.scm

This configuration file should contain an instruction of the following form

(plugin-configure myplugin
  configuration-options)

Here the configuration-options describe the principal actions which have to be undertaken at startup, including sanity checks for the plug-in. In the next sections, we will describe some simple examples of plug-ins and their configuration. Many other examples can be found in the directories

    $TEXMACS_PATH/examples/plugins
    $TEXMACS_PATH/plugins

Some of these are described in more detail in the chapter about writing new interfaces.

3.Example of a plug-in with Scheme code

The world plug-in

Consider the world plug-in in the directory

    $TEXMACS_PATH/examples/plugins

This plug-in shows how to extend TeXmacs with some additional Scheme code in the file

    world/progs/init-world.scm

In order to test the world plug-in, you should recursively copy the directory

    $TEXMACS_PATH/examples/plugins/world

to $TEXMACS_PATH/plugins or $TEXMACS_HOME_PATH/plugins. When relaunching TeXmacs, the plug-in should now be automatically recognized (a World menu should appear in the menu bar).

How it works

The file init-world.scm essentially contains the following code:

(plugin-configure world
  (:require #t))

(when (supports-world?)
  (display* "Using world plug-in!\n"))

The configuration option :require specifies a condition which needs to be satisfied for the plug-in to be detected by TeXmacs (later on, this will for instance allow us to check whether certain programs exist on the system). The configuration is aborted if the requirement is not fulfilled.

Assuming that the configuration succeeds, the supports-world? predicate will evaluate to #t. In our example, the body of the when statement corresponds to some further initialization code, which just sends a message to the standard output that we are using our plug-in. In general, this kind of initialization code should be very short and rather load a module which takes care of the real initialization. Indeed, keeping the init-myplugin.scm files simple will reduce the startup time of TeXmacs.

4.Example of a plug-in with C++ code

The minimal plug-in

Consider the example of the minimal plug-in in the directory

    $TEXMACS_PATH/examples/plugins

It consists of the following files:

    minimal/Makefile
    minimal/progs/init-minimal.scm
    minimal/src/minimal.cpp

In order to try the plug-in, you first have to recursively copy the directory

    $TEXMACS_PATH/examples/plugins/minimal

to $TEXMACS_PATH/progs or $TEXMACS_HOME_PATH/progs. Next, running the Makefile using

    make

will compile the program minimal.cpp and create a binary

    minimal/bin/minimal.bin

When relaunching TeXmacs, the plug-in should now be automatically recognized.

How it works

The minimal plug-in demonstrates a minimal interface between TeXmacs and an extern program; the program minimal.cpp is explained in more detail in the chapter about writing interfaces. The initialization file init-minimal.scm essentially contains the following code:

(plugin-configure minimal
  (:require (url-exists-in-path? "minimal.bin"))
  (:launch "minimal.bin")
  (:session "Minimal"))

The :require option checks whether minimal.bin indeed exists in the path (so this will fail if you forgot to run the Makefile). The :launch option specifies how to launch the extern program. The :session option indicates that it will be possible to create sessions for the minimal plug-in using InsertSessionMinimal.

5.Example of a plug-in with Python code

The pyminimal plug-in

Consider the example of the pyminimal plug-in in the directory

    $TEXMACS_PATH/examples/plugins

It consists of the following files:

    pyminimal/progs/init-pyminimal.scm
    pyminimal/src/minimal.py

In order to try the plug-in, you first have to recursively copy the directory

    $TEXMACS_PATH/examples/plugins/pyminimal

to $TEXMACS_PATH/progs or $TEXMACS_HOME_PATH/progs.

When relaunching TeXmacs, the plug-in should now be automatically recognized.

How it works: The Scheme Part

The pyminimal plug-in demonstrates a minimal interface between TeXmacs and an extern program in python. The initialization file init-pyminimal.scm essentially contains the following code:

(define (python-launcher)
  (if (url-exists? "$TEXMACS_HOME_PATH/plugins/pyminimal")
      (string-append "python \""
                     (getenv "TEXMACS_HOME_PATH")
                     "/plugins/pyminimal/src/minimal.py\"")
      (string-append "python \""
                     (getenv "TEXMACS_PATH")
                     "/plugins/pyminimal/src/minimal.py\"")))

(plugin-configure pyminimal
  (:require (url-exists-in-path? "python"))
  (:launch ,(python-launcher))
  (:session "PyMinimal"))

The :require option checks whether python indeed exists in the path (so this will fail if you did not have python installed). The :launch option specifies how to launch the extern program. The :session option indicates that it will be possible to create sessions for the pyminimal plug-in using InsertSessionPyMinimal.

The python-launcher function will be evaluated and return the proper command to launcher the extern program. If $TEXMACS_HOME_PATH/plugins/pyminimal exists, it would be

python "$TEXMACS_HOME_PATH/plugins/pyminimal/src/minimal.py"

otherwise,

python "$TEXMACS_PATH/plugins/pyminimal/src/minimal.py"

The environment variables will be replaced in runtime. Sometimes, $TEXMACS_HOME_PATH and $TEXMACS_PATH may contain spaces, as a result, we quote the path using the double quotes.

How it works: The Python Part

Using the Python interpreter, we do not need to compile the code. And most of the time, python code can be interpreted without any modification under multiple platforms. The built-in python libraries are really helpful and handy.

Many TeXmacs built-in plugins are written in Python, and we have carefully organized the code and reused the common part named tmpy.

import os
import sys
from os.path import exists
tmpy_home_path = os.environ.get("TEXMACS_HOME_PATH") + "/plugins/tmpy"
if (exists (tmpy_home_path)):
    sys.path.append(os.environ.get("TEXMACS_HOME_PATH") + "/plugins/")
else:
    sys.path.append(os.environ.get("TEXMACS_PATH") + "/plugins/")

The first part of the code just add $TEXMACS_HOME_PATH/plugins or $TEXMACS_PATH/plugins to the python path for importing the tmpy package.

from tmpy.protocol        import *
from tmpy.compat          import *

flush_verbatim ("Hi there!")

while True:
    line = tm_input()
    if not line:
        pass
    else:
        flush_verbatim ("You typed " + line)

flush_verbatim is provided by tmpy.protocol which is a subpackage for interaction with TeXmacs server in Python.

tm_input is provided by tmpy.compat which is a subpackage for compatibility within Python 2 and 3. For built-in plugins written in Python, it would be better to support more Python version. For example, in some desktop environments, the python command may redirect to python2.6.

Comparison with C++

This demo plugin is a Python implementation of the well-documented minimal plugin written in C++. Here is the summary of the differences:

6.Summary of the configuration options for plug-ins

As explained before, the Scheme configuration file myplugin/progs/init-myplugin.scm of a plug-in with name plugin should contain an instruction of the type

(plugin-configure myplugin
  configuration-options)

Here follows a list of the available configuration-options:

(:winpath package-path inner-bin-path)

Specify where to search for the plug-in under windows. The package-path is the usual place where the plug-in is installed. The inner-bin-path is the place where to look for the binary executable corresponding to the plug-in, relative to the package-path.

(:winpath package-path inner-bin-path)

Analogous to :winpath, but under MacOS.

(:require condition)

This option specifies a sanity condition which needs to be satisfied by the plug-in. Usually, it is checked that certain binaries or libraries are present on your system. If the condition fails, then TeXmacs will continue as whether your plug-in did not exist. In that case, further configuration is aborted. The :require option usually occurs first in the list of configuration options.

(:versions version-cmd)

This option specifies a Scheme expression version-cmd which evaluates to a list of available versions of the plug-in.

(:setup cmd)

This command is only executed when the version of the plug-in changed from one execution of TeXmacs to another one. This occurs mainly when installing new versions of TeXmacs or helper applications.

(:launch shell-cmd)

This option specifies that the plug-in is able to evaluate expressions over a pipe, using a helper application which is launched using the shell-command shell-cmd.

(:link lib-name export-struct options)

This option is similar to :launch, except that the extern application is now linked dynamically. For more information, see the section about dynamic linking.

(:session menu-name)

This option indicates that the plug-in supports an evaluator for interactive shell sessions. An item menu-item will be inserted to the InsertSession menu in order to launch such sessions.

(:serializer ,fun-name)

If the plug-in can be used as an evaluator, then this option specifies the Scheme function fun-name which is used in order to transform TeXmacs trees to strings.

(:commander ,fun-name)

This command is similar to the :serializer option except that it is used to transform special commands to strings.

(:tab-completion #t)

This command indicates that the plug-in supports tab-completion.

(:test-input-done #t)

This command indicates that the plug-in provides a routine for testing whether the input is complete.

It should be noticed that the configuration of the plug-in myplugin automatically creates a few predicates:

supports-myplugin?

Test whether the plug-in is fully operational (all requirements are met).

in-myplugin?

Test whether myplugin is the current programming language.

myplugin-scripts?

Test whether myplugin is the current scripting language.