Update C++ style guide to 3.133:

- Clarify that a "very strong convention" is, in fact, only very strong
   within Google code
 - Update the style guide with an additional naming possibility for enums:
   kEnumName
 - Reword the summary for the section on header file dependencies
 - Simplify wording regarding static variables

Update Objective-C style guide to 2.11:
 - Provide guidance on when to use #import and #include
 - Display revision in style guide

Update styleguide.xsl with a hint of things to come

Set svn:eol-style on xmlstyle.html
This commit is contained in:
mmentovai 2009-03-25 22:24:14 +00:00
parent 3664910272
commit 71619d34e3
3 changed files with 521 additions and 71 deletions

View File

@ -4,7 +4,7 @@
<p align="right">
Revision 3.127
Revision 3.133
</p>
@ -146,8 +146,8 @@ Tashana Landray
<STYLEPOINT title="Header File Dependencies">
<SUMMARY>
Use forward declarations to minimize use of
<code>#include</code> in <code>.h</code> files.
Don't use an <code>#include</code> when a forward declaration
would suffice.
</SUMMARY>
<BODY>
<p>
@ -462,8 +462,8 @@ Tashana Landray
namespace { // This is in a .cc file.
// The content of a namespace is not indented
enum { UNUSED, EOF, ERROR }; // Commonly used tokens.
bool AtEof() { return pos_ == EOF; } // Uses our namespace's EOF.
enum { kUnused, kEOF, kError }; // Commonly used tokens.
bool AtEof() { return pos_ == kEOF; } // Uses our namespace's EOF.
} // namespace
</CODE_SNIPPET>
@ -742,52 +742,42 @@ Tashana Landray
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Global Variables">
<STYLEPOINT title="Static and Global Variables">
<SUMMARY>
Global variables of class types are forbidden. Global variables
of built-in types are allowed, although non-<code>const</code>
globals are forbidden in threaded code. Global variables should
never be initialized with the return value of a function.
Static or global variables of class type are forbidden: they cause
hard-to-find bugs due to indeterminate order of construction and
destruction.
</SUMMARY>
<BODY>
<p>
Unfortunately the order in which constructors, destructors,
and initializers for global variables are called is only
partially specified and can change from build to build. This
can cause bugs that are very difficult to find.
Objects with static storage duration, including global variables,
static variables, static class member variables, and function static
variables, must be Plain Old Data (POD): only ints, chars, floats, and
void, and arrays of/structs of/pointers to POD. Static variables must
not be initialized with the result of a function; and non-const static
variables must not be used in threaded code.
</p>
<p>
Therefore we forbid global variables of class types (which
includes STL string, vector, etc.) because initialization
order might matter for their constructor, now or in the
future. Built-in types and structs of built-in types without
constructors are okay.
If you need a global variable of a class
type, use the
<a href="http://en.wikipedia.org/wiki/Singleton_pattern">singleton
pattern</a>.
The order in which class constructors, destructors, and initializers for
static variables are called is only partially specified in C++ and can
even change from build to build, which can cause bugs that are difficult
to find. For example, at program-end time a static variable might have
been destroyed, but code still running -- perhaps in another thread --
tries to access it and fails.
</p>
<p>
For global string constants, use C style strings, <em>not</em>
STL strings:
As a result we only allow static variables to contain POD data. This
rule completely disallows <code>vector</code> (use C arrays instead),
<code>string</code> (use <code>const char*</code>), or anything that
contains or points to any class instance in any way, from ever being a
part of a static variable. For similar reasons, we don't allow static
variables to be initialized with the result of a function call.
</p>
<CODE_SNIPPET>
const char kFrogSays[] = "ribbet";
</CODE_SNIPPET>
<p>
Although we permit global variables in the global scope,
please be judicious in your use of them. Most global variables
should either be static data members of some class, or, if only
needed in one <code>.cc</code> file, defined in an unnamed
<a HREF="#Namespaces">namespace</a>. (As an alternative to using
an unnamed namespace, you can use <code>static</code> linkage to
limit the variable's scope.)
</p>
<p>
Please note that <code>static</code> class member variables
count as global variables, and should not be of class types!
If you need a static or global variable of a class type, consider
initializing a pointer which you never free from your main() function
or from pthread_once().
</p>
@ -1444,19 +1434,22 @@ Tashana Landray
</BODY>
</STYLEPOINT>
<STYLEPOINT title="cpplint">
<SUMMARY>
Use <code>cpplint.py</code> to detect style errors.
Use
<code>cpplint.py</code>
to detect style errors.
</SUMMARY>
<BODY>
<p>
<code>cpplint.py</code> is a tool that reads a source file and
<code>cpplint.py</code>
is a tool that reads a source file and
identifies many style errors. It is not perfect, and has both false
positives and false negatives, but it is still a valuable tool. False
positives can be ignored by putting <code>// NOLINT</code> at the end
of the line.
positives can be ignored by putting <code>// NOLINT</code> at
the end of the line.
</p>
<p>
Some projects have instructions on how to run <code>cpplint.py</code>
from their project tools. If the project you are contributing to does
@ -1501,7 +1494,7 @@ Tashana Landray
void Foo(const string &amp;in, string *out);
</CODE_SNIPPET>
<p>
In fact it is a very strong convention that input
In fact it is a very strong convention in Google code that input
arguments are values or <code>const</code> references while
output arguments are pointers. Input parameters may be
<code>const</code> pointers, but we never allow
@ -1948,7 +1941,7 @@ Tashana Landray
</p>
<p>
Some say <code>printf</code> formatting is ugly and hard to
read, but streams are often no better. Consider the following
read, but streams are often no better. Consider the following
two fragments, both with the same typo. Which is easier to
discover?
</p>
@ -2104,7 +2097,7 @@ Tashana Landray
(<code>const</code>) before the "noun" (<code>int</code>).
</p>
<p>
That said, while we encourage putting <code>const</code> first,
That said, while we encourage putting <code>const</code> first,
we do not require it. But be consistent with the code around
you!
</p>
@ -2560,7 +2553,7 @@ Tashana Landray
</BAD_CODE_SNIPPET>
<p>
Type and variable names should typically be nouns: e.g.,
<code>FileOpener</code>,
<code>FileOpener</code>,
<code>num_errors</code>.
</p>
@ -2832,22 +2825,43 @@ Tashana Landray
<STYLEPOINT title="Enumerator Names">
<SUMMARY>
Enumerators should be all uppercase with underscores between
words: <code>MY_EXCITING_ENUM_VALUE</code>.
Enumerators should be named <i>either</i> like
<A HREF="#Constant_Names">constants</A> or like
<A HREF="#Macro_Names">macros</A>: either <code>kEnumName</code>
or <code>ENUM_NAME</code>.
</SUMMARY>
<BODY>
<p>
The individual enumerators should be all uppercase. The
enumeration name, <code>UrlTableErrors</code>, is a type, and
Preferably, the individual enumerators should be named like
<A HREF="#Constant_Names">constants</A>. However, it is also
acceptable to name them like <A HREF="#Macro_Names">macros</A>. The enumeration name,
<code>UrlTableErrors</code> (and
<code>AlternateUrlTableErrors</code>), is a type, and
therefore mixed case.
</p>
<CODE_SNIPPET>
enum UrlTableErrors {
kOK = 0,
kErrorOutOfMemory,
kErrorMalformedInput,
};
enum AlternateUrlTableErrors {
OK = 0,
ERROR_OUT_OF_MEMORY,
ERROR_MALFORMED_INPUT,
OUT_OF_MEMORY = 1,
MALFORMED_INPUT = 2,
};
</CODE_SNIPPET>
<p>
Until January 2009, the style was to name enum values like
<A HREF="#Macro_Names">macros</A>. This caused problems with
name collisions between enum values and macros. Hence, the
change to prefer constant-style naming was put in place. New
code should prefer constant-style naming if possible.
However, there is no reason to change old code to use
constant-style names, unless the old names are actually
causing a compile-time problem.
</p>
</BODY>
</STYLEPOINT>
@ -4338,7 +4352,7 @@ Tashana Landray
<HR/>
<p align="right">
Revision 3.127
Revision 3.133
</p>

View File

@ -2,6 +2,11 @@
<?xml-stylesheet type="text/xsl" href="styleguide.xsl"?>
<GUIDE title="Google Objective-C Style Guide">
<p align="right">
Revision 2.11
</p>
<div align="right">
@ -444,7 +449,7 @@
};
// file: mac_implementation.mm
#import "cross_platform_header.h"
#include "cross_platform_header.h"
// A typical Objective-C class, using Objective-C naming.
@interface MyDelegate : NSObject {
@ -904,7 +909,58 @@
</p>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="#import and #include">
<SUMMARY>
<code>#import</code> Objective-C/Objective-C++ headers, and
<code>#include</code> C/C++ headers.
</SUMMARY>
<BODY>
<p>
Choose between <code>#import</code> and <code>#include</code> based
on the language of the header that you are including.
</p>
<ul>
<li>When including a header that uses Objective-C or Objective-C++,
use <code>#import</code>.</li>
<li>When including a standard C or C++ header, use
<code>#include</code>. The header should provide its own <a href="cppguide.xml?showone=The__define_Guard#The__define_Guard">#define
guard</a>.</li>
</ul>
<p>
Some Objective-C headers lack <code>#define</code> guards, and expect
to be included only by <code>#import</code>. As Objective-C headers
may only be included in Objective-C source files and other Objective-C
headers, using <code>#import</code> across the board is appropriate.
</p>
<p>
Standard C and C++ headers without any Objective-C in them can expect
to be included by ordinary C and C++ files. Since there is no
<code>#import</code> in standard C or C++, such files will be
included by <code>#include</code> in those cases. Using
<code>#include</code> for them in Objective-C source files as well
means that these headers will always be included with the same
semantics.
</p>
<p>
This rule helps avoid inadvertent errors in cross-platform
projects. A Mac developer introducing a new C or C++ header might
forget to add <code>#define</code> guards, which would not cause
problems on the Mac if the new header were included with
<code>#import</code>, but would break builds on other platforms
where <code>#include</code> is used. Being consistent by using
<code>#include</code> on all platforms means that compilation is
more likely to succeed everywhere or fail everywhere, and avoids
the frustration of files working only on some platforms.
</p>
<CODE_SNIPPET>
#import &lt;Cocoa/Cocoa.h&gt;
#include &lt;CoreFoundation/CoreFoundation.h&gt;
#import "GTMFoo.h"
#include "base/basictypes.h"
</CODE_SNIPPET>
</BODY>
</STYLEPOINT>
<STYLEPOINT title="Use Root Frameworks">
<SUMMARY>
@ -917,7 +973,7 @@
compiler if you include the top-level root framework. The root
framework is generally pre-compiled and can be loaded much more
quickly. In addition, remember to use <code>#import</code> rather than
<code>#include</code>.
<code>#include</code> for Objective-C frameworks.
</p>
<CODE_SNIPPET>
#import &lt;Foundation/Foundation.h&gt; // good
@ -1372,6 +1428,10 @@
<HR/>
<p align="right">
Revision 2.11
</p>
<address>

View File

@ -3,7 +3,8 @@ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:dcq="http://purl.org/dc/qualifiers/1.0/"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:fn="http://www.w3.org/2005/xpath-functions">
<xsl:output method="html"/>
<!-- Set to 1 to show explanations by default. Set to 0 to hide them -->
<xsl:variable name="show_explanation_default" select="0" />
@ -30,13 +31,23 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format">
<SCRIPT language="javascript" type="text/javascript">
function ShowHideByName(bodyName, buttonName) {
var bodyElements = document.getElementsByName(bodyName);
var bodyElements;
if (document.getElementsByName) {
bodyElements = document.getElementsByName(bodyName);
} else {
bodyElements = [document.getElementById(bodyName)];
}
if (bodyElements.length != 1) {
alert("ShowHideByName() got the wrong number of bodyElements: " + bodyElements.length);
} else {
var bodyElement = bodyElements[0];
var buttonElements = document.getElementsByName(buttonName);
var buttonElement = buttonElements[0];
var buttonElement;
if (document.getElementsByName) {
var buttonElements = document.getElementsByName(buttonName);
buttonElement = buttonElements[0];
} else {
buttonElement = document.getElementById(buttonName);
}
if (bodyElement.style.display == "none" || bodyElement.style.display == "") {
bodyElement.style.display = "inline";
buttonElement.innerHTML = '<xsl:value-of select="$hide_button_text"/>';
@ -48,14 +59,19 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format">
}
function ShowHideAll() {
var allButtons = document.getElementsByName("show_hide_all_button");
var allButton = allButtons[0];
var allButton;
if (document.getElementsByName) {
var allButtons = document.getElementsByName("show_hide_all_button");
allButton = allButtons[0];
} else {
allButton = document.getElementById("show_hide_all_button");
}
if (allButton.innerHTML == '<xsl:value-of select="$hide_button_text"/>') {
allButton.innerHTML = '<xsl:value-of select="$show_button_text"/>';
SetHiddenState(document.body.childNodes, "none", '<xsl:value-of select="$show_button_text"/>');
SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "none", '<xsl:value-of select="$show_button_text"/>');
} else {
allButton.innerHTML = '<xsl:value-of select="$hide_button_text"/>';
SetHiddenState(document.body.childNodes, "inline", '<xsl:value-of select="$hide_button_text"/>');
SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "inline", '<xsl:value-of select="$hide_button_text"/>');
}
}
@ -81,9 +97,9 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format">
var showHideAllValue = showHideAllRegex.exec(window.location.href);
if (showHideAllValue != null) {
if (showHideAllValue[2] == "y") {
SetHiddenState(document.body.childNodes, "inline", '<xsl:value-of select="$hide_button_text"/>');
SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "inline", '<xsl:value-of select="$hide_button_text"/>');
} else {
SetHiddenState(document.body.childNodes, "none", '<xsl:value-of select="$show_button_text"/>');
SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "none", '<xsl:value-of select="$show_button_text"/>');
}
}
var showOneRegex = new RegExp("[\\?&amp;](showone)=([^&amp;#]*)");
@ -325,6 +341,30 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format">
</SPAN>
</xsl:template>
<xsl:template match="PY_CODE_SNIPPET">
<SPAN>
<xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute>
<PRE><xsl:call-template name="print_python_code">
<xsl:with-param name="text" select="."/>
</xsl:call-template></PRE>
</SPAN>
</xsl:template>
<xsl:template match="BAD_PY_CODE_SNIPPET">
<SPAN>
<xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute>
<PRE class="badcode"><xsl:call-template name="print_python_code">
<xsl:with-param name="text" select="."/>
</xsl:call-template></PRE>
</SPAN>
</xsl:template>
<xsl:template match="FUNCTION">
<xsl:call-template name="print_function_name">
<xsl:with-param name="text" select="."/>
</xsl:call-template>
</xsl:template>
<xsl:template match="SYNTAX">
<I>
<xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute>
@ -461,6 +501,280 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format">
</xsl:if>
</xsl:template>
<!-- Given text, determine the starting position of code.
This similar to num_leading_spaces_one_line but treats "Yes:" and "No:"
as spaces. Also, if there is no code on the first line, it searches
subsequent lines until a non-empty line is found.
Used to find the start of code in snippets like:
Yes: if(foo):
No : if(foo):
As well as:
Yes:
if (foo):
-->
<xsl:template name="code_start_index">
<xsl:param name="text"/>
<xsl:param name="current_count"/>
<xsl:choose>
<xsl:when test="starts-with($text, ' ')">
<xsl:call-template name="code_start_index">
<xsl:with-param name="text" select="substring($text, 2)"/>
<xsl:with-param name="current_count" select="$current_count + 1"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="starts-with($text, 'Yes:')">
<xsl:call-template name="code_start_index">
<xsl:with-param name="text" select="substring($text, 5)"/>
<xsl:with-param name="current_count" select="$current_count + 4"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="starts-with($text, 'No:')">
<xsl:call-template name="code_start_index">
<xsl:with-param name="text" select="substring($text, 4)"/>
<xsl:with-param name="current_count" select="$current_count + 3"/>
</xsl:call-template>
</xsl:when>
<!-- This is only reached if the first line is entirely whitespace or
contains nothing but "Yes:" or "No:"-->
<xsl:when test="starts-with($text, '&#xA;')">
<xsl:call-template name="code_start_index">
<xsl:with-param name="text" select="substring($text, 2)"/>
<xsl:with-param name="current_count" select="0"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$current_count"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Helper for ends_with_colon. Determine whether the given line is nothing
but spaces and python-style comments. -->
<xsl:template name="is_blank_or_comment">
<xsl:param name="line"/>
<xsl:choose>
<xsl:when test="$line = ''">
<xsl:value-of select="1"/>
</xsl:when>
<xsl:when test="starts-with($line, '&#xA;')">
<xsl:value-of select="1"/>
</xsl:when>
<xsl:when test="starts-with($line, '#')">
<xsl:value-of select="1"/>
</xsl:when>
<xsl:when test="starts-with($line, ' ')">
<xsl:call-template name="is_blank_or_comment">
<xsl:with-param name="line" select="substring($line, 2)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="0"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Determine whether the given line ends with a colon. Note that Python
style comments are ignored so the following lines return True:
- def foo():
- def foo(): # Bar
- if(foo):
But some code may confuse this function. For example the following are
also consider to "end_with_colon" even though they don't for Python
- foo(": #")
- foo() # No need for :
-->
<xsl:template name="ends_with_colon">
<xsl:param name="line"/>
<xsl:param name="found_colon"/>
<xsl:choose>
<xsl:when test="$line = ''">
<xsl:value-of select="$found_colon"/>
</xsl:when>
<xsl:when test="starts-with($line, '&#xA;')">
<xsl:value-of select="$found_colon"/>
</xsl:when>
<xsl:when test="starts-with($line, ' ')">
<xsl:call-template name="ends_with_colon">
<xsl:with-param name="line" select="substring($line, 2)"/>
<xsl:with-param name="found_colon" select="$found_colon"/>
</xsl:call-template>
</xsl:when>
<xsl:when test="starts-with($line, ':')">
<xsl:variable name="rest_is_comment">
<xsl:call-template name="is_blank_or_comment">
<xsl:with-param name="line" select="substring($line, 2)"/>
</xsl:call-template>
</xsl:variable>
<xsl:choose>
<xsl:when test="$rest_is_comment = '1'">
<xsl:value-of select="1"/>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="ends_with_colon">
<xsl:with-param name="line" select="substring($line, 2)"/>
<xsl:with-param name="found_colon" select="0"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:call-template name="ends_with_colon">
<xsl:with-param name="line" select="substring($line, 2)"/>
<xsl:with-param name="found_colon" select="0"/>
</xsl:call-template>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Prints one line of python code with proper indent and calls itself
recursively for the rest of the text.
This template uses "a", "b", "c" and "d" to refer to four key column
numbers. They are:
- a: the indentation common to all lines in a code snippet. This is
stripped out to allow for cleaner code in the xml.
- b: the indentation of the most out-dented line of code. This is
different from "a" when code is labelled with "Yes:" or "No:"
- c: the indentation of the current python block, in other words, the
indentation of the first line of this block, which is the
indentation of the last line we saw that ended with a colon.
- d: the "total" indentation of the line, ignorng possible "Yes:" or
"No:" text on the line.
For example, for the last line of the following code snippet, the
positions of a, b, c and d are indicated below:
Yes: def Foo():
if bar():
a += 1
baz()
a b c d
The algorithm is:
1) Split the text into first line and the rest. Note that the
substring-before function is supposed to handle the case where the
character is not present in the string but does not so we
automatically ignore the last line of the snippet which is always
empty (the closing snippet tag). This is consistent with the
behavior or print_without_leading_chars.
2) If the current is empty (only whitespace), print newline and call
itself recursively on the rest of the text with the rest of the
parameters unchanged.
3) Otherwise, measure "d"
4) Measure "c" by taking:
- the value of "d" if the previous line ended with a colon or the
current line is outdented compare to the previous line
- the indent of the previous line otherwise
5) Print line[a:c] (Note that we ignore line[0:a])
6) Print line[b:c] in an external span (in order to double the block
indent in external code).
7) Print line[c:<end>] with function names processed to produce both
internal and external names.
8) If there are more lines, recurse.
-->
<xsl:template name="print_python_line_recursively">
<xsl:param name="text"/>
<xsl:param name="a"/>
<xsl:param name="b"/>
<xsl:param name="previous_indent"/>
<xsl:param name="previous_ends_with_colon"/>
<xsl:param name="is_first_line"/>
<xsl:variable name="line" select="substring-before($text, '&#xA;')"/>
<xsl:variable name="rest" select="substring-after($text, '&#xA;')"/>
<xsl:choose>
<xsl:when test="substring($line, $b) = '' and not($rest = '')">
<xsl:if test="not($is_first_line = '1')">
<xsl:text>&#xA;</xsl:text>
</xsl:if>
<xsl:call-template name="print_python_line_recursively">
<xsl:with-param name="text" select="$rest"/>
<xsl:with-param name="a" select="$a"/>
<xsl:with-param name="b" select="$b"/>
<xsl:with-param name="previous_indent" select="$previous_indent"/>
<xsl:with-param name="previous_ends_with_colon"
select="$previous_ends_with_colon"/>
<xsl:with-param name="is_first_line" select="0"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="indent_after_b">
<xsl:call-template name="num_leading_spaces_one_line">
<xsl:with-param name="text" select="substring($line, $b + 1)"/>
<xsl:with-param name="current_count" select="0"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="d" select="$b + $indent_after_b"/>
<xsl:variable name="c">
<xsl:choose>
<xsl:when test="$previous_ends_with_colon = '1' or
$previous_indent > $d">
<xsl:value-of select="$d"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$previous_indent"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:value-of select="substring($line, $a + 1, $c - $a)"/>
<span class="external">
<xsl:value-of select="substring($line, $b + 1, $c - $b)"/>
</span>
<xsl:call-template name="munge_function_names_in_text">
<xsl:with-param name="stripped_line"
select="substring($line, $c + 1)"/>
</xsl:call-template>
<xsl:if test="not(substring($rest, $a) = '')">
<xsl:text>&#xA;</xsl:text>
<xsl:call-template name="print_python_line_recursively">
<xsl:with-param name="text" select="$rest"/>
<xsl:with-param name="a" select="$a"/>
<xsl:with-param name="b" select="$b"/>
<xsl:with-param name="previous_indent" select="$c"/>
<xsl:with-param name="previous_ends_with_colon">
<xsl:call-template name="ends_with_colon">
<xsl:with-param name="line" select="$line"/>
<xsl:with-param name="found_colon" select="0"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="is_first_line" select="0"/>
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Print python code with internal and external styles.
In order to conform with PEP-8 externally, we identify 2-space indents
and an external-only 4-space indent.
Function names that are marked with $$FunctionName/$$ have an external
lower_with_underscore version added. -->
<xsl:template name="print_python_code">
<xsl:param name="text"/>
<xsl:variable name="a">
<xsl:call-template name="num_leading_spaces">
<xsl:with-param name="text" select="."/>
<xsl:with-param name="max_so_far" select="1000"/>
</xsl:call-template>
</xsl:variable>
<xsl:variable name="b">
<xsl:call-template name="code_start_index">
<xsl:with-param name="text" select="$text"/>
<xsl:with-param name="current_count" select="0"/>
</xsl:call-template>
</xsl:variable>
<xsl:call-template name="print_python_line_recursively">
<xsl:with-param name="text" select="$text"/>
<xsl:with-param name="a" select="$a"/>
<xsl:with-param name="b" select="$b"/>
<xsl:with-param name="previous_indent" select="$b"/>
<xsl:with-param name="previous_ends_with_colon" select="0"/>
<xsl:with-param name="is_first_line" select="1"/>
</xsl:call-template>
</xsl:template>
<!-- Given a block of text, each line terminated by \n, and a number n,
emits the text with the first n characters of each line
deleted. If strip==1, then we omit blank lines at the beginning
@ -474,6 +788,7 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!-- TODO(csilvers): deal with case text doesn't end in a newline -->
<xsl:variable name="line" select="substring-before($text, '&#xA;')"/>
<xsl:variable name="rest" select="substring-after($text, '&#xA;')"/>
<xsl:variable name="stripped_line" select="substring($line, $trim_count+1)"/>
<xsl:choose>
<!-- $line (or $rest) is considered empty if we'd trim the entire line -->
<xsl:when test="($strip = '1') and ($is_firstline = '1') and
@ -481,10 +796,10 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format">
</xsl:when>
<xsl:when test="($strip = '1') and
(string-length($rest) &lt;= $trim_count)">
<xsl:value-of select="substring($line, $trim_count+1)"/>
<xsl:value-of select="$stripped_line"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="substring($line, $trim_count+1)"/>
<xsl:value-of select="$stripped_line"/>
<xsl:text>&#xA;</xsl:text>
</xsl:otherwise>
</xsl:choose>
@ -498,5 +813,66 @@ xmlns:fo="http://www.w3.org/1999/XSL/Format">
</xsl:if>
</xsl:template>
<!-- Given a line of code, find function names that are marked with $$ /$$ and
print out the line with the internal and external versions of the
function names.-->
<xsl:template name="munge_function_names_in_text">
<xsl:param name="stripped_line"/>
<xsl:choose>
<xsl:when test="contains($stripped_line, '$$')">
<xsl:value-of select="substring-before($stripped_line, '$$')"/>
<xsl:call-template name="print_function_name">
<xsl:with-param name="text" select="substring-after(substring-before($stripped_line, '/$$'), '$$')"/>
</xsl:call-template>
<xsl:call-template name="munge_function_names_in_text">
<xsl:with-param name="stripped_line" select="substring-after($stripped_line, '/$$')"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$stripped_line"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<!-- Given a function name, print out both the internal and external version
of the function name in their respective spans.-->
<xsl:template name="print_function_name">
<xsl:param name="text"/>
<span class="internal"><xsl:value-of select="$text"/></span>
<span class="external">
<xsl:call-template name="convert_camel_case_to_lowercase_with_under">
<xsl:with-param name="text" select="$text"/>
</xsl:call-template>
</span>
</xsl:template>
<!-- Given a single word of text convert it from CamelCase to
lower_with_under.
This means replacing each uppercase character with _ followed by the
lowercase version except for the first character which is replaced
without adding the _.-->
<xsl:template name="convert_camel_case_to_lowercase_with_under">
<xsl:param name="text"/>
<xsl:param name="is_recursive_call"/>
<xsl:variable name="first_char" select="substring($text, 1, 1)"/>
<xsl:variable name="rest" select="substring($text, 2)"/>
<xsl:choose>
<xsl:when test="contains('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $first_char)">
<xsl:if test="$is_recursive_call='1'">
<xsl:text>_</xsl:text>
</xsl:if>
<xsl:value-of select="translate($first_char, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$first_char" />
</xsl:otherwise>
</xsl:choose>
<xsl:if test="not($rest='')">
<xsl:call-template name="convert_camel_case_to_lowercase_with_under">
<xsl:with-param name="text" select="$rest"/>
<xsl:with-param name="is_recursive_call" select="1"/>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>