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