~bzr-pqm/bzr/bzr.dev

« back to all changes in this revision

Viewing changes to bzrlib/help_topics.py

  • Committer: Canonical.com Patch Queue Manager
  • Date: 2007-08-07 06:13:16 UTC
  • mfrom: (2674.1.2 ianc-integration)
  • Revision ID: pqm@pqm.ubuntu.com-20070807061316-b32atzzop4r4y21g
(Ian Clatworthy) Bazaar User Reference

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 
19
19
Help topics are meant to be help for items that aren't commands, but will
20
20
help bzr become fully learnable without referring to a tutorial.
 
21
 
 
22
Limited formatting of help text is permitted to make the text useful
 
23
both within the reference manual (reStructuredText) and on the screen.
 
24
The help text should be reStructuredText with formatting kept to a
 
25
minimum and, in particular, no headings. The onscreen renderer applies
 
26
the following simple rules before rendering the text:
 
27
 
 
28
    1. A '::' appearing on the end of a line is replaced with ':'.
 
29
    2. Lines starting with a ':' have it stripped.
 
30
 
 
31
These rules mean that literal blocks and field lists respectively can
 
32
be used in the help text, producing sensible input to a manual while
 
33
rendering on the screen naturally.
21
34
"""
22
35
 
23
36
from bzrlib import registry
24
37
 
25
38
 
 
39
# Section identifiers (map topics to the right place in the manual)
 
40
SECT_COMMAND = "command"
 
41
SECT_CONCEPT = "concept"
 
42
SECT_HIDDEN =  "hidden"
 
43
SECT_LIST    = "list"
 
44
SECT_PLUGIN  = "plugin"
 
45
 
 
46
 
26
47
class HelpTopicRegistry(registry.Registry):
27
48
    """A Registry customized for handling help topics."""
28
49
 
29
 
    def register(self, topic, detail, summary):
 
50
    def register(self, topic, detail, summary, section=SECT_LIST):
30
51
        """Register a new help topic.
31
52
 
32
53
        :param topic: Name of documentation entry
33
54
        :param detail: Function or string object providing detailed
34
55
            documentation for topic.  Function interface is detail(topic).
35
56
            This should return a text string of the detailed information.
 
57
            See the module documentation for details on help text formatting.
36
58
        :param summary: String providing single-line documentation for topic.
 
59
        :param section: Section in reference manual - see SECT_* identifiers.
37
60
        """
38
 
        # The detail is stored as the 'object' and the 
39
 
        super(HelpTopicRegistry, self).register(topic, detail, info=summary)
 
61
        # The detail is stored as the 'object' and the metadata as the info
 
62
        info=(summary,section)
 
63
        super(HelpTopicRegistry, self).register(topic, detail, info=info)
40
64
 
41
 
    def register_lazy(self, topic, module_name, member_name, summary):
 
65
    def register_lazy(self, topic, module_name, member_name, summary,
 
66
                      section=SECT_LIST):
42
67
        """Register a new help topic, and import the details on demand.
43
68
 
44
69
        :param topic: Name of documentation entry
45
70
        :param module_name: The module to find the detailed help.
46
71
        :param member_name: The member of the module to use for detailed help.
47
72
        :param summary: String providing single-line documentation for topic.
 
73
        :param section: Section in reference manual - see SECT_* identifiers.
48
74
        """
 
75
        # The detail is stored as the 'object' and the metadata as the info
 
76
        info=(summary,section)
49
77
        super(HelpTopicRegistry, self).register_lazy(topic, module_name,
50
 
                                                     member_name, info=summary)
 
78
                                                     member_name, info=info)
51
79
 
52
80
    def get_detail(self, topic):
53
81
        """Get the detailed help on a given topic."""
59
87
 
60
88
    def get_summary(self, topic):
61
89
        """Get the single line summary for the topic."""
62
 
        return self.get_info(topic)
 
90
        info = self.get_info(topic)
 
91
        if info is None:
 
92
            return None
 
93
        else:
 
94
            return info[0]
 
95
 
 
96
    def get_section(self, topic):
 
97
        """Get the section for the topic."""
 
98
        info = self.get_info(topic)
 
99
        if info is None:
 
100
            return None
 
101
        else:
 
102
            return info[1]
 
103
 
 
104
    def get_topics_for_section(self, section):
 
105
        """Get the set of topics in a section."""
 
106
        result = set()
 
107
        for topic in self.keys():
 
108
            if section == self.get_section(topic):
 
109
                result.add(topic)
 
110
        return result
63
111
 
64
112
 
65
113
topic_registry = HelpTopicRegistry()
81
129
 
82
130
 
83
131
def _help_on_revisionspec(name):
84
 
    """Write the summary help for all documented topics to outfile."""
 
132
    """Generate the help for revision specs."""
 
133
    import re
85
134
    import bzrlib.revisionspec
86
135
 
87
136
    out = []
88
 
    out.append("\nRevision prefix specifier:"
89
 
               "\n--------------------------\n")
 
137
    out.append("Revision Identifiers\n")
 
138
    out.append("A revision, or a range bound, can be one of the following.\n")
 
139
    details = []
 
140
    details.append("\nFurther details are given below.\n")
90
141
 
 
142
    # The help text is indented 4 spaces - this re cleans that up below
 
143
    indent_re = re.compile(r'^    ', re.MULTILINE)
91
144
    for i in bzrlib.revisionspec.SPEC_TYPES:
92
145
        doc = i.help_txt
93
146
        if doc == bzrlib.revisionspec.RevisionSpec.help_txt:
94
 
            doc = "N/A\n"
95
 
        while (doc[-2:] == '\n\n' or doc[-1:] == ' '):
96
 
            doc = doc[:-1]
97
 
 
98
 
        out.append("  %s %s\n\n" % (i.prefix, doc))
99
 
 
100
 
    return ''.join(out)
 
147
            summary = "N/A"
 
148
            doc = summary + "\n"
 
149
        else:
 
150
            # Extract out the top line summary from the body and
 
151
            # clean-up the unwanted whitespace
 
152
            summary,doc = doc.split("\n", 1)
 
153
            #doc = indent_re.sub('', doc)
 
154
            while (doc[-2:] == '\n\n' or doc[-1:] == ' '):
 
155
                doc = doc[:-1]
 
156
        
 
157
        # Note: The leading : here are HACKs to get reStructuredText
 
158
        # 'field' formatting - we know that the prefix ends in a ':'.
 
159
        out.append(":%s\n\t%s" % (i.prefix, summary))
 
160
        details.append(":%s\n%s" % (i.prefix, doc))
 
161
 
 
162
    return '\n'.join(out + details)
101
163
 
102
164
 
103
165
def _help_on_transport(name):
122
184
        else:
123
185
            return 0
124
186
 
125
 
    out = []
126
187
    protl = []
127
188
    decl = []
128
189
    protos = transport_list_registry.keys( )
132
193
        if not shorthelp:
133
194
            continue
134
195
        if proto.endswith("://"):
135
 
            protl.extend(add_string(proto, shorthelp, 79))
 
196
            protl.append(add_string(proto, shorthelp, 79))
136
197
        else:
137
 
            decl.extend(add_string(proto, shorthelp, 79))
138
 
 
139
 
 
140
 
    out = "\nSupported URL prefix\n--------------------\n" + \
141
 
            ''.join(protl)
 
198
            decl.append(add_string(proto, shorthelp, 79))
 
199
 
 
200
 
 
201
    out = "URL Identifiers\n\n" + \
 
202
            "Supported URL prefixes::\n\n  " + \
 
203
            '  '.join(protl)
142
204
 
143
205
    if len(decl):
144
 
        out += "\nSupported modifiers\n-------------------\n" + \
145
 
            ''.join(decl)
 
206
        out += "\nSupported modifiers::\n\n  " + \
 
207
            '  '.join(decl)
146
208
 
147
209
    return out
148
210
 
149
211
 
150
 
_basic_help= \
 
212
_basic_help = \
151
213
"""Bazaar -- a free distributed version-control tool
152
214
http://bazaar-vcs.org/
153
215
 
174
236
"""
175
237
 
176
238
 
177
 
_global_options =\
 
239
_global_options = \
178
240
"""Global Options
179
241
 
180
242
These options may be used with any command, and may appear in front of any
268
330
would like to convert your heavy checkout into a normal branch so that every
269
331
commit is local, you can use the "unbind" command.
270
332
 
271
 
Related commands:
 
333
Related commands::
272
334
 
273
335
  checkout    Create a checkout. Pass --lightweight to get a lightweight
274
336
              checkout
318
380
the branches will not have working trees pass the '--no-trees' option to
319
381
'init-repository'.
320
382
 
321
 
Related commands:
 
383
Related commands::
322
384
 
323
385
  init-repository   Create a shared repository. Use --no-trees to create one
324
386
                    in which new branches won't get a working tree.
358
420
is also a 'push-and-update' plugin that automates running 'bzr update' via SSH
359
421
after each push.
360
422
 
361
 
Useful commands:
 
423
Useful commands::
362
424
 
363
425
  checkout     Create a working tree when a branch does not have one.
364
426
  remove-tree  Removes the working tree from a branch when it is safe to do so.
370
432
"""Status Flags
371
433
 
372
434
Status flags are used to summarise changes to the working tree in a concise
373
 
manner.  They are in the form:
 
435
manner.  They are in the form::
 
436
 
374
437
   xxx   <filename>
 
438
 
375
439
where the columns' meanings are as follows.
376
440
 
377
 
Column 1: versioning / renames
 
441
Column 1 - versioning/renames::
 
442
 
378
443
  + File versioned
379
444
  - File unversioned
380
445
  R File renamed
382
447
  C File has conflicts
383
448
  P Entry for a pending merge (not a file)
384
449
 
385
 
Column 2: Contents
 
450
Column 2 - contents::
 
451
 
386
452
  N File created
387
453
  D File deleted
388
454
  K File kind changed
389
455
  M File modified
390
456
 
391
 
Column 3: Execute
 
457
Column 3 - execute::
 
458
 
392
459
  * The execute bit was changed
393
460
"""
394
461
 
395
462
 
 
463
_env_variables = \
 
464
"""Environment Variables
 
465
 
 
466
================ =================================================================
 
467
BZRPATH          Path where bzr is to look for shell plugin external commands.
 
468
BZR_EMAIL        E-Mail address of the user. Overrides EMAIL.
 
469
EMAIL            E-Mail address of the user.
 
470
BZR_EDITOR       Editor for editing commit messages. Overrides EDITOR.
 
471
EDITOR           Editor for editing commit messages.
 
472
BZR_PLUGIN_PATH  Paths where bzr should look for plugins.
 
473
BZR_HOME         Directory holding .bazaar config dir. Overrides HOME.
 
474
BZR_HOME (Win32) Directory holding bazaar config dir. Overrides APPDATA and HOME.
 
475
================ =================================================================
 
476
"""
 
477
 
 
478
 
 
479
_files = \
 
480
r"""Files
 
481
 
 
482
:On Linux:   ~/.bazaar/bazaar.conf
 
483
:On Windows: C:\\Documents and Settings\\username\\Application Data\\bazaar\\2.0\\bazaar.conf
 
484
 
 
485
Contains the user's default configuration. The section ``[DEFAULT]`` is
 
486
used to define general configuration that will be applied everywhere.
 
487
The section ``[ALIASES]`` can be used to create command aliases for
 
488
commonly used options.
 
489
 
 
490
A typical config file might look something like::
 
491
 
 
492
  [DEFAULT]
 
493
  email=John Doe <jdoe@isp.com>
 
494
 
 
495
  [ALIASES]
 
496
  commit = commit --strict
 
497
  log10 = log --short -r -10..-1
 
498
"""
 
499
 
 
500
 
396
501
topic_registry.register("revisionspec", _help_on_revisionspec,
397
502
                        "Explain how to use --revision")
398
 
topic_registry.register('basic', _basic_help, "Basic commands")
399
 
topic_registry.register('topics', _help_on_topics, "Topics list")
 
503
topic_registry.register('basic', _basic_help, "Basic commands", SECT_HIDDEN)
 
504
topic_registry.register('topics', _help_on_topics, "Topics list", SECT_HIDDEN)
400
505
def get_format_topic(topic):
401
506
    from bzrlib import bzrdir
402
 
    return bzrdir.format_registry.help_topic(topic)
 
507
    return "Storage Formats\n\n" + bzrdir.format_registry.help_topic(topic)
403
508
topic_registry.register('formats', get_format_topic, 'Directory formats')
404
509
topic_registry.register('global-options', _global_options,
405
510
                        'Options that can be used with any command')
406
511
topic_registry.register('checkouts', _checkouts,
407
 
                        'Information on what a checkout is')
 
512
                        'Information on what a checkout is', SECT_CONCEPT)
408
513
topic_registry.register('urlspec', _help_on_transport,
409
514
                        "Supported transport protocols")
410
515
topic_registry.register('status-flags', _status_flags,
411
516
                        "Help on status flags")
412
517
def get_bugs_topic(topic):
413
518
    from bzrlib import bugtracker
414
 
    return bugtracker.tracker_registry.help_topic(topic)
 
519
    return "Bug Trackers\n\n" + bugtracker.tracker_registry.help_topic(topic)
415
520
topic_registry.register('bugs', get_bugs_topic, 'Bug tracker support')
416
521
topic_registry.register('repositories', _repositories,
417
 
                        'Basic information on shared repositories.')
 
522
                        'Basic information on shared repositories.',
 
523
                        SECT_CONCEPT)
418
524
topic_registry.register('working-trees', _working_trees,
419
 
                        'Information on working trees')
 
525
                        'Information on working trees', SECT_CONCEPT)
 
526
topic_registry.register('env-variables', _env_variables,
 
527
                        'Environment variable names and values')
 
528
topic_registry.register('files', _files,
 
529
                        'Information on configuration and log files')
420
530
 
421
531
 
422
532
class HelpTopicIndex(object):
454
564
        """
455
565
        self.topic = topic
456
566
 
457
 
    def get_help_text(self, additional_see_also=None):
 
567
    def get_help_text(self, additional_see_also=None, plain=True):
458
568
        """Return a string with the help for this topic.
459
569
 
460
570
        :param additional_see_also: Additional help topics to be
461
571
            cross-referenced.
 
572
        :param plain: if False, raw help (reStructuredText) is
 
573
            returned instead of plain text.
462
574
        """
463
575
        result = topic_registry.get_detail(self.topic)
464
576
        # there is code duplicated here and in bzrlib/plugin.py's 
469
581
        else:
470
582
            see_also = None
471
583
        if see_also:
472
 
            result += '\nSee also: '
 
584
            result += '\n:See also: '
473
585
            result += ', '.join(see_also)
474
586
            result += '\n'
 
587
        if plain:
 
588
            result = help_as_plain_text(result)
475
589
        return result
476
590
 
477
591
    def get_help_topic(self):
478
592
        """Return the help topic this can be found under."""
479
593
        return self.topic
480
594
 
 
595
 
 
596
def help_as_plain_text(text):
 
597
    """Minimal converter of reStructuredText to plain text."""
 
598
    lines = text.splitlines()
 
599
    result = []
 
600
    for line in lines:
 
601
        if line.startswith(':'):
 
602
            line = line[1:]
 
603
        elif line.endswith('::'):
 
604
            line = line[:-1]
 
605
        result.append(line)
 
606
    return "\n".join(result) + "\n"