Sometimes an array initialization in C extends over several lines, especially if the array is multidimensional. In Emacs the result of auto-indentation looks like this:

int a[N][N] = {{0, 0, 6, 7, 0, 4, 0, 2, 0},
               {0, 5, 0, 6, 0, 0, 0, 0, 1},
               {2, 0, 0, 0, 0, 8, 0, 0, 4},
               {4, 0, 9, 5, 0, 7, 0, 0, 3},
               {0, 0, 0, 0, 0, 0, 0, 0, 0},
               {8, 0, 0, 2, 0, 1, 9, 0, 6},
               {6, 0, 0, 1, 0, 0, 0, 0, 7},
               {3, 0, 0, 0, 0, 5, 0, 6, 0},
               {0, 2, 0, 3, 0, 6, 1, 0, 0}};

In Vim the auto-indentation feature enabled by :filetype indent on merely indents the lines by the constant shiftwidth which leads to the following:

int a[N][N] = {{0, 0, 6, 7, 0, 4, 0, 2, 0},
    {0, 5, 0, 6, 0, 0, 0, 0, 1},
    {2, 0, 0, 0, 0, 8, 0, 0, 4},
    {4, 0, 9, 5, 0, 7, 0, 0, 3},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {8, 0, 0, 2, 0, 1, 9, 0, 6},
    {6, 0, 0, 1, 0, 0, 0, 0, 7},
    {3, 0, 0, 0, 0, 5, 0, 6, 0},
    {0, 2, 0, 3, 0, 6, 1, 0, 0}};

Is there a way to make Vim behave like Emacs in this particular situation?

UPDATE:

Herbert Sitz's answer was indeed very helpful (thanks!). I have slightly modified his code to look like this:

setlocal indentexpr=GetMyCIndent()

function! GetMyCIndent()
    let theIndent = cindent(v:lnum)

    let m = matchstr(getline(v:lnum - 1),
    \                '^\s*\w\+\s\+\S\+.*=\s*{\ze[^;]*$')
    if !empty(m)
        let theIndent = len(m)
    endif

    return theIndent
endfunction

Saving this to the file ~/.vim/after/ftplugin/c.vim solves the problem, i.e. it makes Vim align the array declaration the same way Emacs does.

What I have changed:

  • Use matchstr() instead of matchlist() to make the code easier to understand (len(m) in place of len
Edit
Report