summaryrefslogtreecommitdiff
path: root/HACKING
blob: 2c92428b2f263a5a359ae21fa1a58794cb2808e3 (plain)
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
= Hacking =

If you've taken to hacking Vimperator source code, we hope that you'll share
your changes. In case you do, please keep the following in mind, and we'll be
happy to accept your patches.

== Documentation ==

First of all, all new features and all user-visible changes to existing
features need to be documented. That means editing the appropriate help files
and adding a NEWS entry where appropriate. When editing the NEWS file, you
should add your change to the top of the list of changes. If your change
alters an interface (key binding, command) and is likely to cause trouble,
prefix it with 'IMPORTANT:', otherwise, place it below the other 'IMPORTANT'
entries. If you're not sure if your change merits a news entry, or if it's
important, please ask.

== Coding Style ==

In general: Just look at the existing source code!
We try to be quite consistent, but of course, that's not always possible.

=== The most important style issues are: ===

* Use 4 spaces to indent things, no tabs, not 2, nor 8 spaces. If you use Vim,
  this should be taken care of automatically by the modeline (like the
  one below).

* No trailing whitespace.

* Use " for enclosing strings instead of ', unless using ' avoids escaping of lots of "
  Example: alert("foo") instead of alert('foo');

* Exactly one space after if/for/while/catch etc. and after a comma, but none
  after a parenthesis or after a function call:
      for (pre; condition; post)
  but:
      alert("foo");

* Opening curly brackets { must be on a new line, unless it is used in a closure:
      function myFunction ()
      {
          if (foo)
          {
              baz = false;
              return bar;
          }
          else
          {
              return baz;
          }
      }
  but:
      setTimeout(function () {
          ...
      });

* No braces for one-line conditional statements:
  Right:
     if (foo)
         frob();
     else
         unfrob();

* Prefer lambda-style functions where suitable:
  Right: list.filter(function (elem) elem.good != elem.BAD);
  Wrong: list.filter(function (elem) { return elem.good != elem.BAD });

* Anonymous function definitions should be formatted with a space after the
  keyword "function". Example: function () {}, not function() {}.

* Prefer the use of let over var i.e. only use var when required.
  For more details, see
  https://developer.mozilla.org/en/New_in_JavaScript_1.7#Block_scope_with_let

* Reuse common local variable names E.g. "elem" is generally used for element,
  "win" for windows etc.

* Prefer // over /* */ comments (exceptions for big comments are usually OK)
  Right: if (HACK) // TODO: remove hack
  Wrong: if (HACK) /* TODO: remove hack */

* Documentation comment blocks use /** ... */ Wrap these lines at 80
  characters.

* Only wrap lines if it makes the code obviously clearer. Lines longer than 132
  characters should probably be broken up rather than wrapped anyway.

* Use UNIX new lines (\n), not windows (\r\n) or old Mac ones (\r)

* Use Iterators, Array#forEach, or for (let i = 0; i < ary.length; i++)
  to iterate over arrays. for (let i in ary) and for each (let i in ary)
  include members in an Array.prototype, which some extensions alter.
  Right:
    for (let [,elem] in Iterator(ary))
    for (let [k, v] in Iterator(obj))
    ary.forEach(function (elem) { ...
  Wrong:
    for each (let elem in ary)

  The exceptions to this rule are for objects with __iterator__ set,
  and for XML objects (see README.E4X).

* Avoid using 'new' with constructors where possible, and use [] and
  {} rather than new Array/new Object.
  Right:
    RegExp("^" + foo + "$")
    Function(code)
    new Date
  Wrong:
    new RegExp("^" + foo + "$")
    new Function(code)
    Date() // Right if you want a string-representation of the date

  NOTE by mst: That one is debateable, actually I like the "new" as one
  immediately sees that a new object of a class is created which is not
  so obvious by var x = CompletionContext(); which could also mean that
  CompletionContext() could return a cached object. What's thesnowdog's
  opinion and why do you, Kris, think it's better/cleaner?

  I don't think it's better/cleaner, it just seemed to be a consensus.
    --Kris

  I don't like unnecessary use of 'new', I don't like 'new'. --djk

  There is semantic value to using "new." It's good CBSE. --Ted

  There's no semantic value. It's reasonable to infer that any function
  named in CamelCase is a constructor. That's the case with all such
  internal functions. As far as I'm concerned, 'new' is a hack. Actually,
  most of JS is a hack...
    --Kris

      What he said. Although, I would have said "a pretty nifty language
      with some regrettable design decisions" now that I'm in therapy.
      --djk

  There is semantic value: With new you know for SURE it's calling the
  constructor of a class, with CamelCase only you just ASSUME you do.
  I am all about making code clearer also to new developers. And this
  includes getting rid of as many assumptions as possible, by making
  things explicit, when they don't hurt readability (and new doesn't
  for me). It's not so important, that i'll change all instances to
  new immediately, but will probably do so over time, when I see it.
    --mst

      JavaScript doesn't have classes... What about all the other
      'constructor' functions such as Commands? And I think it does hurt
      readability because it's pointless.
      Anyway, if it's important enough to change it should all be
      changed at once. I've removed most of these sorts of
      inconsistencies and I wouldn't like to see them reintroduced.
      --djk

  Actually, you're not sure of anything. You can call new (function (a)
  a.substr(2)), and you don't get a new object. The only difference is
  that it's called with 'this' set. Given that it's uncouth to name a
  non-constructor function in CamelCase, and that most internal
  constructors don't require new (and some, like String, break when
  you use it), it just seems superfluous and distracting.
    --Kris

== Testing/Optimization ==

TODO: Add some information here about testing/validation/etc.
Information about how/when to use :regressions might be nice.
Additionally, maybe there should be some benchmark information here --
something to let a developer know what's "too" slow...? Or general
guidelines about optimization?

== Source Code Management ==

TODO: Document the existence of remote branches and discuss when and how
      to push to them. At least provide an index so that devs know where
      to look if an old branch needs to be maintained or a feature needs
      to be added to a new branch. Keep in mind that git is not the most
      intuitive SCM.

    I don't agree. git is about as intuitive as any other SCM, but,
    regardless, it's by far one of the most popular. There are
    countless git walkthroughs, FAQs, tips pages (not to mention 'git
    help') that I don't see the need to duplicate them here. As for
    branches, 'git branch' should be sufficient, and, if not, there's
    a list on gitweb. --Kris

        I wasn't trying to say that git was a problem (though other DVCS
        have more accessible help systems; except for very complex
        projects, I think Mercurial is a much more comfortable DVCS to
        learn, use, and navigate). I was saying that it might be nice if
        the remote branches (and related polices) were documented. Yes,
        anyone can do a "git branch -r", but seeing that a branch exists
        is not the same as understanding why it's there. --Ted

            Sure, I agree. --djk

// vim: set ft=asciidoc fdm=marker sw=4 ts=4 et ai: