Faire un widget ZLE qui modifie l'argument sous le curseur
==========================================================
Cet exemple remplace l'argument sous le curseur (ou le précédent si le
curseur est entre 2 arguments) (appelons-le "argument courant") par
son chemin parent (son "dirname").
Première méthode (plus simple)
------------------------------
...................
dirname-previous-word () {
autoload -U modify-current-argument
modify-current-argument '${ARG:h}'
}
zle -N dirname-previous-word
bindkey '^[q' dirname-previous-word
...................
Nous définissons ici la fonction "dirname-previous-word" qui sera le
widget, puis nous le déclarons comme widget ZLE avec "zle -N
dirname-previous-word". Enfin, nous assignons ce widget au raccourci
Alt-q.
Dans le code du widget, nous utilisons la fonction
"modify-current-argument" qui est très pratique, car le remplacement
qu'elle fait est pénible autrement.
La fonction "modify-current-argument" prend en paramètre une
expression qui va être évaluée (passée dans un "eval") (il faudra donc
certainement l'échapper), et remplace l'argument courant par le
résultat de cette évaluation. L'expression peut utiliser l'ancienne
valeur de l'argument courant, qui se trouve dans la variable "$ARG".
Cependant, il faut échapper la référence à $ARG car cette variable
n'est pas définie dans notre fonction mais dans la fonction
"modify-current-argument" (là où elle sera évaluée).
Dans ce cas précis, nous remplaçons l'argument courant ($ARG) par son
chemin parent (${ARG:h}).
Méthode un peu plus générique
-----------------------------
Si nous voulons plus de liberté pour modifier l'argument courant,
c'est à dire que la nouvelle valeur de l'argument ne peut pas
"rentrer" dans une simple expression, nous pouvons procéder en 3
étapes : récupérer l'argument courant (grâce à un simple appel d'une
autre fonction qui va nous faciliter la tâche), calculer la nouvelle
valeur (on peut mettre le code qu'on veut), puis faire le remplacement
(toujours avec la fonction modify-current-argument).
...................
dirname-previous-word () {
autoload -U split-shell-arguments
autoload -U modify-current-argument
local res
split-shell-arguments
## pour se positionner sur l'argument précédent si on est entre 2 arguments
## CopierColler de
/usr/share/zsh/functions/Zle/modify-current-argument (licence BSD)
# Get the index of the word we want.
if (( REPLY & 1 )); then
# Odd position; need previous word.
(( REPLY-- ))
# Pretend position was just after the end of it.
(( REPLY2 = ${#reply[REPLY]} + 1 ))
fi
## Fin du CopierColler
res=${reply[$REPLY]}
res=${res:h}
modify-current-argument '$res'
}
zle -N dirname-previous-word
bindkey '^[q' dirname-previous-word
...................
La fonction "split-shell-arguments" ne prend aucun paramètre. Par
contre, elle écrit les variables reply, REPLY et REPLY2.
La valeur de l'argument courant est accessible dans
"${reply[$REPLY]}", nous pouvons faire tous les traitements que l'on
veut dessus, aussi compliqués soient-ils (appels de commandes,
boucles, etc.).
Enfin, nous appelons "modify-current-argument" en passant en paramètre
une référence à la variable qui contient le nouvel argument à
remplacer.
**Attention**, le passage par une variable, de plus échappée, est très
important : si la nouvelle valeur de l'argument contenait ne serait-ce
qu'un '$', ou même un guillemet, et que vous n'aviez pas procédé comme
décrit (mis dans une variable et échappé), vous iriez au devant de
sérieux ennuis.