Studying the “mycas” example

The best way to start implementing a new interface with TeXmacs is to take a look at the sample “computer algebra system” mycas, which can be found in the directory $TEXMACS_PATH/misc/mycas. The file mycas.cpp, which is listed at the end of this section, contains a very simple program which can be interfaced with TeXmacs. In order to test the program, you should compile it using:

    g++ mycas.cpp -o mycas

and move the binary mycas to some location in your path. When starting up TeXmacs, you should then have a Mycas entry in the TextSession menu.

1.Studying the source code step by step

Let us study the source code of mycas step by step. First, all communication takes place via standard input and output, using pipes. In order to make it possible for TeXmacs to know when the output from your system has finished, all output needs to be encapsulated in blocks, using three special control characters:

    #define DATA_BEGIN   ((char) 2)

#define DATA_END ((char) 5)

#define DATA_ESCAPE ((char) 27)

The DATA_ESCAPE character followed by any other character c may be used to produce c, even if c is one of the three control characters. An illustration of how to use DATA_BEGIN and DATA_END is given by the startup banner:

    int

main () {

cout << DATA_BEGIN << "verbatim:";

cout << "–––––––––––––––––––––––––––\n";

cout << "Welcome to my test computer algebra system for TeXmacs\n";

cout << "This software comes with no warranty whatsoever\n";

cout << "(c) 2001 by Joris van der Hoeven\n";

cout << "–––––––––––––––––––––––––––\n";

next_input ();

cout << DATA_END;

fflush (stdout);

The first line of main says that the startup banner will be printed in the “verbatim” format. The next_input function, which is called after outputting the banner, is used for printing a prompt and will be detailed later. The final DATA_END closes the startup banner block and tells TeXmacs that mycas is waiting for input. Don't forget to flush the standard output, so that TeXmacs will receive the whole message.

The main loop starts by asking for input from the standard input:

      while (1) {

char buffer[100];

cin >> buffer;

if (strcmp (buffer, "quit") == 0) break;

The output which is send back should again be enclosed in a DATA_BEGIN-DATA_END block.

        cout << DATA_BEGIN << "verbatim:";

cout << "You typed " << buffer << "\n";

Inside such a block you may recursively send other blocks, which may be specified in different formats. For instance, the following code will send a LaTeX formula:

        cout << "And now a LaTeX formula: ";

cout << DATA_BEGIN << "latex:" << "$x^2+y^2=z^2$" << DATA_END;

cout << "\n";

For certain purposes, it may be useful to directly send output in TeXmacs format using a Scheme representation:

        cout << "And finally a fraction ";

cout << DATA_BEGIN << "scheme:" << "(frac \"a\" \"b\")" << DATA_END;

cout << ".\n";

In order to finish, we should again output the matching DATA_END and flush the standard output:

        next_input ();

cout << DATA_END;

fflush (stdout);

}

return 0;

}

Notice that you should never output more than one DATA_BEGIN-DATA_END block. As soon as the first DATA_BEGIN-DATA_END block has been received by TeXmacs, it is assumed that your system is waiting for input. If you want to send several DATA_BEGIN-DATA_END blocks, then they should be enclosed in one main block.

A special “channel” is used in order to send the input prompt. Channels are specified as special DATA_BEGIN-DATA_END blocks:

    static int counter= 0;



void

next_input () {

counter++;

cout << DATA_BEGIN << "channel:prompt" << DATA_END;

cout << "Input " << counter << "] ";

}

Inside the prompt channel, you may again use DATA_BEGIN-DATA_END blocks in a nested way. This allows you for instance to use a formula as a prompt. There are three standard channels:

output
The default channel for normal output.
prompt
For sending input prompts.
input
For specifying a default value for the next input.

2.Graphical output

It is possible to send postscript graphics as output. Assume for instance that you have a picture picture.ps in your home directory. Then inserting the lines:

        cout << "A little picture:\n";

cout << DATA_BEGIN << "ps:";

fflush (stdout);

system ("cat $HOME/picture.ps");

cout << DATA_END;

cout << "\n";

at the appropriate place in the main loop will display your image in the middle of the output.

3.The complete listing

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <iostream.h>



#define DATA_BEGIN ((char) 2)

#define DATA_END ((char) 5)

#define DATA_ESCAPE ((char) 27)



static int counter= 0;



void

next_input () {

counter++;

cout << DATA_BEGIN << "channel:prompt" << DATA_END;

cout << "Input " << counter << "] ";

}



int

main () {

cout << DATA_BEGIN << "verbatim:";

cout << "–––––––––––––––––––––––––––\n";

cout << "Welcome to my test computer algebra system for TeXmacs\n";

cout << "This software comes with no warranty whatsoever\n";

cout << "(c) 2001 by Joris van der Hoeven\n";

cout << "–––––––––––––––––––––––––––\n";

next_input ();

cout << DATA_END;

fflush (stdout);



while (1) {

char buffer[100];

cin >> buffer;

if (strcmp (buffer, "quit") == 0) break;

cout << DATA_BEGIN << "verbatim:";

cout << "You typed " << buffer << "\n";



cout << "And now a LaTeX formula: ";

cout << DATA_BEGIN << "latex:" << "$x^2+y^2=z^2$" << DATA_END;

cout << "\n";



cout << "And finally a fraction ";

cout << DATA_BEGIN << "scheme:" << "(frac \"a\" \"b\")" << DATA_END;

cout << ".\n";



next_input ();

cout << DATA_END;

fflush (stdout);

}

return 0;

}
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.1 or any later version published by the Free Software Foundation; with no Invariant Sections, with no Front-Cover Texts, and with no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".