L'esempio di “mycas”

Il modo migliore per iniziare ad implementare in TeXmacs una nuova interfaccia, consiste nello studiare attentamente l'esempio del sistema di computer algebra mycas, che è contenuto nella directory $TEXMACS_PATH/misc/mycas. Il file mycas.cpp, il cui listato è disponibile alla fine di questa sezione, contiene un esempio molto semplice di programma che può essere interfacciato con TeXmacs. Per testare il programma è necessario compilarlo utilizzando il comando:

    g++ mycas.cpp -o mycas

e spostare il file binario mycas in qualche punto del vostro path. All'avvio di TeXmacs è quindi necessario avere a disposizione la voce Mycas nel menu TestoSessione.

1.Studiamo il codice sorgente passo dopo passo

Iniziamo a studiare, passo dopo passo, il codice di mycas. In primo luogo osserviamo come ogni comunicazione avvenga utilizzando delle pipes e coinvolga standard input e output. Per permettere a TeXmacs di comprendere quando l'output del sistema ha terminato è necessario che ogni output sia incapsulato in blocchi, utilizzando tre speciali caratteri di controllo:

    #define DATA_BEGIN   ((char) 2)

#define DATA_END ((char) 5)

#define DATA_ESCAPE ((char) 27)

Il carattere DATA_ESCAPE seguito da un qualsiasi altro carattere c può essere usato per produrre c, anche se c è uno dei tre caratteri di controllo. Un'illustrazione di come utilizzare DATA_BEGIN e DATA_END è data dal seguente messaggio di inizio:

    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 prima linea del main definisce il formato del carattere del messaggio di inizio che è di tipo “verbatim”. La funzione next_input, che viene richiamata al termine del messaggio di inizio, serve per stampare un prompt e se ne discuterà in dettaglio nel seguito. In conclusione DATA_END chiude il blocco del messaggio di inizio e informa TeXmacs che mycas è in attesa di un input. Non dimenticate alla fine di svuotare lo standard output, in modo che TeXmacs possa ricevere l'intero messaggio.

Il ciclo principale inizia chiedendo l'input dallo standard input:

      while (1) {

char buffer[100];

cin >> buffer;

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

L'output che viene restituito deve essere ancora una volta incluso in un blocco tipo DATA_BEGIN-DATA_END.

        cout << DATA_BEGIN << "verbatim:";

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

All'interno di tale blocco è possibile inviare ricorsivamente altri blocchi che possono essere specificati in formati diversi. Ad esempio, il seguente codice spedisce una formula in LaTeX:

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

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

cout << "\n";

Per alcuni scopi particolari può essere utile spedire direttamente l'output in formato TeXmacs utilizzando una rappresentazione Scheme:

        cout << "And finally a fraction ";

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

cout << ".\n";

Per concludere, dobbiamo nuovamente inviare l'output DATA_END e svuotare lo standard output:

        next_input ();

cout << DATA_END;

fflush (stdout);

}

return 0;

}

Osserviamo che non è possibile inviare più di un blocco DATA_BEGIN-DATA_END alla volta. Appena il primo blocco DATA_BEGIN-DATA_END è stato ricevuto da TeXmacs, si assume che il sistema sia in attesa dell'input. Se si vuole inviare più di un blocco DATA_BEGIN-DATA_END tutti i blocchi da inviare devono essere inclusi in un blocco principale.

Un “canale” speciale viene impiegato per inviare il prompt di input. I canali sono specificati come blocchi DATA_BEGIN-DATA_END speciali:

    static int counter= 0;



void

next_input () {

counter++;

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

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

}

All'interno del canale di prompt è possibile utilizzare ancora blocchi DATA_BEGIN-DATA_END tuttavia in modo annidato. In questo modo è possibile ad esempio utilizzare come prompt una formula. Sono disponibili tre canali standard:

output
canale predefinito per un output normale;
prompt
per inviare prompt di input;
input
per specificare un valore predefinito per l'input successivo.

2.Output grafici

È possibile anche inviare output grafici in formato postscript. Immaginiamo ad esempio di avere una figura picture.ps nella home directory. Allora inserendo le linee di codice:

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

cout << DATA_BEGIN << "ps:";

fflush (stdout);

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

cout << DATA_END;

cout << "\n";

nel punto appropriato del ciclo principale si otterrà la visualizzazione della figura nel centro dell'output.

3.Il listato completo del programma

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