1. Thejesh GN
  2. pycco

Commits

Thejesh GN  committed 9b5e074

initial

  • Participants
  • Branches default

Comments (0)

Files changed (7)

File pycco/AUTHORS

View file
+Alexis Metaireau
+Anders Bergh
+Antti Kaihola
+Christopher Gateley
+Jack Miller
+Morgan Goose
+Nick Fitzgerald
+goosemo
+khamidou

File pycco/LICENSE

View file
+Copyright (c) 2010 Nick Fitzgerald
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+Parts of Pycco are taken from Docco, see http://github.com/jashkenas/docco for
+more information.

File pycco/README

View file
+888888b.
+888   Y88b
+888    888
+888   d88P  888  888   .d8888b  .d8888b  .d88b.
+8888888P"   888  888  d88P"    d88P"    d88""88b
+888         888  888  888      888      888  888
+888         Y88b 888  Y88b.    Y88b.    Y88..88P
+888          "Y88888   "Y8888P  "Y8888P  "Y88P"
+                 888
+            Y8b d88P
+             "Y88P"
+
+Pycco is a Python port of Docco: the original quick-and-dirty, hundred-line-
+long, literate-programming-style documentation generator. For more information,
+see:
+
+http://fitzgen.github.com/pycco/
+
+Others:
+
+CoffeeScript (Original) - http://jashkenas.github.com/docco/
+
+Ruby - http://rtomayko.github.com/rocco/
+
+Sh - http://rtomayko.github.com/shocco/

File pycco/pycco/__init__.py

View file
+from .main import *
+
+__all__ = ("process",)

File pycco/pycco/main.py

View file
+#!/usr/bin/env python
+
+# "**Pycco**" is a Python port of [Docco](http://jashkenas.github.com/docco/ ):
+# the original quick-and-dirty, hundred-line-long, literate-programming-style
+# documentation generator. It produces HTML that displays your comments
+# alongside your code. Comments are passed through
+# [Markdown](http://daringfireball.net/projects/markdown/syntax) and
+# [SmartyPants](http://daringfireball.net/projects/smartypants), while code is
+# passed through [Pygments](http://pygments.org/) for syntax highlighting.
+# This page is the result of running Pycco against its own source file.
+#
+# If you install Pycco, you can run it from the command-line:
+#
+#     pycco src/*.py
+#
+# This will generate linked HTML documentation for the named source files,
+# saving it into a `docs` folder by default.
+#
+# To install Pycco, simply
+#
+#     pip install pycco
+#
+# Or, to install the latest source
+#
+#     git clone git://github.com/fitzgen/pycco.git
+#     cd pycco
+#     python setup.py install
+
+# === Main Documentation Generation Functions ===
+
+# Generate the documentation for a source file by reading it in, splitting it up
+# into comment/code sections, highlighting them for the appropriate language,
+# and merging them into an HTML template.
+def generate_documentation(source, outdir=None, preserve_paths=True):
+    if not outdir:
+        raise TypeError("Missing the required 'outdir' keyword argument.")
+    fh = open(source, "r")
+    sections = parse(source, fh.read())
+    highlight(source, sections, preserve_paths=preserve_paths, outdir=outdir)
+    return generate_html(source, sections, preserve_paths=preserve_paths, outdir=outdir)
+
+# Given a string of source code, parse out each comment and the code that
+# follows it, and create an individual **section** for it.
+# Sections take the form:
+#
+#     { "docs_text": ...,
+#       "docs_html": ...,
+#       "code_text": ...,
+#       "code_html": ...,
+#       "num":       ...
+#     }
+#
+def parse(source, code):
+    lines = code.split("\n")
+    sections = []
+    language = get_language(source)
+    has_code = docs_text = code_text = ""
+
+    if lines[0].startswith("#!"):
+        lines.pop(0)
+
+    if language["name"] == "python":
+        for linenum, line in enumerate(lines[:2]):
+            if re.search(r'coding[:=]\s*([-\w.]+)', lines[linenum]):
+                lines.pop(linenum)
+                break
+
+
+    def save(docs, code):
+        if docs and code:
+            sections.append({
+                "docs_text": docs,
+                "code_text": code
+            })
+
+    # Setup the variables to get ready to check for multiline comments
+    preformatted = multi_line = False
+    last_scope = 0
+    multi_line_delimiters = [language.get("multistart"), language.get("multiend")]
+
+    for line in lines:
+
+        # Only go into multiline comments section when one of the delimiters is
+        # found to be at the start of a line
+        if all(multi_line_delimiters) and any([line.lstrip().startswith(delim) for delim in multi_line_delimiters]):
+            if not multi_line:
+                multi_line = True
+
+            else:
+                multi_line = False
+
+            # Get rid of the delimiters so that they aren't in the final docs
+            line = re.sub(re.escape(language["multistart"]),'',line)
+            line = re.sub(re.escape(language["multiend"]),'',line)
+            docs_text += line.strip() + '\n'
+
+            if has_code and docs_text.strip():
+                save(docs_text, code_text[:-1])
+                code_text = code_text.split('\n')[-1]
+                last_scope = 0
+                has_code = docs_text = ''
+
+        elif multi_line:
+            line_striped = line.rstrip()
+            current_scope = line_striped.count("    ")
+
+            # This section will parse if the line is indented at least four
+            # places, and if so know to have the final text treat it as a
+            # preformatted text block.
+            if line_striped.startswith("    ") and last_scope:
+                if current_scope > last_scope and not preformatted:
+                    preformatted = True
+                    docs_text += "<pre>"
+
+            else:
+                if preformatted:
+                    preformatted = False
+                    docs_text += "</pre>"
+
+            # Keep a tracker var to see if the scope increases, that way later
+            # the code can decided if a section is indented more than 4 spaces
+            # from the leading code.
+            last_scope = current_scope if current_scope > last_scope else last_scope
+            docs_text += line.strip() + '\n'
+
+        elif re.match(language["comment_matcher"], line):
+            if has_code:
+                save(docs_text, code_text)
+                has_code = docs_text = code_text = ''
+            docs_text += re.sub(language["comment_matcher"], "", line) + "\n"
+
+        else:
+            if code_text and any([line.lstrip().startswith(x) for x in ['class ', 'def ']]):
+                save(docs_text, code_text)
+                code_text = has_code = docs_text = ''
+
+            has_code = True
+            code_text += line + '\n'
+
+
+    save(docs_text, code_text)
+    return sections
+
+# === Preprocessing the comments ===
+
+# Add cross-references before having the text processed by markdown.  It's
+# possible to reference another file, like this : `[[main.py]]` which renders
+# [[main.py]]. You can also reference a specific section of another file, like
+# this: `[[main.py#highlighting-the-source-code]]` which renders as
+# [[main.py#highlighting-the-source-code]]. Sections have to be manually
+# declared; they are written on a single line, and surrounded by equals signs:
+# `=== like this ===`
+def preprocess(comment, section_nr, preserve_paths=True, outdir=None):
+    if not outdir:
+        raise TypeError("Missing the required 'outdir' keyword argument.")
+    def sanitize_section_name(name):
+        return "-".join(name.lower().strip().split(" "))
+
+    def replace_crossref(match):
+        # Check if the match contains an anchor
+        if '#' in match.group(1):
+            name, anchor = match.group(1).split('#')
+            return " [%s](%s#%s)" % (name,
+                                     path.basename(destination(name,
+                                                               preserve_paths=preserve_paths,
+                                                               outdir=outdir)),
+                                     anchor)
+
+        else:
+            return " [%s](%s)" % (match.group(1),
+                                  path.basename(destination(match.group(1),
+                                                            preserve_paths=preserve_paths,
+                                                            outdir=outdir)))
+
+    def replace_section_name(match):
+        return '%(lvl)s <span id="%(id)s" href="%(id)s">%(name)s</span>' % {
+            "lvl"  : re.sub('=', '#', match.group(1)),
+            "id"   : sanitize_section_name(match.group(2)),
+            "name" : match.group(2)
+        }
+
+    comment = re.sub('^([=]+)([^=]+)[=]*\\n', replace_section_name, comment)
+    comment = re.sub('[^`]\[\[(.+)\]\]', replace_crossref, comment)
+
+    return comment
+
+# === Highlighting the source code ===
+
+# Highlights a single chunk of code using the **Pygments** module, and runs the
+# text of its corresponding comment through **Markdown**.
+#
+# We process the entire file in a single call to Pygments by inserting little
+# marker comments between each section and then splitting the result string
+# wherever our markers occur.
+def highlight(source, sections, preserve_paths=True, outdir=None):
+    if not outdir:
+        raise TypeError("Missing the required 'outdir' keyword argument.")
+    language = get_language(source)
+
+    output = pygments.highlight(language["divider_text"].join(section["code_text"] for section in sections),
+                                language["lexer"],
+                                formatters.get_formatter_by_name("html"))
+
+    output = output.replace(highlight_start, "").replace(highlight_end, "")
+    fragments = re.split(language["divider_html"], output)
+    for i, section in enumerate(sections):
+        section["code_html"] = highlight_start + shift(fragments, "") + highlight_end
+        try:
+            docs_text = unicode(section["docs_text"])
+        except UnicodeError:
+            docs_text = unicode(section["docs_text"].decode('utf-8'))
+        section["docs_html"] = markdown(preprocess(docs_text,
+                                                   i,
+                                                   preserve_paths=preserve_paths,
+                                                   outdir=outdir))
+        section["num"] = i
+
+# === HTML Code generation ===
+
+# Once all of the code is finished highlighting, we can generate the HTML file
+# and write out the documentation. Pass the completed sections into the template
+# found in `resources/pycco.html`.
+#
+# Pystache will attempt to recursively render context variables, so we must
+# replace any occurences of `{{`, which is valid in some languages, with a
+# "unique enough" identifier before rendering, and then post-process the
+# rendered template and change the identifier back to `{{`.
+def generate_html(source, sections, preserve_paths=True, outdir=None):
+    if not outdir:
+        raise TypeError("Missing the required 'outdir' keyword argument")
+    title = path.basename(source)
+    dest = destination(source, preserve_paths=preserve_paths, outdir=outdir)
+
+    for sect in sections:
+        sect["code_html"] = re.sub(r"\{\{", r"__DOUBLE_OPEN_STACHE__", sect["code_html"])
+
+    rendered = pycco_template({
+        "title"       : title,
+        "stylesheet"  : path.relpath(path.join(path.dirname(dest), "pycco.css"),
+                                     path.split(dest)[0]),
+        "sections"    : sections,
+        "source"      : source,
+        "path"        : path,
+        "destination" : destination
+    })
+
+    return re.sub(r"__DOUBLE_OPEN_STACHE__", "{{", rendered).encode("utf-8")
+
+# === Helpers & Setup ===
+
+# This module contains all of our static resources.
+import pycco_resources
+
+# Import our external dependencies.
+import optparse
+import os
+import pygments
+import pystache
+import re
+import sys
+from markdown import markdown
+from os import path
+from pygments import lexers, formatters
+
+# A list of the languages that Pycco supports, mapping the file extension to
+# the name of the Pygments lexer and the symbol that indicates a comment. To
+# add another language to Pycco's repertoire, add it here.
+languages = {
+    ".coffee": { "name": "coffee-script", "symbol": "#" },
+
+    ".pl":  { "name": "perl", "symbol": "#" },
+
+    ".sql": { "name": "sql", "symbol": "--" },
+
+    ".c":   { "name": "c", "symbol": "//"},
+
+    ".cpp": { "name": "cpp", "symbol": "//"},
+
+    ".js": { "name": "javascript", "symbol": "//",
+        "multistart": "/*", "multiend": "*/"},
+
+    ".rb": { "name": "ruby", "symbol": "#",
+        "multistart": "=begin", "multiend": "=end"},
+
+    ".py": { "name": "python", "symbol": "#",
+        "multistart": '"""', "multiend": '"""' },
+
+    ".scm": { "name": "scheme", "symbol": ";;",
+        "multistart": "#|", "multiend": "|#"},
+
+    ".lua": { "name": "lua", "symbol": "--",
+        "multistart": "--[[", "mutliend": "--]]"},
+
+    ".erl": { "name": "erlang", "symbol": "%%" },
+}
+
+# Build out the appropriate matchers and delimiters for each language.
+for ext, l in languages.items():
+    # Does the line begin with a comment?
+    l["comment_matcher"] = re.compile(r"^\s*" + l["symbol"] + "\s?")
+
+    # The dividing token we feed into Pygments, to delimit the boundaries between
+    # sections.
+    l["divider_text"] = "\n" + l["symbol"] + "DIVIDER\n"
+
+    # The mirror of `divider_text` that we expect Pygments to return. We can split
+    # on this to recover the original sections.
+    l["divider_html"] = re.compile(r'\n*<span class="c[1]?">' + l["symbol"] + 'DIVIDER</span>\n*')
+
+    # Get the Pygments Lexer for this language.
+    l["lexer"] = lexers.get_lexer_by_name(l["name"])
+
+# Get the current language we're documenting, based on the extension.
+def get_language(source):
+    try:
+        return languages[ source[source.rindex("."):] ]
+    except ValueError:
+        source = open(source, "r")
+        code = source.read()
+        source.close()
+        lang = lexers.guess_lexer(code).name.lower()
+        for l in languages.values():
+            if l["name"] == lang:
+                return l
+        else:
+            raise ValueError("Can't figure out the language!")
+
+# Compute the destination HTML path for an input source file path. If the source
+# is `lib/example.py`, the HTML will be at `docs/example.html`
+def destination(filepath, preserve_paths=True, outdir=None):
+    if not outdir:
+        raise TypeError("Missing the required 'outdir' keyword argument.")
+    try:
+        name = filepath.replace(filepath[ filepath.rindex("."): ], "")
+    except ValueError:
+        name = filepath
+    if not preserve_paths:
+        name = path.basename(name)
+    return path.join(outdir, "%s.html" % name)
+
+# Shift items off the front of the `list` until it is empty, then return
+# `default`.
+def shift(list, default):
+    try:
+        return list.pop(0)
+    except IndexError:
+        return default
+
+# Ensure that the destination directory exists.
+def ensure_directory(directory):
+    if not os.path.isdir(directory):
+        os.mkdir(directory)
+
+def template(source):
+    return lambda context: pystache.render(source, context)
+
+# Create the template that we will use to generate the Pycco HTML page.
+pycco_template = template(pycco_resources.html)
+
+# The CSS styles we'd like to apply to the documentation.
+pycco_styles = pycco_resources.css
+
+# The start of each Pygments highlight block.
+highlight_start = "<div class=\"highlight\"><pre>"
+
+# The end of each Pygments highlight block.
+highlight_end = "</pre></div>"
+
+# For each source file passed in as an argument, generate the documentation.
+def process(sources, preserve_paths=True, outdir=None):
+    if not outdir:
+        raise TypeError("Missing the required 'outdir' keyword argument.")
+
+    sources.sort()
+    if sources:
+        ensure_directory(outdir)
+        css = open(path.join(outdir, "pycco.css"), "w")
+        css.write(pycco_styles)
+        css.close()
+
+        def next_file():
+            s = sources.pop(0)
+            dest = destination(s, preserve_paths=preserve_paths, outdir=outdir)
+
+            try:
+                os.makedirs(path.split(dest)[0])
+            except OSError:
+                pass
+
+            with open(destination(s, preserve_paths=preserve_paths, outdir=outdir), "w") as f:
+                f.write(generate_documentation(s, outdir=outdir))
+
+            print "pycco = %s -> %s" % (s, dest)
+
+            if sources:
+                next_file()
+        next_file()
+
+__all__ = ("process", "generate_documentation")
+
+# Hook spot for the console script.
+def main():
+    parser = optparse.OptionParser()
+    parser.add_option('-p', '--paths', action='store_true',
+                      help='Preserve path structure of original files')
+
+    parser.add_option('-d', '--directory', action='store', type='string',
+                      dest='outdir', default='docs',
+                      help='The output directory that the rendered files should go to.')
+
+    opts, sources = parser.parse_args()
+    process(sources, outdir=opts.outdir, preserve_paths=opts.paths)
+
+# Run the script.
+if __name__ == "__main__":
+    main()

File pycco/pycco_resources/__init__.py

View file
+css = """\
+/*--------------------- Layout and Typography ----------------------------*/
+body {
+  font-family: 'Palatino Linotype', 'Book Antiqua', Palatino, FreeSerif, serif;
+  font-size: 16px;
+  line-height: 24px;
+  color: #252519;
+  margin: 0; padding: 0;
+}
+a {
+  color: #261a3b;
+}
+  a:visited {
+    color: #261a3b;
+  }
+p {
+  margin: 0 0 15px 0;
+}
+h1, h2, h3, h4, h5, h6 {
+  margin: 40px 0 15px 0;
+}
+h2, h3, h4, h5, h6 {
+    margin-top: 0;
+  }
+#container, div.section {
+  position: relative;
+}
+#background {
+  position: fixed;
+  top: 0; left: 580px; right: 0; bottom: 0;
+  background: #f5f5ff;
+  border-left: 1px solid #e5e5ee;
+  z-index: -1;
+}
+#jump_to, #jump_page {
+  background: white;
+  -webkit-box-shadow: 0 0 25px #777; -moz-box-shadow: 0 0 25px #777;
+  -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomleft: 5px;
+  font: 10px Arial;
+  text-transform: uppercase;
+  cursor: pointer;
+  text-align: right;
+}
+#jump_to, #jump_wrapper {
+  position: fixed;
+  right: 0; top: 0;
+  padding: 5px 10px;
+}
+  #jump_wrapper {
+    padding: 0;
+    display: none;
+  }
+    #jump_to:hover #jump_wrapper {
+      display: block;
+    }
+    #jump_page {
+      padding: 5px 0 3px;
+      margin: 0 0 25px 25px;
+    }
+      #jump_page .source {
+        display: block;
+        padding: 5px 10px;
+        text-decoration: none;
+        border-top: 1px solid #eee;
+      }
+        #jump_page .source:hover {
+          background: #f5f5ff;
+        }
+        #jump_page .source:first-child {
+        }
+div.docs {
+  float: left;
+  max-width: 500px;
+  min-width: 500px;
+  min-height: 5px;
+  padding: 10px 25px 1px 50px;
+  vertical-align: top;
+  text-align: left;
+}
+  .docs pre {
+    margin: 15px 0 15px;
+    padding-left: 15px;
+  }
+  .docs p tt, .docs p code {
+    background: #f8f8ff;
+    border: 1px solid #dedede;
+    font-size: 12px;
+    padding: 0 0.2em;
+  }
+  .octowrap {
+    position: relative;
+  }
+    .octothorpe {
+      font: 12px Arial;
+      text-decoration: none;
+      color: #454545;
+      position: absolute;
+      top: 3px; left: -20px;
+      padding: 1px 2px;
+      opacity: 0;
+      -webkit-transition: opacity 0.2s linear;
+    }
+      div.docs:hover .octothorpe {
+        opacity: 1;
+      }
+div.code {
+  margin-left: 580px;
+  padding: 14px 15px 16px 50px;
+  vertical-align: top;
+}
+  .code pre, .docs p code {
+    font-size: 12px;
+  }
+    pre, tt, code {
+      line-height: 18px;
+      font-family: Monaco, Consolas, "Lucida Console", monospace;
+      margin: 0; padding: 0;
+    }
+div.clearall {
+    clear: both;
+}
+
+
+/*---------------------- Syntax Highlighting -----------------------------*/
+td.linenos { background-color: #f0f0f0; padding-right: 10px; }
+span.lineno { background-color: #f0f0f0; padding: 0 5px 0 5px; }
+body .hll { background-color: #ffffcc }
+body .c { color: #408080; font-style: italic }  /* Comment */
+body .err { border: 1px solid #FF0000 }         /* Error */
+body .k { color: #954121 }                      /* Keyword */
+body .o { color: #666666 }                      /* Operator */
+body .cm { color: #408080; font-style: italic } /* Comment.Multiline */
+body .cp { color: #BC7A00 }                     /* Comment.Preproc */
+body .c1 { color: #408080; font-style: italic } /* Comment.Single */
+body .cs { color: #408080; font-style: italic } /* Comment.Special */
+body .gd { color: #A00000 }                     /* Generic.Deleted */
+body .ge { font-style: italic }                 /* Generic.Emph */
+body .gr { color: #FF0000 }                     /* Generic.Error */
+body .gh { color: #000080; font-weight: bold }  /* Generic.Heading */
+body .gi { color: #00A000 }                     /* Generic.Inserted */
+body .go { color: #808080 }                     /* Generic.Output */
+body .gp { color: #000080; font-weight: bold }  /* Generic.Prompt */
+body .gs { font-weight: bold }                  /* Generic.Strong */
+body .gu { color: #800080; font-weight: bold }  /* Generic.Subheading */
+body .gt { color: #0040D0 }                     /* Generic.Traceback */
+body .kc { color: #954121 }                     /* Keyword.Constant */
+body .kd { color: #954121; font-weight: bold }  /* Keyword.Declaration */
+body .kn { color: #954121; font-weight: bold }  /* Keyword.Namespace */
+body .kp { color: #954121 }                     /* Keyword.Pseudo */
+body .kr { color: #954121; font-weight: bold }  /* Keyword.Reserved */
+body .kt { color: #B00040 }                     /* Keyword.Type */
+body .m { color: #666666 }                      /* Literal.Number */
+body .s { color: #219161 }                      /* Literal.String */
+body .na { color: #7D9029 }                     /* Name.Attribute */
+body .nb { color: #954121 }                     /* Name.Builtin */
+body .nc { color: #0000FF; font-weight: bold }  /* Name.Class */
+body .no { color: #880000 }                     /* Name.Constant */
+body .nd { color: #AA22FF }                     /* Name.Decorator */
+body .ni { color: #999999; font-weight: bold }  /* Name.Entity */
+body .ne { color: #D2413A; font-weight: bold }  /* Name.Exception */
+body .nf { color: #0000FF }                     /* Name.Function */
+body .nl { color: #A0A000 }                     /* Name.Label */
+body .nn { color: #0000FF; font-weight: bold }  /* Name.Namespace */
+body .nt { color: #954121; font-weight: bold }  /* Name.Tag */
+body .nv { color: #19469D }                     /* Name.Variable */
+body .ow { color: #AA22FF; font-weight: bold }  /* Operator.Word */
+body .w { color: #bbbbbb }                      /* Text.Whitespace */
+body .mf { color: #666666 }                     /* Literal.Number.Float */
+body .mh { color: #666666 }                     /* Literal.Number.Hex */
+body .mi { color: #666666 }                     /* Literal.Number.Integer */
+body .mo { color: #666666 }                     /* Literal.Number.Oct */
+body .sb { color: #219161 }                     /* Literal.String.Backtick */
+body .sc { color: #219161 }                     /* Literal.String.Char */
+body .sd { color: #219161; font-style: italic } /* Literal.String.Doc */
+body .s2 { color: #219161 }                     /* Literal.String.Double */
+body .se { color: #BB6622; font-weight: bold }  /* Literal.String.Escape */
+body .sh { color: #219161 }                     /* Literal.String.Heredoc */
+body .si { color: #BB6688; font-weight: bold }  /* Literal.String.Interpol */
+body .sx { color: #954121 }                     /* Literal.String.Other */
+body .sr { color: #BB6688 }                     /* Literal.String.Regex */
+body .s1 { color: #219161 }                     /* Literal.String.Single */
+body .ss { color: #19469D }                     /* Literal.String.Symbol */
+body .bp { color: #954121 }                     /* Name.Builtin.Pseudo */
+body .vc { color: #19469D }                     /* Name.Variable.Class */
+body .vg { color: #19469D }                     /* Name.Variable.Global */
+body .vi { color: #19469D }                     /* Name.Variable.Instance */
+body .il { color: #666666 }                     /* Literal.Number.Integer.Long */
+"""
+
+html = """\
+<!DOCTYPE html>
+<html>
+<head>
+  <meta http-equiv="content-type" content="text/html;charset=utf-8">
+  <title>{{ title }}</title>
+  <link rel="stylesheet" href="{{ stylesheet }}">
+</head>
+<body>
+<div id="background"></div>
+<div id='container'>
+  {{#sources?}}
+  <div id="jump_to">
+    Jump To &hellip;
+    <div id="jump_wrapper">
+      <div id="jump_page">
+        {{#sources}}
+          <a class="source" href="{{ url }}">{{ basename }}</a>
+        {{/sources}}
+      </div>
+    </div>
+  </div>
+  {{/sources?}}
+  <div class='section'>
+    <div class='docs'><h1>{{ title }}</h1></div>
+  </div>
+  <div class='clearall'>
+  {{#sections}}
+  <div class='section' id='section-{{ num }}'>
+    <div class='docs'>
+      <div class='octowrap'>
+        <a class='octothorpe' href='#section-{{ num }}'>#</a>
+      </div>
+      {{{ docs_html }}}
+    </div>
+    <div class='code'>
+      {{{ code_html }}}
+    </div>
+  </div>
+  <div class='clearall'></div>
+  {{/sections}}
+</div>
+</body>
+"""

File pycco/setup.py

View file
+from setuptools import setup, find_packages
+
+setup(
+        name = "Pycco",
+        version = "0.2.0",
+        description = """A Python port of Docco: the original quick-and-dirty,
+        hundred-line-long, literate-programming-style documentation generator.
+        """,
+        author = "Nick Fitzgerald",
+        author_email = "fitzgen@gmail.com",
+        url = "http://fitzgen.github.com/pycco",
+        packages = find_packages(),
+        entry_points = {
+            'console_scripts': [
+                'pycco = pycco.main:main',
+                ]
+            },
+        install_requires = ['markdown', 'pygments', 'pystache', 'smartypants'],
+        )