0

I am trying to write my (first) function which is (eventually to be) a toggle on my colorscheme. What I have now is as follows:

nnoremap <expr> <leader>3 ToggleColors()
func ToggleColors()
    let x = ":colorscheme"
    echom '111' + x
    x = x += "TextMate"
    echom '222' + x
    return x
endfunc

Here is what I am trying to do:

  • Set a variable x to be the string :colorscheme
  • Print it, which should give me the output message 111 :colorscheme
  • Append to the variable x, so now it should be :colorscheme TextMate
  • Print it again, so now it should print 222: colorscheme

However, it seems like the echom '111' + x only prints 111, and the string-concatenation is giving me an error.

What would be the proper way to write this? Finally, is there any way to debug functions in vim? Or do you just have to check messages? All the error messages (stacktraces) I get give almost zero information...less than even SQL would.

1

String concatination in Vim is done with a . (dot).

So:

func ToggleColor()
    let x = ":colorscheme"
    echom '111' . x
    let x .= " TextMate"
    echom '222' . x
    return x
endfunc

In your scenario I would not use map-expression. (Guess you want to use a function, because you are learning Vim)

nnoremap <leader>3 :call ToggleColors()<cr>
function ToggleColors()
    let x = "colorscheme"
    let x .= " TextMate"
    call execute(x)
endfunction

And the simplest solution would be:

nnoremap <leader>3 :colorscheme TextMate<cr>

When to use a map-expression?

Normally a mapping is fixed. Like

nnoremap A  B

So whenever you type A you will get B.

With a map-expression you are able to create a dynamic mapping.

This (useless) mapping maps A to either 0 or $.

:nnoremap <expr> A col('.') == 1?'$':'0'

If you hit A and the cursor is in the first column, you will jump to end of line. In all other scenarios the cursor jumps to the first column.

Instead of doing it on one line, you could also do it in a function:

nnoremap <expr> A  JumpAround()
function JumpAround()
    if col('.') == 1
        return '$'
    else
        return '0'
    endif
endfunction

Note that there are limitations what you can do in a function called from a map-expression. See :h map-expression.

| improve this answer | |
  • thanks for this. A few questions: (1) are you able to do func () without a function name, or that's just for an example? (2) why do you call execute at the end instead of return? – David542 Jun 13 at 5:03
  • Finally, (3) In your scenario I would not use map-expression -- why would you use the :call over using the <expr>? When would you ever want to use <expr> then? – David542 Jun 13 at 5:08
  • 1
    @David542 (1) Typo - fixed (2) The execute just executes the string content. (3) see update – Ralf Jun 13 at 6:18

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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