##// END OF EJS Templates
templater: do dict lookup over a wrapped object...
templater: do dict lookup over a wrapped object Dict/list lookup operations will be moved to a wrapped interface so that a returned element can inherit hybrid-ness automatically. wraphybridvalue() will be inlined.

File last commit:

r38019:5fa4e29b default
r38258:c2456a77 default
Show More
help.py
690 lines | 24.4 KiB | text/x-python | PythonLexer
Matt Mackall
Add basic support for help topics and a dates topic
r3795 # help.py - help data for mercurial
#
# Copyright 2006 Matt Mackall <mpm@selenic.com>
#
Martin Geisler
updated license to be explicit about GPL version 2
r8225 # This software may be used and distributed according to the terms of the
Matt Mackall
Update license to GPLv2+
r10263 # GNU General Public License version 2 or any later version.
Matt Mackall
Add basic support for help topics and a dates topic
r3795
Gregory Szorc
help: use absolute_import
r27479 from __future__ import absolute_import
import itertools
import os
import textwrap
from .i18n import (
_,
gettext,
)
from . import (
cmdutil,
encoding,
error,
extensions,
Daniel Ploch
fancyopts: fix rendering of customopt defaults in help text...
r37109 fancyopts,
Gregory Szorc
help: use absolute_import
r27479 filemerge,
fileset,
minirst,
Pulkit Goyal
py3: make sure opts are passed and used correctly in help command...
r32143 pycompat,
Gregory Szorc
help: use absolute_import
r27479 revset,
templatefilters,
Yuya Nishihara
templater: split template functions to new module...
r36940 templatefuncs,
Gregory Szorc
help: use absolute_import
r27479 templatekw,
util,
)
from .hgweb import (
webcommands,
)
Cédric Duval
help: adding a new help topic about extensions...
r8863
Martin von Zweigbergk
cleanup: use set literals...
r32291 _exclkeywords = {
Jun Wu
help: hide command line options marked as "advanced"...
r31080 "(ADVANCED)",
Yuya Nishihara
help: include parens in DEPRECATED/EXPERIMENTAL keywords...
r26370 "(DEPRECATED)",
"(EXPERIMENTAL)",
Jun Wu
help: hide command line options marked as "advanced"...
r31080 # i18n: "(ADVANCED)" is a keyword, must be translated consistently
_("(ADVANCED)"),
Yuya Nishihara
help: include parens in DEPRECATED/EXPERIMENTAL keywords...
r26370 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently
_("(DEPRECATED)"),
# i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently
_("(EXPERIMENTAL)"),
Martin von Zweigbergk
cleanup: use set literals...
r32291 }
Yuya Nishihara
help: define list of keywords that should be excluded from non-verbose output...
r26369
Augie Fackler
help: exclude deprecated extensions in the disabled part of 'help extensions'
r20582 def listexts(header, exts, indent=1, showdeprecated=False):
Cédric Duval
help: more improvements for the extensions topic...
r8879 '''return a text listing of the given extensions'''
Olav Reinert
help: format extension lists using RST...
r16852 rst = []
if exts:
for name, desc in sorted(exts.iteritems()):
Yuya Nishihara
help: unify handling of DEPRECATED/EXPERIMENTAL keywords...
r26371 if not showdeprecated and any(w in desc for w in _exclkeywords):
Augie Fackler
help: exclude deprecated extensions in the disabled part of 'help extensions'
r20582 continue
Olav Reinert
help: format extension lists using RST...
r16852 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
timeless
help: make listexts less confusing for deprecated exts...
r27151 if rst:
rst.insert(0, '\n%s\n\n' % header)
Olav Reinert
help: format extension lists using RST...
r16852 return rst
Cédric Duval
help: refactor extensions listing, and show enabled ones in the dedicated topic
r8864
Yuya Nishihara
help: pass around ui to doc loader (API)...
r26413 def extshelp(ui):
rst = loaddoc('extensions')(ui).splitlines(True)
Augie Fackler
help: exclude deprecated extensions in the disabled part of 'help extensions'
r20582 rst.extend(listexts(
_('enabled extensions:'), extensions.enabled(), showdeprecated=True))
Yuya Nishihara
help: list deprecated and experimental extensions if --verbose...
r36263 rst.extend(listexts(_('disabled extensions:'), extensions.disabled(),
showdeprecated=ui.verbose))
Olav Reinert
help: format extension lists using RST...
r16852 doc = ''.join(rst)
Cédric Duval
help: adding a new help topic about extensions...
r8863 return doc
Martin Geisler
i18n: mark help strings for translation...
r7013
Matt Mackall
help: roll option list header into option formatter
r22116 def optrst(header, options, verbose):
Olav Reinert
help: move some helper functions to help.py
r16781 data = []
multioccur = False
for option in options:
if len(option) == 5:
shortopt, longopt, default, desc, optlabel = option
else:
shortopt, longopt, default, desc = option
optlabel = _("VALUE") # default label
Yuya Nishihara
help: define list of keywords that should be excluded from non-verbose output...
r26369 if not verbose and any(w in desc for w in _exclkeywords):
Olav Reinert
help: move some helper functions to help.py
r16781 continue
so = ''
if shortopt:
so = '-' + shortopt
lo = '--' + longopt
Daniel Ploch
fancyopts: fix rendering of customopt defaults in help text...
r37109
if isinstance(default, fancyopts.customopt):
Daniel Ploch
fancyopts: prevent mutation of the default value in customopts...
r37110 default = default.getdefaultvalue()
Daniel Ploch
fancyopts: fix rendering of customopt defaults in help text...
r37109 if default and not callable(default):
Augie Fackler
help: convert flag default to bytes portably...
r32619 # default is of unknown type, and in Python 2 we abused
# the %s-shows-repr property to handle integers etc. To
# match that behavior on Python 3, we do str(default) and
# then convert it to bytes.
desc += _(" (default: %s)") % pycompat.bytestr(default)
Olav Reinert
help: move some helper functions to help.py
r16781
if isinstance(default, list):
lo += " %s [+]" % optlabel
multioccur = True
elif (default is not None) and not isinstance(default, bool):
lo += " %s" % optlabel
data.append((so, lo, desc))
Matt Mackall
help: fold repeatable option message into option table header...
r22117 if multioccur:
header += (_(" ([+] can be repeated)"))
Olav Reinert
help: move some helper functions to help.py
r16781
Matt Mackall
help: roll option list header into option formatter
r22116 rst = ['\n%s:\n\n' % header]
rst.extend(minirst.maketable(data, 1))
Olav Reinert
help: move some helper functions to help.py
r16781
Olav Reinert
minirst: generate tables as a list of joined lines
r16815 return ''.join(rst)
Olav Reinert
help: move some helper functions to help.py
r16781
FUJIWARA Katsunori
help: indicate help omitting if help document is not fully displayed...
r17837 def indicateomitted(rst, omitted, notomitted=None):
rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
if notomitted:
rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
timeless
help: refactor filtercmd
r27323 def filtercmd(ui, cmd, kw, doc):
if not ui.debugflag and cmd.startswith("debug") and kw != "debug":
return True
if not ui.verbose and doc and any(w in doc for w in _exclkeywords):
return True
return False
Yuya Nishihara
help: pass commands module by argument...
r32567 def topicmatch(ui, commands, kw):
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 """Return help topics matching kw.
Returns {'section': [(name, summary), ...], ...} where section is
one of topics, commands, extensions, or extensioncommands.
"""
kw = encoding.lower(kw)
def lowercontains(container):
Nikolaj Sjujskij
help: fix search with `-k` option in non-ASCII locales...
r16845 return kw in encoding.lower(container) # translated in helptable
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 results = {'topics': [],
'commands': [],
'extensions': [],
'extensioncommands': [],
}
for names, header, doc in helptable:
Gregory Szorc
help: only call doc() when it is callable...
r22322 # Old extensions may use a str as doc.
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 if (sum(map(lowercontains, names))
or lowercontains(header)
Yuya Nishihara
help: pass around ui to doc loader (API)...
r26413 or (callable(doc) and lowercontains(doc(ui)))):
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 results['topics'].append((names[0], header))
for cmd, entry in commands.table.iteritems():
if len(entry) == 3:
summary = entry[2]
else:
summary = ''
Nikolaj Sjujskij
help: fix search with `-k` option in non-ASCII locales...
r16845 # translate docs *before* searching there
Yuya Nishihara
py3: convert __doc__ back to bytes in help.py...
r32615 docs = _(pycompat.getdoc(entry[0])) or ''
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 if kw in cmd or lowercontains(summary) or lowercontains(docs):
Nikolaj Sjujskij
help: fix search with `-k` option in non-ASCII locales...
r16845 doclines = docs.splitlines()
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 if doclines:
summary = doclines[0]
Yuya Nishihara
help: use cmdutil.parsealiases() to resolve command name...
r36264 cmdname = cmdutil.parsealiases(cmd)[0]
timeless
help: call filtercmd from topicmatch...
r27324 if filtercmd(ui, cmdname, kw, docs):
continue
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 results['commands'].append((cmdname, summary))
for name, docs in itertools.chain(
FUJIWARA Katsunori
help: use full name of extensions to look up them for keyword search...
r19769 extensions.enabled(False).iteritems(),
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 extensions.disabled().iteritems()):
Simon Farnsworth
help: don't crash in keyword search if an extension fails to provide docs...
r28058 if not docs:
continue
av6
help: replace some str.split() calls by str.partition() or str.rpartition()...
r26845 name = name.rpartition('.')[-1]
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 if lowercontains(name) or lowercontains(docs):
Nikolaj Sjujskij
help: fix search with `-k` option in non-ASCII locales...
r16845 # extension docs are already translated
results['extensions'].append((name, docs.splitlines()[0]))
Yuya Nishihara
help: do not abort topicmatch() because of unimportable extensions...
r34913 try:
mod = extensions.load(ui, name, '')
except ImportError:
# debug message would be printed in extensions.load()
continue
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
Augie Fackler
help: add --keyword (-k) for searching help
r16711 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
Yuya Nishihara
help: use cmdutil.parsealiases() to resolve command name...
r36264 cmdname = cmdutil.parsealiases(cmd)[0]
Yuya Nishihara
py3: convert __doc__ back to bytes in help.py...
r32615 cmddoc = pycompat.getdoc(entry[0])
if cmddoc:
cmddoc = gettext(cmddoc).splitlines()[0]
Thomas Arendsen Hein
help: fix 'hg help -k' matching an extension without docs...
r16884 else:
cmddoc = _('(no help text available)')
timeless
help: filter extension commands
r27387 if filtercmd(ui, cmdname, kw, cmddoc):
continue
Thomas Arendsen Hein
help: fix 'hg help -k' matching an extension without docs...
r16884 results['extensioncommands'].append((cmdname, cmddoc))
Augie Fackler
help: introduce topicmatch for finding topics matching a keyword
r16710 return results
Gregory Szorc
help: teach loaddoc to load from a different directory...
r27375 def loaddoc(topic, subdir=None):
Martin Geisler
help: move help topics from mercurial/help.py to help/*.txt...
r9539 """Return a delayed loader for help/topic.txt."""
Matt Mackall
move environment topic
r3798
Yuya Nishihara
help: pass around ui to doc loader (API)...
r26413 def loader(ui):
Mads Kiilerich
help: don't search randomly for help data - trust util.datapath...
r22637 docdir = os.path.join(util.datapath, 'help')
Gregory Szorc
help: teach loaddoc to load from a different directory...
r27375 if subdir:
docdir = os.path.join(docdir, subdir)
Martin Geisler
help: move help topics from mercurial/help.py to help/*.txt...
r9539 path = os.path.join(docdir, topic + ".txt")
Dan Villiom Podlaski Christiansen
prevent transient leaks of file handle by using new helper functions...
r14168 doc = gettext(util.readfile(path))
Patrick Mezard
help: add topic rewriting hooks...
r12820 for rewriter in helphooks.get(topic, []):
Yuya Nishihara
help: pass around ui to rewriter hooks (API)...
r26414 doc = rewriter(ui, topic, doc)
Patrick Mezard
help: add topic rewriting hooks...
r12820 return doc
Martin Geisler
help: move help topics from mercurial/help.py to help/*.txt...
r9539 return loader
Alexander Solovyov
help: add a topic about some of the templating features
r7677
Gregory Szorc
help: add "internals" topic...
r27376 internalstable = sorted([
Gregory Szorc
internals: document bundle2 format...
r36469 (['bundle2'], _('Bundle2'),
loaddoc('bundle2', subdir='internals')),
Gregory Szorc
help: don't try to render a section on sub-topics...
r29747 (['bundles'], _('Bundles'),
Gregory Szorc
help: add "internals" topic...
r27376 loaddoc('bundles', subdir='internals')),
Augie Fackler
help: update help.internalstable for new censor docs
r31293 (['censor'], _('Censor'),
loaddoc('censor', subdir='internals')),
Gregory Szorc
help: don't try to render a section on sub-topics...
r29747 (['changegroups'], _('Changegroups'),
Gregory Szorc
help: add "internals" topic...
r27376 loaddoc('changegroups', subdir='internals')),
Kevin Bullock
internals: copy-edit "register" -> "registrar" in configitem docs
r34952 (['config'], _('Config Registrar'),
Boris Feld
internal-doc: document the config register mechanism...
r34933 loaddoc('config', subdir='internals')),
Gregory Szorc
help: don't try to render a section on sub-topics...
r29747 (['requirements'], _('Repository Requirements'),
Gregory Szorc
help: document requirements...
r28523 loaddoc('requirements', subdir='internals')),
Gregory Szorc
help: don't try to render a section on sub-topics...
r29747 (['revlogs'], _('Revision Logs'),
Gregory Szorc
internals: document revlog format...
r27631 loaddoc('revlogs', subdir='internals')),
Gregory Szorc
help: internals topic for wire protocol...
r29859 (['wireprotocol'], _('Wire Protocol'),
loaddoc('wireprotocol', subdir='internals')),
Gregory Szorc
help: add "internals" topic...
r27376 ])
def internalshelp(ui):
"""Generate the index for the "internals" topic."""
Matt DeVore
help: explain how to access subtopics in internals
r32076 lines = ['To access a subtopic, use "hg help internals.{subtopic-name}"\n',
'\n']
Gregory Szorc
help: add "internals" topic...
r27376 for names, header, doc in internalstable:
Yuya Nishihara
help: add missed last new line to "internals" topic...
r27400 lines.append(' :%s: %s\n' % (names[0], header))
Gregory Szorc
help: add "internals" topic...
r27376
Yuya Nishihara
help: add missed last new line to "internals" topic...
r27400 return ''.join(lines)
Gregory Szorc
help: add "internals" topic...
r27376
Yun Lee
help: sort help topics to make the output more readable (issue2751)
r13888 helptable = sorted([
Gregory Szorc
help: document bundle specifications...
r31793 (['bundlespec'], _("Bundle File Formats"), loaddoc('bundlespec')),
Pierre-Yves David
color: update the help table...
r31129 (['color'], _("Colorizing Outputs"), loaddoc('color')),
Martin Geisler
help: make "hg help hgrc" an alias for "hg help config"
r12145 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
David Demelier
help: add new deprecated topic...
r38019 (['deprecated'], _("Deprecated Features"), loaddoc('deprecated')),
Martin Geisler
help: move help topics from mercurial/help.py to help/*.txt...
r9539 (["dates"], _("Date Formats"), loaddoc('dates')),
Rodrigo Damazio Bovendorp
help: adding a topic on flags...
r35036 (["flags"], _("Command-line flags"), loaddoc('flags')),
Martin Geisler
help: move help topics from mercurial/help.py to help/*.txt...
r9539 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
Matt Mackall
many, many trivial check-code fixups
r10282 (['environment', 'env'], _('Environment Variables'),
loaddoc('environment')),
Martin von Zweigbergk
help: merge revsets.txt into revisions.txt...
r30769 (['revisions', 'revs', 'revsets', 'revset', 'multirevs', 'mrevs'],
_('Specifying Revisions'), loaddoc('revisions')),
Mads Kiilerich
help: use the first topic name from helptable, not the longest alias...
r17322 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
Martin Geisler
help: move help topics from mercurial/help.py to help/*.txt...
r9539 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
Gregory Szorc
help: make "mergetool" an alias for "merge-tools"...
r30812 (['merge-tools', 'mergetools', 'mergetool'], _('Merge Tools'),
loaddoc('merge-tools')),
A. S. Budden
help: add reference to template help (issue3413)...
r16568 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
Matt Mackall
many, many trivial check-code fixups
r10282 loaddoc('templates')),
Martin Geisler
help: move help topics from mercurial/help.py to help/*.txt...
r9539 (['urls'], _('URL Paths'), loaddoc('urls')),
Martin Geisler
help: consistently use title capitalization for help topics
r16547 (["extensions"], _("Using Additional Features"), extshelp),
Mads Kiilerich
help: use the first topic name from helptable, not the longest alias...
r17322 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
Mads Kiilerich
help: fix helptable indentation
r17321 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
(["glossary"], _("Glossary"), loaddoc('glossary')),
(["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
loaddoc('hgignore')),
(["phases"], _("Working with Phases"), loaddoc('phases')),
Gregory Szorc
help: scripting help topic...
r25881 (['scripting'], _('Using Mercurial from scripts and automation'),
loaddoc('scripting')),
Gregory Szorc
help: add "internals" topic...
r27376 (['internals'], _("Technical implementation topics"),
internalshelp),
Augie Fackler
pager: move most help to a new help topic and deprecate extension
r31061 (['pager'], _("Pager Support"), loaddoc('pager')),
Yun Lee
help: sort help topics to make the output more readable (issue2751)
r13888 ])
Patrick Mezard
help: add topic rewriting hooks...
r12820
Gregory Szorc
help: support loading sub-topics...
r27379 # Maps topics with sub-topics to a list of their sub-topics.
subtopics = {
'internals': internalstable,
}
Patrick Mezard
help: add topic rewriting hooks...
r12820 # Map topics to lists of callable taking the current topic help and
# returning the updated version
Matt Mackall
help: consolidate topic hooks in help.py...
r14318 helphooks = {}
Patrick Mezard
help: add topic rewriting hooks...
r12820
def addtopichook(topic, rewriter):
helphooks.setdefault(topic, []).append(rewriter)
Patrick Mezard
help: extract items doc generation function
r13593
Yuya Nishihara
help: pass around ui to rewriter hooks (API)...
r26414 def makeitemsdoc(ui, topic, doc, marker, items, dedent=False):
Patrick Mezard
help: extract items doc generation function
r13593 """Extract docstring from the items key to function mapping, build a
timeless@mozdev.org
help: fix makeitemsdoc English description
r26196 single documentation block and use it to overwrite the marker in doc.
Patrick Mezard
help: extract items doc generation function
r13593 """
entries = []
for name in sorted(items):
Yuya Nishihara
py3: convert __doc__ back to bytes in help.py...
r32615 text = (pycompat.getdoc(items[name]) or '').rstrip()
Yuya Nishihara
help: hide deprecated filesets, revsets and template items if not verbose...
r26415 if (not text
or not ui.verbose and any(w in text for w in _exclkeywords)):
Patrick Mezard
help: extract items doc generation function
r13593 continue
text = gettext(text)
Gregory Szorc
help: teach topic symbols how to dedent...
r24098 if dedent:
Augie Fackler
help: work around textwrap.dedent() only working on strings
r32549 # Abuse latin1 to use textwrap.dedent() on bytes.
text = textwrap.dedent(text.decode('latin1')).encode('latin1')
Patrick Mezard
help: extract items doc generation function
r13593 lines = text.splitlines()
"Yann E. MORIN"
help: strip doctest from dochelp...
r16250 doclines = [(lines[0])]
for l in lines[1:]:
# Stop once we find some Python doctest
if l.strip().startswith('>>>'):
break
Gregory Szorc
help: teach topic symbols how to dedent...
r24098 if dedent:
doclines.append(l.rstrip())
else:
doclines.append(' ' + l.strip())
"Yann E. MORIN"
help: strip doctest from dochelp...
r16250 entries.append('\n'.join(doclines))
Patrick Mezard
help: extract items doc generation function
r13593 entries = '\n\n'.join(entries)
return doc.replace(marker, entries)
Matt Mackall
help: consolidate topic hooks in help.py...
r14318
Gregory Szorc
help: teach topic symbols how to dedent...
r24098 def addtopicsymbols(topic, marker, symbols, dedent=False):
Yuya Nishihara
help: pass around ui to rewriter hooks (API)...
r26414 def add(ui, topic, doc):
return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent)
Matt Mackall
help: consolidate topic hooks in help.py...
r14318 addtopichook(topic, add)
Gregory Szorc
help: document bundle specifications...
r31793 addtopicsymbols('bundlespec', '.. bundlecompressionmarker',
util.bundlecompressiontopics())
Matt Mackall
fileset: add a help topic...
r14686 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
Gregory Szorc
help.merge-tools: do not double document merge tools...
r24099 addtopicsymbols('merge-tools', '.. internaltoolsmarker',
filemerge.internalsdoc)
Martin von Zweigbergk
help: merge revsets.txt into revisions.txt...
r30769 addtopicsymbols('revisions', '.. predicatesmarker', revset.symbols)
Yuya Nishihara
templatekw: remove dockeywords hack...
r26436 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
Matt Mackall
help: consolidate topic hooks in help.py...
r14318 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
Yuya Nishihara
templater: split template functions to new module...
r36940 addtopicsymbols('templates', '.. functionsmarker', templatefuncs.funcs)
Gregory Szorc
help: teach topic symbols how to dedent...
r24098 addtopicsymbols('hgweb', '.. webcommandsmarker', webcommands.commands,
dedent=True)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
Yuya Nishihara
help: pass commands module by argument...
r32567 def help_(ui, commands, name, unknowncmd=False, full=True, subtopic=None,
**opts):
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 '''
Generate the help for 'name' as unformatted restructured text. If
'name' is None, describe the commands available.
'''
Pulkit Goyal
py3: make sure opts are passed and used correctly in help command...
r32143 opts = pycompat.byteskwargs(opts)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
Gregory Szorc
help: pass sub-topic into help query functions...
r27378 def helpcmd(name, subtopic=None):
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 try:
aliases, entry = cmdutil.findcmd(name, commands.table,
strict=unknowncmd)
Gregory Szorc
global: mass rewrite to use modern exception syntax...
r25660 except error.AmbiguousCommand as inst:
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 # py3k fix: except vars can't be used outside the scope of the
# except block, nor can be used inside a lambda. python issue4617
prefix = inst.args[0]
Yuya Nishihara
help: use cmdutil.parsealiases() to resolve command name...
r36264 select = lambda c: cmdutil.parsealiases(c)[0].startswith(prefix)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 rst = helplist(select)
return rst
rst = []
# check if it's an invalid alias and display its error if it is
Yuya Nishihara
alias: keep error message in "badalias" so that help can see it...
r22160 if getattr(entry[0], 'badalias', None):
Yuya Nishihara
help: provide help of bad alias without executing aliascmd()...
r22162 rst.append(entry[0].badalias + '\n')
if entry[0].unknowncmd:
try:
rst.extend(helpextcmd(entry[0].cmdname))
except error.UnknownCommand:
pass
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 return rst
# synopsis
if len(entry) > 2:
if entry[2].startswith('hg'):
rst.append("%s\n" % entry[2])
else:
rst.append('hg %s %s\n' % (aliases[0], entry[2]))
else:
rst.append('hg %s\n' % aliases[0])
# aliases
if full and not ui.quiet and len(aliases) > 1:
rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
rst.append('\n')
# description
Yuya Nishihara
py3: convert __doc__ back to bytes in help.py...
r32615 doc = gettext(pycompat.getdoc(entry[0]))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 if not doc:
doc = _("(no help text available)")
if util.safehasattr(entry[0], 'definition'): # aliased command
timeless
help: report source of aliases
r28828 source = entry[0].source
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 if entry[0].definition.startswith('!'): # shell alias
Rodrigo Damazio
help: supporting both help and doc for aliases...
r37152 doc = (_('shell alias for: %s\n\n%s\n\ndefined by: %s\n') %
(entry[0].definition[1:], doc, source))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 else:
timeless
help: report source of aliases
r28828 doc = (_('alias for: hg %s\n\n%s\n\ndefined by: %s\n') %
(entry[0].definition, doc, source))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 doc = doc.splitlines(True)
if ui.quiet or not full:
rst.append(doc[0])
else:
rst.extend(doc)
rst.append('\n')
# check if this command shadows a non-trivial (multi-line)
# extension help text
try:
mod = extensions.find(name)
Yuya Nishihara
py3: convert __doc__ back to bytes in help.py...
r32615 doc = gettext(pycompat.getdoc(mod)) or ''
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 if '\n' in doc.strip():
timeless
help: use single quotes in use warning
r29974 msg = _("(use 'hg help -e %s' to show help for "
"the %s extension)") % (name, name)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 rst.append('\n%s\n' % msg)
except KeyError:
pass
# options
if not ui.quiet and entry[1]:
Matt Mackall
help: roll option list header into option formatter
r22116 rst.append(optrst(_("options"), entry[1], ui.verbose))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
if ui.verbose:
Matt Mackall
help: roll option list header into option formatter
r22116 rst.append(optrst(_("global options"),
commands.globalopts, ui.verbose))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
if not ui.verbose:
if not full:
timeless
help: use single quotes in use warning
r29974 rst.append(_("\n(use 'hg %s -h' to show more help)\n")
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 % name)
elif not ui.quiet:
Matt Mackall
help: tweak --verbose command help hint...
r22110 rst.append(_('\n(some details hidden, use --verbose '
'to show complete help)'))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
return rst
timeless
help: fix help -c/help -e/help -k...
r27325 def helplist(select=None, **opts):
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 # list of commands
if name == "shortlist":
header = _('basic commands:\n\n')
Mads Kiilerich
help: let 'hg help debug' show the list of secret debug commands...
r20822 elif name == "debug":
header = _('debug commands (internal and unsupported):\n\n')
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 else:
header = _('list of commands:\n\n')
h = {}
cmds = {}
for c, e in commands.table.iteritems():
Yuya Nishihara
help: use cmdutil.parsealiases() to resolve command name...
r36264 fs = cmdutil.parsealiases(c)
f = fs[0]
p = ''
if c.startswith("^"):
p = '^'
if select and not select(p + f):
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 continue
if (not select and name != 'shortlist' and
e[0].__module__ != commands.__name__):
continue
Yuya Nishihara
help: use cmdutil.parsealiases() to resolve command name...
r36264 if name == "shortlist" and not p:
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 continue
Yuya Nishihara
py3: convert __doc__ back to bytes in help.py...
r32615 doc = pycompat.getdoc(e[0])
timeless
help: refactor filtercmd
r27323 if filtercmd(ui, f, name, doc):
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 continue
doc = gettext(doc)
if not doc:
doc = _("(no help text available)")
h[f] = doc.splitlines()[0].rstrip()
Yuya Nishihara
help: use cmdutil.parsealiases() to resolve command name...
r36264 cmds[f] = '|'.join(fs)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
rst = []
if not h:
if not ui.quiet:
rst.append(_('no commands defined\n'))
return rst
if not ui.quiet:
rst.append(header)
fns = sorted(h)
for f in fns:
if ui.verbose:
commacmds = cmds[f].replace("|",", ")
rst.append(" :%s: %s\n" % (commacmds, h[f]))
else:
rst.append(' :%s: %s\n' % (f, h[f]))
timeless
help: fix help -c/help -e/help -k...
r27325 ex = opts.get
Pulkit Goyal
py3: handle keyword arguments correctly in help.py...
r35357 anyopts = (ex(r'keyword') or not (ex(r'command') or ex(r'extension')))
timeless
help: fix help -c/help -e/help -k...
r27325 if not name and anyopts:
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 exts = listexts(_('enabled extensions:'), extensions.enabled())
if exts:
rst.append('\n')
rst.extend(exts)
rst.append(_("\nadditional help topics:\n\n"))
topics = []
for names, header, doc in helptable:
topics.append((names[0], header))
for t, desc in topics:
rst.append(" :%s: %s\n" % (t, desc))
Matt Mackall
help: refactor helplist optlist mess...
r22115 if ui.quiet:
pass
elif ui.verbose:
Matt Mackall
help: roll option list header into option formatter
r22116 rst.append('\n%s\n' % optrst(_("global options"),
commands.globalopts, ui.verbose))
Matt Mackall
help: refactor helplist optlist mess...
r22115 if name == 'shortlist':
timeless
help: use single quotes in use warning
r29974 rst.append(_("\n(use 'hg help' for the full list "
"of commands)\n"))
Matt Mackall
help: refactor helplist optlist mess...
r22115 else:
if name == 'shortlist':
timeless
help: use single quotes in use warning
r29974 rst.append(_("\n(use 'hg help' for the full list of commands "
"or 'hg -v' for details)\n"))
Matt Mackall
help: refactor helplist optlist mess...
r22115 elif name and not full:
timeless
help: use single quotes in use warning
r29974 rst.append(_("\n(use 'hg help %s' to show the full help "
"text)\n") % name)
Chingis Dugarzhapov
help: suggest '-v -e' to get built-in aliases for extensions (issue4461)...
r23624 elif name and cmds and name in cmds.keys():
timeless
help: use single quotes in use warning
r29974 rst.append(_("\n(use 'hg help -v -e %s' to show built-in "
"aliases and global options)\n") % name)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 else:
timeless
help: use single quotes in use warning
r29974 rst.append(_("\n(use 'hg help -v%s' to show built-in aliases "
"and global options)\n")
Matt Mackall
help: normalize helplist hints
r22118 % (name and " " + name or ""))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 return rst
Gregory Szorc
help: pass sub-topic into help query functions...
r27378 def helptopic(name, subtopic=None):
Gregory Szorc
help: support loading sub-topics...
r27379 # Look for sub-topic entry first.
header, doc = None, None
if subtopic and name in subtopics:
for names, header, doc in subtopics[name]:
if subtopic in names:
break
if not header:
for names, header, doc in helptable:
if name in names:
break
else:
raise error.UnknownCommand(name)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
Dan Villiom Podlaski Christiansen
help: use a full header for topic titles...
r18748 rst = [minirst.section(header)]
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 # description
if not doc:
rst.append(" %s\n" % _("(no help text available)"))
Augie Fackler
help: restore use of callable() since it was readded in Python 3.2
r21796 if callable(doc):
Yuya Nishihara
help: pass around ui to doc loader (API)...
r26413 rst += [" %s\n" % l for l in doc(ui).splitlines()]
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
if not ui.verbose:
Matt Mackall
help: normalize topic and extension verbose hints
r22114 omitted = _('(some details hidden, use --verbose'
' to show complete help)')
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 indicateomitted(rst, omitted)
try:
cmdutil.findcmd(name, commands.table)
timeless
help: use single quotes in use warning
r29974 rst.append(_("\nuse 'hg help -c %s' to see help for "
"the %s command\n") % (name, name))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 except error.UnknownCommand:
pass
return rst
Gregory Szorc
help: pass sub-topic into help query functions...
r27378 def helpext(name, subtopic=None):
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 try:
mod = extensions.find(name)
Yuya Nishihara
py3: convert __doc__ back to bytes in help.py...
r32615 doc = gettext(pycompat.getdoc(mod)) or _('no help text available')
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 except KeyError:
mod = None
doc = extensions.disabledext(name)
if not doc:
raise error.UnknownCommand(name)
if '\n' not in doc:
head, tail = doc, ""
else:
head, tail = doc.split('\n', 1)
av6
help: replace some str.split() calls by str.partition() or str.rpartition()...
r26845 rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 if tail:
rst.extend(tail.splitlines(True))
rst.append('\n')
if not ui.verbose:
Matt Mackall
help: normalize topic and extension verbose hints
r22114 omitted = _('(some details hidden, use --verbose'
' to show complete help)')
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 indicateomitted(rst, omitted)
if mod:
try:
ct = mod.cmdtable
except AttributeError:
ct = {}
av6
help: replace some str.split() calls by str.partition() or str.rpartition()...
r26845 modcmds = set([c.partition('|')[0] for c in ct])
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 rst.extend(helplist(modcmds.__contains__))
else:
timeless
help: use single quotes in use warning
r29974 rst.append(_("(use 'hg help extensions' for information on enabling"
" extensions)\n"))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 return rst
Gregory Szorc
help: pass sub-topic into help query functions...
r27378 def helpextcmd(name, subtopic=None):
Yuya Nishihara
help: load module doc of disabled extension in extensions.disabledcmd()...
r37996 cmd, ext, doc = extensions.disabledcmd(ui, name,
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 ui.configbool('ui', 'strict'))
Yuya Nishihara
help: load module doc of disabled extension in extensions.disabledcmd()...
r37996 doc = doc.splitlines()[0]
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
rst = listexts(_("'%s' is provided by the following "
timeless
help: make help deprecated mention the extension...
r27152 "extension:") % cmd, {ext: doc}, indent=4,
showdeprecated=True)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 rst.append('\n')
timeless
help: use single quotes in use warning
r29974 rst.append(_("(use 'hg help extensions' for information on enabling "
"extensions)\n"))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 return rst
rst = []
kw = opts.get('keyword')
timeless
help: fix help -c/help -e/help -k...
r27325 if kw or name is None and any(opts[o] for o in opts):
Yuya Nishihara
help: pass commands module by argument...
r32567 matches = topicmatch(ui, commands, name or '')
timeless@mozdev.org
help: fix help argument parsing and documentation...
r26238 helpareas = []
if opts.get('extension'):
helpareas += [('extensions', _('Extensions'))]
if opts.get('command'):
helpareas += [('commands', _('Commands'))]
if not helpareas:
helpareas = [('topics', _('Topics')),
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 ('commands', _('Commands')),
('extensions', _('Extensions')),
timeless@mozdev.org
help: fix help argument parsing and documentation...
r26238 ('extensioncommands', _('Extension Commands'))]
for t, title in helpareas:
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 if matches[t]:
rst.append('%s:\n\n' % title)
rst.extend(minirst.maketable(sorted(matches[t]), 1))
rst.append('\n')
Pierre-Yves David
help: provide a more helpful message when no keyword are matched...
r21288 if not rst:
msg = _('no matches')
timeless
help: use single quotes in use warning
r29974 hint = _("try 'hg help' for a list of topics")
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg, hint=hint)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 elif name and name != 'shortlist':
timeless@mozdev.org
help: fix help argument parsing and documentation...
r26238 queries = []
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 if unknowncmd:
timeless@mozdev.org
help: fix help argument parsing and documentation...
r26238 queries += [helpextcmd]
if opts.get('extension'):
queries += [helpext]
if opts.get('command'):
queries += [helpcmd]
if not queries:
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 queries = (helptopic, helpcmd, helpext, helpextcmd)
for f in queries:
try:
Gregory Szorc
help: pass sub-topic into help query functions...
r27378 rst = f(name, subtopic)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 break
Pierre-Yves David
help: suggest keyword search when no topic is found...
r21289 except error.UnknownCommand:
pass
else:
if unknowncmd:
raise error.UnknownCommand(name)
else:
msg = _('no such help topic: %s') % name
timeless
help: use single quotes in use warning
r29974 hint = _("try 'hg help --keyword %s'") % name
Pierre-Yves David
error: get Abort from 'error' instead of 'util'...
r26587 raise error.Abort(msg, hint=hint)
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746 else:
# program name
if not ui.quiet:
rst = [_("Mercurial Distributed SCM\n"), '\n']
Augie Fackler
help: convert dict to strkwargs
r32547 rst.extend(helplist(None, **pycompat.strkwargs(opts)))
Dan Villiom Podlaski Christiansen
help: move the majority of the help command to the help module...
r18746
return ''.join(rst)
Augie Fackler
help: move rst formatting of help documents into help.py...
r31059
Yuya Nishihara
help: pass commands module by argument...
r32567 def formattedhelp(ui, commands, name, keep=None, unknowncmd=False, full=True,
**opts):
Augie Fackler
help: move rst formatting of help documents into help.py...
r31059 """get help for a given topic (as a dotted name) as rendered rst
Either returns the rendered help text or raises an exception.
"""
if keep is None:
keep = []
Augie Fackler
help: avoid mutating passed-in `keep` list in `formattedhelp`
r31265 else:
keep = list(keep) # make a copy so we can mutate this later
Augie Fackler
help: move rst formatting of help documents into help.py...
r31059 fullname = name
section = None
subtopic = None
if name and '.' in name:
name, remaining = name.split('.', 1)
remaining = encoding.lower(remaining)
if '.' in remaining:
subtopic, section = remaining.split('.', 1)
else:
if name in subtopics:
subtopic = remaining
else:
section = remaining
Jun Wu
codemod: register core configitems using a script...
r33499 textwidth = ui.configint('ui', 'textwidth')
Augie Fackler
help: move rst formatting of help documents into help.py...
r31059 termwidth = ui.termwidth() - 2
if textwidth <= 0 or termwidth < textwidth:
textwidth = termwidth
Yuya Nishihara
help: pass commands module by argument...
r32567 text = help_(ui, commands, name,
Augie Fackler
help: move rst formatting of help documents into help.py...
r31059 subtopic=subtopic, unknowncmd=unknowncmd, full=full, **opts)
formatted, pruned = minirst.format(text, textwidth, keep=keep,
section=section)
# We could have been given a weird ".foo" section without a name
# to look for, or we could have simply failed to found "foo.bar"
# because bar isn't a section of foo
if section and not (formatted and name):
raise error.Abort(_("help section not found: %s") % fullname)
if 'verbose' in pruned:
keep.append('omitted')
else:
keep.append('notomitted')
formatted, pruned = minirst.format(text, textwidth, keep=keep,
section=section)
return formatted