Appariteur
**********

Version du Friday 21 May 2021 à 16H41 (Le manuel n'est pas encore
complet).

See Quelques mots sur les intentions

Quelques mots sur les intentions
================================

Appariteur n'est en lui même pas grand chose.  Juste une
paramétrisation d'Emacs.

Celle-ci est fournie en guise de béquille pour aider chacun à
construire la paramétrisation qui lui conviendrait mieux que
celle-ci.

Il ne faut pas hésiter à faire des modifications
   * dans le Lisp (.el) qui gère les éléments de paramétrisation ;
   * dans le Maxima (.mac) qui gère la décoration du rendu de
     Maxima.

1 Bouée de secours
*******************

   * Que signifie (par exemple) '<C-tab>' :
        * qu'il faut appuyer sur le modificateur 'Control' (='C') et
          simultanément appuyer sur <tab> (la touche de tabulation) ;
        * ça a pour effet de changer la façon dont les 4 fenêtres
          du frame Emacs sont disposées les unes par rapport aux
          autres.
     Les combinaisons de touches permettant d'accéder aux commandes
     sont notées ainsi dans ce manuel.

     Elles sont notées de façon similaire peut-être un peu
     différentes dans la case Action de la barre de menu (en haut à
     gauche).

   * Que signifie '<S-C-p>' : il faut appuyer simultanément sur
     'Shift', 'Control' et 'p'

   * Que signifie '<C-x p>' : il faut appuyer simultanément sur
     'Control' et 'x' puis lâcher 'Control' et appuyer sur 'p'

     (l'exemple choisi est celui d'une combinaison de touches non
     définie, c'est signalé dans le minibuffer, en bas du frame)

   * comment savoir à quelle action correspond un combinaison de
     touches : il faut faire '<C-h k>' puis taper la combinaison de
     touche (le minibuffer l'y invite)

   * Que signifie '<alt-x>' : il faut appuyer simultanément sur 'alt'
     et 'x' ; on se retrouve dans le minibuffer où il est possible
     d'entrer une commande.

     La touche <alt> peut être désignée par <M> (pour <meta>) ; on
     peut aussi rencontrer '<esc> x' (qui fonctionne).

     Cette débauche de touche trouve son origine dans les machines
     Lisp qui avaient des claviers très compliqués
     <http://xahlee.info/kbd/lisp_keyboards.html>.

   * Comment se déplacer entre les fenêtres du frame Emacs :
        * par la souris ;
        * par les touches '<S-left>', '<S-up>', '<S-right>',
          '<S-down>' ;avec <Shift>=<S>, et left, up, down désignent
          les flèches de clavier.

   * Comment se déplacer dans le manuel
        * les possibilités sont indiquées dans la case Info de la
          barre de menu (actif quand le focus est placé sur la
          fenêtre du manuel) ;
        * l'index est obtenu en tapant 'i'.

   * Quelques commandes Emacs Commandes d'Emacs et une liste
     des combinaisons de touches disponibles Clavier.

2 Interface
***********

2.1 4 fenêtres & quelques commandes
====================================

_Appariteur_ est un nom qui désigne la...  disons customization
d'_Emacs_ (see Introduction du manuel d'Emacs (Emacs)) qui
consiste à :

   o- couper le _frame_ de départ en 4 _windows_ : 'wbg', 'wbd',
     'whg' 'whd'
     (pour 'w' = window ; 'b'/'h' = bas/haut ; 'd'/'g' = droite/gauche
     et indiquent ainsi la position de ces windows dans le frame) ;
     see Frame window et buffer (Appariteur).

   o- définir des combinaisons de touches (see Bouée de secours)
     qui permettent de :

     - modifier les dimensions des 'wbg', 'wbd', 'whg', 'whd' ;

     '<C-right>' et '<C-up>' augmentent la largeur et la hauteur de la
     window dans laquel se trouve le _curseur_ actif (on dit qui a le
     _focus_),
     'C-left' et '<C-down>' diminuent ces dimensions.

     - positionner le curseur sur l'une ou l'autre de ces windows

     '<S-right>' et '<S-left>' rendent actif le curseur sur la window
     en vis-à-vis horizontalement (on dit place le focus sur la
     window),
     idem pour '<S-up>' et '<S-down>' mais verticalement .

     - modifier la façon dont les fenêtres sont connectées les unes
     aux autres

     '<C-tab>' commute entre les deux connexions possibles des 4
     fenêtres.

     (Ces actions sont également accessibles par le menu
     'Action->Appariteur') ;

   o- exploiter cette découpe pour organiser :

     - des calculs symboliques et numériques via _Maxima_ ;

     - l'écriture de textes comportant des équations via _Latex_ ou
     encore directement sur un fichier _html_

2.2 Clavier
===========

Voici le contenu de Touches.txt

Emacs
=====

C-x C-f : lire un fichier (le buffer qui lui sera affecté aura le nom du fichier)
C-x C-s : sauver le buffer
C-x i   : insérer le contenu d'un fichier dans le buffer
C-x b   : changer de buffer dans la fenêtre où on est
C-g     : break
C-]     : break de machin récursif
M-x     : aller dans le minibuffer (pour faire une commande par exemple)
F10     : aller dans les menus sans souris
C-x <space> : débuter une sélection de texte
alt-w   : copier le texte sélectionné
C-w     : couper le texte sélectionné
C-y     : coller le texte qui a précédemment été copié
C-s     : chercher
esc %   : chercher et remplacer
esc $   : orthographe (le dictionnaire peut être changé dans Tool -> Spell-checking
          pour le français : francais-med
C-x c   : quitter Emacs proprement

Info
====

d : aller à la racine des nœuds
u : aller au nœud du dessus
l : retourner au nœud où on était juste avant de le quitter
m : sélectionner le info souhaité (dans la racine des nœuds)
i : chercher les occurences d'un terme référencé dans les infos
t : aller au nœud Top
T : table des matières complète

JMaxima
=======

C-ret : envoyer la ligne à Maxima
S-ret : envoyer le texte entre balises %%%; à Maxima
alt-ret : envoyer une fonction à Maxima

S- flèches : changer de fenêtre horizontalement
C- flèches : changer de fenêtre verticalement
C-tab : commuter entre les deux dispositions de fenêtres proposées

C-+ : augmenter la taille de police
C-- : diminuer la taille de police
M-+ : augmenter la taille des images d'expression dans jmaxima (prend effet pour les équations suivantes)
M-+ : diminuer la taille des images d'expression dans jmaxima (prend effet pour les équations suivantes)

C-S-P : demander l'affichage d'un prompt MXM>

alt-home : démarrer Maxima (rien s'il est déjà démarré)
alt-end  : arrêter Maxima (on demande si c'est bien sûr)

C-x c : break à Maxima (SIGNIT)
C-;   : sort du mode debug de Maxima (à la suite du break dans le traitement d'une expression)

esc tab : demander complétion
          en cas de plusieures possibilités : flèche gauche et droite pour les faire apparaître

esc x puis font-lock-mode (dans le minibuffer) : commute entre colorisation ou non

Latex
=====

C-ret : exécute le contenu des balises \rfs et \scriptM
C-'   : reexécute tous les contenus de balises \rfs et \scriptM à partir du début
S-ret : lance la compilation Latex
C-o   : réordonne les labels d'équations
C-l   : canevas de nouvelle équation

Html
====

C-ret : exécute le contenu de <!-- --> et le range dans <img src="...">
S-ret : exécute les instructions entre balise <!--%%%; %%%;>
C-l   : fait apparaître un <!--   --> <img />
C-o   : fait apparaître un <div><!--   --> <img /></div>
C-r   : met le compteur d'équation comme il faut

2.3 Commandes d'Emacs
=====================

Le mieux est de consulter directement le manuel d'Emacs
Emacs, ou encore de regarder les cases de la barre de menu.

Mais voici quelque commandes d'Emacs qui doivent être connues.  Elles
sont accessible par les cases File, Edit et Buffer de la barre de
menu.  Mais il est plus commode de mémoriser les commandes par
touches.  notamment

   * '<C-x-f>' (comprendre <C> appuyé, taper x puis f) qui affiche
          Find file: chemin-de-repertoires
     dans le minibuffer (en bas) ; il faut alors compléter par un nom
     de fichier (la complétion automatique est obtenue par <tab>) qui
     sera lu et dont dont le buffer sera placé dans la fenêtre à
     partir de laquelle on a tapé cette commande.
   * '<C-x-s>' : sauve le buffer actif dans le fichier qui lui est
     affecté.

   * '<C-x-b>' : permet de changer le buffer affecté à une fenêtre
     (regarder le minibuffer).

   * '<C-x-k>' : permet de tuer un buffer.

   * '<C-g>' : quitte ce qu'Emacs est en train de faire (par exemple
     un '<C-s>')

   * '<C-]>' : même chose que <C-g>.

   * '<C-h-k]>' : permet de savoir ce que fait une combinaison de
     touche.  Emacs propose de la taper et renvoie une description.

   * '<S-C-->' undo.

   * '<C-s>' cherche en avant ('<C-r>' pour en arrière).

   * '<alt-%>' cherche et remplace.

2.4 Colorisation syntaxique
===========================

L'édition de fichiers d'extension '.tex' (latex), '.html', '.m'
(octave) et d'autres encore peut être faite avec colorisation
syntaxique.

Appariteur a préempté cette fonctionnalité du mode maxima
<https://www.emacswiki.org/emacs/MaximaMode> pour les fichiers
d'extention '.mac' : le fichier 'maxima-font-lock.elc' est une partie
de ce mode ; par commodité, il est inclu dans Appariteur.zip mais il
peut être trouvé indépendamment.

D'un manière générale, pour commuter entre colorisation syntaxique
et son absence : taper '<esc x>' qui place le focus dans le minibuffer
puis écrire 'font-lock-mode' suivi de '<return>'.

2.5 Complétion
===============

La complétion dans les buffers '.mac' (Appariteur-maxima) ainsi que
dans 'wbg' fonctionne en tapant '<esc tab>' lorsque le curseur est
placé sur un mot.

Si une complétion est trouvée, le mot est remplacé par elle.  Sinon
soit il n'y en a pas et c'est indiqué dans le minibuffer, soit il y a
plusieurs choix possibles qui s'affichent dans 'whd'.  Pour
sélectionner l'un d'entre eux on dispose des touches de flèches
droite '<right>' ou gauche '<left>'.

Les mots qui peuvent être complétés sont un choix des commandes de
Maxima et celles de CDE.

3 Communication avec Maxima
***************************

3.1 Le fonctionnement de la communication
=========================================

3.1.1 Tout d'abord
------------------

Au démarrage, Appariteur lance un _process_ qui le connecte à
Maxima.
(Le process peut être détruit par '<alt-end>' et relancé par
'<alt-home>' ; c'est aussi dans la case Action -> JMaxima de la barre
de menus en haut).

Un _buffer_ nommé 'jmaxima' apparaît alors dans wbd.

Il comporte un caractère de prompt 'MXM>'.  Si on se place dans la
fenêtre wbd, on peut alors envoyer des instructions à Maxima qui y
répond à la ligne juste en dessous.

La touche d'entrée n'est cependant pas '<return>' mais '<S-return>'

La touche '<return>' permet elle d'entrer une suite d'instructions qui
ne seront interprétées par Maxima qu'après avoir tapé
'<S-return>'.

On peut également envoyer des instructions à Maxima à partir d'une
autre window (Notamment wbg qui sert à cela).  Il faut alors placer
ces instructions entre deux balises '%%%;', par exemple
     %%%;
     Num:(x^2-y^2);
     Den:(x-y);
     Frac:Num/Den;
     factor(Frac);
     %%%;
placer le curseur entre les deux balises et taper '<S-return>'.

Si on place le curseur sur une des lignes entre les balises et qu'on
tape '<C-return>', c'est seulement le contenu de la ligne qui est
envoyé à Maxima (les balises sont en fait inutiles).

3.1.2 Ensuite
-------------

Les sorties de
     %%%;
     Num:(x^2-y^2);
     Den:(x-y);
     Frac:Num/Den;
     factor(Frac);
     %%%;
peuvent être améliorées graphiquement en remplaçant le séparateur
d'instruction ';' par '@'.  Soit
     %%%;
     Num:(x^2-y^2)@
     Den:(x-y)@
     Frac:Num/Den@
     factor(Frac)@
     %%%;
Plutôt que du texte qui peut être copié et collé (pour être
réinjecté à Maxima par exemple), ce sont des images qui
apparaissent.

Il faut noter que cela a un coût : l'expression Maxima est
transformée (par Maxima) en une expression Latex ; celle-ci est
compilée par Pdflatex pour produire un dvi ; celui-ci est transformé
en un fichier image ; et finalement ce dernier est inséré dans la
fenêtre du buffer jmaxima par Emacs.

3.1.3 Finalement
----------------

Au démarrage de Maxima, Appariteur lui fait charger un certain nombre
de bibliothèques dont une est 'CDE_FctT.mac'.

Celle-ci contient des fonctions de conversion d'expression Maxima en
chaînes de caractère au format Latex.  La fonction principale est
*FaitLatex*
     FaitLatex(a/b,"");

Cette fonction est appelée par une autre fonction *Latex*
     Latex(a/b)$
qui entoure la chaîne de caractère produite par des '^E' ; ce qui
permet à la fonction filtre associée au process qui a lancé Maxima
de reconnaître qu'il s'agit de code Latex.

(Lorsqu'on met un séparateur '@' plutôt que ';' (ou '$'), la
fonction elisp d'Appariteur qui a la charge d'envoyer des instruction
à Maxima insère la sortie de l'instruction délimitée dans un
'Latex'.)

Lorsque la fonction filtre reçoit un code Latex, elle l'encapsule
dans un format (faire '<C-e>' derrière format et regarder le
minibuffer)
     jmaxima-format
sauve un fichier contenant cela dans un répertoire temporaire
     jmaxima-tmp
appelle pdflatex pour créer un fichier dvi ; puis appelle dvipng pour
créer un fichier png.  Cela de façon synchrone (Emacs attend que le
travail soit fini).

À l'issu de cela, Emacs lit le fichier png produit et l'insère là
où il aurait inséré le texte d'une expression Maxima s'il n'y avait
pas eu l'injonction de produire une image.

3.2 Définitions TeX côté Maxima
==================================

3.2.1 Décoration des vecteurs et dyades
----------------------------------------

Maxima dispose d'une fonction 'tex' qui crée le code Latex à partir
d'une expression Maxima.  Il permet également d'agir sur la
conversion via 'texput' Functions and Variables for TeX Output (Maxima)
mais ce n'est pas commode pour tout,

Notamment pour mettre des flèches sur les vecteurs, il faudrait, à
chaque déclaration d'un symbole comme vecteur donner sa
représentation Tex explicitement.  Ce qui est lourd.

La solution alternative retenue a été la création de la fonction
'FaitLatex' qui examine si le symbole qu'elle a à traiter est un
élément de 'liste_des_vecteurs' Déclaration et produits (NeoCDE)
; s'il l'est le symbole se verra affecté d'une flèche.
Le même mécanisme est utilisé pour les dyades (avec
'liste_des_dyades').

Si on souhaite qu'un symbole particulier ne soit pas traité de cette
façon standardisée, il faut alors explicitement le placer dans la
liste
     ListeTex1;
et, éventuellement, effectuer un 'texput' manuel sur le symbole.

3.2.2 Décoration des dérivations
----------------------------------

Les notations de dérivations connues sont celles de
   * Leibnitz et sa variante abrégée
   * Lagrange
   * Newton

La fonction *addPD(v,derivee)* où 'v' est un symbole (ou une liste de
symboles) et 'derivee' est : Leibnitz, Lagrange ou Newton permet de
spécifier celle qu'on veut affecter à la variable correspond au
symbole (ou à chacun des éléments de la liste de symboles).  Par
exemple, pour des variable dépendantes d'une seule variable
indépendante :
     %%%; nettoie()$ depends([x,y],t)$
      addPD([x,y],Leibnitz)$ diff([x,y],t)@
      addPD([x,y],Lagrange)$ diff([x,y],t)@
      addPD([x,y],Newton)$ diff([x,y],t)@
     %%%;
et pour des variables dépendantes de plusieurs variables
indépendantes :
     %%%; nettoie()$ depends(phi,[x,y])$
      addPD(phi,Leibnitz)$ diff(phi,x)@
      addPD(phi,Lagrange)$ diff(phi,x)@
      addPD(phi,LeibnitzBref)$ diff(phi,x)@
     %%%;

Par défaut la notation utilisée est celle du premier élément de la
liste
     PrefDerivees@
Cette liste contenant également toutes les préférences qui ont
été données lors de la session.  Et elle est initialisée à
'[Leibnitz]'.

3.2.3 Fonctions de décoration
------------------------------

On a souvent besoin de définir des variables dérivées d'un symbole.
Par exemple, pour x : x-point, x-prime, d-x....  Les fonctions
suivantes réalisent cela
   * tildise
          %%%; nettoie()$  tildise(x,y)$ [xt,yt]@ %%%;
   * dotise
          %%%; nettoie()$  dotise(x,y)$ [xp,yp]@ %%%;
   * deltise
          %%%; nettoie()$  deltise(x,y)$ [dx,dy]@ %%%;
   * primise
          %%%; nettoie()$  overise(x,y)$ [xp,yp]@ %%%;
   * secoise
          %%%; nettoie()$  secoise(x,y)$ [xs,ys]@ %%%;
   * tercise
          %%%; nettoie()$  tercise(x,y)$ [xt,yt]@ %%%;
   * primiseV (pour mettre un espace après le prime)
          %%%; nettoie()$  addv(x,y)$ primiseV(x,y)$ [xp,yp]@ %%%;
   * secoiseV
          %%%; nettoie()$ addv(x,y)$  secoiseV(x,y)$ [xs,ys]@ %%%;
   * terciseV
          %%%; nettoie()$ addv(x,y)$  terciseV(x,y)$ [xt,yt]@ %%%;
   * overise
          %%%; nettoie()$  overise(x,y)$ [xb,yb]@ %%%;

On a également souvent besoin d'indicier des symboles.  C'est ce que
permet de faire *Indicie(indices,v1,v2,...)*.  Par exemple
     %%%; nettoie()$
     Indicie([a,b,c],x,y,z)@
     matrix([xa,xb,xc],[ya,yb,yc],[za,zb,zc])@
     %%%;
Pour l'exponentiation, c'est *Exponentie(indices,v1,v2,...)*
     %%%; nettoie()$
     Exponentie([a,b,c],x,y,z)@
     matrix([xa,xb,xc],[ya,yb,yc],[za,zb,zc])@
     %%%;

3.2.4 Faire sa déco
--------------------

Le fichier 'CDE_Pers,mac' contient un certain nombre de fonctions de
décorations.  Elles sont plus ou moins sophistiquées mais toutes
retournent une chaîne de caractère codée en Latex, comme, par
exemple Input and Output (Maxima) pour 'printf'

     %%%; printf(false,"\\begin{array}{l}{~a}\\\\{~a}\\end{array}",FaitLatex(expression1,""),FaitLatex(expression2,"")); %%%;

avec un '@'
     %%%; printf(false,"\\begin{array}{l}{~a}\\\\{~a}\\end{array}",FaitLatex(expression1,""),FaitLatex(expression2,""))@ %%%;

3.3 Gnuplot
===========

C'est maxima qui lance le process Gnuplot.  Par exemple
     %%%; plot2d(sin(x),[x,0,10])$ %%%;
Pour les options de tracé Gnuplot Options (Maxima)

Le tracé apparait sous la forme d'une fenêtre indépendante qu'il
faudra repositionner à la main, par exemple au dessus de 'whd'.

On peut aussi faire en sorte que le tracé se fasse dans le buffer
'jmaxima' par
     %%%; Pngplot2d(300,sin(x),[x,0,10])$ %%%;
où le premier argument est la taille de l'image qu'on veut obtenir.
Mais le résultat n'est pas formidable.  De plus c'est une image que
l'on voit et on ne dispose plus des commandes internes de Gnuplot pour
manipuler le tracé.

Et on peut souhaiter lancer Gnuplot de façon autonome
gnuplot.  Il y a un mode Gnuplot dans Emacs.  Ou encore on peut
fabriquer une fonction elisp

     (defun trace-avec-gnuplot (expr) ""
       (cond
        ((not (get-process "gnuplot"))
         (start-process-shell-command "gnuplot" nil "gnuplot")
         (process-send-string (get-process "gnuplot") "set term wxt persist\n"))
        (t (process-send-string (get-process "gnuplot") (concat expr "\n")))))

avec laquelle gnuplot se manie facilement (pourvu qu'on connaisse ses
commandes)
     (trace-avec-gnuplot "p cos(x) w li")

3.4 FreeFem++
=============

3.4.1 Fonctionnement de l'interface de FreeFem++
------------------------------------------------

L'interface avec FreFem++ fonctionne de la façon suivante :

   * Une liste 'lScript' d'instructions dans la syntaxe de FreeFem++
     étant créée par les fonctions ci-dessous ;

   * Cette liste d'instruction est placée dans un fichier qui est
     sauvé dans le répertoire temporaire de AppariteurMaxima, c'est
     réalisé par la fonction 'FFScript' appelée comme

          FFScript(nom-du-fichier-sans-extension-'.edp')

Et il y a alors une alternative.

3.4.1.1 Appel par Emacs
.......................

Pour que FreeFem++ soit appelé par Emacs, la fonction d'appel est
'FFexec' comme

     FFExec(nom-du-fichier-sans-extension-'.edp')

la sortie de FreeFem++ se fait dans un buffer appelé 'freefem' qui
apparaît dans whd lors de l'exécution.

Ce buffer est fouillé par Emacs et les sorties de FreeFem++
déclarées comme devant être transférées à Maxima sont rangée
dans une variable
     data_nom
('nom' étant le nom du fichier sans extension).

Par exemple
     %%%;
     FFInit()$
     FFDeclare('int,N=5)$
     FFDeclare(real[int],T(N))$
     FFBoucle(j,j>N,N,'[
      FFAffecte(T[j]=j)])$
     NFFCout(N,T)$
     FFgo()$
     %%%;
Les instructions situées au dessus de 'FFgo()' sont détaillées
Fonctions remplissant lScript, et 'FFgo' est une fonction qui
groupe les appels de 'FFScript' et 'FFExec' comme

     FFgo([nom]):=block([],if length(nom)=0 then nom:tst else nom:nom[1],FFScript(nom),FFexec(nom))$

On remarque que 'data_tst' contient bien un retour de 'FreeFem++'.

3.4.1.2 Appel par Maxima
........................

Pour que FreeFem++ soit appelé Maxima, les fonctions d'appels sont
   * 'FFScript(nom)' pour écrire les instuctions FreeFem++ dans un
     fichier de nom 'nom.edp' ;
   * 'FreeFem(nom)' pour l'appel de FreeFem++ proprement dit ;
   * et 'ffglut(nom)' pour les tracés, s'il y a lieu.
Les sorties de FreeFem++ se font dans un fichier 'nom.mac' qui est
placé dans le répertoire temporaire de la session (pas dans le
buffer 'freefem').

La sortie de la fonction 'FreeFem' est faite des sorties de FreeFem++
déclarées comme devant être transférées à Maxima.  (voir
l'exemple).

Par exemple
     %%%;
     FFInit()$
     FFDeclare('int,N=5)$
     FFDeclare(real[int],T(N))$
     FFBoucle(j,j>N,N,'[
      FFAffecte(T[j]=j)])$
     NFFCout(T)$
     NFFCout(N)$
     FFScript(tst)$
     res:FreeFem(tst)$
     res;
     %%%;
Les instructions situées au dessus de 'FFScript' sont détaillées
Fonctions remplissant lScript

On remarque que 'FreeFem++' contient bien un retour de 'FreeFem++' qui
est passé à la variable 'res'.

L'appel de ces trois fonctions est un peu lourd, on peut créer une
fonction sur le modèle de 'FFgo' (regarder dans 'CDE_FctF.mac')
     %%%;
     FFgoM([nom]):= block([],
      if length(nom)=0 then nom:tst else nom:nom[1],
       FFScript(nom),FreeFem(tst))$
     %%%;
avec laquelle l'exemple devient

     %%%;
     FFInit()$
     FFDeclare('int,N=5)$ FFDeclare(real[int],T(N))$
     FFBoucle(j,j>N,N,'[FFAffecte(T[j]=j)])$
     NFFCout(T)$NFFCout(N)$
     res:FFgoM(tst)$
     res;
     %%%;

Emacs ou Maxima ?
.................

Le choix d'appeler Freefem++ par Emacs ou par Maxima dépend de ce
qu'on veut faire.

   * Pour un simple calcul, choisir Emacs.

   * Pour des calculs où il est nécessaire de récupérer des
     valeurs pour les traiter et relancer d'autres calculs, ce sera
     plutôt Maxima.

     Cela assure a priori une meilleure synchronisation puisqu'il
     attend que le process dans lequel il lance 'FreeFem++' est
     synchrone et donc les instructions qui suivent cet appel sont en
     attente qu'il soit fini.

3.4.2 Fonctions remplissant lScript
-----------------------------------

3.4.2.1 FFDeclare
.................

C'est le driver des instructions de déclaration de 'FreeFem++'.  Par
exemple

     %%%;
     FFInit()$
     FFDeclare('real,x,y=1,z)$
     map(print,lScript)$
     %%%;

Sa syntaxe est

     FFDeclare(type,dec1,dec2,...)
où
   * 'type' est le type de la variable ; tout type reconnu par
     'FreeFem++' est légitime, et tout autre conduira à une erreur
     lors de l'exécution de 'FreeFem++'...
   * 'decn' est de la forme
        * atomique, i.e.  'x'
        * une paire avec égalité, i.e.  'x=1', et alors le membre de
          droite est la valeur d'affectation de la variable ;
        *
Pour déclarer un tableau
     %%%;
     FFInit()$
     FFDeclare(real[int],T=[1,2],U(5))$
     map(print,lScript)$
     %%%;
Mais on se limite aux tableaux simples (pas de double indice, comme le
permettrait 'FreeFem++').

Et pour déclarer quelque chose de plus compliqué, comme un champ en
précisant son support et interpolation, c'est comme pour les type
simples entiers et réels.

3.4.2.2 FFAffecte
.................

C'est le driver des instructions d'affectation de 'FreeFem++'.  Par
exemple

     %%%;
     FFInit()$
     FFAffecte(x=1,y=1,z=y)$
     map(print,lScript)$
     %%%;

Sa syntaxe est

     FFDeclare(aff1,aff,...)
où 'affn' est de la forme d'une paire avec égalité, i.e.  'x=1', et
alors le membre de droite est la valeur d'affectation de la variable.

L'affectation d'une valeur de tableau
     %%%;
     FFInit()$
     FFAffecte(T[1]=1,U[2]=1)$
     map(print,lScript)$
     %%%;
on remarque qu'on peut utilser des crochets comme des parenthèses, le
résultat est une parenthèse.  Et ce résultat est (pour l'instant)
compris par 'FreeFem++'.

3.4.2.3 FFCout
..............

C'est le driver de l'instruction 'cout'
<https://doc.freefem.org/references/IO.html> de sortie de 'FreeFem++'.
Par exemple

     %%%;
     FFInit()$
     FFCout(x,y)$
     map(print,lScript)$
     %%%;

Sa syntaxe est

     FFCout(s1,s2,...)
où 'sn' est une variable.

Pour un tableau
     %%%;
     FFInit()$
     FFDeclare(real[int],T(5))$
     FFCout(T)$
     map(print,lScript)$
     %%%;
Rien de particulier ne se produit.

3.4.2.4 NFFCout
...............

Comme 'FFCout' FFCout mais les sorties sont encadrés de
balises '#' qui donnent soit à macs soit à Maxima (suivant le mode
d'exécution Fonctionnement de l'interface de FreeFem++) la
consigne de récupérer ces sorties.  Par exemple

     %%%;
     FFInit()$
     NFFCout(x,y)$
     map(print,lScript)$
     %%%;

Pour un tableau
     %%%;
     FFInit()$
     FFDeclare(real[int],T(5))$
     NFFCout(T)$
     map(print,lScript)$
     %%%;
on remarque que la sortie est plus compliquée.  Elle est adaptée à
la lecture du tableau soir par Emacs soit par Maxima.

La récupération de tableaux de valeurs (NeoCDE) pour une
illustration.

3.4.2.5 FFVerbatim
..................

Sa syntaxe est
     FFVerbatim(s,[f])
où 's' est une chaîne de caractères, 'f' est soit absent, soit
prend la valeur 'fichier'.

Comme son nom l'indique, c'est la fonction qui range dans 'lScript' du
code 'FreeFem++' brut.  Par exemple

     %%%;
     FFInit()$
     FFVerbatim("real x=1;")$
     map(print,lScript)$
     %%%;
ou
     %%%;
     FFInit()$
     FFVerbatim("chemin-complet-de-fichier",fichier)$
     map(print,lScript)$
     %%%;

3.4.2.6 FFPlot
..............

C'est le driver de l'instructions de tracé 'plot'
<https://doc.freefem.org/references/functions.html#plot> de
'FreeFem++'.  Par exemple

     %%%;
     FFInit()$
     FFPlot(m,cmm="m")$
     FFPlot(m,cmm="m",bw)$
     map(print,lScript)$
     %%%;

     FFPlot(s1,s2,...)
où 'sn' est
   * le nom d'une variable qui peut être tracée (maillage, solution
     scalaire, champ de vecteur) ;
   * un indicateur comme 'bw' qui fait que le tracé se fait en noir
     et blanc ;
   * un argument légitime du 'plot' de 'FReeFem++'

3.4.2.7 FFSolve
...............

C'est le driver de l'instruction de résolution 'solve'
<https://doc.freefem.org/references/functions.html#solve> de
'FreeFem++'.  Par exemple

     %%%;
     FFInit()$
     FFSolve(prob,[a,ap],int2d(m,[],dx(a)*dx(ap)+dy(a)*dy(ap)+k*ap),int1d(m,2,a*ap),On(1,a=0))$
     map(print,lScript)$
     %%%;

Sa syntaxe est

     FFSolve(nom-du-problème,liste-variables,terme1,terme2,...)
où
   * 'nom-du-problème' est le nom du problème suivant la syntaxe de
     'FreeFem++' ;
   * liste-variables est une liste de deux termes : le premier est le
     ou les champs dont les valeurs seront calculées et la seconde
     est le ou les variations de ces champs.  Pour deux champs, ça
     sera

          [[a,b],[ap,bp]

   * les 'termen' sont
        * Des expressions de la forme

               int2d(nom-du-maillage,indicateur,intégrant)
        * où
             * 'nom-du-maillage' est le nom de la variable contenant
               le maillage ;
             * 'indicateur' est l'indicateur de sous-domaine sur
               lequel est faite l'intégrale ; on met '[]' pour
               indiquer que c'est sur tout le maillage ; et si
               l'indicateur est une liste, la condition s'exercera sur
               tous les éléments de la liste ;
             * 'intégrant' est l'expression à intégrer.

        * Des expressions de la forme

               int1d(nom-du-maillage,indicateur,intégrant)
        * où
             * 'nom-du-maillage' est le nom de la variable contenant
               le maillage ;
             * 'indicateur' est l'indicateur de ligne sur laquelle est
               faite l'intégrale ; si l'indicateur est une liste, la
               condition s'exercera sur tous les éléments de la
               liste ;
             * 'intégrant' est l'expression à intégrer.

        * Des expressions de la forme

               On(indicateur,p1,p2,...)
          où
             * 'indicateur' est l'indicateur de ligne sur laquelle est
               mise la condition de Dirichlet ; si l'indicateur est
               une liste, la condition s'exercera sur tous les
               éléments de la liste ;

             * 'pn' est la condition de Dirichlet

3.4.2.8 FtoFF
.............

La fonction *FtoFF* est une aide pour créer le second argument de
'FFSolve' automatiquement à partir d'une intégrale de CDE.

Sa syntaxe est
     FtoFF(nom-du-maillage,W,cvs)
où
   * 'nom-du-maillage' est la variable contenant le maillage ;
   * 'W' est l'expression à convertir ;
   * 'cvs' est une liste de conversion.

Les formes que peut prendre 'W'
...............................

Par exemple
     %%%; nettoie$
     GenCar()$ depends(phi,[x,y])$
     Integrant:xtav(nrm(grad(phi))^2)$
     W:Int3D(Integrant,D)@
     cvs:[[D,[]],[detJ,1]]$
     FtoFF(m,W,cvs)@
     %%%;
'Int3D(Integrant,D)' est mis sous une forme qui convient à 'FFsolve'
(et 'FFDeclare', 'FFAffecte').  Ici la liste de conversion
'[[D,[]],[detJ,1]]' ne contient presque rien.
   * '[D,[]]' est la syntaxe qui indique que le domaine 'D' correspond
     au maillage tout entier ;
   * '[detJ,1]' est la donnée du déterminant du jacobien pour
     l'élément de volume.

Maintenant un exemple un peu plus compliqué parce qu'on passe en
coordonnées cylindriques
     %%%; nettoie$
     GenCyl()$ depends(phi,[r,z])$
     Integrant:xtav(nrm(grad(phi))^2)$
     W:Int3D(Integrant,D)@
     cvs:[[D,[]],[r,x],[z,y],[detJ,2*pi*x]]$
     FtoFF(m,W,cvs)@
     %%%;
là on utilise 'r,z' comme nom de coordonnées, mais 'FreFem++' ne
connaît que 'x,y' d'où l'intérêt de la conversion : r -> x ; z ->
y ; et on indique que le déterminant du jacobien est x=2*pi*r (parce
qu'on suppose être en symétrie axisymétrique et qu'on fait
l'intégration par rapport à 'theta').

Ensuite un exemple à plusieurs intégrales dans 'W'
     %%%; nettoie$
     GenCyl()$ depends(phi,[r,z])$
     Integrant:xtav(nrm(grad(phi))^2)$
     W:Int3D(Integrant,D1)+2*Int3D(Integrant,D2)+Int3D(3*Integrant,D3)@
     cvs:[[D1,id1],[D2,id2],[D3,id3],[r,x],[z,y],[detJ,2*pi*x]]$
     FtoFF(m,W,cvs)@
     %%%;
la sortie est une liste qui sera interprétée comme autant de
d'intégrales à ajouter à 'solve' par 'FFsolve' et comme la somme
des intégrales par 'FFDeclare' et 'FFAffecte'.  On note que le
facteur multiplicatif de l'intégrale sur 'D2' est entré dans
l'intégrale.

'FtoFF' fonctionne de la même façon pour les intégrales 'Int2D'.

Le contenu à donner à 'cvs'
.............................

'cvs' est une liste de la forme
     [...,[X,x],...]
où
   * Si 'X' est un nom de domaine sur lequel se fait une intégrale,
     alors 'x' sera le ou les identificateurs de domaine du maillage
     qui lui correspond
        * Si 'x=[]', alors l'intégrale porte sur tout le maillage ;
        * Si 'x=[id1,id2]' alors l'intégrale porte sur chacun des
          sous-domaines du maillage qui correspondent à ces
          identificateurs ;
        * Si 'x=id' alors l'intégrale porte sur le sous-domaine
          d'identificateur 'id' dans le maillage '
        * et sinon, les symboles du domaine de l'intégrale et de
          l'identificteur de sous-domaine doivent être les mêmes.
   * Si 'X' est le symbole représentant une coordonnée et que
     l'intégrant comporte une dérivée première par rapport à
     cette coordonnée, alors cette dérivée sera remplacée ainsi
          %%%; depends(VV,r)$
          FtoFF(m,Int3D(diff(VV,r),D),[[r,x],[detJ,1]])@
          FtoFF(m,Int3D(diff(VV,r),D),[[r,y],[detJ,1]])@
          %%%;
   * et finalement, cvs doit comporter le déterminant du jacobien de
     l'éléments de volume (ou surface) de l'intégrale sous la forme
     '[detJ,val]' et cela dans les coordonnées 'x' et 'y'

3.4.2.9 FtoFFRec
................

La fonction *FtoFFRec* est appelée récursivement par 'FtoFF' pour
effectuer les conversions.  Mais elle peut être appelée
indépendamment.

Sa syntaxe est
     FtoFFRec(W,cvs)
où
   * 'expr' est l'expression à convertir ;
   * 'cvs' est une liste de conversion.

Par exemple
     %%%; nettoie()$ depends(f,r)$
     FtoFFRec(r*diff(f,r),[[r,x]])@
     %%%;

3.4.2.10 FFBoucle
.................

La structure de 'FFBoucle' est
     FFBoucle(nom-du-compteur,condition-d'arret,valeur-maximale-du-compteur,liste-d-instruction)
avec
   * 'nom-du-compteur', comme son nom l'indique ;
   * 'condition-d-arret', c'est la condition pour arrêter la boucle ;
   * 'valeur-maximale-du-compteur', c'est une deuxième condition
     d'arrêt (au cas où la première serait défectueuse).

'liste-d-instruction' est de la forme
     '[instruction1,instruction2,...]
où le quote ''' est indispensable.  Il a pour effet que la liste
d'instruction n'est pas exécutée lors de l'appel de la fonction
'FFBoucle', ce qui aurait pour effet de placer ces instruction en
dehors de la boucle dans le fichier '.edp', mais bien dans cette
boucle.

Cela vient du fait que les instructions ne font que remplir 'lScript'
Interface de FreeFem++ (NeoAppariteur).

Pour une illustration Le problème emblématique (NeoCDE).

3.4.2.11 FFDensite
..................

Inutile si on utilise FaitMaillage FaitMaillage

3.4.2.12 FFMinMax
.................

Syntaxe
     FFMinMAx(c1,c2,...)
renvoie les minimum et maximum des champs 'an'

3.4.2.13 FFFespace
..................

Syntaxe
     FFespace(nom-maillage,type)
où
   * 'nom-maillage' nom de la variable contenant le maillage ;
   * 'type' :
        * si 'type' est un symbole de
          <https://doc.freefem.org/references/types.html#fespace> ;
          crée le 'Fespace' de nom la concaténation de
          'nom-maillage' et de 'type'

3.4.2.14 FFBorderxxx
....................

Ces atrocités sont inutiles si on utilise FaitMaillage
FaitMaillage

3.4.2.15 FFMesh
...............

Inutile si on utilise FaitMaillage FaitMaillage

3.4.2.16 FFAdapt
................

Appelle 'adaptmesh'
<https://doc.freefem.org/references/functions.html#adaptmesh>

La syntaxe est
     FFAdapt(NomOut,NomIn,fct,...)
où
   * 'NomOut' maillage adapté ;
   * 'NomIn' maillage à adapter ;
   * 'fct' champ sur lequel se fait l'adaptation (ou expression d'une
     fonction) ;
   * '...' arguments de 'adaptmesh'

3.4.2.17 FFmovemesh
...................

<https://doc.freefem.org/references/functions.html#movemesh>

3.4.2.18 FaitMaillage
.....................

C'est une fonction globale qui permet d'éviter de créer
explicitement les 'border' et d'en faire un 'mesh'.  Son
fonctionnement est décrit Explications pour FaitMaillage (NeoCDE).

Voici comment elle remplit 'lScript' pour un maillage carré
          %%%;
          FaitMaillage('nom=m,'densite=10,
          'points=[p1=[0,0],p2=[1,0],p3=p2+p4,p4=[0,1]],
          'bords=[[sud,'Rec,p1,p2],[est,'Rec,p2,p3],[nord,'Rec,p3,p4],[ouest,'Rec,p4,p1]],
          'visus=['info,'bords,'maillage])$
          map(print,lScript);
          %%%;

Du point de vue interne, 'FaitMaillage' effectue des traitements sur
ses arguments de manière que ceux-ci définissent les données qui
peuvent être injectées aux FFBorders, à FFMesh et qui permettent de
trouver à quels sous-domaines du maillage correspondent les
identificateurs qu'on lui fournit.

Elle permet de plus d'effectuer ou non des visualisation de contrôle.

3.4.3 Voir le fichier edp
-------------------------

En cas d'erreur dans la compilation FreeFem++, la ligne qui pose
problème est généralement indiquée.

Si on a utilisé 'tst' comme nom de fichier (c'est ce qui est pas
défaut), on peut alors taper '<C-x q>' et elle apparait dans 'whg'
(avec le reste du fichier 'edp')

On peut également taper tape '<C-x w>' et le fichier 'tst' est lu et
placé dans 'whg'.

Sinon on peut toujours le trouver dans le répertoire temporaire
     %%%; jmaxima_temp; %%%;

3.4.4 Tracé de lignes de niveau
--------------------------------

L'intégration de FreeFem++ permet d'obtenir des lignes de niveau
autrement qu'en utilisant, par exemple Functions and Variables for Plotting (Maxima),
     %%%;
     ldnx(expr,x,y,n):=contour_plot(expr,x,y,[gnuplot_preamble,simplode(["unset clabel;set key off;set size ratio -1;set cntrparam levels ",n])])$
     ldnx(x^2-y^2,[x,-1,1],[y,-1,1],20)$
     %%%:
qui échoue pour, par exemple,
     %%%;
     ldnx(1/(x^2+y^2)+1/((x-0.5)^2+y^2),[x,-1,1],[y,-1,1],20)$
     %%%;

En utilisant *FFldlc(nom,densite,f,x_min_max,y_min_max)* où
'x_min_max' et 'y_min_max' sont des listes de la forme
'[x,xmin,xmax]', '[y,ymin,ymax]' et 'f' une expression dépendant de
'x' et 'y' fait apparaître les lignes de niveau de 'f' dans le
rectangle de coins 'xmin,ymin' et 'xmax,ymax'.  Par exemple

     %%%; FFldlc(tst,20,x^2-y^2,[x,-1,1],[y,-1,1])$ %%%;

*FFldlc* admet deux options.  D'abord l'adaptation de maillage qui se
présente comme un élément ajouté de la forme '['adapt,kmax]'

     %%%; FFldlc(m,20,x^2-y^2,[x,-1,1],[y,-1,1],['adapt,0.1])$ %%%;

L'effet de 'kmax' est celui de 'hmax=kmax/densite' dans la fonction
'adaptmedh' de FreeFem++
<https://doc.freefem.org/examples/mesh-generation.html>

La seconde option est l'exclusion de disques centrés sur un point
dans le maillage qui se présente comme un élément ajouté de la
forme '['Cex,[[x1,y1,r1],[x2,y2,r2],...]]'

     %%%; FFldlc(m,20,1/(x^2+y^2)+1/((x-0.5)^2+y^2),[x,-1,1],[y,-1,1],['Cex,[[0,0,0.1],[0.5,0,0.1]]])$ %%%;
C'est utile pour éviter les valeurs infinies.

le buffer 'freefem' fournit les valeurs max et min de 'f' sur le
maillage.

3.4.5 Utilisation des solveurs FreeFem++
----------------------------------------

FreeFem++ dispose de solveurs qui peuvent être utilisés
indépendamment.  Voici un exemple de driver pour 'NLCG'
<https://doc.freefem.org/references/functions.html#nlcg>

     %%%;
     FFVars2Tab(nomX,Vars,sep):=block([%cnv:printf(false,"~a[~a]=~a",nomX,"~a","~a"),res],
      res:map(lambda([%n,%u],[printf(false,%cnv,%n,%u),sep]),makelist(j,j,0,length(Vars)-1),Vars),
      res:rest(flatten(res),-1),
      apply(concat,res))$

     FFTab2Vars(nomX,Vars,sep):=block([%cnv:printf(false,"~a=~a[~a]","~a",nomX,"~a"),res],
      res:map(lambda([%n,%u],[printf(false,%cnv,%u,%n),sep]),makelist(j,j,0,length(Vars)-1),Vars),
      res:rest(flatten(res),-1),
      apply(concat,res))$

     FFNLCG(dF,X,X0):=block([res],
      FFInit(),FFDensite(10,17),
      res:printf(false,
     "real[int] X(~a);~%int conv;~a;~%
       func real[int] Iteration (real[int] &X) {real ~a;~a;return X;};~%
       conv=NLCG(Iteration,X,eps=1.0e-12);~%
       real ~a;",
       length(X),FFVars2Tab('X,X0,";"),FFTab2Vars('X,X,";"),FFVars2Tab('X,dF,";"),FFTab2Vars('X,X,",")),
       res:append([res],map(lambda([%u],printf(false,"cout << \"#\" << ~s << \"=\" << ~a << \"#\" << endl;",%u,%u)), append([conv],X))),
       lScript:append(lScript,res),
       FFScript(tst),FreeFem(tst))$

     F:2*x^4+y^4+z^4+4-x-y-z;
     dF:map(lambda([%u],diff(F,%u)),[x,y,z]);
     res:FFNLCG(dF,[x,y,z],[0,0,0]);
     %%%;

Ça peut être nettement amélioré, cette version est juste fournie à
titre d'exemple.

4 Modes Latex ; Html ; Octave...
********************************

4.1 Latex
=========

Lorsqu'un buffer est associé à un fichier de suffixe '.tex', le mode
Latex standard d'Emacs est activé (taper '<C-h m>' dans un buffer
correspondant à un fichier d'extension 'tex' pour obtenir toutes les
commandes du mode).

Appariteur ajoute des fonctionnalités.

   * '<S-return>' cesse d'envoyer ce qui se trouve entre les balise
     '%%%;' et envoie (après l'avoir sauvé) le fichier à la
     compilation par 'Pdflatex'.

     Les fichiers intermédiaires de la compilation sont placés dans
     le répertoire temporaire (faire '<C-x-e>' derrière directory))
          (format "%sTex-tmp" temporary-file-directory)
     y compris le fichier 'pdf' produit.

     Ce fichier doit être lu par un visionneur externe ('qpdfview'
     sous Linux ou 'sumatra' sous Windows) qu'on doit appeler de
     façon externe.  On peut aussi l'appeler par '<C-v>' ou
     'sumatra') ; Emacs pourrait le lire aussi mais c'est moins
     efficace.  Et il est conseillé de choisir dans les options un
     mode où ce viewver détecte les changements dand le fichier de
     manière que l'affichage soit quasiment synchrone à la
     compilation.

     La case 'TeX' de la barre de menu a été laissée, mais elle ne
     sert plus à rien en principe.

   * Pour commencer un nouveau fichier, on peut
        * faire '<C-x-f>' et taper le nom du nouveau fichier ;

        * invoquer un canevas pour article par Latex -> Nouvel article
          dans le menu Action -> Latex.

          Cela fera apparaître le préambule
               \documentclass[a4paper,oneside,10pt]{article}
               \usepackage[utf8]{inputenc}\usepackage[french]{babel}\usepackage{graphicx}\usepackage{amsfonts,amssymb}\usepackage{amsmath}\usepackage{url}
               \textwidth 16.8cm\oddsidemargin -.25in\evensidemargin -.25in\topmargin -1.0in\textheight 26.5cm
               \newcommand{\frm}[1]{}\newcommand{\scriptM}[1]{}\newcommand{\rfs}[1]{(\ref {#1})}

               \title{}
               \author{Votre nom, comme le système le connaît}
               \date{\today}

               \begin{document}\maketitle
               \end{document}

   * Dans le préambule, il y a deux macros :
          \newcommand{\frm}[1]{}\newcommand{\scriptM}[1]{}
     inactives pour la compilation Latex.

     Par contre si on écrit (entre le begin{document} et
     end{document})
          \frm{ a/b } $ $
     qu'on se place à l'intérieur des accolades, et qu'on tape
     '<C-return>', on obtient
          \frm{ a/b } $\frac{a}{b}$
     Et si on regarde le buffer 'jmaxima' on voit que la commande
     'Latex(a/b)' a été exécutée.

     On peut aussi remplacee '$ $' par '$$ $$' ou '\begin{equation}
     \end{equation}'.

     Il n'est pas possible de mettre un script entier dans \frm{} ; le
     contenu ne doit pas contenir de séparateur d'instructions.

   * Par contre
          \newcommand{\scriptM}[1]{}
     fonctionne de la même façon que '\frm{ }', à ceci près que
        * elle n'insère aucun code Latex dans le fichier ;
        * elle peut contenir des séparateurs d'instruction.

     Elle sert en fait à préparer des affectations pour ne pas être
     obligé de retaper plusieurs fois les même instruction Maxima si
     on les utilise plusieurs fois dans le texte.

   * Si on tape '<C-l>' on obtient
          \frm{ } \begin{equation}\label{aa} \end{equation}
     Ça donne un cadre pour les équations.

     L'équation est affectée à un label 'aa' générique qui sera
     changé par le mécanisme ci-dessous.

   * Si on tape '<C-x o>', les labels des équations sont réordonnés
     de manière que le numéro de label corresponde exactement à la
     place de l'équation dans le texte.

     Si on a effectué les références aux équations par '\\rfs{ }'
     (voir dans le préambule), les labels sont également changés de
     manière cohérente (en principe)

     Ça évite les casses-têtes pour accorder les labels internes.

   * Si on tape '<C-'>'

     L'ensemble des contenus de \script{} et \frm{} sont exécutés
     depuis le début du fichier jusqu'à la fin et toutes les
     équations sont regénérées.

4.2 Html
========

Lorsqu'un buffer est associé à un fichier de suffixe '.html', le
mode html standard d'Emacs est activé (taper '<C-h m>' dans un buffer
correspondant à un fichier d'extension 'html' pour obtenir toutes les
commandes du mode).

En partant de l'idée qu'un fichier html est complété d'un
répertoire (de même nom que celui du fichier) contenant toutes les
images proposées par le fichier,

Appariteur ajoute des fonctionnalités.

Ces fonctionnalités sont

   * <'C-l'> et <'C-o'> font apparaître les canevas '<!-- --> <img
     />' et '<div><!-- --> <img /></div>'

   * On peut écrire une expression Maxima (sans séparateur
     d'instructions) entre les '<!-- -->' ; si on tape (toujours avec
     le curseur entre les '<!-- -->') '<C-return>'

        * cette expression est envoyée à Maxima en demandant une
          sortie d'image d'équation (le résultat apparaît dans le
          buffer jmaxima) ;
        * le fichier de cette image est copié dans un répertoire de
          même nom (sans l'extension) que celui du fichier
          correspondant au buffer dans lequel on travaille :

             * si le répertoire n'existe pas, il est créé comme
               sous-répertoire du répertoire où est localisé le
               fichier html ;
             * s'il existe déjà il est utilisé.

   * le nom de ce fichier image est 'eq<num>' où '<num>' est un
     nombre incrémenté à chaque création de fichier 'eq<num>'.  Le
     compteur est
          jmaxima-compteur
     Au début d'une reprise de session, il peut être mis à une
     valeur qui excède celle qui sont déjà utilisées dans le
     répertoire d'équations par '<C-r>'.

     Il doit même l'être pour éviter que des fichiers d'équation
     existant déjà soient écrasés par de nouveaux.

   * On peut écrire un script Maxima (qui ne produit pas d'insertion
     d'image) dans un fichier html en le plaçant entre '<~--%%%;
     %%%;-->' ; la commande d'exécution est le standard '<S-return>'.

   * Et on peut faire exécuter des commandes en série (script comme
     expression simple produisant une image) par '<C-'>' ; seules
     celles qui sont placées après la postion du curseur le seront.

4.3 Mode Octave
===============

Le mode octave d'Emacs est bien sûr disponible Octave

On s'est contenté d'ajouter quelques éléments de 'Hook'
Hooks (Emacs); ceux-ci sont

   * dans Personnel.el, c'est

            (defun HookOctave () (interactive)
          	 (load-file (concat appariteur-directory "/HookOctave.el")))
            (add-to-list 'auto-mode-alist '("\\.m" . octave-mode))
            (add-hook 'octave-mode-hook 'HookOctave)

   * et dans HookOctave.el dont le contenu est

     (define-key octave-mode-map (kbd "C-<return>") 'octave-send-line)
     (define-key octave-mode-map (kbd "S-<return>") 'octave-envoie-entre-balise)

     (let ((cw (selected-window))(cb (current-buffer)))
       (select-window wbd)
       (run-octave t)
       (switch-to-buffer "*Inferior Octave*")
       (select-window cw)
       (switch-to-buffer cb))

     (defun octave-envoie-entre-balise ()
       (interactive)
       (let ((cb (current-buffer)) s (px (point)) p0 p1)
         (setq p0 (search-backward "%%%;" nil t))
         (cond
          ((not p0) (message "Pas de balise '%%%;' en amont"))
          (t (setq p0 (+ p0 4))
     	(goto-char px)
     	(setq p1 (search-forward "%%%;" nil t))
     	(cond
     	 ((not p1) (message "Pas de balise '%%%;' en aval"))
     	 (t (setq p1 (- p1 4))
     	    (goto-char px)
     	    (setq s (buffer-substring-no-properties p0 p1))
     	    (process-send-string (get-process "Inferior Octave") s)
     	    ))))
         (switch-to-buffer cb)))

Brièvement, chaque fois qu'on charge un fichier d'extention '.m',
emacs le reconnaît comme un fichier Octave et lance le mode Octave.

Ce mode est amendé avec un moyen commode d'envoyer une ligne par
'<C-return>' (là on a juste intercepté une commande du mode Octave)
; et un autre pour envoyer un script entre balises '%%%;' par
'<S-return>'.

Ces combinaisons de touches n'ont effet que dans le buffer affecté
par le mode Octave, elles restent dédiées à Maxima ailleurs (sauf
dans les buffers Latex et Html où elles ont l'effet des hooks
apportés aux modes correspondant).

4.4 Faire une sorte de mode
===========================

La définition donnée par Emacs des modes Modes (elisp) est
assez contraignante.  Notamment il ne faut pas qu'un mode pertube le
fonctionnement d'un autre mode lorsqu'ils sont simultanément
utilisés (sur des buffers différents cependant).

C'est la raison pour laquelle Appariteur n'a pas été appelé un
mode.

Mais on n'a pas besoin de respecter cette règle lorsqu'on souhaite
juste utiliser Emacs pour faire quelque chose qu'il fait bien.  On
peut fabriquer une 'sorte de mode'.

Par exemple, 'imagemagick'...

5 Troubles et Bugs
******************

** Appariteur gère mal les cas où Maxima demande des informations en
cours de calcul ; si cela arrive envoyer manuellement la réponse
demandée comme
     %%%; nettoie()$ forget(a>1);
     integrate(1/x,x,1,a);
     %%%;
dans ce cas envoyer
     %%%;
     p;
     %%%;
On peut aussi faire '<CTRL>-x c' qui envoie un 'SIGNIT' suivi de
'<CTRL>-<SHIFT>-p' pour récupérer le prompt.

Je n'ai pas tenté d'améliorer cela parce que l'objectif d'Appariteur
est d'exécuter des suites d'instructions sans ambiguïtés plutôt
que de faciliter l'usage interactif.  En amont de l'intégration, on
aurait dû préciser que a était positif comme
     %%%; nettoie()$
     assume(a>1)$
     integrate(1/x,x,1,a);
     %%%;

** Dans tous les cas, l'arme absolu est de tuer le process Maxima et
de le relancer.

Ça se fait avec '<alt-end>' pour le tuer et '<alt-home>' pour le
relancer.

** Il peut arriver que des appels à Latex trop rapprochés saturent
la fonction filtre.  Dans ce cas les expressions apparaissent sous la
forme '^E latex <expression> ^E', comme ici (avec une machine
puissante, il faut mettre plus de 25)
     %%%;
     map(lambda([%u],Latex(%u)),makelist(expand((x+1)^i),i,0,25))$
     %%%;
dans ce cas on peut récupérer les expressions avec '<C-x z>'

** Dans les expressions passées à FreeFem++, se méfier des fraction
numériques.  Par exemple '1/2' peut être interprété comme le
quotien de la division entière, c'est à dire 0, alors qu'on a
certainement voulu que ce soit '0.5'.

** Lors des appels à FreeFem++ le buffer jmaxima doit être dans wbd
(les réponses de FreeFem++ s'affichent dans wbd systématiquement).
Là c'est un vrai bug !

6 Index
*******

Concepts
--------

Fonctions et variables
----------------------