##// END OF EJS Templates
help: make listexts less confusing for deprecated exts...
timeless -
r27151:7625f638 default
parent child Browse files
Show More
@@ -1,535 +1,536 b''
1 # help.py - help data for mercurial
1 # help.py - help data for mercurial
2 #
2 #
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
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, os, textwrap
9 import itertools, os, textwrap
10 import error
10 import error
11 import extensions, revset, fileset, templatekw, templatefilters, filemerge
11 import extensions, revset, fileset, templatekw, templatefilters, filemerge
12 import templater
12 import templater
13 import encoding, util, minirst
13 import encoding, util, minirst
14 import cmdutil
14 import cmdutil
15 import hgweb.webcommands as webcommands
15 import hgweb.webcommands as webcommands
16
16
17 _exclkeywords = [
17 _exclkeywords = [
18 "(DEPRECATED)",
18 "(DEPRECATED)",
19 "(EXPERIMENTAL)",
19 "(EXPERIMENTAL)",
20 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently
20 # i18n: "(DEPRECATED)" is a keyword, must be translated consistently
21 _("(DEPRECATED)"),
21 _("(DEPRECATED)"),
22 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently
22 # i18n: "(EXPERIMENTAL)" is a keyword, must be translated consistently
23 _("(EXPERIMENTAL)"),
23 _("(EXPERIMENTAL)"),
24 ]
24 ]
25
25
26 def listexts(header, exts, indent=1, showdeprecated=False):
26 def listexts(header, exts, indent=1, showdeprecated=False):
27 '''return a text listing of the given extensions'''
27 '''return a text listing of the given extensions'''
28 rst = []
28 rst = []
29 if exts:
29 if exts:
30 rst.append('\n%s\n\n' % header)
31 for name, desc in sorted(exts.iteritems()):
30 for name, desc in sorted(exts.iteritems()):
32 if not showdeprecated and any(w in desc for w in _exclkeywords):
31 if not showdeprecated and any(w in desc for w in _exclkeywords):
33 continue
32 continue
34 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
33 rst.append('%s:%s: %s\n' % (' ' * indent, name, desc))
34 if rst:
35 rst.insert(0, '\n%s\n\n' % header)
35 return rst
36 return rst
36
37
37 def extshelp(ui):
38 def extshelp(ui):
38 rst = loaddoc('extensions')(ui).splitlines(True)
39 rst = loaddoc('extensions')(ui).splitlines(True)
39 rst.extend(listexts(
40 rst.extend(listexts(
40 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
41 _('enabled extensions:'), extensions.enabled(), showdeprecated=True))
41 rst.extend(listexts(_('disabled extensions:'), extensions.disabled()))
42 rst.extend(listexts(_('disabled extensions:'), extensions.disabled()))
42 doc = ''.join(rst)
43 doc = ''.join(rst)
43 return doc
44 return doc
44
45
45 def optrst(header, options, verbose):
46 def optrst(header, options, verbose):
46 data = []
47 data = []
47 multioccur = False
48 multioccur = False
48 for option in options:
49 for option in options:
49 if len(option) == 5:
50 if len(option) == 5:
50 shortopt, longopt, default, desc, optlabel = option
51 shortopt, longopt, default, desc, optlabel = option
51 else:
52 else:
52 shortopt, longopt, default, desc = option
53 shortopt, longopt, default, desc = option
53 optlabel = _("VALUE") # default label
54 optlabel = _("VALUE") # default label
54
55
55 if not verbose and any(w in desc for w in _exclkeywords):
56 if not verbose and any(w in desc for w in _exclkeywords):
56 continue
57 continue
57
58
58 so = ''
59 so = ''
59 if shortopt:
60 if shortopt:
60 so = '-' + shortopt
61 so = '-' + shortopt
61 lo = '--' + longopt
62 lo = '--' + longopt
62 if default:
63 if default:
63 desc += _(" (default: %s)") % default
64 desc += _(" (default: %s)") % default
64
65
65 if isinstance(default, list):
66 if isinstance(default, list):
66 lo += " %s [+]" % optlabel
67 lo += " %s [+]" % optlabel
67 multioccur = True
68 multioccur = True
68 elif (default is not None) and not isinstance(default, bool):
69 elif (default is not None) and not isinstance(default, bool):
69 lo += " %s" % optlabel
70 lo += " %s" % optlabel
70
71
71 data.append((so, lo, desc))
72 data.append((so, lo, desc))
72
73
73 if multioccur:
74 if multioccur:
74 header += (_(" ([+] can be repeated)"))
75 header += (_(" ([+] can be repeated)"))
75
76
76 rst = ['\n%s:\n\n' % header]
77 rst = ['\n%s:\n\n' % header]
77 rst.extend(minirst.maketable(data, 1))
78 rst.extend(minirst.maketable(data, 1))
78
79
79 return ''.join(rst)
80 return ''.join(rst)
80
81
81 def indicateomitted(rst, omitted, notomitted=None):
82 def indicateomitted(rst, omitted, notomitted=None):
82 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
83 rst.append('\n\n.. container:: omitted\n\n %s\n\n' % omitted)
83 if notomitted:
84 if notomitted:
84 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
85 rst.append('\n\n.. container:: notomitted\n\n %s\n\n' % notomitted)
85
86
86 def topicmatch(ui, kw):
87 def topicmatch(ui, kw):
87 """Return help topics matching kw.
88 """Return help topics matching kw.
88
89
89 Returns {'section': [(name, summary), ...], ...} where section is
90 Returns {'section': [(name, summary), ...], ...} where section is
90 one of topics, commands, extensions, or extensioncommands.
91 one of topics, commands, extensions, or extensioncommands.
91 """
92 """
92 kw = encoding.lower(kw)
93 kw = encoding.lower(kw)
93 def lowercontains(container):
94 def lowercontains(container):
94 return kw in encoding.lower(container) # translated in helptable
95 return kw in encoding.lower(container) # translated in helptable
95 results = {'topics': [],
96 results = {'topics': [],
96 'commands': [],
97 'commands': [],
97 'extensions': [],
98 'extensions': [],
98 'extensioncommands': [],
99 'extensioncommands': [],
99 }
100 }
100 for names, header, doc in helptable:
101 for names, header, doc in helptable:
101 # Old extensions may use a str as doc.
102 # Old extensions may use a str as doc.
102 if (sum(map(lowercontains, names))
103 if (sum(map(lowercontains, names))
103 or lowercontains(header)
104 or lowercontains(header)
104 or (callable(doc) and lowercontains(doc(ui)))):
105 or (callable(doc) and lowercontains(doc(ui)))):
105 results['topics'].append((names[0], header))
106 results['topics'].append((names[0], header))
106 import commands # avoid cycle
107 import commands # avoid cycle
107 for cmd, entry in commands.table.iteritems():
108 for cmd, entry in commands.table.iteritems():
108 if len(entry) == 3:
109 if len(entry) == 3:
109 summary = entry[2]
110 summary = entry[2]
110 else:
111 else:
111 summary = ''
112 summary = ''
112 # translate docs *before* searching there
113 # translate docs *before* searching there
113 docs = _(getattr(entry[0], '__doc__', None)) or ''
114 docs = _(getattr(entry[0], '__doc__', None)) or ''
114 if kw in cmd or lowercontains(summary) or lowercontains(docs):
115 if kw in cmd or lowercontains(summary) or lowercontains(docs):
115 doclines = docs.splitlines()
116 doclines = docs.splitlines()
116 if doclines:
117 if doclines:
117 summary = doclines[0]
118 summary = doclines[0]
118 cmdname = cmd.partition('|')[0].lstrip('^')
119 cmdname = cmd.partition('|')[0].lstrip('^')
119 results['commands'].append((cmdname, summary))
120 results['commands'].append((cmdname, summary))
120 for name, docs in itertools.chain(
121 for name, docs in itertools.chain(
121 extensions.enabled(False).iteritems(),
122 extensions.enabled(False).iteritems(),
122 extensions.disabled().iteritems()):
123 extensions.disabled().iteritems()):
123 # extensions.load ignores the UI argument
124 # extensions.load ignores the UI argument
124 mod = extensions.load(None, name, '')
125 mod = extensions.load(None, name, '')
125 name = name.rpartition('.')[-1]
126 name = name.rpartition('.')[-1]
126 if lowercontains(name) or lowercontains(docs):
127 if lowercontains(name) or lowercontains(docs):
127 # extension docs are already translated
128 # extension docs are already translated
128 results['extensions'].append((name, docs.splitlines()[0]))
129 results['extensions'].append((name, docs.splitlines()[0]))
129 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
130 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
130 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
131 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
131 cmdname = cmd.partition('|')[0].lstrip('^')
132 cmdname = cmd.partition('|')[0].lstrip('^')
132 if entry[0].__doc__:
133 if entry[0].__doc__:
133 cmddoc = gettext(entry[0].__doc__).splitlines()[0]
134 cmddoc = gettext(entry[0].__doc__).splitlines()[0]
134 else:
135 else:
135 cmddoc = _('(no help text available)')
136 cmddoc = _('(no help text available)')
136 results['extensioncommands'].append((cmdname, cmddoc))
137 results['extensioncommands'].append((cmdname, cmddoc))
137 return results
138 return results
138
139
139 def loaddoc(topic):
140 def loaddoc(topic):
140 """Return a delayed loader for help/topic.txt."""
141 """Return a delayed loader for help/topic.txt."""
141
142
142 def loader(ui):
143 def loader(ui):
143 docdir = os.path.join(util.datapath, 'help')
144 docdir = os.path.join(util.datapath, 'help')
144 path = os.path.join(docdir, topic + ".txt")
145 path = os.path.join(docdir, topic + ".txt")
145 doc = gettext(util.readfile(path))
146 doc = gettext(util.readfile(path))
146 for rewriter in helphooks.get(topic, []):
147 for rewriter in helphooks.get(topic, []):
147 doc = rewriter(ui, topic, doc)
148 doc = rewriter(ui, topic, doc)
148 return doc
149 return doc
149
150
150 return loader
151 return loader
151
152
152 helptable = sorted([
153 helptable = sorted([
153 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
154 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
154 (["dates"], _("Date Formats"), loaddoc('dates')),
155 (["dates"], _("Date Formats"), loaddoc('dates')),
155 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
156 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
156 (['environment', 'env'], _('Environment Variables'),
157 (['environment', 'env'], _('Environment Variables'),
157 loaddoc('environment')),
158 loaddoc('environment')),
158 (['revisions', 'revs'], _('Specifying Single Revisions'),
159 (['revisions', 'revs'], _('Specifying Single Revisions'),
159 loaddoc('revisions')),
160 loaddoc('revisions')),
160 (['multirevs', 'mrevs'], _('Specifying Multiple Revisions'),
161 (['multirevs', 'mrevs'], _('Specifying Multiple Revisions'),
161 loaddoc('multirevs')),
162 loaddoc('multirevs')),
162 (['revsets', 'revset'], _("Specifying Revision Sets"), loaddoc('revsets')),
163 (['revsets', 'revset'], _("Specifying Revision Sets"), loaddoc('revsets')),
163 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
164 (['filesets', 'fileset'], _("Specifying File Sets"), loaddoc('filesets')),
164 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
165 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
165 (['merge-tools', 'mergetools'], _('Merge Tools'), loaddoc('merge-tools')),
166 (['merge-tools', 'mergetools'], _('Merge Tools'), loaddoc('merge-tools')),
166 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
167 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
167 loaddoc('templates')),
168 loaddoc('templates')),
168 (['urls'], _('URL Paths'), loaddoc('urls')),
169 (['urls'], _('URL Paths'), loaddoc('urls')),
169 (["extensions"], _("Using Additional Features"), extshelp),
170 (["extensions"], _("Using Additional Features"), extshelp),
170 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
171 (["subrepos", "subrepo"], _("Subrepositories"), loaddoc('subrepos')),
171 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
172 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
172 (["glossary"], _("Glossary"), loaddoc('glossary')),
173 (["glossary"], _("Glossary"), loaddoc('glossary')),
173 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
174 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
174 loaddoc('hgignore')),
175 loaddoc('hgignore')),
175 (["phases"], _("Working with Phases"), loaddoc('phases')),
176 (["phases"], _("Working with Phases"), loaddoc('phases')),
176 (['scripting'], _('Using Mercurial from scripts and automation'),
177 (['scripting'], _('Using Mercurial from scripts and automation'),
177 loaddoc('scripting')),
178 loaddoc('scripting')),
178 ])
179 ])
179
180
180 # Map topics to lists of callable taking the current topic help and
181 # Map topics to lists of callable taking the current topic help and
181 # returning the updated version
182 # returning the updated version
182 helphooks = {}
183 helphooks = {}
183
184
184 def addtopichook(topic, rewriter):
185 def addtopichook(topic, rewriter):
185 helphooks.setdefault(topic, []).append(rewriter)
186 helphooks.setdefault(topic, []).append(rewriter)
186
187
187 def makeitemsdoc(ui, topic, doc, marker, items, dedent=False):
188 def makeitemsdoc(ui, topic, doc, marker, items, dedent=False):
188 """Extract docstring from the items key to function mapping, build a
189 """Extract docstring from the items key to function mapping, build a
189 single documentation block and use it to overwrite the marker in doc.
190 single documentation block and use it to overwrite the marker in doc.
190 """
191 """
191 entries = []
192 entries = []
192 for name in sorted(items):
193 for name in sorted(items):
193 text = (items[name].__doc__ or '').rstrip()
194 text = (items[name].__doc__ or '').rstrip()
194 if (not text
195 if (not text
195 or not ui.verbose and any(w in text for w in _exclkeywords)):
196 or not ui.verbose and any(w in text for w in _exclkeywords)):
196 continue
197 continue
197 text = gettext(text)
198 text = gettext(text)
198 if dedent:
199 if dedent:
199 text = textwrap.dedent(text)
200 text = textwrap.dedent(text)
200 lines = text.splitlines()
201 lines = text.splitlines()
201 doclines = [(lines[0])]
202 doclines = [(lines[0])]
202 for l in lines[1:]:
203 for l in lines[1:]:
203 # Stop once we find some Python doctest
204 # Stop once we find some Python doctest
204 if l.strip().startswith('>>>'):
205 if l.strip().startswith('>>>'):
205 break
206 break
206 if dedent:
207 if dedent:
207 doclines.append(l.rstrip())
208 doclines.append(l.rstrip())
208 else:
209 else:
209 doclines.append(' ' + l.strip())
210 doclines.append(' ' + l.strip())
210 entries.append('\n'.join(doclines))
211 entries.append('\n'.join(doclines))
211 entries = '\n\n'.join(entries)
212 entries = '\n\n'.join(entries)
212 return doc.replace(marker, entries)
213 return doc.replace(marker, entries)
213
214
214 def addtopicsymbols(topic, marker, symbols, dedent=False):
215 def addtopicsymbols(topic, marker, symbols, dedent=False):
215 def add(ui, topic, doc):
216 def add(ui, topic, doc):
216 return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent)
217 return makeitemsdoc(ui, topic, doc, marker, symbols, dedent=dedent)
217 addtopichook(topic, add)
218 addtopichook(topic, add)
218
219
219 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
220 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
220 addtopicsymbols('merge-tools', '.. internaltoolsmarker',
221 addtopicsymbols('merge-tools', '.. internaltoolsmarker',
221 filemerge.internalsdoc)
222 filemerge.internalsdoc)
222 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
223 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
223 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
224 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
224 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
225 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
225 addtopicsymbols('templates', '.. functionsmarker', templater.funcs)
226 addtopicsymbols('templates', '.. functionsmarker', templater.funcs)
226 addtopicsymbols('hgweb', '.. webcommandsmarker', webcommands.commands,
227 addtopicsymbols('hgweb', '.. webcommandsmarker', webcommands.commands,
227 dedent=True)
228 dedent=True)
228
229
229 def help_(ui, name, unknowncmd=False, full=True, **opts):
230 def help_(ui, name, unknowncmd=False, full=True, **opts):
230 '''
231 '''
231 Generate the help for 'name' as unformatted restructured text. If
232 Generate the help for 'name' as unformatted restructured text. If
232 'name' is None, describe the commands available.
233 'name' is None, describe the commands available.
233 '''
234 '''
234
235
235 import commands # avoid cycle
236 import commands # avoid cycle
236
237
237 def helpcmd(name):
238 def helpcmd(name):
238 try:
239 try:
239 aliases, entry = cmdutil.findcmd(name, commands.table,
240 aliases, entry = cmdutil.findcmd(name, commands.table,
240 strict=unknowncmd)
241 strict=unknowncmd)
241 except error.AmbiguousCommand as inst:
242 except error.AmbiguousCommand as inst:
242 # py3k fix: except vars can't be used outside the scope of the
243 # py3k fix: except vars can't be used outside the scope of the
243 # except block, nor can be used inside a lambda. python issue4617
244 # except block, nor can be used inside a lambda. python issue4617
244 prefix = inst.args[0]
245 prefix = inst.args[0]
245 select = lambda c: c.lstrip('^').startswith(prefix)
246 select = lambda c: c.lstrip('^').startswith(prefix)
246 rst = helplist(select)
247 rst = helplist(select)
247 return rst
248 return rst
248
249
249 rst = []
250 rst = []
250
251
251 # check if it's an invalid alias and display its error if it is
252 # check if it's an invalid alias and display its error if it is
252 if getattr(entry[0], 'badalias', None):
253 if getattr(entry[0], 'badalias', None):
253 rst.append(entry[0].badalias + '\n')
254 rst.append(entry[0].badalias + '\n')
254 if entry[0].unknowncmd:
255 if entry[0].unknowncmd:
255 try:
256 try:
256 rst.extend(helpextcmd(entry[0].cmdname))
257 rst.extend(helpextcmd(entry[0].cmdname))
257 except error.UnknownCommand:
258 except error.UnknownCommand:
258 pass
259 pass
259 return rst
260 return rst
260
261
261 # synopsis
262 # synopsis
262 if len(entry) > 2:
263 if len(entry) > 2:
263 if entry[2].startswith('hg'):
264 if entry[2].startswith('hg'):
264 rst.append("%s\n" % entry[2])
265 rst.append("%s\n" % entry[2])
265 else:
266 else:
266 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
267 rst.append('hg %s %s\n' % (aliases[0], entry[2]))
267 else:
268 else:
268 rst.append('hg %s\n' % aliases[0])
269 rst.append('hg %s\n' % aliases[0])
269 # aliases
270 # aliases
270 if full and not ui.quiet and len(aliases) > 1:
271 if full and not ui.quiet and len(aliases) > 1:
271 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
272 rst.append(_("\naliases: %s\n") % ', '.join(aliases[1:]))
272 rst.append('\n')
273 rst.append('\n')
273
274
274 # description
275 # description
275 doc = gettext(entry[0].__doc__)
276 doc = gettext(entry[0].__doc__)
276 if not doc:
277 if not doc:
277 doc = _("(no help text available)")
278 doc = _("(no help text available)")
278 if util.safehasattr(entry[0], 'definition'): # aliased command
279 if util.safehasattr(entry[0], 'definition'): # aliased command
279 if entry[0].definition.startswith('!'): # shell alias
280 if entry[0].definition.startswith('!'): # shell alias
280 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
281 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
281 else:
282 else:
282 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
283 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
283 doc = doc.splitlines(True)
284 doc = doc.splitlines(True)
284 if ui.quiet or not full:
285 if ui.quiet or not full:
285 rst.append(doc[0])
286 rst.append(doc[0])
286 else:
287 else:
287 rst.extend(doc)
288 rst.extend(doc)
288 rst.append('\n')
289 rst.append('\n')
289
290
290 # check if this command shadows a non-trivial (multi-line)
291 # check if this command shadows a non-trivial (multi-line)
291 # extension help text
292 # extension help text
292 try:
293 try:
293 mod = extensions.find(name)
294 mod = extensions.find(name)
294 doc = gettext(mod.__doc__) or ''
295 doc = gettext(mod.__doc__) or ''
295 if '\n' in doc.strip():
296 if '\n' in doc.strip():
296 msg = _('(use "hg help -e %s" to show help for '
297 msg = _('(use "hg help -e %s" to show help for '
297 'the %s extension)') % (name, name)
298 'the %s extension)') % (name, name)
298 rst.append('\n%s\n' % msg)
299 rst.append('\n%s\n' % msg)
299 except KeyError:
300 except KeyError:
300 pass
301 pass
301
302
302 # options
303 # options
303 if not ui.quiet and entry[1]:
304 if not ui.quiet and entry[1]:
304 rst.append(optrst(_("options"), entry[1], ui.verbose))
305 rst.append(optrst(_("options"), entry[1], ui.verbose))
305
306
306 if ui.verbose:
307 if ui.verbose:
307 rst.append(optrst(_("global options"),
308 rst.append(optrst(_("global options"),
308 commands.globalopts, ui.verbose))
309 commands.globalopts, ui.verbose))
309
310
310 if not ui.verbose:
311 if not ui.verbose:
311 if not full:
312 if not full:
312 rst.append(_('\n(use "hg %s -h" to show more help)\n')
313 rst.append(_('\n(use "hg %s -h" to show more help)\n')
313 % name)
314 % name)
314 elif not ui.quiet:
315 elif not ui.quiet:
315 rst.append(_('\n(some details hidden, use --verbose '
316 rst.append(_('\n(some details hidden, use --verbose '
316 'to show complete help)'))
317 'to show complete help)'))
317
318
318 return rst
319 return rst
319
320
320
321
321 def helplist(select=None):
322 def helplist(select=None):
322 # list of commands
323 # list of commands
323 if name == "shortlist":
324 if name == "shortlist":
324 header = _('basic commands:\n\n')
325 header = _('basic commands:\n\n')
325 elif name == "debug":
326 elif name == "debug":
326 header = _('debug commands (internal and unsupported):\n\n')
327 header = _('debug commands (internal and unsupported):\n\n')
327 else:
328 else:
328 header = _('list of commands:\n\n')
329 header = _('list of commands:\n\n')
329
330
330 h = {}
331 h = {}
331 cmds = {}
332 cmds = {}
332 for c, e in commands.table.iteritems():
333 for c, e in commands.table.iteritems():
333 f = c.partition("|")[0]
334 f = c.partition("|")[0]
334 if select and not select(f):
335 if select and not select(f):
335 continue
336 continue
336 if (not select and name != 'shortlist' and
337 if (not select and name != 'shortlist' and
337 e[0].__module__ != commands.__name__):
338 e[0].__module__ != commands.__name__):
338 continue
339 continue
339 if name == "shortlist" and not f.startswith("^"):
340 if name == "shortlist" and not f.startswith("^"):
340 continue
341 continue
341 f = f.lstrip("^")
342 f = f.lstrip("^")
342 if not ui.debugflag and f.startswith("debug") and name != "debug":
343 if not ui.debugflag and f.startswith("debug") and name != "debug":
343 continue
344 continue
344 doc = e[0].__doc__
345 doc = e[0].__doc__
345 if not ui.verbose and doc and any(w in doc for w in _exclkeywords):
346 if not ui.verbose and doc and any(w in doc for w in _exclkeywords):
346 continue
347 continue
347 doc = gettext(doc)
348 doc = gettext(doc)
348 if not doc:
349 if not doc:
349 doc = _("(no help text available)")
350 doc = _("(no help text available)")
350 h[f] = doc.splitlines()[0].rstrip()
351 h[f] = doc.splitlines()[0].rstrip()
351 cmds[f] = c.lstrip("^")
352 cmds[f] = c.lstrip("^")
352
353
353 rst = []
354 rst = []
354 if not h:
355 if not h:
355 if not ui.quiet:
356 if not ui.quiet:
356 rst.append(_('no commands defined\n'))
357 rst.append(_('no commands defined\n'))
357 return rst
358 return rst
358
359
359 if not ui.quiet:
360 if not ui.quiet:
360 rst.append(header)
361 rst.append(header)
361 fns = sorted(h)
362 fns = sorted(h)
362 for f in fns:
363 for f in fns:
363 if ui.verbose:
364 if ui.verbose:
364 commacmds = cmds[f].replace("|",", ")
365 commacmds = cmds[f].replace("|",", ")
365 rst.append(" :%s: %s\n" % (commacmds, h[f]))
366 rst.append(" :%s: %s\n" % (commacmds, h[f]))
366 else:
367 else:
367 rst.append(' :%s: %s\n' % (f, h[f]))
368 rst.append(' :%s: %s\n' % (f, h[f]))
368
369
369 if not name:
370 if not name:
370 exts = listexts(_('enabled extensions:'), extensions.enabled())
371 exts = listexts(_('enabled extensions:'), extensions.enabled())
371 if exts:
372 if exts:
372 rst.append('\n')
373 rst.append('\n')
373 rst.extend(exts)
374 rst.extend(exts)
374
375
375 rst.append(_("\nadditional help topics:\n\n"))
376 rst.append(_("\nadditional help topics:\n\n"))
376 topics = []
377 topics = []
377 for names, header, doc in helptable:
378 for names, header, doc in helptable:
378 topics.append((names[0], header))
379 topics.append((names[0], header))
379 for t, desc in topics:
380 for t, desc in topics:
380 rst.append(" :%s: %s\n" % (t, desc))
381 rst.append(" :%s: %s\n" % (t, desc))
381
382
382 if ui.quiet:
383 if ui.quiet:
383 pass
384 pass
384 elif ui.verbose:
385 elif ui.verbose:
385 rst.append('\n%s\n' % optrst(_("global options"),
386 rst.append('\n%s\n' % optrst(_("global options"),
386 commands.globalopts, ui.verbose))
387 commands.globalopts, ui.verbose))
387 if name == 'shortlist':
388 if name == 'shortlist':
388 rst.append(_('\n(use "hg help" for the full list '
389 rst.append(_('\n(use "hg help" for the full list '
389 'of commands)\n'))
390 'of commands)\n'))
390 else:
391 else:
391 if name == 'shortlist':
392 if name == 'shortlist':
392 rst.append(_('\n(use "hg help" for the full list of commands '
393 rst.append(_('\n(use "hg help" for the full list of commands '
393 'or "hg -v" for details)\n'))
394 'or "hg -v" for details)\n'))
394 elif name and not full:
395 elif name and not full:
395 rst.append(_('\n(use "hg help %s" to show the full help '
396 rst.append(_('\n(use "hg help %s" to show the full help '
396 'text)\n') % name)
397 'text)\n') % name)
397 elif name and cmds and name in cmds.keys():
398 elif name and cmds and name in cmds.keys():
398 rst.append(_('\n(use "hg help -v -e %s" to show built-in '
399 rst.append(_('\n(use "hg help -v -e %s" to show built-in '
399 'aliases and global options)\n') % name)
400 'aliases and global options)\n') % name)
400 else:
401 else:
401 rst.append(_('\n(use "hg help -v%s" to show built-in aliases '
402 rst.append(_('\n(use "hg help -v%s" to show built-in aliases '
402 'and global options)\n')
403 'and global options)\n')
403 % (name and " " + name or ""))
404 % (name and " " + name or ""))
404 return rst
405 return rst
405
406
406 def helptopic(name):
407 def helptopic(name):
407 for names, header, doc in helptable:
408 for names, header, doc in helptable:
408 if name in names:
409 if name in names:
409 break
410 break
410 else:
411 else:
411 raise error.UnknownCommand(name)
412 raise error.UnknownCommand(name)
412
413
413 rst = [minirst.section(header)]
414 rst = [minirst.section(header)]
414
415
415 # description
416 # description
416 if not doc:
417 if not doc:
417 rst.append(" %s\n" % _("(no help text available)"))
418 rst.append(" %s\n" % _("(no help text available)"))
418 if callable(doc):
419 if callable(doc):
419 rst += [" %s\n" % l for l in doc(ui).splitlines()]
420 rst += [" %s\n" % l for l in doc(ui).splitlines()]
420
421
421 if not ui.verbose:
422 if not ui.verbose:
422 omitted = _('(some details hidden, use --verbose'
423 omitted = _('(some details hidden, use --verbose'
423 ' to show complete help)')
424 ' to show complete help)')
424 indicateomitted(rst, omitted)
425 indicateomitted(rst, omitted)
425
426
426 try:
427 try:
427 cmdutil.findcmd(name, commands.table)
428 cmdutil.findcmd(name, commands.table)
428 rst.append(_('\nuse "hg help -c %s" to see help for '
429 rst.append(_('\nuse "hg help -c %s" to see help for '
429 'the %s command\n') % (name, name))
430 'the %s command\n') % (name, name))
430 except error.UnknownCommand:
431 except error.UnknownCommand:
431 pass
432 pass
432 return rst
433 return rst
433
434
434 def helpext(name):
435 def helpext(name):
435 try:
436 try:
436 mod = extensions.find(name)
437 mod = extensions.find(name)
437 doc = gettext(mod.__doc__) or _('no help text available')
438 doc = gettext(mod.__doc__) or _('no help text available')
438 except KeyError:
439 except KeyError:
439 mod = None
440 mod = None
440 doc = extensions.disabledext(name)
441 doc = extensions.disabledext(name)
441 if not doc:
442 if not doc:
442 raise error.UnknownCommand(name)
443 raise error.UnknownCommand(name)
443
444
444 if '\n' not in doc:
445 if '\n' not in doc:
445 head, tail = doc, ""
446 head, tail = doc, ""
446 else:
447 else:
447 head, tail = doc.split('\n', 1)
448 head, tail = doc.split('\n', 1)
448 rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
449 rst = [_('%s extension - %s\n\n') % (name.rpartition('.')[-1], head)]
449 if tail:
450 if tail:
450 rst.extend(tail.splitlines(True))
451 rst.extend(tail.splitlines(True))
451 rst.append('\n')
452 rst.append('\n')
452
453
453 if not ui.verbose:
454 if not ui.verbose:
454 omitted = _('(some details hidden, use --verbose'
455 omitted = _('(some details hidden, use --verbose'
455 ' to show complete help)')
456 ' to show complete help)')
456 indicateomitted(rst, omitted)
457 indicateomitted(rst, omitted)
457
458
458 if mod:
459 if mod:
459 try:
460 try:
460 ct = mod.cmdtable
461 ct = mod.cmdtable
461 except AttributeError:
462 except AttributeError:
462 ct = {}
463 ct = {}
463 modcmds = set([c.partition('|')[0] for c in ct])
464 modcmds = set([c.partition('|')[0] for c in ct])
464 rst.extend(helplist(modcmds.__contains__))
465 rst.extend(helplist(modcmds.__contains__))
465 else:
466 else:
466 rst.append(_('(use "hg help extensions" for information on enabling'
467 rst.append(_('(use "hg help extensions" for information on enabling'
467 ' extensions)\n'))
468 ' extensions)\n'))
468 return rst
469 return rst
469
470
470 def helpextcmd(name):
471 def helpextcmd(name):
471 cmd, ext, mod = extensions.disabledcmd(ui, name,
472 cmd, ext, mod = extensions.disabledcmd(ui, name,
472 ui.configbool('ui', 'strict'))
473 ui.configbool('ui', 'strict'))
473 doc = gettext(mod.__doc__).splitlines()[0]
474 doc = gettext(mod.__doc__).splitlines()[0]
474
475
475 rst = listexts(_("'%s' is provided by the following "
476 rst = listexts(_("'%s' is provided by the following "
476 "extension:") % cmd, {ext: doc}, indent=4)
477 "extension:") % cmd, {ext: doc}, indent=4)
477 rst.append('\n')
478 rst.append('\n')
478 rst.append(_('(use "hg help extensions" for information on enabling '
479 rst.append(_('(use "hg help extensions" for information on enabling '
479 'extensions)\n'))
480 'extensions)\n'))
480 return rst
481 return rst
481
482
482
483
483 rst = []
484 rst = []
484 kw = opts.get('keyword')
485 kw = opts.get('keyword')
485 if kw:
486 if kw:
486 matches = topicmatch(ui, name)
487 matches = topicmatch(ui, name)
487 helpareas = []
488 helpareas = []
488 if opts.get('extension'):
489 if opts.get('extension'):
489 helpareas += [('extensions', _('Extensions'))]
490 helpareas += [('extensions', _('Extensions'))]
490 if opts.get('command'):
491 if opts.get('command'):
491 helpareas += [('commands', _('Commands'))]
492 helpareas += [('commands', _('Commands'))]
492 if not helpareas:
493 if not helpareas:
493 helpareas = [('topics', _('Topics')),
494 helpareas = [('topics', _('Topics')),
494 ('commands', _('Commands')),
495 ('commands', _('Commands')),
495 ('extensions', _('Extensions')),
496 ('extensions', _('Extensions')),
496 ('extensioncommands', _('Extension Commands'))]
497 ('extensioncommands', _('Extension Commands'))]
497 for t, title in helpareas:
498 for t, title in helpareas:
498 if matches[t]:
499 if matches[t]:
499 rst.append('%s:\n\n' % title)
500 rst.append('%s:\n\n' % title)
500 rst.extend(minirst.maketable(sorted(matches[t]), 1))
501 rst.extend(minirst.maketable(sorted(matches[t]), 1))
501 rst.append('\n')
502 rst.append('\n')
502 if not rst:
503 if not rst:
503 msg = _('no matches')
504 msg = _('no matches')
504 hint = _('try "hg help" for a list of topics')
505 hint = _('try "hg help" for a list of topics')
505 raise error.Abort(msg, hint=hint)
506 raise error.Abort(msg, hint=hint)
506 elif name and name != 'shortlist':
507 elif name and name != 'shortlist':
507 queries = []
508 queries = []
508 if unknowncmd:
509 if unknowncmd:
509 queries += [helpextcmd]
510 queries += [helpextcmd]
510 if opts.get('extension'):
511 if opts.get('extension'):
511 queries += [helpext]
512 queries += [helpext]
512 if opts.get('command'):
513 if opts.get('command'):
513 queries += [helpcmd]
514 queries += [helpcmd]
514 if not queries:
515 if not queries:
515 queries = (helptopic, helpcmd, helpext, helpextcmd)
516 queries = (helptopic, helpcmd, helpext, helpextcmd)
516 for f in queries:
517 for f in queries:
517 try:
518 try:
518 rst = f(name)
519 rst = f(name)
519 break
520 break
520 except error.UnknownCommand:
521 except error.UnknownCommand:
521 pass
522 pass
522 else:
523 else:
523 if unknowncmd:
524 if unknowncmd:
524 raise error.UnknownCommand(name)
525 raise error.UnknownCommand(name)
525 else:
526 else:
526 msg = _('no such help topic: %s') % name
527 msg = _('no such help topic: %s') % name
527 hint = _('try "hg help --keyword %s"') % name
528 hint = _('try "hg help --keyword %s"') % name
528 raise error.Abort(msg, hint=hint)
529 raise error.Abort(msg, hint=hint)
529 else:
530 else:
530 # program name
531 # program name
531 if not ui.quiet:
532 if not ui.quiet:
532 rst = [_("Mercurial Distributed SCM\n"), '\n']
533 rst = [_("Mercurial Distributed SCM\n"), '\n']
533 rst.extend(helplist())
534 rst.extend(helplist())
534
535
535 return ''.join(rst)
536 return ''.join(rst)
General Comments 0
You need to be logged in to leave comments. Login now