cmake_format icon indicating copy to clipboard operation
cmake_format copied to clipboard

Need more empty lines

Open amerlyq opened this issue 5 years ago • 7 comments

I often separate blocks of CMake statements by two and sometimes three empty lines, simulating something akin sections and subsection -- it greatly enhances readability. Especially so, when you mix cmake with markup comments. So I would appreciate option to not touch multiple empty lines when they are less than N. Or (better?) don't touch empty lines < N when next line is comment.

# EXPL:(-std=c++20): enable instead of -std=gnu++20
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)


# EXPL:(-std=c11): enable instead of -std=gnu11
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)


# EXPL:(compile_commands.json): generate cmdline database in build directory
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

amerlyq avatar Oct 26 '19 03:10 amerlyq

This is quite possible.

cheshirekow avatar Oct 27 '19 13:10 cheshirekow

I was in the process of implementing this and it seems kind of silly to add a configuration option for such a specific case. I also don't like introducing any feature where the input formatting can influence the output formatting.

If you want additional newlines to separate things, why not just add a blank line comment:

# EXPL:(-std=c++20): enable instead of -std=gnu++20
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

#
# EXPL:(-std=c11): enable instead of -std=gnu11
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

#
# EXPL:(compile_commands.json): generate cmdline database in build directory
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

Seems like it gives you the flexibility of deciding how many lines to use wherever you think additional visual separation is appropriate beyond the "usual". Alternatively would you utilize a "number of lines before statement prefix-comment" as a consistent way to achieve additional visual separation in the specific case of a comment before a statement?

cheshirekow avatar Jan 23 '20 20:01 cheshirekow

Blindingly simple but tempting solution. OK, in a couple of days I will reformat one of my codebases by this novel suggestion and will share personal experience of staring into the abyss :)

Edit:

Yes, it was actually good enough. Currently spotted cons:

  • It become less clean and aerial, when looking at code, but I hope it's a problem of habit.
#
# EXPL:(-std=c11): enable instead of -std=gnu11
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

#
#
# EXPL:(compile_commands.json): generate cmdline database in build directory
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
  • Somebody will start making these comments symmetrical like in GNU configs, and due to increased distance between code and comments they will become less standing out and may even become totally dangling and unrelated. It's again a matter of perception and discipline, but look here and try to see like comments and code started feeling like two separated entities instead of unified one:
#
# EXPL:(-std=c11): enable instead of -std=gnu11
#
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_STANDARD 11)
set(CMAKE_C_STANDARD_REQUIRED ON)

#
#
# EXPL:(compile_commands.json): generate cmdline database in build directory
#
#
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)

Nevertheless, this approach also has some procs:

  • Logically, spaces belong to the section below it, not above -- i.e. spaces are separators before starting new section, not trailing space after ending section. Therefore rearranging paragraphs in vim by dap become easier -- they are no more moving trailing spaces with them.
  • Sections themselves become more homogeneous, having only single space between them

Overall I think, with such solution there is no need to keep this issue open for now -- at least until new pain arise.

amerlyq avatar Jan 23 '20 22:01 amerlyq

OK, I was too hasty, my bad. Actually, there is still the case, which comments can't solve gracefully:

find_program(mkrc_exe NAMES elf-resource-make)

#
function(make_resource_from_each)
...
endfunction()

#
function(make_resource nm src)

I thinks, it's worth doing the same way as PEP8 in python -- two lines before any global function definition, and one line between everything else. Because that standalone # is as ugly as hell.

amerlyq avatar Jan 26 '20 13:01 amerlyq

Personally I don't particularly mind single hash though I don't generally write uncommented function definitions. Regardless, for this feature:

Would the desired behavior be:

Insert n spaces before a function or macro definition

or

Insert n spaces before a statement which opens scope

In other words, same rule for if() and foreach(), etc.?

Also, given your experimentation, would you still like either of these features or do you think it would be covered by the above?:

  1. Insert n spaces before a comment preceeding a statement
  2. Preserve up to n spaces before a comment preceeding a statement

cheshirekow avatar Jan 31 '20 01:01 cheshirekow

Insert n spaces before a statement which opens scope In other words, same rule for if() and foreach(), etc.?

If they are inside function/macro -- keep no more then one space before if/foreach or their preceding comment. Otherwise functions will look visually too much teared up.

However, if if() / foreach() are outside function/macro, it... depends:

  1. small if() blocks tend to have single empty line between them.
  2. large blocks are varying depending on logical closeness of them.
  3. nested if() are generally mix of above rules inside of them, but outermost always has >= 2 spaces.

Given that it's often hard to make reasonable name to standalone block of if/foreach -- it's often no less hard to add useful comment to them. Therefore we again have a problem of wild single #.

Insert n spaces before a comment preceeding a statement Preserve up to n spaces before a comment preceeding a statement

I assume for if/foreach statements preserving is more useful than inserting, and for function/macro vice versa inserting is more recommended than preserving.

amerlyq avatar Jan 31 '20 02:01 amerlyq

it seems kind of silly to add a configuration option for such a specific case

I don't see how it is silly or this case being too specific. In fact, I'd be very glad to see configuration for blank lines, because blank line of 1 is not enough.

There is potential for the following settings:

max_blank_lines_code

Max number of blank lines between separate statements. Function/macro definition (from function() to endfunction()) is treated as one statement (controlled further by max_blank_lines_function). Everything else is treated as separate statement. Control statement such as if, foreach has its subparts (if(), endif()) treated as separate statements. Comments are treated as separate statements with the exception of comment with 0 blank lines until next statement below. In this case it is treated as one piece with that statement. This is necessary to omit introduction of <max|min>_blank_lines_before_* and <max|min>_blank_lines_after_* options that would manage blank lines before and after terms. Introduction of such options would be necessary in the use-case when comment is documentation for function and therefore should be expected to not have any blank lines between itself and function definition (which is treated as a single statement according to the rule above). Default to 2.

When set to 2, this piece should not be reformatted at blank line level:

a(b)

c()


# foo
function(d)
k()
endfunction()


# bar


macro(e)
endmacro()

max_blank_lines_statement

Max number of blank lines inside a single statement. Default to 0.

When set to 1, this piece should not be reformatted at blank line level:

foo(tgt
    source1

    # foo
    source2)

max_blank_lines_function

Max number of blank lines inside function/macro definition. Default to 1.

When set to 2, this piece should not be reformatted at blank line level:

function(foo)
a()


# bar
b()
endfunction()

OP would set max_blank_lines_code=3 for minimal repro of his example.

There is also a point to introduce min_blank_lines_* settings, but that is out-of-scope here. I can think of at least a few rules: for function/macro definition targeting another function/macro definition (e.g. set min spacing between functions to 2 lines, 1 by default), control statements targeting control statements (e.g. set min spacing between if's/foreach's to 1 line, 0 by default).

ghost avatar Oct 27 '20 23:10 ghost