Coder Social home page Coder Social logo

cheshirekow / cmake_format Goto Github PK

View Code? Open in Web Editor NEW
952.0 952.0 105.0 1.77 MB

Source code formatter for cmake listfiles.

License: GNU General Public License v3.0

Python 75.18% CMake 17.24% Smarty 0.01% CSS 0.05% Starlark 6.96% JavaScript 0.03% TypeScript 0.53%
cmake devtools formatters

cmake_format's People

Contributors

cheshirekow avatar uebelandre avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cmake_format's Issues

default codec used to read long_description can't decode utf8 in README.rst

Looks like a very promising project! I tried to install using pip install cmake_format, but got this error message:

(.venv) c:\home\simulator\dchipset>pip install --user cmake_format
Collecting cmake_format
  Downloading <local pypi proxy path>/cmake_format-0.2.0.tar.gz
    Complete output from command python setup.py egg_info:
    Traceback (most recent call last):
      File "<string>", line 1, in <module>
      File "C:\Users\jce\AppData\Local\Temp\pip-build-1yx3c08l\cmake-format\setup.py", line 4, in <module>
        long_description = infile.read()
      File "C:\Python36\lib\encodings\cp1252.py", line 23, in decode
        return codecs.charmap_decode(input,self.errors,decoding_table)[0]
    UnicodeDecodeError: 'charmap' codec can't decode byte 0x8d in position 3710: character maps to <undefined>

    ----------------------------------------
Command "python setup.py egg_info" failed with error code 1 in C:\Users\jce\AppData\Local\Temp\pip-build-1yx3c08l\cmake-format\

Maybe it's because the README.rst file is a symbolic link, which is not really supported on Windows.

Support keyword/value alignment

For commands with many keyword arguments, it can be nice to align the values to the keywords like this:

some_command(
  KEYWORD       arg
  MULTI_KEYWORD arg
                arg)

Where values are aligned to indentation levels. Combined with #5, it could look like this:

some_command(
  KEYWORD
    arg
  MULTI_KEYWORD
    arg
    arg)

The MULTI_KEYWORD arguments could also be collapsed to a single line following line length limits.

support stdin as input file

I'm trying to use the formatter with vim-autoformat and I'm not seeing what I'm doing wrong.

Error

Formatter cmake_format has errors: b'Traceback (most recent call last):\n  File "/usr/bin/cmake-format", line 11, in <module>\n    load_entry_point(\'cmake-format==0.3.5\', \'console_scripts\', \'cmake-format\')()\n  File "/usr/li
b/python3.6/site-packages/cmake_format/__main__.py", line 243, in main\n    ("if more than one input file is specified, then formatting must be done"\nAssertionError: if more than one input file is specified, then formatting must
be done in-place or written to stdout\n'

The lines in init.vim

let g:formatdef_cmake_format = '"cmake-format --dangle-parens true --line-ending unix --tab-size 0"'
let g:formatters_cmake = ['cmake_format']

I've tried manually running it from the terminal with the same command and on the same file, and it writes to stdout as expected.


Side-note, is --tab-size 0 correct to use tabs instead of spaces? I didn't see anything mentioning tabs/spaces, only that it controlled the number of spaces used.

Allow use of tabs instead of spaces

Some ways I've seen it done is..

  1. A --use-tabs option that doesn't take input
  2. A --use-tabs option that takes a true or false
  3. Using tabs when a setting like --tab-size is set to 0

I'd say either 1 or 2 are good choices, because then --tab-size can still be used for indent level, just with tabs instead of spaces.

Ref #30 (comment)

Wrapping long arguments

I have noticed some strange behavior when formatting commands with long arguments. When formatting this example CMakeLists.txt, the output I get is:

# Normal wrapping
message(FATAL_ERROR
          "82 character line -----------------------------------------")
# Abnormal wrapping
message(FATAL_ERROR
                    "81 character line ----------------------------------------"
       )
message(
  FATAL_ERROR

    "100 character line ----------------------------------------------------------"
 ) # Closing parenthesis is indented one space!
message(

  "100 character line ----------------------------------------------------------------------"
 ) # Closing parenthesis is indented one space!

I am using version 0.3.2 with the default formatting settings.

No comment after ending ctrl statement

Hello. Found another bug related to comments. Pretty self-explanatory from the lines below.

Input:

if(True) #Comment
  message(STATUS "nanana")
endif() #ending comment

Output:

if(True) # Comment
  message(STATUS "nanana")
endif()

Expected:

if(True) # Comment
  message(STATUS "nanana")
endif() # ending comment

The funny thing is that this works:

self.do_format_test("""\
      if(True) #Comment
        message(STATUS "nanana")
      endif(True) #ending comment
      """, """\
      if(True) # Comment
        message(STATUS "nanana")
      endif(True) # ending comment
      """)

Incorrect Formatting of Function Call With Trailing Comment

Steps to Reproduce

  1. Create a file test.cmake with the following content

    set (answer 
         42 # comment  
        )
  2. Run cmake-format

    cmake-format test.cmake

Expected Result

The command cmake-format prints a nicely formatted version of the given CMake code.

Actual Result

The command produces the following syntactically incorrect code:

set(answer 42 # comment)

.

Indented comments incorrectly appended to preceding line

This may be a different aspect of issues #46 and #47

If a comment is already indented, cmake-format seems to consider it as an end-of-line comment for the previous line and appends it to that previous line.

Given this original input file f0.txt, where the if(A) block is unformatted, and the if(E) block is already correctly formatted:

$ cmake-format --version
0.3.6

$ cat f0.txt 
if(A)
# comment about B
baz(B)
# comment about C
baz(C)
endif()

if(E)
  # comment about F
  baz(F)
  # comment about G
  baz(G)
endif()

Running cmake-format on f0.txt to generate f1.txt, where the if(A) block is correctly formatted, but the if(E) block now has comments incorrectly appended to the previous lines:

$ cmake-format f0.txt | tee f1.txt
if(A)
  # comment about B
  baz(B)
  # comment about C
  baz(C)
endif()

if(E) # comment about F
  baz(F) # comment about G
  baz(G)
endif()

Running cmake-format again with the previous output f1.txt to generate f2.txt, where both if(A) and if(E) blocks have comments incorrectly appended to the previous lines:

$ cmake-format f1.txt | tee f2.txt
if(A) # comment about B
  baz(B) # comment about C
  baz(C)
endif()

if(E) # comment about F
  baz(F) # comment about G
  baz(G)
endif()

$ diff -q f1.txt  f2.txt 
Files f1.txt and f2.txt differ

Possible improvement on formatting "string"

Currently in my CMakeLists.txt there is something like

string(REPLACE "/w44668" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")

After reformatting by cmake-format it becomes

  string(REPLACE "/w44668"
                 ""
                 CMAKE_CXX_FLAGS
                 "${CMAKE_CXX_FLAGS}")

which imo is less readable. Is it possible to change it so it doesn't line break if everything can be fitted to one single line?

cmake-format removes entire while()... endwhile() sections

There seems to be a scary bug when running cmake-format in scripts that use while(...) loops! cmake-format just removes them!

Sample file:

set(A "a")


while(condition)
    fun1()
    fun2()
endwhile()

set(B "b")

If you run cmake-format on the latter we end up with this:

set(A "a")



set(B "b")

Any pointers?

Spaces after control flow commands

I like to have spaces between the command and parentheses for control flow commands (if, elseif, else, endif, while, endwhile, foreach, endforeach, continue, break, return, function, endfunction, macro, endmacro). Having a toggle to preserve that would be nice to have.

End of line corruption when writing bracket comment

I am seeing an issue since the last release when formatting files in-place with bracket comments and Windows line endings such as this CMakeLists.txt. When formatted in-place, the lines of the bracket comment pick up an extra carriage return, but the rest of the file is written correctly. The output seems correct when writing to stdout or using Unix line endings.

Invalid CMake syntax crashes cmake format

If I run cmake-format on something like

cmake_minimum_required(VERSION 3.9)

project(test)

sdfsdfsd

There will be error

While processing CMakeLists.txt
Traceback (most recent call last):
  File "/usr/local/bin/cmake-format", line 11, in <module>
    load_entry_point('cmake-format==0.4.0', 'console_scripts', 'cmake-format')()
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/__main__.py", line 336, in main
    process_file(cfg, infile, outfile, args.dump)
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/__main__.py", line 58, in process_file
    parse_tree = parser.parse(tokens, config.fn_spec)
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/parser.py", line 600, in parse
    return consume_body(tokens, cmdspec)
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/parser.py", line 579, in consume_body
    subtree = consume_statement(tokens, cmdspec)
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/parser.py", line 451, in consume_statement
    if tokens[0].type != lexer.TokenType.LEFT_PAREN:
IndexError: list index out of range

and here is another example

cmake_minimum_required(VERSION 3.9)

project(test
While processing CMakeLists.txt
Traceback (most recent call last):
  File "/usr/local/bin/cmake-format", line 11, in <module>
    load_entry_point('cmake-format==0.4.0', 'console_scripts', 'cmake-format')()
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/__main__.py", line 336, in main
    process_file(cfg, infile, outfile, args.dump)
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/__main__.py", line 58, in process_file
    parse_tree = parser.parse(tokens, config.fn_spec)
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/parser.py", line 600, in parse
    return consume_body(tokens, cmdspec)
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/parser.py", line 579, in consume_body
    subtree = consume_statement(tokens, cmdspec)
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/parser.py", line 464, in consume_statement
    consume_arguments(subtree, tokens, cmdspec.get(fnname, None), [])
  File "/usr/local/lib/python2.7/dist-packages/cmake_format/parser.py", line 428, in consume_arguments
    .format(node.get_location()))
ValueError: Token stream expired while parsing statement arguments starting at 3:8

It would be nice if cmake-format will just simply do nothing and return if the syntax is invalid. On top of that perhaps show an error message.

The main reason I am asking this is because for the sublime cmake format plugin I am maintaining sublime_cmake_format there is a format on save functionality that is intended for speeding up development, but the problem is if the developer is typing something halfway and habitually click ctrl+s it will crash because the syntax is invalid.

If we reference clang-format, even if we type in some gibberish that can't be compiled clang-format will still attempt to format it into something instead of crashing it, so there's no problem running it with format on save.

Treat COMPONENT keyword differently so it doesn't line break

Currently in my CMakeLists.txt there is something like

install(TARGETS ${PROJECT_NAME}
          EXPORT ${CMAKE_PROJECT_NAME}Targets
          ARCHIVE DESTINATION lib COMPONENT install-app
          LIBRARY DESTINATION lib COMPONENT install-app
          RUNTIME DESTINATION bin COMPONENT install-app)

After reformatting by cmake-format it becomes

install(TARGETS ${PROJECT_NAME}
          EXPORT ${CMAKE_PROJECT_NAME}Targets
          ARCHIVE DESTINATION lib
          COMPONENT install-app
          LIBRARY DESTINATION lib
          COMPONENT install-app
          RUNTIME DESTINATION bin
          COMPONENT install-app)

which imo is less readable. Is it possible to treat the COMPONENT keyword differently so it doesn't line break ?

override config file option not up to date in readme

There are some new configs to set in the Configuration section,

dangle_parens = False
bullet_char = u'*'
enum_char = u'.'
line_ending = u'unix'
command_case = u'lower'

but they are not mentioned in the Usage --> Override configfile options section. It should be updated as well. I guess some of them myself like cmake-format --command-case upper CMakeLists.txt and it actually works.

Normally I will do a PR for this but I know PR is generally not accepted in this repo.

Treat NAMESPACE keyword differently so it doesn't line break

Currently in my CMakeLists.txt there is something like

install(EXPORT ${CMAKE_PROJECT_NAME}Targets 
        NAMESPACE jas::
        DESTINATION lib/cmake/${CMAKE_PROJECT_NAME})

After reformatting by cmake-format it becomes

install(EXPORT ${CMAKE_PROJECT_NAME}Targets
        NAMESPACE
        jas::
        DESTINATION
        lib/cmake/${CMAKE_PROJECT_NAME})

which imo is less readable. Is it possible to treat the NAMESPACE and DESTINATION keyword differently so it doesn't line break ?

Add NumPy as Required Package

๐Ÿ‘‹ Hi,

thank you for providing this very useful utility.

The last version of cmake-format (0.4.0) requires the package NumPy. However, setup.py does not list numpy as dependency, as far as I can tell. This causes cmake-format to fail, if you do not install numpy too. For example, after I upgraded to the latest version of cmake-format, the command

cmake-format --version

failed printing the following error message:

Traceback (most recent call last):
  File "/Users/rene/.pyenv/versions/3.7.0/bin/cmake-format", line 11, in <module>
    load_entry_point('cmake-format==0.4.0', 'console_scripts', 'cmake-format')()
  File "/Users/rene/.pyenv/versions/3.7.0/lib/python3.7/site-packages/pkg_resources/__init__.py", line 476, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/Users/rene/.pyenv/versions/3.7.0/lib/python3.7/site-packages/pkg_resources/__init__.py", line 2700, in load_entry_point
    return ep.load()
  File "/Users/rene/.pyenv/versions/3.7.0/lib/python3.7/site-packages/pkg_resources/__init__.py", line 2318, in load
    return self.resolve()
  File "/Users/rene/.pyenv/versions/3.7.0/lib/python3.7/site-packages/pkg_resources/__init__.py", line 2324, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/Users/rene/.pyenv/versions/3.7.0/lib/python3.7/site-packages/cmake_format/__main__.py", line 29, in <module>
    from cmake_format import formatter
  File "/Users/rene/.pyenv/versions/3.7.0/lib/python3.7/site-packages/cmake_format/formatter.py", line 10, in <module>
    import numpy as np
ModuleNotFoundError: No module named 'numpy'

.

Leading comments inside function bodies cause errors

$ clang-format --version
0.3.6

When I run cmake-format on a code block like this:

my_function(
  # This comment causes a parse error
  stuff
)

cmake-format gives me the following error:

$ cmake-format test.cmake
Error while processing test.cmake
While processing test.cmake
Traceback (most recent call last):
  File "/usr/local/bin/cmake-format", line 11, in <module>
    sys.exit(main())
  File "/usr/local/lib/python3.6/site-packages/cmake_format/__main__.py", line 312, in main
    process_file(cfg, infile, outfile)
  File "/usr/local/lib/python3.6/site-packages/cmake_format/__main__.py", line 54, in process_file
    fst = parser.construct_fst(tok_seqs)
  File "/usr/local/lib/python3.6/site-packages/cmake_format/parser.py", line 426, in construct_fst
    block_stack[-1].children.append(Statement(tok_seq))
  File "/usr/local/lib/python3.6/site-packages/cmake_format/parser.py", line 315, in __init__
    assert self.body
AssertionError

dangle_parens is not working as intended.

(using 0.3.6 on Ubuntu 14.04)
While using json, python, or yaml config files or command line option the trailing parentheses of a multi-line source list is placed at the end of the last line no matter what the setting of dangle_parens. I see no effect of this setting(perhaps a regression issue?).

Function arguments can get incorrectly appended to comments

$ clang-format --version
0.3.6

When I run cmake-format on a code block like this:

my_function(
  item1

  # Some comment
  item2
)

cmake-format gives me the following output:

my_function(item1 # Some comment item2)

There should be a line break before item2.

Consider supporting dangling parenthesis

It would be good to have an option for dangling parenthesis.

  • dangling parenthesis = on
some_long_command_name(arg arg arg
  arg
)
  • dangling parenthesis = off
some_long_command_name(arg arg arg
  arg)

This idea comes from this comment in #5.

Parsing fails in multiline command with (escaped) quotes

I'm really looking forward to integrating your project with our workflow. I've been looking for something clang-format-for-cmake-like for years.

Using cmake_format from pypi on python 3.5 in a virtualenv, I've run into a speedbump processing this file:

Error while processing OTHERPATH/dune-xt-common/cmake/modules/DuneXTInstallPythonPackage.cmake
While processing OTHERPATH/dune-xt-common/cmake/modules/DuneXTInstallPythonPackage.cmake
Traceback (most recent call last):
  File "SOMEPATH/python-env/bin/cmake-format", line 11, in <module>
    sys.exit(main())
  File "SOMEPATH/python-env/lib/python3.5/site-packages/cmake_format/__main__.py", line 279, in main
    process_file(cfg, infile, outfile)
  File "SOMEPATH/python-env/lib/python3.5/site-packages/cmake_format/__main__.py", line 41, in process_file
    tok_seqs = parser.digest_tokens(tokens)
  File "SOMEPATH/python-env/lib/python3.5/site-packages/cmake_format/parser.py", line 148, in digest_tokens
    tokens[0].line, tokens[0].col))
AssertionError: Unexpected token of type UNQUOTED_LITERAL at 160:38

I'm only using defaults for config options atm.

Installed packages

Config uses only default values

Hey. I noticed that updated config has only default values.

get_config returns a dict with tab_size = 10
after config_dict.update(vars(args)) it's 2 (default value)

Therefore it's only using default values, no matter what I put in the config file. Same goes for other parameters.

Python 2.7.14

separate-ctrl-name-with-space not producing consistent results

Formatting:

project(sxx)
cmake_minimum_required(VERSION 2.8)

include_directories(include)

set(CMAKE_CXX_FLAGS "-std=c++11 -Werror -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wold-style-cast -Wcast-align -Wunused -Wcast-qual -Woverloaded-virtual -Wconversion -Wformat-security -Wwrite-strings -fdiagnostics-show-option")

if (COVERAGE)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
elseif (ASAN)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O1 -fno-omit-frame-pointer -fsanitize=address -fsanitize=leak")
elseif (UBSAN)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -fsanitize=undefined")
elseif (TSAN)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O1 -fsanitize=thread")
else ()
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif ()

add_executable(${PROJECT_NAME} src/sxx.cpp)

target_link_libraries(${PROJECT_NAME} PocoFoundation)

# packaging

install(TARGETS ${PROJECT_NAME} DESTINATION bin)

find_program(rpmbuild_path "rpmbuild" FALSE)
if (rpmbuild_path) # is rpm based
  message(STATUS "rpmbuild found, enabling RPM for the 'package' target")
  list(APPEND CPACK_GENERATOR RPM)
  if (EXISTS "/etc/redhat-release") # is rhel or centos
    execute_process(COMMAND /bin/bash -c "rpm -E %{?dist} | sed -e 's/\\.//g' | sed 's/centos//g'"
      OUTPUT_VARIABLE DISTRO_AND_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
    set(CPACK_RPM_PACKAGE_REQUIRES "poco-foundation")
  else () # is opensuse
    execute_process(COMMAND /bin/bash -c ". /etc/os-release; printf \"%s%.0f\" \"$ID\" \"$VERSION_ID\""
      OUTPUT_VARIABLE DISTRO_AND_VERSION OUTPUT_STRIP_TRAILING_WHITESPACE)
    set(CPACK_RPM_PACKAGE_REQUIRES "libPocoFoundation60")
  endif ()
endif ()

find_program(dpkg_path "dpkg" FALSE)
if (dpkg_path) # is dpkg based
  message(STATUS "dpkg found, enabling DEB for the 'package' target")
  list(APPEND CPACK_GENERATOR DEB)
  execute_process(COMMAND /bin/bash -c "printf \"$(lsb_release -i | awk '{printf tolower($NF)}')\""
    OUTPUT_VARIABLE DISTRO)

  if (${DISTRO} STREQUAL "debian") # is debian
    execute_process(COMMAND /bin/bash -c "printf \"%.f\" \"$(lsb_release -r | awk '{printf int($NF)}')\""
      OUTPUT_VARIABLE DISTRO_VERSION)
    if (${DISTRO_VERSION} EQUAL 8)
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation9")
    else ()
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation46")
    endif ()
  else () # is ubuntu
    execute_process(COMMAND /bin/bash -c "printf \"$(lsb_release -r | awk '{printf $NF}')\""
      OUTPUT_VARIABLE DISTRO_VERSION)
    if (${DISTRO_VERSION} EQUAL 14.04) 
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation9")
    elseif (${DISTRO_VERSION} EQUAL 16.04)
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation9v5")
    else ()
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation50")
    endif ()
  endif ()

  set(DISTRO_AND_VERSION "${DISTRO}${DISTRO_VERSION}")
endif ()

execute_process(COMMAND /bin/bash -c "uname -m" OUTPUT_VARIABLE CPU_ARCH
  OUTPUT_STRIP_TRAILING_WHITESPACE)

set(CPACK_PACKAGE_CONTACT "[email protected]")
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "sxx is a tool that allows you to easily run shell commands on multiple hosts or transfer files to multiple hosts")
set(CPACK_PACKAGE_URL "https://github.com/ericcurtin/sxx")
set(CPACK_PACKAGE_VERSION_MAJOR 1)
set(CPACK_PACKAGE_VERSION_MINOR 0)
set(CPACK_PACKAGE_VERSION_PATCH 1)
set(CPACK_PACKAGE_VERSION
    "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}-${DISTRO_AND_VERSION}-${CPU_ARCH}")

include(CPack)

# man pages

add_custom_target(doc)

add_custom_command(TARGET doc SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/doc/sxx.pod
  COMMAND podchecker --nowarnings ${CMAKE_CURRENT_SOURCE_DIR}/doc/sxx.pod
  COMMAND pod2man -c 'sxx manual' -q none -r 'sxx ${CPACK_PACKAGE_VERSION}' ${CMAKE_CURRENT_SOURCE_DIR}/doc/sxx.pod ${CMAKE_CURRENT_BINARY_DIR}/sxx.1
  COMMAND gzip -f ${CMAKE_CURRENT_BINARY_DIR}/sxx.1
  OUTPUTS ${CMAKE_CURRENT_BINARY_DIR}/sxx.1.gz)

add_custom_command(TARGET doc SOURCE doc
  DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/sxx.1.gz)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/sxx.1.gz
  DESTINATION ${CMAKE_install_PREFIX}/man/man1)

# ctest

enable_testing()
add_subdirectory(test)

# make format - clang-format

add_custom_target(format COMMAND clang-format -i -style=file ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/test/*.cpp)

with:

cmake-format CMakeLists.txt --separate-ctrl-name-with-space True --line-ending unix --keyword-case upper --command-case lower

produces:

project(sxx)
cmake_minimum_required(VERSION 2.8)

include_directories(include)

set(
  CMAKE_CXX_FLAGS
  "-std=c++11 -Werror -Wall -Wextra -Wshadow -Wnon-virtual-dtor -pedantic -Wold-style-cast -Wcast-align -Wunused -Wcast-qual -Woverloaded-virtual -Wconversion -Wformat-security -Wwrite-strings -fdiagnostics-show-option"
  )

if (COVERAGE)
  set(
    CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
  set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
elseif(ASAN)
  set(
    CMAKE_CXX_FLAGS
    "${CMAKE_CXX_FLAGS} -g -O1 -fno-omit-frame-pointer -fsanitize=address -fsanitize=leak"
    )
elseif(UBSAN)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -fsanitize=undefined")
elseif(TSAN)
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O1 -fsanitize=thread")
else()
  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3")
endif ()

add_executable(${PROJECT_NAME} src/sxx.cpp)

target_link_libraries(${PROJECT_NAME} PocoFoundation)

# packaging

install(TARGETS ${PROJECT_NAME} DESTINATION bin)

find_program(rpmbuild_path "rpmbuild" FALSE)
if (rpmbuild_path) # is rpm based
  message(STATUS "rpmbuild found, enabling RPM for the 'package' target")
  list(APPEND CPACK_GENERATOR RPM)
  if (EXISTS "/etc/redhat-release") # is rhel or centos
    execute_process(
      COMMAND /bin/bash -c
              "rpm -E %{?dist} | sed -e 's/\\.//g' | sed 's/centos//g'"
      OUTPUT_VARIABLE DISTRO_AND_VERSION
      OUTPUT_STRIP_TRAILING_WHITESPACE)
    set(CPACK_RPM_PACKAGE_REQUIRES "poco-foundation")
  else() # is opensuse
    execute_process(
      COMMAND /bin/bash -c
              ". /etc/os-release; printf \"%s%.0f\" \"$ID\" \"$VERSION_ID\""
      OUTPUT_VARIABLE DISTRO_AND_VERSION
      OUTPUT_STRIP_TRAILING_WHITESPACE)
    set(CPACK_RPM_PACKAGE_REQUIRES "libPocoFoundation60")
  endif ()
endif ()

find_program(dpkg_path "dpkg" FALSE)
if (dpkg_path) # is dpkg based
  message(STATUS "dpkg found, enabling DEB for the 'package' target")
  list(APPEND CPACK_GENERATOR DEB)
  execute_process(
    COMMAND /bin/bash -c
            "printf \"$(lsb_release -i | awk '{printf tolower($NF)}')\""
    OUTPUT_VARIABLE DISTRO)

  if (${DISTRO} STREQUAL "debian") # is debian
    execute_process(
      COMMAND /bin/bash -c
              "printf \"%.f\" \"$(lsb_release -r | awk '{printf int($NF)}')\""
      OUTPUT_VARIABLE DISTRO_VERSION)
    if (${DISTRO_VERSION} EQUAL 8)
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation9")
    else()
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation46")
    endif ()
  else() # is ubuntu
    execute_process(COMMAND /bin/bash -c
                            "printf \"$(lsb_release -r | awk '{printf $NF}')\""
                    OUTPUT_VARIABLE DISTRO_VERSION)
    if (${DISTRO_VERSION} EQUAL 14.04)
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation9")
    elseif(${DISTRO_VERSION} EQUAL 16.04)
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation9v5")
    else()
      set(CPACK_DEBIAN_PACKAGE_DEPENDS "libpocofoundation50")
    endif ()
  endif ()

  set(DISTRO_AND_VERSION "${DISTRO}${DISTRO_VERSION}")
endif ()

execute_process(COMMAND /bin/bash -c "uname -m"
                OUTPUT_VARIABLE CPU_ARCH
                OUTPUT_STRIP_TRAILING_WHITESPACE)

set(CPACK_PACKAGE_CONTACT "[email protected]")
set(
  CPACK_PACKAGE_DESCRIPTION_SUMMARY
  "sxx is a tool that allows you to easily run shell commands on multiple hosts or transfer files to multiple hosts"
  )
set(CPACK_PACKAGE_URL "https://github.com/ericcurtin/sxx")
set(CPACK_PACKAGE_VERSION_MAJOR 1)
set(CPACK_PACKAGE_VERSION_MINOR 0)
set(CPACK_PACKAGE_VERSION_PATCH 1)
set(
  CPACK_PACKAGE_VERSION
  "${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}"
  )
set(
  CPACK_PACKAGE_FILE_NAME
  "${PROJECT_NAME}-${CPACK_PACKAGE_VERSION}-${DISTRO_AND_VERSION}-${CPU_ARCH}")

include(CPack)

# man pages

add_custom_target(doc)

add_custom_command(TARGET
                   doc
                   SOURCE
                   ${CMAKE_CURRENT_SOURCE_DIR}/doc/sxx.pod
                   COMMAND podchecker
                           --NOWARNINGS ${CMAKE_CURRENT_SOURCE_DIR}/doc/sxx.pod
                   COMMAND pod2man -C 'sxx manual' -Q none -R
                           'sxx ${CPACK_PACKAGE_VERSION}'
                           ${CMAKE_CURRENT_SOURCE_DIR}/doc/sxx.pod
                           ${CMAKE_CURRENT_BINARY_DIR}/sxx.1
                   COMMAND gzip -F ${CMAKE_CURRENT_BINARY_DIR}/sxx.1 OUTPUTS
                           ${CMAKE_CURRENT_BINARY_DIR}/sxx.1.gz)

add_custom_command(TARGET
                   doc
                   SOURCE
                   doc
                   DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/sxx.1.gz)

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/sxx.1.gz
        DESTINATION ${CMAKE_install_PREFIX}/man/man1)

# ctest

enable_testing()
add_subdirectory(test)

# make format - clang-format

add_custom_target(format
                  COMMAND clang-format -I -STYLE=FILE
                          ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp
                          ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp
                          ${CMAKE_CURRENT_SOURCE_DIR}/test/*.cpp)

I would expect "if (", "elseif (", "else (" and "endif (" consistently.

Add auto-line ending option

originally requested in the discussion for #26

Add support for line_ending=auto which will detect the current line-ending mode of a file and preserve it on output. Possibly implemented by counting the number of \r\n versus [^\r]\n and picking whichever there are more of.

Possible improvement on formatting "file"

Currently in my CMakeLists.txt there is something like

file(WRITE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake
    "include(CMakeFindDependencyMacro)\n"
    "include(\${CMAKE_CURRENT_LIST_DIR}/${CMAKE_PROJECT_NAME}Targets.cmake)\n")

After reformatting by cmake-format it becomes

file(
  WRITE
    ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Config.cmake
    "include(CMakeFindDependencyMacro)\n"
    "include(\${CMAKE_CURRENT_LIST_DIR}/${CMAKE_PROJECT_NAME}Targets.cmake)\n")

which imo is less readable. Is it possible to change it so it doesn't line break twice on the first ( and WRITE?

Positional argument of keyword incorrectly matched as keyword of containing command

$ cat CMakeLists.txt
[...]
INSTALL(TARGETS gridDynMain RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime)
[...]

Expected:

[...]
- INSTALL(TARGETS gridDynMain RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime)
+ install(TARGETS gridDynMain
+         RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT
+         runtime)
[...]

Got:

[...]
- INSTALL(TARGETS gridDynMain RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime)
+ install(TARGETS gridDynMain
+         RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT
+         RUNTIME)
[...]

runtime is not a keyword if it immediately follows COMPONENT (or EXPORT/DESTINATION, but I didn't check to see if it was capitalized in either of those cases)

Incorrect Formatting of Function Call With Interspersed Comments

Steps to Reproduce

  1. Create a file test.cmake with the following content

    cmake_parse_arguments(ARG
                          "SILENT" # optional keywords
                          "" # one value keywords
                          "" # multi value keywords
                          ${ARGN})
  2. Create a configuration file .cmake-format.yaml with the following content

    line_width: 140
  3. Run cmake-format

    cmake-format test.cmake

Expected Result

The command cmake-format prints a nicely formatted version of the given CMake code.

Actual Result

The command produces the following syntactically incorrect code:

cmake_parse_arguments(ARG "SILENT" # optional keywords "" # one value keywords "" # multi value keywords ${ARGN})

.

config file not properly loaded if no extension

The following set of commands don't respect the tab-size:

if(condition)
                   include_diredctories(...)
...
...
endif()

I expect that when I run cmake-format --tab-size 4 that the directives inside the if are going to be indented at 4 spaces as shown below, but instead clang-format overrides it and formats it at 2 spaces anyway.

if(condition)
    include_diredctories(...)
endif()

Any pointers on this?

User to specify string for fencing

As far as I can tell from the documentation there is no way for the user to specify a custom string (e.g., "#####" as a fence string that wont be formatted.

Can we add this sort of feature. Also it would make sense to make this a list of strings e.g.,

fence_string_specifiers = ["~~~", "#####"]

# first fenced  block

# ~~~
...
...
# ~~~

# second fenced  block

# #####
...
...
# #####

This can be handy in cases where the users don't want to polute their CMakeLists.txt filese with cmake-format: off specifiers

Add non-builtin commands

Add non-builtin commands from standard cmake modules, like write_basic_package_version_file. See #54 for example.

allow indent earlier

Currently cmake_format reports it as an error if you indent a line earlier than when it is needed.

For me personally I like to 'overintend' especially with functions and the like that get messy to read otherwise.

It would be great to add an option that would allow this kind of behaviour.

if conditions with many elements can get pretty messy

Combining conditions with the variable (NOT X) and Breaking on () would help a lot

https://aomedia-review.googlesource.com/c/aom/+/57102/3/test/test.cmake

    if (("${var}" MATCHES "_TEST_" AND NOT
         "${var}" MATCHES
         "_DATA_\|_CMAKE_\|INTRA_PRED\|_COMPILED\|_HOSTING\|_PERF_\|CODER_")
        OR (CONFIG_AV1_ENCODER AND CONFIG_ENCODE_PERF_TESTS AND
            "${var}" MATCHES "_ENCODE_PERF_TEST_")
        OR (CONFIG_AV1_DECODER AND CONFIG_DECODE_PERF_TESTS AND
            "${var}" MATCHES "_DECODE_PERF_TEST_")
        OR (CONFIG_AV1_ENCODER AND "${var}" MATCHES "_TEST_ENCODER_")
        OR (CONFIG_AV1_DECODER AND  "${var}" MATCHES "_TEST_DECODER_"))
      list(APPEND aom_test_source_vars ${var})
    endif ()

converted

    if((
       "${var}"
       MATCHES
       "_TEST_"
       AND
       NOT
       "${var}"
       MATCHES
       "_DATA_\|_CMAKE_\|INTRA_PRED\|_COMPILED\|_HOSTING\|_PERF_\|CODER_"
       )
       OR
       (
       CONFIG_AV1_ENCODER
       AND
       CONFIG_ENCODE_PERF_TESTS
       AND
       "${var}"
       MATCHES
       "_ENCODE_PERF_TEST_"
       )
       OR
       (
       CONFIG_AV1_DECODER
       AND
       CONFIG_DECODE_PERF_TESTS
       AND
       "${var}"
       MATCHES
       "_DECODE_PERF_TEST_"
       )
       OR
       (
       CONFIG_AV1_ENCODER
       AND
       "${var}"
       MATCHES
       "_TEST_ENCODER_"
       )
       OR
       (
       CONFIG_AV1_DECODER
       AND
       "${var}"
       MATCHES
       "_TEST_DECODER_"
       ))

https://aomedia-review.googlesource.com/c/aom/+/57102/3/test/test_data_download_worker.cmake
if (NOT AOM_ROOT OR NOT AOM_CONFIG_DIR OR NOT AOM_TEST_FILE OR NOT AOM_TEST_CHECKSUM)

converted to

if(NOT
   AOM_ROOT
   OR
   NOT
   AOM_CONFIG_DIR
   OR
   NOT
   AOM_TEST_FILE
   OR
   NOT
   AOM_TEST_CHECKSUM)

comment on it's own line gets moved to previous line

cmake-format 0.3.6

if(test)
  # comment about test_function
  test_function()
endif()

gets reformatted to:

if(test) # comment about test_function
  test_function()
endif()

Is there any way to keep the comment on it's own line? From the example this seems like it should be possible:

if(foo)
  if(sbar)
    # This comment is in-scope.
    add_library(foo_bar_baz

format elseif like if

Currently in my CMakeLists.txt there is something like

if((CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
   OR CMAKE_COMPILER_IS_GNUCC
   OR CMAKE_COMPILER_IS_GNUCXX)

endif()

After reformatting by cmake-format it keeps it the same, which is great. But for the below

if(MSVC)

elseif((CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
       OR CMAKE_COMPILER_IS_GNUCC
       OR CMAKE_COMPILER_IS_GNUCXX)

endif()

it got reformats to

if(MSVC)

elseif((CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
       OR
       CMAKE_COMPILER_IS_GNUCC
       OR
       CMAKE_COMPILER_IS_GNUCXX)

endif()

which imo is less readable. Is it possible to change it so elseif gets treated similarly like if?

Allow individual configurations to be passed from the command line instead of just from a config file

First of all I want to thank you for making this awesome tool. I also made a sublime plugin based on this which can run cmake-format automatically on save and I hope you will also find it useful.

Would it be possible to allow individual configurations to be passed from the command line instead of just from a config file? Kind of like what clang-format is doing. The reason why it's good to have this functionality is because it allows me to support custom configuration in my sublime plugin so no .cmake-format or cmake-format.yaml is needed as long as you are using sublime.

Use same LICENSE as CMake?

If it's possible, can you make LICENSE permissive? (MIT/BSD/Apache, etc?)

Use the same LICENSE as CMake? https://cmake.org/licensing/

GPL causes conflicts with formatting plugins (since they are permissively licensed). GPL is only forward compatible with OSI licenses, not backward compatible. There are also tricky clauses in GPL that can become non-issues when a simpler license is used.

Consider option to not reflow initial comment block

Our CMake list files start with a copyright block. It would be desirable to have an option that prevents reflow of the first comment block on a file. I can use fences (# ~~~) to work around this, but that seems unnecessarily ugly, maybe?

Thanks for the great tool btw.

Support bracket/block comments

Very cool project you've created!

Many of my CMake scripts begin with a multi-line comment of the form #[[comment]]. I get the following error when attempting to format this example CMakeLists.txt:

Error while processing CMakeLists.txt
While processing CMakeLists.txt
Traceback (most recent call last):
File "C:\Python27\Scripts\cmake-format-script.py", line 9, in
load_entry_point('cmake-format==0.3.0', 'console_scripts', 'cmake-format')()
File "c:\python27\lib\site-packages\cmake_format_main_.py", line 211, in main
process_file(config, infile, outfile)
File "c:\python27\lib\site-packages\cmake_format_main_.py", line 35, in process_file
tok_seqs = parser.digest_tokens(tokens)
File "c:\python27\lib\site-packages\cmake_format\parser.py", line 145, in digest_tokens
tokens[0].line, tokens[0].col))
AssertionError: Unexpected token of type UNQUOTED_LITERAL at 2:0

Would you consider adding support for this style of comment?

AssertionError when using on CMakeLists.txt

$ cmake-format CMakeLists.txt
Error while processing CMakeLists.txt
While processing CMakeLists.txt
Traceback (most recent call last):
  File "/Users/$USER/miniconda3/envs/python27/bin/cmake-format", line 11, in <module>
    load_entry_point('cmake-format', 'console_scripts', 'cmake-format')()
  File "/Users/$USER/GitRepos/cmake_format/cmake_format/__main__.py", line 111, in main
    process_file(config, infile, outfile)
  File "/Users/$USER/GitRepos/cmake_format/cmake_format/__main__.py", line 26, in process_file
    fst = parser.construct_fst(tok_seqs)
  File "/Users/$USER/GitRepos/cmake_format/cmake_format/parser.py", line 365, in construct_fst
    assert block_stack and block_stack[-1].block_type == IF_BLOCK
AssertionError

Possible improvement on formatting export

Currently in my CMakeLists.txt there is something like

export(TARGETS ${PROJECT_NAME}
       APPEND FILE ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Targets.cmake)

After reformatting by cmake-format it becomes

export(TARGETS
       ${PROJECT_NAME}
       APPEND
       FILE
       ${CMAKE_BINARY_DIR}/${CMAKE_PROJECT_NAME}Targets.cmake)

which imo is less readable. Is it possible to change it so it doesn't line break on TARGETS and APPEND FILE?

Global option to not format comments?

Can it be possible to turn off comment formatting globally? I'd rather not wrap license headers and commented-out code with # ~~~ or # cmake-format: on/off. cmake-format is also inferring bulleted lists where we didn't mean them.
(These are things we need to fix, but it makes running cmake-format incrementally a little harder).

...

This:

diff --git a/cmake_format/formatter.py b/cmake_format/formatter.py
index 4a80f17..4de3a96 100644
--- a/cmake_format/formatter.py
+++ b/cmake_format/formatter.py
@@ -72,8 +72,7 @@ def format_comment_lines(node, config, line_width):
       inlines.append(token.spelling.strip().lstrip('#'))

   items = markup.parse(inlines)
-  markup_lines = markup.format_items(config, max(10, line_width - 2), items)
-  return ["#" + (" " * len(line[:1])) + line for line in markup_lines]
+  return ["#" + " " + line for item in items for line in item.lines]


 def normalize_line_endings(instr):

works well enough for now

Cannot invoke cmake-format with Python 3 on Windows

When I try to invoke cmake-format with Python 3 from a command prompt in Windows, I get the following error.

c:\>cmake-format
Traceback (most recent call last):
  File "C:\Python36\Scripts\cmake-format-script.py", line 11, in <module>
    load_entry_point('cmake-format==0.3.2', 'console_scripts', 'cmake-format')()
  File "c:\python36\lib\site-packages\cmake_format\__main__.py", line 184, in main
    for key, value in configuration.Configuration().as_dict().iteritems():
AttributeError: 'dict' object has no attribute 'iteritems'

In Python 3 the iteritems does not exist for dict. Use items instead.

Corruption upon trailing whitespace

Thanks for this cool program! I've been looking for something like this for CMake for a while.

I noticed that trailing whitespace seems to confuse the program.

Input CMakeLists.txt:

set(FOO "f") 
set(BAR "b")

Note the trailing whitespace on the first line:
screen shot 2018-02-18 at 09 14 40

Test:

$ python2.7 -m cmake_format CMakeLists.txt

Expected:

set(FOO "f")
set(BAR "b")

Got:

set(FOO "f")set(BAR "b")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.