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