3

I'd like to reproduce this zsh mapping:

smart_dot() {
  if [[ $LBUFFER = *.. ]]; then
    LBUFFER+=/..
  else
    LBUFFER+=.
  fi
}
zle -N smart_dot
bindkey -M viins -- . smart_dot

At first I used this:

function! Smart_dot() abort
  if getcmdtype() =~# '[:]'
    let l:cmd=getcmdline()
    if match(l:cmd, '\.\.$') !=-1
      return '/..'
    else
      return "."
    endif
  else
    return getcmdline()
  endif
endfunction
cnoremap . <c-r>=Smart_dot()<CR>

but how do turn this into local function? I've tried many variants on this that wouldn't work because it complained <SID> was not used in a script context. Do I need to use <c-r>= or <c-\>e? Do I need to use the expand(<sfile>) trick to get the script number, described near the end of section :h script-local? Or do I need to <Plug> this? I'm confused.

" function! s:smart_dot() ...
cnoremap . <C-\>ecall(function('<SID>smart_dot()'), [])<CR>
1
  • You should check :h :map-<expr>.
    – Hauleth
    Jan 8, 2018 at 0:50

1 Answer 1

4

You may use <sid> directly in this context like any other key code:

cnoremap . <c-r>=<sid>Smart_dot()<cr>

The reason is the *map family of commands are special in that they convert key codes to actual real characters. For example, <cr> is converted to a carriage return, code 13, and <c-r> is converted to code 18.

1
  • thanks. When I tried this before, neovim segfaulted, but the function was a little different, so that must have been another issue.
    – Bart
    Jan 5, 2018 at 8:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.