16

I'm currently trying to figure out vimscript and I stumbled upon the append() function. The documentation states that you can specify the line to which an expression should be appended to, so I tried:

:call append(line('.'), Foo())

Foo() returns a string.

The weird thing is that the string is appended to the next line after my current one. So I tried line('.') - 1, just to see that it appends to the line above the current one.

I'm amazed, confused and speechless at this moment.

Hope someone can shed some light on this.

2
  • the documentation clearly states that the expression, Foo() in this case, should be appended as one line below the specified line. It is not to be confused with the normal mode command A which indeed appends text to the current line.
    – Naumann
    Commented May 21, 2017 at 2:10
  • 1
    Take a look at :help function-list to see what built-in functions are available.
    – Antony
    Commented May 21, 2017 at 10:32

3 Answers 3

11

append() inserts several lines of text below the line specified as the first argument. This is in line with the append ex command. You can for example type :append (and enter ex mode) then write several lines of text and exit ex mode (by pressing <c-c> for example), the lines will appear after the line your cursor is on. In other words, the append command means: append the lines of text I'll write below the current one.

The VimScript function append() allows for line specifiers, which makes it more useful than the ex command. Useful things that come often are ways of injecting pieces of text at the beginning and end of a file. e.g. for LaTeX this may be useful:

call append(line('^'), [ '\documentclass[12pt]{article}'
\                      , '\begin{document}'])
call append(line('$'), '\end{document}')

Where line('$') is the last line in the file and line('^') always returns 0 (and I could have written that instead without problems).

To get the behaviour of Vim's A, or any other Vim normal mode command you can use normal. To get the output of Foo() to appear at the end of a line may be a little more complicated, one way is to use execute:

execute ':normal! A' . Foo()

Or you can use append and then perform J:

call append(line('.'), Foo())
normal! Jx

(Note that x is needed to remove the space generated by J, but this may not work as expected if the string generated by Foo() starts with spaces).

2
  • 5
    setline() + getline() is another option.
    – Antony
    Commented May 21, 2017 at 10:36
  • 4
    gJ does the joining without spaces Commented Sep 18, 2017 at 20:00
17

The append() function should perhaps have been named appendline(): it only appends lines to the buffer. You can't change existing lines with it.

It's like using the a flag to fopen(), or using >> in the shell.


If you want to set the value of existing lines, then the easiest way to do that from VimScript is to use setline(). For example to set the current line to Coconuts:

:call setline('.', 'Coconuts')

You can use getline() to get the value of the current line, so to append Coconuts to the line use something like:

:call setline('.', getline('.') . 'Coconuts')

You can also set multiple lines by using a list (just like with append()):

:call setline('.', ['Coconuts', 'Bananas'])

To append text to multiple lines you'll have to use a for loop.


Note that the above is not the only way. Other ways would be to use :substitute (e.g. :s/$/\=Foo()/) or grochmal's answer. The "best" way depends on the context where you're using it as well as personal preference.

0

An alternative to using built in functions like append which might be too clumsy is to use execute "normal! ..." and enter the keystrokes that do what you want. Here's a contrived example:

function! PromptAndAppendWord()
  let word = input("Type a word and press enter: ")
  execute "normal! a" . word
endfunction

When you call this function (:call PromptAndAppendWord()) it will prompt you for a word and then append it after where the cursor is using the normal a command.

Read more about this idiom here: https://learnvimscriptthehardway.stevelosh.com/chapters/30.html

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.