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