Man style
From LSWiki
(diff) ←Older revision | Current revision | Newer revision→ (diff)
style - specification for code style
Synopsis
This document outlines how code should be written for Lost Souls. These specifications are made in the interest of promoting readability by creating reasonable common conventions, so that developers do not need to adapt to an unbounded number of disparate visual organizational styles in order to be able to maintain code. You may feel that your coding style should be your personal choice alone; as the people who will _have_ to maintain your code, we do not agree with that viewpoint.
This document is divided into two sections: requirements and recommendations. Doing what's described in the requirements section is mandatory; doing what's described in the recommendations section is optional and strongly encouraged.
Examples are provided only of the _right_ way to do things, not any _wrong_ ways. This is so you don't visually absorb both ways and then forget which is which. It does not mean that what you may feel are minor, pleasing variations from the right way are okay. In all likelihood, your minor, pleasing variation is exactly what the rule was written to prevent. Do it as shown.
Requirements
Variable names and function names are all-lowercase with underscores separating words. See also 'man function_names'.
[ Example : ] int val, other_val, yet_another_val; [ Example : ] void do_something(int how_much);
Macro names are words-capitalized with underscores separating words. (You will sometimes encounter macros that are all-uppercase; these are macros from driver system header files, and part of the benefit of the macro name pattern mandated for lib and content is that it clearly distinguishes these classes of macro.)
[ Example : ] #define Foo_Value 27 #define Pi 3.14159
Put spaces on either side of assignments, mathematical operators, comparison operators, logical operators, and mapping : elements.
[ Example : ] val = foo * bar / (baz - 3); [ Example : ] val = foo > bar ? 1 : 2; [ Example : ] val = obj->query_value() || 25; [ Example : ] map = ([ "foo" : "bar" ]);
Put spaces following commas.
[ Example : ] list = ({ 1, 2, 3 });
Put spaces following the opening elements of mapping and array literals, and before their closing elements. This is optional where they are adjacent to another array-literal or mapping-literal boundary, or a closure #' element.
[ Example : ] map = ([ "foo" : "bar" ]); [ Example : ] list = ({ 1, 2, 3 }); [ Example : ] list = ({ ({ 1, 2, 3 }), ([ "foo" : ({ "bar" }) ]) }) [ Example : ] list = ({({ 1, 2, 3 }), ([ "foo" : ({ "bar" })])}) [ Example : ] func = lambda(({ 'x }), ({#'environment, 'x })))
Do not put spaces adjacent to the -> indirection operator.
[ Example : ] obj->perform_task("foo");
Do not put spaces between auto-increment and auto-decrement operators and the variables they operate on.
[ Example : ] i++ [ Example : ] --j
Do not put spaces between the name of a function and the parenthesis opening its argument list, either in declarations or calls.
[ Example : ] val = foo(this_object()); [ Example : ] obj->bar(({ 1, 2, 3 }));
Do not put spaces between the name of an array or mapping and its indexing brackets, or around the index expression.
[ Example : ] val = arr[1]; [ Example : ] val = map["foo"];
Put spaces around the .. in array slice indexing when any of the indexes are more complex expressions than a single constant or variable. With simpler indices, this is optional.
[ Example : ] list = arr[1 .. loc - 3]; [ Example : ] list = arr[1 .. <2]; [ Example : ] list = arr[1..<2];
Do not put spaces adjacent to the :: inheritance qualifier.
[ Example : ] Base::create();
Do not put spaces between the * in array variable declarations and the variable name.
[ Example : ] int *vals, *extra;
Declare 'type' and '*type' variables as if you were declaring entirely separate types.
[ Example : ] int i, j, foo, bar; int *vals, *extra;
Put spaces following semicolons in for() statements.
[ Example : ] for(i = 0; i < 7; i++) { obj->do_something(); obj->do_something_else(); }
When writing array, mapping, and inline closure literals in multi-line form, indent the contents at one level deeper than the surrounding code. When writing multi-line array and mapping literals, write one element per line. Prefer to vertically align the colons of mapping literals. Prefer to write such literals in multi-line form when it is feasible and aids clarity. (Note: it is _not_ recommended to write message() arrays in this form.)
[ Example : ] int array list = ({ -127, 52, 32768, });
[ Example : ] mapping numbers = ([ "one" : 1, "two" : 2, "twenty" : 20, ]));
[ Example : ] closure func = (: int foo = $1->query_some_quantity(); if(foo > 27) return "bing"; else if(foo < 1) return "bong"; :);
[ Example : ] who->message(({ 0, ({ "spin", 0 }), "rapidly" }));
Place closing braces at the same indentation level as the construct whose controlled block they close. Opening braces must be the last thing on the line on which they appear, and closing braces must appear on a line by themselves.
[ Example : ] for(i = 0; i < 7; i++) { obj->do_something(); obj->do_something_else(); }
In switch() statements, indent case labels at the same level as the switch statement. Indent case contents at one level deeper than the switch.
[ Example : ] switch(random(7)) { case 0 : do_something(); break; case 2 .. 4 : do_something_else(); break; case 5 .. 6 : do_yet_another_thing(); break; }
In switch() statements using fallthrough from one case to another, use a "// fallthrough" comment to document that the fallthrough is intentional.
[ Example : ] switch(sizeof(list)) { case 0 : return 0; default : list = sort_array(list, #'>); // fallthrough case 1 : return list[0]; }
Semicolons which terminate statements must also terminate lines. (That is, do not put more than one semicolon-terminated statement on the same line.)
[ Example : ] foo = bar(); baz = qxx();
Separate functions with one line of vertical whitespace (a blank line). Do not separate code within a function with vertical whitespace. This allows each function to consist of one logical paragraph.
[ Example : ] int multiply(int a, b) { int out = a * b; return out; } int divide(int a, b) { int out = a / b; return out; }
Use one of the following indentation styles:
- Indent function and variable declarations flush left, and indent one tab
per level. This style is preferable because it essentially allows anyone to view your code with the indentation style they prefer by setting their tab stop interval.
[ Example : ] void do_stuff(object obj) { for(int i = 0; i < 7; i++) { obj->do_something(); obj->do_something_else(); } }
- Indent function and variable declarations flush left, and indent 4 spaces
per level. Do not convert spaces to tabs.
[ Example : ] void do_stuff(object obj) { for(int i = 0; i < 7; i++) { obj->do_something(); obj->do_something_else(); } }
Do not use tabs for any purpose other than code indentation.
Recommendations
Place opening braces on the same line as the construct whose controlled block they open.
[ Example : ] for(int i = 0; i < 7; i++) { obj->do_something(); obj->do_something_else(); }
Indent line continuations at one level deeper than the start of the line. When considering whether to use a line continuation, take into account that not everyone has the same tab stop and terminal width settings as you, and it may be better to simply allow the line to run on. Be further aware that many automated, script-based code revisions, as we are wont to use from time to time, deal with single lines easily, but line continuations tend to break them.
[ Example : ] foo = obj->do_some_complex_thing(val * 32 / 15, obj->query_something() * 27);
Do not put spaces between loop control constructs and the parenthesis opening their condition specifications.
[ Example : ] if(foo) bar(); else baz(); [ Example : ] foreach(object obj : query_relevant_objects()) { obj->do_something(); obj->do_something_else(); }
If any element of a compound if-else statement requires { } block delimiters, use them for every element of the statement.
[ Example : ] if(foo) { do_something(); do_something_else(); } else { do_nothing(); }
Treat 'else if' cases as if 'else if' were a single keyword.
[ Example : ] if(foo) { do_something(); } else if(bar) { do_something_else(); }
Put spaces between parentheses and array/mapping literal boundaries if you feel it significantly improves readability.
[ Example : ] obj->foo( ({ "foo", 2 }), ({ "bar", 3 }), ({ "baz", 4 }) );
Make for() loop control declarations fit onto one line whenever feasible. If it's not feasible, consider using shorter variable names so it becomes feasible. Everyone knows that i and j are counter variables; trust us.
[ Example : ] for(int i = 0; i < 7; i++) { obj->do_something(); obj->do_something_else(); }
Use reasonably clear variable names which indicate something useful about the function of the variable, but it's not necessary to extensively document the usage of the variable in its name. Feel free to use comments for that.
[ Example : ] int value, highest, lowest;
Feel free to use the declare-and-use style of variable declaration rather than declaring all variables separate from their use. Declare-and-use makes code clearer by providing immediate documentation of what the variable is for, makes maintenance easier, and generally looks good. However, do not get so attached to it that you start going to silly lengths in order to use declare-and-use style when it's not appropriate.
[ Example : ] object who = this_player(); object array inv = all_inventory(who); mixed what; if(sizeof(inv) > 1) what = ({ 'j', inv }); else what = inv; who->message(({ 0, ({ "have", 0 }), what }));