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
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
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:
È 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.
#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;
}