color.py
251 lines
| 8.0 KiB
| text/x-python
|
PythonLexer
/ hgext / color.py
|
r22771 | # color.py color output for Mercurial commands | ||
|
r5787 | # | ||
# Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com> | ||||
# | ||||
|
r15771 | # This software may be used and distributed according to the terms of the | ||
# GNU General Public License version 2 or any later version. | ||||
|
r5787 | |||
|
r8894 | '''colorize output from some commands | ||
|
r5787 | |||
|
r22771 | The color extension colorizes output from several Mercurial commands. | ||
For example, the diff command shows additions in green and deletions | ||||
in red, while the status command shows modified files in magenta. Many | ||||
other commands have analogous colors. It is possible to customize | ||||
these colors. | ||||
|
r7457 | |||
|
r22772 | Effects | ||
------- | ||||
|
r7988 | Other effects in addition to color, like bold and underlined text, are | ||
|
r13987 | also available. By default, the terminfo database is used to find the | ||
terminal codes used to change color and effect. If terminfo is not | ||||
available, then effects are rendered with the ECMA-48 SGR control | ||||
|
r13635 | function (aka ANSI escape codes). | ||
|
r5787 | |||
|
r22772 | The available effects in terminfo mode are 'blink', 'bold', 'dim', | ||
'inverse', 'invisible', 'italic', 'standout', and 'underline'; in | ||||
ECMA-48 mode, the options are 'bold', 'inverse', 'italic', and | ||||
'underline'. How each is rendered depends on the terminal emulator. | ||||
Some may not be available for a given terminal type, and will be | ||||
silently ignored. | ||||
|
r30176 | If the terminfo entry for your terminal is missing codes for an effect | ||
or has the wrong codes, you can add or override those codes in your | ||||
configuration:: | ||||
[color] | ||||
terminfo.dim = \E[2m | ||||
where '\E' is substituted with an escape character. | ||||
|
r22772 | Labels | ||
------ | ||||
|
r22462 | Text receives color effects depending on the labels that it has. Many | ||
default Mercurial commands emit labelled text. You can also define | ||||
your own labels in templates using the label function, see :hg:`help | ||||
templates`. A single portion of text may have more than one label. In | ||||
that case, effects given to the last label will override any other | ||||
effects. This includes the special "none" effect, which nullifies | ||||
other effects. | ||||
|
r22463 | Labels are normally invisible. In order to see these labels and their | ||
|
r22711 | position in the text, use the global --color=debug option. The same | ||
anchor text may be associated to multiple labels, e.g. | ||||
|
r22463 | |||
|
r22711 | [log.changeset changeset.secret|changeset: 22611:6f0a53c8f587] | ||
|
r22463 | |||
|
r22462 | The following are the default effects for some default labels. Default | ||
effects may be overridden from your configuration file:: | ||||
|
r5787 | |||
|
r9206 | [color] | ||
status.modified = blue bold underline red_background | ||||
status.added = green bold | ||||
status.removed = red bold blue_background | ||||
status.deleted = cyan bold underline | ||||
status.unknown = magenta bold underline | ||||
status.ignored = black bold | ||||
|
r5787 | |||
|
r9206 | # 'none' turns off all effects | ||
status.clean = none | ||||
status.copied = none | ||||
|
r5787 | |||
|
r9206 | qseries.applied = blue bold underline | ||
qseries.unapplied = black bold | ||||
qseries.missing = red bold | ||||
|
r7456 | |||
|
r9206 | diff.diffline = bold | ||
diff.extended = cyan bold | ||||
diff.file_a = red bold | ||||
diff.file_b = green bold | ||||
diff.hunk = magenta | ||||
diff.deleted = red | ||||
diff.inserted = green | ||||
diff.changed = white | ||||
|
r22710 | diff.tab = | ||
|
r9206 | diff.trailingwhitespace = bold red_background | ||
|
r10046 | |||
|
r22465 | # Blank so it inherits the style of the surrounding label | ||
changeset.public = | ||||
changeset.draft = | ||||
changeset.secret = | ||||
|
r10223 | resolve.unresolved = red bold | ||
resolve.resolved = green bold | ||||
|
r25347 | bookmarks.active = green | ||
|
r10870 | |||
|
r11969 | branches.active = none | ||
branches.closed = black bold | ||||
branches.current = green | ||||
branches.inactive = none | ||||
|
r15048 | tags.normal = green | ||
tags.local = black bold | ||||
|
r19214 | rebase.rebased = blue | ||
rebase.remaining = red bold | ||||
|
r19854 | shelve.age = cyan | ||
shelve.newest = green bold | ||||
shelve.name = blue bold | ||||
|
r19215 | histedit.remaining = red bold | ||
|
r22772 | Custom colors | ||
------------- | ||||
|
r14769 | |||
|
r13987 | Because there are only eight standard colors, this module allows you | ||
to define color names for other color slots which might be available | ||||
for your terminal type, assuming terminfo mode. For instance:: | ||||
color.brightblue = 12 | ||||
color.pink = 207 | ||||
color.orange = 202 | ||||
to set 'brightblue' to color slot 12 (useful for 16 color terminals | ||||
that have brighter colors defined in the upper eight) and, 'pink' and | ||||
'orange' to colors in 256-color xterm's default color cube. These | ||||
defined colors may then be used as any of the pre-defined eight, | ||||
including appending '_background' to set the background to that color. | ||||
|
r22772 | Modes | ||
----- | ||||
|
r14769 | By default, the color extension will use ANSI mode (or win32 mode on | ||
Windows) if it detects a terminal. To override auto mode (to enable | ||||
terminfo mode, for example), set the following configuration option:: | ||||
|
r10870 | |||
[color] | ||||
|
r14769 | mode = terminfo | ||
|
r10870 | |||
|
r13987 | Any value other than 'ansi', 'win32', 'terminfo', or 'auto' will | ||
disable color. | ||||
|
r22772 | |||
Note that on some systems, terminfo mode may cause problems when using | ||||
color with the pager extension and less -R. less with the -R option | ||||
will only display ECMA-48 color codes, and terminfo mode may sometimes | ||||
emit codes that less doesn't understand. You can work around this by | ||||
either using ansi mode (or auto mode), or by using less -r (which will | ||||
pass through all terminal control codes, not just color control | ||||
codes). | ||||
|
r24068 | |||
On some systems (such as MSYS in Windows), the terminal may support | ||||
a different color mode than the pager (activated via the "pager" | ||||
extension). It is possible to define separate modes depending on whether | ||||
the pager is active:: | ||||
[color] | ||||
mode = auto | ||||
pagermode = ansi | ||||
If ``pagermode`` is not defined, the ``mode`` will be used. | ||||
|
r5787 | ''' | ||
|
r28968 | from __future__ import absolute_import | ||
|
r5787 | |||
|
r30968 | try: | ||
import curses | ||||
curses.COLOR_BLACK # force import | ||||
except ImportError: | ||||
curses = None | ||||
|
r29205 | from mercurial.i18n import _ | ||
|
r28968 | from mercurial import ( | ||
cmdutil, | ||||
|
r30652 | color, | ||
|
r28968 | commands, | ||
dispatch, | ||||
extensions, | ||||
ui as uimod, | ||||
) | ||||
|
r5787 | |||
|
r21249 | cmdtable = {} | ||
command = cmdutil.command(cmdtable) | ||||
|
r29841 | # Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for | ||
|
r25186 | # extensions which SHIP WITH MERCURIAL. Non-mainline extensions should | ||
# be specifying the version(s) of Mercurial they are tested with, or | ||||
# leave the attribute unspecified. | ||||
|
r29841 | testedwith = 'ships-with-hg-core' | ||
|
r16743 | |||
|
r10826 | def uisetup(ui): | ||
def colorcmd(orig, ui_, opts, cmd, cmdfunc): | ||||
|
r31101 | mode = color._modesetup(ui_, opts['color']) | ||
|
r31095 | uimod.ui._colormode = mode | ||
|
r22463 | if mode and mode != 'debug': | ||
|
r30971 | color.configstyles(ui_) | ||
|
r10826 | return orig(ui_, opts, cmd, cmdfunc) | ||
extensions.wrapfunction(dispatch, '_runcommand', colorcmd) | ||||
|
r12693 | def extsetup(ui): | ||
commands.globalopts.append( | ||||
('', 'color', 'auto', | ||||
|
r22463 | # i18n: 'always', 'auto', 'never', and 'debug' are keywords | ||
# and should not be translated | ||||
_("when to colorize (boolean, always, auto, never, or debug)"), | ||||
|
r12693 | _('TYPE'))) | ||
|
r10870 | |||
|
r30286 | @command('debugcolor', | ||
[('', 'style', None, _('show all configured styles'))], | ||||
'hg debugcolor') | ||||
|
r20455 | def debugcolor(ui, repo, **opts): | ||
|
r30286 | """show available color, effects or style""" | ||
|
r30284 | ui.write(('color mode: %s\n') % ui._colormode) | ||
|
r30286 | if opts.get('style'): | ||
return _debugdisplaystyle(ui) | ||||
else: | ||||
return _debugdisplaycolor(ui) | ||||
|
r30284 | |||
def _debugdisplaycolor(ui): | ||||
|
r30652 | oldstyle = color._styles.copy() | ||
|
r30283 | try: | ||
|
r30652 | color._styles.clear() | ||
|
r30967 | for effect in color._effects.keys(): | ||
|
r30652 | color._styles[effect] = effect | ||
|
r30968 | if color._terminfo_params: | ||
|
r30283 | for k, v in ui.configitems('color'): | ||
if k.startswith('color.'): | ||||
|
r30652 | color._styles[k] = k[6:] | ||
|
r30283 | elif k.startswith('terminfo.'): | ||
|
r30652 | color._styles[k] = k[9:] | ||
|
r30283 | ui.write(_('available colors:\n')) | ||
|
r30285 | # sort label with a '_' after the other to group '_background' entry. | ||
|
r30652 | items = sorted(color._styles.items(), | ||
|
r30285 | key=lambda i: ('_' in i[0], i[0], i[1])) | ||
for colorname, label in items: | ||||
|
r30283 | ui.write(('%s\n') % colorname, label=label) | ||
finally: | ||||
|
r30652 | color._styles.clear() | ||
color._styles.update(oldstyle) | ||||
|
r20455 | |||
|
r30286 | def _debugdisplaystyle(ui): | ||
ui.write(_('available style:\n')) | ||||
|
r30652 | width = max(len(s) for s in color._styles) | ||
for label, effects in sorted(color._styles.items()): | ||||
|
r30286 | ui.write('%s' % label, label=label) | ||
if effects: | ||||
# 50 | ||||
ui.write(': ') | ||||
ui.write(' ' * (max(0, width - len(label)))) | ||||
ui.write(', '.join(ui.label(e, e) for e in effects.split())) | ||||
ui.write('\n') | ||||