Articles du blog - Page 3

Fonction pour créer un nouveau billet

Bientôt le flux atom

J'avais probablement mal cherché : David Maus a fait un flux atom pour org-mode1 ! Du coup, je testerai ça bientôt, et un flux sera sans doute prêt plus tôt que prévu \o/

En attendant, au hasard de mes pérégrinations, je suis tombé sur une question sur stackoverflow de quelqu'un qui veut créer dynamiquement un nom de fichier en incluant la date. Je me suis dit, chouette idée pour mon blog !

Voilà donc comment j'ai démarré ce billet, en appuyant sur F5 pour exécuter ma fonction newPost. Cette dernière demande un titre, met des _ à la place des espaces, préfixe avec la date du jour, et ouvre le fichier qui va bien à l'endroit qui va bien. Puis elle met automatiquement la date et le titre dans le fichier :

(defvar homeblogdir "/data/Donnees/Sites/fredtantini/")

(defun newPost (title)
  "open a new file in YEAR/MONTH/YearMonthDay_title_with_underscore.org"
   (interactive "sTitre: ")
  (let* ((tmptitle (replace-regexp-in-string "[ ']" "_" title))
         (year (format-time-string "%Y"))
         (month (format-time-string "%m"))
         (day (format-time-string "%d"))
         (newtitle (downcase (concat year month day "_" tmptitle ".org")))
         (newdir (concat homeblogdir year "/" month "/"))
         )
    (make-directory newdir t)
    (find-file (concat newdir newtitle))
    (insert (concat "#+DATE: <" year "-" month "-" day ">\n"))
    (insert (concat "#+TITLE: " title "\n\n"))

    )
  )

Et pour lier F5 à la fonction :

(global-set-key (kbd "<f5>") 'newPost)

(Au passage, j'adore <s[TAB] pour insérer du code.)

Stupides fourmis et PyQt, acte 2

Retour sur la v1

Cette première version est assez lente. Et pour cause… À chaque itération on redessine toute la grille (tous les rectangles, fourmi, ou sol). Autant dire que quand on va ajouter des phéromones, ça va ramer à mort… Pour remédier à ça, il existe heureusement la classe QGraphicsScene : on ajoute des objets que l'on peut déplacer, modifier, etc. Nous, on a besoin de déplacer nos fourmis ; à chaque itération, on va redéfinir notre fourmi sur la « scene ».

La classe fourmi ne bouge pas, l'essentiel des modifications se fait sur notre GridDisplay :

display.py

Pour connaître la position des fourmis sur la grille à partir de GridDisplay, pas besoin de passer toute la grille ; on ajoutera les fourmis une à une à notre scene. Par contre il nous faut quand même connaître les dimensions de la grille. On va ajouter un canvas sur lequel mettre notre scene. Ce canvas sera ajouté au layout du widget. J'ai pris un layout vertical pour pouvoir mettre d'éventuels boutons dessous, chose que je n'ai pas faite.

def __init__(self, dim):
    """ initialisation """
    super(GridDisplay, self).__init__()
    self.dim = dim
    self.coordXmax = self.dim[0]
    self.coordYmax = self.dim[1]

    #central widget pour la fenêtre principale
    cwidget = QtGui.QWidget(self)

    # On met un layout sur lequel ajouter le canvas (et des futurs boutons(?))
    layout = QtGui.QVBoxLayout()
    #le canvas qu'on ajoute au layout
    canvas = QtGui.QGraphicsView()
    layout.addWidget(canvas)
    #et on définit le layout du widget
    cwidget.setLayout(layout)

    #on définit une scene
    self.scene = QtGui.QGraphicsScene()
    canvas.setScene(self.scene)

    #on définit le remplissage et les bords 
    self.pen = QtGui.QPen(QtGui.QColor("white"))
    self.brush = QtGui.QBrush(QtGui.QColor("black"))
    #on initialise la grille
    self.doBackground()

Faire le fond, c'est simple, il suffit de faire un rectangle blanc et de l'ajouter à la @<code>scene@</code> :

def doBackground(self):
    """initialise la grille"""
    w = self.size().width()
    h = self.size().height()
    _item = self.scene.addRect(0, 0, w, h, self.pen,
                              QtGui.QBrush(QtGui.QColor("white")))

Ensuite, il va falloir une méthode pour ajouter nos rectangles-fourmis. Quand on fait un self.scene.addRect(…), ça nous renvoit un pointeur sur l'item ajouté à la scène. On stocke alors ces pointeurs dans une liste pour pouvoir y accéder quand il faudra les déplacer :

def addAnts(self, lAnts):
    """ lAnts = list of ants"""
    self.lAnts = lAnts
    self.lItems = []
    w = self.size().width()
    h = self.size().height()
    x = self.coordXmax
    y = self.coordYmax
    for ant in self.lAnts:
        [i, j] = ant.coord
        item = self.scene.addRect(i*w/x,j*h/y,w/x,h/y,QtGui.QPen(QtGui.QColor("white")),QtGui.QBrush(QtGui.QColor("black")))
        self.lItems.append(item)

Pour la mise à jour, il suffit de parcourir la liste de nos pointeurs de rectangles-fourmis et de les déplacer suivant leurs nouvelles coordonnées.

def animate(self):
    """ lAnts = list of ants"""
    w = self.size().width()
    h = self.size().height()
    x = self.coordXmax
    y = self.coordYmax
    for (nitem, ant) in enumerate(self.lAnts):
        [i, j] = ant.coord
        item = self.lItems[nitem]
        item.setRect(i*w/x, j*h/y, w/x, h/y)

simu.py

Pas grand chose qui change ici : plutôt que de passer la grille au widget central, on lui passe ses dimensions ; plus besoin de tenir à jour une grille de fourmis ; pour la méthode animate, il suffit d'animer la grille, et de déplacer chaque fourmi.

Sources et prochaine fois

La v2 est disponible sur bitbucket.org. La prochaine fois, les fourmis laisseront des p'tites phéromones sur leur passage.

simu3_phero.png

Figure 1: Vivement la suite :þ

Générer une liste de a à z dans emacs

Le problème

Un exercice intéressant a été posté par Xah Lee : http://www.ergoemacs.org/misc/emacs_exercise_gen_a-z.html

Le but est de générer le code suivant :

(global-set-key (kbd "<menu> g a") "A")
(global-set-key (kbd "<menu> g b") "B")
…
(global-set-key (kbd "<menu> g y") "Y")
(global-set-key (kbd "<menu> g z") "Z")

Clairement, la difficulté vient bien entendu de la génération a-zA-Z.

Mes solutions

Je me suis demandé si c'était possible de générer ça avec une macro. Puis y étant arrivé, je me suis dit qu'il fallait que je le fasse en elisp. Et je me suis souvenu qu'on pouvait mettre du elisp dans les regexp…

Sans elisp

Je me suis dit que faire une solution seulement avec une macro ça pourrait être sympa : Ma solution dans view-lossage (C-h l) :

C-x C-k C-f % c <return> <escape> 9 7 <f3>
( g l o b a l - s e t - k e y SPC ( k b d SPC " < m
e n u > SPC g SPC <escape> - 3 2 <f3> " ) SPC " <escape>
3 3 <f3> " ) <return> <f4> <escape> 2 5 <f4>

Plus clairement :

  1. on redéfinit le compteur de macro (C-x C-k C-f) en lui disant de prendre les caractères (%c) ;
  2. on débute la macro en initialisant le compteur à 97 (M-97 <f3>) qui correspond au code ascii de a ;
  3. on commence notre ligne (@<code>(global-set-key (kbd "<menu> g @</code>) ;
  4. on insère le compteur (a) en disant que le pas de comptage est de -32 (M--32 <f3>), donc le prochain sera A ;
  5. on continue notre ligne (@<code>") "@</code>) ;
  6. on insère le compteur (A) en disant que le pas de comptage est maintenant de 33 (M-33 <f3>), donc le prochain sera b ;
  7. on finit notre ligne et on va à la ligne (@<code>")<return>@</code>) ;
  8. on termine la macro (<f4>) ;
  9. on exécute la macro 25 fois (M-25 <f4>).

Un peu d'elisp

En utilisant les chercher/remplacer avec expression régulière (C-M-%), on peut insérer du code elisp en utilisant @<code>\,@</code> dans l'expression régulière.

On commence donc par créer une liste de 26 lignes (<f3> <f3> <return> <f4> M-25 <f4>). (Attention à bien être repassé au compteur « normal » (C-x C-k C-f %d).) Puis on se met au début du buffer (M-<).

Enfin on remplace ^\(.+\)$ par debut \,(string (+ ?a (string-to-number \1))) milieu \,(string (+ ?A (string-to-number \1))) fin (avec C-M-%).

Beaucoup d'elisp

On se met la fonction suivante quelque part, on se place après, on tape C-x C-e, puis M-x az là où on veut mettre notre liste.

(defun az()
  "liste az"
  (interactive)
  (let ((c 97))
  (while (< c 123)
    (insert (concat "debut " (string c) " milieu " (capitalize (string c))" fin" ))
    (newline)
    (setq c (+ c 1)))))

Le principe étant le même qu'avec les regexp, je ne commenterai pas :þ

Autres façons

Bien sûr, il y a tout un tas d'autres façons de faire. On peut combiner tout ça, utiliser du (format "%c" unNombre) plutôt que (string c) par exemple.

Pour les regexp, on n'est même pas obligé d'utiliser un compteur (et donc les macros). Il suffit d'insérer 26 lignes (M-26 <return>), de revenir au début du buffer (ou C-x C-x si on n'est pas au début du buffer et qu'on a activé la « marque » avec C-SPC), et de remplacer ^$ par \,(concat (string (+ ?a \#)) (string (+ ?A \#))) (oui, plus ça va, plus les lignes sont courtes). Le \# étant le nombre de remplacements déjà effectués.

Edit : autres solutions

J'ai encore du boulot en elisp… jcs @irreal propose une solution bien plus élégante (j'me disais bien qu'il y avait moyen de faire une boucle for):

(dotimes (c 26)
  (insert (format "(global-set-key (kbd \"<menu> g %c\") \"%c\")\n"
                  (+ ?a c) (+ ?A c))))

Utilisation de PyQt pour une colonie de fourmis

Préambule

Il y a quelque temps déjà, je me suis mis à Qt avec Python. J'avais trouvé peu de tutoriels, et quasi rien en français (et je ne parle même pas de PyKde, mais ça, c'est une autre histoire…). Même la doc de PyQt, qui est basée sur celle de C++1, contient des bouts de code de C++2 ! Je m'étais alors dit que si je faisais du PyQt, j'essayerai d'en faire un tuto, ou au moins d'expliquer un peu mon code. Puis en voyant je ne sais plus quelle vidéo de petits robots « intelligents », je me suis dit que ce serait sympa que je me fasse un programme de colonies de fourmis. Le but était surtout de faire du PyQt, mais avec un objectif sympatique : des fourmis. Un peu débiles puisque la théorie des colonies de fourmis est quand même assez poussée.

Ça fait un peu plus d'un an et demi que j'ai fait ces programmes, mais je pensais à en faire un article. Du coup, les 4-5 soirs où j'ai travaillé dessus, j'ai fait à chaque fois une nouvelle « version ». Je vais donc commenter le code de ces versions en plusieurs fois pour essayer d'expliquer le code de A à Z. Je pars par contre du principe que vous savez coder orienté objet en python, sinon, pour débuter, je vous conseille d'aller faire un tour sur le net, en commençant par exemple par le site de sam et max. Pour du PyQt une intro est disponible sur learningpython.com et un bon livre sur commandprompt.com.

Première ébauche

Je tiens d'abord à signaler que ce n'est pas forcément bien codé algorithmiquement parlant ; ce n'était pas le but je le rappelle. De plus, comme c'est du vieux code, et que j'avais pas forcément commenté, je louperai peut-être des choses à expliquer :þ (surtout que comme j'étais mal parti, j'ai changé pas mal de choses en cours de route). Oh, et c'est du python2, pas du 3.

Je rappelle également que mon mail est ouvert, et que je posterai un lien vers identi.ca sur lequel vous pouvez répondre également.

Rentrons dans le vif du sujet. Pour faire mon programme, je voulais une classe fourmi (ant) et une classe pour l'affichage (display). Plus une classe d'entrée (simu) qui permettera d'instancier tout ça.

Le principe sera le suivant : on maintient un tableau à deux dimensions à jour. Celui-ci contiendra nos fourmis, la nourriture, le point de départ… Cette grille sera passée en paramètre de la classe display pour pouvoir faire l'affichage et de la classe ant pour que la fourmi connaisse son environnement (enfin, presque…).

Commençons par l'affichage.

display.py

Pour afficher notre grille, on va utiliser un QWidget tout bête et réimplémenter la méthode paintEvent. Pour chaque « case » de la grille, on dessinera un rectangle.

class GridDisplay(QtGui.QWidget):
    """
    Affichage des fourmis, de la nourriture, etc.
    """

    def __init__(self, grille):
        """ initialisation """
        super(GridDisplay, self).__init__()
        self.grille = grille
        self.coordXmax = len(self.grille)
        self.coordYmax = len(self.grille[0])

    def paintEvent(self, event):
        """re-implementation de la fonction paintEvent()"""
        painter = QtGui.QPainter()
        painter.begin(self)

        w = self.size().width()
        h = self.size().height()
        x = self.coordXmax
        y = self.coordYmax

        for i in range(x):
            for j in range(y):
                c = self.grille[i][j]
                painter.setBrush(QtGui.QBrush(QtGui.QColor(c, c, c))) #Comment c'est rempli
                painter.setPen(QtGui.QPen(QtGui.QColor("white"))) #Couleur des bords
                painter.drawRect(i*w/x, j*h/y, w/x, h/y)

        painter.end()

QPainter est la classe qui permet de dessiner sur les widgets. Normalement painter.begin(self) renvoie un booléen indiquant si oui ou non, on a réussi à commencer à peindre (de même pour end()). On dit de quelle couleur peindre avec painter.setBrush(QtGui.QBrush(QtGui.QColor(c, c, c))) puis on dessine notre rectangle avec drawRect(abscisse, ordonnée, hauteur, largeur).

On met tout ça dans un fichier display.py et pour tester, on se fait une grille aléatoire :

if __name__ == '__main__':
    """Pour tester"""
    from random import randint
    app = QtGui.QApplication([])
    xmax = 10
    ymax = 5
    grille = [[randint(0, 255) for _ in range(ymax)][:] for _ in range(xmax)]
    grd = GridDisplay(grille)
    grd.show()
    app.exec_()

Le if __name__ = 'main':= permet d'exécuter le code qui suit uniquement s'il n'est pas appelé en tant que module (c'est-à-dire si on fait python display.py).

Rien de bien compliqué sinon : on crée notre application avec app = QtGui.QApplication([]), notre grille, notre widget, que l'on affiche, et on lance l'application avec app.exec_().

ant.py

Passons à la fourmi. Pour pouvoir retourner à sa fourmilière, une fourmi a besoin de connaître le chemin qu'elle a fait. Il faut également que l'on connaisse ses coordonnées, ainsi que la fameuse grille. Pour instancier une fourmi, on lui donnera également ses coordonnées de départ :

class Ant:
    """
    Ce qui définit une fourmi et ce qu'elle sait faire
    """
    def __init__(self, parent, posx, posy):
        """
        Une fourmi
        """
        self.coord = [posx, posy]
        self.pathDone = [self.coord]
        self.parent = parent

pathDone contiendra la liste des coordonnées de la grille par lesquelles la fourmi est passée.

À chaque itération, une fourmi ira sur une des huit cases adjacentes, selon son état (si elle a trouvé de la nourriture, si elle doit rentrer, etc.). Pour l'instant, elle va juste aller sur une case :

def move(self):
    """
    Un pas, selon l'environnemnt.
    """
    directions = [(-1, -1), (-1, 0), (-1, 1),
                 (0, -1), (0, 1),
                 (1, -1), (1, 0), (1, 1)]
    direction = directions[randint(0,7)]
    self.coord[0] += direction[0]
    self.coord[0] %= self.parent.coordXmax
    self.coord[1] += direction[1]
    self.coord[1] %= self.parent.coordYmax
    self.pathDone += [self.coord[:]]

À la fin de la fonction, on ajoute donc les nouvelles coordonnées.

De nouveau, on va tester notre classe, pour avoir confirmation que nos fourmis se déplace bien. Pour cela, on a besoin d'un affichage de test, ou plutôt de ses coordonnées :

class PourTest:
    """
    Une grille pour tester
    """
    def __init__(self, maxX, maxY):
        """ les coordonnées max de la grille"""
        self.coordXmax = maxX
        self.coordYmax = maxY


if __name__ == '__main__':
    """
    Pour tester
    """
    xmax = 10
    ymax = 5
    grille = [[0 for _ in range(ymax)][:] for _ in range(xmax)] #on initialise la grille
    parent = PourTest(xmax, ymax) #pour l'affichage
    nAnts = 10
    lAnts = [] #liste de nos fourmis
    for _ in range(nAnts): #pour i de 0 à 9
        fourmi = Ant(parent, randint(0, xmax - 1), randint(0, ymax - 1)) #on crée une fourmi
        grille[fourmi.coord[0]][fourmi.coord[1]] += 1 #on l'ajoute à la grille
        lAnts.append(fourmi) #et à la liste 
    niterations = 10
    from time import sleep
    for _ in range(niterations):
        #affichage (à -90°) de la grille 
        for ligne in grille:
            print ligne
        #pour chaque fourmi de la liste
        for fourmi in lAnts:
            ##suppression de la fourmi dans la grille
            grille[fourmi.coord[0]][fourmi.coord[1]] -= 1
            ##déplacement de la fourmi
            fourmi.move()
            ##ajout de la fourmi dans la grille
            grille[fourmi.coord[0]][fourmi.coord[1]] += 1
        sleep(1)
        print "=" * 40

simu.py

Maintenant qu'on a testé nos deux classes, on va les assembler. Notre classe principale va donc : instancier une grille (et la placer en widget central), des fourmis (avec le widget central comme parent), et périodiquement, on met à jour la grille.

def __init__(self):
    """ Initialisation """
    super(Simu, self).__init__()

    #coordonnées + grille
    self.xmax = 50
    self.ymax = 50
    self.grille = [[0 for _ in range(self.ymax)][:] for _ in range(self.xmax)]

    #le widget central est notre affichage de la grille
    self.centralWidget = GridDisplay(self.grille)
    self.setCentralWidget(self.centralWidget)
    self.resize(480, 480)

    #on initialise nos fourmis
    self.nAnts = 30
    self.lAnts = []
    for _ in range(self.nAnts):        
        fourmi = Ant(self.centralWidget, randint(0, self.xmax - 1), randint(0, self.ymax - 1))
        self.grille[fourmi.coord[0]][fourmi.coord[1]] += 1
        self.lAnts.append(fourmi)

    #A chaque top du timer, on actualise la grille
    self.timer = QTimer()
    self.connect(self.timer, SIGNAL("timeout()"), self.animate)
    self.compteur = 0
    #C'est parti pour toutes les 10ms
    self.timer.start(10)

Assez fréquemment on met à jour la grille en faisant bouger les fourmis. Ensuite, on met la grille dans le widget central, et on l'update pour appeler paintEvent

def animate(self):
    """maj de la grille"""
    self.compteur += 1
    for fourmi in self.lAnts:
        #déplacement de la fourmi
        ##suppression de la fourmi dans la grille
        self.grille[fourmi.coord[0]][fourmi.coord[1]] -= 1
        ##déplacement de la fourmi
        fourmi.move()
        self.grille[fourmi.coord[0]][fourmi.coord[1]] += 1
    self.centralWidget.grille = self.grille
    self.centralWidget.update()

    if self.compteur > 50:
        self.timer.stop()

Postambule

La suite sera un peu plus intéressante (et les fourmis aussi). Le code sera disponible sur bitbucket.org au fur et à mesure des épisodes. Pour tout télécharger d'un coup, c'est dans Downloads>Branches.

Le nettoyage de mon .emacs

Pourquoi

Parce que. Un peu plus de 900 lignes, ça commence à faire pas mal. Surtout quand plein de trucs sont plus utilisés (entre autre suite à divers changements de PC). J'ai essayé de faire ça pas trop mal : dans des dossiers tout bien rangé. De plus, tout ce qui peut être customised sera fait dans Customize.

Je vous conseille de regarder le manuel d'emacs sur le fichier d'initialisation et le petit résumé de ce qu'il se passe au démarrage, c'est toujours instructif.

DONE Première étape : les dossiers

Même si je suis supporter de $XDGCONFIGHOME (toutes les configs vont dans le dossier .config), je vais laisser le fichier .emacs dans mon home, ainsi que le dossier .emacs.d (je sais, je pourrais enlever .emacs pour travailler sur .emacs/init.el mais sentimentalement, je suis pas prêt).

Concernant le backup et l'auto-save, je laisse ça par défaut, sachant que ça peut se régler (cf le manuel, et les variables backup-directory-alist et auto-save-file-name-transforms). Avoir ces fichiers dans le dossier du fichier édité me convient parfaitement.

Le reste de la configuration est dans .emacs.d/config/ (.place, .org-timestamps…) et .emacs.d/site-lisp/ (key-bindings.el, mode-mappings.el… et surtout custom.el).

DONE Deuxième étape : customization

J'ai commencé à me servir de la customization en essayant de configurer org-mode, et ça m'a permis de (re)découvrir cette fonctionnalité d'emacs (ô combien disgracieuse à mes yeux). Malgré son aspect qui ne me ragoûte pas, j'ai pu découvrir pas mal d'options — dont je parlerai peut-être à l'occasion — en naviguant à travers les groupes. Je me suis alors mis en tête de définir tout ce qui était customizable par customize.

Je la mets dans un fichier

Comme je veux un .emacs relativement court, je ne veux pas un custom-set-variables en plein milieu qui fasse 500 lignes. Pour ça, on regarde le manuel d'emacs qui nous dit comment faire :

(setq custom-file "~/.emacs-custom.el")
(load custom-file)

Je customize tout ce que je peux customizer

Pour ça, pour « chaque » ligne de mon .emacs, je me place sur la variable concernée et [C-h v]. Si je me suis effectivement placé sur le nom d'une variable, son nom est proposé par défaut. Dans le buffer d'aide, je regarde à la fin si la ligne « You can customize this variable » est présente. Si oui, ben je clique dessus. Je regarde alors sa valeur par défaut. Si c'est la même que celle de mon .emacs, j'enlève la customization. J'ajoute un commentaire pour savoir ce que fait la variable si nécessaire, et je sauve pour les sessions futures. Ces trois dernières opérations étant effectuées en cliquant sur le bouton State. J'en profite aussi généralement pour cliquer sur le Group auquel il appartient, pour voir d'autres options.

Je supprime l'ancienne configuration de mon .emacs

En effet, le C-h v de custom-file nous dit :

It will not delete any customizations from the old custom file. You should do that manually if that is what you want.

TODO Troisième étape : le fichier .emacs

On commence par dire où sont les dossiers/config. Comme je travaille parfois sous windows, je ne veux donc pas que mon home soit en dur.1

(defvar home-dir (concat (getenv "HOME") "/"))

Alternative si l'extension avec ~ marche :

(defvar home-dir)
(setq home-dir (concat (expand-file-name "~") "/"))

J'en profite pour mettre dans load-path mon .emacs.d où l'essentiel va se passer.

(defvar home-lisp-dir (list (concat home-dir ".emacs.d/")))
(setq load-path (append home-lisp-dir load-path))

Au cas où je souhaiterai ajouter plusieurs dossiers, je me mets ça sous le coude :

;; Set up load path 
(setq load-path (append (list (concat home-dir ".emacs.d/")
                              (concat home-dir ".config/emacs/")
                              (concat home-dir ".config/site-lisp/"))
                        load-path))

Dans ce dernier, un petit subdirs.el pour ajouter ses sous-dossiers.

On charge ensuite la susdite customization.

(setq custom-file (concat home-lisp-dir "custom.el"))
(load custom-file)

Et on charge le reste

(load-library "mode-mapping")
(load-library "key-bindings")
(load-library "my-functions")

TODO Quatrième étape : le reste

TODO mode-mapping

On regarde auto-mode-alist pour connaitre quelles sont les extensions qui sont gérées. On regarde également loaddefs.el pour ce qui est déjà autoloadé. On ajoute ce qu'il faut.

Ma config d'org-mode pour la publication de ce site.

Préambule

Voici ma config d'org-mode temporaire pour la publication de ce site. Elle est actuellement en cours d'étude :þ

J'ai en effet plein de choses que je veux mettre en place. J'y reviendrai plus tard. Un certain nombre de choses ne fonctionnent également pas. (It's not a bug, it's a feature ;]) Il va me falloir (comme tout le monde) plus de temps…

Au passage, pour avoir la dernière version d'org-mode dans debian, pour utiliser les postamble et autres nouveautés et ne pas se demander pourquoi ça ne marche pas (suivez mon regard… <_<) :

su -c "aptitude install org-mode"

Et pour que les begin_src soient en couleur une fois l'export effectué :

htmlize : su -c "aptitude install emacs-goodies-el"

Dans customize

Tout d'abord, pour la configuration des choses qui ne devraient pas changer d'un « site » à l'autre, j'ai mis ça dans customize. Je sais pas ce que seront les autres sites (ni s'il y en aura). Le postamble risque en fait de changer… Bon, ok, j'ai dû plutôt mettre le plus de choses possibles pour ne pas trop alourdir mon .emacs avec M-x org-customize. Pas d'explications à donner, le nom des variables étant suffisamment explicite (sinon, dans emacs C-h v puis Enter en étant positionné sur le nom de la variable) :

  '(org-export-author-info nil)
 '(org-export-creator-info nil)
 '(org-export-headline-levels 6)
 '(org-export-html-link-home "index.html")
 '(org-export-html-link-up "sitemap.html")
 '(org-export-html-postamble t)
 '(org-export-html-postamble-format (quote (("en" "<p class=\"date\">Date: %d</p><p class=\"creator\">Generated by %c - <a href=\"#\" onClick='show_org_source()'>Show Org source</a> (<a href=\"#\" onClick='show_htmlized_source()'>htmlized</a>)</p>
<p class=\"style\">CSS inspired by <a href=\"http://tontof.net/\">Tontof</a>, colors by <a href=\"http://http://theme.wordpress.com/themes/chaoticsoul/\">Chaotic Soul</a></p>
<p class=\"xhtml-validation\">%v</p>
"))))
 '(org-export-html-preamble-format (quote (("en" "<script type=\"text/javascript\">
    function rpl(expr,a,b) {
      var i=0
      while (i!=-1) {
         i=expr.indexOf(a,i);
         if (i>=0) {
            expr=expr.substring(0,i)+b+expr.substring(i+a.length);
            i+=b.length;
         }
      }
      return expr
    }

    function show_org_source(){
       document.location.href = rpl(document.location.href,\"html\",\"org\");
    }
    function show_htmlized_source(){
       document.location.href = rpl(document.location.href,\"html\",\"org.html\");
    }
</script>"))))
 '(org-export-html-style "<link rel=\"stylesheet\" type=\"text/css\" href=\"http://fredtantini.free.fr/other/mystyle.css\" />")
 '(org-export-html-style-include-default nil)
 '(org-export-section-number-format (quote ((("1" ".")) . ". -")))
 '(org-export-with-section-numbers nil)
 '(org-export-with-toc nil)
 '(org-log-done (quote time) nil nil "quand on passe en DONE, timestamp")
 '(org-publish-sitemap-sort-files (quote alphabetically))
 '(org-publish-timestamp-directory "~/.config/org-timestamps/")
 '(org-use-sub-superscripts nil)

Dans mon .emacs

Il reste là la configuration du fameux org-publish-project-alist :

;;org-export/publish
(setq org-publish-project-alist
      '(("larticles"
         :base-directory "/data/Donnees/Sites/fredtantini/"  ;le dossier où se trouvent mes fichiers
         :base-extension "org"                               ;qu'exporter
         :publishing-directory "/var/www/FT/"                ;où exporter
         :publishing-function org-publish-org-to-html        ;comment exporter
         :auto-sitemap t                                     ;on crée un fichier sitemap pour avoir la liste des fichiers
         :sitemap-filename "sitemap.org"                     ;le nom du sitemap
         :sitemap-title "Articles Index"                     ;son titre
         :sitemap-style tree                                 ;l'autre choix : list
         :recursive t                                        ;on parcourt les sous-dossiers
         )

        ("limages"
         :base-directory "/data/Donnees/Sites/fredtantini/"  
         :base-extension "jpg\\|gif\\|png"                   
         :publishing-directory "/var/www/FT/images/"         
         :publishing-function org-publish-attachment         
         :recursive t)

        ("lother"
         :base-directory "/data/Donnees/Sites/fredtantini/other/"
         :base-extension "css\\|el"
         :publishing-directory "/var/www/FT/other/"
         :publishing-function org-publish-attachment)

        ("lft" :components ("larticles" "limages" "lother"))


        ("rarticles"
         :base-directory "/data/Donnees/Sites/fredtantini/"
         :base-extension "org"
         :exclude "^00"                                                        ;les fichiers qui commencent par 00 sont exclus
         :publishing-directory "/ftp:fredtantini@fredtantini.free.fr:~/"       ;où exporter (par ftp, avec tramp)
         :publishing-function (org-publish-org-to-html org-publish-org-to-org) ;on publie le .html, et le .org
         :plain-source t                                                       ;on publie le source tel quel
         :htmlized-source t                                                    ;et aussi comme il apparait dans mon emacs
         :auto-sitemap t
         :sitemap-filename "sitemap.org"
         :sitemap-title "Articles Index"
         :sitemap-style tree
         :recursive t
         )

        ("rimages"
         :base-directory "/data/Donnees/Sites/fredtantini/images/"
         :base-extension "jpg\\|gif\\|png"
         :publishing-directory "/ftp:fredtantini@fredtantini.free.fr:~/images/"
         :publishing-function org-publish-attachment
         :recursive t)

        ("rother"
         :base-directory "/data/Donnees/Sites/fredtantini/other/"
         :base-extension "css\\|el"
         :publishing-directory "/ftp:fredtantini@fredtantini.free.fr:~/other/"
         :publishing-function org-publish-attachment)

        ("rft" :components ("rarticles" "rimages" "rother"))

        ("all" :components ("lft" "rft")))
      )

Petites explications : l pour local qui va dans var/www et r pour remote qui va sur ce site (en utilisant tramp). Pas trop de différences entre les deux, si ce n'est qu'en local, je mets les futurs articles dans des fichiers qui commencent par 00. De plus, en local, je n'ai pas besoin des sources de la page, donc pas d'options plain-source et htmlize-source.

Reste a faire pour avoir un blog qui tienne la route

et pas seulement.

raf [9/17]

TODO lien auto vers précédent/suivant ?

DONE voir si conserve up + home ?

non

DONE lien auto vers source

DONE fichier sitemap qui bouge pas si seulement update

réglé en préfixant les fichiers par date de création

DONE problème avec %d dans sitemap ?

n'affiche plus %t… mais pas utilisé

TODO Problème du CLOSED tout moche à enlever dans les fichiers du site

TODO Couleur des tags:   tagToutMoche

modifier le css pour changer background et mettre à droite comme dans emacs ?

TODO faire un index avec les tags contenus dans les fichiers ?

TODO Et l'inclure dans un menu sur la droite avec suivant/précédent/autres infos ?

DONE Quand C-u C-c C-e E le timestamp «originel» est perdu

utile de l'afficher ?

mettre un #+DATE: <YYYY-MM-DD> force la date

DONE Paginer le futur fichier index ?

tous les 10 articles, par année/mois…

TODO mettre une navigation SOUS les footnotes…

TODO Faire un fichier index avec un chapeau de l'article en plus d'un index avec les articles complet?

première section/100 premiers mots/…

TODO plein d'autres choses

DONE faire un fichier RSS

-faire marcher org-atom…-

ai fait le mien, en attendant de voir si ox-rss.el peut faire un rss pour un dossier, et pas seulement un buffer.

DONE mettre = pour les noms de fonctions, fichiers, etc. ~ pour les choses à taper, et du coup, exporter en <kbd>

‰ pour les touches

DONE régler ce souci d'espace insécable qui n'est pas pris en compte dans les regexp pour les =qqchose= ou ~truc~

TODO faire un index par sous dossier

voir :preparation function

TODO revoir le css

Page d’accueil

Soyez les bienvenu·e·s. Voici de quoi vous diriger :

Contenu

  • Un « blog ». Plutôt orienté programmation, Emacs, logiciels libres… En construction
  • Les sources des programmes dont je parle dans le blog.
  • Un « lab » où je mets des choses pas abouties (orienté php/html/css/javascript).
  • Des fichiers de config, pas bien à jour…

Divers

  • Les pages html sont recensées dans le sitemap. C’est aussi un bon moyen pour trouver une page du blog.
  • À part si mentionné autrement, le contenu est placé en domaine publique / CC0.
  • Mes programmes sont sur bitbucket. Je contribue également modestement sur github.

Ma cheat-sheet d’Emacs

En construction. Version moins moche : fichier.org.

C-u

Pour les commandes suivantes, je renseigne deux colonnes supplémentaires : M-4 commande, et C-u commande. Si C-u se comporte comme C-u 4, je laisse vide.

C-u « argument universel ».
  Permet de modifier le comportement d’une fonction
  Permet d'exécuter la commande plusieurs fois
  Permet de passer un paramètre numérique à une fonction
C-u chiffres commande faire la commande chiffres fois
C-u 5 - -----
C-u 5 BackSpace efface les 5 dernières lettres
C-u 2 M-x forward-word avance de 2 mots
C-u commande répète la commande 4 fois
C-u C-u commande répète la commande 16 fois
C-u C-u * **
M-chiffres commande fait la commande chiffres fois, comme C-u chiffres commande
M-5 - -----
M-1 M-6 * **
C-u commande appelle la commande avec un comportement spécial
M-x goto-line 4 (C-x l 4) va à la ligne 4
C-u 4 goto-line (C-u 4 C-x l) va à la ligne 4
M-4 goto-line (M-4 C-x l) va à la ligne 4
C-u M-x goto-line 4 (C-u C-x l 4) va à la ligne 4 dans un autre buffer
M-x yank (C-y) colle le texte le plus récemment coupé, en mettant la marque au début, le point à la fin
C-u 4 M-x yank (C-u 4 C-y) colle le 4ème texte le plus récemment coupé
C-u M-x yank (C-u C-y) colle le texte le plus récemment coupé, en mettant la marque à la fin, le point au début

Aide

raccourci commande ce que ça fait M-4 commande C-u commande
C-h a apropos montre ce que fait la commande dans un buffer montre aussi les fonctions non-interactive idem
C-h k describe-key affiche ce que fait un raccourci dans un buffer    
C-h c describe-key-briefly affiche la fonction appelée par un raccourci dans le minibuffer    
C-h f describe-function affiche ce que fait la fonction dans un buffer    
C-h t help-with-tutorial affiche le tutoriel demande la langue du tutoriel idem
C-h w where-is affiche le raccourci correspondant à la commande    
C-h e view-eco-area-messages montre la log des messages récents    
C-h i info affiche Info    
C-h l view-lossage affiche les 300 dernières frappes de touche    
C-h m describe-mode affiche la doc du mode majeur et des modes mineurs du buffer    

Se déplacer

      M-4 C-u
C-a move-beginning-of-line aller en début de ligne se déplace de 3 lignes vers le bas d’abord  
M-a backward-sentence aller en début de phrase remonte de 4 phrases  
C-e move-end-of-line aller en fin de ligne se déplace de 3 lignes vers le bas d’abord  
M-e forward-sentence aller en fin de phrase avance de 4 phrases  
C-f forward-char lettre suivante avance de 4 lettres  
M-f forward-word mot suivant avance de 4 mots  
C-b backward-char lettre précédente (backward) recule de 4 lettres  
M-b backward-char mot précédent recule de 4 mots  
C-p previous-line ligne précédente recule de 4 lignes  
C-n next-line ligne suivante avance de 4 lignes  
C-v scroll-up-command avance le texte d’un écran déplace le texte de 4 lignes vers le haut  
M-v scroll-down-command recule le texte d’un écran déplace le texte de 4 lignes vers le bas  
C-M-v scroll-other-window avance le texte de la prochaine fenêtre d’un écran déplace le texte de la prochaine fenêtre de 4 lignes  
C-l recenter-top-bottom met la ligne courante avec le point au centre (en haut/en bas, après appels successifs) met la ligne courante sur la 4e ligne de la fenêtre met la ligne au centre
M-g g chiffres goto-line aller à la ligne chiffres du buffer va à la 4e ligne du buffer va à la 4e ligne de l’autre buffer
M-g M-g chiffres goto-line      
C-x l chiffres goto-line      
M-r move-to-window-line-top-bottom met le point sur la ligne au milieu de la fenêtre (en haut/en bas, si appels successifs) met le point sur la 4e ligne de la fenêtre  
M-< beginning-of-buffer aller au début du buffer aller au 4/10 du buffer ne laisse pas de marque à la précédente position
M-> end-of-buffer aller à la fin du buffer aller au 4/10 à partir du bas ne laisse pas de marque à la précédente position
M-m back-to-indentation aller au premier caractère non blanc de la ligne    

Éditer

      M-4 C-u
M-i tab-to-tab-stop insère des espaces/tabulations jusqu’au prochain tab-stop    
C-i indent-for-tab-command indente la ligne ou la région, ou insère une tabulation, ou fait une complétion    
TAB indent-for-tab-command dépend beaucoup du mode    
C-x TAB indent-rigidly indente toutes les lignes de la région avec [S-]gauche/droite indente de 4 colonnes  
M-; comment-dwim appelle la commande de commentaire (Do What I Mean)    
    si une région est active et transient-mark-mode est on, commente la région    
    sauf si la région n'est composée que de commentaire, la décommente    
    sinon, si la ligne est vide, insère un commentaire (et indente)    
    sinon, si un argument est présent, appelle comment-kill    
    sinon appelle comment-indent    
C-j electric-indent-just-newline insère une nouvelle ligne, sans indentation insère 4 lignes  
C-o open-line insère une ligne en laissant le point à sa place insère 4 lignes  
C-M-o split-line sépare la ligne en déplaçant la fin verticalement n’insère pas fill-prefix  
C-x C-o delete-blank-lines supprime les lignes vides    
M-^ delete-indentation joint cette ligne et la précédente joint cette ligne et la suivante  
M-\ delete-horizontal-space supprime toutes les espaces/tabulations autour du point supprime seulement celles précédent le point  
M-SPC just-one-space supprime les espaces/tabulations autour du point et ne laisse qu’une espace laisse 4 espaces  
    avec un argument négatif, supprime également les fins de ligne    
M-q fill-paragraph reformate le paragraphe sur ou après le point, ou les paragraphes de la région idem et justify  
C-x f chiffres set-fill-column définit fill-column à chiffres définit fill-column à 4 définit fill-column à la colonne courante
M-o M-s center-line centre la ligne centre 4 lignes  
M-o M-S center-paragraph centre le paragraphe    
C-t transpose-chars échange 2 lettres avance le caractère précédent le point de 4 caractères  
M-t transpose-words échange 2 mots avance le mot de 4 mots  
M-0 M-t   échange le mot vers le point avec le mot vers la marque    
C-x C-t transpose-lines échange la ligne courante et la précédente déplace la ligne précédente de 4 lignes  
M-0 C-x C-t   échange la ligne courante avec celle de la marque    
M-u upcase-word met en lettres capitales le mot et les 3 prochains  
M-l downcase-word met en lettres minuscules le mot et les 3 prochains  
M-c capitalize-word met en lettre capitale la lettre et va à la fin du mot et les 3 prochains  
    pour ces 3 commandes    
    si au milieu d’un mot, ne prend pas en compte le début    
    avec un argument négatif, le point reste en place    
C-x C-u upcase-region met en lettres capitales la region    
C-x C-l downcase-region met en lettres capitales la region    

Si font-lock-mode n’est pas on

M-o d facemenu-set-default met la face par défaut    
M-o b facemenu-set-bold en gras    
M-o i facemenu-set-italic en italique    
M-o l facemenu-set-bold-italic en gras et italique    
M-o o facemenu-set-face applique la face (TAB pour avoir une liste)    
M-o u facemenu-set-underline souligne    

Couper/Copier/Coller

      M-4 C-u
C-d delete-char supprime la prochaine lettre kill les 4 prochaines lettres  
M-d kill-word kill le prochain mot kill les 4 prochains mots  
BackSpc delete-backward-char supprime la lettre précédente kill les 4 lettres précédentes  
M-BackSpc backward-kill-word kill le mot précédent kill les 4 mots précédents  
C-k kill-line kill le reste de la ligne kill les 3 prochaines lignes également  
M-0 C-k   kill le début de la ligne    
C-w kill-region kill la région    
M-w kill-ring-save copie la région    
C-M-w append-next-kill si la commande suivante est un kill, ajoute au précédent kill    
C-y yank colle le texte le plus récemment coupé, en mettant la marque au début, le point à la fin colle le 4ème kill le plus récent met la marque à la fin, le point au début
M-y yank-pop après un yank (ou un yank-pop) remplace le yank par le kill précédent par le 4ème kill le plus récent  
M-z x zap-to-char kill jusqu’au caractère x inclus jusqu’au 4ème caractère x  

Fenêtres/buffers

      M-4 C-u
C-x 1 delete-other-windows la window remplit la frame (le buffer courant devient le seul buffer de la fenêtre)    
C-x 2 split-window-below splitte la window en 2, la nouvelle est dessous la window du dessus fait 4 lignes  
C-x 3 split-window-right splitte la window en 2, la nouvelle est à droite la window de gauche fait 4 lignes  
C-x 0 delete-window supprime la fenêtre    
C-x o other-window choisit la prochaine window choisit la 4e prochaine window  
C-x ^ enlarge-window réduit la window d’une ligne réduit de 4 lines  
C-x { shrink-window-horizontally réduit la window d’une colonne réduit de 4 colonnes  
C-x } enlarge-window-horizontally agrandit la window d’une colonne agrandit de 4 colonnes  
C-x K kill-buffer kill le buffer    
C-x droite/gauche next/previous-buffer va au buffer suivant/précédent    
C-x b switch-to-buffer affiche le buffer dans la window (le crée s’il n’existe pas)    
C-x C-b list-buffers affiche une liste des buffers existants affiche uniquement ceux qui visitent un fichier  
C-x C-q read-only-mode change le fait que le buffer soit en lecture seule le met en lecture seule. Un argument négatif le met en écriture  
C-x 4 0 kill-buffer-and-window tue le buffer et ferme la window courante    
C-x 4 b switch-to-buffer-other-window affiche le buffer dans une autre window, se positionne dessus    
C-x 4 C-o display-buffer affiche le buffer dans une autre window, ne se positionne pas dessus    
C-x 4 f find-file-other-window ouvre le fichier dans une autre fenêtre    

Fichiers

      M-4 C-u
C-x C-f find-file édite le fichier, se met dans un buffer le visitant, en le créant si nécessaire    
C-x C-s save-buffer sauve le buffer courant dans le fichier visité. La version précédente devient le backup   1 fois : cette version devient le backup de la prochaine sauvegarde
        2 fois : la version précédente devient le backup inconditionnelement
M-0 C-x C-s   ne fait pas un backup de la version précédente    
        3 fois : 1 fois + 2 fois
         
C-x C-w write-file écrit le buffer dans le fichier en argument ne demande pas confirmation pour écraser  
C-x i insert-file insère le contenu du fichier dans le buffer après le point, met la marque après le texte inséré    

Marques

      M-4 C-u
C-SPC set-mark-command fait une marque (donc le début d'une région/rectangle) fait une marque et va à la précédente  
C-@ set-mark-command      
C-x C-SPC pop-global-mark va à la précédente marque globale    
C-x C-@ pop-global-mark      
M-@ mark-word marque jusqu'à la fin du mot marque jusqu’au 4 prochains mots  
C-x C-x exchange-point-and-mark échanger le point et la marque ne passe pas en Transient  
M-h mark-paragraph sélectionne le paragraphe, le point au début met la marque à la fin du 4e paragraphe  
C-x h mark-whole-buffer sélectionne tout le buffer    

Macro

      M-4 C-u
C-x ( kmacro-start-macro démarre l’enregistrement d’une macro   ajoute à la dernière macro
C-x ) kmacro-end-macro arrête l’enregistrement de la macro répète la macro 4 fois  
         
C-x C-k C-a kmacro-add-counter demande la valeur à ajouter au compteur ajoute 4 au compteur remet l’ancienne valeur
C-x C-k C-c kmacro-set-counter demande quelle valeur mettre au compteur met 4 au compteur remet le compteur à la valeur avant l’itération de la macro
C-x C-k C-e kmacro-edit-macro-repeat édite la dernière macro    
C-x C-k C-f kmacro-set-format met le compteur au format donné    
C-x C-k TAB kmacro-insert-counter insère le compteur, ajoute 1 insère et ajoute 4 insère le précédent compteur et le ne modifie pas
C-x C-k C-l kmacro-call-ring-2nd-repeat exécute la pénultième macro    
C-x C-k C-n kmacro-cycle-ring-next prochaine macro dans le ring 4e prochaine macro dans le ring  
C-x C-k C-p kmacro-cycle-ring-previous précédente macro dans le ring 4e précédente macro  
C-x C-k C-t kmacro-swap-ring échange les 2 premières macro du ring    
C-x C-k C-v kmacro-view-macro-repeat affiche la dernière macro la 4e dernière macro  
C-x C-k SPC kmacro-step-edit-macro exécute la derinère macro en éditant pas à pas    
C-x C-k b kmacro-bind-to-key demande à quelle touche lier la dernière macro    
C-x C-k [0-9A-Z]   exécute la commande liée à la touche    
C-x C-k e edit-kbd-macro édite une macro    
C-x C-k l kmacro-edit-lossage édite les 300 dernières frappe comme une macro    
C-x C-k n kmacro-name-last-macro nomme la dernière macro    
C-x C-k r apply-macro-to-region-lines exécute la dernière macro pour chaque ligne de la région    
C-x C-k x kmacro-to-register store la dernière macro dans le registre    
F3 kmacro-start-macro-or-insert-counter met le compteur à 0, enregistre la macro met le compteur à 4, enregistre la requête ajoute à la dernière macro
    en enregistrant, insère le compteur et ajoute 1 insère et ajoute 4 insère le précédent compteur, ne l’incrémente pas
F4 kmacro-end-or-call-macro termine l’enregistrement de la macro    
    si pas en enregistrement, exécute la macro exécute 4 fois exécute la penultième macro

Recherches

      M-4 C-u
C-s isearch-forward fait une recherche incrémentale après le point avec regexp  
C-r isearch-backward fait une recherche incrémentale avant le point avec regexp  
M-% query-replace chercher/remplacer (dans la région si en mode transient mark avec marque active) remplace les mots seulement  
C-M-s isearch-forward-regexp chercher avec regexp sans regexp  
C-M-r isearch-backward-regexp chercher avec regexp en arrière sans regexp  
C-M-% query-replace-regexp chercher/remplacer avec regexp remplace les mots seulement  
M-s w isearch-forward-word cherche la séquence de mots (peuvent être séparés par de la ponctuation) recherche normale  
M-s . isearch-forward-symbol-at-point cherche le symbole sur lequel le point se trouve    
M-s o occur affiche les lignes contenant la regexp dans un buffer avec 4 lignes de contexte  
M-s h . highlight-symbol-at-point highlight le symbole sur lequel le point se trouve    
M-s h l highlight-lines-matching-regexp highlight les lignes qui matchent la regexp    
M-s h r highlight-regexp highlight la regexp    
M-s h u unhighlight-regexp enlève l'highlight sur la regexp   enlève tous les highlights

Pendant une recherche

BackSpc supprime le dernier caractère de la recherche
Entrée sort de la recherche, laisse le point à l’emplacement trouvé
M-p cherche le précédent item du search-ring
M-n cherche le prochain item du search-ring
C-M-i complète la chaîne de recherche à partir du search-ring
C-j cherche la fin de ligne
C-s cherche la prochaine occurence
C-r cherche l’occurence précédente
C-w ajoute la fin du mot à la fin de la chaîne de recherche
M-s C-e ajoute la fin de la ligne à la chaîne de recherche
C-y ajoute le dernier kill
C-g si la recherche échoue, revient à la dernière recherche en succès
  si la recherche est en succès, arrête la recherche, revient au point de départ
M-s c recherche en étant sensible ou non à la casse
M-s r recherche en expression régulière ou non
M-s w recherche les mots
M-s e édite la chaîne de recherche
M-% lance query-replace avec la dernière chaîne de recherche à remplacer
C-M-% lance query-replace-regexp
M-s o lance occur avec la dernière recherche
M-s h r lance highlight-regexp avec la dernière recherche

Pendant un remplacement

SPC remplace
y remplace
n ne remplace pas, va au prochain
Suppr/Backspc ne remplace pas, va au prochain
Entrée quitte
q quitte
. remplace et quitte
, remplace et ne bouge pas le point tout de suite
\! remplace toutes les occurences du modem
\^ revient à la précédente
E édite la chaîne de remplacement
Y remplace toutes les occurences de tous les buffers restants
N ne remplace pas toutes les occurences de ce buffer, va au suivant

Rectangles

      M-4 C-u
C-x r c clear-rectangle vide le rectangle (remplit de blanc) remplit de blanc les parties du rectangle qui étaient vides  
C-x r d delete-rectangle supprime le rectangle remplit de blanc les parties du rectangle qui étaient vides  
C-x r k kill-rectangle supprime le rectangle et le sauve dans le kill-ring remplit de blanc les parties du rectangle qui étaient vides  
C-x r o open-rectangle ouvre un rectangle (insère des blancs) remplit de blanc même s’il n’y a pas de texte à droite  
C-x r r copy-rectangle-to-register copie le rectangle dans un registre    
C-x r t string-rectangle insère un rectangle    
C-x r y yank-rectangle colle un rectangle    
C-x r M-w copy-rectangle-as-kill copie le rectangle et le sauve dans le kill-ring    

Registres

Demande un registre : un caractère

      M-4 C-u
C-x r SPC point-to-register stocke l’emplacement du point dans le registre enregistre la configuration de la frame  
C-x r C-@ point-to-register      
C-x r C-SPC point-to-register      
C-x r + increment-register incrémente le registre si c’est un nombre ajoute 4 au registre  
    ajoute la région entre point et marque si c’est du texte et supprime la région  
C-x r f frameset-to-register stocke l’ensemble des frames dans le registre    
C-x r i insert-register insère le contenu du registre, le point avant et la marque après le texte inséré inverse le point et la marque  
C-x r j jump-to-register déplace le point vers l’emplacement stocké dans le registre    
    si c’est un fichier, va au fichier    
    si c’est une configuration de windows, rétablit la frame    
    si c’est une configuration de frames, rétablit les frames supprime les frames en plus  
C-x r n number-to-register stocke à partir du point jusqu’à la fin le chiffre dans le registre, 0 si pas de chiffre stocke 4 dans le registre  
C-x r r copy-rectangle-to-register stocke le rectangle dans le registre le supprime  
C-x r s copy-to-register stocke la région dans le registre la supprime  
C-x r x copy-to-register      
C-x r w window-configuration-to-register stocke la configuration des windows de la frame actuelle    
C-x r m bookmark-set ajoute un bookmark à l’emplacement courant n’écrase pas si un bookmark de même nom existe déjà insère le nom du dernier bookmark utilisé dans le document
C-x r b bookmark-jump va au bookmark    
C-x r l bookmark-bmenu-list affiche la liste des bookmarks    

Divers

      M-4 C-u
C-x C-c save-buffers-kill-terminal demande s’il faut sauver chaque buffer, ferme la connexion sauve sans demander puis ferme  
C-z suspend-frame suspend la frame courante    
C-g keyboard-quit quitte la commande en cours    
C-x u undo annule les précédents changements annule les 4 derniers changements  
C-_ undo (si en mode transient mark, (si pas en mode transient mark,  
C-/ undo avec la marque active uniquement dans la région) limite à la région)  
M-/ dabbrev-expand complétion dynamique : les précédents mots du buffer prend la 4ème possibilité  
    les suivants, les autres buffers    
M-$ ispell-word ispell sur le mot retourne à la vérification  
M-! shell-command exécuter une commande shell insère le résultat de la commande  
M-& async-shell-command comme shell-command mais ajoute un &    
M-| shell-command-on-region exécuter une commande shell avec la région comme input remplace la région avec le résultat  
M-. find-tag trouve le tag dans la table des tags courante trouve le prochain  
C-x C-e eval-last-sexp évalue la sexp avant le point insère le résultat dans le buffer  
M-0 C-x C-e     insère le résultat non tronqué  
M-: EXP eval-expression évalue la sexp EXP insère le résultat dans le buffer  
M-0 M-:     insère le résultat non tronqué  

Footnotes:

1

pas bien sûr que ce soit utile… En plus risque de pourrir le fichier custom ?

2

C'est le cas pour la majorité des exemples j'ai l'impression, même si on trouve des bouts de python pour les classes principales : http://www.riverbankcomputing.co.uk/static/Docs/PyQt4/html/qimage.html#QImage-8

Autres billets

Date:

Generated by Emacs 24.3.1 (Org mode 8.2.4) - Show Org source (htmlized)

CSS inspired by Tontof, colors by Chaotic Soul

Validate