zshzsh-zle

widgets for case manipulation: `gU` in normal and `U` in visual mode


I reckon there's already a widget for the g~ action in zle. So g~iw will invert the case of a word.

I read the zshzle manual and did not find a widget that would give me the behaviour of gU (capitalize action) in vim.

for example: for the word "path_variable", with the cursor on the v, gUiW would change the world to "PATH_VARIABLE", and so on and so forth.

the widget capitalize-word does not seem to be the answer. I've tested it.

I also found that the key U in visual mode does not capitalize the visually selected text/region. I did not find a widget in the manual that would give me the desired behaviour either.

Is this a matter of writing a custom widget, or would one have to submit a patch upstream with c code changes? How can I bind gU in normal and U in visual mode to achieve the desired behaviour in zle vi-mode?


Solution

  • ZSH 5.3 will have pre built widgets for that. But if you can't wait, here it is:

    # credits go to Oliver Kiddle <opk@zsh.org>,
    # who personally shared these upper/lower widgets.
    # I just corrected a small bug.
    vi-lowercase() {
      local save_cut="$CUTBUFFER"
      local save_cur="$CURSOR"
    
      zle .vi-change || return
      zle .vi-cmd-mode
    
      CUTBUFFER="${CUTBUFFER:l}"
    
      if [[ $CURSOR = '0' ]]; then
        zle .vi-put-before -n 1
      else
        zle .vi-put-after -n 1
      fi
    
      CUTBUFFER="$save_cut" 
      CURSOR="$save_cur"
    }
    
    vi-uppercase() {
      local save_cut="$CUTBUFFER" 
      local save_cur="$CURSOR"
    
      zle .vi-change || return
      zle .vi-cmd-mode
    
      CUTBUFFER="${CUTBUFFER:u}"
    
      if [[ $CURSOR = '0' ]]; then
        zle .vi-put-before -n 1
      else
        zle .vi-put-after -n 1
      fi
    
      CUTBUFFER="$save_cut" 
      CURSOR="$save_cur"
    }
    
    # can safely disable this after commit zsh commit #a73ae70 (zsh-5.2-301-    ga73ae70)
    zle -N vi-lowercase
    zle -N vi-uppercase
    bindkey -a 'gU' vi-uppercase
    bindkey -a 'gu' vi-lowercase
    bindkey -M visual 'u' vi-lowercase
    bindkey -M visual 'U' vi-uppercase