##// END OF EJS Templates
help: introduce topicmatch for finding topics matching a keyword
Augie Fackler -
r16710:a1798368 default
parent child Browse files
Show More
@@ -1,116 +1,164 b''
1 1 # help.py - help data for mercurial
2 2 #
3 3 # Copyright 2006 Matt Mackall <mpm@selenic.com>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from i18n import gettext, _
9 import sys, os
9 import itertools, sys, os
10 10 import extensions, revset, fileset, templatekw, templatefilters, filemerge
11 import util
11 import encoding, util
12 12
13 13 def listexts(header, exts, indent=1):
14 14 '''return a text listing of the given extensions'''
15 15 if not exts:
16 16 return ''
17 17 maxlength = max(len(e) for e in exts)
18 18 result = '\n%s\n\n' % header
19 19 for name, desc in sorted(exts.iteritems()):
20 20 result += '%s%-*s %s\n' % (' ' * indent, maxlength + 2,
21 21 ':%s:' % name, desc)
22 22 return result
23 23
24 24 def extshelp():
25 25 doc = loaddoc('extensions')()
26 26 doc += listexts(_('enabled extensions:'), extensions.enabled())
27 27 doc += listexts(_('disabled extensions:'), extensions.disabled())
28 28 return doc
29 29
30 def topicmatch(kw):
31 """Return help topics matching kw.
32
33 Returns {'section': [(name, summary), ...], ...} where section is
34 one of topics, commands, extensions, or extensioncommands.
35 """
36 kw = encoding.lower(kw)
37 def lowercontains(container):
38 return kw in encoding.lower(_(container))
39 results = {'topics': [],
40 'commands': [],
41 'extensions': [],
42 'extensioncommands': [],
43 }
44 for names, header, doc in helptable:
45 if (sum(map(lowercontains, names))
46 or lowercontains(header)
47 or lowercontains(doc())):
48 results['topics'].append((names[0], header))
49 import commands # avoid cycle
50 for cmd, entry in commands.table.iteritems():
51 if cmd.startswith('debug'):
52 continue
53 if len(entry) == 3:
54 summary = entry[2]
55 else:
56 summary = ''
57 docs = getattr(entry[0], '__doc__', None) or ''
58 if kw in cmd or lowercontains(summary) or lowercontains(docs):
59 doclines = _(docs).splitlines()
60 if doclines:
61 summary = doclines[0]
62 cmdname = cmd.split('|')[0].lstrip('^')
63 results['commands'].append((cmdname, summary))
64 for name, docs in itertools.chain(
65 extensions.enabled().iteritems(),
66 extensions.disabled().iteritems()):
67 # extensions.load ignores the UI argument
68 mod = extensions.load(None, name, '')
69 if lowercontains(name) or lowercontains(docs):
70 results['extensions'].append((name, _(docs).splitlines()[0]))
71 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
72 if kw in cmd or lowercontains(entry[2]):
73 cmdname = cmd.split('|')[0].lstrip('^')
74 results['extensioncommands'].append(
75 (cmdname, _(getattr(cmd, '__doc__', ''))))
76 return results
77
30 78 def loaddoc(topic):
31 79 """Return a delayed loader for help/topic.txt."""
32 80
33 81 def loader():
34 82 if util.mainfrozen():
35 83 module = sys.executable
36 84 else:
37 85 module = __file__
38 86 base = os.path.dirname(module)
39 87
40 88 for dir in ('.', '..'):
41 89 docdir = os.path.join(base, dir, 'help')
42 90 if os.path.isdir(docdir):
43 91 break
44 92
45 93 path = os.path.join(docdir, topic + ".txt")
46 94 doc = gettext(util.readfile(path))
47 95 for rewriter in helphooks.get(topic, []):
48 96 doc = rewriter(topic, doc)
49 97 return doc
50 98
51 99 return loader
52 100
53 101 helptable = sorted([
54 102 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
55 103 (["dates"], _("Date Formats"), loaddoc('dates')),
56 104 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
57 105 (['environment', 'env'], _('Environment Variables'),
58 106 loaddoc('environment')),
59 107 (['revs', 'revisions'], _('Specifying Single Revisions'),
60 108 loaddoc('revisions')),
61 109 (['mrevs', 'multirevs'], _('Specifying Multiple Revisions'),
62 110 loaddoc('multirevs')),
63 111 (['revset', 'revsets'], _("Specifying Revision Sets"), loaddoc('revsets')),
64 112 (['fileset', 'filesets'], _("Specifying File Sets"), loaddoc('filesets')),
65 113 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
66 114 (['merge-tools'], _('Merge Tools'), loaddoc('merge-tools')),
67 115 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
68 116 loaddoc('templates')),
69 117 (['urls'], _('URL Paths'), loaddoc('urls')),
70 118 (["extensions"], _("Using Additional Features"), extshelp),
71 119 (["subrepo", "subrepos"], _("Subrepositories"), loaddoc('subrepos')),
72 120 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
73 121 (["glossary"], _("Glossary"), loaddoc('glossary')),
74 122 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
75 123 loaddoc('hgignore')),
76 124 (["phases"], _("Working with Phases"), loaddoc('phases')),
77 125 ])
78 126
79 127 # Map topics to lists of callable taking the current topic help and
80 128 # returning the updated version
81 129 helphooks = {}
82 130
83 131 def addtopichook(topic, rewriter):
84 132 helphooks.setdefault(topic, []).append(rewriter)
85 133
86 134 def makeitemsdoc(topic, doc, marker, items):
87 135 """Extract docstring from the items key to function mapping, build a
88 136 .single documentation block and use it to overwrite the marker in doc
89 137 """
90 138 entries = []
91 139 for name in sorted(items):
92 140 text = (items[name].__doc__ or '').rstrip()
93 141 if not text:
94 142 continue
95 143 text = gettext(text)
96 144 lines = text.splitlines()
97 145 doclines = [(lines[0])]
98 146 for l in lines[1:]:
99 147 # Stop once we find some Python doctest
100 148 if l.strip().startswith('>>>'):
101 149 break
102 150 doclines.append(' ' + l.strip())
103 151 entries.append('\n'.join(doclines))
104 152 entries = '\n\n'.join(entries)
105 153 return doc.replace(marker, entries)
106 154
107 155 def addtopicsymbols(topic, marker, symbols):
108 156 def add(topic, doc):
109 157 return makeitemsdoc(topic, doc, marker, symbols)
110 158 addtopichook(topic, add)
111 159
112 160 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
113 161 addtopicsymbols('merge-tools', '.. internaltoolsmarker', filemerge.internals)
114 162 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
115 163 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
116 164 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
General Comments 0
You need to be logged in to leave comments. Login now