jdost

Zsh & ZLE

I have been working on my zsh configs (Github Repo) and came across a pretty useful snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
function rationalize_dot {
   local MATCH
   if [[ $LBUFFER =~ '(^|/| |      |'$'\n''|\||;|&)\.\.$' ]]; then
      LBUFFER+=/
      zle self-insert
      zle self-insert
   else
      zle self-insert
   fi
}
zle -N rationalize_dot
bindkey . rationalize_dot
bindkey -M isearch . self-insert

What’s happening in this code is, first, the definition of a function rationalize_dot that scans the current command buffer ($LBUFFER to see if it ends with ... If it does, it will add a / and then insert the character typed twice (this will make more sense in a moment). If the $LBUFFER does not end with .., the character typed is only inserted once. After the function definition is the integration with ZLE. The zle -N rationalize_dot call registers the created function as a valid ZLE key action. Then the following line binds the created function to execute whenever a . is typed and the following disables this binding when in search mode.

So now what does this stuff do? When traversing your file tree, you can now type ... and it will expand as ../.. and each subsequent . typed will expand as another level up the tree. This has been very useful in my day to day usage of the shell. With this inserting works as desired, but what if I have done one too many .s ? So I wrote an unrationalize_dot ZLE function to perform the opposite action as rationalize_dot. (Tools that are extendable via programming are so awesome). So what I ended up with:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function unrationalize_dot {
   local MATCH # keep regex match from leaking into the environment
   if [[ $LBUFFER =~ '(^|/| |      |'$'\n''|\||;|&)\.\.$' ]]; then
      zle backward-delete-char
      zle backward-delete-char
      if [[ $MATCH =~ '^/' ]]; then
         zle backward-delete-char
      fi
   else
      zle backward-delete-char
   fi
}
zle -N unrationalize_dot
bindkey "^h" unrationalize_dot
bindkey "^?" unrationalize_dot

This does basically the same as the other, except it will use backward-delete-char instead of self-insert and will delete one more character if there is a leading / in the buffer (so .. removes both and ../.. becomes just ..). The keys bound to are ^h and ^?, one is for ‘Delete’ and the other ‘Backspace’.

So just a little snippet to power up some of my development tools!