/brz/remove-bazaar

To get this branch, use:
bzr branch http://gegoxaren.bato24.eu/bzr/brz/remove-bazaar

« back to all changes in this revision

Viewing changes to bzrlib/commands.py

  • Committer: Robert Collins
  • Date: 2007-08-22 00:00:26 UTC
  • mfrom: (2739 +trunk)
  • mto: (2592.3.96 repository)
  • mto: This revision was merged to the branch mainline in revision 2742.
  • Revision ID: robertc@robertcollins.net-20070822000026-kvufiqhlreokb1en
Merge bzr.dev

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
from bzrlib.symbol_versioning import (
52
52
    deprecated_function,
53
53
    deprecated_method,
54
 
    zero_eight,
55
 
    zero_eleven,
56
54
    )
57
55
# Compatibility
58
56
from bzrlib.option import Option
274
272
        s = s[:-1]
275
273
        return s
276
274
 
277
 
    def get_help_text(self, additional_see_also=None):
 
275
    def get_help_text(self, additional_see_also=None, plain=True,
 
276
                      see_also_as_links=False):
278
277
        """Return a text string with help for this command.
279
278
        
280
279
        :param additional_see_also: Additional help topics to be
281
280
            cross-referenced.
 
281
        :param plain: if False, raw help (reStructuredText) is
 
282
            returned instead of plain text.
 
283
        :param see_also_as_links: if True, convert items in 'See also'
 
284
            list to internal links (used by bzr_man rstx generator)
282
285
        """
283
286
        doc = self.help()
284
287
        if doc is None:
285
288
            raise NotImplementedError("sorry, no detailed help yet for %r" % self.name())
286
289
 
 
290
        # Extract the summary (purpose) and sections out from the text
 
291
        purpose,sections = self._get_help_parts(doc)
 
292
 
 
293
        # If a custom usage section was provided, use it
 
294
        if sections.has_key('Usage'):
 
295
            usage = sections.pop('Usage')
 
296
        else:
 
297
            usage = self._usage()
 
298
 
 
299
        # The header is the purpose and usage
287
300
        result = ""
288
 
        result += 'usage: %s\n' % self._usage()
289
 
 
 
301
        result += ':Purpose: %s\n' % purpose
 
302
        if usage.find('\n') >= 0:
 
303
            result += ':Usage:\n%s\n' % usage
 
304
        else:
 
305
            result += ':Usage:   %s\n' % usage
 
306
        result += '\n'
 
307
 
 
308
        # Add the options
 
309
        options = option.get_optparser(self.options()).format_option_help()
 
310
        if options.startswith('Options:'):
 
311
            result += ':' + options
 
312
        elif options.startswith('options:'):
 
313
            # Python 2.4 version of optparse
 
314
            result += ':Options:' + options[len('options:'):]
 
315
        else:
 
316
            result += options
 
317
        result += '\n'
 
318
 
 
319
        # Add the description, indenting it 2 spaces
 
320
        # to match the indentation of the options
 
321
        if sections.has_key(None):
 
322
            text = sections.pop(None)
 
323
            text = '\n  '.join(text.splitlines())
 
324
            result += ':%s:\n  %s\n\n' % ('Description',text)
 
325
 
 
326
        # Add the custom sections (e.g. Examples). Note that there's no need
 
327
        # to indent these as they must be indented already in the source.
 
328
        if sections:
 
329
            labels = sorted(sections.keys())
 
330
            for label in labels:
 
331
                result += ':%s:\n%s\n\n' % (label,sections[label])
 
332
 
 
333
        # Add the aliases, source (plug-in) and see also links, if any
290
334
        if self.aliases:
291
 
            result += 'aliases: '
 
335
            result += ':Aliases:  '
292
336
            result += ', '.join(self.aliases) + '\n'
293
 
 
294
 
        result += '\n'
295
 
 
296
337
        plugin_name = self.plugin_name()
297
338
        if plugin_name is not None:
298
 
            result += '(From plugin "%s")' % plugin_name
299
 
            result += '\n\n'
300
 
 
301
 
        result += doc
302
 
        if result[-1] != '\n':
303
 
            result += '\n'
304
 
        result += '\n'
305
 
        result += option.get_optparser(self.options()).format_option_help()
 
339
            result += ':From:     plugin "%s"\n' % plugin_name
306
340
        see_also = self.get_see_also(additional_see_also)
307
341
        if see_also:
308
 
            result += '\nSee also: '
309
 
            result += ', '.join(see_also)
310
 
            result += '\n'
 
342
            if not plain and see_also_as_links:
 
343
                see_also_links = []
 
344
                for item in see_also:
 
345
                    if item == 'topics':
 
346
                        # topics doesn't have an independent section
 
347
                        # so don't create a real link
 
348
                        see_also_links.append(item)
 
349
                    else:
 
350
                        # Use a reST link for this entry
 
351
                        see_also_links.append("`%s`_" % (item,))
 
352
                see_also = see_also_links
 
353
            result += ':See also: '
 
354
            result += ', '.join(see_also) + '\n'
 
355
 
 
356
        # If this will be rendered as plan text, convert it
 
357
        if plain:
 
358
            import bzrlib.help_topics
 
359
            result = bzrlib.help_topics.help_as_plain_text(result)
311
360
        return result
312
361
 
 
362
    @staticmethod
 
363
    def _get_help_parts(text):
 
364
        """Split help text into a summary and named sections.
 
365
 
 
366
        :return: (summary,sections) where summary is the top line and
 
367
            sections is a dictionary of the rest indexed by section name.
 
368
            A section starts with a heading line of the form ":xxx:".
 
369
            Indented text on following lines is the section value.
 
370
            All text found outside a named section is assigned to the
 
371
            default section which is given the key of None.
 
372
        """
 
373
        def save_section(sections, label, section):
 
374
            if len(section) > 0:
 
375
                if sections.has_key(label):
 
376
                    sections[label] += '\n' + section
 
377
                else:
 
378
                    sections[label] = section
 
379
            
 
380
        lines = text.rstrip().splitlines()
 
381
        summary = lines.pop(0)
 
382
        sections = {}
 
383
        label,section = None,''
 
384
        for line in lines:
 
385
            if line.startswith(':') and line.endswith(':') and len(line) > 2:
 
386
                save_section(sections, label, section)
 
387
                label,section = line[1:-1],''
 
388
            elif label != None and len(line) > 1 and not line[0].isspace():
 
389
                save_section(sections, label, section)
 
390
                label,section = None,line
 
391
            else:
 
392
                if len(section) > 0:
 
393
                    section += '\n' + line
 
394
                else:
 
395
                    section = line
 
396
        save_section(sections, label, section)
 
397
        return summary, sections
 
398
 
313
399
    def get_help_topic(self):
314
400
        """Return the commands help topic - its name."""
315
401
        return self.name()
316
402
 
317
403
    def get_see_also(self, additional_terms=None):
318
 
        """Return a list of help topics that are related to this ommand.
 
404
        """Return a list of help topics that are related to this command.
319
405
        
320
406
        The list is derived from the content of the _see_also attribute. Any
321
407
        duplicates are removed and the result is in lexical order.
423
509
            return None
424
510
 
425
511
 
426
 
# Technically, this function hasn't been use in a *really* long time
427
 
# but we are only deprecating it now.
428
 
@deprecated_function(zero_eleven)
429
 
def parse_spec(spec):
430
 
    """
431
 
    >>> parse_spec(None)
432
 
    [None, None]
433
 
    >>> parse_spec("./")
434
 
    ['./', None]
435
 
    >>> parse_spec("../@")
436
 
    ['..', -1]
437
 
    >>> parse_spec("../f/@35")
438
 
    ['../f', 35]
439
 
    >>> parse_spec('./@revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67')
440
 
    ['.', 'revid:john@arbash-meinel.com-20050711044610-3ca0327c6a222f67']
441
 
    """
442
 
    if spec is None:
443
 
        return [None, None]
444
 
    if '/@' in spec:
445
 
        parsed = spec.split('/@')
446
 
        assert len(parsed) == 2
447
 
        if parsed[1] == "":
448
 
            parsed[1] = -1
449
 
        else:
450
 
            try:
451
 
                parsed[1] = int(parsed[1])
452
 
            except ValueError:
453
 
                pass # We can allow stuff like ./@revid:blahblahblah
454
 
            else:
455
 
                assert parsed[1] >=0
456
 
    else:
457
 
        parsed = [spec, None]
458
 
    return parsed
459
 
 
460
512
def parse_args(command, argv, alias_argv=None):
461
513
    """Parse command line.
462
514