1

I'm trying to set up some fancy zle completion that requires passing the word at point to a subprocess.

Zsh obviously knows about the current word/token/directory, and I can see how to bind things based on the current word, but I can't figure out how to turn "where I am" into a variable capable of being passed into subprocesses. (I want emacs' thing at point but in zsh.)

1 Answer 1

3

I use a simple zle widget print-current-word to illustrate how you can extract the current word on the command line in simple cases, i.e. assuming that blanks are always word separators. (So this fails when quoting or escaped blanks come into play):

print-current-word() {
  CURRENTWORD="${LBUFFER/* /}${RBUFFER/ */}"
  print; print "The current word is: $CURRENTWORD"
}
zle -N print-current-word
  • $LBUFFER and $RBUFFER contains the command line left and right from the cursor, respectively.
  • ${name/pattern/repl} return the variable name with pattern replaced with repl. So in that case this trims in $LBUFFER everything up to the last blank, leaving the portion left of the cursor of the current word. Analog for $RBUFFER.

A more complicated approach would be:

print-current-word () {
    local words i beginword
    i=0 
    beginword=0
    words=("${(z)BUFFER}") 

    while (( beginword <= CURSOR )); do
            (( i++ ))
            (( beginword += ${#words[$i]}+1 ))
    done
    CURRENTWORD="$words[$i]"
    print; print "The current word is: $CURRENTWORD"
}

However, this one is also not free of assumptions, as it is assumes that every word is separated by exactly one blank (addition of +1 to beginword).

Just a few words about some special things:

  • words=("${(z)BUFFER}") splits $BUFFER, i.e. the complete command line, into shell words using shell parsing rules by Expansion Flag (z) and puts it into an array
  • (( ... )) activates zsh's math mode
  • ${#name} gives the length of the variable name
0

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .