; .EnTete "Le-Lisp (c) version 15.2" " " "L'e'diteur vide'o minimum PEPE"
; .EnPied "pepe.ll" "M-%" " "
; .Annexe M "L'e'diteur vide'o minimum PEPE"
; .nr % 1
;
; .Centre "*****************************************************************"
; .Centre " Ce fichier est en lecture seule hors du projet ALE de l'INRIA.  "
; .Centre " Il est maintenu par ILOG SA, 2 Avenue Gallie'ni, 94250 Gentilly "
; .Centre " (c) Le-Lisp est une marque de'pose'e de l'INRIA                 "
; .Centre "*****************************************************************"

; .Centre "$Header: pepe.ll,v 4.2 88/11/23 10:44:11 gallou Exp $"

(unless (>= (version) 15.21)
        (error 'load 'erricf 'pepe))

; Tous les symboles pre'ce'de's de : seront cre'e's dans le package PEPE.

(defvar #:sys-package:colon 'pepe)

(add-feature 'pepe)

; PEPE  est l'e'diteur minimum de Le←Lisp version 15.2. 
; Il permet d'e'diter des fichiers ou n'importe quelle
; expression Lisp. Il fonctionne sur tout terminal vide'o
; qui doit au moins permettre l'effacement de tout
; l'e'cran et le positionnement absolu du curseur.

; Le tampon de PEPE est une liste de chai↑nes de caracte`res,
; chacunes d'elles repre'sentant une ligne.
; Cette repre'sentation qui a le me'rite de la simplicite'
; entrainera la fabrication d'une nouvelle chai↑ne pour chaque
; caracte`re tape'.

; PEPE, tout comme EMACS, garde les proprie'te's suivantes\ :
;  - e'crit entie`rement en Lisp
;  - extensible tre`s facilement
;  - inde'pendant vis-a`-vis du mate'riel
;  - reaffichage asynchrone.

; Le terminal virtuel doit e↑tre charge' et initialise' 
; avant de lire ce fichier par exemple au moyen de :
;       (initty)

; .Section "Les Variables Globales"

; La pre'sence de ces variables globales, empe↑che PEPE
; d'e↑tre reentrant.

(defvar :buffer ())         ; le tampon des lignes
(defvar :xcursor 0)         ; X courant
(defvar :ycursor 0)         ; Y courant
(defvar :column 0)          ; colonne courante
(defvar :ydisplay 0)        ; nume'ro de la 1e`re ligne visible
(defvar :file "tmp")        ; nom du fichier courant
(defvar :commands ())       ; liste des commandes
(defvar :escommands ())     ; liste des ESC-commandes
(defvar :modbuf ())         ; indicateur de tampon modifie'
(defvar :kill ())           ; la chai↑ne du dernier kill
(defvar :searchstrg "")     ; la chai↑ne de la dernie`re recherche

; Quelques DEFVAR supple'mentaires, pour s'accorder au nouveau comportement du
; compilateur : les utilisations de variables dynamiques doivent e↑tre voulues.

; ces 6 variables sont utilisees par :matchparent, :curlexnext, :curchar

(defvar :x)			; copie locale de Xcursor
(defvar :y)			; copie locale de Ycursor
(defvar :l)			; pointeur courant dans la ligne
(defvar :s)			; longueur actuelle de la ligne pointe'e par :l
(defvar :fm)			; la ligne courante
(defvar :char)			; le caracte`re courant dans la ligne

; ces 2 variables sont utilisees par pepefile, :[true]redisplay, :clrscreen, 
;                                    :fillminibuf[nb], :help et evalbuffer:eol

(defvar :oscreen)		; copie en memoire de l'e'cran
(defvar :nscreen)		;

; cette variable est utilise'e dans :evalbuffer et :evalbuffer:eol

(defvar :xy)		        ; sauvegarde de :-xmax-1 le temps d'e'valuer


; cette variable est utilise'e dans :redisplay et :fillminibufnb

(defvar :pos)		        ; position a` partir de laquelle on e'crira


; variables de'finies dans pepefile, figeant l'espace de la fene↑tre PEPE

(defvar :xmax)
(defvar :xmax+1)
(defvar :xmax/2+2)
(defvar :xmax/2-2)
(defvar :xmax+1*ymax)
(defvar :-xmax+1)
(defvar :ymax)
(defvar :ymax+1)
(defvar :ymax-1)
(defvar :ymax/2)
(defvar :ymax/4)


; .Section "La Boucle Principale"

(df pepe (:f)
    ; la forme FSUBRe'e de la fonction suivante
    (pepefile :f))

(de pepefile (:f)
    ; la fonction qui e'value son nom de fichier
    (let ((:xmax         (tyxmax))
          (:ymax         (tyymax))
          (:xmax+1       (add1 (tyxmax)))
          (:-xmax+1      (sub 0 (add1 (tyxmax))))
          (:xmax-1       (sub1 (tyxmax)))
          (:xmax/2+2     (add (div (tyxmax) 2) 2))
          (:xmax/2-2     (sub (div (tyxmax) 2) 2))
          (:ymax+1       (add1 (tyymax)))
          (:ymax-1       (sub1 (tyymax)))
          (:ymax/2       (div (tyymax) 2))
          (:ymax/4       (div (tyymax) 4))
          (:xmax+1*ymax  (mul (add1 (tyxmax)) (tyymax))))
      (let ((:oscreen (makestring (mul :xmax+1 :ymax+1) #\SP))
	    (:nscreen (makestring (mul :xmax+1 :ymax+1) #\SP)))
	(:clrscreen)
	(ifn :f
	     (unless :buffer (setq :buffer (list "")))
	     (setq :file "tmp" :xcursor 0 :ycursor 0 :column 0 :ydisplay 0
		   :modbuf ())
	     (cond
	      ((equal :f t)		; je veux un fichier scratch
	       (setq :buffer (list "")))
	      ((atom :f)		; ce doit e↑tre un fichier qui existe
	       (tag eoc (setq :buffer (:readfile :f)))
	       (setq :file (string :f)))
	      (t			; c'est donc un PROGN a` e'valuer
	       (setq :buffer (list ""))
	       (let ((#:sys-package:itsoft ':eval))
		 (eval :f))
	       (setq :buffer (nreverse :buffer)))))
	(typrologue)
	;
	; le top-level proprement dit de PEPE
	;
	(untilexit pepe
		   (tag eoc
			(:redisplay)
			(tycursor :xcursor :ycursor)
			(:pepecmd (tyi))))
	; je sors de PEPE : qu'Il soit avec vous!
	(tycursor 0 :ymax)
	(tycleol)
	(tycursor 0 :ymax-1)
	(tycleol)
	(tyepilogue)
	(tyflush)
	'pepe))))))

(de :eval:eol ()
    ; re'cupe'ration de la ligne imprime'e
    ; s'il faut e'diter le re'sulat d'une e'valuation
    (newl :buffer (substring (outbuf) 0 (outpos)))
    (fillstring (outbuf) 0 #\SP (outpos))
    (outpos (lmargin)))

; .Section "Les interpre`tes des commandes"

(de :pepecmd (c)
    ; interpre`te la commande <c>
    ; la A-liste des commandes se trouve dans :commands
    (let ((l (cassq c :commands)))
         (if l (eprogn l)
             ; ce n'est pas une commande
             (if (lt c 32)
                 (:deadend)
                 (:insertchar c))))
    (when (setq c (tys))
          (:pepecmd c)))

(de :escommand ()
    ; L'interpre`te des commandes <esc> X
    ; la A-Liste des commandes se trouve dans :escommands
    (let ((c (tyi)))
         ; passage en majuscule
         (when (and (ge c #/a) (le c #/z))
               (setq c (sub c 32)))
         (let ((l (cassq c :escommands)))
              (if l (eprogn l) (:deadend)))))

; .Section "Les fonctions d'affichage"

; A de rares exceptions, ces fonctions n'utilisent pas
; les fonctions du terminal virtuel mais la fonction de
; reaffichage asynchrone REDISPLAYSCREEN.

(de  :redisplay ()
     ; reaffiche toute la fene↑tre visible
     (fillstring :nscreen 0 #\SP)
     (let ((y :-xmax+1)
           (:pos (add :xmax+1*ymax :xmax/2-2))
           (s (length :buffer))
           (lib1 "Pepe: ")
           (l (nthcdr :ydisplay :buffer)))
          ; affiche le texte
          (repeat :ymax
                  (bltstring :nscreen (setq y (add y :xmax+1))
                             (car l) 0 :xmax+1)
                  (when (and (car l) (gt (slen (nextl l)) :xmax+1))
                        (sset :nscreen (add y :xmax) #/\)))
          ; affiche la "who-line"
          (fillstring :nscreen :xmax+1*ymax #\SP :xmax)
          (:fillminibuf 0 lib1)
          (:fillminibuf (slen lib1) :file)
          (:fillminibufnb s)
          (sset :nscreen (setq :pos (sub1 :pos)) #//)
          (:fillminibufnb (add1 (add :ydisplay :ycursor)))
 ;          (setq :pos (sub1 :pos))
 ;          (:fillminibufnb (slen (:currentline)))
 ;          (sset :nscreen (setq :pos (sub1 :pos)) #//)
 ;          (:fillminibufnb (add1 :xcursor))
          (:fillminibuf :xmax/2-2 (if :modbuf " <M> " "    "))
          (:trueredisplay)))

(dmd :trueredisplay ()
     `(redisplayscreen :nscreen :oscreen :xmax+1 :ymax+1))

(dmd :fillminibuf (x strg)
     ; e'crit dans la dernie`re ligne a` partir de <x> la chai↑ne <strg>
     `(bltstring :nscreen (add :xmax+1*ymax ,x) ,strg 0))

(de  :fillminibufnb (nb)
     ; e'crit dans :nscreen a` partir de <:pos> la valeur nume'rique <nb>
     (sset :nscreen (setq :pos (sub1 :pos)) (add #/0 (rem nb 10)))
     (when (ge nb 10)
           (:fillminibufnb (div nb 10))))

(de  :clrscreen () 
     ; efface tout l'e'cran
     (tycursor 0 0) 
     (tycls)
     (fillstring :oscreen 0 #\SP))

; .Section "Les fonctions de dialogue"

(de :more ()
    ; demande s'il faut continuer les impressions.
    (slet ((prmpt " Encore? ")
           (lenpr (slen prmpt)))
          (:fillminibuf :xmax/2+2 prmpt)
          (:trueredisplay) 
          (tycursor (add :xmax/2+2 lenpr) :ymax)
          (unless (chrpos (tyi) " YyOoTt") (exit eoc))
          (:fillminibuf :xmax/2+2 (makestring lenpr #\SP))))

(de :readname (strg)
    ; Lecture d'une chai↑ne sur le terminal
    ; <strg> est la chai↑ne d'invite
    (:fillminibuf :xmax/2+2 strg)
    (let ((l) (c) (p (add :xmax/2+2 (slen strg))))
         (:trueredisplay)
         (tycursor p :ymax)
         (while (neq (setq c (tyi)) #↑M)
                (cond ((eq c #↑G) (exit eoc ()))
                      ((eq c #\BS) 
                       (:fillminibuf (setq p (sub1 p)) " ") 
                       (setq p (sub1 p))
                       (nextl l))
                      (t (:fillminibuf p (list c)) (newl l c)))
                (:trueredisplay)
                (tycursor (setq p (add1 p)) :ymax))
         (if l (string (nreverse l)) (exit eoc "")))))

; .Section "Les Fonctions Auxiliaires"

(dmd :deadend ()
     ; fin de la route : on ne plus plus bouger!
     `(progn (tybeep) (exit eoc)))

(dmd :currentline ()
     ; retourne la ligne courante
     `(nth (add :ydisplay :ycursor) :buffer))

(dmd :currentlines ()
     ; retourne la liste commencant par la ligne courante
     `(nthcdr (add :ydisplay :ycursor) :buffer))

(dmd :cursor (x y)
     ; change la position du curseur de PEPE
     `(setq :xcursor ,x :ycursor ,y))

; .Section "Une Brouette de Pre'dicats Utiles"

(dmd :bolp ()
     ; teste si on se trouve en de'but de ligne
     `(eqn :xcursor 0)))

(dmd :eolp ()
     ; teste si on se trouve en fin de ligne
     `(ge :xcursor (slen (:currentline))))

(dmd :bobp ()
     ; teste si on se trouve en de'but de buffer
     `(and (eqn :ydisplay 0) (eqn :ycursor 0)))

(dmd :eobp ()
     ; teste si on se trouve en fin de buffer
     `(ge (add1 (add :ydisplay :ycursor)) (length :buffer)))

(dmd :bosp ()
     ; teste si on se trouve au de'but de l'e'cran
     `(eqn :ycursor 0))

(dmd :eosp ()
     ; teste si on se trouve a` la fin de l'e'cran
     `(ge :ycursor :ymax-1))

; .Section "Les Commandes de Base de PEPE"

(de :left ()
    ; un coup a` gauche
    (ifn (:bolp)
         (setq :column (setq :xcursor (sub1 :xcursor)))
         (:up) (:endline)))

(de :right ()
    ; un coup a` droite
    (ifn (:eolp)
         (if (ge :xcursor :xmax)
             (:deadend)
             (setq :column (setq :xcursor (add1 :xcursor))))
         (:begline) 
         (:down)))

(de :endline ()
    ; va a` la fin de la ligne
    (setq :xcursor (imin (slen (:currentline)) :xmax)
          :column :xcursor))

(de :begline ()
    ; va au de'but de la ligne
    (setq :xcursor 0 :column 0)))

(de :up ()
    ; va a` la ligne pre'ce'dente
    (if (:bobp)
        (:deadend)
        (ifn (:bosp)
             (setq :ycursor (sub1 :ycursor)
                   :xcursor (imin :column
                                     (slen (:currentline))))
             (setq :ydisplay (sub :ydisplay (add1 :ymax/4))
                   :ycursor (add :ycursor :ymax/4))
             (when (lt :ydisplay 0)
                   (setq :ydisplay 0 :ycursor 0)))
        (setq :xcursor (imin :column (slen (:currentline))))))

(de :down ()
    ; va a` la ligne suivante
    (if (:eobp)
        (:deadend)
        (if (:eosp)
            (setq :ydisplay (add :ydisplay (add1 :ymax/4))
                  :ycursor (sub :ycursor :ymax/4))
            (setq :ycursor (add1 :ycursor)))
        (setq :xcursor (imin :column (slen (:currentline))))))

(de :nextscreen ()
    ; passe a` l'e'cran suivant
    (when (gt (add :ydisplay :ymax-1) (length :buffer))
          (:deadend))
    (setq :ydisplay (add :ydisplay :ymax-1))
    (:begline))

(de :prevscreen ()
    ; passe a` l'e'cran pre'ce'dent
    (when (lt (setq :ydisplay (sub :ydisplay  :ymax-1)) 0) 
          (setq :ydisplay 0))
    (:begline))

(de :insertchar (c)
    ; rajoute le caracte`re <c> a` la position courante
    ; re`gle le pb du bltstring a` droite sur la me↑me chai↑ne.
    (let* ((l (:currentlines))
           (s (catenate " "  (car l))))
          (if (ge :xcursor :xmax)
              (:deadend)
              (bltstring s 0 s 1 :xcursor)
              (sset s :xcursor c)
              (rplaca l s))
         (setq :column (setq :xcursor (add1 :xcursor)))
         (setq :modbuf t)))

(de :deletechar ()
    ; enle`ve le caracte`re a` la position du curseur
    (let ((l (:currentlines)) 
          (s))
         (if (:eolp)
             (rplac l (catenate (car l) (cadr l)) (cddr l))
             (setq s (makestring (sub1 (slen (car l))) #\SP))
             (bltstring s 0 (car l) 0 :xcursor)
             (bltstring s :xcursor (car l) (add1 :xcursor))
             (rplaca l s)))
    (setq :modbuf t))

(de :breakline ()
    ; casse la ligne a` la position du curseur
    (let ((l (:currentlines)))
         (ifn (:eolp)
              (rplac l (substring (car l) 0 :xcursor)
                       (cons (substring (car l) :xcursor) (cdr l)))
              (rplacd l (cons "" (cdr l))))
         (setq :modbuf t)))

(de :killine ()
    ; de'truit la ligne courante
    (setq :modbuf t)
    (cond ((:bobp)
             (setq :kill (nextl :buffer))
             (when (null :buffer)
                   (setq :buffer (list ""))))
          ((:eobp)
             (let ((l (nthcdr (sub1 (add :ydisplay :ycursor)) :buffer)))
                  (setq :kill (cadr l))
                  (rplacd l (cddr l))
                  (:up)))
          (t (let ((l (:currentlines)))
                  (setq :kill (car l))
                  (rplac l (cadr l) (cddr l)))))
    (when (lt (slen (:currentline)) :xcursor)
          (:endline))))

; .Section "Les Fonctions de Recherche"

(de  :search ()
     ; cherche une chai↑ne de caracte`res
     (let ((s (tag eoc (:readname " Chaine? ")))
           (f (:currentlines))
           (y 0)
           (r))
          (cond ((null s) (exit eoc))
                ((eqstring s "") (setq s :searchstrg))
                (t (setq :searchstrg s)))
          (setq r (index s (nextl f) :xcursor))
          (untilexit search
               (cond
                   (r (:gotoabs (add r (slen s)) y)
                      (exit search))
                   ((null f) (:deadend))
                   (t (setq r (index s (nextl f) 0)
                            y (add1 y)))))))

(de :gotoabs (x y)
    ; se positionne en <x> et <y> du tampon
    ; <y> est en relatif par rapport a` :ycursor
    ; Si ce n'est pas sur l'e'cran se positionne au
    ; milieu de la fene↑tre visible.
    (setq :xcursor x :column x)
    (let ((y (add :ycursor y)))
         (if (gt y :ymax-1)
             (setq :ydisplay (sub (add :ydisplay y) :ymax/2)
                   :ycursor :ymax/2)
             (setq :ycursor y))))


(de :matchparent (c)
    ; Ve'rificateur de parenthe`ses a` la Lisp
    ; <c> peut e↑tre une parenthe`se ou un crochet.
    (slet ((:fm (:currentlines))
           (:x :xcursor)
           (:y 0)
           (:l (nextl :fm))
           (:s (slen :l))
           (:char))
          (until (eqn (:curlexnext) c))
          (:gotoabs :x :y)))

(de :curlexnext ()
    (selectq (:curchar)
             (#/( (until (eqn (:curlexnext) #/))) #/()
             (#/[ (until (eqn (:curlexnext) #/])) #/[)
             (#/| (until (eqn (:curchar) #/|))    #/|)
             (#/" (until (eqn (:curchar) #/"))    #/")
             (#/# (selectq (:curchar)
                     ((#/( #/[ #/") (:curlexnext))
                     (#// (:curchar) #//)
                     (t :char)))
             (#/; (setq :x :s) (:curlexnext))
             (t :char)))

(de :curchar ()
    (while (ge :x :s)
           (if (null :fm)
               (:deadend)
               (setq :x 0
                     :y (add1 :y)
                     :l (nextl :fm)
                     :s (slen :l))))
    (setq :char (sref :l :x)
          :x    (add1 :x))
    :char)

; .Section "Les Fonctions sur les Fichiers"

(de :readfile (f)
    ; Lecture d'un fichier : retourne une liste (non vide) 
    ; de lignes d'au plus :xmax caracte`res.
     (let ((ll)
           (in (probefile f)))
          (if in
              ; c'est un fichier connu
              (with ((inchan (openi f)))
                    (inmax 0)
                    (untilexit eof (newl ll (readstring)))
                    (if (consp ll) (nreverse ll) (list "")))
              ; c'est un nouveau fichier
              (tybeep)          ;  pour indiquer une cre'ation!
              (list ""))))

(de :writefile (f)
    ; Ecriture d'un fichier
    (let ((out (catcherror () (openo f))))
         (unless (consp out) (:deadend))
         (with ((outchan (car out))
                (lmargin 0)
                (rmargin (sub1 (slen (outbuf)))))
               (let ((:xcursor :xcursor)
                     (:ycursor :ycursor)
                     (#:system:print-for-read ()))
                    (:cursor 0 :ymax)
                    (mapc 'print :buffer))
               (close (outchan)))    ; Redde Caesari quae sunt Caesaris !
         (setq :modbuf ())))

(de  :insertfile ()
     ; Insert un fichier a` la position du curseur.
     (let ((l (:currentlines)))
          (rplacd l (nconc (:readfile (:readname " Fichier? "))
                           (cdr l)))
          (setq :modbuf t)))

(de :backup ()
    ; change le nom de :file en :file.BAK
    ; a` utiliser avant un :write
    (when (probefile :file)
          (let ((i (index "." :file)) (:backup))
               (setq :backup 
                     (catenate (if i (substring :file 0 i) :file) ".BAK"))
               (renamefile :file :backup))))

(de  :help ()
     ; affiche un aide me'moire des commandes.
     (let ((:ycursor :ycursor)
           (y :-xmax+1)
           (in))
          (unless (catcherror () 
                     (setq in (openi (catenate #:system:llib-directory
                                               'pepehelp
                                               #:system:lelisp-extension))))
                  (:deadend))
          (:clrscreen)
          (with ((inchan in))
                (fillstring :nscreen 0 #\SP)
                (untilexit eof
                  (bltstring :nscreen (setq y (add y :xmax+1))
                             (readstring) 0 :xmax+1)))
          (:fillminibuf 0 "Aide memoire de PEPE"))
     ; attend la frappe d'un caracte`re pour continuer
     (tag eoc (:more))
     (:clrscreen))

; .Section "Les Autres Fonctions"

(de :evalbuffer ()
    ; Evaluation de tout le tampon sans sortir de PEPE
    ; inde'pendant du format des lignes.
    ; Toutes les impressions vont sur le terminal tre`s proprement
    (let ((#:sys-package:itsoft ':evalbuffer)
          (:buffer :buffer) ; sauvetage du tampon
          (:xy :-xmax+1))
      (with ((lmargin 0)
	     (rmargin :xmax-1))
	    (tycursor 0 0) 
	    (tyflush)
	    (catcherror (untilexit eoc (print "=> " (eval (read)))))
	    (teread)
	    (:more))))

(de :evalbuffer:bol ()
    ; nouvelle ligne en entre'e sous EVALBUFFER
    (ifn :buffer
	 (exit eoc)
	 (let* ((l (nextl :buffer)) 
		(n (slen l)))
	   (bltstring (inbuf) 0 l)
	   (sset (inbuf) n #\CR)
	   (sset (inbuf) (setq n (add1 n)) #\LF)
	   (inmax (setq n (add1 n))))))

(de  :evalbuffer:syserror (f m b)
     (printerror f m b)
     (exit eoc))

(de  :evalbuffer:eol ()
     ; ITSOFT fin de ligne sous EVALBUFFER
     (fillstring :nscreen (setq :xy (add :xy :xmax+1)) #\SP :xmax+1)
     (bltstring :nscreen :xy (outbuf) 0 (outpos))
     (fillstring (outbuf) 0 #\SP (outpos))
     (outpos (lmargin))
     (when (ge :xy (mul :xmax+1 :ymax-1))
           (:more) 
           (setq :xy :-xmax+1)))

; .Section "Initialisation des Clefs"

(dmd defkey (k . f)  `(newl :commands (cons ,k ',f)))

(progn

        (defkey  #↑A          (:begline))
        (defkey  #:tty:left   (:left))
        (defkey  #↑C          (exit pepe))
        (defkey  #↑D          (:deletechar))
        (defkey  #↑E          (:endline))
        (defkey  #:tty:right  (:right))
        (defkey  #↑G          (:deadend))
        (defkey  #↑H          (:left) 
                              (:cursor :xcursor :ycursor) 
                              (:deletechar))
        (defkey  #↑K          (:killine))
        (defkey  #↑L          (:clrscreen))
        (defkey  #↑M          (:breakline) (:right))
        (defkey  #:tty:down   (:down))
        (defkey  #↑O          (:breakline))
        (defkey  #:tty:up     (:up))
        (defkey  #↑S          (:search))
        (defkey  #↑V          (:clrscreen) (:nextscreen))
        (defkey  #↑Y          (:breakline)
                              (:cursor :xcursor :ycursor)
                              (mapc ':insertchar 
                                    (pname :kill)))
        (defkey  #$7F         (:left) 
                              (:cursor :xcursor :ycursor) 
                              (:deletechar))
        (defkey  27           (:escommand))
)

(df defesckey (k . f)     (newl :escommands (cons k f)))

(progn

        (defesckey  #/E    (:evalbuffer))
        (defesckey  #/F    (setq :file 
                                 (:readname " Nom du fichier? ")))
        (defesckey  #/I    (:insertfile))
        (defesckey  #/R    (setq :file (:readname " Fichier? ")
                                 :buffer (:readfile :file)
                                 :xcursor 0 :ycursor 0
                                 :column 0 :ydisplay 0
                                 :modbuf ()))
        (defesckey  #/S    (:backup) (:writefile :file))
        (defesckey  #/V    (:clrscreen) (:prevscreen))
        (defesckey  #/W    (:writefile (:readname " Fichier? ")))
        (defesckey  #/X    (apply (or (getfn '#.#:sys-package:colon 
                                             (concat (:readname
                                                         " Fonction? ")))
                                      ':deadend)
                                  ()))
        (defesckey  #/Z    (:writefile :file)
                           (tycursor 0 :ymax)
                           (loadfile :file t)
                           (exit pepe))
        (defesckey  #/)    (:matchparent #/())
        (defesckey  #/]    (:matchparent #/[))
        (defesckey  #/<    (:clrscreen)
                           (setq :ydisplay 0 :xcursor 0 :ycursor 0 :column 0))
        (defesckey  #/>    (:clrscreen)
                           (setq :ycursor (length :buffer)
                                 :ydisplay (imax 0 (sub :ycursor :ymax/2))
                                 :ycursor (sub1 (sub :ycursor :ydisplay)))
                           (:endline))
        (defesckey  #/?    (:help))
))

; .Section "Pour Re'cupe'rer la Place de PEPE"

(de  pepend ()
     ; de'truit tous les symboles de :...
     (mapc 'remob (oblist '#.#:sys-package:colon))
     ; enle`ve le trait PEPE
     (rem-feature 'pepe)
     ; rede'finit les fonctions autoload
     (libautoload pepe pepe pepefile))