diff --git a/README.md b/README.md index ff251ac..9d1e828 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,52 @@ With Vundle " inside .vimrc Plugin 'pboettch/vim-cmake-syntax' +## Indentation + +There is also an indent file which can do some intelligent alignment. + +### Control-statements + +For control-keywords (`if`, `while`, `foreach`, `macro`, etc) it automatically adds a +`shiftwidth()` (and substracts it for a `end`-keyword). + +### Command arguments + +For commands (so everything which has arguments between parenthesis `(...)`) is tries to do the following: + +Either it aligns all arguments on a new line in the same column as the opening parenthesis if the first argument is on the +same line as the command: + +```cmake +add_custom_target(TARGET name + DEPENDS target + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +``` + +or it indents it with one additional `shiftwidth()` if the first argument is on a new line + +```cmake +add_custom_target( + TARGET name + DEPENDS target + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +``` + +This is achieved by letting `g:cmake_indent_align_command_arguments` to be 1. + +By setting it to 0 (the default) in your vimrc-file the standard behavior is achieved. + +```cmake +add_custom_target(TARGET name + DEPENDS target + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}) +``` + +### Comments + +By setting `g:cmake_indent_align_comments_to_first_column` to 1 (default: 0) comment will always be aligned to the +zero column - otherwise they will aligned as normal line with a statement. + ## Test There is a ever growing test-suite based on ctest located in test/ diff --git a/indent/cmake.vim b/indent/cmake.vim index 33e583d..57343c4 100644 --- a/indent/cmake.vim +++ b/indent/cmake.vim @@ -3,7 +3,7 @@ " Author: Andy Cedilnik " Maintainer: Dimitri Merejkowsky " Former Maintainer: Karthik Krishnan -" Last Change: 2017 Aug 30 +" Last Change: 2017 Sep 24 " " Licence: The CMake license applies to this file. See " https://cmake.org/licensing @@ -14,9 +14,6 @@ if exists("b:did_indent") endif let b:did_indent = 1 -let s:keepcpo= &cpo -set cpo&vim - setlocal indentexpr=CMakeGetIndent(v:lnum) setlocal indentkeys+==ENDIF(,ENDFOREACH(,ENDMACRO(,ELSE(,ELSEIF(,ENDWHILE( @@ -25,13 +22,55 @@ if exists("*CMakeGetIndent") finish endif +let s:keepcpo= &cpo +set cpo&vim + +let s:or = '\|' +" Regular expressions used by line indentation function. +let s:cmake_regex_comment = '#.*' +let s:cmake_regex_identifier = '[A-Za-z][A-Za-z0-9_]*' +let s:cmake_regex_quoted = '"\([^"\\]\|\\.\)*"' +let s:cmake_regex_arguments = '\(' . s:cmake_regex_quoted . + \ s:or . '\$(' . s:cmake_regex_identifier . ')' . + \ s:or . '[^()\\#"]' . s:or . '\\.' . '\)*' + +let s:cmake_indent_comment_line = '^\s*' . s:cmake_regex_comment +let s:cmake_indent_open_regex = '^\s*' . s:cmake_regex_identifier . + \ '\s*(' . s:cmake_regex_arguments . + \ '\(' . s:cmake_regex_comment . '\)\?$' + +let s:cmake_indent_close_regex = '^' . s:cmake_regex_arguments . + \ '\zs)\s*' . + \ '\(' . s:cmake_regex_comment . '\)\?$' + +let s:cmake_indent_begin_regex = '^\s*\(IF\|MACRO\|FOREACH\|ELSE\|ELSEIF\|WHILE\|FUNCTION\)\s*(' +let s:cmake_indent_end_regex = '^\s*\(ENDIF\|ENDFOREACH\|ENDMACRO\|ELSE\|ELSEIF\|ENDWHILE\|ENDFUNCTION\)\s*(' + +if !exists('g:cmake_indent_align_command_arguments') + let g:cmake_indent_align_command_arguments = 0 +endif + +if !exists('g:cmake_indent_align_comments_to_first_column') + let g:cmake_indent_align_comments_to_first_column = 0 +endif + fun! CMakeGetIndent(lnum) let this_line = getline(a:lnum) - " Find a non-blank line above the current line. - let lnum = a:lnum - let lnum = prevnonblank(lnum - 1) - let previous_line = getline(lnum) + let lnum = a:lnum - 1 + + " Find a non-blank/non-comment line above the current line. + while lnum > 0 + let lnum = prevnonblank(lnum) + let previous_line = getline(lnum) + + " ignore comments (# only, lua-like comment TODO) + if previous_line !~? s:cmake_indent_comment_line + break + endif + + let lnum -= 1 + endwhile " Hit the start of the file, use zero indent. if lnum == 0 @@ -40,46 +79,40 @@ fun! CMakeGetIndent(lnum) let ind = indent(lnum) - let or = '\|' - " Regular expressions used by line indentation function. - let cmake_regex_comment = '#.*' - let cmake_regex_identifier = '[A-Za-z][A-Za-z0-9_]*' - let cmake_regex_quoted = '"\([^"\\]\|\\.\)*"' - let cmake_regex_arguments = '\(' . cmake_regex_quoted . - \ or . '\$(' . cmake_regex_identifier . ')' . - \ or . '[^()\\#"]' . or . '\\.' . '\)*' - - let cmake_indent_comment_line = '^\s*' . cmake_regex_comment - let cmake_indent_blank_regex = '^\s*$' - let cmake_indent_open_regex = '^\s*' . cmake_regex_identifier . - \ '\s*(' . cmake_regex_arguments . - \ '\(' . cmake_regex_comment . '\)\?$' - - let cmake_indent_close_regex = '^' . cmake_regex_arguments . - \ ')\s*' . - \ '\(' . cmake_regex_comment . '\)\?$' - - let cmake_indent_begin_regex = '^\s*\(IF\|MACRO\|FOREACH\|ELSE\|ELSEIF\|WHILE\|FUNCTION\)\s*(' - let cmake_indent_end_regex = '^\s*\(ENDIF\|ENDFOREACH\|ENDMACRO\|ELSE\|ELSEIF\|ENDWHILE\|ENDFUNCTION\)\s*(' - - " Add - if previous_line =~? cmake_indent_comment_line " Handle comments - let ind = ind - else - if previous_line =~? cmake_indent_begin_regex - let ind = ind + shiftwidth() - endif - if previous_line =~? cmake_indent_open_regex - let ind = ind + shiftwidth() - endif + if previous_line =~? s:cmake_indent_open_regex " open parenthesis + if previous_line !~? s:cmake_indent_close_regex " closing parenthesis is not on the same line + call cursor(lnum, 1) + let s = searchpos('(\s*$') " find '(' with nothing or only spaces until the end of the line + if s[0] == lnum + let ind += shiftwidth() + else " an argument after the keyword + call cursor(lnum, 1) + let s = searchpos('(') " find position of first '(' + if g:cmake_indent_align_command_arguments == 0 " old behavior + let ind += shiftwidth() + else + let ind = s[1] + endif + endif + endif + elseif previous_line =~? s:cmake_indent_close_regex " close parenthesis + call cursor(lnum, strlen(previous_line)) + let pairpos = searchpos(s:cmake_indent_open_regex, 'nbz') " find corresponding open paren + if pairpos[0] != 0 + let ind = indent(pairpos[0]) + endif endif - " Subtract - if this_line =~? cmake_indent_end_regex - let ind = ind - shiftwidth() + if previous_line =~? s:cmake_indent_begin_regex " control begin block + let ind = ind + shiftwidth() endif - if previous_line =~? cmake_indent_close_regex - let ind = ind - shiftwidth() + + if this_line =~? s:cmake_indent_end_regex " control end block + let ind = ind - shiftwidth() + elseif this_line =~? s:cmake_indent_comment_line + if g:cmake_indent_align_comments_to_first_column == 1 + let ind = 0 + endif endif return ind diff --git a/test/.vimrc b/test/.vimrc index 7aa0135..d561df2 100644 --- a/test/.vimrc +++ b/test/.vimrc @@ -3,10 +3,21 @@ " remove user's .vimrc - what else? set runtimepath-=~/.vimrc -" add .. as vim-plugin-path (for syntax) +" add .. as vim-plugin-path (for syntax and indent) set runtimepath^=../ " nocompat is needed for html-output set nocompatible +source ../syntax/cmake.vim +source ../indent/cmake.vim + +set expandtab +set nocopyindent +set nopreserveindent +set nosmartindent +set softtabstop=0 +set shiftwidth=4 +set tabstop=4 + syntax on diff --git a/test/if-endif-indent.cmake b/test/if-endif-indent.cmake new file mode 100644 index 0000000..1c4eb32 --- /dev/null +++ b/test/if-endif-indent.cmake @@ -0,0 +1,2 @@ +if(HELLO) +endif() diff --git a/test/if-endif-indent.cmake.html.ref b/test/if-endif-indent.cmake.html.ref new file mode 100644 index 0000000..062a963 --- /dev/null +++ b/test/if-endif-indent.cmake.html.ref @@ -0,0 +1,6 @@ + +
+if(HELLO)
+endif()
+
+ diff --git a/test/indent1.cmake b/test/indent1.cmake new file mode 100644 index 0000000..605c33c --- /dev/null +++ b/test/indent1.cmake @@ -0,0 +1,6 @@ +set_property(TARGET foo APPEND PROPERTY +INCLUDE_DIRECTORIES ${BAR} + +# closing parens "forgotten" + +message(STATUS "Hello World") diff --git a/test/indent1.cmake.html.ref b/test/indent1.cmake.html.ref new file mode 100644 index 0000000..c3cfbe0 --- /dev/null +++ b/test/indent1.cmake.html.ref @@ -0,0 +1,10 @@ + +
+set_property(TARGET foo APPEND PROPERTY
+    INCLUDE_DIRECTORIES ${BAR}
+
+    # closing parens "forgotten"
+
+    message(STATUS "Hello World")
+
+ diff --git a/test/indent2.cmake b/test/indent2.cmake new file mode 100644 index 0000000..22b5451 --- /dev/null +++ b/test/indent2.cmake @@ -0,0 +1,8 @@ +set_property(TARGET foo APPEND PROPERTY +INCLUDE_DIRECTORIES ${BAR}) +message(STATUS "Hello World") + + +set_property(TARGET foo APPEND PROPERTY +INCLUDE_DIRECTORIES ${BAR}) +message(STATUS "Hello World") diff --git a/test/indent2.cmake.html.ref b/test/indent2.cmake.html.ref new file mode 100644 index 0000000..c976b82 --- /dev/null +++ b/test/indent2.cmake.html.ref @@ -0,0 +1,12 @@ + +
+set_property(TARGET foo APPEND PROPERTY
+    INCLUDE_DIRECTORIES ${BAR})
+message(STATUS "Hello World")
+
+
+set_property(TARGET foo APPEND PROPERTY
+    INCLUDE_DIRECTORIES ${BAR})
+message(STATUS "Hello World")
+
+ diff --git a/test/indent3.cmake b/test/indent3.cmake new file mode 100644 index 0000000..e8e953b --- /dev/null +++ b/test/indent3.cmake @@ -0,0 +1,2 @@ +set_property(TARGET foo APPEND PROPERTY INCLUDE_DIRECTORIES ${BAR}) +message(STATUS "Hello World") diff --git a/test/indent3.cmake.html.ref b/test/indent3.cmake.html.ref new file mode 100644 index 0000000..823f02e --- /dev/null +++ b/test/indent3.cmake.html.ref @@ -0,0 +1,6 @@ + +
+set_property(TARGET foo APPEND PROPERTY INCLUDE_DIRECTORIES ${BAR})
+message(STATUS "Hello World")
+
+ diff --git a/test/indent4-align-comment-zero-col.cmake b/test/indent4-align-comment-zero-col.cmake new file mode 100644 index 0000000..90d47dd --- /dev/null +++ b/test/indent4-align-comment-zero-col.cmake @@ -0,0 +1,40 @@ +set_property(TARGET foo APPEND PROPERTY +INCLUDE_DIRECTORIES ${BAR}) + +message(STATUS "Hello World") + +set_property(TARGET foo APPEND PROPERTY # with comment +INCLUDE_DIRECTORIES ${BAR} "()") + +if(VAR) +set_property(TARGET foo APPEND PROPERTY # with comment +INCLUDE_DIRECTORIES ${BAR}) + +message(STATUS "Hello World") + +set_property(TARGET foo APPEND PROPERTY +# with comment +INCLUDE_DIRECTORIES ${BAR}) +endif() + +if(VAR) +set_property(TARGET +HELLO +HELLO) +endif() + +if(VAR) +set_property( +TARGET +HELLO +HELLO) +endif() + +add_custom_command(tout # ) +#add_custom_command( +hallo +) + +message(STATUS "Hello" #[[Bracket Comment]] "second") + +add_custom_command() # TODO this will wrongly align to ( due to bracket-comment diff --git a/test/indent4-align-comment-zero-col.cmake.html.ref b/test/indent4-align-comment-zero-col.cmake.html.ref new file mode 100644 index 0000000..b71d823 --- /dev/null +++ b/test/indent4-align-comment-zero-col.cmake.html.ref @@ -0,0 +1,44 @@ + +
+set_property(TARGET foo APPEND PROPERTY
+             INCLUDE_DIRECTORIES ${BAR})
+
+message(STATUS "Hello World")
+
+set_property(TARGET foo APPEND PROPERTY # with comment
+             INCLUDE_DIRECTORIES ${BAR} "()")
+
+if(VAR)
+    set_property(TARGET foo APPEND PROPERTY # with comment
+                 INCLUDE_DIRECTORIES ${BAR})
+
+    message(STATUS "Hello World")
+
+    set_property(TARGET foo APPEND PROPERTY
+# with comment
+                 INCLUDE_DIRECTORIES ${BAR})
+endif()
+
+if(VAR)
+    set_property(TARGET
+                 HELLO
+                 HELLO)
+endif()
+
+if(VAR)
+    set_property(
+        TARGET
+        HELLO
+        HELLO)
+endif()
+
+add_custom_command(tout # )
+#add_custom_command(
+                   hallo
+                   )
+
+message(STATUS "Hello" #[[Bracket Comment]] "second")
+
+        add_custom_command() # TODO this will wrongly align to ( due to bracket-comment
+
+ diff --git a/test/indent4-align-comment-zero-col.vim b/test/indent4-align-comment-zero-col.vim new file mode 100644 index 0000000..d389041 --- /dev/null +++ b/test/indent4-align-comment-zero-col.vim @@ -0,0 +1,2 @@ +let g:cmake_indent_align_command_arguments = 1 +let g:cmake_indent_align_comments_to_first_column = 1 diff --git a/test/indent4-align.cmake b/test/indent4-align.cmake new file mode 120000 index 0000000..aabc365 --- /dev/null +++ b/test/indent4-align.cmake @@ -0,0 +1 @@ +indent4.cmake \ No newline at end of file diff --git a/test/indent4-align.cmake.html.ref b/test/indent4-align.cmake.html.ref new file mode 100644 index 0000000..f4eefee --- /dev/null +++ b/test/indent4-align.cmake.html.ref @@ -0,0 +1,44 @@ + +
+set_property(TARGET foo APPEND PROPERTY
+             INCLUDE_DIRECTORIES ${BAR})
+
+message(STATUS "Hello World")
+
+set_property(TARGET foo APPEND PROPERTY # with comment
+             INCLUDE_DIRECTORIES ${BAR} "()")
+
+if(VAR)
+    set_property(TARGET foo APPEND PROPERTY # with comment
+                 INCLUDE_DIRECTORIES ${BAR})
+
+    message(STATUS "Hello World")
+
+    set_property(TARGET foo APPEND PROPERTY
+                 # with comment
+                 INCLUDE_DIRECTORIES ${BAR})
+endif()
+
+if(VAR)
+    set_property(TARGET
+                 HELLO
+                 HELLO)
+endif()
+
+if(VAR)
+    set_property(
+        TARGET
+        HELLO
+        HELLO)
+endif()
+
+add_custom_command(tout # )
+                   #add_custom_command(
+                   hallo
+                   )
+
+message(STATUS "Hello" #[[Bracket Comment]] "second")
+
+        add_custom_command() # TODO this will wrongly align to ( due to bracket-comment
+
+ diff --git a/test/indent4-align.vim b/test/indent4-align.vim new file mode 100644 index 0000000..04e9c7e --- /dev/null +++ b/test/indent4-align.vim @@ -0,0 +1 @@ +let g:cmake_indent_align_command_arguments = 1 diff --git a/test/indent4-comment-zero-col.cmake b/test/indent4-comment-zero-col.cmake new file mode 120000 index 0000000..aabc365 --- /dev/null +++ b/test/indent4-comment-zero-col.cmake @@ -0,0 +1 @@ +indent4.cmake \ No newline at end of file diff --git a/test/indent4-comment-zero-col.cmake.html.ref b/test/indent4-comment-zero-col.cmake.html.ref new file mode 100644 index 0000000..2870e35 --- /dev/null +++ b/test/indent4-comment-zero-col.cmake.html.ref @@ -0,0 +1,44 @@ + +
+set_property(TARGET foo APPEND PROPERTY
+    INCLUDE_DIRECTORIES ${BAR})
+
+message(STATUS "Hello World")
+
+set_property(TARGET foo APPEND PROPERTY # with comment
+    INCLUDE_DIRECTORIES ${BAR} "()")
+
+if(VAR)
+    set_property(TARGET foo APPEND PROPERTY # with comment
+        INCLUDE_DIRECTORIES ${BAR})
+
+    message(STATUS "Hello World")
+
+    set_property(TARGET foo APPEND PROPERTY
+# with comment
+        INCLUDE_DIRECTORIES ${BAR})
+endif()
+
+if(VAR)
+    set_property(TARGET
+        HELLO
+        HELLO)
+endif()
+
+if(VAR)
+    set_property(
+        TARGET
+        HELLO
+        HELLO)
+endif()
+
+add_custom_command(tout # )
+#add_custom_command(
+    hallo
+    )
+
+message(STATUS "Hello" #[[Bracket Comment]] "second")
+
+    add_custom_command() # TODO this will wrongly align to ( due to bracket-comment
+
+ diff --git a/test/indent4-comment-zero-col.vim b/test/indent4-comment-zero-col.vim new file mode 100644 index 0000000..4cc8878 --- /dev/null +++ b/test/indent4-comment-zero-col.vim @@ -0,0 +1 @@ +let g:cmake_indent_align_comments_to_first_column = 1 diff --git a/test/indent4.cmake b/test/indent4.cmake new file mode 100644 index 0000000..90d47dd --- /dev/null +++ b/test/indent4.cmake @@ -0,0 +1,40 @@ +set_property(TARGET foo APPEND PROPERTY +INCLUDE_DIRECTORIES ${BAR}) + +message(STATUS "Hello World") + +set_property(TARGET foo APPEND PROPERTY # with comment +INCLUDE_DIRECTORIES ${BAR} "()") + +if(VAR) +set_property(TARGET foo APPEND PROPERTY # with comment +INCLUDE_DIRECTORIES ${BAR}) + +message(STATUS "Hello World") + +set_property(TARGET foo APPEND PROPERTY +# with comment +INCLUDE_DIRECTORIES ${BAR}) +endif() + +if(VAR) +set_property(TARGET +HELLO +HELLO) +endif() + +if(VAR) +set_property( +TARGET +HELLO +HELLO) +endif() + +add_custom_command(tout # ) +#add_custom_command( +hallo +) + +message(STATUS "Hello" #[[Bracket Comment]] "second") + +add_custom_command() # TODO this will wrongly align to ( due to bracket-comment diff --git a/test/indent4.cmake.html.ref b/test/indent4.cmake.html.ref new file mode 100644 index 0000000..0422263 --- /dev/null +++ b/test/indent4.cmake.html.ref @@ -0,0 +1,44 @@ + +
+set_property(TARGET foo APPEND PROPERTY
+    INCLUDE_DIRECTORIES ${BAR})
+
+message(STATUS "Hello World")
+
+set_property(TARGET foo APPEND PROPERTY # with comment
+    INCLUDE_DIRECTORIES ${BAR} "()")
+
+if(VAR)
+    set_property(TARGET foo APPEND PROPERTY # with comment
+        INCLUDE_DIRECTORIES ${BAR})
+
+    message(STATUS "Hello World")
+
+    set_property(TARGET foo APPEND PROPERTY
+        # with comment
+        INCLUDE_DIRECTORIES ${BAR})
+endif()
+
+if(VAR)
+    set_property(TARGET
+        HELLO
+        HELLO)
+endif()
+
+if(VAR)
+    set_property(
+        TARGET
+        HELLO
+        HELLO)
+endif()
+
+add_custom_command(tout # )
+    #add_custom_command(
+    hallo
+    )
+
+message(STATUS "Hello" #[[Bracket Comment]] "second")
+
+    add_custom_command() # TODO this will wrongly align to ( due to bracket-comment
+
+ diff --git a/test/run-test.sh b/test/run-test.sh index 35fa48b..596aa0b 100755 --- a/test/run-test.sh +++ b/test/run-test.sh @@ -2,8 +2,22 @@ TMP=$(mktemp) +if [[ $1 == *"indent"* ]] +then + INDENT="norm gg=G" +else + INDENT="norm gg" +fi + +if [ -e "$1.vim" ] +then + OPTION_FILE="source $1.vim" +else + OPTION_FILE="" +fi + # generate html-file with local .vimrc and local syntax highlighting and only that! -vim -u .vimrc -n -es -c TOhtml -c "w! $TMP" -c 'qa!' $1.cmake >/dev/null 2>&1 +vim -u .vimrc -n -es -c "$OPTION_FILE" -c "$INDENT" -c "w! $TMP.cmake" -c TOhtml -c "w! $TMP" -c 'qa!' $1.cmake >/dev/null 2>&1 # extract the body of the html-file sed -i -n -e '//,$p' $TMP