# HG changeset patch # User Pascal Volk <user@localhost.localdomain.org> # Date 1346619700 0 # Node ID ab97727357a494240ae8b302cbd2481dccb86b11 # Parent b994444f7dee8b1f31217aeadcd9c0e453ecceef VMM/cli: Activated help subcommand. Implemented Command.help_(), which reads the command's help message from cli.clihelp. diff -r b994444f7dee -r ab97727357a4 VirtualMailManager/cli/clihelp.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/VirtualMailManager/cli/clihelp.py Sun Sep 02 21:01:40 2012 +0000 @@ -0,0 +1,222 @@ +# -*- coding: UTF-8 -*- +# Copyright (c) 2012, Pascal Volk +# See COPYING for distribution information. +""" + VirtualMailManager.cli.vmmhelp + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + Virtual Mail Manager's command line help. +""" + +_ = lambda msg: msg + + +help_msgs = {'configget': (_(u"""This subcommand is used to display the +actual value of the given configuration <option>."""),), + # configset + 'configset': (_(u"""Use this subcommand to set or update a single +configuration option's value. <option> is the configuration option, <value> +is the <option>'s new value."""), +_(u"""Note: This subcommand will create a new vmm.cfg without any comments. +Your current configuration file will be backed as vmm.cfg.bak."""),), + # configure + 'configure': (_(u"""Starts the interactive configuration for all +configuration sections."""), +_(u"""In this process the currently set value of each option will be displayed +in square brackets. If no value is configured, the default value of each +option will be displayed in square brackets. Press the return key, to accept +the displayed value."""), +_(u"""If the optional argument <section> is given, only the configuration +options from the given section will be displayed and will be configurable. +The following sections are available: +"""), +""" account, bin, database, domain, mailbox, misc""", +_(u"""All configuration options are described in vmm.cfg(5)."""), +_(u"""Note: This subcommand will create a new vmm.cfg without any comments. +Your current configuration file will be backed as vmm.cfg.bak."""),), + # getuser + 'getuser': (_(u"""If only the <uid> is available, for example from process +list, the subcommand getuser will show the user's address."""),), + # listdomains + 'listdomains': (_(u"""This subcommand lists all available domains. All +domain names will be prefixed either with `[+]', if the domain is a primary +domain, or with `[-]', if it is an alias domain name. The output can be +limited with an optional <pattern>."""), +_(u"""To perform a wild card search, the % character can be used at the start +and/or the end of the <pattern>."""),), + # listpwschemes + 'listpwschemes': (_(u"""This subcommand lists all password schemes which +could be used in the vmm.cfg as value of the misc.password_scheme option. +The output varies, depending on the used Dovecot version and the system's +libc."""), +_(u"""When your Dovecot installation isn't too old, you will see additionally +a few usable encoding suffixes. One of them can be appended to the password +scheme."""),), + # version + 'version': (_(u"""Prints vmm's version and copyright information to stdout. +After this vmm exits."""),), + # domainadd + 'domainadd': (_(u"""Adds the new domain into the database and creates the +domain directory."""), +_(u"""If the optional argument <transport> is given, it will override the +default transport (domain.transport) from vmm.cfg. The specified <transport> +will be the default transport for all new accounts in this domain."""), +_(u"""Configuration-related behavior:"""), +u""" * domain.auto_postmaster""", +_(u"""When that option is set to true (default) vmm will automatically create +the postmaster account for the new domain and prompt for postmaster@<fqdn>'s +password."""), +u""" * account.random_password""", +_(u"""When the value of that option is also set to true, vmm will automatically +create the postmaster account for the new domain and print the generated +postmaster password to stdout."""),), + # domaindelete + 'domaindelete': (_(u"""This subcommand deletes the domain specified by +<fqdn>."""), +_(u"""If there are accounts, aliases and/or relocated users assigned to the +given domain, vmm will abort the requested operation and show an error +message. If you know, what you are doing, you can specify the optional keyword +'force'."""), +_(u"""If you really always know what you are doing, edit your vmm.cfg and set +the option domain.force_deletion to true."""),), + # domaininfo + 'domaininfo': (_(u"""This subcommand shows some information about the +given domain."""), +_(u"""For a more detailed information about the domain the optional argument +<details> can be specified. A possible <details> value can be one of the +following six keywords:"""), +""" accounts, aliasdomains, aliases, catchall, relocated, full""",), + # domainquota + 'domainquota': (_(u"""This subcommand is used to configure a new quota +limit for the accounts of the domain - not for the domain itself."""), +_(u"""The default quota limit for accounts is defined in the vmm.cfg +(domain.quota_bytes and domain.quota_messages)."""), +_(u"""The new quota limit will affect only those accounts for which the limit +has not been overridden. If you want to restore the default to all accounts, +you may pass the keyword 'force'. When the argument <messages> was omitted the +default number of messages 0 (zero) will be applied."""),), + # domainservices + 'domainservices': (_(u"""To define which services could be used by the +users of the domain — with the given <fqdn> — use this subcommand."""), +_(u"""Each specified <service> will be enabled/usable. All other services +will be deactivated/unusable. Possible <service> names are:"""), +u""" imap, pop3, sieve, smtp""", +_(u"""The new service set will affect only those accounts for which the set has +not been overridden. If you want to restore the default to all accounts, you +may pass the keyword 'force'."""),), + # domaintransport + 'domaintransport': (_(u"""A new transport for the indicated domain can be +set with this subcommand."""), +_(u"""The new transport will affect only those accounts for which the transport +has not been overridden. If you want to restore the default to all accounts, +you may pass the keyword 'force'."""),), + # domainnote + 'domainnote': (_(u"""With this subcommand, it is possible to attach a +note to the specified domain. Without an argument, an existing note is +removed."""),), + # aliasdomainadd + 'aliasdomainadd': (_(u"""This subcommand adds the new alias domain +(<fqdn>) to the destination <domain> that should be aliased."""),), + # aliasdomaindelete + 'aliasdomaindelete': (_(u"""Use this subcommand if the alias domain +<fqdn> should be removed."""),), + # aliasdomaininfo + 'aliasdomaininfo': (_(u"""This subcommand shows to which domain the alias +domain <fqdn> is assigned to."""),), + # aliasdomainswitch + 'aliasdomainswitch': (_(u"""If the destination of the existing alias +domain <fqdn> should be switched to another <destination> use this +subcommand."""),), + # useradd + 'useradd': (_(u"""Use this subcommand to create a new e-mail account for +the given <address>."""), +_(u"""If the <password> is not provided, vmm will prompt for it interactively. +When no <password> is provided and account.random_password is set to true, vmm +will generate a random password and print it to stdout after the account has +been created."""),), + # userdelete + 'userdelete': (_(u"""Use this subcommand to delete the account with the +given <address>."""), +_(u"""If there are one or more aliases with an identical destination address, +vmm will abort the requested operation and show an error message. To prevent +this, specify the optional keyword 'force'."""),), + # userinfo + 'userinfo': (_(u"""This subcommand displays some information about the +account specified by <address>."""), +_(u"""If the optional argument <details> is given some more information will be +displayed. Possible values for <details> are:"""), +u""" aliases, du. full""",), + # username + 'username': (_(u"""The user's real <name> can be set/updated with this +subcommand."""), +_(u"""If no <name> is given, the value stored for the account is erased."""), +), + # userpassword + 'userpassword': (_(u"""The password of an account can be updated with this +subcommand."""), +_(u"""If no <password> was provided, vmm will prompt for it interactively."""), +), + # usernote + 'usernote': (_(u"""With this subcommand, it is possible to attach a note +to the specified account. Without an argument, an existing note is +removed."""),), + # userquota + 'userquota': (_(u"""This subcommand is used to set a new quota limit for +the given account."""), +_(u"""When the argument <messages> was omitted the default number of messages +0 (zero) will be applied."""), +_(u"""Instead of <storage> pass the keyword 'domain' to remove the +account-specific override, causing the domain's value to be in effect."""),), + # userservices + 'userservices': (_(u"""To grant a user access to the specified services, +use this command."""), +_(u"""All omitted services will be deactivated/unusable for the user with the +given <address>."""), +_(u"""Instead of <service> pass 'domain' to remove the account-specific +override, causing the domain's value to be in effect."""),), + # usertransport + 'usertransport': (_(u"""A different <transport> for an account can be +specified with this subcommand."""), +_(u"""Instead of <transport> pass 'domain' to remove the account-specific +override, causing the domain's value to be in effect."""),), + # aliasadd + 'aliasadd': (_(u"""This subcommand is used to create a new alias +<address> with one or more <destination> addresses."""), +_(u"""Within the destination address, the placeholders '%n', '%d', and '%=' +will be replaced by the local part, the domain, or the email address with '@' +replaced by '=' respectively. In combination with alias domains, this enables +domain-specific destinations."""),), + # aliasinfo + 'aliasinfo': (_(u"""Information about the alias with the given <address> +can be displayed with this subcommand."""),), + # relocatedadd + 'relocatedadd': (_(u"""A new relocated user can be created with this +subcommand."""), +_(u"""<address> is the user's ex-email address, for example +b.user@example.com, and <newaddress> points to the new email address where +the user can be reached."""),), + # relocatedinfo + 'relocatedinfo': (_(u"""This subcommand shows the new address of the +relocated user with the given <address>."""),), + # relocateddelete + 'relocateddelete': (_(u"""Use this subcommand in order to delete the +relocated user with the given <address>."""),), + # catchalladd + 'catchalladd': (_(u"""This subcommand allows to specify destination +addresses for a domain, which shall receive mail addressed to unknown +local-parts within that domain. Those catch-all aliases hence "catch all" mail +to any address in the domain (unless a more specific alias, mailbox or +relocated entry exists)."""), +_(u"""WARNING: Catch-all addresses can cause mail server flooding because +spammers like to deliver mail to all possible combinations of names, e.g. +to all addresses between abba@example.org and zztop@example.org."""),), + # catchallinfo + 'catchallinfo': (_(u"""This subcommand displays information about catch-all +aliases defined for the domain <fqdn>."""),), + # catchalldelete + 'catchalldelete': (_(u"""With this subcommand, catch-all aliases defined +for a domain can be removed, either all of them, or a single one if specified +explicitly."""),), +} + +del _ diff -r b994444f7dee -r ab97727357a4 VirtualMailManager/cli/subcommands.py --- a/VirtualMailManager/cli/subcommands.py Sun Sep 02 20:18:16 2012 +0000 +++ b/VirtualMailManager/cli/subcommands.py Sun Sep 02 21:01:40 2012 +0000 @@ -16,6 +16,7 @@ from VirtualMailManager import ENCODING from VirtualMailManager.cli import get_winsize, prog, w_err, w_std +from VirtualMailManager.cli.clihelp import help_msgs from VirtualMailManager.common import human_size, size_in_bytes, \ version_str, format_domain_default from VirtualMailManager.constants import __copyright__, __date__, \ @@ -48,6 +49,10 @@ class Command(object): """Container class for command information.""" __slots__ = ('name', 'alias', 'func', 'args', 'descr') + FMT_HLP_USAGE = """ +usage: %(prog)s %(name)s %(args)s + %(prog)s %(alias)s %(args)s +""" def __init__(self, name, alias, func, args, descr): """Create a new Command instance. @@ -76,6 +81,26 @@ """the command's usage info.""" return u'%s %s %s' % (prog, self.name, self.args) + def help_(self): + """Print the Command's help message to stdout.""" + old_ii = txt_wrpr.initial_indent + old_si = txt_wrpr.subsequent_indent + + txt_wrpr.subsequent_indent = (len(self.name) + 2) * ' ' + w_std(txt_wrpr.fill('%s: %s' % (self.name, self.descr))) + + info = Command.FMT_HLP_USAGE % dict(alias=self.alias, args=self.args, + name=self.name, prog=prog) + w_std(info) + + txt_wrpr.initial_indent = txt_wrpr.subsequent_indent = ' ' + try: + [w_std(txt_wrpr.fill(_(para)) + '\n') for para + in help_msgs[self.name]] + except KeyError: + w_err(1, _(u"Subcommand '%s' is not yet documented." % self.name), + 'see also: vmm(1)') + class RunContext(object): """Contains all information necessary to run a subcommand.""" @@ -445,8 +470,8 @@ else: usage(INVALID_ARGUMENT, _(u"Unknown help topic: '%s'") % ctx.args[2], ctx.scmd) - # FIXME - w_err(1, "'help %s' not yet implemented." % topic, 'see also: vmm(1)') + if topic != u'help': + return cmd_map[topic].help_() old_ii = txt_wrpr.initial_indent old_si = txt_wrpr.subsequent_indent