##// END OF EJS Templates
color: add --color switch...
Brodie Rao -
r7455:c9fd5474 default
parent child Browse files
Show More
@@ -1,185 +1,194 b''
1 1 # color.py color output for the status and qseries commands
2 2 #
3 3 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com>
4 4 #
5 5 # This program is free software; you can redistribute it and/or modify it
6 6 # under the terms of the GNU General Public License as published by the
7 7 # Free Software Foundation; either version 2 of the License, or (at your
8 8 # option) any later version.
9 9 #
10 10 # This program is distributed in the hope that it will be useful, but
11 11 # WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
13 13 # Public License for more details.
14 14 #
15 15 # You should have received a copy of the GNU General Public License along
16 16 # with this program; if not, write to the Free Software Foundation, Inc.,
17 17 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 18
19 19 '''add color output to the status and qseries commands
20 20
21 21 This extension modifies the status command to add color to its output to
22 22 reflect file status, and the qseries command to add color to reflect patch
23 23 status (applied, unapplied, missing). Other effects in addition to color,
24 24 like bold and underlined text, are also available. Effects are rendered
25 25 with the ECMA-48 SGR control function (aka ANSI escape codes). This module
26 26 also provides the render_text function, which can be used to add effects to
27 27 any text.
28 28
29 29 To enable this extension, add this to your .hgrc file:
30 30 [extensions]
31 31 color =
32 32
33 33 Default effects my be overriden from the .hgrc file:
34 34
35 35 [color]
36 36 status.modified = blue bold underline red_background
37 37 status.added = green bold
38 38 status.removed = red bold blue_background
39 39 status.deleted = cyan bold underline
40 40 status.unknown = magenta bold underline
41 41 status.ignored = black bold
42 42
43 43 # 'none' turns off all effects
44 44 status.clean = none
45 45 status.copied = none
46 46
47 47 qseries.applied = blue bold underline
48 48 qseries.unapplied = black bold
49 49 qseries.missing = red bold
50 50 '''
51 51
52 import re, sys
52 import os, re, sys
53 53
54 54 from mercurial import commands, extensions
55 55 from mercurial.i18n import _
56 56
57 57 # start and stop parameters for effects
58 58 _effect_params = { 'none': (0, 0),
59 59 'black': (30, 39),
60 60 'red': (31, 39),
61 61 'green': (32, 39),
62 62 'yellow': (33, 39),
63 63 'blue': (34, 39),
64 64 'magenta': (35, 39),
65 65 'cyan': (36, 39),
66 66 'white': (37, 39),
67 67 'bold': (1, 22),
68 68 'italic': (3, 23),
69 69 'underline': (4, 24),
70 70 'inverse': (7, 27),
71 71 'black_background': (40, 49),
72 72 'red_background': (41, 49),
73 73 'green_background': (42, 49),
74 74 'yellow_background': (43, 49),
75 75 'blue_background': (44, 49),
76 76 'purple_background': (45, 49),
77 77 'cyan_background': (46, 49),
78 78 'white_background': (47, 49), }
79 79
80 80 def render_effects(text, *effects):
81 81 'Wrap text in commands to turn on each effect.'
82 82 start = [ str(_effect_params['none'][0]) ]
83 83 stop = []
84 84 for effect in effects:
85 85 start.append(str(_effect_params[effect][0]))
86 86 stop.append(str(_effect_params[effect][1]))
87 87 stop.append(str(_effect_params['none'][1]))
88 88 start = '\033[' + ';'.join(start) + 'm'
89 89 stop = '\033[' + ';'.join(stop) + 'm'
90 90 return start + text + stop
91 91
92 92 def colorstatus(orig, ui, repo, *pats, **opts):
93 93 '''run the status command with colored output'''
94 94
95 95 delimiter = opts['print0'] and '\0' or '\n'
96 96
97 97 nostatus = opts.get('no_status')
98 98 opts['no_status'] = False
99 99 # run status and capture its output
100 100 ui.pushbuffer()
101 101 retval = orig(ui, repo, *pats, **opts)
102 102 # filter out empty strings
103 103 lines_with_status = [ line for line in ui.popbuffer().split(delimiter) if line ]
104 104
105 105 if nostatus:
106 106 lines = [l[2:] for l in lines_with_status]
107 107 else:
108 108 lines = lines_with_status
109 109
110 110 # apply color to output and display it
111 111 for i in xrange(0, len(lines)):
112 112 status = _status_abbreviations[lines_with_status[i][0]]
113 113 effects = _status_effects[status]
114 114 if effects:
115 115 lines[i] = render_effects(lines[i], *effects)
116 sys.stdout.write(lines[i] + delimiter)
116 ui.write(lines[i] + delimiter)
117 117 return retval
118 118
119 119 _status_abbreviations = { 'M': 'modified',
120 120 'A': 'added',
121 121 'R': 'removed',
122 122 '!': 'deleted',
123 123 '?': 'unknown',
124 124 'I': 'ignored',
125 125 'C': 'clean',
126 126 ' ': 'copied', }
127 127
128 128 _status_effects = { 'modified': ('blue', 'bold'),
129 129 'added': ('green', 'bold'),
130 130 'removed': ('red', 'bold'),
131 131 'deleted': ('cyan', 'bold', 'underline'),
132 132 'unknown': ('magenta', 'bold', 'underline'),
133 133 'ignored': ('black', 'bold'),
134 134 'clean': ('none', ),
135 135 'copied': ('none', ), }
136 136
137 137 def colorqseries(orig, ui, repo, *dummy, **opts):
138 138 '''run the qseries command with colored output'''
139 139 ui.pushbuffer()
140 140 retval = orig(ui, repo, **opts)
141 141 patches = ui.popbuffer().splitlines()
142 142 for patch in patches:
143 143 patchname = patch
144 144 if opts['summary']:
145 145 patchname = patchname.split(': ')[0]
146 146 if ui.verbose:
147 147 patchname = patchname.split(' ', 2)[-1]
148 148
149 149 if opts['missing']:
150 150 effects = _patch_effects['missing']
151 151 # Determine if patch is applied.
152 152 elif [ applied for applied in repo.mq.applied
153 153 if patchname == applied.name ]:
154 154 effects = _patch_effects['applied']
155 155 else:
156 156 effects = _patch_effects['unapplied']
157 sys.stdout.write(render_effects(patch, *effects) + '\n')
157 ui.write(render_effects(patch, *effects) + '\n')
158 158 return retval
159 159
160 160 _patch_effects = { 'applied': ('blue', 'bold', 'underline'),
161 161 'missing': ('red', 'bold'),
162 162 'unapplied': ('black', 'bold'), }
163 163
164 164 def uisetup(ui):
165 165 '''Initialize the extension.'''
166 166 _setupcmd(ui, 'status', commands.table, colorstatus, _status_effects)
167 167 if ui.config('extensions', 'hgext.mq') is not None or \
168 168 ui.config('extensions', 'mq') is not None:
169 169 from hgext import mq
170 170 _setupcmd(ui, 'qseries', mq.cmdtable, colorqseries, _patch_effects)
171 171
172 172 def _setupcmd(ui, cmd, table, func, effectsmap):
173 173 '''patch in command to command table and load effect map'''
174 def nocolor(orig, *args, **kwargs):
175 if kwargs['no_color']:
176 return orig(*args, **kwargs)
177 return func(orig, *args, **kwargs)
174 def nocolor(orig, *args, **opts):
175
176 if (opts['no_color'] or opts['color'] == 'never' or
177 (opts['color'] == 'auto' and (os.environ.get('TERM') == 'dumb'
178 or not sys.__stdout__.isatty()))):
179 return orig(*args, **opts)
180
181 if func is not None:
182 return func(orig, *args, **opts)
183 return orig(*args, **opts)
178 184
179 185 entry = extensions.wrapcommand(table, cmd, nocolor)
180 entry[1].append(('', 'no-color', None, _("don't colorize output")))
186 entry[1].extend([
187 ('', 'color', 'auto', _("when to colorize (always, auto, or never)")),
188 ('', 'no-color', None, _("don't colorize output")),
189 ])
181 190
182 191 for status in effectsmap:
183 192 effects = ui.config('color', cmd + '.' + status)
184 193 if effects:
185 194 effectsmap[status] = re.split('\W+', effects)
General Comments 0
You need to be logged in to leave comments. Login now