Macaulay2 / M2

The primary source code repository for Macaulay2, a system for computing in commutative algebra, algebraic geometry and related fields.
https://macaulay2.com
349 stars 235 forks source link

Style guide and linter for M2 code #3290

Open mahrud opened 5 months ago

mahrud commented 5 months ago

(I thought there was an issue about this already, but I can't find it.)

We need a basic linter for M2, but there needs to be a style guide first. We can use this issue to collect suggestions. I'll start with a few. Feedback for changing these are welcome!


  1. Break any of the rules below when necessary for readability.
  2. Use 4 space indents inside code after opened (, {, [, <|.
  3. Use 4 space indents inside code after for, do, list, while, if, then, else, e.g.
    
    if cond then (
    multi-line code 1
    )
    else (
    multi-line code 2
    )

if cond then result1 else result2

if cond then result1 else result2

while cond do stuff

while cond do stuff

while cond do ( multi-line stuff )

for i in range do stuff

for i in range do stuff

for i in range do ( multi-line stuff )

3. Use 4 spaces after `->` and `=>`, e.g.
```m2
longMethodName Module := Module => opts -> (n, R, M) ->
    if n == 0 then R^1 else
    if n  > 0 then blah blah M else
    error "expected non-negative integer"

longMethodName Ideal := Module => opts -> (n, R, I) ->
    longMethodName(n, R, module I)

longMethodName Ideal := Module => opts ->
    (n, R, I) -> longMethodName(n, R, module I)

H = new HashTable from {
    "very very ......................................... very long key" =>
        12,
    }
  1. When plausible, use spaces to tabulate keys and values in hash tables, e.g.
    blah = method(
    Options => {
        Strategy    => null,
        LengthLimit => infinity,
        }
    )
  2. Use 2 space indents inside documentation after things like Node, Key, ..., but one more or less for cases like this is acceptable:
    doc ///
    Node
    Key
    func
    (func, Module)
    (func, Sequence)
    [func, Strategy]
    Usage
    func M
    func(M,N)
    Inputs
     M:Module -- graded
    "(M,N)":
       a pair of modules
    SeeAlso
    func2
    (func, Ideal)
    ///
  3. Use tabs for each 8 spaces and remove extra spaces before the tab character.
  4. Insert a space after each comma in sequence of different types, e.g. (n, R, M).
  5. Dropping the space is fine in sequences of same type, e.g. [x,y,z].
  6. Insert a comma after the last item in hash tables, export lists, etc., e.g.
    export {
    "blah",
    "foo",
    }
  7. Don't use parenthesis around a single object:
    
    blah(ZZ) := (n) -> (2*n) -- bad
    blah ZZ := n -> 2*n      -- good

dim(module(I) -- bad dim module I -- good

coker(gens(I M)) -- good coker gens(I M) -- good

-- exception: functions which accept only a single object func = (x) -> stuff


11. Put a space before and after binary operators like `= := -> => < ? | xor`
d-torrance commented 5 months ago
  1. No trailing whitespace
mahrud commented 5 months ago
  1. Use 2 space indents inside TEST.