Unwrap project first argument
Project first argument must be stopped from wrapping
project(dummy_pj
VERSION ${PROJECT_VERSION}
DESCRIPTION "Dummy example"
HOMEPAGE_URL "https://example.com/"
LANGUAGES CXX
)
project(
dummy_pj
VERSION ${PROJECT_VERSION}
DESCRIPTION "Dummy example"
HOMEPAGE_URL "https://example.com/"
LANGUAGES CXX
)
Somewhat related to the problem -- other standard functions with specific handling. In all cases I strongly prefer to group heterogeneous keywords to keep indent level of homogeneous lists to the minimum:
### Main
list(APPEND qa_warn
-Wall # MAYBE: -Wno-unused-variable -Wno-unused-but-set-parameter
-Wextra
-Wpedantic
-Wuninitialized
-Wmissing-include-dirs
-Wshadow
-Wundef
-Winvalid-pch
)
### Extra
list(APPEND qa_warn
## Control flow
-Winit-self
-Wswitch-enum -Wswitch-default
-Wformat=2 -Wformat-nonliteral -Wformat-security -Wformat-y2k
## Arithmetic
-Wdouble-promotion
...
list(APPEND qa_c_warn
-Waggregate-return
-Wbad-function-cast
-Wc++-compat
)
But what I see -- discourages me :(
list(
APPEND qa_warn
-Wall # MAYBE: -Wno-unused-variable -Wno-unused-but-set-parameter
-Wextra
-Wpedantic
-Wuninitialized
-Wmissing-include-dirs
-Wshadow
-Wundef
-Winvalid-pch
)
list(
APPEND
qa_warn
## Control flow
-Winit-self
-Wswitch-enum
-Wswitch-default
-Wformat=2
-Wformat-nonliteral
-Wformat-security
-Wformat-y2k
## Arithmetic
-Wdouble-promotion
...
list(APPEND qa_c_warn -Waggregate-return -Wbad-function-cast -Wc++-compat)
I'm sorry that you dislike the design choice here, but a large motivation for using a formatter is to avoid useless style arguments and meaningless preferences. I think it's better to follow standard practice here and take guidance from the established conventions of other languages.
re: project-first argument, this was an intentional choice. A common rule among most language style guides is to prefer breaking at higher semantic level, so that is what is implemented. I will leave this issue open and investigate whether or not this can be tunable with a parameter, but my suspicion is that it is too specific of an exception to the rules to be worth implementing.
re: lists at lower indentation level:
I don't think it makes sense for something at a deeper semantic level to be formatted at a more shallow indentation. In addition to being "unusual" (see e.g. the google style guides for python, java, c++, javascript, kotlin), it would be particularly challenging to implement with the current design of cmake-format.
Thanks for the answer. If it's really challenging to implement this, than it's not worth it. I will simply stick to manual formatting in my own projects as did last 10+ years, despite strong temptation of cmake-format, and only use it in highly-opionated production, where it's easire to force tool on everyone, than to agree on some practice.
Still, I can't agree with comparison of CMake to majorly similar between themselves languages like Python/C++/Java.
Don't be mislead by CMake functions in the form funcname(args...) -- whole CMake is mush-up of features which were new-popular through its 30 years of existance. We have Pascal syntax for definintions, C-like syntax for calls, and... Lisp syntax for arguments lists and work with properties.
Complete mess.
Altogether I claim, that CMake is much nicer formatted using Lisp rules, with some minor quirks -- and my desire to split arguments to primary/secondary and format them differently -- is from Lisp.
REF: http://www.gigamonkeys.com/book/practical-a-simple-database.html
;; Look for treating some positional args "specially"
(defun where (&key title artist rating (ripped nil ripped-p))
#'(lambda (cd)
(and
(if title (equal (getf cd :title) title) t)
(if artist (equal (getf cd :artist) artist) t)
(if rating (equal (getf cd :rating) rating) t)
(if ripped-p (equal (getf cd :ripped) ripped) t))))
E.g. when you see list(APPEND mylist a b c) -- you see function list with argument group APPEND which consumes rest or arguments until next group, and ignore the fact mylist different from rest args.
But when I see the same list(APPEND mylist a b c) -- what I see is actually closure with function name list(APPEND which catches first argument mylist and carries on other arguments -- i.e. list_append_to_mylist(a b c) or list.append_to_mylist(a b c) or list(mylist).append(a b c) -- and therefore I naturally will format accordingly to what I "see" in my mind.
# my formatting
list(APPEND mylist
a
b
c
)
# formatting in my head
list(mylist).append(
a
b
c
)
# How it could look in Lisp-like language
(list-append mylist
a
b
c)
Therefore I don't have contradiction of reducing indent of list -- because such keywords-which-are-not-keywords for me are not counted toward nesting level at all.
After all whole group of list(...) / file(...) ... functions is totally inconsistent and could have bunch of different names, instead of parametrization by keywords (which would make CMake much simpler).
I don't reduce the value of treating argument groups differently. I like them in "staging" context where in single function call you change how you treat arguments multiple times -- e.g.
target_link_libraries(${PROJECT_NAME}
PUBLIC
libour.a
PRIVATE
libmy.a
SYSTEM PRIVATE
libsqlite.a
)
Therefore I'm actually much looking forward for this to be implemented -- to adhere to Lisp-like formatting which don't contradict to everything in my head :)
Edit: added code examples to dilute wall of text
But when I see the same [...] -- what I see is actually closure
I think you are essentially arguing exactly my point: prefer breaking at a higher semantic level. I guess your claim can be summarized as: "The first argument is at the same semantic level as the statement name". I can maybe get behind that.
This is kind of what I had in mind as far as implementation as well: Capture the first argument at the same semantic level as the statement during parsing. That is possibly something that would fit into the current framework and might achieve what you want.
As you said though:
Complete mess.
So it probably makes the most sense on a per-statement level. Some statements capture their first argument at the higher semantic level (probably the more declarative ones), while others do not (the more functional ones).
More or less I agree with your interpretation of my above textwall, beside single point: I don't count first keyword as first real argument. Therefore I actually need to keep two arguments on the same line as function name: list(APPEND mylist \n
I actually need to keep two...
This is a good point. list() is interesting because really the first argument is a discriminator for the different kinds of lists, and the second is the actual name of the list. As you illustrated, it is more like list(mylist).append(...). This illustrates that there might be a different number of "distinguished" arguments depending on statement. set() I think has one distinguished argument.
In both cases the "distinguished" arguments also happen to form the first "positional argument group" by the current parser implementation, which might help make this implementation a bit easier.
side thoughts: maybe it will be a good way to solve the problem and make more customizable formatting its to have some kind of map functions-to-settings:
- project : unwrap: first positional argument
- list: unwrap: first keyword argument group: unwrap first positional argument in parent group
- etc
and propagate this map to configuration file
solve the problem and make more customizable formatting its to have some kind of map functions-to-settings
Such functionality exists already, though the set of configuration options which are supported at a per-command level is very small right now :slightly_smiling_face:. Indeed once the feature itself is implemented, it can be exposed per-command for customization.
Came to give a vote to this feature request. Beyond just unwrapping first argument, I need our cmake files formatted so they are "search friendly" to cleanly reveal as much about a target as possible just by looking just a search results. e.g. I prefer to see add_library(target STATIC all on one line to tell me that target is a static library. In general, expressing the configuration options related to formatting on a per-command basis, and even in terms of semantics of cmake rather than min/max character counts or positional argument counts would, IMHO, be a good thing.
Thank you for your efforts on cmake-format... it has the potential to be as invaluable as clang-format.
Any updates here?
@blackliner I have a branch with a prototype implementation, but that is the only update.
Any chance I could take a look at the branch, maybe contribute?
@blackliner I have a branch with a prototype implementation, but that is the only update.
@cheshirekow can you push that branch?
The more I try to fine-tune formatting, the more I conclude there is nothing we can do w/o explicit rules per each command (and not some "weights"). CMake syntax is simply sooo broken.
Basically config would look like several sections, each with dict over statements names:
- overrides per each concrete command -- name of command as key, name of each known kwarg and how to format it and values after it.
- fallback for cmd glob -- to allow separate special rules for cmake frameworks (around dozen in the wild).
- fallback for rest of known std commands.
- fallback to all other user-defined and unknown commands.
Yep, we must setup each command separately, by fully knowing syntax of each command, there is no other general way around.