zsh et ZLE (Zsh Line Editor)

Bruno Bonfils asyd at asyd.net
Wed Aug 9 09:24:19 CEST 2006


Voilà ce que ca donne un geek qui a envie de geeker mais qui n'a pas
d'internet ! Petit conseil, lisez jusqu'au bout, je pense que ca vaut le
coup.


Table des matières
----------------------------------------------------------------------

1] Quelques exemples de widget
   -) push-line
   -) history-search-{forward,backward}
   -) insert-last-word
   -) run-help
2] Astuces
   -) zle
   -) bindkey
3] Définir d'un nouveau widget

4] Création d'un nouveau widget : regex-edit

0] Introduction
----------------------------------------------------------------------

ZLE (zsh line editor) est le composant de zsh qui interagit avec
l'utilisateur, celui qui reçoit les entrées du clavier.  Il est
composé en widgets, certains sont builtins, d'autres sont des scripts
zsh (répertoire zle).

Voici quelques widgets que j'affectionne particulièrement, la séquence
entre parenthèse correspond au raccourci du mode emacs. ( ^[
correspond à ESC)

1] Quelques exemples de widget
----------------------------------------------------------------------

push-line (^[q)

   Garde en mémoire le buffer actuel (la commande à éxécuter), puis
   proprose un nouveau prompt, pour finalement insérer le contenu
   du précedent buffer.

   Exemple :

   % vi .zshrc (on appuie pas sur entrée mais sur ^[q)
   % cd
   % vi .zshrc (rajouté automatiquement par zsh)

   Ce widget est particulièrement utile pour changer de répertoire
   avant d'exécuter la commande voulue.

history-search-forward (^[n]
history-search-backward (^[p)

   Recherche avant (^[n) ou arrière (^[p) dans l'historique en
   utilisant le premier mot (i.e. la commande) en motif de recherche.
   Personnellement, ces deux widgets me sont vraiment très utile, et je
   les utilise régulièrement.  Concrètement, voici ce que ca donne :

   % ping guses.org
   [.. nombreuses commandes autre que ping ..]
   % ping cli.asyd.net
   [.. nombreuses commandes autre que ping ..]
   % ping

   Une première utilisation de history-search-backward complétera
   cli.asyd.net, le second complétera guses.org, finalement
   history-search-forward complétera cli.asyd.net

insert-last-word (^[.])

   Insère le dernier mot de la commande précédente

   % ssh kaoru
   % ping rei
   % ssh
      le premier ^[.] complétera rei
      le second complétera kaoru

run-help (^[h)

   Exécute la commande man (généralement) avec en argument le premier
   mot (la commande donc)

2] Astuces
----------------------------------------------------------------------

Lister les widgets disponibles

   % zle -l

Lister les raccourcis

   % bindkey

Définir un nouveau raccourci

   % bindkey <séquence> <widget>

Afficher en texte une séquence

   % <Control-v> <séquence>

   Par exemple, la succession de Control-V ESC p affichera ^[p

3] Définir un nouveau widget
----------------------------------------------------------------------

Il suffit de créer une fonction puis d'utiliser la commande zle de la
manière suivante :

   % zle -N <nom widget> [<nom fonction>]

Il existe un certain nombre de variables disponibles dans le contexte
zle, mais généralement le but est de modifier la variable BUFFER.

4] Création d'un nouveau widget : regex-edit

J'ai toujours révé d'un widget me permettant d'appliquer une regex
à la commande en cours, en fait, j'aurais dû me motiver plus tôt,
car c'est vraiment simple !

Il suffit de créer une fonction qui modifie la variable BUFFER (l'une
des nombreuses disponible dans un contexte ZLE). Dans mon cas,
j'utilise le module read-from-minibuffer pour demander à l'utilisateur
de fournir la regex, puis je modifie chaque mot de $BUFFER sauf le
premier (la commande). Merci aux quelques scripts zle qui m'ont permis
de trouver read-from-minibuffer !

--%--
# Charge le module
autoload -U read-from-minibuffer

regex-edit () {
   # variables locales
   local REPLY words result
   # fais un split de BUFFER (créer un tableau avec chaque mot)
   words=(${=BUFFER})
   # demande la regexp (et rempli la variable REPLY)
   read-from-minibuffer "Regex:"
   if [ -n $REPLY ]; then
      # applique la regex sur les mots 2 à (longueur du tableau)
      # et finalement reforme BUFFER à partir de la commande et du
      # résultat
      BUFFER="$words[1] $(echo $words[2,${#words}] | sed ${REPLY})"
   fi
}

zle -N regex-edit
bindkey "^[e"] regex-edit
--%--

Attention, il n'y a pas de gestion d'erreur sur sed.

Petit test :

% echo toto
Regex: s/o/a/g
% echo tata

Et voilà, zsh, c'est magique !


-- 
http://asyd.net/home/   - Home Page
http://guses.org/home/  - French Speaking Solaris User Group


More information about the Shell mailing list