Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: zle insert problems

On Tue, 2 Aug 2011 16:55:46 +0200
Pascal Wittmann <PascalWittmann@xxxxxxx> wrote:
> Ok, that would work in this simple example. But actually I want to do
> some more stuff (the code above was just a minimal working example),
> here is the function:
>  9 replace-pacman-command() {
> 10   if [[ $LBUFFER = "pacman"* ]]; then
> 11      zle beginning-of-line
> 12      zle forward-word
> 13      zle delete-word
> 14      zle -U -- $@
> 15      zle end-of-line
> 16   fi
> 17 }
> 18
> 19 replace-pacman-command-insert() {
> 20   replace-pacman-command "-S"
> 21 }
> 22
> 23 zle -N replace-pacman-command-insert
> 24 bindkey "^[i" replace-pacman-command-insert

To back up Mikael and answer your original question: yes, you're doing
this the wrong way.  The commands you're executing move the cursor and
edit the buffer as for user interaction, which will be painful because
actually there is no user interaction.  All you're trying to do is edit
the text in the buffer, without intervention from the user.  So you're
much better off operating on BUFFER or equivalent, where instead of a
sequence of operations you can encode the whole operation in patterns,
in fact one pattern.  This does require you to know a bit about zsh
patterns, but the following should be enough to get you going.

I'm not sure why you need this only to work when the first word is
"pacman", given the user is initiating this explicitly so should be able
to decide whether they want the word replaced, but to follow what you're
doing...  I'm assuming you have a recent version of zsh (any version of
4.3 within the last few years is certainly OK).

replace-pacman-command() {
   # Ensure extended globbing is on.
   emulate -L zsh
   setopt extendedglob
   # The variables used by the extendeglob (#b) matching option.
   local -a match mbegin mend
   # Match the line in three parts.
   # - "pacman" plus any characters not part of a word.
   # - Any set of characters that are part of the word.
   # - The rest
   # You could replace "pacman" with [[:WORD:]]## which matches
   # any number of word charaters at this point.
   # Translation:
   # (#b) - turn on match references ("backreferences").
   # (....) - each of these now produces a word in the match array
   # [[:WORD:]] - Any character that can be in a word.  This
   #              bit won't work in zsh 4.2, but you can make something up.
   # [[:WORD:]]## - Same, with as may repetitions as will match, but at
   #                least one occurrence.
   # [^[:WORD:]] - Any character that can't be in a word
   if [[ $BUFFER = (#b)("pacman"[^[:WORD:]]##)([[:WORD:]]##)(*) ]]; then
      # Replace the middle part, keeping the rest.
   # Always put the cursor at the end of the line.
   # (Not actually needed for the rest of the logic to work.)
   zle end-of-line

Peter Stephenson <pws@xxxxxxx>            Software Engineer
Tel: +44 (0)1223 692070                   Cambridge Silicon Radio Limited
Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, UK

Member of the CSR plc group of companies. CSR plc registered in England and Wales, registered number 4187346, registered office Churchill House, Cambridge Business Park, Cowley Road, Cambridge, CB4 0WZ, United Kingdom
More information can be found at www.csr.com. Follow CSR on Twitter at http://twitter.com/CSR_PLC and read our blog at www.csr.com/blog

Messages sorted by: Reverse Date, Date, Thread, Author