hgext/show.py
changeset 31765 264baeef3588
child 31820 45761ef1bc93
equal deleted inserted replaced
31764:15707e58fc3d 31765:264baeef3588
       
     1 # show.py - Extension implementing `hg show`
       
     2 #
       
     3 # Copyright 2017 Gregory Szorc <gregory.szorc@gmail.com>
       
     4 #
       
     5 # This software may be used and distributed according to the terms of the
       
     6 # GNU General Public License version 2 or any later version.
       
     7 
       
     8 """unified command to show various repository information (EXPERIMENTAL)
       
     9 
       
    10 This extension provides the :hg:`show` command, which provides a central
       
    11 command for displaying commonly-accessed repository data and views of that
       
    12 data.
       
    13 """
       
    14 
       
    15 from __future__ import absolute_import
       
    16 
       
    17 from mercurial.i18n import _
       
    18 from mercurial import (
       
    19     cmdutil,
       
    20     commands,
       
    21     error,
       
    22     registrar,
       
    23 )
       
    24 
       
    25 # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
       
    26 # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
       
    27 # be specifying the version(s) of Mercurial they are tested with, or
       
    28 # leave the attribute unspecified.
       
    29 testedwith = 'ships-with-hg-core'
       
    30 
       
    31 cmdtable = {}
       
    32 command = cmdutil.command(cmdtable)
       
    33 
       
    34 class showcmdfunc(registrar._funcregistrarbase):
       
    35     """Register a function to be invoked for an `hg show <thing>`."""
       
    36 
       
    37     # Used by _formatdoc().
       
    38     _docformat = '%s -- %s'
       
    39 
       
    40     def _extrasetup(self, name, func, fmtopic=None):
       
    41         """Called with decorator arguments to register a show view.
       
    42 
       
    43         ``name`` is the sub-command name.
       
    44 
       
    45         ``func`` is the function being decorated.
       
    46 
       
    47         ``fmtopic`` is the topic in the style that will be rendered for
       
    48         this view.
       
    49         """
       
    50         func._fmtopic = fmtopic
       
    51 
       
    52 showview = showcmdfunc()
       
    53 
       
    54 @command('show', commands.formatteropts, _('VIEW'))
       
    55 def show(ui, repo, view=None, template=None):
       
    56     """show various repository information
       
    57 
       
    58     A requested view of repository data is displayed.
       
    59 
       
    60     If no view is requested, the list of available views is shown and the
       
    61     command aborts.
       
    62 
       
    63     .. note::
       
    64 
       
    65        There are no backwards compatibility guarantees for the output of this
       
    66        command. Output may change in any future Mercurial release.
       
    67 
       
    68        Consumers wanting stable command output should specify a template via
       
    69        ``-T/--template``.
       
    70 
       
    71     List of available views:
       
    72 
       
    73     """
       
    74     if ui.plain() and not template:
       
    75         raise error.Abort(_('"hg show" cannot be used in plain mode because '
       
    76                             'output is not stable'),
       
    77                           hint=_('unset HGPLAIN and invoke with -T/--template '
       
    78                                  'to control output'))
       
    79 
       
    80     views = showview._table
       
    81 
       
    82     if not view:
       
    83         ui.pager('show')
       
    84         # TODO consider using formatter here so available views can be
       
    85         # rendered to custom format.
       
    86         ui.write(_('available views:\n'))
       
    87         ui.write('\n')
       
    88 
       
    89         for name, func in sorted(views.items()):
       
    90             ui.write(('%s\n') % func.__doc__)
       
    91 
       
    92         ui.write('\n')
       
    93         raise error.Abort(_('no view requested'),
       
    94                           hint=_('use "hg show VIEW" to choose a view'))
       
    95 
       
    96     # TODO use same logic as dispatch to perform prefix matching.
       
    97     if view not in views:
       
    98         raise error.Abort(_('unknown view: %s') % view,
       
    99                           hint=_('run "hg show" to see available views'))
       
   100 
       
   101     template = template or 'show'
       
   102     fmtopic = 'show%s' % views[view]._fmtopic
       
   103 
       
   104     ui.pager('show')
       
   105     with ui.formatter(fmtopic, {'template': template}) as fm:
       
   106         return views[view](ui, repo, fm)
       
   107 
       
   108 @showview('bookmarks', fmtopic='bookmarks')
       
   109 def showbookmarks(ui, repo, fm):
       
   110     """bookmarks and their associated changeset"""
       
   111     marks = repo._bookmarks
       
   112     if not len(marks):
       
   113         # TODO json output is corrupted; consider using formatter
       
   114         ui.write(_('(no bookmarks set)\n'))
       
   115         return
       
   116 
       
   117     active = repo._activebookmark
       
   118     longestname = max(len(b) for b in marks)
       
   119     # TODO consider exposing longest shortest(node).
       
   120 
       
   121     for bm, node in sorted(marks.items()):
       
   122         fm.startitem()
       
   123         fm.context(ctx=repo[node])
       
   124         fm.write('bookmark', '%s', bm)
       
   125         fm.write('node', fm.hexfunc(node), fm.hexfunc(node))
       
   126         fm.data(active=bm == active,
       
   127                 longestbookmarklen=longestname)
       
   128 
       
   129 # Adjust the docstring of the show command so it shows all registered views.
       
   130 # This is a bit hacky because it runs at the end of module load. When moved
       
   131 # into core or when another extension wants to provide a view, we'll need
       
   132 # to do this more robustly.
       
   133 # TODO make this more robust.
       
   134 longest = max(map(len, showview._table.keys()))
       
   135 for key in sorted(showview._table.keys()):
       
   136     cmdtable['show'][0].__doc__ += ' %s   %s\n' % (
       
   137         key.ljust(longest), showview._table[key]._origdoc)