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