# 13. Édition interactive des entrées et substitution d’historique

Certaines versions de l’interpréteur Python prennent en charge l’édition de la ligne d’entrée courante et la substitution d’historique, similaires aux facilités que l’on trouve dans le shell Korn et dans le shell GNU Bash. C’est implémenté en utilisant la bibliothèque GNU Readline, qui supporte l’édition en style Emacs et en style Vi. La bibliothèque a sa propre documentation qui ne va pas être dupliquée ici ; toutefois, les bases seront expliquées rapidement. L’éditeur interactif et la gestion d’historique décrits ici sont disponibles en option sous les versions Unix et Cygwin de l’interpréteur.

Ce chapitre ne décrit pas les possibilités d’édition du paquet PythonWin de Mark Hammond ou de l’environnement basé sur Tk, IDLE, distribué avec Python. Le rappel d’historique des lignes de commandes qui fonctionne dans des fenêtres DOS sous NT ou d’autres variétés de Windows est encore une autre histoire.

## 13.1. Édition de ligne

Si elle est supportée, l’édition de la ligne d’entrée est active lorsque l’interpréteur affiche une invite primaire ou secondaire. La ligne courante peut être éditée en utilisant les caractères de contrôles traditionnels d’Emacs. Les plus importants d’entre eux sont : `C-A` (Contrôle-A) déplace le curseur au début de la ligne, `C-E` à la fin, `C-B` d’un caractère vers la gauche, `C-F` d’un caractère vers la droite. La touche retour arrière efface le caractère à la gauche du curseur, `C-D` le caractère à sa droite. `C-K` supprime le reste de la ligne à la droite du curseur, `C-Y` rappelle la dernière chaîne supprimée. `C-tiret bas` annule la dernière modification ; cette commande peut être répétée pour cumuler ses effets.

## 13.2. Substitution d’historique

La substitution d’historique fonctionne comme ceci. Toutes les lignes non vides reçues sont enregistrées dans un tampon d’historique et, à chaque fois qu’une invite est affichée, vous êtes positionné sur une nouvelle ligne à la fin de ce tampon. `C-P` remonte d’une ligne (en arrière) dans ce tampon, `C-N` descend d’une ligne. Chaque ligne présente dans le tampon d’historique peut être éditée ; un astérisque apparaît en face de l’invite pour indiquer qu’une ligne a été modifiée. Presser la touche `Entrée` envoie la ligne en cours à l’interpréteur. `C-R` démarre une recherche incrémentale en arrière ; `C-S` démarre une recherche en avant.

## 13.3. Raccourcis clavier

Les raccourcis clavier ainsi que d’autres paramètres de la bibliothèque Readline peuvent être personnalisés en inscrivant des commandes dans un fichier d’initialisation appelé `~/.inputrc`. Les raccourcis sont de la forme

    key-name: function-name

ou :

    "string": function-name

et les options peuvent être définies avec

    set option-name value

Par exemple :

    # I prefer vi-style editing:
    set editing-mode vi

    # Edit using a single line:
    set horizontal-scroll-mode On

    # Rebind some keys:
    Meta-h: backward-kill-word
    "\C-u": universal-argument
    "\C-x\C-r": re-read-init-file

Notez que le raccourci par défaut pour la touche `Tab` en Python est d’insérer un caractère de tabulation au lieu de la fonction par défaut de complétion des noms de fichiers de la bibliothèque Readline. Si vous y tenez, vous pouvez surcharger ce comportement en indiquant

    Tab: complete

dans votre fichier `~/.inputrc` (bien sûr, avec cela il devient plus difficile d’entrer des lignes de continuation indentées si vous êtes habitué à utiliser `Tab` dans ce but).

La complétude automatique des noms de variables et de modules est disponible de manière optionnelle. Pour l’activer dans le mode interactif de l’interpréteur, ajoutez les lignes suivantes à votre fichier de démarrage : [1]

    import rlcompleter, readline
    readline.parse_and_bind('tab: complete')

Ceci lie la touche `Tab` à la fonction de complétude, donc taper la touche `Tab` deux fois de suite suggère les options disponibles ; la recherche s’effectue dans les noms d’instructions Python, les noms des variables locales et les noms de modules disponibles. Pour les expressions pointées telles que `string.a`, l’expression est évaluée jusqu’au dernier `'.'` avant de suggérer les options disponibles à partir des attributs de l’objet résultant de cette évaluation. Notez bien que ceci peut exécuter une partie du code de l’application si un objet disposant d’une méthode `__getattr__()` fait partie de l’expression.

Un fichier de démarrage plus complet peut ressembler à cet exemple. Notez que celui-ci supprime les noms qu’il crée dès qu’ils ne sont plus nécessaires ; ceci est possible car le fichier de démarrage est exécuté dans le même espace de noms que les commandes interactives, et supprimer les noms évite de générer des effets de bord dans l’environnement interactif. Vous pouvez trouver pratique de conserver certains des modules importés, tels que `os`, qui s’avère nécessaire dans la plupart des sessions avec l’interpréteur.

    # Add auto-completion and a stored history file of commands to your Python
    # interactive interpreter. Requires Python 2.0+, readline. Autocomplete is
    # bound to the Esc key by default (you can change it - see readline docs).
    #
    # Store the file in ~/.pystartup, and set an environment variable to point
    # to it:  "export PYTHONSTARTUP=~/.pystartup" in bash.

    import atexit
    import os
    import readline
    import rlcompleter

    historyPath = os.path.expanduser("~/.pyhistory")

    def save_history(historyPath=historyPath):
        import readline
        readline.write_history_file(historyPath)

    if os.path.exists(historyPath):
        readline.read_history_file(historyPath)

    atexit.register(save_history)
    del os, atexit, readline, rlcompleter, save_history, historyPath

## 13.4. Alternatives à l’interpréteur interactif

Cette facilité constitue un énorme pas en avant comparé aux versions précédentes de l’interpréteur. Toutefois, il reste des fonctions à implémenter comme l’indentation correcte sur les lignes de continuation (l’analyseur sait si une indentation doit suivre) ; le mécanisme de complétion devrait utiliser la table de symboles de l’interpréteur. Une commande pour vérifier (ou même suggérer) les correspondances de parenthèses, de guillemets…, serait également utile.

Une alternative améliorée de l’interpréteur interactif est développée depuis maintenant quelques temps : IPython. Il fournit la complétion, l’exploration d’objets et une gestion avancée de l’historique. Il peut également être personnalisé en profondeur et embarqué dans d’autres applications. Un autre environnement interactif amélioré similaire est bpython.

Notes

[1] | Python exécute le contenu d’un fichier identifié par la variable d’environnement `PYTHONSTARTUP` lorsque vous démarrez un interpréteur interactif. Pour personnaliser Python y compris en mode non interactif, consultez Modules de personnalisation.