Étude de l'exemple “mycas”

La meilleure façon d'implémenter votre première interface avec TeXmacs est d'examiner soigneusement l'exemple mycas, que vous trouverez dans le répertoire $TEXMACS_PATH/misc/mycas. Le fichier mycas.cpp, dont le contenu est inclus à la fin de cette section, contient un programme très simple que l'on peut interfacer avec TeXmacs. Pour tester ce programme, compilez-le avec :

    g++ mycas.cpp -o mycas

et déplacez le fichier binaire mycas obtenu dans un répertoire connu de la variable d'environnement système PATH. Quand vous démarrerez TeXmacs, un nouvel article Mycas sera intégré dans le menu TexteSession.

NdT: Si vous utilisez le port Fink de TeXmacs, le plus simple est de copier le fichier mycas.cpp, situé dans le répertoire /sw/share/TeXmacs.../plugins/mycas/examples, dans ~/bin (créez le répertoire auparavant s'il n'existe pas déjà), puis compilez-le comment indiqué ci-dessus.

1.Étude du code source pas à pas

Étudions le code source de mycas pas à pas. Tout d'abord, toutes les communications se font via les entrées et sorties standards à l'aide de tubes. Pour permettre à TeXmacs de savoir quand les sorties système sont terminées, toutes les sorties doivent être encapsulées dans des blocs contenant trois caractères de contrôle spéciaux :

    #define DATA_BEGIN   ((char) 2)

#define DATA_END ((char) 5)

#define DATA_ESCAPE ((char) 27)

Le caractère DATA_ESCAPE suivi de n'importe quel autre caractère c est utilisé pour générer c, y compris dans le cas où c est l'un des trois caractères de contrôle mentionnés ci-dessus. Le message affiché au démarrage de la session montre comment utiliser DATA_BEGIN et DATA_END :

    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);

La première ligne du main stipule que le message de démarrage sera imprimé en format «verbatim». La fonction next_input, qui est appelée après la sortie du message, est utilisée pour afficher une invite et sera expliquée plus loin. Le DATA_END final ferme le bloc de message de démarrage et indique à TeXmacs que mycas est en attente d'entrée. N'oubliez de vider la sortie standard, de façon à ce que TeXmacs puisse recevoir le message dans son entier.

La boucle principale commence par demander une saisie à partir de l'entrée standard :

      while (1) {

char buffer[100];

cin >> buffer;

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

La sortie générée doit de nouveau figurer dans un bloc DATA_BEGIN-DATA_END.

        cout << DATA_BEGIN << "verbatim:";

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

À l'intérieur de ce type de bloc, on peut envoyer récursivement d'autre blocs qui peuvent utiliser des formats différents. Par exemple, le code suivant envoie une formule LaTeX :

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

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

cout << "\n";

Dans certains cas, il peut être utile d'envoyer directement la sortie en format TeXmacs en utilisant une représentation Scheme :

        cout << "And finally a fraction ";

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

cout << ".\n";

À la fin, il faut de nouveau envoyer DATA_END et vider la sortie standard :

        next_input ();

cout << DATA_END;

fflush (stdout);

}

return 0;

}

Notez qu'il ne faut jamais envoyer plus d'un bloc DATA_BEGIN-DATA_END. Dès que le premier bloc DATA_BEGIN-DATA_END est reçu par TeXmacs, le système se met en attente d'entrée. Si vous voulez envoyer plusieurs blocs DATA_BEGIN-DATA_END, vous devez les inclure dans un bloc principal.

Un «canal» spécifique est utilisé pour envoyer l'invite. Les canaux sont spécifiés comme des blocs DATA_BEGIN-DATA_END spéciaux :

    static int counter= 0;



void

next_input () {

counter++;

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

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

}

À l'intérieur d'un canal d'invite, vous pouvez aussi utiliser des blocs DATA_BEGIN-DATA_END imbriqués. Ceci permet, par exemple, d'utiliser une formule comme invite. Il existe trois canaux standards :

output
Canal de sortie normale par défaut.
prompt
Canal d'envoi d'une invite de saisie.
input
Canal servant à envoyer une valeur par défaut à la prochaine entrée.

2.Sortie graphique

On peut envoyer des images PostScript en sortie. À supposer qu'il existe une image picture.ps dans votre répertoire utilisateur, si vous insérez les lignes suivantes :

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

cout << DATA_BEGIN << "ps:";

fflush (stdout);

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

cout << DATA_END;

cout << "\n";

à l'endroit approprié dans la boucle principale, votre image s'affichera dans la sortie.

3.Le listing complet

#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".