diff options
Diffstat (limited to 'docs/source')
27 files changed, 2164 insertions, 0 deletions
diff --git a/docs/source/_templates/layout.html b/docs/source/_templates/layout.html new file mode 100644 index 00000000..b4384e43 --- /dev/null +++ b/docs/source/_templates/layout.html @@ -0,0 +1,7 @@ +{% extends "!layout.html" %} +{% set script_files = [] %} + +{% block linktags %}{% endblock %} +{% block relbar1 %}{% endblock %} +{% block footer %}{% endblock %} +{% block relbaritems %}{% endblock %} diff --git a/docs/source/api/accounts.rst b/docs/source/api/accounts.rst new file mode 100644 index 00000000..c09b43fa --- /dev/null +++ b/docs/source/api/accounts.rst @@ -0,0 +1,5 @@ +Accounts +======== + +.. automodule:: alot.account + :members: diff --git a/docs/source/api/commands.rst b/docs/source/api/commands.rst new file mode 100644 index 00000000..f38ac04c --- /dev/null +++ b/docs/source/api/commands.rst @@ -0,0 +1,80 @@ +Commands +========= + +.. module:: alot.commands + +User actions are represented by :class:`Command` objects that can then be triggered by +:meth:`alot.ui.UI.apply_command`. +Commandline strings given by the user via the prompt or keybindings can be translated to +:class:`Command` objects using :func:`alot.commands.commandfactory`. +Specific actions are defined as subclasses of :class:`Command` and can be registered +to a global command pool using the :class:`registerCommand` decorator. + +.. Note:: + + that the return value + of :func:`commandfactory` depends on the current *mode* the user interface is in. + The mode identifier is a string that is uniquely defined by the currently focussed + :class:`~alot.buffers.Buffer`. + +.. note:: + + The names of the commands available to the user in any given mode do not correspond + one-to-one to these subclasses. You can register a Command multiple times under different + names, with different forced constructor parameters and so on. See for instance the + definition of BufferFocusCommand in 'commands/globals.py':: + + @registerCommand(MODE, 'bprevious', forced={'offset': -1}, + help='focus previous buffer') + @registerCommand(MODE, 'bnext', forced={'offset': +1}, + help='focus next buffer') + class BufferFocusCommand(Command): + def __init__(self, buffer=None, offset=0, **kwargs): + ... + +.. autoclass:: Command + :members: + +.. autoclass:: CommandParseError +.. autoclass:: CommandArgumentParser +.. autofunction:: commandfactory +.. autofunction:: lookup_command +.. autofunction:: lookup_parser +.. autoclass:: registerCommand + + +Globals +-------- + +.. automodule:: alot.commands.globals + :members: + +Envelope +-------- + +.. automodule:: alot.commands.envelope + :members: + +Bufferlist +---------- + +.. automodule:: alot.commands.bufferlist + :members: + +Search +-------- + +.. automodule:: alot.commands.search + :members: + +Taglist +-------- + +.. automodule:: alot.commands.taglist + :members: + +Thread +-------- + +.. automodule:: alot.commands.thread + :members: diff --git a/docs/source/api/conf.py b/docs/source/api/conf.py new file mode 100644 index 00000000..0c36a73f --- /dev/null +++ b/docs/source/api/conf.py @@ -0,0 +1,255 @@ +# -*- coding: utf-8 -*- +# +# alot documentation build configuration file, created by +# sphinx-quickstart on Tue Aug 9 15:00:51 2011. +# +# 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 + +############################### +# readthedocs.org hack, +# needed to use autodocs on their build-servers: +# http://readthedocs.org/docs/read-the-docs/en/latest/faq.html?highlight=autodocs#where-do-i-need-to-put-my-docs-for-rtd-to-find-it + +class Mock(object): + def __init__(self, *args, **kwargs): + pass + + def __call__(self, *args, **kwargs): + return Mock() + + @classmethod + def __getattr__(self, name): + return Mock() if name not in ('__file__', '__path__') else '/dev/null' + +MOCK_MODULES = ['notmuch', 'notmuch.globals', + 'twisted', 'twisted.internet', + 'twisted.internet.defer', + 'twisted.python', + 'twisted.python.failure', + 'urwid', + 'magic', + 'argparse'] +for mod_name in MOCK_MODULES: + sys.modules[mod_name] = Mock() + +# end of readthedocs.org hack +############################## + +# 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.insert(0, os.path.abspath('..')) +from alot import __version__,__author__ + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# 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.intersphinx'] + +# 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-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'alot' +copyright = u'2011 ' + __author__ + +# 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 = __version__ +# The full version, including alpha/beta/rc tags. +release = __version__ + +# 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 patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = ['_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. See the documentation for +# a list of builtin themes. +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_domain_indices = 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 = False + +# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = 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 = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'alotdoc' + + +# -- 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', 'alot.tex', u'alot Documentation', + u'Patrick Totzke', '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 + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = 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_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('index', 'alot', u'alot Documentation', + [u'Patrick Totzke'], 1) +] + +autodoc_member_order = 'bysource' +autoclass_content = 'both' +intersphinx_mapping = { + 'python': ('http://docs.python.org/3.2', None), + 'notmuch': ('http://packages.python.org/notmuch', None), + 'urwid': ('http://urwid.readthedocs.org/en/latest', None), + } diff --git a/docs/source/api/contributing.rst b/docs/source/api/contributing.rst new file mode 100644 index 00000000..c5770aca --- /dev/null +++ b/docs/source/api/contributing.rst @@ -0,0 +1,23 @@ +Contributing +============ + +Development is coordinated entirely via the projects `github page <https://github.com/pazz/alot>`_ +especially the `issue tracker <https://github.com/pazz/alot/issues>`_. +Current HEAD can be found in branch `testing` from `git@github.com:pazz/alot.git`. + +You can send patches to notmuch's mailing list but pull requests on github are preferred. +Here are a few more things you should know and check before you send pull requests: + +* Follow :pep:`8`. This means in particular a maximum linewidth of *79* and no trailing + white spaces. If in doubt, use an `automatic tool <http://pypi.python.org/pypi/pep8>`_ + to verify your code. + +* Document! Needless to say, we want readable and well documented code. Moreover, + + * use `sphinx directives <http://sphinx.pocoo.org/rest.html>`_ to document + the parameters and return values of your methods so that we maintain up-to-date API docs. + * Make sure your patch doesn't break the API docs. The build service at `readthedocs.org <http:alot.rtfd.org>`_ + is fragile when it comes to new import statements in our code. + * If you implemented a new feature, update the user manual in :file:`/docs/user` accordingly. + + diff --git a/docs/source/api/database.rst b/docs/source/api/database.rst new file mode 100644 index 00000000..00334a4b --- /dev/null +++ b/docs/source/api/database.rst @@ -0,0 +1,55 @@ +Email Database +============== + +.. module:: alot.db + +The python bindings to libnotmuch define :class:`notmuch.Thread` and +:class:`notmuch.Message`, which unfortunately are very fragile. +Alot defines the wrapper classes :class:`Thread` and :class:`~alot.message.Message` that +use an :class:`DBManager` instance to transparently provide persistent objects. + +:class:`~alot.message.Message` moreover contains convenience methods +to extract information about the message like reformated header values, a summary, +decoded and interpreted body text and a list of :class:`Attachments <alot.message.Attachment>`. + +The central :class:`~alot.ui.UI` instance carries around a :class:`DBManager` object that +is used for any lookups or modifications of the email base. :class:`DBManager` can +directly look up :class:`Thread` and :class:`~alot.message.Message` objects and is able to +postpone/cache/retry writing operations in case the Xapian index is locked by another +process. + + +Database Manager +----------------- +.. autoclass:: DBManager + :members: + + +Exceptions +---------- +.. autoclass:: DatabaseError + :members: +.. autoclass:: DatabaseROError + :members: +.. autoclass:: DatabaseLockedError + :members: + +Wrapper +------- +.. autoclass:: Thread + :members: + +.. module:: alot.message + +.. autoclass:: Message + :members: + + +Other Structures +--------------------------- + +.. autoclass:: Attachment + :members: + +.. autoclass:: Envelope + :members: diff --git a/docs/source/api/index.rst b/docs/source/api/index.rst new file mode 100644 index 00000000..35b4fd7c --- /dev/null +++ b/docs/source/api/index.rst @@ -0,0 +1,15 @@ +API and Development +******************* + +.. module:: alot +.. toctree:: + :maxdepth: 1 + + overview + contributing + database + interface + settings + accounts + utils + commands diff --git a/docs/source/api/interface.rst b/docs/source/api/interface.rst new file mode 100644 index 00000000..0df9d7ca --- /dev/null +++ b/docs/source/api/interface.rst @@ -0,0 +1,110 @@ +User Interface +================== + +Alot sets up a widget tree and an :class:`mainloop <urwid.main_loop.TwistedEventLoop>` +in the constructor of :class:`alot.ui.UI`. The visible area is +a :class:`urwid.Frame`, where the footer is used as a status line and the body part +displays the currently active :class:`alot.buffers.Buffer`. + +To be able to bind keystrokes and translate them to :class:`Commands +<alot.commands.Command>`, keypresses are *not* propagated down the widget tree as is +customary in urwid. Instead, the root widget given to urwids mainloop is a custom wrapper +(:class:`alot.ui.Inputwrap`) that interprets key presses. A dedicated +:class:`~alot.commands.globals.SendKeypressCommand` can be used to trigger +key presses to the wrapped root widget and thereby accessing standard urwid +behaviour. + +In order to keep the interface non-blocking, alot makes use of twisted's deferred_ - a +framework that makes it easy to deal with callbacks. Many commands in alot make use of +`inline callbacks`_, which allow you to treat deferred-returning functions almost like +syncronous functions. Consider the following example of a function that prompts for some +input and acts on it: + +.. _deferred: http://twistedmatrix.com/documents/current/core/howto/defer.html +.. _`inline callbacks`: http://twistedmatrix.com/documents/8.1.0/api/twisted.internet.defer.html#inlineCallbacks + +.. code-block:: python + + from twisted.internet import defer + + @defer.inlineCallbacks + def greet(ui): # ui is instance of alot.ui.UI + name = yield ui.prompt(prefix='pls enter your name>') + ui.notify('your name is: ' + name) + + +:class:`UI` - the main component +----------------------------------- + +.. module:: alot.ui +.. autoclass:: UI + + .. autoattribute:: buffers + .. autoattribute:: current_buffer + .. autoattribute:: dbman + .. autoattribute:: accountman + + .. automethod:: apply_command + .. automethod:: prompt + .. automethod:: choice + .. automethod:: notify + .. automethod:: clear_notify + .. automethod:: buffer_open + .. automethod:: buffer_focus + .. automethod:: buffer_close + .. automethod:: get_buffers_of_type + .. automethod:: exit + + +Buffers +---------- + +A buffer defines a view to your data. It knows how to render itself, to interpret +keypresses and is visible in the "body" part of the widget frame. +Different modes are defined by subclasses of the following base class. + +.. autoclass:: alot.buffers.Buffer + :members: + +Available modes are: + +========== ======================================== + Mode Buffer Subclass +========== ======================================== +search :class:`~alot.buffers.SearchBuffer` +thread :class:`~alot.buffers.ThreadBuffer` +bufferlist :class:`~alot.buffers.BufferlistBuffer` +taglist :class:`~alot.buffers.TagListBuffer` +envelope :class:`~alot.buffers.EnvelopeBuffer` +========== ======================================== + +.. automodule:: alot.buffers + :members: BufferlistBuffer, EnvelopeBuffer,SearchBuffer,ThreadBuffer,TagListBuffer + +Widgets +-------- +What follows is a list of the non-standard urwid widgets used in alot. +Some of them respect :doc:`user settings <settings>`, themes in particular. + +.. automodule:: alot.widgets + :members: + +Completion +---------- + +:meth:`alot.ui.UI.prompt` allows tab completion using a :class:`~alot.completion.Completer` +object handed as 'completer' parameter. :mod:`alot.completion` defines several +subclasses for different occasions like completing email addresses from an +:class:`~alot.account.AddressBook`, notmuch tagstrings. Some of these actually build on top +of each other; the :class:`~alot.completion.QueryCompleter` for example uses a +:class:`~alot.completion.TagsCompleter` internally to allow tagstring completion after +"is:" or "tag:" keywords when typing a notmuch querystring. + +All these classes overide the method :class:`~alot.completion.Completer.complete`, which +for a given string and cursor position in that string returns +a list of tuples `(completed_string, new_cursor_position)` that are taken to be +the completed values. Note that `completed_string` does not need to have the original +string as prefix. + +.. automodule:: alot.completion + :members: diff --git a/docs/source/api/overview.rst b/docs/source/api/overview.rst new file mode 100644 index 00000000..051eacaa --- /dev/null +++ b/docs/source/api/overview.rst @@ -0,0 +1,19 @@ +Overview +======== + +The main component is :class:`alot.ui.UI`, which provides methods for user input and notifications, +sets up an :mod:`urwid` :class:`mainloop <urwid.main_loop.TwistedEventLoop>` and widget tree and +maintains the list of active buffers. Moreover, it integrates different "managers" responsible for +core functionalities: + +* a :class:`~db.DBManager` to access the email database +* an :class:`~account.AccountManager` to deal with user accounts +* a :class:`~settings.AlotConfigParser` (subclasses :class:`configparser.ConfigParser`) for user settings + +Every user action, triggered either by keybindings or as input to the commandprompt, is +given as commandline string that gets :func:`translated <commands.commandfactory>` +to a :class:`~commands.Command` which is then :meth:`applied <ui.UI.apply_command>`. +Different actions are defined as a subclasses of :class:`~commands.Command`, which live +in `alot/commands/MODE.py`, where MODE is the name of the mode (:class:`Buffer` type) they +are used in. + diff --git a/docs/source/api/settings.rst b/docs/source/api/settings.rst new file mode 100644 index 00000000..f7272756 --- /dev/null +++ b/docs/source/api/settings.rst @@ -0,0 +1,55 @@ +Accessing User Settings +======================= + +.. module:: alot.settings + +There are four types of user settings: notmuchs and alot's config +files, the hooks-file for user provided python code and the mailcap, +defining shellcomands as handlers for files of certain mime types. + +Alot sets up :class:`FallbackConfigParser` objects to access the configs +of alot and notmuch`. +Hooks can be accessed via :meth:`AlotConfigParser.get_hook` +and MIME handlers can be looked up using :func:`alot.settings.get_mime_handler`. + ++----------------+-----------------------------------+------------------------------+ +| What | accessible via | Type | ++================+===================================+==============================+ +| alot config | :obj:`alot.settings.config` | :class:`AlotConfigParser` | ++----------------+-----------------------------------+------------------------------+ +| notmuch config | :obj:`alot.settings.notmuchconfig`| :class:`FallbackConfigParser`| ++----------------+-----------------------------------+------------------------------+ + +Through these objects you can access user settings (or their default values +if unset) in the following manner:: + + from alot.settings import config, notmuchconfig + + # alot config + >>> config.getint('general', 'notify_timeout') + 5 + >>> config.getboolean('general', 'show_statusbar') + True + >>> config.getstringlist('general', 'displayed_headers') + [u'From', u'To', u'Cc', u'Bcc', u'Subject'] + + # notmuch config + >>> notmuchconfig.get('user', 'primary_email') + 'patricktotzke@gmail.com' + >>> notmuchconfig.getboolean('maildir', 'synchronize_flags') + True + +Hooks can be looked up using :meth:`AlotConfigParser.get_hook`. +They are user defined callables that expect to be called with the following parameters: + + :ui: :class:`~alot.ui.UI` -- the initialized main component + :dbm: :class:`~alot.db.DBManager` -- :obj:`ui.dbman` + :aman: :class:`~alot.account.AccountManager` -- :obj:`ui.accountman` + :log: :class:`~logging.Logger` -- :obj:`ui.logger` + :config: :class:`AlotConfigParser` :obj:`alot.settings.config` + +.. autoclass:: FallbackConfigParser + :members: +.. autoclass:: AlotConfigParser + :members: +.. autofunction:: get_mime_handler diff --git a/docs/source/api/utils.rst b/docs/source/api/utils.rst new file mode 100644 index 00000000..8cfae2b7 --- /dev/null +++ b/docs/source/api/utils.rst @@ -0,0 +1,7 @@ +Utils +===== + +.. currentmodule:: alot.helper + +.. automodule:: alot.helper + :members: diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 00000000..7a74dd46 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,254 @@ +# -*- coding: utf-8 -*- +# +# alot documentation build configuration file, created by +# sphinx-quickstart on Tue Jan 10 16:45:54 2012. +# +# 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 + +############################### +# readthedocs.org hack, +# needed to use autodocs on their build-servers: +# http://readthedocs.org/docs/read-the-docs/en/latest/faq.html?highlight=autodocs#where-do-i-need-to-put-my-docs-for-rtd-to-find-it + +class Mock(object): + def __init__(self, *args, **kwargs): + pass + + def __call__(self, *args, **kwargs): + return Mock() + + @classmethod + def __getattr__(self, name): + return Mock() if name not in ('__file__', '__path__') else '/dev/null' + +MOCK_MODULES = ['notmuch', 'notmuch.globals', + 'twisted', 'twisted.internet', + 'twisted.internet.defer', + 'twisted.python', + 'twisted.python.failure', + 'twisted.internet.protocol', + 'urwid', + 'magic', + 'argparse'] +for mod_name in MOCK_MODULES: + sys.modules[mod_name] = Mock() + +# end of readthedocs.org hack +############################## + +# 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.insert(0, os.path.abspath('..')) +from alot import __version__,__author__ + +# -- General configuration ----------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.0' + +# 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.intersphinx'] + +# 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-sig' + +# The master toctree document. +master_doc = 'index' + +# General information about the project. +project = u'alot' +copyright = u'2012, Patrick Totzke' + +# 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.21' +# The full version, including alpha/beta/rc tags. +release = '0.21' + +# 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 patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns = [] + +# 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. See the documentation for +# a list of builtin themes. +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 = {'nosidebar': True} + +# 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 = 'Alot User Manual' + +# 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_domain_indices = 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, "Created using Sphinx" is shown in the HTML footer. Default is True. +#html_show_sphinx = True + +# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. +#html_show_copyright = 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 = '' + +# This is the file name suffix for HTML files (e.g. ".xhtml"). +#html_file_suffix = None + +# Output file base name for HTML help builder. +htmlhelp_basename = 'alotdoc' + + +# -- 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', 'alot.tex', u'alot Documentation', + u'Patrick Totzke', '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 + +# If true, show page references after internal links. +#latex_show_pagerefs = False + +# If true, show URL addresses after external links. +#latex_show_urls = 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_domain_indices = True + + +# -- Options for manual page output -------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [ + ('manpage', 'alot', u'mail user agent for the notmuch mail system', + [u'Patrick Totzke'], 1), + ('configuration', 'alot.rc', u'CONF', + [u'Patrick Totzke'], 5) +] + + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'http://docs.python.org/': None} diff --git a/docs/source/configuration.rst b/docs/source/configuration.rst new file mode 100644 index 00000000..1c1d3eec --- /dev/null +++ b/docs/source/configuration.rst @@ -0,0 +1,428 @@ +************* +Configuration +************* + + +All configs are optional, but if you want to send mails you need to +specify at least one account section. + +Alot reads a config file in the "INI" syntax: +It consists of some sections whose names are given in square brackets, followed by +key-value pairs that use "=" or ":" as separator, ';' and '#' are comment-prefixes. + +The default location for the config file is `~/.config/alot/config`. +You can find a complete example config with the default values and their decriptions in +`alot/defaults/alot.rc`. + +Note that since ":" is a separator for key-value pairs you need to use "colon" to bind +commands to ":". + +Here is a key for the interpreted sections: + +[general] + global settings: set your editor etc +[account X] + defines properties of account X: (see below) +[X-maps] + defines keymaps for mode X. possible modes are: + envelope, search, thread, taglist, bufferlist and global. + global-maps are valid in all modes. +[tag-translate] + defines a map from tagnames to strings that is used when + displaying tags. utf-8 symbols welcome. +[Xc-theme] + define colour palette for colour mode. X is in {1, 16, 256}. + + +Accounts +======== +A sample gmail section looks like this (provided you have configured msmtp accordingly):: + + [account gmail] + realname = Patrick Totzke + address = patricktotzke@gmail.com + aliases = patricktotzke@googlemail.com + sendmail_command = msmtp --account=gmail -t + +Here's a full list of the interpreted keywords in account sections:: + + # used to format the (proposed) From-header in outgoing mails + realname = your name + address = this accounts email address + + # used to clear your addresses/ match account when formating replies + aliases = foobar@myuni.uk;f.bar@myuni.uk;f.b100@students.myuni.uk + + # how to send mails + sendmail_command = command, defaults to 'sendmail' + + # where to store outgoing mail + sent_box = maildir:///home/you/mail//Sent + + # how to tag sent mails [default: sent]. seperate multiple tags with ','. + sent_tags = sent + + # path to signature file + signature = ~/your_vcard_for_this_account.vcs + + # attach signature file if set to True, append its content (mimetype text) + # to the body text if set to False. Defaults to False. + signature_as_attachment = False + + # signature file's name as it appears in outgoing mails if + # signature_as_attachment is set to True + signature_filename = you.vcs + + # command to lookup contacts + abook_command = abook --mutt-query + abook_regexp = regexp to match name & address in abook_commands output. + +.. warning:: + + Sending mails is only supported via sendmail for now. If you want + to use a sendmail command different from `sendmail`, specify it as `sendmail_command`. + +`send_box` specifies the mailbox where you want outgoing mails to be stored +after successfully sending them. You can use mbox, maildir, mh, babyl and mmdf +in the protocol part of the url. + +The file specified by `signature` is attached to all outgoing mails from this account, optionally +renamed to `signature_filename`. + +If you specified `abook_command`, it will be used for tab completion in queries (to/from) +and in message composition. The command will be called with your prefix as only argument +and its output is searched for name-email pairs. The regular expression used here +defaults to `(?P<email>.+?@.+?)\s+(?P<name>.+)`, which makes it work nicely with `abook --mutt-query`. +You can tune this using the `abook_regexp` option (beware Commandparsers escaping semantic!). +Have a look at the FAQ for other examples. + + +Key Bindings +============ +If you want to bind a commandline to a key you can do so by adding the pair to the +`[MODE-maps]` config section, where MODE is the buffer mode you want the binding to hold. +Consider the following lines, which allow you to send mails in envelope buffers using the +combination `control` + `s`:: + + [envelope-maps] + ctrl s = send + +Possible MODE strings are: + +* envelope +* search +* thread +* taglist +* bufferlist +* global + +Bindings defined in section `[global-maps]` are valid in all modes. + +Have a look at `the urwid User Input documentation <http://excess.org/urwid/wiki/UserInput>`_ on how key strings are formated. + + + +Hooks +===== +Hooks are python callables that live in a module specified by `hooksfile` in the `[global]` +section of your config. Per default this points to `~/.config/alot/hooks.py`. +For every command X in mode M, the callables 'pre_M_X' and 'post_M_X' +-- if defined -- will be called before and after the command is applied respectively. + +When a hook gets called, it receives instances of + +ui + `alot.ui.UI`, the main user interface object that can prompt etc. +dbm + `alot.db.DBManager`, the applications database manager +aman + `alot.account.AccountManager`, can be used to look up account info +config + `alot.settings.config`, a configparser to access the users config + +An autogenerated API doc for these can be found at http://alot.rtfd.org , +the sphinx sources live in the `docs` folder. +As an example, consider this pre-hook for the exit command, +that logs a personalized goodby message:: + + import logging + def pre_global_exit(aman=None, **rest): + accounts = aman.get_accounts() + if accounts: + logging.info('goodbye, %s!' % accounts[0].realname) + else: + logging.info('goodbye!') + +Apart from command pre and posthooks, the following hooks will be interpreted: + +`reply_prefix(realname, address, timestamp, **kwargs)` + Is used to reformat the first indented line in a reply message. + Should return a string and defaults to 'Quoting %s (%s)\n' % (realname, timestamp) +`forward_prefix(realname, address, timestamp, **kwargs)` + Is used to reformat the first indented line in a inline forwarded message. + Returns a string and defaults to 'Forwarded message from %s (%s)\n' % (realname, timestamp) +`pre_edit_translate(bodytext, **kwargs)` + can be used to manipulate a messages bodytext before the editor is called. + Receives and returns a string. +`post_edit_translate(bodytext, **kwargs)` + can be used to manipulate a messages bodytext after the editor is called + Receives and returns a string. + + + +Widget Colours +============== +Alot can be run in 1, 16 or 256 colour mode. +The requested mode is determined by the commandline parameter `-C` or read from +option `colourmode` in section `[globals]` of your config file. +The default is 256, which will be scaled down depending on how many colours +your terminal supports. + +The interface will theme its widgets according to the palette defined in +section `[MODEc-theme]` where `MODE` is the integer indicating the colour mode. +Have a look at the default config (`alot/defaults/alot.rc`) for a complete list +of interpreted widget settings; the keys in this section should be self-explanatory. + +Values can be colour names (`light red`, `dark green`..), RGB colour codes (e.g. `#868`), +font attributes (`bold`, `underline`, `blink`, `standout`) or a comma separated combination of +colour and font attributes. +In sections `[16c-theme]` and `[256c-theme]` you can define Y_fg and +Y_bg for the foreground and background of each widget keyword Y, whereas the monochromatic +(`[1c-theme]`) palette can only interpret font attributes for key Y without the suffix. +As an example, check the setting below that makes the footer line appear as +underlined bold red text on a bright green background:: + + [256c-theme] + global_footer_bg = #8f6 + global_footer_fg = light red, bold, underline + +See `urwids docs on Attributes <http://excess.org/urwid/reference.html#AttrSpec>`_ for more details +on the interpreted values. Urwid provides a `neat colour picker script`_ that makes choosing +colours easy. + +.. _neat colour picker script: http://excess.org/urwid/browser/palette_test.py + + +Custom Tagstring Formatting +=========================== +In theme sections you can use keys with prefix `tag_` to format specific tagstrings. For instance, +the following will make alot display the "todo" tag in white on red when in 256c-mode. :: + + [256c-theme] + tag_todo_bg = #d66 + tag_todo_fg = white + +You can translate tag strings before displaying them using the `[tag-translate]` section. A +key=value statement in this section is interpreted as: +Always display the tag `key` as string `value`. Utf-8 symbols are welcome here, see e.g. +http://panmental.de/symbols/info.htm for some fancy symbols. I personally display my maildir flags +like this:: + + [tag-translate] + flagged = ⚑ + unread = ✉ + replied = ⇄ + +Highlighting Search Results +=========================== +Thread lines in the ``SearchBuffer`` can be highlighted by applying a theme different +from their regular one if they match a `notmuch` query. + +The default config predefines highlighting for threads that carry the `unread`, +the `flagged` or both of those tags. + +Thread lines consist of up to six components (not all of which are shown by +default) that may be themed individually to provide highlighting. The components +are + + - `date` + - `mailcount` + - `tags` + - `authors` + - `subject` + - `content` + +Have a look at Alot's interface to see what they are. + +Customizing highlighting, you may define which components you want highlighted. +Add a `highlighting` section to your config file and define a comma separated +list of highlightable components: :: + + [highlighting] + components = date, mailcount, tags, authors, subject + +Rules +----- +To specify which threads should be highlighted, you need to define highlighting +rules. Rules map queries onto theme identifiers. Each thread that matches a given rule +will use a theme identified by the ID the rule is mapped to. + +.. admonition:: Example + + To highlight threads that are tagged as 'important', add the `rules` + key to your `highlighting` section and provide a dict in JSON syntax. Use an + appropriate `notmuch` query as a key and select a meaningful theme identifier as + its value: + +:: + + rules = { "tag:important":"isimportant" } + +.. note:: + Please make sure the identifier isn't the name of an actual tag, since this + may introduce ambiguity when highlighting tags. More on that `later`_. + +If you want highlighting for other threads as well, just add more rules to the +dict: :: + + rules = { "tag:important":"isimportant", + "subject:alot":"concernsalot", + "from:mom@example.com":"frommom"} + +.. note:: + The sequence of the list defines the search order. The first query that + matches selects the highlighting. So if you have queries that are harder to + satisfy, you should put them earlier in the dict than ones that match more + easily: + +:: + + rules = { "tag:unread":"isunread", + "tag:unread AND tag:important":"isunreadimportant"} + +This setup will never highlight any threads as `isunreadimportant`, since alle +threads that would match that identifier's query will *also* have matched the +`isunread` query earlier in the rules dict. So, again, make sure that rules that +are hard to satisfy show up early in the dict: :: + + rules = { "tag:unread AND tag:important":"isunreadimportant", + "tag:unread":"isunread"} + +This way only threads that didn't match `isunreadimportant` before end up +highlighted as `isunread` only. + +.. _later: `ambiguous theme identifiers`_ + +Theme Generic Components +------------------------ +.. note:: + The following schema will allow you to define highlighting themes for all + components *except* `tags`, which follow a different system and will be + explained in the `next section`_. + +To define a highlighting theme for a component, you need to add a key of the +following format to your colour theme (please cf. `Widget Colours`_ for more information +on theming): :: + + search_thread_COMPONENT_ID_[focus_][fg|bg] + +where + + - ``COMPONENT`` is the component this theme is meant to highlight, + - ``ID`` is the theme identifier that defines which query this option belongs + to, + - ``focus_`` is optional and if present defines that the theme should only be + used if the current thread is focussed and + - ``fg`` or ``bg`` is a selection that specifies which themable part of the + component this option refers to. + +.. admonition:: Example + + The following option will highlight the `subject` of each thread that + matches the query mapping to `isimportant` if the current thread is + `focus`\sed by theming its `foreground` according to the values stated + below: + +:: + + search_thread_subject_isimportant_focus_fg = dark red, underline + +Following this pattern will allow you to set theming for the `background`, for +the `subject` of threads tagged as `important` that are currently not focussed +(by omitting the `focus_` part of the key string), for `subject`\s of threads +matching a different query, and all other components except `tags`. + +.. _next section: `Theme Tags Component`_ + +Theme `Tags` Component +---------------------- +As described in `Custom Tagstring Formatting`_, tags may be themed individually. +Highlighting expands this concept by allowing default themed tags as well as +individual themed tags to provide highlighting variants. + +To specify highlighting themes for default themed tags, just add a key with the wanted +theme identifier: :: + + tag_ID_[focus_][fg|bg] + +where + + - ``ID`` is the theme identifier that defines which query this option belongs + to, + - ``focus_`` is optional and if present defines that the theme should only be + used if the current thread is focussed and + - ``fg`` or ``bg`` is a selection that specifies which themable part of the + component this option refers to. + +To highlight custom themed tags, proceed accordingly. Specify :: + + tag_TAG_ID_[focus_][fg|bg] + +where + + - ``TAG`` is the name of the custom themed tag that is to be highlighted, + - ``ID`` is the theme identifier that defines which query this option belongs + to, + - ``focus_`` is optional and if present defines that the theme should only be + used if the current thread is focussed and + - ``fg`` or ``bg`` is a selection that specifies which themable part of the + component this option refers to. + +.. _ambiguous theme identifiers: +.. caution:: + As mentioned earlier, using tag names as theme identifiers may introduce + ambiguity and lead to unexpected theming results. + +Assuming one would replace the theme identifier `isimportant` with its intuitive +alternative `important`, the tag theme ``tag_important_fg`` might either be a +custom theme for the tag `important` of the form ``tag_TAG_fg`` or the highlight +theme for default themed tags of threads that match the query that maps to the +`important` identifier: ``tag_ID_fg``. + +Using above proper identifier would distinguish those options as +``tag_important_fg`` for the custom theme and ``tag_isimportant_fg`` for the +highlighting theme. + + +Contacts Completion +=================== +In each `account` section you can specify a `abook_command` that +is considered the address book of that account and will be used +for address completion where appropriate. + +This shell command will be called with the search prefix as only argument. +Its output is searched for email-name pairs using the regular expression given as `abook_regexp`, +which must include named groups "email" and "name" to match the email address and realname parts +respectively. See below for an example that uses `abook <http://abook.sourceforge.net/>`_:: + + [account YOURACCOUNT] + realname = ... + address = ... + abook_command = abook --mutt-query + abook_regexp = '(?P<email>.+?@.+?)\s+(?P<name>.+?)\s*$' + +See `here <http://notmuchmail.org/emacstips/#index11h2>`_ for alternative lookup commands. The few others I have tested so far are: + +`goobook <http://code.google.com/p/goobook/>`_ + for cached google contacts lookups:: + + abook_command = goobook query + abook_regexp = (?P<email>.+?@.+?)\s\s+(?P<name>.+)\s\s+.+ + +`nottoomuch-addresses <http://www.iki.fi/too/nottoomuch/nottoomuch-addresses/>`_ + completes contacts found in the notmuch index:: + + abook_command = nottoomuch-addresses.sh + abook_regexp = \"(?P<name>.+)\"\s*<(?P<email>.*.+?@.+?)> + +Don't hesitate to send me your custom `abook_regexp` values to list them here. diff --git a/docs/source/description.rst b/docs/source/description.rst new file mode 100644 index 00000000..9dea9693 --- /dev/null +++ b/docs/source/description.rst @@ -0,0 +1,4 @@ +Alot is a terminal-based mail user agent for the notmuch mail system. +It features a modular and command prompt driven interface +to provide a full MUA experience as an alternative to the Emacs mode shipped +with notmuch. diff --git a/docs/source/generate_commands.py b/docs/source/generate_commands.py new file mode 100755 index 00000000..9179b952 --- /dev/null +++ b/docs/source/generate_commands.py @@ -0,0 +1,143 @@ +import sys +import os +HERE = os.path.dirname(__file__) +sys.path.append(os.path.join(HERE, '..', '..', '..')) +from alot.commands import * +from alot.commands import COMMANDS +import alot.buffers +from argparse import HelpFormatter, SUPPRESS, OPTIONAL, ZERO_OR_MORE, ONE_OR_MORE, PARSER, REMAINDER +from gettext import gettext as _ +import collections as _collections +import copy as _copy +import os as _os +import re as _re +import sys as _sys +import textwrap as _textwrap + +#print """ +#******** +#Commands +#******** +#""" + +class HF(HelpFormatter): + def _metavar_formatter(self, action, default_metavar): + if action.metavar is not None: + result = action.metavar + else: + result = default_metavar + + def format(tuple_size): + if isinstance(result, tuple): + return result + else: + return (result, ) * tuple_size + return format + + +def rstify_parser(parser): + #header = parser.format_usage().strip() + #print '\n\n%s\n' % header + '_' * len(header) + parser.formatter_class = HF + #parser.print_help() + #continue + + formatter = parser._get_formatter() + out = "" + + # usage + usage = formatter._format_usage(None, parser._actions, + parser._mutually_exclusive_groups, + '').strip() + usage = usage.replace('--','---') + + # section header + out += '.. index:: %s\n' % parser.prog + out +='\n%s\n' % parser.prog + out += '_'*len(parser.prog) + out += '\n\n' + + # description + out += parser.description + out += '\n\n' + + if len(parser._positionals._group_actions) == 1: + out += "argument\n" + a = parser._positionals._group_actions[0] + out += "\t%s" % parser._positionals._group_actions[0].help + if a.choices: + out += ". valid choices are: %s." % ','.join(['\`%s\`' % s for s + in a.choices]) + if a.default: + out += ". defaults to: '%s'." % a.default + out += '\n\n' + elif len(parser._positionals._group_actions) > 1: + out += "positional arguments\n" + for index, a in enumerate(parser._positionals._group_actions): + out += "\t:%s: %s" % (index, a.help) + if a.choices: + out += ". valid choices are: %s." % ','.join(['\`%s\`' % s for s + in a.choices]) + if a.default: + out += ". defaults to: '%s'." % a.default + out += '\n' + out += '\n\n' + + if parser._optionals._group_actions: + out += "optional arguments\n" + for a in parser._optionals._group_actions: + switches = [s.replace('--','---') for s in a.option_strings] + out += "\t:%s: %s" % (', '.join(switches), a.help) + if a.choices: + out += ". Valid choices are: %s" % ','.join(['\`%s\`' % s for s + in a.choices]) + if a.default: + out += " (Defaults to: '%s')" % a.default + out += '.\n' + out += '\n' + + # epilog + #out += formatter.add_text(parser.epilog) + + return out + +def get_mode_docs(): + docs = {} + b = alot.buffers.Buffer + for entry in alot.buffers.__dict__.values(): + if isinstance(entry, type): + if issubclass(entry, b) and not entry == b: + docs[entry.modename] = entry.__doc__.strip() + return docs + + +if __name__ == "__main__": + + modes = [] + for mode, modecommands in COMMANDS.items(): + modefilename = mode+'.rst' + modefile = open(os.path.join(HERE, 'usage', 'modes', modefilename), 'w') + modefile.write('%s\n%s\n' % (mode, '-' * len(mode))) + if mode != 'global': + modes.append(mode) + modefile.write('The following commands are available in %s mode\n\n' % mode) + else: + modefile.write('The following commands are available globally\n\n') + for cmdstring,struct in modecommands.items(): + cls, parser, forced_args = struct + modefile.write(rstify_parser(parser)) + modefile.close() + indexfile = open(os.path.join(HERE, 'usage', 'commands.rst'), 'w') + + mode_docstrings = get_mode_docs() + tbl = ':doc:`modes/global`\n' + tbl += (' ' * 4) + 'globally available commands\n' + for m in modes: + tbl += ':doc:`modes/%s`\n' % m + tbl += (' ' * 4) + mode_docstrings[m] + '\n' + + includes = '\n'.join([':doc:`modes/%s`' % m for m in modes]) + indexfile.write('Commands\n========\n\n') + indexfile.write('\n\n') + indexfile.write(tbl) + indexfile.close() diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 00000000..03dacb4b --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,16 @@ +.. alot documentation master file, created by + sphinx-quickstart on Tue Jan 10 16:45:54 2012. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +User Manual +=========== +.. include:: description.rst + +.. toctree:: + :maxdepth: 2 + :numbered: + + usage/index + configuration + api/index diff --git a/docs/source/manpage.rst b/docs/source/manpage.rst new file mode 100644 index 00000000..ae62bce7 --- /dev/null +++ b/docs/source/manpage.rst @@ -0,0 +1,26 @@ +.. alot documentation master file, created by + sphinx-quickstart on Tue Jan 10 16:45:54 2012. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +Manpage +======= + +Synopsis +-------- + +.. include:: usage/synopsis.rst + +Description +----------- + +.. include:: description.rst + +Usage +----- +.. include:: usage/first_steps.rst + + +See Also +----- +:manpage:`alot.rc(5)` diff --git a/docs/source/usage/commands.rst b/docs/source/usage/commands.rst new file mode 100644 index 00000000..8608bc50 --- /dev/null +++ b/docs/source/usage/commands.rst @@ -0,0 +1,17 @@ +Commands +======== + + + +:doc:`modes/global` + globally available commands +:doc:`modes/search` + shows a result list of threads for a query +:doc:`modes/thread` + displays a thread as a tree of messages +:doc:`modes/envelope` + message composition mode +:doc:`modes/bufferlist` + lists all active buffers +:doc:`modes/taglist` + lists all tagstrings present in the notmuch database diff --git a/docs/source/usage/first_steps.rst b/docs/source/usage/first_steps.rst new file mode 100644 index 00000000..3ffa09ac --- /dev/null +++ b/docs/source/usage/first_steps.rst @@ -0,0 +1,6 @@ +The arrow keys, `page-up/down`, `j`, `k` and `Space` can be used to move the focus. +`Escape` cancels prompts and `Enter` selects. Hit `:` at any time and type in commands +to the prompt. + +Usage information on any command can be listed by typing `help YOURCOMMAND` to the prompt; +The key bindings for the current mode are listed upon pressing `?`. diff --git a/docs/source/usage/index.rst b/docs/source/usage/index.rst new file mode 100644 index 00000000..7e97e78e --- /dev/null +++ b/docs/source/usage/index.rst @@ -0,0 +1,14 @@ +***** +Usage +***** + +Commandline invocation +====================== +.. include:: synopsis.rst + +First Steps +=========== + +.. include:: first_steps.rst + +.. include:: commands.rst diff --git a/docs/source/usage/modes/bufferlist.rst b/docs/source/usage/modes/bufferlist.rst new file mode 100644 index 00000000..b619edf5 --- /dev/null +++ b/docs/source/usage/modes/bufferlist.rst @@ -0,0 +1,20 @@ +bufferlist +---------- +The following commands are available in bufferlist mode + +.. index:: close + +close +_____ + +close focussed buffer + + +.. index:: select + +select +______ + +focus selected buffer + + diff --git a/docs/source/usage/modes/envelope.rst b/docs/source/usage/modes/envelope.rst new file mode 100644 index 00000000..5e7cc1f3 --- /dev/null +++ b/docs/source/usage/modes/envelope.rst @@ -0,0 +1,87 @@ +envelope +-------- +The following commands are available in envelope mode + +.. index:: set + +set +___ + +set header value + +positional arguments + :0: header to refine + :1: value + + +optional arguments + :---append: keep previous values. + +.. index:: toggleheaders + +toggleheaders +_____________ + +toggle display of all headers + + +.. index:: edit + +edit +____ + +edit mail + +optional arguments + :---spawn: force spawning of editor in a new terminal. + :---no-refocus: don't refocus envelope after editing (Defaults to: 'True'). + +.. index:: send + +send +____ + +send mail + + +.. index:: attach + +attach +______ + +attach files to the mail + +argument + file(s) to attach (accepts wildcads) + + +.. index:: refine + +refine +______ + +prompt to change the value of a header + +argument + header to refine + + +.. index:: save + +save +____ + +save draft + + +.. index:: unset + +unset +_____ + +remove header field + +argument + header to refine + + diff --git a/docs/source/usage/modes/global.rst b/docs/source/usage/modes/global.rst new file mode 100644 index 00000000..845db65f --- /dev/null +++ b/docs/source/usage/modes/global.rst @@ -0,0 +1,174 @@ +global +------ +The following commands are available globally + +.. index:: bclose + +bclose +______ + +close a buffer + + +.. index:: bprevious + +bprevious +_________ + +focus previous buffer + + +.. index:: search + +search +______ + +open a new search buffer + +argument + search string + +optional arguments + :---sort: sort order. Valid choices are: \`oldest_first\`,\`newest_first\`,\`message_id\`,\`unsorted\`. + +.. index:: compose + +compose +_______ + +compose a new email + +optional arguments + :---sender: sender. + :---template: path to a template message file. + :---subject: subject line. + :---to: recipients. + :---cc: copy to. + :---bcc: blind copy to. + :---attach: attach files. + :---omit_signature: do not add signature. + :---spawn: spawn editor in new terminal. + +.. index:: prompt + +prompt +______ + +prompts for commandline and interprets it upon select + +argument + initial content + + +.. index:: help + +help +____ + + + display help for a command. Use 'bindings' to + display all keybings interpreted in current mode.' + + +argument + command or 'bindings' + + +.. index:: move + +move +____ + +move focus + +argument + direction + + +.. index:: shellescape + +shellescape +___________ + +run external command + +argument + command line to execute + +optional arguments + :---spawn: run in terminal window. + :---thread: run in separate thread. + :---refocus: refocus current buffer after command has finished. + +.. index:: refresh + +refresh +_______ + +refresh the current buffer + + +.. index:: cancel + +cancel +______ + +send cancel event + + +.. index:: pyshell + +pyshell +_______ + +open an interactive python shell for introspection + + +.. index:: exit + +exit +____ + +shut down cleanly + + +.. index:: flush + +flush +_____ + +flush write operations or retry until committed + + +.. index:: bufferlist + +bufferlist +__________ + +open a list of active buffers + + +.. index:: bnext + +bnext +_____ + +focus next buffer + + +.. index:: select + +select +______ + +send select event + + +.. index:: taglist + +taglist +_______ + +opens taglist buffer + + diff --git a/docs/source/usage/modes/search.rst b/docs/source/usage/modes/search.rst new file mode 100644 index 00000000..6a8632d5 --- /dev/null +++ b/docs/source/usage/modes/search.rst @@ -0,0 +1,108 @@ +search +------ +The following commands are available in search mode + +.. index:: sort + +sort +____ + +set sort order + +argument + sort order. valid choices are: \`oldest_first\`,\`newest_first\`,\`message_id\`,\`unsorted\`. + + +.. index:: untag + +untag +_____ + +remove tags from all messages in the thread + +argument + comma separated list of tags + +optional arguments + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + +.. index:: retag + +retag +_____ + +set tags of all messages in the thread + +argument + comma separated list of tags + +optional arguments + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + +.. index:: refineprompt + +refineprompt +____________ + +prompt to change this buffers querystring + + +.. index:: tag + +tag +___ + +add tags to all messages in the thread + +argument + comma separated list of tags + +optional arguments + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + +.. index:: refine + +refine +______ + +refine query + +argument + search string + +optional arguments + :---sort: sort order. Valid choices are: \`oldest_first\`,\`newest_first\`,\`message_id\`,\`unsorted\`. + +.. index:: retagprompt + +retagprompt +___________ + +prompt to retag selected threads' tags + + +.. index:: toggletags + +toggletags +__________ + +flip presence of tags on this thread. + A tag is considered present if at least one message contained in this + thread is tagged with it. In that case this command will remove the tag + from every message in the thread. + + +argument + comma separated list of tags + +optional arguments + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + +.. index:: select + +select +______ + +open thread in a new buffer + + diff --git a/docs/source/usage/modes/taglist.rst b/docs/source/usage/modes/taglist.rst new file mode 100644 index 00000000..4272ccfa --- /dev/null +++ b/docs/source/usage/modes/taglist.rst @@ -0,0 +1,12 @@ +taglist +------- +The following commands are available in taglist mode + +.. index:: select + +select +______ + +search for messages with selected tag + + diff --git a/docs/source/usage/modes/thread.rst b/docs/source/usage/modes/thread.rst new file mode 100644 index 00000000..41d58b52 --- /dev/null +++ b/docs/source/usage/modes/thread.rst @@ -0,0 +1,193 @@ +thread +------ +The following commands are available in thread mode + +.. index:: pipeto + +pipeto +______ + +pipe message(s) to stdin of a shellcommand + +argument + shellcommand to pipe to + +optional arguments + :---all: pass all messages. + :---format: output format. Valid choices are: \`raw\`,\`decoded\`,\`id\`,\`filepath\` (Defaults to: 'raw'). + :---separately: call command once for each message. + :---background: don't stop the interface. + :---add_tags: add 'Tags' header to the message. + :---shell: let the shell interpret the command. + :---notify_stdout: display command's stdout as notification message. + +.. index:: editnew + +editnew +_______ + +edit message in as new + + +.. index:: toggleheaders + +toggleheaders +_____________ + +display all headers + +optional arguments + :---all: affect all messages. + +.. index:: print + +print +_____ + +print message(s) + +optional arguments + :---all: print all messages. + :---raw: pass raw mail string. + :---separately: call print command once for each message. + :---add_tags: add 'Tags' header to the message. + +.. index:: remove + +remove +______ + +remove message(s) from the index + +optional arguments + :---all: remove whole thread. + +.. index:: togglesource + +togglesource +____________ + +display message source + +optional arguments + :---all: affect all messages. + +.. index:: retag + +retag +_____ + +set message(s) tags. + +argument + comma separated list of tags + +optional arguments + :---all: tag all messages in thread. + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + +.. index:: fold + +fold +____ + +fold message(s) + +optional arguments + :---all: fold all messages. + +.. index:: tag + +tag +___ + +add tags to message(s) + +argument + comma separated list of tags + +optional arguments + :---all: tag all messages in thread. + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + +.. index:: untag + +untag +_____ + +remove tags from message(s) + +argument + comma separated list of tags + +optional arguments + :---all: tag all messages in thread. + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + +.. index:: unfold + +unfold +______ + +unfold message(s) + +optional arguments + :---all: unfold all messages. + +.. index:: forward + +forward +_______ + +forward message + +optional arguments + :---attach: attach original mail. + +.. index:: reply + +reply +_____ + +reply to message + +optional arguments + :---all: reply to all. + +.. index:: save + +save +____ + +save attachment(s) + +argument + path to save to + +optional arguments + :---all: save all attachments. + +.. index:: toggletags + +toggletags +__________ + +flip presence of tags on message(s) + +argument + comma separated list of tags + +optional arguments + :---all: tag all messages in thread. + :---no-flush: postpone a writeout to the index (Defaults to: 'True'). + +.. index:: select + +select +______ + +select focussed element. The fired action depends on the focus: + - if message summary, this toggles visibility of the message, + - if attachment line, this opens the attachment + + diff --git a/docs/source/usage/synopsis.rst b/docs/source/usage/synopsis.rst new file mode 100644 index 00000000..c18bfa03 --- /dev/null +++ b/docs/source/usage/synopsis.rst @@ -0,0 +1,31 @@ +.. code-block:: none + + alot [-r] [-c CONFIGFILE] [-n NOTMUCHCONFIGFILE] [-C {1,16,256}] [-p DB_PATH] + [-d {debug,info,warning,error}] [-l LOGFILE] [--version] [--help] + [command] + +Options + + -r, --read-only open db in read only mode + -c, --config=FILENAME config file (default: ~/.config/alot/config) + -n, --notmuch-config=FILENAME notmuch config (default: ~/.notmuch-config) + -C, --colour-mode=COLOR terminal colour mode (default: 256). Must be 1, 16 or 256 + -p, --mailindex-path=PATH path to notmuch index + -d, --debug-level=LEVEL debug log (default: info). Must be one of debug,info,warning or error + -l, --logfile=FILENAME logfile (default: /dev/null) + --version Display version string and exit + --help Display help and exit + +% .. option:: -m <module>, --module <module> +% +% Run a module as a script. +% + + +Commands + + search + start in a search buffer using the querystring provided as + parameter. See the SEARCH SYNTAX section of notmuch(1). + compose + compose a new message |