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