diff options
author | Zearin <zearin@gonk.net> | 2011-12-30 12:30:54 -0500 |
---|---|---|
committer | Zearin <zearin@gonk.net> | 2011-12-30 12:30:54 -0500 |
commit | e8c7d7a4de0c6cb8cf6760d4d07bd8001455b18d (patch) | |
tree | 572a6d18ac4385ac73aa319695a7e16e7c62e81b | |
parent | 4ad50dbd97d27717c7307597e0349e767ccd880a (diff) | |
download | cmd2-feature/refactor.tar.gz |
Move documentation to top-level.feature/refactor
Following the examples I’ve seen in other Python projects.
44 files changed, 2674 insertions, 0 deletions
diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000..76bdbe2 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,89 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest + +help: + @echo "Please use \`make <target>' where <target> is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + @echo " doctest to run all doctests embedded in the documentation (if enabled)" + +clean: + -rm -rf $(BUILDDIR)/* + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/cmd2.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/cmd2.qhc" + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \ + "run these through (pdf)latex." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest + @echo "Testing of doctests in the sources finished, look at the " \ + "results in $(BUILDDIR)/doctest/output.txt." diff --git a/docs/alternatives.rst b/docs/alternatives.rst new file mode 100644 index 0000000..bbf2ae2 --- /dev/null +++ b/docs/alternatives.rst @@ -0,0 +1,50 @@ +============================ +Alternatives to cmd and cmd2 +============================ + +For programs that do not interact with the user in a continuous loop - +programs that simply accept a set of arguments from the command line, return +results, and do not keep the user within the program's environment - all +you need are sys_\ .argv (the command-line arguments) and optparse_ +(for parsing UNIX-style options and flags). + +.. _optparse: http://docs.python.org/library/optparse.html#module-optparse + +.. _sys: http://docs.python.org/library/sys.html#module-sys + +.. _curses: http://docs.python.org/library/curses.html#module-curses + +.. _cmd: http://docs.python.org/library/cmd.html#module-cmd + +The curses_ module produces applications that interact via a plaintext +terminal window, but are not limited to simple text input and output; +they can paint the screen with options that are selected from using the +cursor keys. However, programming a curses_-based application is not as +straightforward as using cmd_. + +Several packages in PyPI enable interactive command-line applications +approximately similar in concept to cmd_ applications. None of them +share cmd2's close ties to cmd, but they may be worth investigating +nonetheless. + + * CmdLoop_ + * cly_ + * CmDO_ (As of Feb. 2010, webpage is missing.) + * pycopia-CLI_ + +cmdln_, another package in PyPI, is an extension to cmd_ and, though it +doesn't retain full cmd_ compatibility, shares its basic structure with +cmd_. + +.. _cmdln: http://pypi.python.org/pypi/cmdln + +.. _CmdLoop: http://pypi.python.org/pypi/CmdLoop + +.. _cly: http://pypi.python.org/pypi/cly + +.. _CmDO: http://pypi.python.org/pypi/CmDO/0.7 + +.. _pycopia-CLI: http://pypi.python.org/pypi/pycopia-CLI/1.0 + +I've found several alternatives to cmd in the Cheese Shop - CmdLoop, cly, CMdO, and pycopia. cly looks wonderful, but I haven't been able to get it working under Windows, and that's a show-stopper for many potential sqlpython users. In any case, none of the alternatives are based on cmd - they're written from scratch, which means that a cmd-based app would need complete rewriting to use them. I like sticking close to the Standard Library whenever possible. cmd2 lets you do that. + diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 0000000..131a187 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# +# cmd2 documentation build configuration file, created by +# sphinx-quickstart on Wed Feb 10 12:05:28 2010. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this +# autogenerated file. +# +# All configuration values have a default; values that are commented out +# serve to show the default. + +import sys, os + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +#sys.path.append(os.path.abspath('.')) + +# -- General configuration ----------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be extensions +# coming with Sphinx (named 'sphinx.ext.*') or your custom ones. +extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.todo'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix of source filenames. +source_suffix = '.rst' + +# The encoding of source files. +#source_encoding = 'utf-8' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'cmd2' +copyright = u'2010, Catherine Devlin' + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. +# +# The short X.Y version. +version = '0.6.0' +# The full version, including alpha/beta/rc tags. +release = '0.6.0' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +#language = None + +# There are two options for replacing |today|: either, you set today to some +# non-false value, then it is used: +#today = '' +# Else, today_fmt is used as the format for a strftime call. +#today_fmt = '%B %d, %Y' + +# List of documents that shouldn't be included in the build. +#unused_docs = [] + +# List of directories, relative to source directory, that shouldn't be searched +# for source files. +exclude_trees = ['_build'] + +# The reST default role (used for this markup: `text`) to use for all documents. +#default_role = None + +# If true, '()' will be appended to :func: etc. cross-reference text. +#add_function_parentheses = True + +# If true, the current module name will be prepended to all description +# unit titles (such as .. function::). +#add_module_names = True + +# If true, sectionauthor and moduleauthor directives will be shown in the +# output. They are ignored by default. +#show_authors = False + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# A list of ignored prefixes for module index sorting. +#modindex_common_prefix = [] + + +# -- Options for HTML output --------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. Major themes that come with +# Sphinx are currently 'default' and 'sphinxdoc'. +html_theme = 'default' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +#html_theme_options = {} + +# Add any paths that contain custom themes here, relative to this directory. +#html_theme_path = [] + +# The name for this set of Sphinx documents. If None, it defaults to +# "<project> v<release> documentation". +#html_title = None + +# A shorter title for the navigation bar. Default is the same as html_title. +#html_short_title = None + +# The name of an image file (relative to this directory) to place at the top +# of the sidebar. +#html_logo = None + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = None + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". +html_static_path = ['_static'] + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '%b %d, %Y' + +# If true, SmartyPants will be used to convert quotes and dashes to +# typographically correct entities. +#html_use_smartypants = True + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# Additional templates that should be rendered to pages, maps page names to +# template names. +#html_additional_pages = {} + +# If false, no module index is generated. +#html_use_modindex = True + +# If false, no index is generated. +#html_use_index = True + +# If true, the index is split into individual pages for each letter. +#html_split_index = False + +# If true, links to the reST sources are added to the pages. +#html_show_sourcelink = True + +# If true, an OpenSearch description file will be output, and all pages will +# contain a <link> tag referring to it. The value of this option must be the +# base URL from which the finished HTML is served. +#html_use_opensearch = '' + +# If nonempty, this is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = '' + +# Output file base name for HTML help builder. +htmlhelp_basename = 'cmd2doc' + + +# -- Options for LaTeX output -------------------------------------------------- + +# The paper size ('letter' or 'a4'). +#latex_paper_size = 'letter' + +# The font size ('10pt', '11pt' or '12pt'). +#latex_font_size = '10pt' + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [ + ('index', 'cmd2.tex', u'cmd2 Documentation', + u'Catherine Devlin', 'manual'), +] + +# The name of an image file (relative to this directory) to place at the top of +# the title page. +#latex_logo = None + +# For "manual" documents, if this is true, then toplevel headings are parts, +# not chapters. +#latex_use_parts = False + +# Additional stuff for the LaTeX preamble. +#latex_preamble = '' + +# Documents to append as an appendix to all manuals. +#latex_appendices = [] + +# If false, no module index is generated. +#latex_use_modindex = True + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/docs/freefeatures.rst b/docs/freefeatures.rst new file mode 100644 index 0000000..8795261 --- /dev/null +++ b/docs/freefeatures.rst @@ -0,0 +1,207 @@ +=================================== +Features requiring no modifications +=================================== + +These features are provided "for free" to a cmd_-based application +simply by replacing ``import cmd`` with ``import cmd2 as cmd``. + +.. _cmd: http://docs.python.org/library/cmd.html#module-cmd + +Script files +============ + +Text files can serve as scripts for your ``cmd2``-based +application, with the ``load``, ``save``, and ``edit`` +commands. + +.. automethod:: cmd2.Cmd.do_load + +.. automethod:: cmd2.Cmd.do_save + +.. automethod:: cmd2.Cmd.do_edit + +Comments +======== + +Comments are omitted from the argument list +before it is passed to a ``do_`` method. By +default, both Python-style and C-style comments +are recognized; you may change this by overriding +``app.commentGrammars`` with a different pyparsing_ +grammar. + +Comments can be useful in :ref:`scripts`. Used +in an interactive session, they may indicate +mental imbalance. + +:: + + def do_speak(self, arg): + self.stdout.write(arg + '\n') + +:: + + (Cmd) speak it was /* not */ delicious! # Yuck! + it was delicious! + +.. _pyparsing: http://pyparsing.wikispaces.com/ + +Commands at invocation +====================== + +You can send commands to your app as you invoke it by +including them as extra arguments to the program. +``cmd2`` interprets each argument as a separate +command, so you should enclose each command in +quotation marks if it is more than a one-word command. + +:: + + cat@eee:~/proj/cmd2/example$ python example.py "say hello" "say Gracie" quit + hello + Gracie + cat@eee:~/proj/cmd2/example$ + + +Output redirection +================== + +As in a Unix shell, output of a command can be redirected: + + - sent to a file with ``>``, as in ``mycommand args > filename.txt`` + - piped (``|``) as input to operating-system commands, as in + ``mycommand args | wc`` + - sent to the paste buffer, ready for the next Copy operation, by + ending with a bare ``>``, as in ``mycommand args >``.. Redirecting + to paste buffer requires software to be installed on the operating + system, pywin32_ on Windows or xclip_ on \*nix. + +If your application depends on mathematical syntax, ``>`` may be a bad +choice for redirecting output - it will prevent you from using the +greater-than sign in your actual user commands. You can override your +app's value of ``self.redirector`` to use a different string for output redirection:: + + class MyApp(cmd2.Cmd): + redirector = '->' + +:: + + (Cmd) say line1 -> out.txt + (Cmd) say line2 ->-> out.txt + (Cmd) !cat out.txt + line1 + line2 + +.. _pywin32: http://sourceforge.net/projects/pywin32/ +.. _xclip: http://www.cyberciti.biz/faq/xclip-linux-insert-files-command-output-intoclipboard/ + +Python +====== + +The ``py`` command will run its arguments as a Python +command. Entered without arguments, it enters an +interactive Python session. That session can call +"back" to your application with ``cmd("")``. Through +``self``, it also has access to your application +instance itself. (If that thought terrifies you, +you can set the ``locals_in_py`` parameter to ``False``. +See see :ref:`parameters`) + +:: + + (Cmd) py print("-".join("spelling")) + s-p-e-l-l-i-n-g + (Cmd) py + Python 2.6.4 (r264:75706, Dec 7 2009, 18:45:15) + [GCC 4.4.1] on linux2 + Type "help", "copyright", "credits" or "license" for more information. + (CmdLineApp) + + py <command>: Executes a Python command. + py: Enters interactive Python mode. + End with `Ctrl-D` (Unix) / `Ctrl-Z` (Windows), `quit()`, 'exit()`. + Non-python commands can be issued with `cmd("your command")`. + + >>> import os + >>> os.uname() + ('Linux', 'eee', '2.6.31-19-generic', '#56-Ubuntu SMP Thu Jan 28 01:26:53 UTC 2010', 'i686') + >>> cmd("say --piglatin {os}".format(os=os.uname()[0])) + inuxLay + >>> self.prompt + '(Cmd) ' + >>> self.prompt = 'Python was here > ' + >>> quit() + Python was here > + +Searchable command history +========================== + +All cmd_-based applications have access to previous commands with +the up- and down- cursor keys. + +All cmd_-based applications on systems with the ``readline`` module +also provide `bash-like history list editing`_. + +.. _`bash-like history list editing`: http://www.talug.org/events/20030709/cmdline_history.html + +``cmd2`` makes a third type of history access available, consisting of these commands: + +.. automethod:: cmd2.Cmd.do_history + +.. automethod:: cmd2.Cmd.do_list + +.. automethod:: cmd2.Cmd.do_run + +Quitting the application +======================== + +``cmd2`` pre-defines a ``quit`` command for you (with +synonyms ``exit`` and simply ``q``). +It's trivial, but it's one less thing for you to remember. + + +Abbreviated commands +==================== + +``cmd2`` apps will accept shortened command names +so long as there is no ambiguity. Thus, if +``do_divide`` is defined, then ``divid``, ``div``, +or even ``d`` will suffice, so long as there are +no other commands defined beginning with *divid*, +*div*, or *d*. + +This behavior can be turned off with ``app.abbrev`` (see :ref:`parameters`) + +Misc. pre-defined commands +========================== + +Several generically useful commands are defined +with automatically included ``do_`` methods. + +.. automethod:: cmd2.Cmd.do_quit + +.. automethod:: cmd2.Cmd.do_pause + +.. automethod:: cmd2.Cmd.do_shell + +( ``!`` is a shortcut for ``shell``; thus ``!ls`` +is equivalent to ``shell ls``.) + + +Transcript-based testing +======================== + +If the entire transcript (input and output) of a successful session of +a ``cmd2``-based app is copied from the screen and pasted into a text +file, ``transcript.txt``, then a transcript test can be run against it:: + + python app.py --test transcript.txt + +Any non-whitespace deviations between the output prescribed in ``transcript.txt`` and +the actual output from a fresh run of the application will be reported +as a unit test failure. (Whitespace is ignored during the comparison.) + +Regular expressions can be embedded in the transcript inside paired ``/`` +slashes. These regular expressions should not include any whitespace +expressions. + diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 0000000..58feacc --- /dev/null +++ b/docs/index.rst @@ -0,0 +1,72 @@ +.. cmd2 documentation master file, created by + sphinx-quickstart on Wed Feb 10 12:05:28 2010. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +cmd2 +==== + +A python package for building powerful command-line interpreter (CLI) +programs. Extends the Python Standard Library's cmd_ package. + + +.. _`cmd2 project page`: http://www.assembla.com/wiki/show/python-cmd2 +.. _`project bug tracker`: http://trac-hg.assembla.com/python-cmd2/report/1 + +.. _cmd: http://docs.python.org/library/cmd.html#module-cmd + +The basic use of ``cmd2`` is identical to that of cmd_. + +1. Create a subclass of ``cmd2.Cmd``. Define attributes and + ``do_*`` methods to control its behavior. Throughout this documentation, + we will assume that you are naming your subclass ``App``:: + + from cmd2 import Cmd + class App(Cmd): + # customized attributes and methods here + +2. Instantiate ``App`` and start the command loop:: + + app = App() + app.cmdloop() + +Resources +--------- + +* cmd_ +* `project bug tracker`_ +* `cmd2 project page`_ +* `PyCon 2010 presentation <http://us.pycon.org/2010/conference/talks/#proposal_link_153>`_, + *Easy Command-Line Applications with cmd and cmd2*: + :doc:`slides <pycon2010/pycon2010>`, + `video <http://python.mirocommunity.com/video/1533/easy-command-line-applications>`_ + +These docs will refer to ``App`` as your ``cmd2.Cmd`` +subclass, and ``app`` as an instance of ``App``. Of +course, in your program, you may name them whatever +you want. + +Contents: + +.. toctree:: + :maxdepth: 2 + + overview + example + freefeatures + settingchanges + unfreefeatures + alternatives + +Compatibility +============= + +Tested and working with Python 2.5, 2.6, 2.7, 3.1; Jython 2.5 + +Indices and tables +================== + +* :ref:`genindex` +* :ref:`modindex` +* :ref:`search` + diff --git a/docs/make.bat b/docs/make.bat new file mode 100755 index 0000000..3e88e03 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,113 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +set SPHINXBUILD=sphinx-build +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^<target^>` where ^<target^> is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\cmd2.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\cmd2.ghc + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/docs/overview.rst b/docs/overview.rst new file mode 100644 index 0000000..cb0c80e --- /dev/null +++ b/docs/overview.rst @@ -0,0 +1,17 @@ + +======== +Overview +======== + +``cmd2`` is an extension of cmd_, the Python Standard Library's module for +creating simple interactive command-line applications. + +``cmd2`` can be used as a drop-in replacement for cmd_. Simply importing ``cmd2`` +in place of cmd_ will add many features to an application without any further +modifications. + +Understanding the use of cmd_ is the first step in learning the use of ``cmd2``. +Once you have read the cmd_ docs, return here to learn the ways that ``cmd2`` +differs from cmd_. + +.. _cmd: http://docs.python.org/library/cmd.html
\ No newline at end of file diff --git a/docs/pycon2010/akkad.png b/docs/pycon2010/akkad.png Binary files differnew file mode 100644 index 0000000..57799e9 --- /dev/null +++ b/docs/pycon2010/akkad.png diff --git a/docs/pycon2010/apple.jpg b/docs/pycon2010/apple.jpg Binary files differnew file mode 100644 index 0000000..2148af3 --- /dev/null +++ b/docs/pycon2010/apple.jpg diff --git a/docs/pycon2010/fileutil.py b/docs/pycon2010/fileutil.py new file mode 100644 index 0000000..5e754b5 --- /dev/null +++ b/docs/pycon2010/fileutil.py @@ -0,0 +1,12 @@ +import glob +import os.path + +for fullfilename in glob.glob('/home/cat/proj/cmd2/*.py'): + (dirpath, fname) = os.path.split(fullfilename) + stats = os.stat(fullfilename) + binds['path'] = dirpath + binds['name'] = fname + binds['bytes'] = stats.st_size + cmd("""INSERT INTO cat.files (path, name, bytes) + VALUES (%(path)s, %(name)s, %(bytes)s)""") +quit() diff --git a/docs/pycon2010/graph.py b/docs/pycon2010/graph.py new file mode 100644 index 0000000..96ffde7 --- /dev/null +++ b/docs/pycon2010/graph.py @@ -0,0 +1,41 @@ +from turtle import * +pu() +goto(-400,-400) + +def label(txt): + write(txt, font=('Arial', 20, 'italic')) +hideturtle() +width(6) + +def line(len, _label): + start = pos() + pd() + forward(len) + pu() + forward(30) + pd() + label(_label) + pu() + goto(start) + +def tech(x, y, _label): + pu() + goto(x, y) + pd() + write(_label, font=('Arial', 40, 'bold')) + pu() + +line(600, "Easy to write") +left(90) +line(600, "Easy to use") + +tech(-360, 160, 'GUI') +tech(-390, 100, 'AJAX') +tech(-300, -10, 'webapp') +tech(190, -380, 'CLU') +tech(60, -320, 'TUI') +tech(100, -210, 'cmd') +tech(80, -80, 'cmd2') + +while True: + pass
\ No newline at end of file diff --git a/docs/pycon2010/hook.jpg b/docs/pycon2010/hook.jpg Binary files differnew file mode 100644 index 0000000..819370d --- /dev/null +++ b/docs/pycon2010/hook.jpg diff --git a/docs/pycon2010/pirate.py b/docs/pycon2010/pirate.py new file mode 100644 index 0000000..98db50e --- /dev/null +++ b/docs/pycon2010/pirate.py @@ -0,0 +1,7 @@ +from cmd import Cmd + +class Pirate(Cmd): + pass + +pirate = Pirate() +pirate.cmdloop()
\ No newline at end of file diff --git a/docs/pycon2010/pirate2.py b/docs/pycon2010/pirate2.py new file mode 100644 index 0000000..e2c4960 --- /dev/null +++ b/docs/pycon2010/pirate2.py @@ -0,0 +1,18 @@ +from cmd import Cmd +# using ``do_`` methods + +class Pirate(Cmd): + gold = 3 + def do_loot(self, arg): + 'Seize booty from a passing ship.' + self.gold += 1 + print('Now we gots {0} doubloons' + .format(self.gold)) + def do_drink(self, arg): + 'Drown your sorrrows in rrrum.' + self.gold -= 1 + print('Now we gots {0} doubloons' + .format(self.gold)) + +pirate = Pirate() +pirate.cmdloop() diff --git a/docs/pycon2010/pirate3.py b/docs/pycon2010/pirate3.py new file mode 100644 index 0000000..7977a8d --- /dev/null +++ b/docs/pycon2010/pirate3.py @@ -0,0 +1,21 @@ +from cmd import Cmd +# using hook + +class Pirate(Cmd): + gold = 3 + def do_loot(self, arg): + 'Seize booty from a passing ship.' + self.gold += 1 + def do_drink(self, arg): + 'Drown your sorrrows in rrrum.' + self.gold -= 1 + def precmd(self, line): + self.initial_gold = self.gold + return line + def postcmd(self, stop, line): + if self.gold != self.initial_gold: + print('Now we gots {0} doubloons' + .format(self.gold)) + +pirate = Pirate() +pirate.cmdloop() diff --git a/docs/pycon2010/pirate4.py b/docs/pycon2010/pirate4.py new file mode 100644 index 0000000..5de9c21 --- /dev/null +++ b/docs/pycon2010/pirate4.py @@ -0,0 +1,27 @@ +from cmd import Cmd +# using arguments + +class Pirate(Cmd): + gold = 3 + def do_loot(self, arg): + 'Seize booty from a passing ship.' + self.gold += 1 + def do_drink(self, arg): + '''Drown your sorrrows in rrrum. + + drink [n] - drink [n] barrel[s] o' rum.''' + try: + self.gold -= int(arg) + except: + if arg: + print('''What's "{0}"? I'll take rrrum.'''.format(arg)) + self.gold -= 1 + def precmd(self, line): + self.initial_gold = self.gold + return line + def postcmd(self, stop, line): + if self.gold != self.initial_gold: + print('Now we gots {0} doubloons'.format(self.gold)) + +pirate = Pirate() +pirate.cmdloop()
\ No newline at end of file diff --git a/docs/pycon2010/pirate5.py b/docs/pycon2010/pirate5.py new file mode 100644 index 0000000..7add463 --- /dev/null +++ b/docs/pycon2010/pirate5.py @@ -0,0 +1,35 @@ +from cmd import Cmd +# quitting + +class Pirate(Cmd): + gold = 3 + def do_loot(self, arg): + 'Seize booty from a passing ship.' + self.gold += 1 + def do_drink(self, arg): + '''Drown your sorrrows in rrrum. + + drink [n] - drink [n] barrel[s] o' rum.''' + try: + self.gold -= int(arg) + except: + if arg: + print('''What's "{0}"? I'll take rrrum.'''.format(arg)) + self.gold -= 1 + def precmd(self, line): + self.initial_gold = self.gold + return line + def postcmd(self, stop, line): + if self.gold != self.initial_gold: + print('Now we gots {0} doubloons' + .format(self.gold)) + if self.gold < 0: + print("Off to debtorrr's prison.") + stop = True + return stop + def do_quit(self, arg): + print("Quiterrr!") + return True + +pirate = Pirate() +pirate.cmdloop() diff --git a/docs/pycon2010/pirate6.py b/docs/pycon2010/pirate6.py new file mode 100644 index 0000000..4a03fed --- /dev/null +++ b/docs/pycon2010/pirate6.py @@ -0,0 +1,39 @@ +from cmd2 import Cmd +# prompts and defaults + +class Pirate(Cmd): + gold = 3 + prompt = 'arrr> ' + def default(self, line): + print('What mean ye by "{0}"?' + .format(line)) + def do_loot(self, arg): + 'Seize booty from a passing ship.' + self.gold += 1 + def do_drink(self, arg): + '''Drown your sorrrows in rrrum. + + drink [n] - drink [n] barrel[s] o' rum.''' + try: + self.gold -= int(arg) + except: + if arg: + print('''What's "{0}"? I'll take rrrum.'''.format(arg)) + self.gold -= 1 + def precmd(self, line): + self.initial_gold = self.gold + return line + def postcmd(self, stop, line): + if self.gold != self.initial_gold: + print('Now we gots {0} doubloons' + .format(self.gold)) + if self.gold < 0: + print("Off to debtorrr's prison.") + stop = True + return stop + def do_quit(self, arg): + print("Quiterrr!") + return True + +pirate = Pirate() +pirate.cmdloop() diff --git a/docs/pycon2010/pirate7.py b/docs/pycon2010/pirate7.py new file mode 100644 index 0000000..25ff582 --- /dev/null +++ b/docs/pycon2010/pirate7.py @@ -0,0 +1,46 @@ +from cmd2 import Cmd +# prompts and defaults + +class Pirate(Cmd): + gold = 3 + prompt = 'arrr> ' + def default(self, line): + print('What mean ye by "{0}"?'.format(line)) + def do_loot(self, arg): + 'Seize booty from a passing ship.' + self.gold += 1 + def do_drink(self, arg): + '''Drown your sorrrows in rrrum. + + drink [n] - drink [n] barrel[s] o' rum.''' + try: + self.gold -= int(arg) + except: + if arg: + print('''What's "{0}"? I'll take rrrum.'''.format(arg)) + self.gold -= 1 + def precmd(self, line): + self.initial_gold = self.gold + return line + def postcmd(self, stop, line): + if self.gold != self.initial_gold: + print('Now we gots {0} doubloons' + .format(self.gold)) + if self.gold < 0: + print("Off to debtorrr's prison.") + stop = True + return stop + def do_quit(self, arg): + print("Quiterrr!") + return True + default_to_shell = True + multilineCommands = ['sing'] + terminators = Cmd.terminators + ['...'] + songcolor = 'blue' + settable = Cmd.settable + 'songcolor Color to ``sing`` in (red/blue/green/cyan/magenta, bold, underline)' + Cmd.shortcuts.update({'~': 'sing'}) + def do_sing(self, arg): + print(self.colorize(arg, self.songcolor)) + +pirate = Pirate() +pirate.cmdloop() diff --git a/docs/pycon2010/pirate8.py b/docs/pycon2010/pirate8.py new file mode 100644 index 0000000..3e80b24 --- /dev/null +++ b/docs/pycon2010/pirate8.py @@ -0,0 +1,57 @@ +from cmd2 import Cmd, options, make_option +# prompts and defaults + +class Pirate(Cmd): + gold = 3 + prompt = 'arrr> ' + def default(self, line): + print('What mean ye by "{0}"?'.format(line)) + def do_loot(self, arg): + 'Seize booty from a passing ship.' + self.gold += 1 + def do_drink(self, arg): + '''Drown your sorrrows in rrrum. + + drink [n] - drink [n] barrel[s] o' rum.''' + try: + self.gold -= int(arg) + except: + if arg: + print('''What's "{0}"? I'll take rrrum.'''.format(arg)) + self.gold -= 1 + def precmd(self, line): + self.initial_gold = self.gold + return line + def postcmd(self, stop, line): + if self.gold != self.initial_gold: + print('Now we gots {0} doubloons' + .format(self.gold)) + if self.gold < 0: + print("Off to debtorrr's prison.") + stop = True + return stop + def do_quit(self, arg): + print("Quiterrr!") + return True + default_to_shell = True + multilineCommands = ['sing'] + terminators = Cmd.terminators + ['...'] + songcolor = 'blue' + settable = Cmd.settable + 'songcolor Color to ``sing`` in (red/blue/green/cyan/magenta, bold, underline)' + Cmd.shortcuts.update({'~': 'sing'}) + def do_sing(self, arg): + print(self.colorize(arg, self.songcolor)) + @options([make_option('--ho', type='int', default=2, + help="How often to chant 'ho'"), + make_option('-c', '--commas', + action="store_true", + help="Intersperse commas")]) + def do_yo(self, arg, opts): + chant = ['yo'] + ['ho'] * opts.ho + separator = ', ' if opts.commas else ' ' + chant = separator.join(chant) + print('{0} and a bottle of {1}' + .format(chant, arg)) + +pirate = Pirate() +pirate.cmdloop() diff --git a/docs/pycon2010/pycon2010.rst b/docs/pycon2010/pycon2010.rst new file mode 100644 index 0000000..0b3b7a4 --- /dev/null +++ b/docs/pycon2010/pycon2010.rst @@ -0,0 +1,382 @@ +================================================ +Easy command-line interpreters with cmd and cmd2 +================================================ + +:author: Catherine Devlin +:date: 2010-02-20 +:slides: http://pypi.python.org/pypi/cmd2 + +Web 2.0 +======= + +.. image:: web-2-0-logos.gif + :height: 350px + +But first... +============ + +.. image:: sargon.jpg + :height: 250px + +.. image:: akkad.png + :height: 250px + +Sargon the Great + Founder of Akkadian Empire + +.. twenty-third century BC + +In between +========== + +.. image:: apple.jpg + :height: 250px + +Command-Line Interface + Unlike the Akkadian Empire, + the CLI will never die. + +Defining CLI +============ + +Also known as + +- "Line-oriented command interpreter" +- "Command-line interface" +- "Shell" + +1. Accepts free text input at prompt +2. Outputs lines of text +3. (repeat) + +Examples +======== + +.. class:: big + + * Bash, Korn, zsh + * Python shell + * screen + * Zork + * SQL clients: psql, SQL*\Plus, mysql... + * ed + +.. ``ed`` proves that CLI is sometimes the wrong answer. + +!= Command Line Utilities +========================= + +.. class:: big + + (``ls``, ``grep``, ``ping``, etc.) + + 1. Accept arguments at invocation + 2. execute + 3. terminate + + Use ``sys.argv``, ``optparse`` + +!="Text User Interface" +======================= + +* Use entire (session) screen +* I/O is *not* line-by-line +* See ``curses``, ``urwid`` + +.. image:: urwid.png + :height: 250px + + +Decide your priorities +====================== + +.. image:: strategy.png + :height: 350px + +A ``cmd`` app: pirate.py +======================== + +:: + + from cmd import Cmd + + class Pirate(Cmd): + pass + + pirate = Pirate() + pirate.cmdloop() + +.. Nothing here... but history and help + +.. ctrl-r for bash-style history + +Fundamental prrrinciple +======================= + +.. class:: huge + + ``(Cmd) foo a b c`` + + becomes + + ``self.do_foo('a b c')`` + +``do_``-methods: pirate2.py +=========================== + +:: + + class Pirate(Cmd): + gold = 3 + def do_loot(self, arg): + 'Seize booty frrrom a passing ship.' + self.gold += 1 + print('Now we gots {0} doubloons' + .format(self.gold)) + def do_drink(self, arg): + 'Drown your sorrrows in rrrum.' + self.gold -= 1 + print('Now we gots {0} doubloons' + .format(self.gold)) + +.. do_methods; more help + +Hooks +===== + +.. image:: hook.jpg + :height: 250px + +:: + + self.preloop() + self.postloop() + self.precmd(line) + self.postcmd(stop, line) + +Hooks: pirate3.py +================= + +:: + + def do_loot(self, arg): + 'Seize booty from a passing ship.' + self.gold += 1 + def do_drink(self, arg): + 'Drown your sorrrows in rrrum.' + self.gold -= 1 + def precmd(self, line): + self.initial_gold = self.gold + return line + def postcmd(self, stop, line): + if self.gold != self.initial_gold: + print('Now we gots {0} doubloons' + .format(self.gold)) + +Arguments: pirate4.py +===================== + +:: + + def do_drink(self, arg): + '''Drown your sorrrows in rrrum. + + drink [n] - drink [n] barrel[s] o' rum.''' + try: + self.gold -= int(arg) + except: + if arg: + print('''What's "{0}"? I'll take rrrum.''' + .format(arg)) + self.gold -= 1 + +quitting: pirate5.py +==================== + +:: + + def postcmd(self, stop, line): + if self.gold != self.initial_gold: + print('Now we gots {0} doubloons' + .format(self.gold)) + if self.gold < 0: + print("Off to debtorrr's prison.") + stop = True + return stop + def do_quit(self, arg): + print("Quiterrr!") + return True + +prompts, defaults: pirate6.py +============================= + +:: + + prompt = 'arrr> ' + def default(self, line): + print('What mean ye by "{0}"?' + .format(line)) + +Other CLI packages +================== + +.. class:: big + + * CmdLoop + * cly + * CMdO + * pycopia + * cmdlin + * cmd2 + +Demo +==== + +.. class:: huge + + Convert ``cmd`` app to ``cmd2`` + +cmd2 +==== + +.. image:: schematic.png + :height: 350px + +As you wish, Guido +================== + +.. class:: huge + + Python 3 compatible + +(um, mostly) + +Absolutely free +=============== + +Script files + +Commands at invocation + +Output redirection + +Python + +Transcript testing + +But wait, there's more +====================== + + * Abbreviated commands + * Shell commands + * Quitting + * Timing + * Echo + * Debug + +Minor changes: pirate7.py +========================= + +:: + + default_to_shell = True + multilineCommands = ['sing'] + terminators = Cmd.terminators + ['...'] + songcolor = 'blue' + settable = Cmd.settable + 'songcolor Color to ``sing`` in (red/blue/green/cyan/magenta, bold, underline)' + Cmd.shortcuts.update({'~': 'sing'}) + def do_sing(self, arg): + print(self.colorize(arg, self.songcolor)) + +Now how much would you pay? +=========================== + +options / flags + +Quiet (suppress feedback) + +BASH-style ``select`` + +Parsing: terminators, suffixes + +Options: pirate8.py +=================== + +:: + + @options([make_option('--ho', type='int', default=2, + help="How often to chant 'ho'"), + make_option('-c', '--commas', + action="store_true", + help="Intersperse commas")]) + def do_yo(self, arg, opts): + chant = ['yo'] + ['ho'] * opts.ho + separator = ', ' if opts.commas else ' ' + chant = separator.join(chant) + print('{0} and a bottle of {1}' + .format(chant, arg)) + +Serious example: sqlpython +========================== + +.. class:: big + + ``cmd``-based app by Luca Canali @ CERN + + Replacement for Oracle SQL\*Plus + + Now ``cmd2``-based; postgreSQL; MySQL + +File reporter +============= + +.. class:: huge + + Gather info: Python + + Store: postgresql + + Report: html + +fileutil.py +=========== + +:: + + import glob + import os.path + + for fullfilename in glob.glob('/home/cat/proj/cmd2/*.py'): + (dirpath, fname) = os.path.split(fullfilename) + stats = os.stat(fullfilename) + binds['path'] = dirpath + binds['name'] = fname + binds['bytes'] = stats.st_size + cmd("""INSERT INTO cat.files (path, name, bytes) + VALUES (%(path)s, %(name)s, %(bytes)s)""") + quit() + +sqlpython features +================== + +.. class:: big + + * from ``cmd2``: scripts, redirection, + py, etc. + * multiple connections + * UNIX: ls, cat, grep + * Special output + + +Thank you +========= + +.. class:: big + + http://pypi.python.org/pypi/cmd2 + + http://catherinedevlin.blogspot.com + + http://catherinedevlin.pythoneers.com + + diff --git a/docs/pycon2010/refresh.bash b/docs/pycon2010/refresh.bash new file mode 100755 index 0000000..26827b5 --- /dev/null +++ b/docs/pycon2010/refresh.bash @@ -0,0 +1 @@ +rst2s5.py --theme-url ui/pycon pycon2010.rst pycon2010.html diff --git a/docs/pycon2010/sargon.jpg b/docs/pycon2010/sargon.jpg Binary files differnew file mode 100644 index 0000000..5960f1e --- /dev/null +++ b/docs/pycon2010/sargon.jpg diff --git a/docs/pycon2010/schematic.png b/docs/pycon2010/schematic.png Binary files differnew file mode 100644 index 0000000..d4b3909 --- /dev/null +++ b/docs/pycon2010/schematic.png diff --git a/docs/pycon2010/schematic.py b/docs/pycon2010/schematic.py new file mode 100644 index 0000000..8077485 --- /dev/null +++ b/docs/pycon2010/schematic.py @@ -0,0 +1,32 @@ +from turtle import * +hideturtle() +width(6) +pensize = 10 +pu() +goto(0,-400) + +def rectangle(x, y, _label): + pu() + seth(0) + backward(x / 2) + fontsize = 40 + pd() + for i in range(2): + forward(x) + left(90) + forward(y) + left(90) + pu() + forward(x / 2) + left(90) + forward(y / 2 - fontsize) + pd() + write(_label, align='center', font=('Arial', fontsize, 'bold')) + +rectangle(800, 80, 'cmd') +pu() +forward(80) +rectangle(200, 400, 'cmd2') + +while True: + pass diff --git a/docs/pycon2010/script.txt b/docs/pycon2010/script.txt new file mode 100644 index 0000000..c638b1a --- /dev/null +++ b/docs/pycon2010/script.txt @@ -0,0 +1,5 @@ +loot +loot +drink /* arrr */ 2 # matey +drink chardonnay + diff --git a/docs/pycon2010/strategy.png b/docs/pycon2010/strategy.png Binary files differnew file mode 100644 index 0000000..7d6afdc --- /dev/null +++ b/docs/pycon2010/strategy.png diff --git a/docs/pycon2010/transcript.txt b/docs/pycon2010/transcript.txt new file mode 100644 index 0000000..d00e44f --- /dev/null +++ b/docs/pycon2010/transcript.txt @@ -0,0 +1,12 @@ +arrr> loot +Now we gots 4 doubloons +arrr> loot +Now we gots 5 doubloons +arrr> drink 3 +Now we gots 2 doubloons +arrr> drink chardonnay +What's "chardonnay"? I'll take rrrum. +Now we gots 1 doubloons +arrr> quit +Quiterrr! + diff --git a/docs/pycon2010/ui/pycon/blank.gif b/docs/pycon2010/ui/pycon/blank.gif Binary files differnew file mode 100644 index 0000000..75b945d --- /dev/null +++ b/docs/pycon2010/ui/pycon/blank.gif diff --git a/docs/pycon2010/ui/pycon/framing.css b/docs/pycon2010/ui/pycon/framing.css new file mode 100644 index 0000000..c4727f3 --- /dev/null +++ b/docs/pycon2010/ui/pycon/framing.css @@ -0,0 +1,25 @@ +/* This file has been placed in the public domain. */ +/* The following styles size, place, and layer the slide components. + Edit these if you want to change the overall slide layout. + The commented lines can be uncommented (and modified, if necessary) + to help you with the rearrangement process. */ + +/* target = 1024x768 */ + +div#header, div#footer, .slide {width: 100%; top: 0; left: 0;} +div#header {position: fixed; top: 0; height: 3em; z-index: 1;} +div#footer {top: auto; bottom: 0; height: 2.5em; z-index: 5;} +.slide {top: 0; width: 92%; padding: 2.5em 4% 4%; z-index: 2;} +div#controls {left: 50%; bottom: 0; width: 50%; z-index: 100;} +div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; + margin: 0;} +#currentSlide {position: absolute; width: 10%; left: 45%; bottom: 1em; + z-index: 10;} +html>body #currentSlide {position: fixed;} + +/* +div#header {background: #FCC;} +div#footer {background: #CCF;} +div#controls {background: #BBD;} +div#currentSlide {background: #FFC;} +*/ diff --git a/docs/pycon2010/ui/pycon/iepngfix.htc b/docs/pycon2010/ui/pycon/iepngfix.htc new file mode 100644 index 0000000..9f3d628 --- /dev/null +++ b/docs/pycon2010/ui/pycon/iepngfix.htc @@ -0,0 +1,42 @@ +<public:component> +<public:attach event="onpropertychange" onevent="doFix()" /> + +<script> + +// IE5.5+ PNG Alpha Fix v1.0 by Angus Turnbull http://www.twinhelix.com +// Free usage permitted as long as this notice remains intact. + +// This must be a path to a blank image. That's all the configuration you need here. +var blankImg = 'ui/default/blank.gif'; + +var f = 'DXImageTransform.Microsoft.AlphaImageLoader'; + +function filt(s, m) { + if (filters[f]) { + filters[f].enabled = s ? true : false; + if (s) with (filters[f]) { src = s; sizingMethod = m } + } else if (s) style.filter = 'progid:'+f+'(src="'+s+'",sizingMethod="'+m+'")'; +} + +function doFix() { + if ((parseFloat(navigator.userAgent.match(/MSIE (\S+)/)[1]) < 5.5) || + (event && !/(background|src)/.test(event.propertyName))) return; + + if (tagName == 'IMG') { + if ((/\.png$/i).test(src)) { + filt(src, 'image'); // was 'scale' + src = blankImg; + } else if (src.indexOf(blankImg) < 0) filt(); + } else if (style.backgroundImage) { + if (style.backgroundImage.match(/^url[("']+(.*\.png)[)"']+$/i)) { + var s = RegExp.$1; + style.backgroundImage = ''; + filt(s, 'crop'); + } else filt(); + } +} + +doFix(); + +</script> +</public:component>
\ No newline at end of file diff --git a/docs/pycon2010/ui/pycon/opera.css b/docs/pycon2010/ui/pycon/opera.css new file mode 100644 index 0000000..c9d1148 --- /dev/null +++ b/docs/pycon2010/ui/pycon/opera.css @@ -0,0 +1,8 @@ +/* This file has been placed in the public domain. */ +/* DO NOT CHANGE THESE unless you really want to break Opera Show */ +.slide { + visibility: visible !important; + position: static !important; + page-break-before: always; +} +#slide0 {page-break-before: avoid;} diff --git a/docs/pycon2010/ui/pycon/outline.css b/docs/pycon2010/ui/pycon/outline.css new file mode 100644 index 0000000..fa767e2 --- /dev/null +++ b/docs/pycon2010/ui/pycon/outline.css @@ -0,0 +1,16 @@ +/* This file has been placed in the public domain. */ +/* Don't change this unless you want the layout stuff to show up in the + outline view! */ + +.layout div, #footer *, #controlForm * {display: none;} +#footer, #controls, #controlForm, #navLinks, #toggle { + display: block; visibility: visible; margin: 0; padding: 0;} +#toggle {float: right; padding: 0.5em;} +html>body #toggle {position: fixed; top: 0; right: 0;} + +/* making the outline look pretty-ish */ + +#slide0 h1, #slide0 h2, #slide0 h3, #slide0 h4 {border: none; margin: 0;} +#toggle {border: 1px solid; border-width: 0 0 1px 1px; background: #FFF;} + +.outline {display: inline ! important;} diff --git a/docs/pycon2010/ui/pycon/pretty.css b/docs/pycon2010/ui/pycon/pretty.css new file mode 100644 index 0000000..1097903 --- /dev/null +++ b/docs/pycon2010/ui/pycon/pretty.css @@ -0,0 +1,120 @@ +/* This file has been placed in the public domain. */ +/* Following are the presentation styles -- edit away! */ + +html, body {margin: 0; padding: 0;} +body {background: white; color: black; font-family: sans-serif;} +/* Replace the background style above with the style below (and again for + div#header) for a graphic: */ +/* background: white url(bodybg.gif) -16px 0 no-repeat; */ +:link, :visited {text-decoration: none; color: #00C;} +#controls :active {color: #88A !important;} +#controls :focus {outline: 1px dotted #227;} +h1, h2, h3, h4 {font-size: 100%; margin: 0; padding: 0; font-weight: inherit;} + +blockquote {padding: 0 2em 0.5em; margin: 0 1.5em 0.5em;} +blockquote p {margin: 0;} + +kbd {font-weight: bold; font-size: 1em;} +sup {font-size: smaller; line-height: 1px;} + +.slide pre {padding: 0; margin-left: 0; margin-right: 0; font-size: 90%;} +.slide ul ul li {list-style: square;} +.slide img.leader {display: block; margin: 0 auto;} +.slide tt {font-size: 90%;} + +div#header, div#footer {background: green; color: #AAB; font-family: sans-serif;} +/* background: green url(bodybg.gif) -16px 0 no-repeat; */ +div#footer {font-size: 0.5em; font-weight: bold; padding: 1em 0;} +#footer h1 {display: block; padding: 0 1em;} +#footer h2 {display: block; padding: 0.8em 1em 0;} + +.slide {font-size: 1.2em;} +.slide h1 {position: absolute; top: 0.45em; z-index: 1; + margin: 0; padding-left: 0.7em; white-space: nowrap; + font: bold 150% sans-serif; color: #DDE; background: green;} +.slide h2 {font: bold 120%/1em sans-serif; padding-top: 0.5em;} +.slide h3 {font: bold 100% sans-serif; padding-top: 0.5em;} +h1 abbr {font-variant: small-caps;} + +div#controls {position: absolute; left: 50%; bottom: 0; + width: 50%; text-align: right; font: bold 0.9em sans-serif;} +html>body div#controls {position: fixed; padding: 0 0 1em 0; top: auto;} +div#controls form {position: absolute; bottom: 0; right: 0; width: 100%; + margin: 0; padding: 0;} +#controls #navLinks a {padding: 0; margin: 0 0.5em; + background: green; border: none; color: #779; cursor: pointer;} +#controls #navList {height: 1em;} +#controls #navList #jumplist {position: absolute; bottom: 0; right: 0; + background: #DDD; color: #227;} + +#currentSlide {text-align: center; font-size: 0.5em; color: #449; + font-family: sans-serif; font-weight: bold;} + +#slide0 {padding-top: 1.5em} +#slide0 h1 {position: static; margin: 1em 0 0; padding: 0; color: #000; + font: bold 2em sans-serif; white-space: normal; background: transparent;} +#slide0 h2 {font: bold italic 1em sans-serif; margin: 0.25em;} +#slide0 h3 {margin-top: 1.5em; font-size: 1.5em;} +#slide0 h4 {margin-top: 0; font-size: 1em;} + +ul.urls {list-style: none; display: inline; margin: 0;} +.urls li {display: inline; margin: 0;} +.external {border-bottom: 1px dotted gray;} +html>body .external {border-bottom: none;} +.external:after {content: " \274F"; font-size: smaller; color: #77B;} + +.incremental, .incremental *, .incremental *:after {visibility: visible; + color: white; border: 0;} +img.incremental {visibility: hidden;} +.slide .current {color: green;} + +.slide-display {display: inline ! important;} + +.huge {font-family: sans-serif; font-weight: bold; font-size: 150%;} +.big {font-family: sans-serif; font-weight: bold; font-size: 120%;} +.small {font-size: 75%;} +.tiny {font-size: 50%;} +.huge tt, .big tt, .small tt, .tiny tt {font-size: 115%;} +.huge pre, .big pre, .small pre, .tiny pre {font-size: 115%;} + +.maroon {color: maroon;} +.red {color: red;} +.magenta {color: magenta;} +.fuchsia {color: fuchsia;} +.pink {color: #FAA;} +.orange {color: orange;} +.yellow {color: yellow;} +.lime {color: lime;} +.green {color: green;} +.olive {color: olive;} +.teal {color: teal;} +.cyan {color: cyan;} +.aqua {color: aqua;} +.blue {color: blue;} +.navy {color: navy;} +.purple {color: purple;} +.black {color: black;} +.gray {color: gray;} +.silver {color: silver;} +.white {color: white;} + +.left {text-align: left ! important;} +.center {text-align: center ! important;} +.right {text-align: right ! important;} + +.animation {position: relative; margin: 1em 0; padding: 0;} +.animation img {position: absolute;} + +/* Docutils-specific overrides */ + +.slide table.docinfo {margin: 1em 0 0.5em 2em;} + +pre.literal-block, pre.doctest-block {background-color: white;} + +tt.docutils {background-color: white;} + +/* diagnostics */ +/* +li:after {content: " [" attr(class) "]"; color: #F88;} +div:before {content: "[" attr(class) "]"; color: #F88;} +*/ diff --git a/docs/pycon2010/ui/pycon/print.css b/docs/pycon2010/ui/pycon/print.css new file mode 100644 index 0000000..9d057cc --- /dev/null +++ b/docs/pycon2010/ui/pycon/print.css @@ -0,0 +1,24 @@ +/* This file has been placed in the public domain. */ +/* The following rule is necessary to have all slides appear in print! + DO NOT REMOVE IT! */ +.slide, ul {page-break-inside: avoid; visibility: visible !important;} +h1 {page-break-after: avoid;} + +body {font-size: 12pt; background: white;} +* {color: black;} + +#slide0 h1 {font-size: 200%; border: none; margin: 0.5em 0 0.25em;} +#slide0 h3 {margin: 0; padding: 0;} +#slide0 h4 {margin: 0 0 0.5em; padding: 0;} +#slide0 {margin-bottom: 3em;} + +#header {display: none;} +#footer h1 {margin: 0; border-bottom: 1px solid; color: gray; + font-style: italic;} +#footer h2, #controls {display: none;} + +.print {display: inline ! important;} + +/* The following rule keeps the layout stuff out of print. + Remove at your own risk! */ +.layout, .layout * {display: none !important;} diff --git a/docs/pycon2010/ui/pycon/s5-core.css b/docs/pycon2010/ui/pycon/s5-core.css new file mode 100644 index 0000000..6965f5e --- /dev/null +++ b/docs/pycon2010/ui/pycon/s5-core.css @@ -0,0 +1,11 @@ +/* This file has been placed in the public domain. */ +/* Do not edit or override these styles! + The system will likely break if you do. */ + +div#header, div#footer, div#controls, .slide {position: absolute;} +html>body div#header, html>body div#footer, + html>body div#controls, html>body .slide {position: fixed;} +.handout {display: none;} +.layout {display: block;} +.slide, .hideme, .incremental {visibility: hidden;} +#slide0 {visibility: visible;} diff --git a/docs/pycon2010/ui/pycon/slides.css b/docs/pycon2010/ui/pycon/slides.css new file mode 100644 index 0000000..82bdc0e --- /dev/null +++ b/docs/pycon2010/ui/pycon/slides.css @@ -0,0 +1,10 @@ +/* This file has been placed in the public domain. */ + +/* required to make the slide show run at all */ +@import url(s5-core.css); + +/* sets basic placement and size of slide components */ +@import url(framing.css); + +/* styles that make the slides look good */ +@import url(pretty.css); diff --git a/docs/pycon2010/ui/pycon/slides.js b/docs/pycon2010/ui/pycon/slides.js new file mode 100644 index 0000000..81e04e5 --- /dev/null +++ b/docs/pycon2010/ui/pycon/slides.js @@ -0,0 +1,558 @@ +// S5 v1.1 slides.js -- released into the Public Domain +// Modified for Docutils (http://docutils.sf.net) by David Goodger +// +// Please see http://www.meyerweb.com/eric/tools/s5/credits.html for +// information about all the wonderful and talented contributors to this code! + +var undef; +var slideCSS = ''; +var snum = 0; +var smax = 1; +var slideIDs = new Array(); +var incpos = 0; +var number = undef; +var s5mode = true; +var defaultView = 'slideshow'; +var controlVis = 'visible'; + +var isIE = navigator.appName == 'Microsoft Internet Explorer' ? 1 : 0; +var isOp = navigator.userAgent.indexOf('Opera') > -1 ? 1 : 0; +var isGe = navigator.userAgent.indexOf('Gecko') > -1 && navigator.userAgent.indexOf('Safari') < 1 ? 1 : 0; + +function hasClass(object, className) { + if (!object.className) return false; + return (object.className.search('(^|\\s)' + className + '(\\s|$)') != -1); +} + +function hasValue(object, value) { + if (!object) return false; + return (object.search('(^|\\s)' + value + '(\\s|$)') != -1); +} + +function removeClass(object,className) { + if (!object) return; + object.className = object.className.replace(new RegExp('(^|\\s)'+className+'(\\s|$)'), RegExp.$1+RegExp.$2); +} + +function addClass(object,className) { + if (!object || hasClass(object, className)) return; + if (object.className) { + object.className += ' '+className; + } else { + object.className = className; + } +} + +function GetElementsWithClassName(elementName,className) { + var allElements = document.getElementsByTagName(elementName); + var elemColl = new Array(); + for (var i = 0; i< allElements.length; i++) { + if (hasClass(allElements[i], className)) { + elemColl[elemColl.length] = allElements[i]; + } + } + return elemColl; +} + +function isParentOrSelf(element, id) { + if (element == null || element.nodeName=='BODY') return false; + else if (element.id == id) return true; + else return isParentOrSelf(element.parentNode, id); +} + +function nodeValue(node) { + var result = ""; + if (node.nodeType == 1) { + var children = node.childNodes; + for (var i = 0; i < children.length; ++i) { + result += nodeValue(children[i]); + } + } + else if (node.nodeType == 3) { + result = node.nodeValue; + } + return(result); +} + +function slideLabel() { + var slideColl = GetElementsWithClassName('*','slide'); + var list = document.getElementById('jumplist'); + smax = slideColl.length; + for (var n = 0; n < smax; n++) { + var obj = slideColl[n]; + + var did = 'slide' + n.toString(); + if (obj.getAttribute('id')) { + slideIDs[n] = obj.getAttribute('id'); + } + else { + obj.setAttribute('id',did); + slideIDs[n] = did; + } + if (isOp) continue; + + var otext = ''; + var menu = obj.firstChild; + if (!menu) continue; // to cope with empty slides + while (menu && menu.nodeType == 3) { + menu = menu.nextSibling; + } + if (!menu) continue; // to cope with slides with only text nodes + + var menunodes = menu.childNodes; + for (var o = 0; o < menunodes.length; o++) { + otext += nodeValue(menunodes[o]); + } + list.options[list.length] = new Option(n + ' : ' + otext, n); + } +} + +function currentSlide() { + var cs; + var footer_nodes; + var vis = 'visible'; + if (document.getElementById) { + cs = document.getElementById('currentSlide'); + footer_nodes = document.getElementById('footer').childNodes; + } else { + cs = document.currentSlide; + footer = document.footer.childNodes; + } + cs.innerHTML = '<span id="csHere">' + snum + '<\/span> ' + + '<span id="csSep">\/<\/span> ' + + '<span id="csTotal">' + (smax-1) + '<\/span>'; + if (snum == 0) { + vis = 'hidden'; + } + cs.style.visibility = vis; + for (var i = 0; i < footer_nodes.length; i++) { + if (footer_nodes[i].nodeType == 1) { + footer_nodes[i].style.visibility = vis; + } + } +} + +function go(step) { + if (document.getElementById('slideProj').disabled || step == 0) return; + var jl = document.getElementById('jumplist'); + var cid = slideIDs[snum]; + var ce = document.getElementById(cid); + if (incrementals[snum].length > 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + removeClass(incrementals[snum][i], 'current'); + removeClass(incrementals[snum][i], 'incremental'); + } + } + if (step != 'j') { + snum += step; + lmax = smax - 1; + if (snum > lmax) snum = lmax; + if (snum < 0) snum = 0; + } else + snum = parseInt(jl.value); + var nid = slideIDs[snum]; + var ne = document.getElementById(nid); + if (!ne) { + ne = document.getElementById(slideIDs[0]); + snum = 0; + } + if (step < 0) {incpos = incrementals[snum].length} else {incpos = 0;} + if (incrementals[snum].length > 0 && incpos == 0) { + for (var i = 0; i < incrementals[snum].length; i++) { + if (hasClass(incrementals[snum][i], 'current')) + incpos = i + 1; + else + addClass(incrementals[snum][i], 'incremental'); + } + } + if (incrementals[snum].length > 0 && incpos > 0) + addClass(incrementals[snum][incpos - 1], 'current'); + ce.style.visibility = 'hidden'; + ne.style.visibility = 'visible'; + jl.selectedIndex = snum; + currentSlide(); + number = 0; +} + +function goTo(target) { + if (target >= smax || target == snum) return; + go(target - snum); +} + +function subgo(step) { + if (step > 0) { + removeClass(incrementals[snum][incpos - 1],'current'); + removeClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos],'current'); + incpos++; + } else { + incpos--; + removeClass(incrementals[snum][incpos],'current'); + addClass(incrementals[snum][incpos], 'incremental'); + addClass(incrementals[snum][incpos - 1],'current'); + } +} + +function toggle() { + var slideColl = GetElementsWithClassName('*','slide'); + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + if (!slides.disabled) { + slides.disabled = true; + outline.disabled = false; + s5mode = false; + fontSize('1em'); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'visible'; + } + } else { + slides.disabled = false; + outline.disabled = true; + s5mode = true; + fontScale(); + for (var n = 0; n < smax; n++) { + var slide = slideColl[n]; + slide.style.visibility = 'hidden'; + } + slideColl[snum].style.visibility = 'visible'; + } +} + +function showHide(action) { + var obj = GetElementsWithClassName('*','hideme')[0]; + switch (action) { + case 's': obj.style.visibility = 'visible'; break; + case 'h': obj.style.visibility = 'hidden'; break; + case 'k': + if (obj.style.visibility != 'visible') { + obj.style.visibility = 'visible'; + } else { + obj.style.visibility = 'hidden'; + } + break; + } +} + +// 'keys' code adapted from MozPoint (http://mozpoint.mozdev.org/) +function keys(key) { + if (!key) { + key = event; + key.which = key.keyCode; + } + if (key.which == 84) { + toggle(); + return; + } + if (s5mode) { + switch (key.which) { + case 10: // return + case 13: // enter + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + if(number != undef) { + goTo(number); + break; + } + case 32: // spacebar + case 34: // page down + case 39: // rightkey + case 40: // downkey + if(number != undef) { + go(number); + } else if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + break; + case 33: // page up + case 37: // leftkey + case 38: // upkey + if(number != undef) { + go(-1 * number); + } else if (!incrementals[snum] || incpos <= 0) { + go(-1); + } else { + subgo(-1); + } + break; + case 36: // home + goTo(0); + break; + case 35: // end + goTo(smax-1); + break; + case 67: // c + showHide('k'); + break; + } + if (key.which < 48 || key.which > 57) { + number = undef; + } else { + if (window.event && isParentOrSelf(window.event.srcElement, 'controls')) return; + if (key.target && isParentOrSelf(key.target, 'controls')) return; + number = (((number != undef) ? number : 0) * 10) + (key.which - 48); + } + } + return false; +} + +function clicker(e) { + number = undef; + var target; + if (window.event) { + target = window.event.srcElement; + e = window.event; + } else target = e.target; + if (target.href != null || hasValue(target.rel, 'external') || isParentOrSelf(target, 'controls') || isParentOrSelf(target,'embed') || isParentOrSelf(target, 'object')) return true; + if (!e.which || e.which == 1) { + if (!incrementals[snum] || incpos >= incrementals[snum].length) { + go(1); + } else { + subgo(1); + } + } +} + +function findSlide(hash) { + var target = document.getElementById(hash); + if (target) { + for (var i = 0; i < slideIDs.length; i++) { + if (target.id == slideIDs[i]) return i; + } + } + return null; +} + +function slideJump() { + if (window.location.hash == null || window.location.hash == '') { + currentSlide(); + return; + } + if (window.location.hash == null) return; + var dest = null; + dest = findSlide(window.location.hash.slice(1)); + if (dest == null) { + dest = 0; + } + go(dest - snum); +} + +function fixLinks() { + var thisUri = window.location.href; + thisUri = thisUri.slice(0, thisUri.length - window.location.hash.length); + var aelements = document.getElementsByTagName('A'); + for (var i = 0; i < aelements.length; i++) { + var a = aelements[i].href; + var slideID = a.match('\#.+'); + if ((slideID) && (slideID[0].slice(0,1) == '#')) { + var dest = findSlide(slideID[0].slice(1)); + if (dest != null) { + if (aelements[i].addEventListener) { + aelements[i].addEventListener("click", new Function("e", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "if (e.preventDefault) e.preventDefault();"), true); + } else if (aelements[i].attachEvent) { + aelements[i].attachEvent("onclick", new Function("", + "if (document.getElementById('slideProj').disabled) return;" + + "go("+dest+" - snum); " + + "event.returnValue = false;")); + } + } + } + } +} + +function externalLinks() { + if (!document.getElementsByTagName) return; + var anchors = document.getElementsByTagName('a'); + for (var i=0; i<anchors.length; i++) { + var anchor = anchors[i]; + if (anchor.getAttribute('href') && hasValue(anchor.rel, 'external')) { + anchor.target = '_blank'; + addClass(anchor,'external'); + } + } +} + +function createControls() { + var controlsDiv = document.getElementById("controls"); + if (!controlsDiv) return; + var hider = ' onmouseover="showHide(\'s\');" onmouseout="showHide(\'h\');"'; + var hideDiv, hideList = ''; + if (controlVis == 'hidden') { + hideDiv = hider; + } else { + hideList = hider; + } + controlsDiv.innerHTML = '<form action="#" id="controlForm"' + hideDiv + '>' + + '<div id="navLinks">' + + '<a accesskey="t" id="toggle" href="javascript:toggle();">Ø<\/a>' + + '<a accesskey="z" id="prev" href="javascript:go(-1);">«<\/a>' + + '<a accesskey="x" id="next" href="javascript:go(1);">»<\/a>' + + '<div id="navList"' + hideList + '><select id="jumplist" onchange="go(\'j\');"><\/select><\/div>' + + '<\/div><\/form>'; + if (controlVis == 'hidden') { + var hidden = document.getElementById('navLinks'); + } else { + var hidden = document.getElementById('jumplist'); + } + addClass(hidden,'hideme'); +} + +function fontScale() { // causes layout problems in FireFox that get fixed if browser's Reload is used; same may be true of other Gecko-based browsers + if (!s5mode) return false; + var vScale = 22; // both yield 32 (after rounding) at 1024x768 + var hScale = 32; // perhaps should auto-calculate based on theme's declared value? + if (window.innerHeight) { + var vSize = window.innerHeight; + var hSize = window.innerWidth; + } else if (document.documentElement.clientHeight) { + var vSize = document.documentElement.clientHeight; + var hSize = document.documentElement.clientWidth; + } else if (document.body.clientHeight) { + var vSize = document.body.clientHeight; + var hSize = document.body.clientWidth; + } else { + var vSize = 700; // assuming 1024x768, minus chrome and such + var hSize = 1024; // these do not account for kiosk mode or Opera Show + } + var newSize = Math.min(Math.round(vSize/vScale),Math.round(hSize/hScale)); + fontSize(newSize + 'px'); + if (isGe) { // hack to counter incremental reflow bugs + var obj = document.getElementsByTagName('body')[0]; + obj.style.display = 'none'; + obj.style.display = 'block'; + } +} + +function fontSize(value) { + if (!(s5ss = document.getElementById('s5ss'))) { + if (!isIE) { + document.getElementsByTagName('head')[0].appendChild(s5ss = document.createElement('style')); + s5ss.setAttribute('media','screen, projection'); + s5ss.setAttribute('id','s5ss'); + } else { + document.createStyleSheet(); + document.s5ss = document.styleSheets[document.styleSheets.length - 1]; + } + } + if (!isIE) { + while (s5ss.lastChild) s5ss.removeChild(s5ss.lastChild); + s5ss.appendChild(document.createTextNode('body {font-size: ' + value + ' !important;}')); + } else { + document.s5ss.addRule('body','font-size: ' + value + ' !important;'); + } +} + +function notOperaFix() { + slideCSS = document.getElementById('slideProj').href; + var slides = document.getElementById('slideProj'); + var outline = document.getElementById('outlineStyle'); + slides.setAttribute('media','screen'); + outline.disabled = true; + if (isGe) { + slides.setAttribute('href','null'); // Gecko fix + slides.setAttribute('href',slideCSS); // Gecko fix + } + if (isIE && document.styleSheets && document.styleSheets[0]) { + document.styleSheets[0].addRule('img', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('div', 'behavior: url(ui/default/iepngfix.htc)'); + document.styleSheets[0].addRule('.slide', 'behavior: url(ui/default/iepngfix.htc)'); + } +} + +function getIncrementals(obj) { + var incrementals = new Array(); + if (!obj) + return incrementals; + var children = obj.childNodes; + for (var i = 0; i < children.length; i++) { + var child = children[i]; + if (hasClass(child, 'incremental')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'incremental'); + for (var j = 0; j < child.childNodes.length; j++) { + if (child.childNodes[j].nodeType == 1) { + addClass(child.childNodes[j], 'incremental'); + } + } + } else { + incrementals[incrementals.length] = child; + removeClass(child,'incremental'); + } + } + if (hasClass(child, 'show-first')) { + if (child.nodeName == 'OL' || child.nodeName == 'UL') { + removeClass(child, 'show-first'); + if (child.childNodes[isGe].nodeType == 1) { + removeClass(child.childNodes[isGe], 'incremental'); + } + } else { + incrementals[incrementals.length] = child; + } + } + incrementals = incrementals.concat(getIncrementals(child)); + } + return incrementals; +} + +function createIncrementals() { + var incrementals = new Array(); + for (var i = 0; i < smax; i++) { + incrementals[i] = getIncrementals(document.getElementById(slideIDs[i])); + } + return incrementals; +} + +function defaultCheck() { + var allMetas = document.getElementsByTagName('meta'); + for (var i = 0; i< allMetas.length; i++) { + if (allMetas[i].name == 'defaultView') { + defaultView = allMetas[i].content; + } + if (allMetas[i].name == 'controlVis') { + controlVis = allMetas[i].content; + } + } +} + +// Key trap fix, new function body for trap() +function trap(e) { + if (!e) { + e = event; + e.which = e.keyCode; + } + try { + modifierKey = e.ctrlKey || e.altKey || e.metaKey; + } + catch(e) { + modifierKey = false; + } + return modifierKey || e.which == 0; +} + +function startup() { + defaultCheck(); + if (!isOp) createControls(); + slideLabel(); + fixLinks(); + externalLinks(); + fontScale(); + if (!isOp) { + notOperaFix(); + incrementals = createIncrementals(); + slideJump(); + if (defaultView == 'outline') { + toggle(); + } + document.onkeyup = keys; + document.onkeypress = trap; + document.onclick = clicker; + } +} + +window.onload = startup; +window.onresize = function(){setTimeout('fontScale()', 50);} diff --git a/docs/pycon2010/urwid.png b/docs/pycon2010/urwid.png Binary files differnew file mode 100644 index 0000000..c2b5a9b --- /dev/null +++ b/docs/pycon2010/urwid.png diff --git a/docs/pycon2010/web-2-0-logos.gif b/docs/pycon2010/web-2-0-logos.gif Binary files differnew file mode 100644 index 0000000..9d48e37 --- /dev/null +++ b/docs/pycon2010/web-2-0-logos.gif diff --git a/docs/refresh.bash b/docs/refresh.bash new file mode 100755 index 0000000..d0b8651 --- /dev/null +++ b/docs/refresh.bash @@ -0,0 +1,8 @@ +make html +#scp -r build catherine@$tummy:/var/www/sqlpython +cd _build/html +zip -r cmd2_docs * +mv cmd2_docs.zip ../.. +cd .. +echo "Upload cmd2_docs.zip to http://pypi.python.org/pypi?%3Aaction=pkg_edit&name=cmd2" +scp -r _build/html www-data@$tummy:/var/www/cmd2 diff --git a/docs/settingchanges.rst b/docs/settingchanges.rst new file mode 100644 index 0000000..290e4e0 --- /dev/null +++ b/docs/settingchanges.rst @@ -0,0 +1,118 @@ +========================================= +Features requiring only parameter changes +========================================= + +Several aspects of a ``cmd2`` application's behavior +can be controlled simply by setting attributes of ``App``. +A parameter can also be changed at runtime by the user *if* +its name is included in the dictionary ``app.settable``. +(To define your own user-settable parameters, see :ref:`parameters`) + +Case-insensitivity +================== + +By default, all ``cmd2`` command names are case-insensitive; +``sing the blues`` and ``SiNg the blues`` are equivalent. To change this, +set ``App.case_insensitive`` to False. + +Whether or not you set ``case_insensitive``, *please do not* define +command method names with any uppercase letters. ``cmd2`` will probably +do something evil if you do. + +Shortcuts +========= + +Special-character shortcuts for common commands can make life more convenient for your +users. Shortcuts are used without a space separating them from their arguments, +like ``!ls``. By default, the following shortcuts are defined: + + ``?`` + help + + ``!`` + shell: run as OS-level command + + ``@`` + load script file + + ``@@`` + load script file; filename is relative to current script location + +To define more shortcuts, update the dict ``App.shortcuts`` with the +{'shortcut': 'command_name'} (omit ``do_``):: + + class App(Cmd2): + Cmd2.shortcuts.update({'*': 'sneeze', '~': 'squirm'}) + +Default to shell +================ + +Every ``cmd2`` application can execute operating-system +level (shell) commands with ``shell`` or a ``!`` +shortcut:: + + (Cmd) shell which python + /usr/bin/python + (Cmd) !which python + /usr/bin/python + +However, if the parameter ``default_to_shell`` is +``True``, then *every* command will be attempted on +the operating system. Only if that attempt fails +(i.e., produces a nonzero return value) will the +application's own ``default`` method be called. + +:: + + (Cmd) which python + /usr/bin/python + (Cmd) my dog has fleas + sh: my: not found + *** Unknown syntax: my dog has fleas + +Timing +====== + +Setting ``App.timing`` to ``True`` outputs timing data after +every application command is executed. |settable| + +Echo +==== + +If ``True``, each command the user issues will be repeated +to the screen before it is executed. This is particularly +useful when running scripts. + +Debug +===== + +Setting ``App.debug`` to ``True`` will produce detailed error stacks +whenever the application generates an error. |settable| + +.. |settable| replace:: The user can ``set`` this parameter + during application execution. + (See :ref:`parameters`) + + +Other user-settable parameters +============================== + +A list of all user-settable parameters, with brief +comments, is viewable from within a running application +with:: + + (Cmd) set --long + abbrev: True # Accept abbreviated commands + case_insensitive: True # upper- and lower-case both OK + colors: True # Colorized output (*nix only) + continuation_prompt: > # On 2nd+ line of input + debug: False # Show full error stack on error + default_file_name: command.txt # for ``save``, ``load``, etc. + echo: False # Echo command issued into output + editor: gedit # Program used by ``edit`` + feedback_to_output: False # include nonessentials in `|`, `>` results + prompt: (Cmd) # + quiet: False # Don't print nonessential feedback + timing: False # Report execution times + + diff --git a/docs/unfreefeatures.rst b/docs/unfreefeatures.rst new file mode 100644 index 0000000..1cd0081 --- /dev/null +++ b/docs/unfreefeatures.rst @@ -0,0 +1,251 @@ +====================================== +Features requiring application changes +====================================== + +Multiline commands +================== + +Command input may span multiple lines for the +commands whose names are listed in the +parameter ``app.multilineCommands``. These +commands will be executed only +after the user has entered a *terminator*. +By default, the command terminators is +``;``; replacing or appending to the list +``app.terminators`` allows different +terminators. A blank line +is *always* considered a command terminator +(cannot be overridden). + +Parsed statements +================= + +``cmd2`` passes ``arg`` to a ``do_`` method (or +``default`) as a ParsedString, a subclass of +string that includes an attribute ``parsed``. +``parsed`` is a ``pyparsing.ParseResults`` +object produced by applying a pyparsing_ +grammar applied to ``arg``. It may include: + +command + Name of the command called + +raw + Full input exactly as typed. + +terminator + Character used to end a multiline command + +suffix + Remnant of input after terminator + +:: + + def do_parsereport(self, arg): + self.stdout.write(arg.parsed.dump() + '\n') + +:: + + (Cmd) parsereport A B /* C */ D; E + ['parsereport', 'A B D', ';', 'E'] + - args: A B D + - command: parsereport + - raw: parsereport A B /* C */ D; E + - statement: ['parsereport', 'A B D', ';'] + - args: A B D + - command: parsereport + - terminator: ; + - suffix: E + - terminator: ; + +If ``parsed`` does not contain an attribute, +querying for it will return ``None``. (This +is a characteristic of ``pyparsing.ParseResults``.) + +ParsedString was developed to support sqlpython_ +and reflects its needs. The parsing grammar and +process are painfully complex and should not be +considered stable; future ``cmd2`` releases may +change it somewhat (hopefully reducing complexity). + +(Getting ``arg`` as a ``ParsedString`` is +technically "free", in that it requires no application +changes from the cmd_ standard, but there will +be no result unless you change your application +to *use* ``arg.parsed``.) + +.. _sqlpython: http://pypi.python.org/pypi/sqlpython/ + +.. _cmd: http://docs.python.org/library/cmd.html#module-cmd + +.. _pyparsing: http://pyparsing.wikispaces.com/ + +Environment parameters +====================== + +Your application can define user-settable parameters +which your code can reference. Create them as class attributes +with their default values, and add them (with optional +documentation) to ``settable``. + +:: + + from cmd2 import Cmd + class App(Cmd): + degrees_c = 22 + sunny = False + settable = Cmd.settable + '''degrees_c temperature in Celsius + sunny''' + def do_sunbathe(self, arg): + if self.degrees_c < 20: + result = "It's {temp} C - are you a penguin?".format(temp=self.degrees_c) + elif not self.sunny: + result = 'Too dim.' + else: + result = 'UV is bad for your skin.' + self.stdout.write(result + '\n') + app = App() + app.cmdloop() + +:: + + (Cmd) set --long + degrees_c: 22 # temperature in Celsius + sunny: False # + (Cmd) sunbathe + Too dim. + (Cmd) set sunny yes + sunny - was: False + now: True + (Cmd) sunbathe + UV is bad for your skin. + (Cmd) set degrees_c 13 + degrees_c - was: 22 + now: 13 + (Cmd) sunbathe + It's 13 C - are you a penguin? + + +Commands with flags +=================== + +All ``do_`` methods are responsible for interpreting +the arguments passed to them. However, ``cmd2`` lets +a ``do_`` methods accept Unix-style *flags*. It uses optparse_ +to parse the flags, and they work the same way as for +that module. + +Flags are defined with the ``options`` decorator, +which is passed a list of optparse_-style options, +each created with ``make_option``. The method +should accept a second argument, ``opts``, in +addition to ``args``; the flags will be stripped +from ``args``. + +:: + + @options([make_option('-p', '--piglatin', action="store_true", help="atinLay"), + make_option('-s', '--shout', action="store_true", help="N00B EMULATION MODE"), + make_option('-r', '--repeat', type="int", help="output [n] times") + ]) + def do_speak(self, arg, opts=None): + """Repeats what you tell me to.""" + arg = ''.join(arg) + if opts.piglatin: + arg = '%s%say' % (arg[1:].rstrip(), arg[0]) + if opts.shout: + arg = arg.upper() + repetitions = opts.repeat or 1 + for i in range(min(repetitions, self.maxrepeats)): + self.stdout.write(arg) + self.stdout.write('\n') + +:: + + (Cmd) say goodnight, gracie + goodnight, gracie + (Cmd) say -sp goodnight, gracie + OODNIGHT, GRACIEGAY + (Cmd) say -r 2 --shout goodnight, gracie + GOODNIGHT, GRACIE + GOODNIGHT, GRACIE + +``options`` takes an optional additional argument, ``arg_desc``. +If present, ``arg_desc`` will appear in place of ``arg`` in +the option's online help. + +:: + + @options([make_option('-t', '--train', action='store_true', help='by train')], + arg_desc='(from city) (to city)') + def do_travel(self, arg, opts=None): + 'Gets you from (from city) to (to city).' + + +:: + + (Cmd) help travel + Gets you from (from city) to (to city). + Usage: travel [options] (from-city) (to-city) + + Options: + -h, --help show this help message and exit + -t, --train by train + +.. _optparse: + +.. _outputters: + +poutput, pfeedback, perror +========================== + +Standard ``cmd`` applications produce their output with ``self.stdout.write('output')`` (or with ``print``, +but ``print`` decreases output flexibility). ``cmd2`` applications can use +``self.poutput('output')``, ``self.pfeedback('message')``, and ``self.perror('errmsg')`` +instead. These methods have these advantages: + +- More concise + - ``.pfeedback()`` destination is controlled by :ref:`quiet` parameter. + +color +===== + +Text output can be colored by wrapping it in the ``colorize`` method. + +.. automethod:: cmd2.Cmd.colorize + +.. _quiet: + +quiet +===== + +Controls whether ``self.pfeedback('message')`` output is suppressed; +useful for non-essential feedback that the user may not always want +to read. ``quiet`` is only relevant if +``app.pfeedback`` is sometimes used. + +``select`` +========== + +Presents numbered options to user, as bash ``select``. + +``app.select`` is called from within a method (not by the user directly; it is ``app.select``, not ``app.do_select``). + +.. automethod:: cmd2.Cmd.select + +:: + + def do_eat(self, arg): + sauce = self.select('sweet salty', 'Sauce? ') + result = '{food} with {sauce} sauce, yum!' + result = result.format(food=arg, sauce=sauce) + self.stdout.write(result + '\n') + +:: + + (Cmd) eat wheaties + 1. sweet + 2. salty + Sauce? 2 + wheaties with salty sauce, yum! +
\ No newline at end of file diff --git a/docs/upload_pycon.bash b/docs/upload_pycon.bash new file mode 100755 index 0000000..4f35188 --- /dev/null +++ b/docs/upload_pycon.bash @@ -0,0 +1,2 @@ +rst2s5.py --theme-url=pycon2010/ui/pycon pycon2010/pycon2010.rst pycon2010/pycon2010.html +scp -r pycon2010/ www-data@$tummy:/var/www/presentations/cmd_cmd2 |