Software /
code /
prosody
Comparison
doc/coding_style.md @ 9939:3a7f822f6edd
doc/coding_style: apply consistent semi-colon usage
Make all "good" statements in the coding style document use consistent
statement-separator semi-colon
author | marc0s <marcos@tenak.net> |
---|---|
date | Sat, 30 Mar 2019 18:44:34 +0100 |
parent | 9900:f2104b36f673 |
child | 11000:d9aae4734f38 |
comparison
equal
deleted
inserted
replaced
9938:4e8ba156738b | 9939:3a7f822f6edd |
---|---|
11 | 11 |
12 ```lua | 12 ```lua |
13 for i, pkg in ipairs(packages) do | 13 for i, pkg in ipairs(packages) do |
14 for name, version in pairs(pkg) do | 14 for name, version in pairs(pkg) do |
15 if name == searched then | 15 if name == searched then |
16 print(version) | 16 print(version); |
17 end | 17 end |
18 end | 18 end |
19 end | 19 end |
20 ``` | 20 ``` |
21 | 21 |
67 | 67 |
68 * Use `_` for ignored variables (e.g. in for loops:) | 68 * Use `_` for ignored variables (e.g. in for loops:) |
69 | 69 |
70 ```lua | 70 ```lua |
71 for _, item in ipairs(items) do | 71 for _, item in ipairs(items) do |
72 do_something_with_item(item) | 72 do_something_with_item(item); |
73 end | 73 end |
74 ``` | 74 ``` |
75 | 75 |
76 * Generally all identifiers (variables and function names) should use `snake_case`, | 76 * Generally all identifiers (variables and function names) should use `snake_case`, |
77 i.e. lowercase words joined by `_`. | 77 i.e. lowercase words joined by `_`. |
83 local c = function() | 83 local c = function() |
84 -- ...stuff... | 84 -- ...stuff... |
85 end | 85 end |
86 | 86 |
87 -- good | 87 -- good |
88 local this_is_my_object = {} | 88 local this_is_my_object = {}; |
89 | 89 |
90 local function do_that_thing() | 90 local function do_that_thing() |
91 -- ...stuff... | 91 -- ...stuff... |
92 end | 92 end |
93 ``` | 93 ``` |
111 return alignment < 100 | 111 return alignment < 100 |
112 end | 112 end |
113 | 113 |
114 -- good | 114 -- good |
115 local function is_evil(alignment) | 115 local function is_evil(alignment) |
116 return alignment < 100 | 116 return alignment < 100; |
117 end | 117 end |
118 ``` | 118 ``` |
119 | 119 |
120 * `UPPER_CASE` is to be used sparingly, with "constants" only. | 120 * `UPPER_CASE` is to be used sparingly, with "constants" only. |
121 | 121 |
128 ## Tables | 128 ## Tables |
129 | 129 |
130 * When creating a table, prefer populating its fields all at once, if possible: | 130 * When creating a table, prefer populating its fields all at once, if possible: |
131 | 131 |
132 ```lua | 132 ```lua |
133 local player = { name = "Jack", class = "Rogue" } | 133 local player = { name = "Jack", class = "Rogue" }; |
134 ``` | 134 ``` |
135 | 135 |
136 * Items should be separated by commas. If there are many items, put each | 136 * Items should be separated by commas. If there are many items, put each |
137 key/value on a separate line and use a semi-colon after each item (including | 137 key/value on a separate line and use a semi-colon after each item (including |
138 the last one): | 138 the last one): |
143 class = "Rogue"; | 143 class = "Rogue"; |
144 } | 144 } |
145 ``` | 145 ``` |
146 | 146 |
147 > **Rationale:** This makes the structure of your tables more evident at a glance. | 147 > **Rationale:** This makes the structure of your tables more evident at a glance. |
148 Trailing commas make it quicker to add new fields and produces shorter diffs. | 148 Trailing semi-colons make it quicker to add new fields and produces shorter diffs. |
149 | 149 |
150 * Use plain `key` syntax whenever possible, use `["key"]` syntax when using names | 150 * Use plain `key` syntax whenever possible, use `["key"]` syntax when using names |
151 that can't be represented as identifiers and avoid mixing representations in | 151 that can't be represented as identifiers and avoid mixing representations in |
152 a declaration: | 152 a declaration: |
153 | 153 |
154 ```lua | 154 ```lua |
155 local mytable = { | 155 local mytable = { |
156 ["1394-E"] = val1, | 156 ["1394-E"] = val1; |
157 ["UTF-8"] = val2, | 157 ["UTF-8"] = val2; |
158 ["and"] = val2, | 158 ["and"] = val2; |
159 } | 159 } |
160 ``` | 160 ``` |
161 | 161 |
162 ## Strings | 162 ## Strings |
163 | 163 |
164 * Use `"double quotes"` for strings; use `'single quotes'` when writing strings | 164 * Use `"double quotes"` for strings; use `'single quotes'` when writing strings |
165 that contain double quotes. | 165 that contain double quotes. |
166 | 166 |
167 ```lua | 167 ```lua |
168 local name = "Prosody" | 168 local name = "Prosody"; |
169 local sentence = 'The name of the program is "Prosody"' | 169 local sentence = 'The name of the program is "Prosody"'; |
170 ``` | 170 ``` |
171 | 171 |
172 > **Rationale:** Double quotes are used as string delimiters in a larger number of | 172 > **Rationale:** Double quotes are used as string delimiters in a larger number of |
173 programming languages. Single quotes are useful for avoiding escaping when | 173 programming languages. Single quotes are useful for avoiding escaping when |
174 using double quotes in literals. | 174 using double quotes in literals. |
216 end | 216 end |
217 | 217 |
218 -- good | 218 -- good |
219 local function is_good_name(name, options, args) | 219 local function is_good_name(name, options, args) |
220 if #name < 3 or #name > 30 then | 220 if #name < 3 or #name > 30 then |
221 return false | 221 return false; |
222 end | 222 end |
223 | 223 |
224 -- ...stuff... | 224 -- ...stuff... |
225 | 225 |
226 return true | 226 return true; |
227 end | 227 end |
228 ``` | 228 ``` |
229 | 229 |
230 ## Function calls | 230 ## Function calls |
231 | 231 |
234 | 234 |
235 ```lua | 235 ```lua |
236 -- bad | 236 -- bad |
237 local data = get_data"KRP"..tostring(area_number) | 237 local data = get_data"KRP"..tostring(area_number) |
238 -- good | 238 -- good |
239 local data = get_data("KRP"..tostring(area_number)) | 239 local data = get_data("KRP"..tostring(area_number)); |
240 local data = get_data("KRP")..tostring(area_number) | 240 local data = get_data("KRP")..tostring(area_number); |
241 ``` | 241 ``` |
242 | 242 |
243 > **Rationale:** It is not obvious at a glace what the precedence rules are | 243 > **Rationale:** It is not obvious at a glace what the precedence rules are |
244 when omitting the parentheses in a function call. Can you quickly tell which | 244 when omitting the parentheses in a function call. Can you quickly tell which |
245 of the two "good" examples in equivalent to the "bad" one? (It's the second | 245 of the two "good" examples in equivalent to the "bad" one? (It's the second |
249 argument on a single line. You may do so for table arguments that span several | 249 argument on a single line. You may do so for table arguments that span several |
250 lines. | 250 lines. |
251 | 251 |
252 ```lua | 252 ```lua |
253 local an_instance = a_module.new { | 253 local an_instance = a_module.new { |
254 a_parameter = 42, | 254 a_parameter = 42; |
255 another_parameter = "yay", | 255 another_parameter = "yay"; |
256 } | 256 } |
257 ``` | 257 ``` |
258 | 258 |
259 > **Rationale:** The use as in `a_module.new` above occurs alone in a statement, | 259 > **Rationale:** The use as in `a_module.new` above occurs alone in a statement, |
260 so there are no precedence issues. | 260 so there are no precedence issues. |
263 | 263 |
264 * Use dot notation when accessing known properties. | 264 * Use dot notation when accessing known properties. |
265 | 265 |
266 ```lua | 266 ```lua |
267 local luke = { | 267 local luke = { |
268 jedi = true, | 268 jedi = true; |
269 age = 28, | 269 age = 28; |
270 } | 270 } |
271 | 271 |
272 -- bad | 272 -- bad |
273 local is_jedi = luke["jedi"] | 273 local is_jedi = luke["jedi"] |
274 | 274 |
275 -- good | 275 -- good |
276 local is_jedi = luke.jedi | 276 local is_jedi = luke.jedi; |
277 ``` | 277 ``` |
278 | 278 |
279 * Use subscript notation `[]` when accessing properties with a variable or if using a table as a list. | 279 * Use subscript notation `[]` when accessing properties with a variable or if using a table as a list. |
280 | 280 |
281 ```lua | 281 ```lua |
282 local vehicles = load_vehicles_from_disk("vehicles.dat") | 282 local vehicles = load_vehicles_from_disk("vehicles.dat") |
283 | 283 |
284 if vehicles["Porsche"] then | 284 if vehicles["Porsche"] then |
285 porsche_handler(vehicles["Porsche"]) | 285 porsche_handler(vehicles["Porsche"]); |
286 vehicles["Porsche"] = nil | 286 vehicles["Porsche"] = nil; |
287 end | 287 end |
288 for name, cars in pairs(vehicles) do | 288 for name, cars in pairs(vehicles) do |
289 regular_handler(cars) | 289 regular_handler(cars); |
290 end | 290 end |
291 ``` | 291 ``` |
292 | 292 |
293 > **Rationale:** Using dot notation makes it clearer that the given key is meant | 293 > **Rationale:** Using dot notation makes it clearer that the given key is meant |
294 to be used as a record/object field. | 294 to be used as a record/object field. |
296 ## Functions in tables | 296 ## Functions in tables |
297 | 297 |
298 * When declaring modules and classes, declare functions external to the table definition: | 298 * When declaring modules and classes, declare functions external to the table definition: |
299 | 299 |
300 ```lua | 300 ```lua |
301 local my_module = {} | 301 local my_module = {}; |
302 | 302 |
303 function my_module.a_function(x) | 303 function my_module.a_function(x) |
304 -- code | 304 -- code |
305 end | 305 end |
306 ``` | 306 ``` |
335 ```lua | 335 ```lua |
336 -- bad | 336 -- bad |
337 superpower = get_superpower() | 337 superpower = get_superpower() |
338 | 338 |
339 -- good | 339 -- good |
340 local superpower = get_superpower() | 340 local superpower = get_superpower(); |
341 ``` | 341 ``` |
342 | 342 |
343 > **Rationale:** Not doing so will result in global variables to avoid polluting | 343 > **Rationale:** Not doing so will result in global variables to avoid polluting |
344 the global namespace. | 344 the global namespace. |
345 | 345 |
364 return name | 364 return name |
365 end | 365 end |
366 | 366 |
367 -- good | 367 -- good |
368 local bad = function() | 368 local bad = function() |
369 test() | 369 test(); |
370 print("doing stuff..") | 370 print("doing stuff.."); |
371 | 371 |
372 --...other stuff... | 372 --...other stuff... |
373 | 373 |
374 local name = get_name() | 374 local name = get_name(); |
375 | 375 |
376 if name == "test" then | 376 if name == "test" then |
377 return false | 377 return false; |
378 end | 378 end |
379 | 379 |
380 return name | 380 return name; |
381 end | 381 end |
382 ``` | 382 ``` |
383 | 383 |
384 > **Rationale:** Lua has proper lexical scoping. Declaring the function later means that its | 384 > **Rationale:** Lua has proper lexical scoping. Declaring the function later means that its |
385 scope is smaller, so this makes it easier to check for the effects of a variable. | 385 scope is smaller, so this makes it easier to check for the effects of a variable. |
408 easier to scan visually: | 408 easier to scan visually: |
409 | 409 |
410 ```lua | 410 ```lua |
411 local function default_name(name) | 411 local function default_name(name) |
412 -- return the default "Waldo" if name is nil | 412 -- return the default "Waldo" if name is nil |
413 return name or "Waldo" | 413 return name or "Waldo"; |
414 end | 414 end |
415 | 415 |
416 local function brew_coffee(machine) | 416 local function brew_coffee(machine) |
417 return (machine and machine.is_loaded) and "coffee brewing" or "fill your water" | 417 return (machine and machine.is_loaded) and "coffee brewing" or "fill your water"; |
418 end | 418 end |
419 ``` | 419 ``` |
420 | 420 |
421 Note that the `x and y or z` as a substitute for `x ? y : z` does not work if | 421 Note that the `x and y or z` as a substitute for `x ? y : z` does not work if |
422 `y` may be `nil` or `false` so avoid it altogether for returning booleans or | 422 `y` may be `nil` or `false` so avoid it altogether for returning booleans or |
432 | 432 |
433 -- good | 433 -- good |
434 if not ok then return nil, "this failed for this reason: " .. reason end | 434 if not ok then return nil, "this failed for this reason: " .. reason end |
435 | 435 |
436 -- good | 436 -- good |
437 use_callback(x, function(k) return k.last end) | 437 use_callback(x, function(k) return k.last end); |
438 | 438 |
439 -- good | 439 -- good |
440 if test then | 440 if test then |
441 return false | 441 return false |
442 end | 442 end |
444 -- bad | 444 -- bad |
445 if test < 1 and do_complicated_function(test) == false or seven == 8 and nine == 10 then do_other_complicated_function() end | 445 if test < 1 and do_complicated_function(test) == false or seven == 8 and nine == 10 then do_other_complicated_function() end |
446 | 446 |
447 -- good | 447 -- good |
448 if test < 1 and do_complicated_function(test) == false or seven == 8 and nine == 10 then | 448 if test < 1 and do_complicated_function(test) == false or seven == 8 and nine == 10 then |
449 do_other_complicated_function() | 449 do_other_complicated_function(); |
450 return false | 450 return false; |
451 end | 451 end |
452 ``` | 452 ``` |
453 | 453 |
454 * Separate statements onto multiple lines. Use semicolons as statement terminators. | 454 * Separate statements onto multiple lines. Use semicolons as statement terminators. |
455 | 455 |
489 age="1 year", | 489 age="1 year", |
490 breed="Bernese Mountain Dog" | 490 breed="Bernese Mountain Dog" |
491 }) | 491 }) |
492 | 492 |
493 -- good | 493 -- good |
494 local x = y * 9 | 494 local x = y * 9; |
495 local numbers = {1, 2, 3} | 495 local numbers = {1, 2, 3}; |
496 local strings = { | 496 local strings = { |
497 "hello"; | 497 "hello"; |
498 "Lua"; | 498 "Lua"; |
499 "world"; | 499 "world"; |
500 } | 500 } |
501 dog.set("attr", { | 501 dog.set("attr", { |
502 age = "1 year", | 502 age = "1 year"; |
503 breed = "Bernese Mountain Dog", | 503 breed = "Bernese Mountain Dog"; |
504 }) | 504 }); |
505 ``` | 505 ``` |
506 | 506 |
507 * Indent tables and functions according to the start of the line, not the construct: | 507 * Indent tables and functions according to the start of the line, not the construct: |
508 | 508 |
509 ```lua | 509 ```lua |
520 local my_table = { | 520 local my_table = { |
521 "hello"; | 521 "hello"; |
522 "world"; | 522 "world"; |
523 } | 523 } |
524 using_a_callback(x, function(...) | 524 using_a_callback(x, function(...) |
525 print("hello") | 525 print("hello"); |
526 end) | 526 end) |
527 ``` | 527 ``` |
528 | 528 |
529 > **Rationale:** This keep indentation levels aligned at predictable places. You don't | 529 > **Rationale:** This keep indentation levels aligned at predictable places. You don't |
530 need to realign the entire block if something in the first line changes (such as | 530 need to realign the entire block if something in the first line changes (such as |
532 | 532 |
533 * The concatenation operator gets a pass for avoiding spaces: | 533 * The concatenation operator gets a pass for avoiding spaces: |
534 | 534 |
535 ```lua | 535 ```lua |
536 -- okay | 536 -- okay |
537 local message = "Hello, "..user.."! This is your day # "..day.." in our platform!" | 537 local message = "Hello, "..user.."! This is your day # "..day.." in our platform!"; |
538 ``` | 538 ``` |
539 | 539 |
540 > **Rationale:** Being at the baseline, the dots already provide some visual spacing. | 540 > **Rationale:** Being at the baseline, the dots already provide some visual spacing. |
541 | 541 |
542 * No spaces after the name of a function in a declaration or in its arguments: | 542 * No spaces after the name of a function in a declaration or in its arguments: |
580 -- bad | 580 -- bad |
581 local a = 1 | 581 local a = 1 |
582 local long_identifier = 2 | 582 local long_identifier = 2 |
583 | 583 |
584 -- good | 584 -- good |
585 local a = 1 | 585 local a = 1; |
586 local long_identifier = 2 | 586 local long_identifier = 2; |
587 ``` | 587 ``` |
588 | 588 |
589 > **Rationale:** This produces extra diffs which add noise to `git blame`. | 589 > **Rationale:** This produces extra diffs which add noise to `git blame`. |
590 | 590 |
591 * Alignment is occasionally useful when logical correspondence is to be highlighted: | 591 * Alignment is occasionally useful when logical correspondence is to be highlighted: |
592 | 592 |
593 ```lua | 593 ```lua |
594 -- okay | 594 -- okay |
595 sys_command(form, UI_FORM_UPDATE_NODE, "a", FORM_NODE_HIDDEN, false) | 595 sys_command(form, UI_FORM_UPDATE_NODE, "a", FORM_NODE_HIDDEN, false); |
596 sys_command(form, UI_FORM_UPDATE_NODE, "sample", FORM_NODE_VISIBLE, false) | 596 sys_command(form, UI_FORM_UPDATE_NODE, "sample", FORM_NODE_VISIBLE, false); |
597 ``` | 597 ``` |
598 | 598 |
599 ## Typing | 599 ## Typing |
600 | 600 |
601 * In non-performance critical code, it can be useful to add type-checking assertions | 601 * In non-performance critical code, it can be useful to add type-checking assertions |
602 for function arguments: | 602 for function arguments: |
603 | 603 |
604 ```lua | 604 ```lua |
605 function manif.load_manifest(repo_url, lua_version) | 605 function manif.load_manifest(repo_url, lua_version) |
606 assert(type(repo_url) == "string") | 606 assert(type(repo_url) == "string"); |
607 assert(type(lua_version) == "string" or not lua_version) | 607 assert(type(lua_version) == "string" or not lua_version); |
608 | 608 |
609 -- ... | 609 -- ... |
610 end | 610 end |
611 ``` | 611 ``` |
612 | 612 |
615 ```lua | 615 ```lua |
616 -- bad | 616 -- bad |
617 local total_score = review_score .. "" | 617 local total_score = review_score .. "" |
618 | 618 |
619 -- good | 619 -- good |
620 local total_score = tostring(review_score) | 620 local total_score = tostring(review_score); |
621 ``` | 621 ``` |
622 | 622 |
623 ## Errors | 623 ## Errors |
624 | 624 |
625 * Functions that can fail for reasons that are expected (e.g. I/O) should | 625 * Functions that can fail for reasons that are expected (e.g. I/O) should |
634 Follow [these guidelines](http://hisham.hm/2014/01/02/how-to-write-lua-modules-in-a-post-module-world/) for writing modules. In short: | 634 Follow [these guidelines](http://hisham.hm/2014/01/02/how-to-write-lua-modules-in-a-post-module-world/) for writing modules. In short: |
635 | 635 |
636 * Always require a module into a local variable named after the last component of the module’s full name. | 636 * Always require a module into a local variable named after the last component of the module’s full name. |
637 | 637 |
638 ```lua | 638 ```lua |
639 local bar = require("foo.bar") -- requiring the module | 639 local bar = require("foo.bar"); -- requiring the module |
640 | 640 |
641 bar.say("hello") -- using the module | 641 bar.say("hello"); -- using the module |
642 ``` | 642 ``` |
643 | 643 |
644 * Don’t rename modules arbitrarily: | 644 * Don’t rename modules arbitrarily: |
645 | 645 |
646 ```lua | 646 ```lua |
655 name that will be used to require it. You may use an LDoc comment to identify | 655 name that will be used to require it. You may use an LDoc comment to identify |
656 the whole module path. | 656 the whole module path. |
657 | 657 |
658 ```lua | 658 ```lua |
659 --- @module foo.bar | 659 --- @module foo.bar |
660 local bar = {} | 660 local bar = {}; |
661 ``` | 661 ``` |
662 | 662 |
663 * Try to use names that won't clash with your local variables. For instance, don't | 663 * Try to use names that won't clash with your local variables. For instance, don't |
664 name your module something like “size”. | 664 name your module something like “size”. |
665 | 665 |
670 | 670 |
671 * Public functions are declared in the module table, with dot syntax: | 671 * Public functions are declared in the module table, with dot syntax: |
672 | 672 |
673 ```lua | 673 ```lua |
674 function bar.say(greeting) | 674 function bar.say(greeting) |
675 print(greeting) | 675 print(greeting); |
676 end | 676 end |
677 ``` | 677 ``` |
678 | 678 |
679 > **Rationale:** Visibility rules are made explicit through syntax. | 679 > **Rationale:** Visibility rules are made explicit through syntax. |
680 | 680 |
700 | 700 |
701 and do something like this instead: | 701 and do something like this instead: |
702 | 702 |
703 ```lua | 703 ```lua |
704 -- good | 704 -- good |
705 local messagepack = require("messagepack") | 705 local messagepack = require("messagepack"); |
706 local mpack = messagepack.new({integer = "unsigned"}) | 706 local mpack = messagepack.new({integer = "unsigned"}); |
707 ``` | 707 ``` |
708 | 708 |
709 * The invocation of require may omit parentheses around the module name: | 709 * The invocation of require may omit parentheses around the module name: |
710 | 710 |
711 ```lua | 711 ```lua |
712 local bla = require "bla" | 712 local bla = require "bla"; |
713 ``` | 713 ``` |
714 | 714 |
715 ## Metatables, classes and objects | 715 ## Metatables, classes and objects |
716 | 716 |
717 If creating a new type of object that has a metatable and methods, the | 717 If creating a new type of object that has a metatable and methods, the |
737 ``` | 737 ``` |
738 -- bad | 738 -- bad |
739 my_object.my_method(my_object) | 739 my_object.my_method(my_object) |
740 | 740 |
741 -- good | 741 -- good |
742 my_object:my_method() | 742 my_object:my_method(); |
743 ``` | 743 ``` |
744 | 744 |
745 > **Rationale:** This makes it explicit that the intent is to use the function as a method. | 745 > **Rationale:** This makes it explicit that the intent is to use the function as a method. |
746 | 746 |
747 * Do not rely on the `__gc` metamethod to release resources other than memory. | 747 * Do not rely on the `__gc` metamethod to release resources other than memory. |
778 reasons (e.g. a callback that follows a given format) but doesn't use some of | 778 reasons (e.g. a callback that follows a given format) but doesn't use some of |
779 its arguments; it's better to spell out in the argument what the API the | 779 its arguments; it's better to spell out in the argument what the API the |
780 function implements is, instead of adding `_` variables. | 780 function implements is, instead of adding `_` variables. |
781 | 781 |
782 ``` | 782 ``` |
783 local foo, bar = some_function() --luacheck: ignore 212/foo | 783 local foo, bar = some_function(); --luacheck: ignore 212/foo |
784 print(bar) | 784 print(bar); |
785 ``` | 785 ``` |
786 | 786 |
787 * luacheck warning 542 (empty if branch) can also be ignored, when a sequence | 787 * luacheck warning 542 (empty if branch) can also be ignored, when a sequence |
788 of `if`/`elseif`/`else` blocks implements a "switch/case"-style list of cases, | 788 of `if`/`elseif`/`else` blocks implements a "switch/case"-style list of cases, |
789 and one of the cases is meant to mean "pass". For example: | 789 and one of the cases is meant to mean "pass". For example: |
790 | 790 |
791 ```lua | 791 ```lua |
792 if warning >= 600 and warning <= 699 then | 792 if warning >= 600 and warning <= 699 then |
793 print("no whitespace warnings") | 793 print("no whitespace warnings"); |
794 elseif warning == 542 then --luacheck: ignore 542 | 794 elseif warning == 542 then --luacheck: ignore 542 |
795 -- pass | 795 -- pass |
796 else | 796 else |
797 print("got a warning: "..warning) | 797 print("got a warning: "..warning); |
798 end | 798 end |
799 ``` | 799 ``` |
800 | 800 |
801 > **Rationale:** This avoids writing negated conditions in the final fallback | 801 > **Rationale:** This avoids writing negated conditions in the final fallback |
802 case, and it's easy to add another case to the construct without having to | 802 case, and it's easy to add another case to the construct without having to |