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