##// END OF EJS Templates
help: restore use of callable() since it was readded in Python 3.2
Augie Fackler -
r21796:8225bb1f default
parent child Browse files
Show More
@@ -1,516 +1,516 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(_('\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')
297 % name)
297 % name)
298 elif not ui.quiet:
298 elif not ui.quiet:
299 omitted = _('use "hg -v help %s" to show more complete'
299 omitted = _('use "hg -v help %s" to show more complete'
300 ' help and the global options') % name
300 ' help and the global options') % name
301 notomitted = _('use "hg -v help %s" to show'
301 notomitted = _('use "hg -v help %s" to show'
302 ' the global options') % name
302 ' the global options') % name
303 indicateomitted(rst, omitted, notomitted)
303 indicateomitted(rst, omitted, notomitted)
304
304
305 return rst
305 return rst
306
306
307
307
308 def helplist(select=None):
308 def helplist(select=None):
309 # list of commands
309 # list of commands
310 if name == "shortlist":
310 if name == "shortlist":
311 header = _('basic commands:\n\n')
311 header = _('basic commands:\n\n')
312 elif name == "debug":
312 elif name == "debug":
313 header = _('debug commands (internal and unsupported):\n\n')
313 header = _('debug commands (internal and unsupported):\n\n')
314 else:
314 else:
315 header = _('list of commands:\n\n')
315 header = _('list of commands:\n\n')
316
316
317 h = {}
317 h = {}
318 cmds = {}
318 cmds = {}
319 for c, e in commands.table.iteritems():
319 for c, e in commands.table.iteritems():
320 f = c.split("|", 1)[0]
320 f = c.split("|", 1)[0]
321 if select and not select(f):
321 if select and not select(f):
322 continue
322 continue
323 if (not select and name != 'shortlist' and
323 if (not select and name != 'shortlist' and
324 e[0].__module__ != commands.__name__):
324 e[0].__module__ != commands.__name__):
325 continue
325 continue
326 if name == "shortlist" and not f.startswith("^"):
326 if name == "shortlist" and not f.startswith("^"):
327 continue
327 continue
328 f = f.lstrip("^")
328 f = f.lstrip("^")
329 if not ui.debugflag and f.startswith("debug") and name != "debug":
329 if not ui.debugflag and f.startswith("debug") and name != "debug":
330 continue
330 continue
331 doc = e[0].__doc__
331 doc = e[0].__doc__
332 if doc and 'DEPRECATED' in doc and not ui.verbose:
332 if doc and 'DEPRECATED' in doc and not ui.verbose:
333 continue
333 continue
334 doc = gettext(doc)
334 doc = gettext(doc)
335 if not doc:
335 if not doc:
336 doc = _("(no help text available)")
336 doc = _("(no help text available)")
337 h[f] = doc.splitlines()[0].rstrip()
337 h[f] = doc.splitlines()[0].rstrip()
338 cmds[f] = c.lstrip("^")
338 cmds[f] = c.lstrip("^")
339
339
340 rst = []
340 rst = []
341 if not h:
341 if not h:
342 if not ui.quiet:
342 if not ui.quiet:
343 rst.append(_('no commands defined\n'))
343 rst.append(_('no commands defined\n'))
344 return rst
344 return rst
345
345
346 if not ui.quiet:
346 if not ui.quiet:
347 rst.append(header)
347 rst.append(header)
348 fns = sorted(h)
348 fns = sorted(h)
349 for f in fns:
349 for f in fns:
350 if ui.verbose:
350 if ui.verbose:
351 commacmds = cmds[f].replace("|",", ")
351 commacmds = cmds[f].replace("|",", ")
352 rst.append(" :%s: %s\n" % (commacmds, h[f]))
352 rst.append(" :%s: %s\n" % (commacmds, h[f]))
353 else:
353 else:
354 rst.append(' :%s: %s\n' % (f, h[f]))
354 rst.append(' :%s: %s\n' % (f, h[f]))
355
355
356 if not name:
356 if not name:
357 exts = listexts(_('enabled extensions:'), extensions.enabled())
357 exts = listexts(_('enabled extensions:'), extensions.enabled())
358 if exts:
358 if exts:
359 rst.append('\n')
359 rst.append('\n')
360 rst.extend(exts)
360 rst.extend(exts)
361
361
362 rst.append(_("\nadditional help topics:\n\n"))
362 rst.append(_("\nadditional help topics:\n\n"))
363 topics = []
363 topics = []
364 for names, header, doc in helptable:
364 for names, header, doc in helptable:
365 topics.append((names[0], header))
365 topics.append((names[0], header))
366 for t, desc in topics:
366 for t, desc in topics:
367 rst.append(" :%s: %s\n" % (t, desc))
367 rst.append(" :%s: %s\n" % (t, desc))
368
368
369 optlist = []
369 optlist = []
370 if not ui.quiet:
370 if not ui.quiet:
371 if ui.verbose:
371 if ui.verbose:
372 optlist.append((_("global options:"), commands.globalopts))
372 optlist.append((_("global options:"), commands.globalopts))
373 if name == 'shortlist':
373 if name == 'shortlist':
374 optlist.append((_('use "hg help" for the full list '
374 optlist.append((_('use "hg help" for the full list '
375 'of commands'), ()))
375 'of commands'), ()))
376 else:
376 else:
377 if name == 'shortlist':
377 if name == 'shortlist':
378 msg = _('use "hg help" for the full list of commands '
378 msg = _('use "hg help" for the full list of commands '
379 'or "hg -v" for details')
379 'or "hg -v" for details')
380 elif name and not full:
380 elif name and not full:
381 msg = _('use "hg help %s" to show the full help '
381 msg = _('use "hg help %s" to show the full help '
382 'text') % name
382 'text') % name
383 else:
383 else:
384 msg = _('use "hg -v help%s" to show builtin aliases and '
384 msg = _('use "hg -v help%s" to show builtin aliases and '
385 'global options') % (name and " " + name or "")
385 'global options') % (name and " " + name or "")
386 optlist.append((msg, ()))
386 optlist.append((msg, ()))
387
387
388 if optlist:
388 if optlist:
389 for title, options in optlist:
389 for title, options in optlist:
390 rst.append('\n%s\n' % title)
390 rst.append('\n%s\n' % title)
391 if options:
391 if options:
392 rst.append('\n%s\n' % optrst(options, ui.verbose))
392 rst.append('\n%s\n' % optrst(options, ui.verbose))
393 return rst
393 return rst
394
394
395 def helptopic(name):
395 def helptopic(name):
396 for names, header, doc in helptable:
396 for names, header, doc in helptable:
397 if name in names:
397 if name in names:
398 break
398 break
399 else:
399 else:
400 raise error.UnknownCommand(name)
400 raise error.UnknownCommand(name)
401
401
402 rst = [minirst.section(header)]
402 rst = [minirst.section(header)]
403
403
404 # description
404 # description
405 if not doc:
405 if not doc:
406 rst.append(" %s\n" % _("(no help text available)"))
406 rst.append(" %s\n" % _("(no help text available)"))
407 if util.safehasattr(doc, '__call__'):
407 if callable(doc):
408 rst += [" %s\n" % l for l in doc().splitlines()]
408 rst += [" %s\n" % l for l in doc().splitlines()]
409
409
410 if not ui.verbose:
410 if not ui.verbose:
411 omitted = (_('use "hg help -v %s" to show more complete help') %
411 omitted = (_('use "hg help -v %s" to show more complete help') %
412 name)
412 name)
413 indicateomitted(rst, omitted)
413 indicateomitted(rst, omitted)
414
414
415 try:
415 try:
416 cmdutil.findcmd(name, commands.table)
416 cmdutil.findcmd(name, commands.table)
417 rst.append(_('\nuse "hg help -c %s" to see help for '
417 rst.append(_('\nuse "hg help -c %s" to see help for '
418 'the %s command\n') % (name, name))
418 'the %s command\n') % (name, name))
419 except error.UnknownCommand:
419 except error.UnknownCommand:
420 pass
420 pass
421 return rst
421 return rst
422
422
423 def helpext(name):
423 def helpext(name):
424 try:
424 try:
425 mod = extensions.find(name)
425 mod = extensions.find(name)
426 doc = gettext(mod.__doc__) or _('no help text available')
426 doc = gettext(mod.__doc__) or _('no help text available')
427 except KeyError:
427 except KeyError:
428 mod = None
428 mod = None
429 doc = extensions.disabledext(name)
429 doc = extensions.disabledext(name)
430 if not doc:
430 if not doc:
431 raise error.UnknownCommand(name)
431 raise error.UnknownCommand(name)
432
432
433 if '\n' not in doc:
433 if '\n' not in doc:
434 head, tail = doc, ""
434 head, tail = doc, ""
435 else:
435 else:
436 head, tail = doc.split('\n', 1)
436 head, tail = doc.split('\n', 1)
437 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
437 rst = [_('%s extension - %s\n\n') % (name.split('.')[-1], head)]
438 if tail:
438 if tail:
439 rst.extend(tail.splitlines(True))
439 rst.extend(tail.splitlines(True))
440 rst.append('\n')
440 rst.append('\n')
441
441
442 if not ui.verbose:
442 if not ui.verbose:
443 omitted = (_('use "hg help -v %s" to show more complete help') %
443 omitted = (_('use "hg help -v %s" to show more complete help') %
444 name)
444 name)
445 indicateomitted(rst, omitted)
445 indicateomitted(rst, omitted)
446
446
447 if mod:
447 if mod:
448 try:
448 try:
449 ct = mod.cmdtable
449 ct = mod.cmdtable
450 except AttributeError:
450 except AttributeError:
451 ct = {}
451 ct = {}
452 modcmds = set([c.split('|', 1)[0] for c in ct])
452 modcmds = set([c.split('|', 1)[0] for c in ct])
453 rst.extend(helplist(modcmds.__contains__))
453 rst.extend(helplist(modcmds.__contains__))
454 else:
454 else:
455 rst.append(_('use "hg help extensions" for information on enabling '
455 rst.append(_('use "hg help extensions" for information on enabling '
456 'extensions\n'))
456 'extensions\n'))
457 return rst
457 return rst
458
458
459 def helpextcmd(name):
459 def helpextcmd(name):
460 cmd, ext, mod = extensions.disabledcmd(ui, name,
460 cmd, ext, mod = extensions.disabledcmd(ui, name,
461 ui.configbool('ui', 'strict'))
461 ui.configbool('ui', 'strict'))
462 doc = gettext(mod.__doc__).splitlines()[0]
462 doc = gettext(mod.__doc__).splitlines()[0]
463
463
464 rst = listexts(_("'%s' is provided by the following "
464 rst = listexts(_("'%s' is provided by the following "
465 "extension:") % cmd, {ext: doc}, indent=4)
465 "extension:") % cmd, {ext: doc}, indent=4)
466 rst.append('\n')
466 rst.append('\n')
467 rst.append(_('use "hg help extensions" for information on enabling '
467 rst.append(_('use "hg help extensions" for information on enabling '
468 'extensions\n'))
468 'extensions\n'))
469 return rst
469 return rst
470
470
471
471
472 rst = []
472 rst = []
473 kw = opts.get('keyword')
473 kw = opts.get('keyword')
474 if kw:
474 if kw:
475 matches = topicmatch(kw)
475 matches = topicmatch(kw)
476 for t, title in (('topics', _('Topics')),
476 for t, title in (('topics', _('Topics')),
477 ('commands', _('Commands')),
477 ('commands', _('Commands')),
478 ('extensions', _('Extensions')),
478 ('extensions', _('Extensions')),
479 ('extensioncommands', _('Extension Commands'))):
479 ('extensioncommands', _('Extension Commands'))):
480 if matches[t]:
480 if matches[t]:
481 rst.append('%s:\n\n' % title)
481 rst.append('%s:\n\n' % title)
482 rst.extend(minirst.maketable(sorted(matches[t]), 1))
482 rst.extend(minirst.maketable(sorted(matches[t]), 1))
483 rst.append('\n')
483 rst.append('\n')
484 if not rst:
484 if not rst:
485 msg = _('no matches')
485 msg = _('no matches')
486 hint = _('try "hg help" for a list of topics')
486 hint = _('try "hg help" for a list of topics')
487 raise util.Abort(msg, hint=hint)
487 raise util.Abort(msg, hint=hint)
488 elif name and name != 'shortlist':
488 elif name and name != 'shortlist':
489 if unknowncmd:
489 if unknowncmd:
490 queries = (helpextcmd,)
490 queries = (helpextcmd,)
491 elif opts.get('extension'):
491 elif opts.get('extension'):
492 queries = (helpext,)
492 queries = (helpext,)
493 elif opts.get('command'):
493 elif opts.get('command'):
494 queries = (helpcmd,)
494 queries = (helpcmd,)
495 else:
495 else:
496 queries = (helptopic, helpcmd, helpext, helpextcmd)
496 queries = (helptopic, helpcmd, helpext, helpextcmd)
497 for f in queries:
497 for f in queries:
498 try:
498 try:
499 rst = f(name)
499 rst = f(name)
500 break
500 break
501 except error.UnknownCommand:
501 except error.UnknownCommand:
502 pass
502 pass
503 else:
503 else:
504 if unknowncmd:
504 if unknowncmd:
505 raise error.UnknownCommand(name)
505 raise error.UnknownCommand(name)
506 else:
506 else:
507 msg = _('no such help topic: %s') % name
507 msg = _('no such help topic: %s') % name
508 hint = _('try "hg help --keyword %s"') % name
508 hint = _('try "hg help --keyword %s"') % name
509 raise util.Abort(msg, hint=hint)
509 raise util.Abort(msg, hint=hint)
510 else:
510 else:
511 # program name
511 # program name
512 if not ui.quiet:
512 if not ui.quiet:
513 rst = [_("Mercurial Distributed SCM\n"), '\n']
513 rst = [_("Mercurial Distributed SCM\n"), '\n']
514 rst.extend(helplist())
514 rst.extend(helplist())
515
515
516 return ''.join(rst)
516 return ''.join(rst)
General Comments 0
You need to be logged in to leave comments. Login now