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