about summary refs log tree commit diff
path: root/doc/coding-conventions.xml
blob: 586fcd98f23d82a9a36609f263974c38ab1000b3 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
<chapter xmlns="http://docbook.org/ns/docbook"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         xml:id="chap-conventions">

<title>Coding conventions</title>


<section><title>Syntax</title>

<itemizedlist>

  <listitem><para>Use 2 spaces of indentation per indentation level in
  Nix expressions, 4 spaces in shell scripts.</para></listitem>

  <listitem><para>Do not use tab characters, i.e. configure your
  editor to use soft tabs.  For instance, use <literal>(setq-default
  indent-tabs-mode nil)</literal> in Emacs.  Everybody has different
  tab settings so it’s asking for trouble.</para></listitem>

  <listitem><para>Use <literal>lowerCamelCase</literal> for variable
  names, not <literal>UpperCamelCase</literal>.  TODO: naming of
  attributes in
  <filename>all-packages.nix</filename>?</para></listitem>

  <listitem><para>Function calls with attribute set arguments are
  written as

<programlisting>
foo {
  arg = ...;
}
</programlisting>

  not

<programlisting>
foo
{
  arg = ...;
}
</programlisting>

  Also fine is

<programlisting>
foo { arg = ...; }
</programlisting>

  if it's a short call.</para></listitem>

  <listitem><para>In attribute sets or lists that span multiple lines,
  the attribute names or list elements should be aligned:

<programlisting>
# A long list.
list =
  [ elem1
    elem2
    elem3
  ];

# A long attribute set.
attrs =
  { attr1 = short_expr;
    attr2 =
      if true then big_expr else big_expr;
  };

# Alternatively:
attrs = {
  attr1 = short_expr;
  attr2 =
    if true then big_expr else big_expr;
};
</programlisting>

  </para></listitem>

  <listitem><para>Short lists or attribute sets can be written on one
  line:

<programlisting>
# A short list.
list = [ elem1 elem2 elem3 ];

# A short set.
attrs = { x = 1280; y = 1024; };
</programlisting>

  </para></listitem>

  <listitem><para>Breaking in the middle of a function argument can
  give hard-to-read code, like

<programlisting>
someFunction { x = 1280;
  y = 1024; } otherArg
  yetAnotherArg
</programlisting>

  (especially if the argument is very large, spanning multiple
  lines).</para>

  <para>Better:

<programlisting>
someFunction
  { x = 1280; y = 1024; }
  otherArg
  yetAnotherArg
</programlisting>

  or

<programlisting>
let res = { x = 1280; y = 1024; };
in someFunction res otherArg yetAnotherArg
</programlisting>

  </para></listitem>

  <listitem><para>The bodies of functions, asserts, and withs are not
  indented to prevent a lot of superfluous indentation levels, i.e.

<programlisting>
{ arg1, arg2 }:
assert system == "i686-linux";
stdenv.mkDerivation { ...
</programlisting>

  not

<programlisting>
{ arg1, arg2 }:
  assert system == "i686-linux";
    stdenv.mkDerivation { ...
</programlisting>

  </para></listitem>

  <listitem><para>Function formal arguments are written as:

<programlisting>
{ arg1, arg2, arg3 }:
</programlisting>

  but if they don't fit on one line they're written as:

<programlisting>
{ arg1, arg2, arg3
, arg4, ...
, # Some comment...
  argN
}:
</programlisting>

  </para></listitem>

  <listitem><para>Functions should list their expected arguments as
  precisely as possible.  That is, write

<programlisting>
{ stdenv, fetchurl, perl }: <replaceable>...</replaceable>
</programlisting>

  instead of

<programlisting>
args: with args; <replaceable>...</replaceable>
</programlisting>

  or 
  
<programlisting>
{ stdenv, fetchurl, perl, ... }: <replaceable>...</replaceable>
</programlisting>

  </para>

  <para>For functions that are truly generic in the number of
  arguments (such as wrappers around <varname>mkDerivation</varname>)
  that have some required arguments, you should write them using an
  <literal>@</literal>-pattern:

<programlisting>
{ stdenv, doCoverageAnalysis ? false, ... } @ args:

stdenv.mkDerivation (args // {
  <replaceable>...</replaceable> if doCoverageAnalysis then "bla" else "" <replaceable>...</replaceable>
})
</programlisting>

  instead of

<programlisting>
args:

args.stdenv.mkDerivation (args // {
  <replaceable>...</replaceable> if args ? doCoverageAnalysis &amp;&amp; args.doCoverageAnalysis then "bla" else "" <replaceable>...</replaceable>
})
</programlisting>

  </para></listitem>

</itemizedlist>

</section>


<section><title>File naming and organisation</title>

<para>Names of files and directories should be in lowercase, with
dashes between words — not in camel case.  For instance, it should be
<filename>all-packages.nix</filename>, not
<filename>allPackages.nix</filename> or
<filename>AllPackages.nix</filename>.</para>

</section>


</chapter>