Don't Assume My Tab Width — DAM'TW (Damn It)
Ideas for a Source Code Formatter
This style is intended to be used for braced languages.
This describes a loose formatter meaning if all rules are followed the file is considered complying but many formats of the same code may exist.
File
- UTF-8
- Trailing newline
- Unix style line endings
Proverbs
- The tab width can be freely chosen without messing up the formatting
- The least configuration necessary.
- Guide the readers eye with the semantics of the language and the program
- It should be clearly visible where something ends
- and which parts form a unit
- Consistent
- Concise
- Let short things be short, longer things may grow by a constant amount
- Tabular layouts are great
- Lets help humans by machines that can create them easily
- Easy to follow by machines and humans.
- Small diffs
Caveats
- You may need to loosen the rules for individual languages.
- Follow the naming convention of a given language!
Rules
- Use tabs for indentation and spaces for alignment.
- Every line starts indented. This implies no initial alignment.
- Use at most one space except for alignment.
- No limit on line length (but make sure long lines are rare, follow an exponential distribution)
- Paren-Space-Brace
) { - Use vertical alignment.
- Prefer line comments.
- Either put a list all on a single line or elements indented on lines between unindented opener and closer lines.
- Use a trailing comma when followed by a new line.
- Keep nesting low.
- Allow the use of zero to two blank lines between elements.
- Use zero to one space to communicate operator precedence when multiple operators are involved.
- Add parentheses if more than two levels of operators are involved.
- Always put spaces around keywords and blocks.
- Don’t use spaces around call opener.
- No trailing white space.
Examples
struct ComplicatedReturnType {
some *Type;
another Filed;
third Entry;
};
static int the_func() { return 42; } // single line function definition allowed
// expl_func2 is an example of the function naming and documentation
// convention. Doc comments should be put on the same line or the line
// above.
char *expl_func2(int convert) {
char *buf = (char *)calloc(30); // cast only for demonstration
sprintf(buf, "%d", convert);
if (buf[0] == '\0') {
free(buf);
return NULL;
}
else {
return buf; // guard case does not apply (last statement)
}
}
static int const MinLenForFibNumbers = 8; // (unit local) constant
char explGlobalBuffer[200];
struct ComplicatedReturnType * // broken return type
expl_common_function(const int *inp_array, size_t len) {
struct ComplicatedReturnType *ret_value =
calloc(sizeof(struct ComplicatedReturnType));
const double fibonacci_numbers[] = {
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 79 // break of large array literal
};
#define ARRAY_LEN(array) (sizeof(array) / sizeof(array[0]))
if (
// preceeding logical operator, notice the break of this conditional
ARRAY_LEN(fibonacci_numbers) < MinLenForFibNumbers ||
fibonacci_numbers[0] != 0.0
) {
// guard clause but if condition is too comlex so this has curlies
return NULL;
}
#undef ARRAY_LEN
for (size_t i = 0; i < min_len; ++i) {
printf("%d fibonacci number: %f", i, fibonacci_numbers[i]);
}
return expl_function_that_takes_many_parameters(
ret_value,
true,
false,
fibonacci_numbers[3] // C does not allow a trailing comma
);
}
char *expl_function_declaration(
char const **name,
size_t length,
bool condition
);
auto my_var =
a_long().
method().
chain().
looks.
like(this);
auto other_var = 5*a + b; // semantic indicating whitespace
Tags:
Categories: