有时,C中的数组初始化会延伸到多行,特别是如果数组是多维的。在Emacs中,自动缩进的结果如下所示:
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}};
在Vim中,:filetype indent on
启用的自动缩进功能只是按常量shiftwidth
缩进行,这导致以下内容:
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}};
在这种特殊情况下,有没有办法让Vim像Emacs一样?
Herbert Sitz的答案确实非常有用(谢谢!)。我稍微修改了他的代码,看起来像这样:
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
将其保存到文件~/.vim/after/ftplugin/c.vim
可以解决问题,即它使Vim以与Emacs相同的方式对齐数组声明。
matchstr()
代替matchlist()
使代码更易于理解(len(m)
代替len(m[0])
)。static
声明。{
),以便表达式也匹配一维数组(或结构)。;
)的表达式,因为这表示声明保存在一行中(即下一行不应在左括号下对齐)。我认为这比在行尾查找右括号或逗号更为通用。如果我错过了重要的事情,请告诉我。
答案 0 :(得分:6)
有人可能比我更了解,但这是第一次刺:是的,缩进可以定制。如果您的文件是公认的语言“filetype”,那么它将使用/ indent目录(e..g,vim / vim72 / indent)中相应的* .vim文件中的规则/代码缩进。
您需要修改在多行数组上提供缩进的代码,这可能涉及向创建缩进的部分添加新的if块,if表达式匹配所有且只有多行的第一行阵列。您应该能够通过检查/ indent目录中的文件来了解工作原理。
更新:这是c.vim缩进文件的一个mod,应该接近你想要的,似乎对我来说很好。这是整个文件:
" Last Change: 2005 Mar 27
" Only load this indent file when no other was loaded.
if exists("b:did_indent")
finish
endif
let b:did_indent = 1
" C indenting is built-in, thus this is very simple
setlocal cindent
setlocal indentexpr=GetMyCIndent()
function! GetMyCIndent()
let theIndent = cindent(v:lnum)
let m = matchlist(getline(v:lnum - 1),'^\S\+\s\+\S\+\s*=\s*{\s*{\ze.*}[^}*]')
let m2 = matchlist(getline(v:lnum - 1),'}.*}')
if (!empty(m)) && (empty(m2))
let theIndent = len(m[0]) - 1
endif
return theIndent
endfunction
let b:undo_indent = "setl cin<"
这个代码唯一的问题(我认为)是它会给在一行上完成 的数组初始化数组提供相同的缩进。为了避免模式需要修改以仅在行上有一个结束括号时匹配,而不是两个。 (或者,你可以做一个单独的测试。)这需要一点点,但不应该太难。 (另外,如果你扩展当前模式,你将需要在模式中使用\ ze标记来标记你想要存储在m [0]中的匹配的结尾,这将是在第二个开始括号之后的最后一个字符目前的模式。)我修改了上面的代码进行单独测试(使用变量m2)我认为解决了问题。不确定需要注意哪些其他细节。
一种替代方法是,只要行上至少有两个左括号,而最后一行char是逗号,就会想要这种缩进行为。这实际上可能是最好的方法,因为它可以让你在一行上有元素,三元组等元素:
let m = matchlist(getline(v:lnum - 1),'^\S\+\s\+\S\+\s*=\s*{\s*{\ze.*,\s*$')
if !empty(m)
let theIndent = len(m[0]) - 1
endif
答案 1 :(得分:0)
我认为您可以键入:set ai!
然后缩进第二个维度行,然后当您按Enter键并键入第三个维度行时,它将正确缩进...抱歉,如果它不是一个有效的解决方案。