I have written a function which capitalises the first letter of each word like this:

function! CamelCase() range
  let old = getline(a:firstline, a:lastline)
  for line in old
      let x = substitute(line,'\v<(.)(\w*)', '\u\1\L\2', 'g')
      echom x

command! -range=% CamelCase <line1>,<line2>call CamelCase()

Currently :CamelCase()displays the output in :messsages (because of echom)

How do i modify the function so it modifies the current buffer directly instead ? I have tried removing echom x and let x= but I get a large number of errors.

  • 2
    setline(line, substitute(...)), for one.
    – B Layer
    Mar 1, 2020 at 12:33
  • thank you, for some reason i had to use call : call setline(line,substitute(line,'\v<(.)(\w*)', '\u\1\L\2', 'g')) . I don't understand when to use call and when not to quite yet. Mar 1, 2020 at 12:47
  • 1
    Sorry, the call was implied in my comment but I should have been explicit. function() won't work without preceding it with call or something that consumes its output (e.g.echo or variable assignment). Commands are different...they can be called straight/unadorned.
    – B Layer
    Mar 1, 2020 at 12:50
  • 2
    A little more explicitly, if you are using the return value of func() (examples: let foo = func(), echo func(), call otherfunc(func())) then invocation of func() is implied. If you only care about the side-effects (i.e. you want to ignore/discard the returned value) then use call to invoke func().
    – B Layer
    Mar 1, 2020 at 13:11

1 Answer 1


You can use setline() to set the contents of a line in the current buffer.

Which, in your case, should be enough, since you're changing line contents in place and not inserting or deleting lines. (There's appendbufline() and deletebufline() which can help with that.)

Note that in your case you don't need to have your function be a range function, since the behavior of :call of a non-range function with a range is to call it repeatedly for each line in the range. So that would implicitly loop over the lines for you.

This should be enough:

function! CamelCase()
    call setline('.',
       \ substitute(getline('.'),
       \ '\v<(.)(\w*)', '\u\1\L\2', 'g'))

And you can keep the exact same command definition:

command! -range=% CamelCase <line1>,<line2>call CamelCase()

Your Answer

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

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