##// END OF EJS Templates
help: fix search with `-k` option in non-ASCII locales...
Nikolaj Sjujskij -
r16845:4594729c default
parent child Browse files
Show More
@@ -1,199 +1,201
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 9 import itertools, sys, os
10 10 import extensions, revset, fileset, templatekw, templatefilters, filemerge
11 11 import encoding, util, minirst
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 30 def optrst(options, verbose):
31 31 data = []
32 32 multioccur = False
33 33 for option in options:
34 34 if len(option) == 5:
35 35 shortopt, longopt, default, desc, optlabel = option
36 36 else:
37 37 shortopt, longopt, default, desc = option
38 38 optlabel = _("VALUE") # default label
39 39
40 40 if _("DEPRECATED") in desc and not verbose:
41 41 continue
42 42
43 43 so = ''
44 44 if shortopt:
45 45 so = '-' + shortopt
46 46 lo = '--' + longopt
47 47 if default:
48 48 desc += _(" (default: %s)") % default
49 49
50 50 if isinstance(default, list):
51 51 lo += " %s [+]" % optlabel
52 52 multioccur = True
53 53 elif (default is not None) and not isinstance(default, bool):
54 54 lo += " %s" % optlabel
55 55
56 56 data.append((so, lo, desc))
57 57
58 58 rst = minirst.maketable(data, 1)
59 59
60 60 if multioccur:
61 61 rst.append(_("\n[+] marked option can be specified multiple times\n"))
62 62
63 63 return ''.join(rst)
64 64
65 65 def topicmatch(kw):
66 66 """Return help topics matching kw.
67 67
68 68 Returns {'section': [(name, summary), ...], ...} where section is
69 69 one of topics, commands, extensions, or extensioncommands.
70 70 """
71 71 kw = encoding.lower(kw)
72 72 def lowercontains(container):
73 return kw in encoding.lower(_(container))
73 return kw in encoding.lower(container) # translated in helptable
74 74 results = {'topics': [],
75 75 'commands': [],
76 76 'extensions': [],
77 77 'extensioncommands': [],
78 78 }
79 79 for names, header, doc in helptable:
80 80 if (sum(map(lowercontains, names))
81 81 or lowercontains(header)
82 82 or lowercontains(doc())):
83 83 results['topics'].append((names[0], header))
84 84 import commands # avoid cycle
85 85 for cmd, entry in commands.table.iteritems():
86 86 if cmd.startswith('debug'):
87 87 continue
88 88 if len(entry) == 3:
89 89 summary = entry[2]
90 90 else:
91 91 summary = ''
92 docs = getattr(entry[0], '__doc__', None) or ''
92 # translate docs *before* searching there
93 docs = _(getattr(entry[0], '__doc__', None)) or ''
93 94 if kw in cmd or lowercontains(summary) or lowercontains(docs):
94 doclines = _(docs).splitlines()
95 doclines = docs.splitlines()
95 96 if doclines:
96 97 summary = doclines[0]
97 98 cmdname = cmd.split('|')[0].lstrip('^')
98 99 results['commands'].append((cmdname, summary))
99 100 for name, docs in itertools.chain(
100 101 extensions.enabled().iteritems(),
101 102 extensions.disabled().iteritems()):
102 103 # extensions.load ignores the UI argument
103 104 mod = extensions.load(None, name, '')
104 105 if lowercontains(name) or lowercontains(docs):
105 results['extensions'].append((name, _(docs).splitlines()[0]))
106 # extension docs are already translated
107 results['extensions'].append((name, docs.splitlines()[0]))
106 108 for cmd, entry in getattr(mod, 'cmdtable', {}).iteritems():
107 109 if kw in cmd or (len(entry) > 2 and lowercontains(entry[2])):
108 110 cmdname = cmd.split('|')[0].lstrip('^')
109 111 results['extensioncommands'].append(
110 112 (cmdname, _(getattr(cmd, '__doc__', ''))))
111 113 return results
112 114
113 115 def loaddoc(topic):
114 116 """Return a delayed loader for help/topic.txt."""
115 117
116 118 def loader():
117 119 if util.mainfrozen():
118 120 module = sys.executable
119 121 else:
120 122 module = __file__
121 123 base = os.path.dirname(module)
122 124
123 125 for dir in ('.', '..'):
124 126 docdir = os.path.join(base, dir, 'help')
125 127 if os.path.isdir(docdir):
126 128 break
127 129
128 130 path = os.path.join(docdir, topic + ".txt")
129 131 doc = gettext(util.readfile(path))
130 132 for rewriter in helphooks.get(topic, []):
131 133 doc = rewriter(topic, doc)
132 134 return doc
133 135
134 136 return loader
135 137
136 138 helptable = sorted([
137 139 (["config", "hgrc"], _("Configuration Files"), loaddoc('config')),
138 140 (["dates"], _("Date Formats"), loaddoc('dates')),
139 141 (["patterns"], _("File Name Patterns"), loaddoc('patterns')),
140 142 (['environment', 'env'], _('Environment Variables'),
141 143 loaddoc('environment')),
142 144 (['revs', 'revisions'], _('Specifying Single Revisions'),
143 145 loaddoc('revisions')),
144 146 (['mrevs', 'multirevs'], _('Specifying Multiple Revisions'),
145 147 loaddoc('multirevs')),
146 148 (['revset', 'revsets'], _("Specifying Revision Sets"), loaddoc('revsets')),
147 149 (['fileset', 'filesets'], _("Specifying File Sets"), loaddoc('filesets')),
148 150 (['diffs'], _('Diff Formats'), loaddoc('diffs')),
149 151 (['merge-tools'], _('Merge Tools'), loaddoc('merge-tools')),
150 152 (['templating', 'templates', 'template', 'style'], _('Template Usage'),
151 153 loaddoc('templates')),
152 154 (['urls'], _('URL Paths'), loaddoc('urls')),
153 155 (["extensions"], _("Using Additional Features"), extshelp),
154 156 (["subrepo", "subrepos"], _("Subrepositories"), loaddoc('subrepos')),
155 157 (["hgweb"], _("Configuring hgweb"), loaddoc('hgweb')),
156 158 (["glossary"], _("Glossary"), loaddoc('glossary')),
157 159 (["hgignore", "ignore"], _("Syntax for Mercurial Ignore Files"),
158 160 loaddoc('hgignore')),
159 161 (["phases"], _("Working with Phases"), loaddoc('phases')),
160 162 ])
161 163
162 164 # Map topics to lists of callable taking the current topic help and
163 165 # returning the updated version
164 166 helphooks = {}
165 167
166 168 def addtopichook(topic, rewriter):
167 169 helphooks.setdefault(topic, []).append(rewriter)
168 170
169 171 def makeitemsdoc(topic, doc, marker, items):
170 172 """Extract docstring from the items key to function mapping, build a
171 173 .single documentation block and use it to overwrite the marker in doc
172 174 """
173 175 entries = []
174 176 for name in sorted(items):
175 177 text = (items[name].__doc__ or '').rstrip()
176 178 if not text:
177 179 continue
178 180 text = gettext(text)
179 181 lines = text.splitlines()
180 182 doclines = [(lines[0])]
181 183 for l in lines[1:]:
182 184 # Stop once we find some Python doctest
183 185 if l.strip().startswith('>>>'):
184 186 break
185 187 doclines.append(' ' + l.strip())
186 188 entries.append('\n'.join(doclines))
187 189 entries = '\n\n'.join(entries)
188 190 return doc.replace(marker, entries)
189 191
190 192 def addtopicsymbols(topic, marker, symbols):
191 193 def add(topic, doc):
192 194 return makeitemsdoc(topic, doc, marker, symbols)
193 195 addtopichook(topic, add)
194 196
195 197 addtopicsymbols('filesets', '.. predicatesmarker', fileset.symbols)
196 198 addtopicsymbols('merge-tools', '.. internaltoolsmarker', filemerge.internals)
197 199 addtopicsymbols('revsets', '.. predicatesmarker', revset.symbols)
198 200 addtopicsymbols('templates', '.. keywordsmarker', templatekw.keywords)
199 201 addtopicsymbols('templates', '.. filtersmarker', templatefilters.filters)
General Comments 0
You need to be logged in to leave comments. Login now