mercurial/help.py
changeset 18746 c0087d48ec3a
parent 17837 b623e323c561
child 18748 6e676fb6ea44
equal deleted inserted replaced
18745:3c7c25fa58e0 18746:c0087d48ec3a
     4 #
     4 #
     5 # This software may be used and distributed according to the terms of the
     5 # This software may be used and distributed according to the terms of the
     6 # GNU General Public License version 2 or any later version.
     6 # GNU General Public License version 2 or any later version.
     7 
     7 
     8 from i18n import gettext, _
     8 from i18n import gettext, _
     9 import itertools, sys, os
     9 import itertools, sys, os, error
    10 import extensions, revset, fileset, templatekw, templatefilters, filemerge
    10 import extensions, revset, fileset, templatekw, templatefilters, filemerge
    11 import encoding, util, minirst
    11 import encoding, util, minirst
       
    12 import cmdutil
    12 
    13 
    13 def listexts(header, exts, indent=1):
    14 def listexts(header, exts, indent=1):
    14     '''return a text listing of the given extensions'''
    15     '''return a text listing of the given extensions'''
    15     rst = []
    16     rst = []
    16     if exts:
    17     if exts:
   204 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
   205 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
   205 addtopicsymbols('merge-tools', '.. internaltoolsmarker', filemerge.internals)
   206 addtopicsymbols('merge-tools', '.. internaltoolsmarker', filemerge.internals)
   206 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
   207 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
   207 addtopicsymbols('templates', '.. keywordsmarker', templatekw.dockeywords)
   208 addtopicsymbols('templates', '.. keywordsmarker', templatekw.dockeywords)
   208 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
   209 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
       
   210 
       
   211 def help_(ui, name, unknowncmd=False, full=True, **opts):
       
   212     '''
       
   213     Generate the help for 'name' as unformatted restructured text. If
       
   214     'name' is None, describe the commands available.
       
   215     '''
       
   216 
       
   217     import commands # avoid cycle
       
   218 
       
   219     def helpcmd(name):
       
   220         try:
       
   221             aliases, entry = cmdutil.findcmd(name, commands.table,
       
   222                                              strict=unknowncmd)
       
   223         except error.AmbiguousCommand, inst:
       
   224             # py3k fix: except vars can't be used outside the scope of the
       
   225             # except block, nor can be used inside a lambda. python issue4617
       
   226             prefix = inst.args[0]
       
   227             select = lambda c: c.lstrip('^').startswith(prefix)
       
   228             rst = helplist(select)
       
   229             return rst
       
   230 
       
   231         rst = []
       
   232 
       
   233         # check if it's an invalid alias and display its error if it is
       
   234         if getattr(entry[0], 'badalias', False):
       
   235             if not unknowncmd:
       
   236                 ui.pushbuffer()
       
   237                 entry[0](ui)
       
   238                 rst.append(ui.popbuffer())
       
   239             return rst
       
   240 
       
   241         # synopsis
       
   242         if len(entry) > 2:
       
   243             if entry[2].startswith('hg'):
       
   244                 rst.append("%s\n" % entry[2])
       
   245             else:
       
   246                 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
       
   247         else:
       
   248             rst.append('hg %s\n' % aliases[0])
       
   249         # aliases
       
   250         if full and not ui.quiet and len(aliases) > 1:
       
   251             rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
       
   252         rst.append('\n')
       
   253 
       
   254         # description
       
   255         doc = gettext(entry[0].__doc__)
       
   256         if not doc:
       
   257             doc = _("(no help text available)")
       
   258         if util.safehasattr(entry[0], 'definition'):  # aliased command
       
   259             if entry[0].definition.startswith('!'):  # shell alias
       
   260                 doc = _('shell alias for::\n\n    %s') % entry[0].definition[1:]
       
   261             else:
       
   262                 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
       
   263         doc = doc.splitlines(True)
       
   264         if ui.quiet or not full:
       
   265             rst.append(doc[0])
       
   266         else:
       
   267             rst.extend(doc)
       
   268         rst.append('\n')
       
   269 
       
   270         # check if this command shadows a non-trivial (multi-line)
       
   271         # extension help text
       
   272         try:
       
   273             mod = extensions.find(name)
       
   274             doc = gettext(mod.__doc__) or ''
       
   275             if '\n' in doc.strip():
       
   276                 msg = _('use "hg help -e %s" to show help for '
       
   277                         'the %s extension') % (name, name)
       
   278                 rst.append('\n%s\n' % msg)
       
   279         except KeyError:
       
   280             pass
       
   281 
       
   282         # options
       
   283         if not ui.quiet and entry[1]:
       
   284             rst.append('\n%s\n\n' % _("options:"))
       
   285             rst.append(optrst(entry[1], ui.verbose))
       
   286 
       
   287         if ui.verbose:
       
   288             rst.append('\n%s\n\n' % _("global options:"))
       
   289             rst.append(optrst(commands.globalopts, ui.verbose))
       
   290 
       
   291         if not ui.verbose:
       
   292             if not full:
       
   293                 rst.append(_('\nuse "hg help %s" to show the full help text\n')
       
   294                            % name)
       
   295             elif not ui.quiet:
       
   296                 omitted = _('use "hg -v help %s" to show more complete'
       
   297                             ' help and the global options') % name
       
   298                 notomitted = _('use "hg -v help %s" to show'
       
   299                                ' the global options') % name
       
   300                 indicateomitted(rst, omitted, notomitted)
       
   301 
       
   302         return rst
       
   303 
       
   304 
       
   305     def helplist(select=None):
       
   306         # list of commands
       
   307         if name == "shortlist":
       
   308             header = _('basic commands:\n\n')
       
   309         else:
       
   310             header = _('list of commands:\n\n')
       
   311 
       
   312         h = {}
       
   313         cmds = {}
       
   314         for c, e in commands.table.iteritems():
       
   315             f = c.split("|", 1)[0]
       
   316             if select and not select(f):
       
   317                 continue
       
   318             if (not select and name != 'shortlist' and
       
   319                 e[0].__module__ != commands.__name__):
       
   320                 continue
       
   321             if name == "shortlist" and not f.startswith("^"):
       
   322                 continue
       
   323             f = f.lstrip("^")
       
   324             if not ui.debugflag and f.startswith("debug"):
       
   325                 continue
       
   326             doc = e[0].__doc__
       
   327             if doc and 'DEPRECATED' in doc and not ui.verbose:
       
   328                 continue
       
   329             doc = gettext(doc)
       
   330             if not doc:
       
   331                 doc = _("(no help text available)")
       
   332             h[f] = doc.splitlines()[0].rstrip()
       
   333             cmds[f] = c.lstrip("^")
       
   334 
       
   335         rst = []
       
   336         if not h:
       
   337             if not ui.quiet:
       
   338                 rst.append(_('no commands defined\n'))
       
   339             return rst
       
   340 
       
   341         if not ui.quiet:
       
   342             rst.append(header)
       
   343         fns = sorted(h)
       
   344         for f in fns:
       
   345             if ui.verbose:
       
   346                 commacmds = cmds[f].replace("|",", ")
       
   347                 rst.append(" :%s: %s\n" % (commacmds, h[f]))
       
   348             else:
       
   349                 rst.append(' :%s: %s\n' % (f, h[f]))
       
   350 
       
   351         if not name:
       
   352             exts = listexts(_('enabled extensions:'), extensions.enabled())
       
   353             if exts:
       
   354                 rst.append('\n')
       
   355                 rst.extend(exts)
       
   356 
       
   357             rst.append(_("\nadditional help topics:\n\n"))
       
   358             topics = []
       
   359             for names, header, doc in helptable:
       
   360                 topics.append((names[0], header))
       
   361             for t, desc in topics:
       
   362                 rst.append(" :%s: %s\n" % (t, desc))
       
   363 
       
   364         optlist = []
       
   365         if not ui.quiet:
       
   366             if ui.verbose:
       
   367                 optlist.append((_("global options:"), commands.globalopts))
       
   368                 if name == 'shortlist':
       
   369                     optlist.append((_('use "hg help" for the full list '
       
   370                                            'of commands'), ()))
       
   371             else:
       
   372                 if name == 'shortlist':
       
   373                     msg = _('use "hg help" for the full list of commands '
       
   374                             'or "hg -v" for details')
       
   375                 elif name and not full:
       
   376                     msg = _('use "hg help %s" to show the full help '
       
   377                             'text') % name
       
   378                 else:
       
   379                     msg = _('use "hg -v help%s" to show builtin aliases and '
       
   380                             'global options') % (name and " " + name or "")
       
   381                 optlist.append((msg, ()))
       
   382 
       
   383         if optlist:
       
   384             for title, options in optlist:
       
   385                 rst.append('\n%s\n' % title)
       
   386                 if options:
       
   387                     rst.append('\n%s\n' % optrst(options, ui.verbose))
       
   388         return rst
       
   389 
       
   390     def helptopic(name):
       
   391         for names, header, doc in helptable:
       
   392             if name in names:
       
   393                 break
       
   394         else:
       
   395             raise error.UnknownCommand(name)
       
   396 
       
   397         rst = ["%s\n\n" % header]
       
   398         # description
       
   399         if not doc:
       
   400             rst.append("    %s\n" % _("(no help text available)"))
       
   401         if util.safehasattr(doc, '__call__'):
       
   402             rst += ["    %s\n" % l for l in doc().splitlines()]
       
   403 
       
   404         if not ui.verbose:
       
   405             omitted = (_('use "hg help -v %s" to show more complete help') %
       
   406                        name)
       
   407             indicateomitted(rst, omitted)
       
   408 
       
   409         try:
       
   410             cmdutil.findcmd(name, commands.table)
       
   411             rst.append(_('\nuse "hg help -c %s" to see help for '
       
   412                        'the %s command\n') % (name, name))
       
   413         except error.UnknownCommand:
       
   414             pass
       
   415         return rst
       
   416 
       
   417     def helpext(name):
       
   418         try:
       
   419             mod = extensions.find(name)
       
   420             doc = gettext(mod.__doc__) or _('no help text available')
       
   421         except KeyError:
       
   422             mod = None
       
   423             doc = extensions.disabledext(name)
       
   424             if not doc:
       
   425                 raise error.UnknownCommand(name)
       
   426 
       
   427         if '\n' not in doc:
       
   428             head, tail = doc, ""
       
   429         else:
       
   430             head, tail = doc.split('\n', 1)
       
   431         rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
       
   432         if tail:
       
   433             rst.extend(tail.splitlines(True))
       
   434             rst.append('\n')
       
   435 
       
   436         if not ui.verbose:
       
   437             omitted = (_('use "hg help -v %s" to show more complete help') %
       
   438                        name)
       
   439             indicateomitted(rst, omitted)
       
   440 
       
   441         if mod:
       
   442             try:
       
   443                 ct = mod.cmdtable
       
   444             except AttributeError:
       
   445                 ct = {}
       
   446             modcmds = set([c.split('|', 1)[0] for c in ct])
       
   447             rst.extend(helplist(modcmds.__contains__))
       
   448         else:
       
   449             rst.append(_('use "hg help extensions" for information on enabling '
       
   450                        'extensions\n'))
       
   451         return rst
       
   452 
       
   453     def helpextcmd(name):
       
   454         cmd, ext, mod = extensions.disabledcmd(ui, name,
       
   455                                                ui.configbool('ui', 'strict'))
       
   456         doc = gettext(mod.__doc__).splitlines()[0]
       
   457 
       
   458         rst = listexts(_("'%s' is provided by the following "
       
   459                               "extension:") % cmd, {ext: doc}, indent=4)
       
   460         rst.append('\n')
       
   461         rst.append(_('use "hg help extensions" for information on enabling '
       
   462                    'extensions\n'))
       
   463         return rst
       
   464 
       
   465 
       
   466     rst = []
       
   467     kw = opts.get('keyword')
       
   468     if kw:
       
   469         matches = topicmatch(kw)
       
   470         for t, title in (('topics', _('Topics')),
       
   471                          ('commands', _('Commands')),
       
   472                          ('extensions', _('Extensions')),
       
   473                          ('extensioncommands', _('Extension Commands'))):
       
   474             if matches[t]:
       
   475                 rst.append('%s:\n\n' % title)
       
   476                 rst.extend(minirst.maketable(sorted(matches[t]), 1))
       
   477                 rst.append('\n')
       
   478     elif name and name != 'shortlist':
       
   479         i = None
       
   480         if unknowncmd:
       
   481             queries = (helpextcmd,)
       
   482         elif opts.get('extension'):
       
   483             queries = (helpext,)
       
   484         elif opts.get('command'):
       
   485             queries = (helpcmd,)
       
   486         else:
       
   487             queries = (helptopic, helpcmd, helpext, helpextcmd)
       
   488         for f in queries:
       
   489             try:
       
   490                 rst = f(name)
       
   491                 i = None
       
   492                 break
       
   493             except error.UnknownCommand, inst:
       
   494                 i = inst
       
   495         if i:
       
   496             raise i
       
   497     else:
       
   498         # program name
       
   499         if not ui.quiet:
       
   500             rst = [_("Mercurial Distributed SCM\n"), '\n']
       
   501         rst.extend(helplist())
       
   502 
       
   503     return ''.join(rst)