From 2b21895cd5f2fbc6e041f9f0a2dbb32b44b5fe7b Mon Sep 17 00:00:00 2001
From: Mike Frysinger
Date: Sun, 20 Sep 2026 22:13:06 -0400
Subject: [PATCH] generate html for remaining XML guides
Since Chrome is dropping support for this completely this year,
generate HTML from all remaining XML guides. These have largely
been migrated to other formats internally already too.
---
404.html | 4 +
README.md | 4 +-
javascriptguide.html | 3691 +++++++++++++++++++++++
javascriptguide.xml | 3630 ----------------------
lispguide.xml => lispguide.html | 1721 +++++++----
styleguide.xsl | 924 ------
vimscriptfull.xml => vimscriptfull.html | 643 ++--
vimscriptguide.html | 662 ++++
vimscriptguide.xml | 412 ---
9 files changed, 5855 insertions(+), 5836 deletions(-)
create mode 100644 javascriptguide.html
delete mode 100644 javascriptguide.xml
rename lispguide.xml => lispguide.html (67%)
delete mode 100644 styleguide.xsl
rename vimscriptfull.xml => vimscriptfull.html (66%)
create mode 100644 vimscriptguide.html
delete mode 100644 vimscriptguide.xml
diff --git a/404.html b/404.html
index 1414d87..8d60c79 100644
--- a/404.html
+++ b/404.html
@@ -15,11 +15,15 @@ window.onload = function() {
'cppguide.xml': 'cppguide.html',
'google-r-style.html': 'Rguide.html',
'htmlcssguide.xml': 'htmlcssguide.html',
+ 'javascriptguide.xml': 'javascriptguide.html',
'jsoncstyleguide.html': 'jsoncguide.html',
'jsoncstyleguide.xml': 'jsoncguide.html',
+ 'lispguide.xml': 'lispguide.html',
'objcguide.xml': 'objcguide.html',
'Rguide.xml': 'Rguide.html',
'shell.xml': 'shellguide.html',
+ 'vimscriptfull.xml': 'vimscriptfull.html',
+ 'vimscriptguide.xml': 'vimscriptguide.html',
};
const newPage = map[missingPage];
if (newPage) {
diff --git a/README.md b/README.md
index 19257bf..d8ff41d 100644
--- a/README.md
+++ b/README.md
@@ -92,8 +92,8 @@ primarily optimizing for Google's internal needs.
[markdown]: docguide/style.md
[ts]: https://google.github.io/styleguide/tsguide.html
[angular]: https://google.github.io/styleguide/angularjs-google-style.html
-[cl]: https://google.github.io/styleguide/lispguide.xml
-[vim]: https://google.github.io/styleguide/vimscriptguide.xml
+[cl]: https://google.github.io/styleguide/lispguide.html
+[vim]: https://google.github.io/styleguide/vimscriptguide.html
[emacs]: https://raw.githubusercontent.com/google/styleguide/gh-pages/google-c-style.el
[xml]: https://google.github.io/styleguide/xmlstyle.html
[dart]: https://www.dartlang.org/guides/language/effective-dart
diff --git a/javascriptguide.html b/javascriptguide.html
new file mode 100644
index 0000000..c93a9d0
--- /dev/null
+++ b/javascriptguide.html
@@ -0,0 +1,3691 @@
+
+
+Google JavaScript Style Guide
+
+
+
+
+
+
+
Google JavaScript Style Guide
+
+ Please note: This guide is old and is not being updated. It is retained
+ as a reference as it was written for pre-ECMAScript 6th Edition features.
+ Please use the newer guide instead.
+
+
+ Revision 2.93
+
+
+
+ Aaron Whyte
+ Bob Jervis
+ Dan Pupius
+ Erik Arvidsson
+ Fritz Schneider
+ Robby Walker
+
+
+
+ Each style point has a summary for which additional information is available
+ by toggling the accompanying arrow button that looks this way:
+ ▶.
+ You may toggle all summaries with the big arrow button:
+
+ This style guide contains many details that are initially
+ hidden from view. They are marked by the triangle icon, which you
+ see here on your left. Click it now.
+ You should see "Hooray" appear below.
+
+
+
+ Hooray! Now you know you can expand points to get more
+ details. Alternatively, there's a "toggle all" at the
+ top of this document.
+
+
+
+
+
+
Background
+
+ JavaScript is the main client-side scripting language used
+
+ by many of Google's open-source
+ projects.
+ This style guide is a list of dos and don'ts for
+ JavaScript programs.
+
+Decision:
+ When you fail to specify var,
+ the variable gets placed in the global context, potentially clobbering
+ existing values. Also, if there's no declaration, it's hard to tell in
+ what scope a variable lives (e.g., it could be in the Document or
+ Window just as easily as in the local scope). So always declare with
+ var.
+
Use @const to indicate a constant (non-overwritable)
+ pointer (a variable or property).
+
Never use the
+
+ const keyword
+ as it's not supported in Internet Explorer.
+
+
+
+
+Decision:
+
+Constant values
+
+
If a value is intended to be constant
+ and immutable, it should be given a name
+ in CONSTANT_VALUE_CASE.
+ ALL_CAPS additionally implies @const
+ (that the value is not overwritable).
+
+
+
Primitive types (number, string,
+ boolean) are constant values.
+
+
Objects'
+ immutability is more subjective — objects should be
+ considered immutable only if they do not demonstrate observable
+ state change. This is not enforced by the compiler.
+
+
+
+
+
+Constant pointers (variables and properties)
+
The @const annotation on a variable or property
+ implies that it is not overwritable. This is enforced by the
+ compiler at build time. This behavior is consistent with the
+
+ const keyword (which we do not use due to the
+ lack of support in Internet Explorer).
+
+
A @const annotation on a method additionally
+ implies that the method cannot not be overridden in subclasses.
+
+
+
A @const annotation on a constructor implies the
+ class cannot be subclassed (akin to final in Java).
+
+
+
+
+
+Examples
+
+
Note that @const does not necessarily imply
+ CONSTANT_VALUES_CASE.
+
+ However, CONSTANT_VALUES_CASE
+ does imply @const.
+
Relying on implicit insertion can cause subtle, hard to debug
+ problems. Don't do it. You're better than that.
+
There are a couple places where missing semicolons are particularly
+ dangerous:
+
// 1.
+MyClass.prototype.myMethod = function() {
+ return 42;
+} // No semicolon here.
+
+(function() {
+ // Some initialization code wrapped in a function to create a scope for locals.
+})();
+
+
+var x = {
+ 'i': 1,
+ 'j': 2
+} // No semicolon here.
+
+// 2. Trying to do one thing on Internet Explorer and another on Firefox.
+// I know you'd never write code like this, but throw me a bone.
+[ffVersion, ieVersion][isIE]();
+
+
+var THINGS_TO_EAT = [apples, oysters, sprayOnCheese] // No semicolon here.
+
+// 3. conditional execution a la bash
+-1 == resultOfOperation() || die();
+
+So what happens?
+
+
JavaScript error - first the function returning 42 is called
+ with the second function as a parameter, then the number 42 is
+ "called" resulting in an error.
+
You will most likely get a 'no such property in undefined'
+ error at runtime as it tries to call
+ x[ffVersion, ieVersion][isIE]().
+
+die is always called since the array minus 1 is
+ NaN which is never equal to anything (not even if
+ resultOfOperation() returns NaN) and
+ THINGS_TO_EAT gets assigned the result of
+ die().
+
+
+
+Why?
+
JavaScript requires statements to end with a semicolon, except when
+ it thinks it can safely infer their existence. In each of these
+ examples, a function declaration or object or array literal is used
+ inside a statement. The closing brackets are not enough to signal
+ the end of the statement. Javascript never ends a statement if the
+ next token is an infix or bracket operator.
+
This has really surprised people, so make sure your assignments end
+ with semicolons.
+
+
+Clarification: Semicolons and functions
+
Semicolons should be included at the end of function expressions,
+ but not at the end of function declarations. The distinction is
+ best illustrated with an example:
Nested functions can be very useful, for example in the creation of
+ continuations and for the task of hiding helper functions. Feel free
+ to use them.
While most script engines support Function Declarations within blocks
+ it is not part of ECMAScript (see
+ ECMA-262,
+ clause 13 and 14). Worse implementations are inconsistent with each
+ other and with future EcmaScript proposals. ECMAScript only allows for
+ Function Declarations in the root statement list of a script or
+ function. Instead use a variable initialized with a Function
+ Expression to define a function within a block:
Without custom exceptions, returning error information from a
+ function that also returns a value can be tricky, not to mention
+ inelegant. Bad solutions include passing in a reference type to hold
+ error information or always returning Objects with a potential
+ error member. These basically amount to a primitive exception
+ handling hack. Feel free to use custom exceptions when
+ appropriate.
For maximum portability and compatibility, always prefer standards
+ features over non-standards features (e.g.,
+ string.charAt(3) over string[3] and element
+ access with DOM functions instead of using an application-specific
+ shorthand).
Multi-level prototype hierarchies are how JavaScript implements
+ inheritance. You have a multi-level hierarchy if you have a
+ user-defined class D with another user-defined class B as its
+ prototype. These hierarchies are much harder to get right than they
+ first appear!
+
+
For that reason, it is best to use goog.inherits() from
+
+ the Closure Library
+
+ or a similar library function.
+
In modern JavaScript engines, changing the number of properties on an
+ object is much slower than reassigning the values. The delete keyword
+ should be avoided except when it is necessary to remove a property
+ from an object's iterated list of keys, or to change the result of
+ if (key in obj).
One thing to keep in mind, however, is that a closure keeps a pointer
+ to its enclosing scope. As a result, attaching a closure to a DOM
+ element can create a circular reference and thus, a memory leak. For
+ example, in the following code:
+
function foo(element, a, b) {
+ element.onclick = function() { /* uses a and b */ };
+}
+
the function closure keeps a reference to element,
+ a, and b even if it never uses
+ element. Since element also keeps a
+ reference to the closure, we have a cycle that won't be cleaned up by
+ garbage collection. In these situations, the code can be structured
+ as follows:
+
function foo(element, a, b) {
+ element.onclick = bar(a, b);
+}
+
+function bar(a, b) {
+ return function() { /* uses a and b */ };
+}
+ Only for code loaders and REPL (Read–eval–print loop)
+
+
+
eval() makes for confusing semantics and is dangerous
+ to use if the string being eval()'d contains user input.
+ There's usually a better, clearer, and safer way to write your code,
+ so its use is generally not permitted.
+
+
For RPC you can always use JSON and read the result using
+ JSON.parse() instead of eval().
+
+
Let's assume we have a server that returns something like this:
Using with clouds the semantics of your program.
+ Because the object of the with can have properties that
+ collide with local variables, it can drastically change the meaning
+ of your program. For example, what does this do?
+
with (foo) {
+ var x = 3;
+ return x;
+}
+
Answer: anything. The local variable x could be
+ clobbered by a property of foo and perhaps it even has
+ a setter, in which case assigning 3 could cause lots of
+ other code to execute. Don't use with.
+ Only in object constructors, methods, and in setting up closures
+
+
+
The semantics of this can be tricky. At times it refers
+ to the global object (in most places), the scope of the caller (in
+ eval), a node in the DOM tree (when attached using an
+ event handler HTML attribute), a newly created object (in a
+ constructor), or some other object (if function was
+ call()ed or apply()ed).
+
Because this is so easy to get wrong, limit its use to those places
+ where it is required:
+
+
in constructors
+
in methods of objects (including in the creation of closures)
+ Only for iterating over keys in an object/map/hash
+
+
+
for-in loops are often incorrectly used to loop over
+ the elements in an Array. This is however very error
+ prone because it does not loop from 0 to
+ length - 1 but over all the present keys in the object
+ and its prototype chain. Here are a few cases where it fails:
+
function printArray(arr) {
+ for (var key in arr) {
+ print(arr[key]);
+ }
+}
+
+printArray([0,1,2,3]); // This works.
+
+var a = new Array(10);
+printArray(a); // This is wrong.
+
+a = document.getElementsByTagName('*');
+printArray(a); // This is wrong.
+
+a = [0,1,2,3];
+a.buhu = 'wine';
+printArray(a); // This is wrong again.
+
+a = new Array;
+a[3] = 3;
+printArray(a); // This is wrong again.
+
Always use normal for loops when using arrays.
+
function printArray(arr) {
+ var l = arr.length;
+ for (var i = 0; i < l; i++) {
+ print(arr[i]);
+ }
+}
+ Never use Array as a map/hash/associative array
+
+
+
Associative Arrays are not allowed... or more precisely
+ you are not allowed to use non number indexes for arrays. If you need
+ a map/hash use Object instead of Array in
+ these cases because the features that you want are actually features
+ of Object and not of Array.
+ Array just happens to extend Object (like
+ any other object in JS and therefore you might as well have used
+ Date, RegExp or String).
var myString = 'A rather long string of English text, an error message \
+ actually that just keeps going and going -- an error \
+ message to make the Energizer bunny blush (right through \
+ those Schwarzenegger shades)! Where was I? Oh yes, \
+ you\'ve got an error and all the extraneous whitespace is \
+ just gravy. Have a nice day.';
+
The whitespace at the beginning of each line can't be safely stripped
+ at compile time; whitespace after the slash will result in tricky
+ errors.
+
Use string concatenation instead:
+
var myString = 'A rather long string of English text, an error message ' +
+ 'actually that just keeps going and going -- an error ' +
+ 'message to make the Energizer bunny blush (right through ' +
+ 'those Schwarzenegger shades)! Where was I? Oh yes, ' +
+ 'you\'ve got an error and all the extraneous whitespace is ' +
+ 'just gravy. Have a nice day.';
Use Array and Object literals instead of
+ Array and Object constructors.
+
Array constructors are error-prone due to their arguments.
+
// Length is 3.
+var a1 = new Array(x1, x2, x3);
+
+// Length is 2.
+var a2 = new Array(x1, x2);
+
+// If x1 is a number and it is a natural number the length will be x1.
+// If x1 is a number but not a natural number this will throw an exception.
+// Otherwise the array will have one element with x1 as its value.
+var a3 = new Array(x1);
+
+// Length is 0.
+var a4 = new Array();
+
Because of this, if someone changes the code to pass 1 argument
+ instead of 2 arguments, the array might not have the expected
+ length.
+
To avoid these kinds of weird cases, always use the more readable
+ array literal.
+
var a = [x1, x2, x3];
+var a2 = [x1, x2];
+var a3 = [x1];
+var a4 = [];
+
Object constructors don't have the same problems, but for readability
+ and consistency object literals should be used.
+
var o = new Object();
+
+var o2 = new Object();
+o2.a = 0;
+o2.b = 1;
+o2.c = 2;
+o2['strange key'] = 3;
Modifying builtins like Object.prototype and
+ Array.prototype are strictly forbidden. Modifying other
+ builtins like Function.prototype is less dangerous but
+ still leads to hard to debug issues in production and should be
+ avoided.
In general, use
+ functionNamesLikeThis,
+ variableNamesLikeThis,
+ ClassNamesLikeThis,
+ EnumNamesLikeThis,
+ methodNamesLikeThis,
+ CONSTANT_VALUES_LIKE_THIS,
+ foo.namespaceNamesLikeThis.bar, and
+ filenameslikethis.js.
+
+
+
+
+Properties and methods
+
+
+Private properties and methods should be named with a
+ trailing underscore.
+
+
+Protected properties and methods should be
+ named without a trailing underscore (like public ones).
+
+
For more information on private and protected,
+ read the section on
+
+ visibility.
+
+
+
+
+
+
+
+
+Method and function parameter
+
Optional function arguments start with opt_.
+
Functions that take a variable number of arguments should have the
+ last argument named var_args. You may not refer to
+ var_args in the code; use the arguments
+ array.
+
Optional and variable arguments can also be specified in
+ @param annotations. Although either convention is
+ acceptable to the compiler, using both together is preferred.
+
+
+
+
+Getters and Setters
+
EcmaScript 5 getters and setters for properties are discouraged.
+ However, if they are used, then getters must not change observable
+ state.
+
/**
+ * WRONG -- Do NOT do this.
+ */
+var foo = { get next() { return this.nextId++; } };
+
+
+
+Accessor functions
+
Getters and setters methods for properties are not required.
+ However, if they are used, then getters must be named
+ getFoo() and setters must be named
+ setFoo(value). (For boolean getters,
+ isFoo() is also acceptable, and often sounds more
+ natural.)
+
+
+
+Namespaces
+
JavaScript has no inherent packaging or namespacing support.
+
Global name conflicts are difficult to debug, and can cause
+ intractable problems when two projects try to integrate. In order
+ to make it possible to share common JavaScript code, we've adopted
+ conventions to prevent collisions.
+
+Use namespaces for global code
+
ALWAYS prefix identifiers in the global scope with a
+ unique pseudo namespace related to the project or library. If you
+ are working on "Project Sloth", a reasonable pseudo namespace
+ would be sloth.*.
Many JavaScript libraries, including
+
+ the Closure Library
+
+ and
+
+ Dojo toolkit
+
+ give you high-level functions for declaring your namespaces.
+ Be consistent about how you declare your namespaces.
When choosing a child-namespace, make sure that the owners of the
+ parent namespace know what you are doing. If you start a project
+ that creates hats for sloths, make sure that the Sloth team knows
+ that you're using sloth.hats.
+
+
+
+Use different namespaces for external code and internal code
+
"External code" is code that comes from outside your codebase,
+ and is compiled independently. Internal and external names should
+ be kept strictly separate. If you're using an external library
+ that makes things available in foo.hats.*, your
+ internal code should not define all its symbols in
+ foo.hats.*, because it will break if the other
+ team defines new symbols.
+
foo.require('foo.hats');
+
+/**
+ * WRONG -- Do NOT do this.
+ * @constructor
+ * @extends {foo.hats.RoundHat}
+ */
+foo.hats.BowlerHat = function() {
+};
+
If you need to define new APIs on an external namespace, then you
+ should explicitly export the public API functions, and only those
+ functions. Your internal code should call the internal APIs by
+ their internal names, for consistency and so that the compiler
+ can optimize them better.
Never create aliases in the global scope. Use them only in
+ function blocks.
+
+
+
+Filenames
+
Filenames should be all lowercase in order to avoid confusion on
+ case-sensitive platforms. Filenames should end in .js,
+ and should contain no punctuation except for - or
+ _ (prefer - to _).
You can control how your objects string-ify themselves by defining a
+ custom toString() method. This is fine, but you need
+ to ensure that your method (1) always succeeds and (2) does not have
+ side-effects. If your method doesn't meet these criteria, it's very
+ easy to run into serious problems. For example, if
+ toString() calls a method that does an
+ assert, assert might try to output the name
+ of the object in which it failed, which of course requires calling
+ toString().
Always use explicit scope - doing so increases portability and
+ clarity. For example, don't rely on window being in the
+ scope chain. You might want to use your function in another
+ application for which window is not the content
+ window.
WRONG_Object.prototype = {
+ a : 0,
+ b : 1,
+ lengthyName: 2
+};
+
+
+Function Arguments
+
When possible, all function arguments should be listed on the same
+ line. If doing so would exceed the 80-column limit, the arguments
+ must be line-wrapped in a readable way. To save space, you may wrap
+ as close to 80 as possible, or put each argument on its own line to
+ enhance readability. The indentation may be either four spaces, or
+ aligned to the parenthesis. Below are the most common patterns for
+ argument wrapping:
+
// Four-space, wrap at 80. Works with very long function names, survives
+// renaming without reindenting, low on space.
+goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
+ veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
+ tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
+ // ...
+};
+
+// Four-space, one argument per line. Works with long function names,
+// survives renaming, and emphasizes each argument.
+goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
+ veryDescriptiveArgumentNumberOne,
+ veryDescriptiveArgumentTwo,
+ tableModelEventHandlerProxy,
+ artichokeDescriptorAdapterIterator) {
+ // ...
+};
+
+// Parenthesis-aligned indentation, wrap at 80. Visually groups arguments,
+// low on space.
+function foo(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
+ tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
+ // ...
+}
+
+// Parenthesis-aligned, one argument per line. Emphasizes each
+// individual argument.
+function bar(veryDescriptiveArgumentNumberOne,
+ veryDescriptiveArgumentTwo,
+ tableModelEventHandlerProxy,
+ artichokeDescriptorAdapterIterator) {
+ // ...
+}
+
When the function call is itself indented, you're free to start the
+ 4-space indent relative to the beginning of the original statement
+ or relative to the beginning of the current function call.
+ The following are all acceptable indentation styles.
When declaring an anonymous function in the list of arguments for
+ a function call, the body of the function is indented two spaces
+ from the left edge of the statement, or two spaces from the left
+ edge of the function keyword. This is to make the body of the
+ anonymous function easier to read (i.e. not be all squished up into
+ the right half of the screen).
Only one goog.scope invocation may be added per
+ file. Always place it in the global scope.
+
The opening goog.scope(function() { invocation
+ must be preceded by exactly one blank line and follow any
+ goog.provide statements, goog.require
+ statements, or top-level comments. The invocation must be closed on
+ the last line in the file. Append // goog.scope to the
+ closing statement of the scope. Separate the comment from the
+ semicolon by two spaces.
+
Similar to C++ namespaces, do not indent under goog.scope
+ declarations. Instead, continue from the 0 column.
+
Only alias names that will not be re-assigned to another object
+ (e.g., most constructors, enums, and namespaces). Do not do
+ this (see below for how to alias a constructor):
Names must be the same as the last property of the global that they
+ are aliasing.
+
+
goog.provide('my.module.SomeType');
+
+goog.require('goog.dom');
+goog.require('goog.ui.Button');
+
+goog.scope(function() {
+var Button = goog.ui.Button;
+var dom = goog.dom;
+
+// Alias new types after the constructor declaration.
+my.module.SomeType = function() { ... };
+var SomeType = my.module.SomeType;
+
+// Declare methods on the prototype as usual:
+SomeType.prototype.findButton = function() {
+ // Button as aliased above.
+ this.button = new Button(dom.getElement('my-button'));
+};
+...
+}); // goog.scope
+
+
+Indenting wrapped lines
+
Except for array literals,
+ object literals, and anonymous functions, all wrapped lines
+ should be indented either left-aligned to a sibling expression
+ above, or four spaces (not two spaces) deeper than a parent
+ expression (where "sibling" and "parent" refer to parenthesis
+ nesting level).
+
Always put the operator on the preceding line. Otherwise,
+ line breaks and indentation follow the same rules as in other
+ Google style guides. This operator placement was initially agreed
+ upon out of concerns about automatic semicolon insertion. In fact,
+ semicolon insertion cannot happen before a binary operator, but new
+ code should stick to this style for consistency.
+
var x = a ? b : c; // All on one line if it will fit.
+
+// Indentation +4 is OK.
+var y = a ?
+ longButSimpleOperandB : longButSimpleOperandC;
+
+// Indenting to the line position of the first operand is also OK.
+var z = a ?
+ moreComplicatedB :
+ moreComplicatedC;
+
This includes the dot operator.
+
var x = foo.bar().
+ doSomething().
+ doSomethingElse();
Use sparingly and in general only where required by the syntax
+ and semantics.
+
Never use parentheses for unary operators such as
+ delete, typeof and void or
+ after keywords such as return, throw as
+ well as others (case, in or
+ new).
Encouraged, use JSDoc annotations @private and
+ @protected
+
+
+
We recommend the use of the JSDoc annotations @private and
+ @protected to indicate visibility levels for classes,
+ functions, and properties.
+
The --jscomp_warning=visibility compiler flag turns on compiler
+ warnings for visibility violations. See
+
+ Closure Compiler
+ Warnings.
+
+
@private global variables and functions are only
+ accessible to code in the same file.
+
Constructors marked @private may only be instantiated by
+ code in the same file and by their static and instance members.
+ @private constructors may also be accessed anywhere in the
+ same file for their public static properties and by the
+ instanceof operator.
+
Global variables, functions, and constructors should never be
+ annotated @protected.
+
// File 1.
+// AA_PrivateClass_ and AA_init_ are accessible because they are global
+// and in the same file.
+
+/**
+ * @private
+ * @constructor
+ */
+AA_PrivateClass_ = function() {
+};
+
+/** @private */
+function AA_init_() {
+ return new AA_PrivateClass_();
+}
+
+AA_init_();
+
@private properties are accessible to all code in the
+ same file, plus all static methods and instance methods of that class
+ that "owns" the property, if the property belongs to a class. They
+ cannot be accessed or overridden from a subclass in a different file.
+
@protected properties are accessible to all code in the
+ same file, plus any static methods and instance methods of any subclass
+ of a class that "owns" the property.
+
Note that these semantics differ from those of C++ and Java, in that
+ they grant private and protected access to all code in the same file,
+ not just in the same class or class hierarchy. Also, unlike in C++,
+ private properties cannot be overridden by a subclass.
+
+
// File 1.
+
+/** @constructor */
+AA_PublicClass = function() {
+ /** @private */
+ this.privateProp_ = 2;
+
+ /** @protected */
+ this.protectedProp = 4;
+};
+
+/** @private */
+AA_PublicClass.staticPrivateProp_ = 1;
+
+/** @protected */
+AA_PublicClass.staticProtectedProp = 31;
+
+/** @private */
+AA_PublicClass.prototype.privateMethod_ = function() {};
+
+/** @protected */
+AA_PublicClass.prototype.protectedMethod = function() {};
+
+// File 2.
+
+/**
+ * @return {number} The number of ducks we've arranged in a row.
+ */
+AA_PublicClass.prototype.method = function() {
+ // Legal accesses of these two properties.
+ return this.privateProp_ + AA_PublicClass.staticPrivateProp_;
+};
+
+// File 3.
+
+/**
+ * @constructor
+ * @extends {AA_PublicClass}
+ */
+AA_SubClass = function() {
+ // Legal access of a protected static property.
+ AA_PublicClass.staticProtectedProp = this.method();
+};
+goog.inherits(AA_SubClass, AA_PublicClass);
+
+/**
+ * @return {number} The number of ducks we've arranged in a row.
+ */
+AA_SubClass.prototype.method = function() {
+ // Legal access of a protected instance property.
+ return this.protectedProp;
+};
+
+
Notice that in JavaScript, there is no distinction between a type
+ (like AA_PrivateClass_) and the constructor for that
+ type. There is no way to express both that a type is public and its
+ constructor is private (because the constructor could easily be aliased
+ in a way that would defeat the privacy check).
When documenting a type in JSDoc, be as specific and accurate as
+ possible. The types we support are based on the
+
+ EcmaScript 4 spec.
+
+The JavaScript Type Language
+
The ES4 proposal contained a language for specifying JavaScript
+ types. We use this language in JsDoc to express the types of
+ function parameters and return values.
+
+
As the ES4 proposal has evolved, this language has changed. The
+ compiler still supports old syntaxes for types, but those syntaxes
+ are deprecated.
+
+
+
+
+
+
Syntax Name
+
Syntax
+
Description
+
Deprecated Syntaxes
+
+
+
+
+
Primitive Type
+
+ There are 5 primitive types in JavaScript:
+ {null},
+ {undefined},
+ {boolean},
+ {number}, and
+ {string}.
+
+
Simply the name of a type.
+
+
+
+
+
Instance Type
+
+ {Object}
+ An instance of Object or null.
+ {Function}
+ An instance of Function or null.
+ {EventTarget}
+ An instance of a constructor that implements the EventTarget
+ interface, or null.
+
+
An instance of a constructor or interface function.
+
+ Constructor functions are functions defined with the
+ @constructor JSDoc tag.
+ Interface functions are functions defined with the
+ @interface JSDoc tag.
+
+ By default, instance types will accept null. This is the only
+ type syntax that makes the type nullable. Other type syntaxes
+ in this table will not accept null.
+
+
+
+
+
+
Enum Type
+
+ {goog.events.EventType}
+ One of the properties of the object literal initializer
+ of goog.events.EventType.
+
+
An enum must be initialized as an object literal, or as
+ an alias of another enum, annotated with the @enum
+ JSDoc tag. The properties of this literal are the instances
+ of the enum. The syntax of the enum is defined
+ below.
+
+ Note that this is one of the few things in our type system
+ that were not in the ES4 spec.
+
+
+
+
+
+
Type Application
+
+ {Array.<string>} An array of strings.
+ {Object.<string, number>}
+ An object in which the keys are strings and the values
+ are numbers.
+
+
Parameterizes a type, by applying a set of type arguments
+ to that type. The idea is analogous to generics in Java.
+
+
+
+
+
+
Type Union
+
+ {(number|boolean)} A number or a boolean.
+
+
Indicates that a value might have type A OR type B.
+
+ The parentheses may be omitted at the top-level
+ expression, but the parentheses should be included in
+ sub-expressions to avoid ambiguity.
+ {number|boolean}
+ {function(): (number|boolean)}
+
+
+ {(number,boolean)},
+ {(number||boolean)}
+
+
+
+
+
Nullable type
+
+ {?number} A number or null.
+
+
Shorthand for the union of the null type with any
+ other type. This is just syntactic sugar.
+
+
+ {number?}
+
+
+
+
+
Non-nullable type
+
+ {!Object} An Object, but never the
+ null value.
+
+
Filters null out of nullable types. Most often used
+ with instance types, which are nullable by default.
+
+
+ {Object!}
+
+
+
+
+
Record Type
+
+ {{myNum: number, myObject}}
+ An anonymous type with the given type members.
+
+
+
Indicates that the value has the specified members with the
+ specified types. In this case, myNum with a
+ type number and myObject with any
+ type.
+
Notice that the braces are part of the type syntax. For
+ example, to denote an Array of objects that
+ have a length property, you might write
+ Array.<{length}>.
+
+
+
+
+
+
Function Type
+
+ {function(string, boolean)}
+ A function that takes two arguments (a string and a boolean),
+ and has an unknown return value.
+
+
Specifies a function.
+
+
+
+
+
Function Return Type
+
+ {function(): number}
+ A function that takes no arguments and returns a number.
+
+
Specifies a function return type.
+
+
+
+
+
Function this Type
+
+ {function(this:goog.ui.Menu, string)}
+ A function that takes one argument (a string), and executes
+ in the context of a goog.ui.Menu.
+
+
Specifies the context type of a function type.
+
+
+
+
+
Function new Type
+
+ {function(new:goog.ui.Menu, string)}
+ A constructor that takes one argument (a string), and
+ creates a new instance of goog.ui.Menu when called
+ with the 'new' keyword.
+
+
Specifies the constructed type of a constructor.
+
+
+
+
+
Variable arguments
+
+ {function(string, ...[number]): number}
+ A function that takes one argument (a string), and then a
+ variable number of arguments that must be numbers.
+
+
Specifies variable arguments to a function.
+
+
+
+
+
+
+ Variable arguments (in @param annotations)
+
+
+ @param {...number} var_args
+ A variable number of arguments to an annotated function.
+
+
+ Specifies that the annotated function accepts a variable
+ number of arguments.
+
+ {function(?string=, number=)}
+ A function that takes one optional, nullable string and one
+ optional number as arguments. The = syntax is
+ only for function type declarations.
+
+ An Object in which the keys are numbers and the values are
+ strings. Note that in JavaScript, the keys are always
+ implicitly converted to strings, so
+ obj['1'] == obj[1].
+ So the key will always be a string in for...in loops. But the
+ compiler will verify the type of the key when indexing into
+ the object.
+
/** @enum {string} */
+project.MyEnum = {
+ /** The color blue. */
+ BLUE: '#0000dd',
+ /** The color red. */
+ RED: '#dd0000'
+};
+
+
+Enumeration
+ JSDoc comments on enum values are optional.
+
+
+
+
+
Element
+
+
document.createElement('div')
+
+
Elements in the DOM.
+
+
+
+
Node
+
+
document.body.firstChild
+
+
Nodes in the DOM.
+
+
+
+
HTMLInputElement
+
+
htmlDocument.getElementsByTagName('input')[0]
+
+
A specific type of DOM element.
+
+
+
+
+
+
+Type Casts
+
In cases where type-checking doesn't accurately infer the type of
+ an expression, it is possible to add a type cast comment by adding a
+ type annotation comment and enclosing the expression in
+ parentheses. The parentheses are required.
+
+
/** @type {number} */ (x)
+
+
+
+Nullable vs. Optional Parameters and Properties
+
+
Because JavaScript is a loosely-typed language, it is very
+ important to understand the subtle differences between optional,
+ nullable, and undefined function parameters and class
+ properties.
+
+
Instances of classes and interfaces are nullable by default.
+ For example, the following declaration
+
+
/**
+ * Some class, initialized with a value.
+ * @param {Object} value Some value.
+ * @constructor
+ */
+function MyClass(value) {
+ /**
+ * Some value.
+ * @type {Object}
+ * @private
+ */
+ this.myValue_ = value;
+}
+
+
tells the compiler that the myValue_ property holds
+ either an Object or null. If myValue_ must never be
+ null, it should be declared like this:
+
+
/**
+ * Some class, initialized with a non-null value.
+ * @param {!Object} value Some value.
+ * @constructor
+ */
+function MyClass(value) {
+ /**
+ * Some value.
+ * @type {!Object}
+ * @private
+ */
+ this.myValue_ = value;
+}
+
+
This way, if the compiler can determine that somewhere in the code
+ MyClass is initialized with a null value, it will issue
+ a warning.
+
+
+
+
Optional parameters to functions may be undefined at runtime, so if
+ they are assigned to class properties, those properties must be
+ declared accordingly:
+
+
/**
+ * Some class, initialized with an optional value.
+ * @param {Object=} opt_value Some value (optional).
+ * @constructor
+ */
+function MyClass(opt_value) {
+ /**
+ * Some value.
+ * @type {Object|undefined}
+ * @private
+ */
+ this.myValue_ = opt_value;
+}
+
+
This tells the compiler that myValue_ may hold an
+ Object, null, or remain undefined.
+
+
Note that the optional parameter opt_value is declared
+ to be of type {Object=}, not
+ {Object|undefined}. This is because optional
+ parameters may, by definition, be undefined. While there is no harm
+ in explicitly declaring an optional parameter as possibly undefined,
+ it is both unnecessary and makes the code harder to read.
+
+
Finally, note that being nullable and being optional are orthogonal
+ properties. The following four declarations are all different:
+
+
/**
+ * Takes four arguments, two of which are nullable, and two of which are
+ * optional.
+ * @param {!Object} nonNull Mandatory (must not be undefined), must not be null.
+ * @param {Object} mayBeNull Mandatory (must not be undefined), may be null.
+ * @param {!Object=} opt_nonNull Optional (may be undefined), but if present,
+ * must not be null!
+ * @param {Object=} opt_mayBeNull Optional (may be undefined), may be null.
+ */
+function strangeButTrue(nonNull, mayBeNull, opt_nonNull, opt_mayBeNull) {
+ // ...
+};
+
+
+
+Typedefs
+
+
Sometimes types can get complicated. A function that accepts
+ content for an Element might look like:
The compiler has limited support for template types. It can only
+ infer the type of this inside an anonymous function
+ literal from the type of the this argument and whether the
+ this argument is missing.
All files, classes, methods and properties should be documented with
+ JSDoc
+ comments with the appropriate tags
+ and types. Textual descriptions for properties,
+ methods, method parameters and method return values should be included
+ unless obvious from the property, method, or parameter name.
+
+
+
Inline comments should be of the // variety.
+
+
Complete sentences are recommended but not required.
+ Complete sentences should use appropriate capitalization
+ and punctuation.
+
+
+Comment Syntax
+
The JSDoc syntax is based on
+
+ JavaDoc. Many tools extract metadata from JSDoc comments to
+ perform code validation and optimizations. These comments must be
+ well-formed.
+
+
/**
+ * A JSDoc comment should begin with a slash and 2 asterisks.
+ * Inline tags should be enclosed in braces like {@code this}.
+ * @desc Block tags should always start on their own line.
+ */
+
+
+
+JSDoc Indentation
+
If you have to line break a block tag, you should treat this as
+ breaking a code statement and indent it four spaces.
+
+
/**
+ * Illustrates line wrapping for long param/return descriptions.
+ * @param {string} foo This is a param with a description too long to fit in
+ * one line.
+ * @return {number} This returns something that has a description too long to
+ * fit in one line.
+ */
+project.MyClass.prototype.method = function(foo) {
+ return 5;
+};
+
+
You should not indent the @fileoverview command. You do not have to
+ indent the @desc command.
+
+
Even though it is not preferred, it is also acceptable to line up
+ the description.
+
+
/**
+ * This is NOT the preferred indentation method.
+ * @param {string} foo This is a param with a description too long to fit in
+ * one line.
+ * @return {number} This returns something that has a description too long to
+ * fit in one line.
+ */
+project.MyClass.prototype.method = function(foo) {
+ return 5;
+};
+
+
+
+HTML in JSDoc
+
Like JavaDoc, JSDoc supports many HTML tags, like <code>,
+ <pre>, <tt>, <strong>, <ul>, <ol>,
+ <li>, <a>, and others.
+
+
This means that plaintext formatting is not respected. So, don't
+ rely on whitespace to format JSDoc:
+
+
/**
+ * Computes weight based on three factors:
+ * items sent
+ * items received
+ * last timestamp
+ */
+
+
It'll come out like this:
+
+
Computes weight based on three factors: items sent items received last timestamp
+
+
Instead, do this:
+
+
/**
+ * Computes weight based on three factors:
+ * <ul>
+ * <li>items sent
+ * <li>items received
+ * <li>last timestamp
+ * </ul>
+ */
+
+ The
+ JavaDoc style guide is a useful resource on how to write
+ well-formed doc comments.
+
+
+
+Top/File-Level Comments
+
+
+ A copyright notice and author information are optional.
+ File overviews are generally recommended whenever a file consists of
+ more than a single class definition. The top level comment is
+ designed to orient readers unfamiliar with the code to what is in
+ this file. If present, it should provide a description of the
+ file's contents and any dependencies or compatibility information.
+ As an example:
+
+
+
/**
+ * @fileoverview Description of file, its uses and information
+ * about its dependencies.
+ */
/**
+ * Class making something fun and easy.
+ * @param {string} arg1 An argument that makes this more interesting.
+ * @param {Array.<number>} arg2 List of numbers to be processed.
+ * @constructor
+ * @extends {goog.Disposable}
+ */
+project.MyClass = function(arg1, arg2) {
+ // ...
+};
+goog.inherits(project.MyClass, goog.Disposable);
+
+
+
+Method and Function Comments
+
Parameter and return types should be documented. The method
+ description may be omitted if it is obvious from the parameter
+ or return type descriptions. Method descriptions should start
+ with a sentence written in the third person declarative voice.
+
/**
+ * Operates on an instance of MyClass and returns something.
+ * @param {project.MyClass} obj Instance of MyClass which leads to a long
+ * comment that needs to be wrapped to two lines.
+ * @return {boolean} Whether something occurred.
+ */
+function PR_someMethod(obj) {
+ // ...
+}
+
+
+
+Property Comments
+
/** @constructor */
+project.MyClass = function() {
+ /**
+ * Maximum number of things per pane.
+ * @type {number}
+ */
+ this.someProperty = 4;
+}
/**
+ * Moves to the next position in the selection.
+ * Throws {@code goog.iter.StopIteration} when it
+ * passes the end of the range.
+ * @return {Node} The node at the next position.
+ */
+goog.dom.RangeIterator.prototype.next = function() {
+ // ...
+};
+
+
+ Indicates that a term in a JSDoc description is code so it may
+ be correctly formatted in generated documentation.
+
/** @const */ var MY_BEER = 'stout';
+
+/**
+ * My namespace's favorite kind of beer.
+ * @const {string}
+ */
+mynamespace.MY_BEER = 'stout';
+
+/** @const */ MyClass.MY_BEER = 'stout';
+
+/**
+ * Initializes the request.
+ * @const
+ */
+mynamespace.Request.prototype.initialize = function() {
+ // This method cannot be overridden in a subclass.
+};
+
+
+
Marks a variable (or property) as read-only and suitable
+ for inlining.
+
+
A @const variable is an immutable pointer to
+ a value. If a variable or property marked as
+ @const is overwritten, JSCompiler will give
+ warnings.
+
+
The type declaration of a constant value can be omitted
+ if it can be clearly inferred. An additional comment about
+ the variable is optional.
+
+
When @const is applied to a method, it
+ implies the method is not only not overwritable, but also
+ that the method is finalized —
+ not overridable in subclasses.
/** @define {boolean} */
+var TR_FLAGS_ENABLE_DEBUG = true;
+
+/**
+ * @define {boolean} Whether we know at compile-time that
+ * the browser is IE.
+ */
+goog.userAgent.ASSUME_IE = false;
+
+
+ Indicates a constant that can be overridden by the compiler at
+ compile-time. In the example, the compiler flag
+ --define='goog.userAgent.ASSUME_IE=true'
+ could be specified in the BUILD file to indicate that the
+ constant goog.userAgent.ASSUME_IE should be replaced
+ with true.
+
/**
+ * Determines whether a node is a field.
+ * @return {boolean} True if the contents of
+ * the element are editable, but the element
+ * itself is not.
+ * @deprecated Use isField().
+ */
+BN_EditUtil.isTopEditableField = function(node) {
+ // ...
+};
+
+
+ Used to tell that a function, method or property should not be
+ used any more. Always provide instructions on what callers
+ should use instead.
+
+ When a constructor (Foo in the example) is
+ annotated with @dict, you can only use the
+ bracket notation to access the properties of Foo
+ objects.
+ The annotation can also be used directly on object literals.
+
+ Declares an exposed property. Exposed properties
+ will not be removed, or renamed, or collapsed,
+ or optimized in any way by the compiler. No properties
+ with the same name will be able to be optimized either.
+
+
+
+ @expose should never be used in library code,
+ because it will prevent that property from ever getting
+ removed.
+
/**
+ * @fileoverview Utilities for doing things that require this very long
+ * but not indented comment.
+ * @author kuth@google.com (Uthur Pendragon)
+ */
+
+
Makes the comment block provide file level information.
+
+ Indicates that a method or property of a subclass
+ intentionally hides a method or property of the superclass,
+ and has exactly the same documentation. Notice that
+ @inheritDoc implies @override
+
+ Indicates that the keys of an object literal should
+ be treated as properties of some other object. This annotation
+ should only appear on object literals.
+
+ Notice that the name in braces is not a type name like
+ in other annotations. It's an object name. It names
+ the object on which the properties are "lent".
+ For example, @type {Foo} means "an instance of Foo",
+ but @lends {Foo} means "the constructor Foo".
+
+ The
+ JSDoc Toolkit docs have more information on this
+ annotation.
+
/**
+ * @preserve Copyright 2009 SomeThirdParty.
+ * Here is the full license text and copyright
+ * notice for this file. Note that the notice can span several
+ * lines and is only terminated by the closing star and slash:
+ */
+
+
+ Anything marked by @license or
+ @preserve will be retained by the compiler and
+ output at the top of the compiled code for that file. This
+ annotation allows important notices (such as legal licenses or
+ copyright text) to survive compilation unchanged. Line breaks
+ are preserved.
+
+ Used in an externs file to indicate to the compiler that the
+ variable or function should not be aliased as part of the
+ alias externals pass of the compiler.
+
+ Used at the top of a file to tell the compiler to parse this
+ file but not compile it.
+ Code that is not meant for compilation and should be omitted
+ from compilation tests (such as bootstrap code) uses this
+ annotation.
+ Use sparingly.
+
+ This annotation can be used as part of function and
+ constructor declarations to indicate that calls to the
+ declared function have no side-effects. This annotation
+ allows the compiler to remove calls to these functions if the
+ return value is not used.
+
+ Indicates that a method or property of a subclass
+ intentionally hides a method or property of the superclass. If
+ no other documentation is included, the method or property
+ also inherits documentation from its superclass.
+
/**
+ * Queries a Baz for items.
+ * @param {number} groupNum Subgroup id to query.
+ * @param {string|number|null} term An itemName,
+ * or itemId, or null to search everything.
+ */
+goog.Baz.prototype.query = function(groupNum, term) {
+ // ...
+};
+
+
+ Used with method, function and constructor calls to document
+ the arguments of a function.
+
+ Type
+ names must be enclosed in curly braces. If the type
+ is omitted, the compiler will not type-check the parameter.
+
/**
+ * Sets the component's root element to the given element.
+ * @param {Element} element Root element for the component.
+ * @protected
+ */
+goog.ui.Component.prototype.setElementInternal = function(element) {
+ // ...
+};
+
+
+ Used to indicate that the member or property is
+ protected.
+ Should be used in conjunction with names with no trailing
+ underscore.
+
/**
+ * Whether to cancel the event in internal capture/bubble processing.
+ * @public {boolean}
+ * @suppress {visibility} Referencing this outside this package is strongly
+ * discouraged.
+ */
+ goog.events.Event.prototype.propagationStopped_ = false;
+
+
+ Used to indicate that the member or property is public. Variables and
+ properties are public by default, so this annotation is rarely necessary.
+ Should only be used in legacy code that cannot be easily changed to
+ override the visibility of members that were named as private variables.
+
/**
+ * @return {string} The hex ID of the last item.
+ */
+goog.Baz.prototype.getLastId = function() {
+ // ...
+ return id;
+};
+
+
+ Used with method and function calls to document the return
+ type. When writing descriptions for boolean parameters,
+ prefer "Whether the component is visible" to "True if the
+ component is visible, false otherwise". If there is no return
+ value, do not use an @return tag.
+
+ Type
+ names must be enclosed in curly braces. If the type
+ is omitted, the compiler will not type-check the return value.
+
+ When a constructor (Foo in the example) is
+ annotated with @struct, you can only use the dot
+ notation to access the properties of Foo objects.
+ Also, you cannot add new properties to Foo
+ objects after they have been created.
+ The annotation can also be used directly on object literals.
+
/**
+ * @fileoverview Event Manager
+ * Provides an abstracted interface to the
+ * browsers' event systems.
+ * @supported So far tested in IE6 and FF1.5
+ */
+
+
+ Used in a fileoverview to indicate what browsers are supported
+ by the file.
+
+ The type of the object in whose context a particular method is
+ called. Required when the this keyword is referenced
+ from a function that is not a prototype method.
+
+ Identifies the type of a variable,
+ property, or expression. Curly braces are not required around
+ most types, but some projects mandate them for all types, for
+ consistency.
+
/** @typedef {(string|number)} */
+goog.NumberLike;
+
+/** @param {goog.NumberLike} x A number or a string. */
+goog.readNumber = function(x) {
+ ...
+}
+
+
+ This annotation can be used to declare an alias of a more
+ complex type.
+
+
+
+
+
+
+
+
+
+
+
+ You may also see other types of JSDoc annotations in third-party
+ code. These annotations appear in the
+
+ JSDoc Toolkit Tag Reference
+
+ but are currently discouraged in Google code. You should consider
+ them "reserved" names for future use. These include:
+
+ All members defined on a class should be in the same file. So, only
+ top-level classes should be provided in a file that contains multiple
+ members defined on the same class (e.g. enums, inner classes, etc).
+
Node lists are often implemented as node iterators with a filter.
+ This means that getting a property like length is O(n), and
+ iterating over the list by re-checking the length will be
+ O(n^2).
+
var paragraphs = document.getElementsByTagName('p');
+for (var i = 0; i < paragraphs.length; i++) {
+ doSomething(paragraphs[i]);
+}
+
+
It is better to do this instead:
+
var paragraphs = document.getElementsByTagName('p');
+for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) {
+ doSomething(paragraph);
+}
+
+
This works well for all collections and arrays as long as the array
+ does not contain things that are treated as boolean false.
+
+
In cases where you are iterating over the childNodes you can also
+ use the firstChild and nextSibling properties.
+ If you're editing code, take a few minutes to look at the code
+ around you and determine its style. If they use spaces around
+ all their arithmetic operators, you should too. If their
+ comments have little boxes of hash marks around them, make your
+ comments have little boxes of hash marks around them too.
+
+
+
+ The point of having style guidelines is to have a common vocabulary
+ of coding so people can concentrate on what you're saying rather
+ than on how you're saying it. We present global style rules here so
+ people know the vocabulary, but local style is also important. If
+ code you add to a file looks drastically different from the existing
+ code around it, it throws readers out of their rhythm when they go to
+ read it. Avoid this.
+
+
+
+
+
+ Revision 2.93
+
+
+
+
+ Aaron Whyte
+ Bob Jervis
+ Dan Pupius
+ Erik Arvidsson
+ Fritz Schneider
+ Robby Walker
+
+
+
diff --git a/javascriptguide.xml b/javascriptguide.xml
deleted file mode 100644
index 1106a83..0000000
--- a/javascriptguide.xml
+++ /dev/null
@@ -1,3630 +0,0 @@
-
-
-
-
- Please note: This guide is old and is not being updated. It is retained
- as a reference as it was written for pre-ECMAScript 6th Edition features.
- Please use the newer guide instead.
-
-
- Revision 2.93
-
-
-
- Aaron Whyte
- Bob Jervis
- Dan Pupius
- Erik Arvidsson
- Fritz Schneider
- Robby Walker
-
-
-
-
-
- This style guide contains many details that are initially
- hidden from view. They are marked by the triangle icon, which you
- see here on your left. Click it now.
- You should see "Hooray" appear below.
-
-
-
- Hooray! Now you know you can expand points to get more
- details. Alternatively, there's a "toggle all" at the
- top of this document.
-
-
-
-
-
-
- JavaScript is the main client-side scripting language used
-
- by many of Google's open-source
- projects.
- This style guide is a list of dos and don'ts for
- JavaScript programs.
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Declarations with var: Always
-
-
-
- When you fail to specify var,
- the variable gets placed in the global context, potentially clobbering
- existing values. Also, if there's no declaration, it's hard to tell in
- what scope a variable lives (e.g., it could be in the Document or
- Window just as easily as in the local scope). So always declare with
- var.
-
-
-
-
-
-
-
-
Use NAMES_LIKE_THIS for constant values.
-
Use @const to indicate a constant (non-overwritable)
- pointer (a variable or property).
-
Never use the
-
- const keyword
- as it's not supported in Internet Explorer.
-
-
-
-
-
-
-
If a value is intended to be constant
- and immutable, it should be given a name
- in CONSTANT_VALUE_CASE.
- ALL_CAPS additionally implies @const
- (that the value is not overwritable).
-
-
-
Primitive types (number, string,
- boolean) are constant values.
-
-
Objects'
- immutability is more subjective — objects should be
- considered immutable only if they do not demonstrate observable
- state change. This is not enforced by the compiler.
-
-
-
-
-
-
The @const annotation on a variable or property
- implies that it is not overwritable. This is enforced by the
- compiler at build time. This behavior is consistent with the
-
- const keyword (which we do not use due to the
- lack of support in Internet Explorer).
-
-
A @const annotation on a method additionally
- implies that the method cannot not be overridden in subclasses.
-
-
-
A @const annotation on a constructor implies the
- class cannot be subclassed (akin to final in Java).
-
-
-
-
-
-
-
Note that @const does not necessarily imply
- CONSTANT_VALUES_CASE.
-
- However, CONSTANT_VALUES_CASE
- does imply @const.
-
The number of seconds in a minute never changes. It is a
- constant value. ALL_CAPS
- also implies @const, so the constant cannot be
- overwritten.
-
-
-
The open source compiler will allow the symbol to be
- overwritten because the constant is
- not marked as @const.
-
-
- /**
- * Map of URL to response string.
- * @const
- */
- MyClass.fetchedUrlCache_ = new goog.structs.Map();
-
-
-
- /**
- * Class that cannot be subclassed.
- * @const
- * @constructor
- */
- sloth.MyFinalClass = function() {};
-
-
-
In this case, the pointer can never be overwritten, but
- value is highly mutable and not constant (and thus in
- camelCase, not ALL_CAPS).
-
-
-
-
-
-
-
-
- Always use semicolons.
-
-
-
Relying on implicit insertion can cause subtle, hard to debug
- problems. Don't do it. You're better than that.
-
There are a couple places where missing semicolons are particularly
- dangerous:
-
- // 1.
- MyClass.prototype.myMethod = function() {
- return 42;
- } // No semicolon here.
-
- (function() {
- // Some initialization code wrapped in a function to create a scope for locals.
- })();
-
-
- var x = {
- 'i': 1,
- 'j': 2
- } // No semicolon here.
-
- // 2. Trying to do one thing on Internet Explorer and another on Firefox.
- // I know you'd never write code like this, but throw me a bone.
- [ffVersion, ieVersion][isIE]();
-
-
- var THINGS_TO_EAT = [apples, oysters, sprayOnCheese] // No semicolon here.
-
- // 3. conditional execution a la bash
- -1 == resultOfOperation() || die();
-
-
-
-
JavaScript error - first the function returning 42 is called
- with the second function as a parameter, then the number 42 is
- "called" resulting in an error.
-
You will most likely get a 'no such property in undefined'
- error at runtime as it tries to call
- x[ffVersion, ieVersion][isIE]().
-
die is always called since the array minus 1 is
- NaN which is never equal to anything (not even if
- resultOfOperation() returns NaN) and
- THINGS_TO_EAT gets assigned the result of
- die().
-
-
-
-
JavaScript requires statements to end with a semicolon, except when
- it thinks it can safely infer their existence. In each of these
- examples, a function declaration or object or array literal is used
- inside a statement. The closing brackets are not enough to signal
- the end of the statement. Javascript never ends a statement if the
- next token is an infix or bracket operator.
-
This has really surprised people, so make sure your assignments end
- with semicolons.
-
-
-
Semicolons should be included at the end of function expressions,
- but not at the end of function declarations. The distinction is
- best illustrated with an example:
Nested functions can be very useful, for example in the creation of
- continuations and for the task of hiding helper functions. Feel free
- to use them.
-
-
-
-
- No
-
-
Do not do this:
-
- if (x) {
- function foo() {}
- }
-
-
-
While most script engines support Function Declarations within blocks
- it is not part of ECMAScript (see
- ECMA-262,
- clause 13 and 14). Worse implementations are inconsistent with each
- other and with future EcmaScript proposals. ECMAScript only allows for
- Function Declarations in the root statement list of a script or
- function. Instead use a variable initialized with a Function
- Expression to define a function within a block:
You basically can't avoid exceptions if you're doing something
- non-trivial (using an application development framework, etc.).
- Go for it.
-
-
-
-
- Yes
-
-
Without custom exceptions, returning error information from a
- function that also returns a value can be tricky, not to mention
- inelegant. Bad solutions include passing in a reference type to hold
- error information or always returning Objects with a potential
- error member. These basically amount to a primitive exception
- handling hack. Feel free to use custom exceptions when
- appropriate.
-
-
-
-
- Always preferred over non-standards features
-
-
For maximum portability and compatibility, always prefer standards
- features over non-standards features (e.g.,
- string.charAt(3) over string[3] and element
- access with DOM functions instead of using an application-specific
- shorthand).
-
-
-
-
- No
-
-
There's no reason to use wrapper objects for primitive types, plus
- they're dangerous:
-
- var x = new Boolean(false);
- if (x) {
- alert('hi'); // Shows 'hi'.
- }
-
-
Don't do it!
-
However type casting is fine.
-
- var x = Boolean(0);
- if (x) {
- alert('hi'); // This will never be alerted.
- }
- typeof Boolean(0) == 'boolean';
- typeof new Boolean(0) == 'object';
-
-
This is very useful for casting things to
- number, string and boolean.
-
-
-
-
- Not preferred
-
-
Multi-level prototype hierarchies are how JavaScript implements
- inheritance. You have a multi-level hierarchy if you have a
- user-defined class D with another user-defined class B as its
- prototype. These hierarchies are much harder to get right than they
- first appear!
-
-
For that reason, it is best to use goog.inherits() from
-
- the Closure Library
-
- or a similar library function.
-
In modern JavaScript engines, changing the number of properties on an
- object is much slower than reassigning the values. The delete keyword
- should be avoided except when it is necessary to remove a property
- from an object's iterated list of keys, or to change the result of
- if (key in obj).
One thing to keep in mind, however, is that a closure keeps a pointer
- to its enclosing scope. As a result, attaching a closure to a DOM
- element can create a circular reference and thus, a memory leak. For
- example, in the following code:
-
- function foo(element, a, b) {
- element.onclick = function() { /* uses a and b */ };
- }
-
-
the function closure keeps a reference to element,
- a, and b even if it never uses
- element. Since element also keeps a
- reference to the closure, we have a cycle that won't be cleaned up by
- garbage collection. In these situations, the code can be structured
- as follows:
-
- function foo(element, a, b) {
- element.onclick = bar(a, b);
- }
-
- function bar(a, b) {
- return function() { /* uses a and b */ };
- }
-
-
-
-
-
-
- Only for code loaders and REPL (Read–eval–print loop)
-
-
-
eval() makes for confusing semantics and is dangerous
- to use if the string being eval()'d contains user input.
- There's usually a better, clearer, and safer way to write your code,
- so its use is generally not permitted.
-
-
For RPC you can always use JSON and read the result using
- JSON.parse() instead of eval().
-
-
Let's assume we have a server that returns something like this:
If the feed was modified to include malicious JavaScript code, then
- if we use eval then that code will be executed.
-
-
- var userInfo = JSON.parse(feed);
- var email = userInfo['email'];
-
-
-
With JSON.parse, invalid JSON (including all executable
- JavaScript) will cause an exception to be thrown.
-
-
-
-
-
- No
-
-
Using with clouds the semantics of your program.
- Because the object of the with can have properties that
- collide with local variables, it can drastically change the meaning
- of your program. For example, what does this do?
-
- with (foo) {
- var x = 3;
- return x;
- }
-
-
Answer: anything. The local variable x could be
- clobbered by a property of foo and perhaps it even has
- a setter, in which case assigning 3 could cause lots of
- other code to execute. Don't use with.
-
-
-
-
-
- Only in object constructors, methods, and in setting up closures
-
-
-
The semantics of this can be tricky. At times it refers
- to the global object (in most places), the scope of the caller (in
- eval), a node in the DOM tree (when attached using an
- event handler HTML attribute), a newly created object (in a
- constructor), or some other object (if function was
- call()ed or apply()ed).
-
Because this is so easy to get wrong, limit its use to those places
- where it is required:
-
-
in constructors
-
in methods of objects (including in the creation of closures)
-
-
-
-
-
-
- Only for iterating over keys in an object/map/hash
-
-
-
for-in loops are often incorrectly used to loop over
- the elements in an Array. This is however very error
- prone because it does not loop from 0 to
- length - 1 but over all the present keys in the object
- and its prototype chain. Here are a few cases where it fails:
-
- function printArray(arr) {
- for (var key in arr) {
- print(arr[key]);
- }
- }
-
- printArray([0,1,2,3]); // This works.
-
- var a = new Array(10);
- printArray(a); // This is wrong.
-
- a = document.getElementsByTagName('*');
- printArray(a); // This is wrong.
-
- a = [0,1,2,3];
- a.buhu = 'wine';
- printArray(a); // This is wrong again.
-
- a = new Array;
- a[3] = 3;
- printArray(a); // This is wrong again.
-
-
Always use normal for loops when using arrays.
-
- function printArray(arr) {
- var l = arr.length;
- for (var i = 0; i < l; i++) {
- print(arr[i]);
- }
- }
-
-
-
-
-
-
- Never use Array as a map/hash/associative array
-
-
-
Associative Arrays are not allowed... or more precisely
- you are not allowed to use non number indexes for arrays. If you need
- a map/hash use Object instead of Array in
- these cases because the features that you want are actually features
- of Object and not of Array.
- Array just happens to extend Object (like
- any other object in JS and therefore you might as well have used
- Date, RegExp or String).
-
-
-
-
- No
-
-
Do not do this:
-
- var myString = 'A rather long string of English text, an error message \
- actually that just keeps going and going -- an error \
- message to make the Energizer bunny blush (right through \
- those Schwarzenegger shades)! Where was I? Oh yes, \
- you\'ve got an error and all the extraneous whitespace is \
- just gravy. Have a nice day.';
-
-
The whitespace at the beginning of each line can't be safely stripped
- at compile time; whitespace after the slash will result in tricky
- errors.
-
Use string concatenation instead:
-
- var myString = 'A rather long string of English text, an error message ' +
- 'actually that just keeps going and going -- an error ' +
- 'message to make the Energizer bunny blush (right through ' +
- 'those Schwarzenegger shades)! Where was I? Oh yes, ' +
- 'you\'ve got an error and all the extraneous whitespace is ' +
- 'just gravy. Have a nice day.';
-
-
-
-
-
- Yes
-
-
Use Array and Object literals instead of
- Array and Object constructors.
-
Array constructors are error-prone due to their arguments.
-
- // Length is 3.
- var a1 = new Array(x1, x2, x3);
-
- // Length is 2.
- var a2 = new Array(x1, x2);
-
- // If x1 is a number and it is a natural number the length will be x1.
- // If x1 is a number but not a natural number this will throw an exception.
- // Otherwise the array will have one element with x1 as its value.
- var a3 = new Array(x1);
-
- // Length is 0.
- var a4 = new Array();
-
-
Because of this, if someone changes the code to pass 1 argument
- instead of 2 arguments, the array might not have the expected
- length.
-
To avoid these kinds of weird cases, always use the more readable
- array literal.
-
- var a = [x1, x2, x3];
- var a2 = [x1, x2];
- var a3 = [x1];
- var a4 = [];
-
-
Object constructors don't have the same problems, but for readability
- and consistency object literals should be used.
-
- var o = new Object();
-
- var o2 = new Object();
- o2.a = 0;
- o2.b = 1;
- o2.c = 2;
- o2['strange key'] = 3;
-
-
Should be written as:
-
- var o = {};
-
- var o2 = {
- a: 0,
- b: 1,
- c: 2,
- 'strange key': 3
- };
-
-
-
-
-
- No
-
-
Modifying builtins like Object.prototype and
- Array.prototype are strictly forbidden. Modifying other
- builtins like Function.prototype is less dangerous but
- still leads to hard to debug issues in production and should be
- avoided.
-
-
-
-
- No
-
-
Don't do this:
-
- var f = function () {
- /*@cc_on if (@_jscript) { return 2* @*/ 3; /*@ } @*/
- };
-
-
Conditional Comments hinder automated tools as they can vary the
- JavaScript syntax tree at runtime.
-
-
-
-
-
-
-
-
In general, use
- functionNamesLikeThis,
- variableNamesLikeThis,
- ClassNamesLikeThis,
- EnumNamesLikeThis,
- methodNamesLikeThis,
- CONSTANT_VALUES_LIKE_THIS,
- foo.namespaceNamesLikeThis.bar, and
- filenameslikethis.js.
-
-
-
-
-
-
Private properties and methods should be named with a
- trailing underscore.
-
-
Protected properties and methods should be
- named without a trailing underscore (like public ones).
-
-
For more information on private and protected,
- read the section on
-
- visibility.
-
-
-
-
-
-
-
-
-
Optional function arguments start with opt_.
-
Functions that take a variable number of arguments should have the
- last argument named var_args. You may not refer to
- var_args in the code; use the arguments
- array.
-
Optional and variable arguments can also be specified in
- @param annotations. Although either convention is
- acceptable to the compiler, using both together is preferred.
-
-
-
-
-
EcmaScript 5 getters and setters for properties are discouraged.
- However, if they are used, then getters must not change observable
- state.
-
- /**
- * WRONG -- Do NOT do this.
- */
- var foo = { get next() { return this.nextId++; } };
-
-
-
-
-
Getters and setters methods for properties are not required.
- However, if they are used, then getters must be named
- getFoo() and setters must be named
- setFoo(value). (For boolean getters,
- isFoo() is also acceptable, and often sounds more
- natural.)
-
-
-
-
JavaScript has no inherent packaging or namespacing support.
-
Global name conflicts are difficult to debug, and can cause
- intractable problems when two projects try to integrate. In order
- to make it possible to share common JavaScript code, we've adopted
- conventions to prevent collisions.
-
-
ALWAYS prefix identifiers in the global scope with a
- unique pseudo namespace related to the project or library. If you
- are working on "Project Sloth", a reasonable pseudo namespace
- would be sloth.*.
Many JavaScript libraries, including
-
- the Closure Library
-
- and
-
- Dojo toolkit
-
- give you high-level functions for declaring your namespaces.
- Be consistent about how you declare your namespaces.
When choosing a child-namespace, make sure that the owners of the
- parent namespace know what you are doing. If you start a project
- that creates hats for sloths, make sure that the Sloth team knows
- that you're using sloth.hats.
-
-
-
-
"External code" is code that comes from outside your codebase,
- and is compiled independently. Internal and external names should
- be kept strictly separate. If you're using an external library
- that makes things available in foo.hats.*, your
- internal code should not define all its symbols in
- foo.hats.*, because it will break if the other
- team defines new symbols.
If you need to define new APIs on an external namespace, then you
- should explicitly export the public API functions, and only those
- functions. Your internal code should call the internal APIs by
- their internal names, for consistency and so that the compiler
- can optimize them better.
Never create aliases in the global scope. Use them only in
- function blocks.
-
-
-
-
Filenames should be all lowercase in order to avoid confusion on
- case-sensitive platforms. Filenames should end in .js,
- and should contain no punctuation except for - or
- _ (prefer - to _).
-
-
-
-
-
-
-
- Must always succeed without side effects.
-
-
-
You can control how your objects string-ify themselves by defining a
- custom toString() method. This is fine, but you need
- to ensure that your method (1) always succeeds and (2) does not have
- side-effects. If your method doesn't meet these criteria, it's very
- easy to run into serious problems. For example, if
- toString() calls a method that does an
- assert, assert might try to output the name
- of the object in which it failed, which of course requires calling
- toString().
-
-
-
-
- OK
-
-
It isn't always possible to initialize variables at the point of
- declaration, so deferred initialization is fine.
-
-
-
-
- Always
-
-
Always use explicit scope - doing so increases portability and
- clarity. For example, don't rely on window being in the
- scope chain. You might want to use your function in another
- application for which window is not the content
- window.
-
-
-
-
- Expand for more information.
-
-
We follow the C++ formatting
- rules in spirit, with the following additional clarifications.
-
-
Because of implicit semicolon insertion, always start your curly
- braces on the same line as whatever they're opening. For
- example:
When possible, all function arguments should be listed on the same
- line. If doing so would exceed the 80-column limit, the arguments
- must be line-wrapped in a readable way. To save space, you may wrap
- as close to 80 as possible, or put each argument on its own line to
- enhance readability. The indentation may be either four spaces, or
- aligned to the parenthesis. Below are the most common patterns for
- argument wrapping:
-
- // Four-space, wrap at 80. Works with very long function names, survives
- // renaming without reindenting, low on space.
- goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
- veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
- tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
- // ...
- };
-
- // Four-space, one argument per line. Works with long function names,
- // survives renaming, and emphasizes each argument.
- goog.foo.bar.doThingThatIsVeryDifficultToExplain = function(
- veryDescriptiveArgumentNumberOne,
- veryDescriptiveArgumentTwo,
- tableModelEventHandlerProxy,
- artichokeDescriptorAdapterIterator) {
- // ...
- };
-
- // Parenthesis-aligned indentation, wrap at 80. Visually groups arguments,
- // low on space.
- function foo(veryDescriptiveArgumentNumberOne, veryDescriptiveArgumentTwo,
- tableModelEventHandlerProxy, artichokeDescriptorAdapterIterator) {
- // ...
- }
-
- // Parenthesis-aligned, one argument per line. Emphasizes each
- // individual argument.
- function bar(veryDescriptiveArgumentNumberOne,
- veryDescriptiveArgumentTwo,
- tableModelEventHandlerProxy,
- artichokeDescriptorAdapterIterator) {
- // ...
- }
-
-
When the function call is itself indented, you're free to start the
- 4-space indent relative to the beginning of the original statement
- or relative to the beginning of the current function call.
- The following are all acceptable indentation styles.
When declaring an anonymous function in the list of arguments for
- a function call, the body of the function is indented two spaces
- from the left edge of the statement, or two spaces from the left
- edge of the function keyword. This is to make the body of the
- anonymous function easier to read (i.e. not be all squished up into
- the right half of the screen).
Only one goog.scope invocation may be added per
- file. Always place it in the global scope.
-
The opening goog.scope(function() { invocation
- must be preceded by exactly one blank line and follow any
- goog.provide statements, goog.require
- statements, or top-level comments. The invocation must be closed on
- the last line in the file. Append // goog.scope to the
- closing statement of the scope. Separate the comment from the
- semicolon by two spaces.
-
Similar to C++ namespaces, do not indent under goog.scope
- declarations. Instead, continue from the 0 column.
-
Only alias names that will not be re-assigned to another object
- (e.g., most constructors, enums, and namespaces). Do not do
- this (see below for how to alias a constructor):
Names must be the same as the last property of the global that they
- are aliasing.
-
-
- goog.provide('my.module.SomeType');
-
- goog.require('goog.dom');
- goog.require('goog.ui.Button');
-
- goog.scope(function() {
- var Button = goog.ui.Button;
- var dom = goog.dom;
-
- // Alias new types after the constructor declaration.
- my.module.SomeType = function() { ... };
- var SomeType = my.module.SomeType;
-
- // Declare methods on the prototype as usual:
- SomeType.prototype.findButton = function() {
- // Button as aliased above.
- this.button = new Button(dom.getElement('my-button'));
- };
- ...
- }); // goog.scope
-
-
-
-
Except for array literals,
- object literals, and anonymous functions, all wrapped lines
- should be indented either left-aligned to a sibling expression
- above, or four spaces (not two spaces) deeper than a parent
- expression (where "sibling" and "parent" refer to parenthesis
- nesting level).
-
Always put the operator on the preceding line. Otherwise,
- line breaks and indentation follow the same rules as in other
- Google style guides. This operator placement was initially agreed
- upon out of concerns about automatic semicolon insertion. In fact,
- semicolon insertion cannot happen before a binary operator, but new
- code should stick to this style for consistency.
-
- var x = a ? b : c; // All on one line if it will fit.
-
- // Indentation +4 is OK.
- var y = a ?
- longButSimpleOperandB : longButSimpleOperandC;
-
- // Indenting to the line position of the first operand is also OK.
- var z = a ?
- moreComplicatedB :
- moreComplicatedC;
-
-
This includes the dot operator.
-
- var x = foo.bar().
- doSomething().
- doSomethingElse();
-
-
-
-
-
-
- Only where required
-
-
Use sparingly and in general only where required by the syntax
- and semantics.
-
Never use parentheses for unary operators such as
- delete, typeof and void or
- after keywords such as return, throw as
- well as others (case, in or
- new).
-
-
-
-
- Prefer ' over "
-
-
For consistency single-quotes (') are preferred to double-quotes (").
- This is helpful when creating strings that include HTML:
-
- var msg = 'This is some HTML';
-
-
-
-
-
- Encouraged, use JSDoc annotations @private and
- @protected
-
-
We recommend the use of the JSDoc annotations @private and
- @protected to indicate visibility levels for classes,
- functions, and properties.
-
The --jscomp_warning=visibility compiler flag turns on compiler
- warnings for visibility violations. See
-
- Closure Compiler
- Warnings.
-
-
@private global variables and functions are only
- accessible to code in the same file.
-
Constructors marked @private may only be instantiated by
- code in the same file and by their static and instance members.
- @private constructors may also be accessed anywhere in the
- same file for their public static properties and by the
- instanceof operator.
-
Global variables, functions, and constructors should never be
- annotated @protected.
-
- // File 1.
- // AA_PrivateClass_ and AA_init_ are accessible because they are global
- // and in the same file.
-
- /**
- * @private
- * @constructor
- */
- AA_PrivateClass_ = function() {
- };
-
- /** @private */
- function AA_init_() {
- return new AA_PrivateClass_();
- }
-
- AA_init_();
-
-
@private properties are accessible to all code in the
- same file, plus all static methods and instance methods of that class
- that "owns" the property, if the property belongs to a class. They
- cannot be accessed or overridden from a subclass in a different file.
-
@protected properties are accessible to all code in the
- same file, plus any static methods and instance methods of any subclass
- of a class that "owns" the property.
-
Note that these semantics differ from those of C++ and Java, in that
- they grant private and protected access to all code in the same file,
- not just in the same class or class hierarchy. Also, unlike in C++,
- private properties cannot be overridden by a subclass.
-
Notice that in JavaScript, there is no distinction between a type
- (like AA_PrivateClass_) and the constructor for that
- type. There is no way to express both that a type is public and its
- constructor is private (because the constructor could easily be aliased
- in a way that would defeat the privacy check).
-
-
-
-
- Encouraged and enforced by the compiler.
-
-
-
When documenting a type in JSDoc, be as specific and accurate as
- possible. The types we support are based on the
-
- EcmaScript 4 spec.
-
-
The ES4 proposal contained a language for specifying JavaScript
- types. We use this language in JsDoc to express the types of
- function parameters and return values.
-
-
As the ES4 proposal has evolved, this language has changed. The
- compiler still supports old syntaxes for types, but those syntaxes
- are deprecated.
-
-
-
-
-
-
Syntax Name
-
Syntax
-
Description
-
Deprecated Syntaxes
-
-
-
-
-
Primitive Type
-
- There are 5 primitive types in JavaScript:
- {null},
- {undefined},
- {boolean},
- {number}, and
- {string}.
-
-
Simply the name of a type.
-
-
-
-
-
Instance Type
-
- {Object}
- An instance of Object or null.
- {Function}
- An instance of Function or null.
- {EventTarget}
- An instance of a constructor that implements the EventTarget
- interface, or null.
-
-
An instance of a constructor or interface function.
-
- Constructor functions are functions defined with the
- @constructor JSDoc tag.
- Interface functions are functions defined with the
- @interface JSDoc tag.
-
- By default, instance types will accept null. This is the only
- type syntax that makes the type nullable. Other type syntaxes
- in this table will not accept null.
-
-
-
-
-
-
Enum Type
-
- {goog.events.EventType}
- One of the properties of the object literal initializer
- of goog.events.EventType.
-
-
An enum must be initialized as an object literal, or as
- an alias of another enum, annotated with the @enum
- JSDoc tag. The properties of this literal are the instances
- of the enum. The syntax of the enum is defined
- below.
-
- Note that this is one of the few things in our type system
- that were not in the ES4 spec.
-
-
-
-
-
-
Type Application
-
- {Array.<string>} An array of strings.
- {Object.<string, number>}
- An object in which the keys are strings and the values
- are numbers.
-
-
Parameterizes a type, by applying a set of type arguments
- to that type. The idea is analogous to generics in Java.
-
-
-
-
-
-
Type Union
-
- {(number|boolean)} A number or a boolean.
-
-
Indicates that a value might have type A OR type B.
-
- The parentheses may be omitted at the top-level
- expression, but the parentheses should be included in
- sub-expressions to avoid ambiguity.
- {number|boolean}
- {function(): (number|boolean)}
-
-
- {(number,boolean)},
- {(number||boolean)}
-
-
-
-
-
Nullable type
-
- {?number} A number or null.
-
-
Shorthand for the union of the null type with any
- other type. This is just syntactic sugar.
-
-
- {number?}
-
-
-
-
-
Non-nullable type
-
- {!Object} An Object, but never the
- null value.
-
-
Filters null out of nullable types. Most often used
- with instance types, which are nullable by default.
-
-
- {Object!}
-
-
-
-
-
Record Type
-
- {{myNum: number, myObject}}
- An anonymous type with the given type members.
-
-
-
Indicates that the value has the specified members with the
- specified types. In this case, myNum with a
- type number and myObject with any
- type.
-
Notice that the braces are part of the type syntax. For
- example, to denote an Array of objects that
- have a length property, you might write
- Array.<{length}>.
-
-
-
-
-
-
Function Type
-
- {function(string, boolean)}
- A function that takes two arguments (a string and a boolean),
- and has an unknown return value.
-
-
Specifies a function.
-
-
-
-
-
Function Return Type
-
- {function(): number}
- A function that takes no arguments and returns a number.
-
-
Specifies a function return type.
-
-
-
-
-
Function this Type
-
- {function(this:goog.ui.Menu, string)}
- A function that takes one argument (a string), and executes
- in the context of a goog.ui.Menu.
-
-
Specifies the context type of a function type.
-
-
-
-
-
Function new Type
-
- {function(new:goog.ui.Menu, string)}
- A constructor that takes one argument (a string), and
- creates a new instance of goog.ui.Menu when called
- with the 'new' keyword.
-
-
Specifies the constructed type of a constructor.
-
-
-
-
-
Variable arguments
-
- {function(string, ...[number]): number}
- A function that takes one argument (a string), and then a
- variable number of arguments that must be numbers.
-
-
Specifies variable arguments to a function.
-
-
-
-
-
-
- Variable arguments (in @param annotations)
-
-
- @param {...number} var_args
- A variable number of arguments to an annotated function.
-
-
- Specifies that the annotated function accepts a variable
- number of arguments.
-
- {function(?string=, number=)}
- A function that takes one optional, nullable string and one
- optional number as arguments. The = syntax is
- only for function type declarations.
-
- An Object in which the keys are numbers and the values are
- strings. Note that in JavaScript, the keys are always
- implicitly converted to strings, so
- obj['1'] == obj[1].
- So the key will always be a string in for...in loops. But the
- compiler will verify the type of the key when indexing into
- the object.
-
In cases where type-checking doesn't accurately infer the type of
- an expression, it is possible to add a type cast comment by adding a
- type annotation comment and enclosing the expression in
- parentheses. The parentheses are required.
-
-
- /** @type {number} */ (x)
-
-
-
-
-
-
Because JavaScript is a loosely-typed language, it is very
- important to understand the subtle differences between optional,
- nullable, and undefined function parameters and class
- properties.
-
-
Instances of classes and interfaces are nullable by default.
- For example, the following declaration
-
-
- /**
- * Some class, initialized with a value.
- * @param {Object} value Some value.
- * @constructor
- */
- function MyClass(value) {
- /**
- * Some value.
- * @type {Object}
- * @private
- */
- this.myValue_ = value;
- }
-
-
-
tells the compiler that the myValue_ property holds
- either an Object or null. If myValue_ must never be
- null, it should be declared like this:
-
-
- /**
- * Some class, initialized with a non-null value.
- * @param {!Object} value Some value.
- * @constructor
- */
- function MyClass(value) {
- /**
- * Some value.
- * @type {!Object}
- * @private
- */
- this.myValue_ = value;
- }
-
-
-
This way, if the compiler can determine that somewhere in the code
- MyClass is initialized with a null value, it will issue
- a warning.
-
-
-
-
Optional parameters to functions may be undefined at runtime, so if
- they are assigned to class properties, those properties must be
- declared accordingly:
-
-
- /**
- * Some class, initialized with an optional value.
- * @param {Object=} opt_value Some value (optional).
- * @constructor
- */
- function MyClass(opt_value) {
- /**
- * Some value.
- * @type {Object|undefined}
- * @private
- */
- this.myValue_ = opt_value;
- }
-
-
-
This tells the compiler that myValue_ may hold an
- Object, null, or remain undefined.
-
-
Note that the optional parameter opt_value is declared
- to be of type {Object=}, not
- {Object|undefined}. This is because optional
- parameters may, by definition, be undefined. While there is no harm
- in explicitly declaring an optional parameter as possibly undefined,
- it is both unnecessary and makes the code harder to read.
-
-
Finally, note that being nullable and being optional are orthogonal
- properties. The following four declarations are all different:
-
-
- /**
- * Takes four arguments, two of which are nullable, and two of which are
- * optional.
- * @param {!Object} nonNull Mandatory (must not be undefined), must not be null.
- * @param {Object} mayBeNull Mandatory (must not be undefined), may be null.
- * @param {!Object=} opt_nonNull Optional (may be undefined), but if present,
- * must not be null!
- * @param {Object=} opt_mayBeNull Optional (may be undefined), may be null.
- */
- function strangeButTrue(nonNull, mayBeNull, opt_nonNull, opt_mayBeNull) {
- // ...
- };
-
-
-
-
-
-
Sometimes types can get complicated. A function that accepts
- content for an Element might look like:
The compiler has limited support for template types. It can only
- infer the type of this inside an anonymous function
- literal from the type of the this argument and whether the
- this argument is missing.
All files, classes, methods and properties should be documented with
- JSDoc
- comments with the appropriate tags
- and types. Textual descriptions for properties,
- methods, method parameters and method return values should be included
- unless obvious from the property, method, or parameter name.
-
-
-
Inline comments should be of the // variety.
-
-
Complete sentences are recommended but not required.
- Complete sentences should use appropriate capitalization
- and punctuation.
-
-
-
The JSDoc syntax is based on
-
- JavaDoc. Many tools extract metadata from JSDoc comments to
- perform code validation and optimizations. These comments must be
- well-formed.
-
-
- /**
- * A JSDoc comment should begin with a slash and 2 asterisks.
- * Inline tags should be enclosed in braces like {@code this}.
- * @desc Block tags should always start on their own line.
- */
-
-
-
-
-
If you have to line break a block tag, you should treat this as
- breaking a code statement and indent it four spaces.
-
-
- /**
- * Illustrates line wrapping for long param/return descriptions.
- * @param {string} foo This is a param with a description too long to fit in
- * one line.
- * @return {number} This returns something that has a description too long to
- * fit in one line.
- */
- project.MyClass.prototype.method = function(foo) {
- return 5;
- };
-
-
-
You should not indent the @fileoverview command. You do not have to
- indent the @desc command.
-
-
Even though it is not preferred, it is also acceptable to line up
- the description.
-
-
- /**
- * This is NOT the preferred indentation method.
- * @param {string} foo This is a param with a description too long to fit in
- * one line.
- * @return {number} This returns something that has a description too long to
- * fit in one line.
- */
- project.MyClass.prototype.method = function(foo) {
- return 5;
- };
-
-
-
-
-
Like JavaDoc, JSDoc supports many HTML tags, like <code>,
- <pre>, <tt>, <strong>, <ul>, <ol>,
- <li>, <a>, and others.
-
-
This means that plaintext formatting is not respected. So, don't
- rely on whitespace to format JSDoc:
-
-
- /**
- * Computes weight based on three factors:
- * items sent
- * items received
- * last timestamp
- */
-
-
-
It'll come out like this:
-
-
- Computes weight based on three factors: items sent items received last timestamp
-
-
-
Instead, do this:
-
-
- /**
- * Computes weight based on three factors:
- * <ul>
- * <li>items sent
- * <li>items received
- * <li>last timestamp
- * </ul>
- */
-
-
- The
- JavaDoc style guide is a useful resource on how to write
- well-formed doc comments.
-
-
-
-
-
- A copyright notice and author information are optional.
- File overviews are generally recommended whenever a file consists of
- more than a single class definition. The top level comment is
- designed to orient readers unfamiliar with the code to what is in
- this file. If present, it should provide a description of the
- file's contents and any dependencies or compatibility information.
- As an example:
-
-
-
- /**
- * @fileoverview Description of file, its uses and information
- * about its dependencies.
- */
-
-
-
-
-
-
-
-
-
- /**
- * Class making something fun and easy.
- * @param {string} arg1 An argument that makes this more interesting.
- * @param {Array.<number>} arg2 List of numbers to be processed.
- * @constructor
- * @extends {goog.Disposable}
- */
- project.MyClass = function(arg1, arg2) {
- // ...
- };
- goog.inherits(project.MyClass, goog.Disposable);
-
-
-
-
-
Parameter and return types should be documented. The method
- description may be omitted if it is obvious from the parameter
- or return type descriptions. Method descriptions should start
- with a sentence written in the third person declarative voice.
-
- /**
- * Operates on an instance of MyClass and returns something.
- * @param {project.MyClass} obj Instance of MyClass which leads to a long
- * comment that needs to be wrapped to two lines.
- * @return {boolean} Whether something occurred.
- */
- function PR_someMethod(obj) {
- // ...
- }
-
-
-
-
-
- /** @constructor */
- project.MyClass = function() {
- /**
- * Maximum number of things per pane.
- * @type {number}
- */
- this.someProperty = 4;
- }
-
-
-
-
-
-
-
-
- /**
- * Moves to the next position in the selection.
- * Throws {@code goog.iter.StopIteration} when it
- * passes the end of the range.
- * @return {Node} The node at the next position.
- */
- goog.dom.RangeIterator.prototype.next = function() {
- // ...
- };
-
-
-
- Indicates that a term in a JSDoc description is code so it may
- be correctly formatted in generated documentation.
-
-
- /** @const */ var MY_BEER = 'stout';
-
- /**
- * My namespace's favorite kind of beer.
- * @const {string}
- */
- mynamespace.MY_BEER = 'stout';
-
- /** @const */ MyClass.MY_BEER = 'stout';
-
- /**
- * Initializes the request.
- * @const
- */
- mynamespace.Request.prototype.initialize = function() {
- // This method cannot be overridden in a subclass.
- };
-
-
-
-
Marks a variable (or property) as read-only and suitable
- for inlining.
-
-
A @const variable is an immutable pointer to
- a value. If a variable or property marked as
- @const is overwritten, JSCompiler will give
- warnings.
-
-
The type declaration of a constant value can be omitted
- if it can be clearly inferred. An additional comment about
- the variable is optional.
-
-
When @const is applied to a method, it
- implies the method is not only not overwritable, but also
- that the method is finalized —
- not overridable in subclasses.
-
- /** @define {boolean} */
- var TR_FLAGS_ENABLE_DEBUG = true;
-
- /**
- * @define {boolean} Whether we know at compile-time that
- * the browser is IE.
- */
- goog.userAgent.ASSUME_IE = false;
-
-
-
- Indicates a constant that can be overridden by the compiler at
- compile-time. In the example, the compiler flag
- --define='goog.userAgent.ASSUME_IE=true'
- could be specified in the BUILD file to indicate that the
- constant goog.userAgent.ASSUME_IE should be replaced
- with true.
-
-
- /**
- * Determines whether a node is a field.
- * @return {boolean} True if the contents of
- * the element are editable, but the element
- * itself is not.
- * @deprecated Use isField().
- */
- BN_EditUtil.isTopEditableField = function(node) {
- // ...
- };
-
-
-
- Used to tell that a function, method or property should not be
- used any more. Always provide instructions on what callers
- should use instead.
-
-
- /**
- * @constructor
- * @dict
- */
- function Foo(x) {
- this['x'] = x;
- }
- var obj = new Foo(123);
- var num = obj.x; // warning
-
- (/** @dict */ { x: 1 }).x = 123; // warning
-
-
-
- When a constructor (Foo in the example) is
- annotated with @dict, you can only use the
- bracket notation to access the properties of Foo
- objects.
- The annotation can also be used directly on object literals.
-
- Declares an exposed property. Exposed properties
- will not be removed, or renamed, or collapsed,
- or optimized in any way by the compiler. No properties
- with the same name will be able to be optimized either.
-
-
-
- @expose should never be used in library code,
- because it will prevent that property from ever getting
- removed.
-
-
- /**
- * @fileoverview Utilities for doing things that require this very long
- * but not indented comment.
- * @author kuth@google.com (Uthur Pendragon)
- */
-
-
-
Makes the comment block provide file level information.
-
- Indicates that a method or property of a subclass
- intentionally hides a method or property of the superclass,
- and has exactly the same documentation. Notice that
- @inheritDoc implies @override
-
- Indicates that the keys of an object literal should
- be treated as properties of some other object. This annotation
- should only appear on object literals.
-
- Notice that the name in braces is not a type name like
- in other annotations. It's an object name. It names
- the object on which the properties are "lent".
- For example, @type {Foo} means "an instance of Foo",
- but @lends {Foo} means "the constructor Foo".
-
- The
- JSDoc Toolkit docs have more information on this
- annotation.
-
-
- /**
- * @preserve Copyright 2009 SomeThirdParty.
- * Here is the full license text and copyright
- * notice for this file. Note that the notice can span several
- * lines and is only terminated by the closing star and slash:
- */
-
-
-
- Anything marked by @license or
- @preserve will be retained by the compiler and
- output at the top of the compiled code for that file. This
- annotation allows important notices (such as legal licenses or
- copyright text) to survive compilation unchanged. Line breaks
- are preserved.
-
- Used in an externs file to indicate to the compiler that the
- variable or function should not be aliased as part of the
- alias externals pass of the compiler.
-
- Used at the top of a file to tell the compiler to parse this
- file but not compile it.
- Code that is not meant for compilation and should be omitted
- from compilation tests (such as bootstrap code) uses this
- annotation.
- Use sparingly.
-
- This annotation can be used as part of function and
- constructor declarations to indicate that calls to the
- declared function have no side-effects. This annotation
- allows the compiler to remove calls to these functions if the
- return value is not used.
-
- Indicates that a method or property of a subclass
- intentionally hides a method or property of the superclass. If
- no other documentation is included, the method or property
- also inherits documentation from its superclass.
-
-
- /**
- * Queries a Baz for items.
- * @param {number} groupNum Subgroup id to query.
- * @param {string|number|null} term An itemName,
- * or itemId, or null to search everything.
- */
- goog.Baz.prototype.query = function(groupNum, term) {
- // ...
- };
-
-
-
- Used with method, function and constructor calls to document
- the arguments of a function.
-
- Type
- names must be enclosed in curly braces. If the type
- is omitted, the compiler will not type-check the parameter.
-
-
- /**
- * Sets the component's root element to the given element.
- * @param {Element} element Root element for the component.
- * @protected
- */
- goog.ui.Component.prototype.setElementInternal = function(element) {
- // ...
- };
-
-
-
- Used to indicate that the member or property is
- protected.
- Should be used in conjunction with names with no trailing
- underscore.
-
-
- /**
- * Whether to cancel the event in internal capture/bubble processing.
- * @public {boolean}
- * @suppress {visibility} Referencing this outside this package is strongly
- * discouraged.
- */
- goog.events.Event.prototype.propagationStopped_ = false;
-
-
-
- Used to indicate that the member or property is public. Variables and
- properties are public by default, so this annotation is rarely necessary.
- Should only be used in legacy code that cannot be easily changed to
- override the visibility of members that were named as private variables.
-
-
- /**
- * @return {string} The hex ID of the last item.
- */
- goog.Baz.prototype.getLastId = function() {
- // ...
- return id;
- };
-
-
-
- Used with method and function calls to document the return
- type. When writing descriptions for boolean parameters,
- prefer "Whether the component is visible" to "True if the
- component is visible, false otherwise". If there is no return
- value, do not use an @return tag.
-
- Type
- names must be enclosed in curly braces. If the type
- is omitted, the compiler will not type-check the return value.
-
- When a constructor (Foo in the example) is
- annotated with @struct, you can only use the dot
- notation to access the properties of Foo objects.
- Also, you cannot add new properties to Foo
- objects after they have been created.
- The annotation can also be used directly on object literals.
-
-
- /**
- * @fileoverview Event Manager
- * Provides an abstracted interface to the
- * browsers' event systems.
- * @supported So far tested in IE6 and FF1.5
- */
-
-
-
- Used in a fileoverview to indicate what browsers are supported
- by the file.
-
- The type of the object in whose context a particular method is
- called. Required when the this keyword is referenced
- from a function that is not a prototype method.
-
- Identifies the type of a variable,
- property, or expression. Curly braces are not required around
- most types, but some projects mandate them for all types, for
- consistency.
-
-
- /** @typedef {(string|number)} */
- goog.NumberLike;
-
- /** @param {goog.NumberLike} x A number or a string. */
- goog.readNumber = function(x) {
- ...
- }
-
-
-
- This annotation can be used to declare an alias of a more
- complex type.
-
-
-
-
-
-
-
-
-
-
-
- You may also see other types of JSDoc annotations in third-party
- code. These annotations appear in the
-
- JSDoc Toolkit Tag Reference
-
- but are currently discouraged in Google code. You should consider
- them "reserved" names for future use. These include:
-
-
@augments
-
@argument
-
@borrows
-
@class
-
@constant
-
@constructs
-
@default
-
@event
-
@example
-
@field
-
@function
-
@ignore
-
@inner
-
@link
-
@memberOf
-
@name
-
@namespace
-
@property
-
@public
-
@requires
-
@returns
-
@since
-
@static
-
@version
-
-
-
-
-
-
-
-
- Only provide top-level symbols.
-
-
-
- All members defined on a class should be in the same file. So, only
- top-level classes should be provided in a file that contains multiple
- members defined on the same class (e.g. enums, inner classes, etc).
-
Node lists are often implemented as node iterators with a filter.
- This means that getting a property like length is O(n), and
- iterating over the list by re-checking the length will be
- O(n^2).
-
- var paragraphs = document.getElementsByTagName('p');
- for (var i = 0; i < paragraphs.length; i++) {
- doSomething(paragraphs[i]);
- }
-
-
-
It is better to do this instead:
-
- var paragraphs = document.getElementsByTagName('p');
- for (var i = 0, paragraph; paragraph = paragraphs[i]; i++) {
- doSomething(paragraph);
- }
-
-
-
This works well for all collections and arrays as long as the array
- does not contain things that are treated as boolean false.
-
-
In cases where you are iterating over the childNodes you can also
- use the firstChild and nextSibling properties.
- If you're editing code, take a few minutes to look at the code
- around you and determine its style. If they use spaces around
- all their arithmetic operators, you should too. If their
- comments have little boxes of hash marks around them, make your
- comments have little boxes of hash marks around them too.
-
-
-
- The point of having style guidelines is to have a common vocabulary
- of coding so people can concentrate on what you're saying rather
- than on how you're saying it. We present global style rules here so
- people know the vocabulary, but local style is also important. If
- code you add to a file looks drastically different from the existing
- code around it, it throws readers out of their rhythm when they go to
- read it. Avoid this.
-
-
-
-
-
- Revision 2.93
-
-
-
-
- Aaron Whyte
- Bob Jervis
- Dan Pupius
- Erik Arvidsson
- Fritz Schneider
- Robby Walker
-
-
diff --git a/lispguide.xml b/lispguide.html
similarity index 67%
rename from lispguide.xml
rename to lispguide.html
index d4f3841..e1a3d23 100644
--- a/lispguide.xml
+++ b/lispguide.html
@@ -1,6 +1,139 @@
-
-
-
+
+
+Google Common Lisp Style Guide
+
+
+
+
+
+
+
Google Common Lisp Style Guide
@@ -25,24 +158,101 @@ Robert Brown
-
-
-
-
+
+
+ Each style point has a summary for which additional information is available
+ by toggling the accompanying arrow button that looks this way:
+ ▶.
+ You may toggle all summaries with the big arrow button:
+
This style guide contains many details
that are initially hidden from view.
They are marked by the triangle icon, which you see here on your left.
Click it now. You should see "Hooray" appear below.
-
-
+
+
Hooray! Now you know you can expand points to get more details.
Alternatively, there's an "expand all" at the top of this document.
-
-
-
-
+
+
+
+
+
Background
Common Lisp is a powerful multiparadigm programming language.
With great power comes great responsibility.
@@ -78,16 +288,21 @@ Robert Brown
a look at Peter Norvig and Kent Pitman's
style guide.
There are cases where transgression of some of these rules
is useful or even necessary.
In some cases, you must seek permission or obtain forgiveness
from the proper people.
-
-
+
+
Permission comes from the owners of your project.
@@ -171,13 +390,17 @@ Robert Brown
the reviewer should add a signed approval to the comment at review time.
-
-
-
-
+
You MUST follow conventions. They are not optional.
-
-
+
+
Some of these guidelines are motivated by universal principles of good programming.
Some guidelines are motivated by technical peculiarities of Common Lisp.
@@ -209,13 +432,17 @@ Robert Brown
so you know when best to defy conventions for good effect,
and when not to fall into the pitfalls that the conventions are there to help avoid.
A lot of our code was written before these guidelines existed.
You should fix violations as you encounter them
@@ -227,15 +454,19 @@ Robert Brown
so as not to make the merging of large branches
more difficult than it already is.
There are some basic principles for team software development
that every developer must keep in mind.
Whenever the detailed guidelines are inadequate, confusing or contradictory,
@@ -342,12 +578,16 @@ Robert Brown
someone has to do to understand an area of code.
-
-
-
-
-
-
+
When making decisions about how to write a given piece of
code, aim for the following -ilities in this priority order:
@@ -369,8 +609,8 @@ Robert Brown
Efficiency (of the Lisp code at runtime)
-
-
+
+
Most of these are obvious.
@@ -396,10 +636,14 @@ Robert Brown
Don't add complexity to speed up something that runs rarely,
since in the long run, it matters less whether such code is fast.
-
-
-
-
+
To build code that is robust and maintainable,
it matters a lot how the code is divided into components,
how these components communicate,
@@ -407,8 +651,8 @@ Robert Brown
and more importantly
how the programmers who develop these components communicate
as these components evolve.
-
-
+
+
If your work affects other groups, might be reusable across groups,
adds new components, has an impact on other groups
@@ -422,16 +666,20 @@ Robert Brown
If you don't know or don't care about these issues,
ask someone who does.
Often, the smallest hammer is to use an existing library.
Or one that doesn't exist yet.
In such cases, you are encouraged to use or develop such a library,
but you must take appropriate precautions.
-
-
+
+
You MUST NOT start a new library
@@ -458,10 +706,14 @@ Robert Brown
If you write a general-purpose library,
or modify an existing open-source library,
@@ -470,8 +722,8 @@ Robert Brown
have your project import it like any other open-source library.
-
-
+
+
Use your judgment to distinguish
general-purpose versus business-specific code,
@@ -491,15 +743,19 @@ Robert Brown
is not directly usable by third parties.
Development process is outside the scope of this document.
However, developers should remember at least these bits:
get reviewed, write tests, eliminate warnings, run tests, avoid mass-changes.
-
-
+
+
@@ -553,12 +809,17 @@ Robert Brown
and give branch residents time to get back on the mainline
You must use correct spelling in your comments,
and most importantly in your identifiers.
@@ -574,8 +835,8 @@ Robert Brown
lexical variables of limited scope in order to avoid overly-long
symbol names.
-
-
+
+
If you're not sure, consult a dictionary,
Google for alternative spellings,
@@ -643,13 +904,17 @@ Robert Brown
-
-
-
-
+
You should format source code so that no line is longer than 100 characters.
-
-
+
+
Some line length restriction is better than none at all.
While old text terminals used to make 80 columns the standard,
@@ -658,10 +923,14 @@ Robert Brown
descriptive variables and function names.
Indent your code the way a properly configured GNU Emacs does.
@@ -671,8 +940,8 @@ Robert Brown
Indent carefully to make the code easier to understand.
-
-
+
+
Common Lisp indentation in Emacs is provided by the cl-indent library.
The latest version of cl-indent is packaged with
@@ -707,31 +976,31 @@ Robert Brown
how many arguments the function takes
or where an argument form starts and ends.
You should include a description at the top of each source file.
You should include neither authorship nor copyright information in a source file.
-
-
+
+
Every source file should begin with a brief description
of the contents of that file.
@@ -746,12 +1015,10 @@ Robert Brown
(declaim (optimize ...)) declaration
that is not covered by an ASDF:around-compile hook.
-
- ;;;; Variable length encoding for integers and floating point numbers.
+
;;;; Variable length encoding for integers and floating point numbers.
- (in-package #:varint)
- (declaim #.*optimize-default*)
-
+(in-package #:varint)
+(declaim #.*optimize-default*)
You should not include authorship information at the top of a file:
better information is available from version control,
@@ -767,13 +1034,17 @@ Robert Brown
Vertical white space: one blank line between top-level forms.
-
-
+
+
You should include one blank line between top-level forms,
such as function definitions.
@@ -781,20 +1052,18 @@ Robert Brown
between simple, closely related defining forms of the same kind,
such as a group of related type declarations or constant definitions.
-
- (defconstant +mix32+ #x12b9b0a1 "pi, an arbitrary number")
- (defconstant +mix64+ #x2b992ddfa23249d6 "more digits of pi")
+
(defconstant +mix32+ #x12b9b0a1 "pi, an arbitrary number")
+(defconstant +mix64+ #x2b992ddfa23249d6 "more digits of pi")
- (defconstant +golden-ratio32+ #x9e3779b9 "the golden ratio")
- (defconstant +golden-ratio64+ #xe08c1d668b756f82 "more digits of the golden ratio")
+(defconstant +golden-ratio32+ #x9e3779b9 "the golden ratio")
+(defconstant +golden-ratio64+ #xe08c1d668b756f82 "more digits of the golden ratio")
- (defmacro incf32 (x y)
- "Like INCF, but for integers modulo 2**32"
- `(setf ,x (logand (+ ,x ,y) #xffffffff)))
- (defmacro incf64 (x y)
- "Like INCF, but for integers modulo 2**64"
- `(setf ,x (logand (+ ,x ,y) #xffffffffffffffff)))
-
+(defmacro incf32 (x y)
+ "Like INCF, but for integers modulo 2**32"
+ `(setf ,x (logand (+ ,x ,y) #xffffffff)))
+(defmacro incf64 (x y)
+ "Like INCF, but for integers modulo 2**64"
+ `(setf ,x (logand (+ ,x ,y) #xffffffffffffffff)))
Blank lines can be used to separate parts of a complicated function.
Generally, however, you should break a large function into smaller ones
@@ -812,13 +1081,17 @@ Robert Brown
Additionally, defpackage forms may be longer,
since they may include long lists of symbols.
Horizontal white space: none around parentheses. No tabs.
-
-
+
+
You must not include extra horizontal whitespace
before or after parentheses or around symbols.
@@ -827,24 +1100,20 @@ Robert Brown
You must not place right parentheses by themselves on a line.
A set of consecutive trailing parentheses must appear on the same line.
-
- ;; Very Bad
- ( defun factorial ( limit )
- ( let (( product 1 ))
- ( loop for i from 1 upto limit
- do (setf product ( * product i ) ) )
- product
- )
- )
-
-
- ;; Better
- (defun factorial (limit)
- (let ((product 1))
- (loop for i from 1 upto limit
- do (setf product (* product i)))
- product))
-
+
;; Very Bad
+( defun factorial ( limit )
+ ( let (( product 1 ))
+ ( loop for i from 1 upto limit
+ do (setf product ( * product i ) ) )
+ product
+ )
+)
+
;; Better
+(defun factorial (limit)
+ (let ((product 1))
+ (loop for i from 1 upto limit
+ do (setf product (* product i)))
+ product))
You should use only one space between forms.
@@ -855,35 +1124,27 @@ Robert Brown
an important yet otherwise not visible symmetry
that you want to emphasize.
-
- ;; Bad
- (let* ((low 1)
- (high 2)
- (sum (+ (* low low) (* high high))))
- ...)
-
-
- ;; Better
- (let* ((low 1)
- (high 2)
- (sum (+ (* low low) (* high high))))
- ...))
-
+
;; Bad
+(let* ((low 1)
+ (high 2)
+ (sum (+ (* low low) (* high high))))
+ ...)
You must align nested forms if they occur across more than one line.
-
- ;; Bad
- (defun munge (a b c)
- (* (+ a b)
- c))
-
-
- ;; Better
- (defun munge (a b c)
- (* (+ a b)
- c))
-
+
;; Bad
+(defun munge (a b c)
+(* (+ a b)
+c))
+
;; Better
+(defun munge (a b c)
+ (* (+ a b)
+ c))
The convention is that the body of a binding form
is indented two spaces after the form.
@@ -892,13 +1153,11 @@ Robert Brown
if the first argument is on its own line,
it is aligned with the function name.
-
- (multiple-value-bind (a b c d)
- (function-returning-four-values x y)
- (declare (ignore c))
- (something-using a)
- (also-using b d))
-
+
(multiple-value-bind (a b c d)
+ (function-returning-four-values x y)
+ (declare (ignore c))
+ (something-using a)
+ (also-using b d))
An exception to the rule against lonely parentheses
is made for an eval-when form around several definitions;
@@ -912,17 +1171,22 @@ Robert Brown
on how many spaces they represent.
In Emacs, do (setq-default indent-tabs-mode nil).
You should use document strings on all visible functions
to explain how to use your code.
-
-
+
+
Unless some bit of code is painfully self-explanatory,
document it with a documentation string (also known as docstring).
@@ -958,25 +1222,21 @@ Robert Brown
such as function arguments.
For example, "The value of LENGTH should be an integer."
-
- (defun small-prime-number-p (n)
- "Return T if N, an integer, is a prime number. Otherwise, return NIL."
- (cond ((or (< n 2))
- nil)
- ((= n 2)
- t)
- ((divisorp 2 n)
- nil)
- (t
- (loop for i from 3 upto (sqrt n) by 2
- never (divisorp i n)))))
-
-
- (defgeneric table-clear (table)
- (:documentation
- "Like clrhash, empties the TABLE of all
- associations, and returns the table itself."))
-
+
(defun small-prime-number-p (n)
+ "Return T if N, an integer, is a prime number. Otherwise, return NIL."
+ (cond ((or (< n 2))
+ nil)
+ ((= n 2)
+ t)
+ ((divisorp 2 n)
+ nil)
+ (t
+ (loop for i from 3 upto (sqrt n) by 2
+ never (divisorp i n)))))
+
(defgeneric table-clear (table)
+ (:documentation
+ "Like clrhash, empties the TABLE of all
+ associations, and returns the table itself."))
A long docstring may usefully
begin with a short, single-sentence summary,
@@ -987,15 +1247,13 @@ Robert Brown
the symbol may be quoted by surrounding it with
a back quote at the beginning and a single quote at the end.
Emacs will highlight the type, and the highlighting serves
- as a cue to the reader that M-.
+ as a cue to the reader that M-.
will lead to the symbol's definition.
-
- (defun bag-tag-expected-itinerary (bag-tag)
- "Return a list of `legacy-pnr-pax-segment' objects representing
- the expected itinerary of the `bag-tag' object, BAG-TAG."
- ...)
-
+
(defun bag-tag-expected-itinerary (bag-tag)
+ "Return a list of `legacy-pnr-pax-segment' objects representing
+ the expected itinerary of the `bag-tag' object, BAG-TAG."
+ ...)
Every method of a generic function should be independently documented
when the specialization affects what the method does,
@@ -1008,13 +1266,17 @@ Robert Brown
the reason for the code in terms of fixing the bug.
Adding the bug number, if any, is also recommended.
You must use the appropriate number of semicolons to introduce comments.
-
-
+
+
Comments are explanations to the future maintainers of the code.
Even if you're the only person who will ever see and touch the code,
@@ -1061,63 +1323,69 @@ Robert Brown
consecutive related end-of-line comments.
-
- ;;;; project-euler.lisp
- ;;;; File-level comments or comments for large sections of code.
+
;;;; project-euler.lisp
+;;;; File-level comments or comments for large sections of code.
- ;;; Problems are described in more detail here: https://projecteuler.net/
+;;; Problems are described in more detail here: https://projecteuler.net/
- ;;; Divisibility
- ;;; Comments that describe a group of definitions.
+;;; Divisibility
+;;; Comments that describe a group of definitions.
- (defun divisorp (d n)
- (zerop (mod n d)))
+(defun divisorp (d n)
+ (zerop (mod n d)))
- (defun proper-divisors (n)
- ...)
+(defun proper-divisors (n)
+ ...)
- (defun divisors (n)
- (cons n (proper-divisors n)))
+(defun divisors (n)
+ (cons n (proper-divisors n)))
- ;;; Prime numbers
+;;; Prime numbers
- (defun small-prime-number-p (n)
- (cond ((or (< n 2))
- nil)
- ((= n 2) ; parenthetical remark here
- t) ; continuation of the remark
- ((divisorp 2 n)
- nil) ; different remark
- ;; Comment that applies to a section of code.
- (t
- (loop for i from 3 upto (sqrt n) by 2
- never (divisorp i n)))))
-
+(defun small-prime-number-p (n)
+ (cond ((or (< n 2))
+ nil)
+ ((= n 2) ; parenthetical remark here
+ t) ; continuation of the remark
+ ((divisorp 2 n)
+ nil) ; different remark
+ ;; Comment that applies to a section of code.
+ (t
+ (loop for i from 3 upto (sqrt n) by 2
+ never (divisorp i n)))))
You should include a space between the semicolon and the text of the comment.
You should punctuate documentation correctly.
-
-
+
+
When a comment is a full sentence,
you should capitalize the initial letter of the first word
and end the comment with a period.
In general, you should use correct punctuation.
You must follow the convention of using TODO comments
for code requiring special attention.
For code using unobvious forms, you must include a comment.
-
-
+
+
For comments requiring special attention, such as
incomplete code, todo items, questions, breakage, and danger,
@@ -1147,9 +1415,7 @@ Robert Brown
not just initials.
-
- ;;--- TODO(george@gmail.com): Refactor to provide a better API.
-
+
;;--- TODO(george@gmail.com): Refactor to provide a better API.
Be specific when indicating times or software releases
in a TODO comment and use
@@ -1157,21 +1423,23 @@ Robert Brown
format for dates to make automated processing of such dates easier,
e.g., 2038-01-20 for the end of the 32-bit signed time_t.
-
- ;;--- TODO(brown): Remove this code after release 1.7 or before 2012-11-30.
-
+
;;--- TODO(brown): Remove this code after release 1.7 or before 2012-11-30.
For code that uses unobvious forms to accomplish a task, you must include a comment
stating the purpose of the form and the task it accomplishes.
You should document DSLs and
any terse program in a DSL.
-
-
+
+
You should design your Domain Specific Language
to be easy to read and understand by people familiar with the domain.
@@ -1195,19 +1463,24 @@ Robert Brown
it should be possible for someone to follow the logic of the code
without actually parsing the regular expression.
You should use lower case.
You should follow the rules for Spelling and Abbreviations
You should follow punctuation conventions.
-
-
+
+
Use lower case for all symbols.
Consistently using lower case makes searching for symbol names easier
@@ -1241,16 +1514,12 @@ Robert Brown
See the section on Spelling and Abbreviations
for guidelines on using abbreviations.
There are conventions in Common Lisp
for the use of punctuation in symbols.
@@ -1261,14 +1530,18 @@ Robert Brown
do not use overly short names like
i and zq.
Name your variables according to their intent,
not their content.
-
-
+
+
You should name a variable according
to the high-level concept that it represents,
@@ -1312,13 +1585,17 @@ Robert Brown
then call it row rather than, say, value
(this was a real case).
The names of global constants should start and end
with plus characters.
@@ -1347,18 +1624,20 @@ Robert Brown
You should not use this trick,
unless you first publish a library that abstracts it away.
Names of predicate functions and variables end with a "P".
-
-
+
+
You should name boolean-valued functions and variables with a
trailing "P" or "-P",
@@ -1386,14 +1665,18 @@ Robert Brown
you should not use such an alternative rule
without a very good documented reason.
You should not include a library or package name
as a prefix within the name of symbols.
-
-
+
+
When naming a symbol (external or internal) in a package,
you should not include the package name
@@ -1405,22 +1688,18 @@ Robert Brown
(once as a package prefix,
another time as a prefix within the symbol name).
An exception to the above rule would be to include a prefix
for the names of variables that would otherwise be expected to clash
@@ -1429,13 +1708,17 @@ Robert Brown
that controls the verbosity of ASDF only,
rather than of the entire Lisp program.
Common Lisp systems are not required to implement
function calls from tail positions without leaking stack space
@@ -1618,13 +1910,17 @@ Robert Brown
with appropriate optimization settings.
For fully portable code, you may have to use trampolines instead.
Using Lisp "special" (dynamically bound) variables
as implicit arguments to functions should be used sparingly,
@@ -1688,13 +1984,17 @@ Robert Brown
to automate the appropriate declaration of such variables.
There are several styles for dealing with assignment and side-effects;
whichever a given package is using,
@@ -1734,13 +2034,17 @@ Robert Brown
which makes testing and maintenance easier,
we invite you to consider how to do things with the fewest assignments required.
You must make proper usage of assertions and conditions.
-
-
+
+
ASSERT should be used ONLY to detect internal bugs.
@@ -1856,32 +2160,32 @@ Robert Brown
the stack trace will halt at the point of the resignal,
hiding the rest.
And the rest is the part we really care about!
-
- ;; Bad
- (handler-case
- (catch 'ticket-at
- (etd-process-blocks))
- (error (c)
- (reset-parser-values)
- (error c)))
-
-
- ;; Better
- (unwind-protect
- (catch 'ticket-at
- (etd-process-blocks))
- (reset-parser-values))
-
+
If you know the type of something, you should make it explicit
in order to enable compile-time and run-time sanity-checking.
-
-
+
+
If your function is using a special variable as an implicit argument,
@@ -1923,13 +2227,17 @@ Robert Brown
When you do, however, see our recommendations for
Unsafe Operations.
Use macros when appropriate, which is often.
Define macros when appropriate, which is seldom.
-
-
+
+
Macros bring syntactic abstraction, which is a wonderful thing.
It helps make your code clearer, by describing your intent
@@ -2299,14 +2610,18 @@ Robert Brown
you can add them without necessarily having to change
all the uses of the macro.
You should use #. sparingly,
and you must avoid read-time side-effects.
-
-
+
+
The #. standard read-macro
will read one object, evaluate the object, and
@@ -2416,13 +2735,17 @@ Robert Brown
possibly in an EVAL-WHEN,
to give the value a name explaining what it means.
Places where it is actually appropriate to use EVAL
are so few and far between that you must consult with your reviewers;
@@ -2490,13 +2813,17 @@ Robert Brown
ASDF-FINALIZERS ensures that the form is present,
by throwing an error if you omit it.
You must not use INTERN or UNINTERN at runtime.
-
-
+
+
You must not use INTERN at runtime.
Not only does it cons,
@@ -2510,12 +2837,8 @@ Robert Brown
just to compare it to a keyword;
use STRING= or STRING-EQUAL.
You must not use UNINTERN at runtime.
It can break code that relies on dynamic binding.
@@ -2533,16 +2856,21 @@ Robert Brown
to create the symbols you need.
You must select proper data representation.
You must not abuse the LIST data structure.
-
-
+
+
Even though back in 1958, LISP was short for "LISt Processing",
its successor Common Lisp has been a modern programming language
@@ -2659,13 +2991,17 @@ Robert Brown
Using Libraries and
Open-Sourcing Code.
You should use the appropriate representation for product types.
-
-
+
+
You should avoid using a list as anything
besides a container of elements of like type.
@@ -2703,13 +3039,17 @@ Robert Brown
You should signal a condition to denote an unusual outcome,
rather than relying on a special return type.
Use the appropriate functions when manipulating lists.
-
-
+
+
Use FIRST to access the first element of a list,
SECOND to access the second element, etc.
@@ -2737,13 +3077,17 @@ Robert Brown
to use higher-level constructs such as
DESTRUCTURING-BIND or OPTIMA:MATCH.
You should use arrays rather than lists where random access matters.
-
-
+
+
ELT has O(n) behavior when used on lists.
If you are to use random element access on an object,
@@ -2753,13 +3097,17 @@ Robert Brown
The exception is for code outside the critical path
where the list is known to be small anyway.
You should only use lists as sets for very small lists.
-
-
+
+
Using lists as representations of sets is a bad idea
unless you know the lists will be small,
@@ -2771,31 +3119,32 @@ Robert Brown
If you still use lists as sets,
you should not UNION lists just to search them.
You must use proper defining forms for constant values.
-
-
+
+
The Lisp system we primarily use, SBCL, is very picky and
signals a condition whenever a constant is redefined to a value not
@@ -2806,11 +3155,9 @@ Robert Brown
Instead, consistently use whichever alternative
is recommended for your project.
-
- ;; Bad
- (defconstant +google-url+ "https://www.google.com/")
- (defconstant +valid-colors+ '(red green blue))
-
+
;; Bad
+(defconstant +google-url+ "https://www.google.com/")
+(defconstant +valid-colors+ '(red green blue))
@@ -2823,11 +3170,9 @@ Robert Brown
You may use the :TEST keyword argument
to specify an equality predicate.
-
- ;; Better, for Open-Source code:
- (define-constant +google-url+ "https://www.google.com/" :test #'string=)
- (define-constant +valid-colors+ '(red green blue))
-
+
;; Better, for Open-Source code:
+(define-constant +google-url+ "https://www.google.com/" :test #'string=)
+(define-constant +valid-colors+ '(red green blue))
Note that with optimizing implementations, such as SBCL or CMUCL,
defining constants this way precludes any later redefinition
@@ -2850,16 +3195,20 @@ Robert Brown
Also note that LOAD-TIME-VALUE may help you
avoid the need for defined constants.
You should make proper use of
&OPTIONAL and
&KEY arguments.
You should not use &AUX arguments.
-
-
+
+
You should avoid using &ALLOW-OTHER-KEYS,
since it blurs the contract of a function.
@@ -2924,13 +3273,17 @@ Robert Brown
Use your judgment and consult your reviewers.
Use WHEN and UNLESS
when there is only one alternative.
@@ -2950,8 +3303,8 @@ Robert Brown
to explicitly return NIL
if you have a specific reason to insist on the return value.
You may similarly include a fall-through clause (t nil)
- as the last in your COND,
- or (otherwise nil) as the last in your CASE,
+ as the last in your COND,
+ or (otherwise nil) as the last in your CASE,
to insist on the fact that the value returned by the conditional matters
and that such a case is going to be used.
You should omit the fall-through clause
@@ -2992,16 +3345,12 @@ Robert Brown
You must not use gratuitous single quotes in CASE forms.
This is a common error:
-
- (case x ; Bad: silently returns NIL on mismatch
- ('bar :bar) ; Bad: catches QUOTE
- ('baz :baz)) ; Bad: also would catch QUOTE
-
-
- (ecase x ; Better: will error on mismatch
- ((bar) :bar) ; Better: won't match QUOTE
- ((baz) :baz)) ; Better: same reason
-
+
(case x ; Bad: silently returns NIL on mismatch
+ ('bar :bar) ; Bad: catches QUOTE
+ ('baz :baz)) ; Bad: also would catch QUOTE
+
(ecase x ; Better: will error on mismatch
+ ((bar) :bar) ; Better: won't match QUOTE
+ ((baz) :baz)) ; Better: same reason
'BAR there is (QUOTE BAR),
meaning this leg of the case will be executed
@@ -3024,23 +3373,23 @@ Robert Brown
to respective symbols :BAR and :QUUX,
you should avoid the former way and do it the latter way:
-
- (ecase x ; Bad: has no actual error case!
- (nil :bar)) ; Bad: matches nothing
- (t :quux)) ; Bad: matches anything
-
-
- (ecase x ; Better: will actually catch non-booleans
- ((nil) :bar)) ; Better: matches NIL
- ((t) :quux)) ; Better: matches T
-
-
-
-
-
+
(ecase x ; Bad: has no actual error case!
+ (nil :bar)) ; Bad: matches nothing
+ (t :quux)) ; Bad: matches anything
+
(ecase x ; Better: will actually catch non-booleans
+ ((nil) :bar)) ; Better: matches NIL
+ ((t) :quux)) ; Better: matches T
You should use simpler forms such as
DOLIST or DOTIMES
@@ -3173,13 +3526,17 @@ Robert Brown
as LOOP keywords.
You must be consistent with the convention used in your system.
When writing a server,
code must not send output to the standard streams such as
@@ -3228,7 +3585,8 @@ Robert Brown
The parameters are easy to forget.
-
No parameters, e.g. "~[Siamese~;Manx~;Persian~] Cat"
+
No parameters, e.g. "~[Siamese~;Manx~;Persian~] Cat"
+
Take one format argument, which should be an integer.
Use it to choose a clause. Clause numbers are zero-based.
@@ -3238,19 +3596,25 @@ Robert Brown
E.g. in "~[Siamese~;Manx~;Persian~:;Alley~] Cat",
an out-of-range arg prints "Alley".
-
: parameter, e.g. "~:[Siamese~;Manx~]"
+
+: parameter, e.g. "~:[Siamese~;Manx~]"
+
Take one format argument. If it's NIL,
use the first clause, otherwise use the second clause.
-
@ parameter, e.g. "~@[Siamese ~a~]"
+
+@ parameter, e.g. "~@[Siamese ~a~]"
+
If the next format argument is true,
use the choice, but do NOT take the argument.
If it's false, take one format argument and print nothing.
(Normally the clause uses the format argument.)
-
# parameter, e.g. "~#[ none~; ~s~; ~s and ~s~]"
+
+# parameter, e.g. "~#[ none~; ~s~; ~s and ~s~]"
+
Use the number of arguments to format
as the number to choose a clause.
@@ -3259,16 +3623,21 @@ Robert Brown
"Items: ~#[ none~; ~S~; ~S and ~S~:;~@{~S~^~#[~; and ~:;, ~]~}~]."
You should avoid unnecessary allocation of memory.
-
-
+
+
In a language with automatic storage management (such as Lisp or Java),
the colloquial phrase "memory leak" refers to situation
@@ -3293,15 +3662,19 @@ Robert Brown
Garbage collection is not magic.
Excessive allocation is usually a performance problem.
You must only use faster unsafe operations
when there is a clear performance need
and you can document why it's correct.
-
-
+
+
Common Lisp implementations often provide backdoors
to compute some operations faster in an unsafe way.
@@ -3366,15 +3739,19 @@ Robert Brown
it defeats the purpose of declarations as a performance trick.
You should only use DYNAMIC-EXTENT
where it matters for performance,
and you can document why it is correct.
-
-
+
+
DYNAMIC-EXTENT declarations are
a particular case of
@@ -3489,14 +3866,18 @@ Robert Brown
(Ideally it would be easier to make such measurements
than it actually is.)
You should use REDUCE
instead of APPLY where appropriate.
-
-
+
+
You should use REDUCE
instead of APPLY and a consed-up list,
@@ -3506,14 +3887,10 @@ Robert Brown
if it does what you want and REDUCE doesn't.
For instance:
This is preferable because it does not do extra consing,
and does not risk going beyond CALL-ARGUMENTS-LIMIT
@@ -3539,15 +3916,19 @@ Robert Brown
See for instance UIOP:REDUCE/STRCAT.
You should not use NCONC;
you should use APPEND instead,
or better data structures.
-
-
+
+
You should almost never use NCONC.
You should use APPEND
@@ -3599,16 +3980,21 @@ Robert Brown
Even then, the use of such primitives must be rare,
and accompanied by justifying documentation.
You should usually refer to a function as #'FUN rather than 'FUN.
-
-
+
+
The former, which reads as (FUNCTION FUN),
refers to the function object, and is lexically scoped.
@@ -3664,13 +4050,17 @@ Robert Brown
But you must not start using such a syntactic extension
in an existing system without getting permission from other developers.
You must be careful when using a SATISFIES clause in a type specifier.
-
-
+
+
Most Common Lisp implementations can't optimize
based on a SATISFIES type,
@@ -3770,12 +4164,8 @@ Robert Brown
without any SATISFIES
and the second term is the SATISFIES.
However, AND in the DEFTYPE language
isn't a left-to-right short-circuit operator
@@ -3797,22 +4187,18 @@ Robert Brown
and MUST be defined within an EVAL-WHEN
(as well as any variable it uses or function it calls):
In particular, the above means that the
example
@@ -3854,20 +4240,20 @@ Robert Brown
Common Lisp is hard to satisfy.
-
-
-
+
+
+
-
+
-Credits:
+Credits:
Adam Worrall, Dan Pierson, Matt Marjanovic, Matt Reklaitis,
Paul Weiss, Scott McKay, Sundar Narasimhan,
and several other people contributed.
Special thanks to Steve Hain,
and to the previous editors,
in reverse chronological order Dan Weinreb and Jeremy Brown.
-
+
- Each style point has a summary for which additional information is available
- by toggling the accompanying arrow button that looks this way:
-
- .
- You may toggle all summaries with the big arrow button:
-
+ Each style point has a summary for which additional information is available
+ by toggling the accompanying arrow button that looks this way:
+ ▶.
+ You may toggle all summaries with the big arrow button:
+
This is the in-depth vimscript guide. If you're just a casual user
looking to write a plugin, the
@@ -35,10 +230,11 @@
Fair warning: Vimscript is a maddening abyss. When you gaze into it, it
gazes also into you. Proceed with caution.
-
-
+
+
-
+
+
Portability
Vim is highly configurable. Users can change many of the default
settings, including the case sensitivity, the regular expression rules,
@@ -181,24 +377,25 @@
In general, guard all commands and functions against user settings.
-
-
+
+
+
Language Guide
- Line continuations: Yes
+ Line continuations: Yes
Plugins that support vi compatibility mode must save and restore
compatibility options as described in the
- Errata section so line continuations work properly.
+ Errata section so line continuations work properly.
- Exceptions: Yes, with caution
+ Exceptions: Yes, with caution
Always use an error code in thrown exception messages.
@@ -218,7 +415,7 @@
- Global Variables: As configuration only
+ Global Variables: As configuration only
See the plugin guide.
@@ -226,7 +423,7 @@
- Messaging: As little as possible.
+ Messaging: As little as possible.
Loud scripts are annoying.
@@ -245,7 +442,7 @@
Type checking:
- Use strict and explicit checks where possible.
+ Use strict and explicit checks where possible.
Vimscript has unsafe, unintuitive behavior when dealing with some
@@ -270,7 +467,7 @@
- FuncRefs: No in most cases.
+ FuncRefs: No in most cases.
FuncRefs have inconsistently enforced naming restrictions.
@@ -292,7 +489,7 @@
- Python: Sparingly
+ Python: Sparingly
@@ -311,7 +508,7 @@
- Ruby: No
+ Ruby: No
We can not assume ruby interoperability.
@@ -323,7 +520,7 @@
Vimscript can attach functions to dictionaries. Such functions
@@ -351,8 +548,9 @@
All other language features are fair game.
-
-
+
+
+
Structure
Provided functionality should be packed into modular plugins.
@@ -404,12 +602,10 @@
Each file in the plugin/ or instant/ directory
should begin with the boilerplate
-
- let [s:plugin, s:enter] = maktaba#plugin#Enter(expand('<sfile>:p'))
- if !s:enter
- finish
- endif
-
+
let [s:plugin, s:enter] = maktaba#plugin#Enter(expand('<sfile>:p'))
+if !s:enter
+ finish
+endif
(This prevents re-entry and allows users to selectively disable
functionality.)
Separate library-providing plugins from command-providing plugins.
-
-
+
+
Many plugins provide either user functionality (commands,
autocommands, etc) or an API (of autoloaded functions) but not both.
@@ -477,15 +677,19 @@
library without also pulling in commands, setting changes, and other
plugin functionality that affects the end user.
When continuing a multi-line command a pipe can be substituted
for this space as necessary, as follows:
-
- autocommand BufEnter <buffer>
- \ if !empty(s:var)
- \| call some#function()
- \|else
- \| call some#function(s:var)
- \|endif
-
+
Prefer long names of built in settings (i.e. tabstop
@@ -892,28 +1099,34 @@
-
-
-
-
+
+
+
+
+
Usage Guide
Vim plugins should provide any or all of the following:
- Commands,Autocommands,
- Functions,Statusline Flags, and
- Mappings.
+ Commands, Autocommands,
+ Functions, Statusline Flags, and
+ Mappings.
Declare dependencies in addon-info.json and use maktaba.
-
-
+
+
Declaring dependencies in addon-info.json allows conformant plugin
managers (like VAM) to ensure dependencies are installed. See the
@@ -1280,15 +1508,19 @@
runtime ensures that dependencies have been installed and that they
don't include unsafe non-library files.
Use <plugin-name>#status#Status() or its
finer-grained variants to provide statusline flags.
-
-
+
+
Following is a convention for exposing statusline flags to the user. A
plugin should never modify the user's statusline except for when that
@@ -1373,10 +1605,11 @@
-
-
-
-
+
+
+
+
+
Forbidden Commands
These are commands which can only be used by a limited number of
plugins, and should not in general be used by yours.
@@ -1429,8 +1662,9 @@
-
-
+
+
+
Layout
Lay out plugin/ files in the following sections, if
applicable, separated by two blank lines:
@@ -1472,8 +1706,9 @@
This is recommended convention and is not enforced.
-
-
+
+
+
Recommended Shortcuts
Use the following shortcuts:
@@ -1488,19 +1723,24 @@
-
-
+
+
+
Errata
This section plumbs some of the darker corners of vimscript, explaining
the language pathologies that you wish you didn't have to know.
If you don't support vi-compatibility mode, fail gracefully.
-
-
+
+
When compatible is set, many vim features are not
available. The vim feature which most commonly affects vimscript
@@ -1517,9 +1757,9 @@
compatible mode since maktaba currently just disables it, printing a
warning.
+ Each style point has a summary for which additional information is available
+ by toggling the accompanying arrow button that looks this way:
+ ▶.
+ You may toggle all summaries with the big arrow button:
+
+ This is a casual version of the vimscript style guide, because
+ vimscript is a casual language. When submitting vim plugin code, you
+ must adhere to these rules. For clarifications, justifications, and
+ explanations about the finer points of vimscript, please refer to the
+ heavy guide.
+
+
+
+
+
+
Portability
+
+ It's hard to get vimscript right. Many commands depend upon the user's
+ settings. By following these guidelines, you can hope to make your
+ scripts portable.
+
+ Double quoted strings are semantically different in vimscript, and
+ you probably don't want them (they break regexes).
+
+
+ Use double quoted strings when you need an escape sequence (such as
+ "\n") or if you know it doesn't matter and you need to
+ embed single quotes.
+
+ Use the =~# or =~? operator families over the
+ =~ family.
+
+
+
+ The matching behavior depends upon the user's ignorecase and smartcase
+ settings and on whether you compare them with the =~,
+ =~#, or =~? family of operators. Use the
+ =~# and =~? operator families explicitly
+ when comparing strings unless you explicitly need to honor the user's
+ case sensitivity settings.
+
+ In addition to the case sensitivity settings, regex behavior depends
+ upon the user's nomagic setting. To make regexes act like nomagic and
+ noignorecase are set, prepend all regexes with \m\C.
+
+
+ You are welcome to use other magic levels (\v) and case
+ sensitivities (\c) so long as they are intentional and
+ explicit.
+
+ Vimscript has unsafe, unintuitive behavior when dealing with some
+ types. For instance, 0 == 'foo' evaluates to true.
+
+
+ Use strict comparison operators where possible. When comparing against
+ a string literal, use the is# operator. Otherwise, prefer
+ maktaba#value#IsEqual or check type()
+ explicitly.
+
+
+ Check variable types explicitly before using them. Use functions from
+ maktaba#ensure, or check maktaba#value or
+ type() and throw your own errors.
+
+
+ Use :unlet for variables that may change types,
+ particularly those assigned inside loops.
+
+ Avoid using other scripting languages such as ruby and lua. We can
+ not guarantee that the end user's vim has been compiled with support
+ for non-vimscript languages.
+
+ Group your functionality as a plugin, unified in one directory (or
+ code repository) which shares your plugin's name (with a "vim-" prefix
+ or ".vim" suffix if desired). It should be split into plugin/,
+ autoload/, etc. subdirectories as necessary, and it should declare
+ metadata in the addon-info.json format (see the
+ VAM documentation for details).
+
+ In general, use
+ plugin-names-like-this,
+ FunctionNamesLikeThis,
+ CommandNamesLikeThis,
+ augroup_names_like_this,
+ variable_names_like_this.
+
+
Always prefix variables with their scope.
+
+
+
+plugin-names-like-this
+
Keep them short and sweet.
+
+
+
+FunctionNamesLikeThis
+
Prefix script-local functions with s:
+
Autoloaded functions may not have a scope prefix.
+
+ Do not create global functions. Use autoloaded functions
+ instead.
+
+
+
+CommandNamesLikeThis
+
Prefer succinct command names over common command prefixes.
+
+
+variable_names_like_this
+
Augroup names count as variables for naming purposes.
+
+
+Prefix all variables with their scope.
+
+
Global variables with g:
+
+
Script-local variables with s:
+
+
Function arguments with a:
+
+
Function-local variables with l:
+
+
Vim-predefined variables with v:
+
+
Buffer-local variables with b:
+
+
+
+ g:, s:, and a: must always
+ be used.
+
+
+ b: changes the variable semantics; use it when you
+ want buffer-local semantics.
+
+
+ l: and v: should be used for consistency,
+ future proofing, and to avoid subtle bugs. They are not strictly
+ required. Add them in new code but don’t go out of your way to add
+ them elsewhere.
+
- This is a casual version of the vimscript style guide, because
- vimscript is a casual language. When submitting vim plugin code, you
- must adhere to these rules. For clarifications, justifications, and
- explanations about the finer points of vimscript, please refer to the
- heavy guide.
-
-
-
-
-
-
- It's hard to get vimscript right. Many commands depend upon the user's
- settings. By following these guidelines, you can hope to make your
- scripts portable.
-
-
- Prefer single quoted strings
-
-
- Double quoted strings are semantically different in vimscript, and
- you probably don't want them (they break regexes).
-
-
- Use double quoted strings when you need an escape sequence (such as
- "\n") or if you know it doesn't matter and you need to
- embed single quotes.
-
-
-
-
-
- Use the =~# or =~? operator families over the
- =~ family.
-
-
-
- The matching behavior depends upon the user's ignorecase and smartcase
- settings and on whether you compare them with the =~,
- =~#, or =~? family of operators. Use the
- =~# and =~? operator families explicitly
- when comparing strings unless you explicitly need to honor the user's
- case sensitivity settings.
-
-
-
-
- Prefix all regexes with \m\C.
-
-
- In addition to the case sensitivity settings, regex behavior depends
- upon the user's nomagic setting. To make regexes act like nomagic and
- noignorecase are set, prepend all regexes with \m\C.
-
-
- You are welcome to use other magic levels (\v) and case
- sensitivities (\c) so long as they are intentional and
- explicit.
-
-
-
-
- Avoid commands with unintended side effects.
-
-
- Avoid using :s[ubstitute] as it moves the cursor and
- prints error messages. Prefer functions (such as
- search()) better suited to scripts.
-
-
- For many vim commands, functions exist that do the same thing with
- fewer side effects. See :help functions() for a list of
- built-in functions.
-
-
-
-
- Avoid commands that rely on user settings.
-
-
- Always use normal! instead of normal. The
- latter depends upon the user's key mappings and could do anything.
-
-
- Avoid :s[ubstitute], as its behavior depends upon a
- number of local settings.
-
-
- The same applies to other commands not listed here.
-
-
-
-
- Match error codes, not error text.
-
-
Error text may be locale dependent.
-
-
-
-
-
-
-
-
- Message the user infrequently.
-
-
- Loud scripts are annoying. Message the user only when:
-
-
A long-running process has kicked off.
-
An error has occurred.
-
-
-
-
-
- Use strict and explicit checks where possible.
-
-
- Vimscript has unsafe, unintuitive behavior when dealing with some
- types. For instance, 0 == 'foo' evaluates to true.
-
-
- Use strict comparison operators where possible. When comparing against
- a string literal, use the is# operator. Otherwise, prefer
- maktaba#value#IsEqual or check type()
- explicitly.
-
-
- Check variable types explicitly before using them. Use functions from
- maktaba#ensure, or check maktaba#value or
- type() and throw your own errors.
-
-
- Use :unlet for variables that may change types,
- particularly those assigned inside loops.
-
-
-
-
- Use sparingly.
-
-
- Use python only when it provides critical functionality, for example
- when writing threaded code.
-
-
-
-
- Use vimscript instead.
-
-
- Avoid using other scripting languages such as ruby and lua. We can
- not guarantee that the end user's vim has been compiled with support
- for non-vimscript languages.
-
-
-
-
-
- Organize functionality into modular plugins
-
-
- Group your functionality as a plugin, unified in one directory (or
- code repository) which shares your plugin's name (with a "vim-" prefix
- or ".vim" suffix if desired). It should be split into plugin/,
- autoload/, etc. subdirectories as necessary, and it should declare
- metadata in the addon-info.json format (see the
- VAM documentation for details).
-
-
-
-
-
- In the autoload/ directory, defined with [!] and
- [abort].
-
-
-
- Autoloading allows functions to be loaded on demand, which makes
- startuptime faster and enforces function namespacing.
-
-
- Script-local functions are welcome, but should also live in autoload/
- and be called by autoloaded functions.
-
-
- Non-library plugins should expose commands instead of functions.
- Command logic should be extracted into functions and autoloaded.
-
-
- [!] allows developers to reload their functions
- without complaint.
-
-
- [abort] forces the function to halt when it encounters
- an error.
-
-
-
-
-
- In the plugin/commands.vim or under the ftplugin/ directory, defined
- without [!].
-
-
-
- General commands go in plugin/commands.vim.
- Filetype-specific commands go in ftplugin/.
-
-
- Excluding [!] prevents your plugin from silently
- clobbering existing commands. Command conflicts should be resolved by
- the user.
-
-
-
-
-
- Place them in plugin/autocmds.vim, within augroups.
-
-
-
- Place all autocommands in augroups.
-
-
- The augroup name should be unique. It should either be, or be prefixed
- with, the plugin name.
-
-
- Clear the augroup with autocmd! before defining new
- autocommands in the augroup. This makes your plugin re-entrable.
-
-
-
-
-
- Place them in plugin/mappings.vim, using
- maktaba#plugin#MapPrefix to get a prefix.
-
-
-
- All key mappings should be defined in
- plugin/mappings.vim.
-
-
- Partial mappings (see :help using-<Plug>.) should be defined in
- plugin/plugs.vim.
-
-
-
-
- Change settings locally
-
-
- Use :setlocal and &l: instead of
- :set and & unless you have explicit
- reason to do otherwise.
-
-
-
-
-
-
-
- Follow google style conventions. When in doubt, treat vimscript style
- like python style.
-
- In general, use
- plugin-names-like-this,
- FunctionNamesLikeThis,
- CommandNamesLikeThis,
- augroup_names_like_this,
- variable_names_like_this.
-
-
Always prefix variables with their scope.
-
-
-
-
Keep them short and sweet.
-
-
-
-
Prefix script-local functions with s:
-
Autoloaded functions may not have a scope prefix.
-
- Do not create global functions. Use autoloaded functions
- instead.
-
-
-
-
Prefer succinct command names over common command prefixes.
-
-
-
Augroup names count as variables for naming purposes.
-
-
-
-
Global variables with g:
-
Script-local variables with s:
-
Function arguments with a:
-
Function-local variables with l:
-
Vim-predefined variables with v:
-
Buffer-local variables with b:
-
-
- g:, s:, and a: must always
- be used.
-
-
- b: changes the variable semantics; use it when you
- want buffer-local semantics.
-
-
- l: and v: should be used for consistency,
- future proofing, and to avoid subtle bugs. They are not strictly
- required. Add them in new code but don’t go out of your way to add
- them elsewhere.
-