Support extracting inline example documentation.

Fixes #1

RELNOTES: Support inline example documentation.

--
MOS_MIGRATED_REVID=119726298
diff --git a/skydoc/common.py b/skydoc/common.py
index 8707479..517648d 100644
--- a/skydoc/common.py
+++ b/skydoc/common.py
@@ -15,13 +15,87 @@
 """Common functions for skydoc."""
 
 import re
+import textwrap
 from xml.sax.saxutils import escape
 
 
+ARGS_HEADING = "Args:"
+EXAMPLES_HEADING = "Examples:"
+EXAMPLE_HEADING = "Example:"
+
+
 def leading_whitespace(line):
+  """Returns the number of leading whitespace in the line."""
   return len(line) - len(line.lstrip())
 
-def parse_attribute_doc(doc):
+
+def _parse_attribute_docs(attr_doc, lines, index):
+  """Extracts attribute documentation.
+
+  Args:
+    attr_doc: A dict used to store the extracted attribute documentation.
+    lines: List containing the input docstring split into lines.
+    index: The index in lines containing "Args:", which begins the argument
+        documentation.
+
+  Returns:
+    Returns the next index after the attribute documentation to resume
+    processing documentation in the caller.
+  """
+  attr = None  # Current attribute name
+  desc = None  # Description for current attribute
+  args_leading_ws = leading_whitespace(lines[index])
+  i = index + 1
+  while i < len(lines):
+    line = lines[i]
+    # If a blank line is encountered, we have finished parsing the "Args"
+    # section.
+    if line.strip() and leading_whitespace(line) == args_leading_ws:
+      break
+    # In practice, users sometimes add a "-" prefix, so we strip it even
+    # though it is not recommended by the style guide
+    match = re.search(r"^\s*-?\s*(\w+):\s*(.*)", line)
+    if match:  # We have found a new attribute
+      if attr:
+        attr_doc[attr] = escape(desc)
+      attr, desc = match.group(1), match.group(2)
+    elif attr:
+      # Merge documentation when it is multiline
+      desc = desc + "\n" + line.strip()
+    i += + 1
+
+  if attr:
+    attr_doc[attr] = escape(desc).strip()
+
+  return i
+
+
+def _parse_example_docs(examples, lines, index):
+  """Extracts example documentation.
+
+  Args:
+    examples: A list to contain the lines containing the example documentation.
+    lines: List containing the input docstring split into lines.
+    index: The index in lines containing "Example[s]:", which begins the
+        example documentation.
+
+  Returns:
+    Returns the next index after the attribute documentation to resume
+    processing documentation in the caller.
+  """
+  heading_leading_ws = leading_whitespace(lines[index])
+  i = index + 1
+  while i < len(lines):
+    line = lines[i]
+    if line.strip() and leading_whitespace(line) == heading_leading_ws:
+      break
+    examples.append(line)
+    i += 1
+
+  return i
+
+
+def parse_docstring(doc):
   """Analyzes the documentation string for attributes.
 
   This looks for the "Args:" separator to fetch documentation for each
@@ -34,33 +108,23 @@
     The new documentation string and a dictionary that maps each attribute to
     its documentation
   """
-  doc_attr = {}
+  attr_doc = {}
+  examples = []
   lines = doc.split("\n")
-  if "Args:" not in lines:
-    return doc, doc_attr
-  start = lines.index("Args:")
+  docs = []
+  i = 0
+  while i < len(lines):
+    line = lines[i]
+    if line.strip() == ARGS_HEADING:
+      i = _parse_attribute_docs(attr_doc, lines, i)
+      continue
+    elif line.strip() == EXAMPLES_HEADING or line.strip() == EXAMPLE_HEADING:
+      i = _parse_example_docs(examples, lines, i)
+      continue
 
-  i = start + 1
-  var = None  # Current attribute name
-  desc = None  # Description for current attribute
-  args_leading_ws = leading_whitespace(lines[start])
-  for i in xrange(start + 1, len(lines)):
-    # If a blank line is encountered, we have finished parsing the "Args"
-    # section.
-    if lines[i].strip() and leading_whitespace(lines[i]) == args_leading_ws:
-      break
-    # In practice, users sometimes add a "-" prefix, so we strip it even
-    # though it is not recommended by the style guide
-    match = re.search(r"^\s*-?\s*(\w+):\s*(.*)", lines[i])
-    if match:  # We have found a new attribute
-      if var:
-        doc_attr[var] = escape(desc)
-      var, desc = match.group(1), match.group(2)
-    elif var:
-      # Merge documentation when it is multiline
-      desc = desc + "\n" + lines[i].strip()
+    docs.append(line)
+    i += 1
 
-  if var:
-    doc_attr[var] = escape(desc)
-  doc = "\n".join(lines[:start - 1])
-  return doc, doc_attr
+  doc = "\n".join(docs).strip()
+  examples_doc = textwrap.dedent("\n".join(examples)).strip()
+  return doc, attr_doc, examples_doc