--- a/.hgignore Mon Jul 13 17:50:35 2009 +0300
+++ b/.hgignore Mon Jul 13 18:23:42 2009 +0300
@@ -1,1 +1,2 @@
\.pyc$
+^docs/_build/
--- a/README Mon Jul 13 17:50:35 2009 +0300
+++ b/README Mon Jul 13 18:23:42 2009 +0300
@@ -1,118 +1,51 @@
.. -*- mode: rst -*-
-==========
- Fancycmd
-==========
-
-Fancycmd is a command line parser, indented to make writing command line
-applications easy and painless. It uses built-in Python types (lists,
-dictionaries, etc) to define options (or subcommands in case you need them),
-which makes configuration clear and concise.
-
+=============
+ Finaloption
+=============
-Options
--------
-
-Configuration of option parser is a list of tuples::
+::
- opts = [('l', 'listen', 'localhost', 'ip to listen on'),
- ('p', 'port', 8000, 'port to listen on'),
- ('d', 'daemonize', False, 'daemonize process'),
- ('', 'pid-file', '', 'name of file to write process ID to')]
-
-Each tuple is a definition of some option, consisting of 4 elements:
+ If that's the Final Option,
+ I'm gonna choose it.
+ Die Krupps
- 1. short name
- 2. long name
- 3. default value
- 4. help string
-
-If a short name renders to False (for example, empty string), then it's not used
-at all. Long name is pretended to be available in any case. Default value also
-determines how supplied argument should be parsed:
-
- - function: return value of function called with a specified value is passed
- - integer: value is convert to integer
- - string: value is passed as is
- - list: value is appended to this list
- - boolean/None: ``not default`` is passed and option takes no argument
+Finaloption is a command line parser, indented to make writing command line
+applications easy and painless. It uses built-in Python types (lists,
+dictionaries, etc) to define options, which makes configuration clear and
+concise. Additionally it contains possibility to handle subcommands (i.e.
+``hg commit`` or ``svn update``).
-Usage is easy like that::
+JFYI: name is derived from Die Krupps' song Final Option, featured in epigraph.
- from fancycmd import fancyopts
- def main(dirname, **opts):
- '''write some help here'''
- pass
- parser = fancyopts(main, opts, usage='%s [-l HOST] DIR' % sys.argv[0])
- parser(sys.argv[1:])
+Quick example
+-------------
-Subcommands
------------
-
-It's pretty usual for complex application to have some system of subcommands,
-and fancycmd provides facility for handling them. Configuration is simple as
-well::
+That's simple example to show you example of an option definition::
- cmdtable = {
- '^simple':
- (simple,
- [('t', 'test', False, 'just test execution')],
- '[-t] ...'),
- 'complex|hard':
- (complex_,
- [('p', 'pass', False, 'don\'t run the command'),
- ('', 'exit', 0, 'exit with supplied code (default: 0)')],
- '[-p] [--exit value] ...')}
+ import sys
+ from finaloption import command
-Keys in this dictionary are subcommand names. You can add aliases for
-subcommands, separating them with the ``|`` sign (of course, there can be few
-aliases). Marking command with preceding ``^`` means that this commands should
-be included in short help (more on that later).
-
-Values here are tuples, consisting of 3 elements:
-
- 1. function, which will handle this subcommand
- 2. list of options
- 3. usage string (used by help generator)
-
-Your application will also always have ``help`` command, when it uses subcommand
-system.
-
-You can define your functions for subcommands like this::
-
- def simple(ui, *args, **opts):
- '''some descriptive text here
+ @command(usage='%name [-n] MESSAGE')
+ def main(message,
+ nonewline=('n', False, 'don\'t print a newline')):
+ 'Simple echo program'
+ sys.stdout.write(message)
+ if not nonewline:
+ sys.stdout.write('\n')
- more help, I'd said a lot of help here ;-)
- '''
- pass
-
-Naturally ``args`` is a list, containing all arguments to command, and ``opts``
-is a dictionary, containing every option. ``ui`` is an UI_ instance.
+ if __name__ == '__main__':
+ main()
-Usage::
+Running this program will print the help::
- describe api here
-
-UI
---
+ echo.py [-n] MESSAGE
-``UI`` is a special object intended to ease output handling in your
-application. There are two global options added, which are used by this object:
-``-v/--verbose`` and ``-q/--quiet``. And then you are encouraged to use ``UI``
-instance to output instead of directly printing messages, which is possible by
-using one of following methods:
+ Simple echo program
+
+ options:
- - ``UI.info`` prints by default, but hides output with quiet option
- - ``UI.note`` prints only if verbose option supplied
- - ``UI.write`` prints in any case
- - ``UI.warn`` prints to stderr (in any case)
-
+ -n --nonewline don't print a newline
+ -h --help show help
-Help generation
----------------
-
-Help is generated automatically and is available by the ``--help`` command line
-option or by ``help`` subcommand (if you're using subcommand system).
-
-Help is wrapped to length of 70 characters.
+I think this mostly describes what's going to. To learn more, read documentation.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/Makefile Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,94 @@
+# Makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line.
+SPHINXOPTS =
+SPHINXBUILD = sphinx-build
+PAPER =
+
+# Internal variables.
+PAPEROPT_a4 = -D latex_paper_size=a4
+PAPEROPT_letter = -D latex_paper_size=letter
+ALLSPHINXOPTS = -d _build/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
+
+.PHONY: all help clean html dirhtml pickle json htmlhelp qthelp latex changes linkcheck doctest
+
+all:
+ make html
+
+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 _build/*
+
+html:
+ $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) _build/html
+ @echo
+ @echo "Build finished. The HTML pages are in _build/html."
+
+dirhtml:
+ $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) _build/dirhtml
+ @echo
+ @echo "Build finished. The HTML pages are in _build/dirhtml."
+
+pickle:
+ $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) _build/pickle
+ @echo
+ @echo "Build finished; now you can process the pickle files."
+
+json:
+ $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) _build/json
+ @echo
+ @echo "Build finished; now you can process the JSON files."
+
+htmlhelp:
+ $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) _build/htmlhelp
+ @echo
+ @echo "Build finished; now you can run HTML Help Workshop with the" \
+ ".hhp project file in _build/htmlhelp."
+
+qthelp:
+ $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) _build/qthelp
+ @echo
+ @echo "Build finished; now you can run "qcollectiongenerator" with the" \
+ ".qhcp project file in _build/qthelp, like this:"
+ @echo "# qcollectiongenerator _build/qthelp/Finaloption.qhcp"
+ @echo "To view the help file:"
+ @echo "# assistant -collectionFile _build/qthelp/Finaloption.qhc"
+
+latex:
+ $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) _build/latex
+ @echo
+ @echo "Build finished; the LaTeX files are in _build/latex."
+ @echo "Run \`make all-pdf' or \`make all-ps' in that directory to" \
+ "run these through (pdf)latex."
+
+changes:
+ $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) _build/changes
+ @echo
+ @echo "The overview file is in _build/changes."
+
+linkcheck:
+ $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) _build/linkcheck
+ @echo
+ @echo "Link check complete; look for any errors in the above output " \
+ "or in _build/linkcheck/output.txt."
+
+doctest:
+ $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) _build/doctest
+ @echo "Testing of doctests in the sources finished, look at the " \
+ "results in _build/doctest/output.txt."
+
+open:
+ open _build/html/index.html
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/api.rst Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,8 @@
+=================
+ Finaloption API
+=================
+
+.. module:: finaloption
+
+.. autofunction:: command
+.. autofunction:: dispatch
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/conf.py Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,41 @@
+# -*- coding: utf-8 -*-
+
+import sys, os
+
+sys.path.append('..')
+
+# -- General configuration -----------------------------------------------------
+
+extensions = ['sphinx.ext.autodoc', 'sphinx.ext.doctest']
+templates_path = ['_templates']
+source_suffix = '.rst'
+master_doc = 'index'
+project = u'Finaloption'
+copyright = u'2009, Alexander Solovyov'
+version = '0.9'
+release = '0.9'
+exclude_trees = ['_build']
+pygments_style = 'sphinx'
+
+
+# -- Options for HTML output ---------------------------------------------------
+
+html_theme = 'default'
+# "<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
+
+#html_logo = None
+#html_favicon = None
+html_static_path = ['_static']
+html_use_smartypants = True
+htmlhelp_basename = 'Finaloptiondoc'
+
+
+# -- Options for LaTeX output --------------------------------------------------
+
+latex_documents = [
+ ('index', 'Finaloption.tex', u'Finaloption Documentation',
+ u'Alexander Solovyov', 'manual'),
+]
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/index.rst Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,34 @@
+=============
+ Finaloption
+=============
+
+::
+
+ If that's the Final Option,
+ I'm gonna choose it.
+ Die Krupps
+
+.. toctree::
+ :maxdepth: 2
+
+ overview
+ api
+
+Finaloption is a command line parser, indented to make writing command line
+applications easy and painless. It uses built-in Python types (lists,
+dictionaries, etc) to define options, which makes configuration clear and
+concise. Additionally it contains possibility to handle subcommands (i.e.
+``hg commit`` or ``svn update``).
+
+JFYI: name is derived from Die Krupps' song Final Option, featured in epigraph.
+
+Features
+--------
+
+ - parsing arguments from sys.argv or custom strings
+ - converting from string to appropriate Python objects
+ - generating help message
+ - positional and named arguments
+ - subcommands support
+ - short, clean and concise definitions
+ - ability to shorten names of subcommand and long options
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/make.bat Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,112 @@
+@ECHO OFF
+
+REM Command file for Sphinx documentation
+
+set SPHINXBUILD=sphinx-build
+set ALLSPHINXOPTS=-d _build/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 (_build\*) do rmdir /q /s %%i
+ del /q /s _build\*
+ goto end
+)
+
+if "%1" == "html" (
+ %SPHINXBUILD% -b html %ALLSPHINXOPTS% _build/html
+ echo.
+ echo.Build finished. The HTML pages are in _build/html.
+ goto end
+)
+
+if "%1" == "dirhtml" (
+ %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% _build/dirhtml
+ echo.
+ echo.Build finished. The HTML pages are in _build/dirhtml.
+ goto end
+)
+
+if "%1" == "pickle" (
+ %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% _build/pickle
+ echo.
+ echo.Build finished; now you can process the pickle files.
+ goto end
+)
+
+if "%1" == "json" (
+ %SPHINXBUILD% -b json %ALLSPHINXOPTS% _build/json
+ echo.
+ echo.Build finished; now you can process the JSON files.
+ goto end
+)
+
+if "%1" == "htmlhelp" (
+ %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% _build/htmlhelp
+ echo.
+ echo.Build finished; now you can run HTML Help Workshop with the ^
+.hhp project file in _build/htmlhelp.
+ goto end
+)
+
+if "%1" == "qthelp" (
+ %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% _build/qthelp
+ echo.
+ echo.Build finished; now you can run "qcollectiongenerator" with the ^
+.qhcp project file in _build/qthelp, like this:
+ echo.^> qcollectiongenerator _build\qthelp\Finaloption.qhcp
+ echo.To view the help file:
+ echo.^> assistant -collectionFile _build\qthelp\Finaloption.ghc
+ goto end
+)
+
+if "%1" == "latex" (
+ %SPHINXBUILD% -b latex %ALLSPHINXOPTS% _build/latex
+ echo.
+ echo.Build finished; the LaTeX files are in _build/latex.
+ goto end
+)
+
+if "%1" == "changes" (
+ %SPHINXBUILD% -b changes %ALLSPHINXOPTS% _build/changes
+ echo.
+ echo.The overview file is in _build/changes.
+ goto end
+)
+
+if "%1" == "linkcheck" (
+ %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% _build/linkcheck
+ echo.
+ echo.Link check complete; look for any errors in the above output ^
+or in _build/linkcheck/output.txt.
+ goto end
+)
+
+if "%1" == "doctest" (
+ %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% _build/doctest
+ echo.
+ echo.Testing of doctests in the sources finished, look at the ^
+results in _build/doctest/output.txt.
+ goto end
+)
+
+:end
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/docs/overview.rst Mon Jul 13 18:23:42 2009 +0300
@@ -0,0 +1,146 @@
+===================
+ Finaloption usage
+===================
+
+Options
+-------
+
+Configuration of option parser is a list of tuples::
+
+ opts = [('l', 'listen', 'localhost', 'ip to listen on'),
+ ('p', 'port', 8000, 'port to listen on'),
+ ('d', 'daemonize', False, 'daemonize process'),
+ ('', 'pid-file', '', 'name of file to write process ID to')]
+
+Each tuple is a definition of some option, consisting of 4 elements:
+
+ 1. short name
+ 2. long name (read note_)
+ 3. default value
+ 4. help string
+
+If a short name renders to False (for example, empty string), then it's not used
+at all. Long name is pretended to be available in any case. Default value also
+determines how supplied argument should be parsed:
+
+ - function: return value of function called with a specified value is passed
+ - integer: value is convert to integer
+ - string: value is passed as is
+ - list: value is appended to this list
+ - boolean/None: ``not default`` is passed and option takes no argument
+
+Usage is easy like that::
+
+ from finaloption import command
+
+ @command(options=opts, usage='%name [-l HOST] DIR')
+ def main(dirname, **opts):
+ '''write some help here'''
+ pass
+
+There is alternative declaration, easier for simple cases::
+
+ @command(usage='%name [-l HOST] DIR')
+ def main(dirname,
+ listen=('l', 'localhost', 'ip to listen on'),
+ pid_file=('', '', 'name of file to write process ID to')):
+ pass
+
+.. _note:
+
+I think it's easy to understand what's going on here, except that you need to
+know that underscores in the long name will be replaced with dash at the command
+line. Of course, reverse process happens: if you have option with a dash in long
+name in a definition, it will be replaced with underscore when passed to
+function. This is done to comply with standarts of writing both console
+interfaces and Python application.
+
+To make your application work, just call ``main()`` to parse ``sys.argv``.
+
+Subcommands
+-----------
+
+It's pretty usual for complex application to have some system of subcommands,
+and finaloption provides facility for handling them. Configuration is simple::
+
+ cmdtable = {
+ '^simple':
+ (simple,
+ [('t', 'test', False, 'just test execution')],
+ '[-t] ...'),
+ 'complex|hard':
+ (complex_,
+ [('p', 'pass', False, 'don\'t run the command'),
+ ('', 'exit', 0, 'exit with supplied code (default: 0)')],
+ '[-p] [--exit value] ...')}
+
+Keys in this dictionary are subcommand names. You can add aliases for
+subcommands, separating them with the ``|`` sign (of course, there can be few
+aliases). Marking command with preceding ``^`` means that this commands should
+be included in short help (more on that later).
+
+Values here are tuples, consisting of 3 elements:
+
+ 1. function, which will handle this subcommand
+ 2. list of options
+ 3. usage string (used by help generator)
+
+Your application will also always have ``help`` command, when it uses subcommand
+system.
+
+You can define your functions for subcommands like this::
+
+ def simple(*args, **opts):
+ '''some descriptive text here
+
+ more help, I'd said a lot of help here ;-)
+ '''
+ pass
+
+Naturally ``args`` is a list, containing all arguments to command, and ``opts``
+is a dictionary, containing every option.
+
+After definition of all elements you can call command dispatcher::
+
+ from finaloption import dispatch
+
+ if __name__ == '__main__':
+ dispatch(cmdtable=cmdtable)
+
+But if your program is something like program shown earlier, you can use
+shortened api::
+
+ @command(usage='[-t] ...', shortlist=True)
+ def simple(somearg,
+ test=('t', False, 'just test execution')):
+ pass
+
+ if __name__ == '__main__':
+ dispatch()
+
+Every ``@command`` stores information about decorated function in special global
+command table, which allows to call ``dispatch()`` without arguments.
+
+
+Help generation
+---------------
+
+Help is generated automatically and is available by the ``-h/--help`` command
+line option or by ``help`` subcommand (if you're using subcommand system).
+
+It is generated from usage, function docstring and a list of option help
+strings, wrapped to length of 70 characters and looks like that::
+
+ > ./test.py help complex
+ complex: [-p] [--exit value] ...
+
+ That's more complex command indented to do something
+
+ Let's try to do that (what?!)
+
+ options:
+
+ -p --pass don't run the command
+ --exit exit with supplied code (default: 0)
+ -h --help show help
+
--- a/finaloption.py Mon Jul 13 17:50:35 2009 +0300
+++ b/finaloption.py Mon Jul 13 18:23:42 2009 +0300
@@ -23,10 +23,10 @@
- ``options``: options in format described in docs. If not supplied,
will be determined from function.
- - ``usage``: usage string for function, replaces %name with name
- of program or subcommand. In case if it's subcommand and %name
- is not present, usage is prepended by 'name: '
- - ``name``: used for multiple subcommands. defaults to wrapped
+ - ``usage``: usage string for function, replaces ``%name`` with name
+ of program or subcommand. In case if it's subcommand and ``%name``
+ is not present, usage is prepended by ``name``
+ - ``name``: used for multiple subcommands. Defaults to wrapped
function name
- ``shortlist``: if command should be included in shortlist. Used
only for multiple subcommands
@@ -68,25 +68,23 @@
def dispatch(args=None, cmdtable=None, globalopts=None):
'''Dispatch command arguments based on subcommands.
- - ``args``: list of arguments, default: sys.argv[1:]
- - ``cmdtable``: dict of commands in next format::
-
- {'name': (function, options, usage)}
+ - ``args``: list of arguments, default: ``sys.argv[1:]``
+ - ``cmdtable``: dict of commands in format described below.
+ If not supplied, functions decorated with ``@command`` will be used.
+ - ``globalopts``: list of options which are applied to all
+ commands, if not supplied will contain ``--help`` option
- if not supplied, functions decorated with @command will be used.
-
- - ``globalopts``: list of options which are applied to all
- commands, if not supplied will contain ``--help`` option
+ cmdtable format description::
- cmdtable format description follows:
+ {'name': (function, options, usage)}
- - ``name`` is the name used on command-line. Can containt
- aliases (separate them with '|') or pointer to the fact
- that this command should be displayed in short help (start
- name with '^')
- - ``function`` is the actual callable
- - ``options`` is options list in format described in docs
- - ``usage`` is the short string of usage
+ - ``name`` is the name used on command-line. Can containt
+ aliases (separate them with ``|``) or pointer to the fact
+ that this command should be displayed in short help (start
+ name with ``^``)
+ - ``function`` is the actual callable
+ - ``options`` is options list in format described in docs
+ - ``usage`` is the short string of usage
'''
args = args or sys.argv[1:]
cmdtable = cmdtable or CMDTABLE
@@ -156,6 +154,10 @@
def help_cmd(func, usage, options):
'''show help for given command
+ - ``func``: function to generate help for (``func.__doc__`` is taken)
+ - ``usage``: usage string
+ - ``options``: options in usual format
+
>>> def test(*args, **opts):
... """that's a test command
...