Mercurial > hg
comparison mercurial/minirst.py @ 10065:a1ae0ed78d1a
minirst: improve layout of field lists
Before, we used the padding following the key to compute where to wrap
the text. Long keys would thus give a big indentation. It also
required careful alignment of the source text, making it cumbersome to
items to the list.
We now compute the maximum key length and use that for all items in
the list. We also put a cap on the indentation: keys longer than 10
characters are put on their own line. This is similar to how rst2html
handles large keys: it uses 14 as the cutoff point, but I felt that 10
was better for monospaced text in the console.
author | Martin Geisler <mg@lazybytes.net> |
---|---|
date | Sun, 13 Dec 2009 23:49:53 +0100 |
parents | 6f30c35766d6 |
children | d6512b3e9ac0 |
comparison
equal
deleted
inserted
replaced
10064:6f30c35766d6 | 10065:a1ae0ed78d1a |
---|---|
111 i += 1 | 111 i += 1 |
112 return blocks | 112 return blocks |
113 | 113 |
114 _bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)) ') | 114 _bulletre = re.compile(r'(-|[0-9A-Za-z]+\.|\(?[0-9A-Za-z]+\)) ') |
115 _optionre = re.compile(r'^(--[a-z-]+)((?:[ =][a-zA-Z][\w-]*)? +)(.*)$') | 115 _optionre = re.compile(r'^(--[a-z-]+)((?:[ =][a-zA-Z][\w-]*)? +)(.*)$') |
116 _fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):( +)(.*)') | 116 _fieldre = re.compile(r':(?![: ])([^:]*)(?<! ):[ ]+(.*)') |
117 _definitionre = re.compile(r'[^ ]') | 117 _definitionre = re.compile(r'[^ ]') |
118 | 118 |
119 def splitparagraphs(blocks): | 119 def splitparagraphs(blocks): |
120 """Split paragraphs into lists.""" | 120 """Split paragraphs into lists.""" |
121 # Tuples with (list type, item regexp, single line items?). Order | 121 # Tuples with (list type, item regexp, single line items?). Order |
154 indent=blocks[i]['indent'])) | 154 indent=blocks[i]['indent'])) |
155 items[-1]['lines'].append(line) | 155 items[-1]['lines'].append(line) |
156 blocks[i:i+1] = items | 156 blocks[i:i+1] = items |
157 break | 157 break |
158 i += 1 | 158 i += 1 |
159 return blocks | |
160 | |
161 | |
162 _fieldwidth = 12 | |
163 | |
164 def updatefieldlists(blocks): | |
165 """Find key and maximum key width for field lists.""" | |
166 i = 0 | |
167 while i < len(blocks): | |
168 if blocks[i]['type'] != 'field': | |
169 i += 1 | |
170 continue | |
171 | |
172 keywidth = 0 | |
173 j = i | |
174 while j < len(blocks) and blocks[j]['type'] == 'field': | |
175 m = _fieldre.match(blocks[j]['lines'][0]) | |
176 key, rest = m.groups() | |
177 blocks[j]['lines'][0] = rest | |
178 blocks[j]['key'] = key | |
179 keywidth = max(keywidth, len(key)) | |
180 j += 1 | |
181 | |
182 for block in blocks[i:j]: | |
183 block['keywidth'] = keywidth | |
184 i = j + 1 | |
185 | |
159 return blocks | 186 return blocks |
160 | 187 |
161 | 188 |
162 def findsections(blocks): | 189 def findsections(blocks): |
163 """Finds sections. | 190 """Finds sections. |
226 initindent = subindent = indent | 253 initindent = subindent = indent |
227 if block['type'] == 'bullet': | 254 if block['type'] == 'bullet': |
228 m = _bulletre.match(block['lines'][0]) | 255 m = _bulletre.match(block['lines'][0]) |
229 subindent = indent + m.end() * ' ' | 256 subindent = indent + m.end() * ' ' |
230 elif block['type'] == 'field': | 257 elif block['type'] == 'field': |
231 m = _fieldre.match(block['lines'][0]) | 258 keywidth = block['keywidth'] |
232 key, spaces, rest = m.groups() | 259 key = block['key'] |
233 # Turn ":foo: bar" into "foo bar". | 260 |
234 block['lines'][0] = '%s %s%s' % (key, spaces, rest) | 261 subindent = indent + _fieldwidth * ' ' |
235 subindent = indent + (2 + len(key) + len(spaces)) * ' ' | 262 if len(key) + 2 > _fieldwidth: |
263 # key too large, use full line width | |
264 key = key.ljust(width) | |
265 elif keywidth + 2 < _fieldwidth: | |
266 # all keys are small, add only two spaces | |
267 key = key.ljust(keywidth + 2) | |
268 subindent = indent + (keywidth + 2) * ' ' | |
269 else: | |
270 # mixed sizes, use fieldwidth for this one | |
271 key = key.ljust(_fieldwidth) | |
272 block['lines'][0] = key + block['lines'][0] | |
236 elif block['type'] == 'option': | 273 elif block['type'] == 'option': |
237 m = _optionre.match(block['lines'][0]) | 274 m = _optionre.match(block['lines'][0]) |
238 option, arg, rest = m.groups() | 275 option, arg, rest = m.groups() |
239 subindent = indent + (len(option) + len(arg)) * ' ' | 276 subindent = indent + (len(option) + len(arg)) * ' ' |
240 | 277 |
250 for b in blocks: | 287 for b in blocks: |
251 b['indent'] += indent | 288 b['indent'] += indent |
252 blocks = findliteralblocks(blocks) | 289 blocks = findliteralblocks(blocks) |
253 blocks = inlineliterals(blocks) | 290 blocks = inlineliterals(blocks) |
254 blocks = splitparagraphs(blocks) | 291 blocks = splitparagraphs(blocks) |
292 blocks = updatefieldlists(blocks) | |
255 blocks = findsections(blocks) | 293 blocks = findsections(blocks) |
256 blocks = addmargins(blocks) | 294 blocks = addmargins(blocks) |
257 return '\n'.join(formatblock(b, width) for b in blocks) | 295 return '\n'.join(formatblock(b, width) for b in blocks) |
258 | 296 |
259 | 297 |
270 text = open(sys.argv[1]).read() | 308 text = open(sys.argv[1]).read() |
271 blocks = debug(findblocks, text) | 309 blocks = debug(findblocks, text) |
272 blocks = debug(findliteralblocks, blocks) | 310 blocks = debug(findliteralblocks, blocks) |
273 blocks = debug(inlineliterals, blocks) | 311 blocks = debug(inlineliterals, blocks) |
274 blocks = debug(splitparagraphs, blocks) | 312 blocks = debug(splitparagraphs, blocks) |
313 blocks = debug(updatefieldlists, blocks) | |
275 blocks = debug(findsections, blocks) | 314 blocks = debug(findsections, blocks) |
276 blocks = debug(addmargins, blocks) | 315 blocks = debug(addmargins, blocks) |
277 print '\n'.join(formatblock(b, 30) for b in blocks) | 316 print '\n'.join(formatblock(b, 30) for b in blocks) |