17 |
17 |
18 try: |
18 try: |
19 import curses |
19 import curses |
20 # Mapping from effect name to terminfo attribute name (or raw code) or |
20 # Mapping from effect name to terminfo attribute name (or raw code) or |
21 # color number. This will also force-load the curses module. |
21 # color number. This will also force-load the curses module. |
22 _terminfo_params = { |
22 _baseterminfoparams = { |
23 'none': (True, 'sgr0', ''), |
23 'none': (True, 'sgr0', ''), |
24 'standout': (True, 'smso', ''), |
24 'standout': (True, 'smso', ''), |
25 'underline': (True, 'smul', ''), |
25 'underline': (True, 'smul', ''), |
26 'reverse': (True, 'rev', ''), |
26 'reverse': (True, 'rev', ''), |
27 'inverse': (True, 'rev', ''), |
27 'inverse': (True, 'rev', ''), |
39 'cyan': (False, curses.COLOR_CYAN, ''), |
39 'cyan': (False, curses.COLOR_CYAN, ''), |
40 'white': (False, curses.COLOR_WHITE, ''), |
40 'white': (False, curses.COLOR_WHITE, ''), |
41 } |
41 } |
42 except ImportError: |
42 except ImportError: |
43 curses = None |
43 curses = None |
44 _terminfo_params = {} |
44 _baseterminfoparams = {} |
45 |
45 |
46 # allow the extensions to change the default |
46 # allow the extensions to change the default |
47 _enabledbydefault = False |
47 _enabledbydefault = False |
48 |
48 |
49 # start and stop parameters for effects |
49 # start and stop parameters for effects |
138 if curses is None: |
138 if curses is None: |
139 return |
139 return |
140 # Otherwise, see what the config file says. |
140 # Otherwise, see what the config file says. |
141 if mode not in ('auto', 'terminfo'): |
141 if mode not in ('auto', 'terminfo'): |
142 return |
142 return |
|
143 ui._terminfoparams.update(_baseterminfoparams) |
143 |
144 |
144 for key, val in ui.configitems('color'): |
145 for key, val in ui.configitems('color'): |
145 if key.startswith('color.'): |
146 if key.startswith('color.'): |
146 newval = (False, int(val), '') |
147 newval = (False, int(val), '') |
147 _terminfo_params[key[6:]] = newval |
148 ui._terminfoparams[key[6:]] = newval |
148 elif key.startswith('terminfo.'): |
149 elif key.startswith('terminfo.'): |
149 newval = (True, '', val.replace('\\E', '\x1b')) |
150 newval = (True, '', val.replace('\\E', '\x1b')) |
150 _terminfo_params[key[9:]] = newval |
151 ui._terminfoparams[key[9:]] = newval |
151 try: |
152 try: |
152 curses.setupterm() |
153 curses.setupterm() |
153 except curses.error as e: |
154 except curses.error as e: |
154 _terminfo_params.clear() |
155 ui._terminfoparams.clear() |
155 return |
156 return |
156 |
157 |
157 for key, (b, e, c) in _terminfo_params.items(): |
158 for key, (b, e, c) in ui._terminfoparams.items(): |
158 if not b: |
159 if not b: |
159 continue |
160 continue |
160 if not c and not curses.tigetstr(e): |
161 if not c and not curses.tigetstr(e): |
161 # Most terminals don't support dim, invis, etc, so don't be |
162 # Most terminals don't support dim, invis, etc, so don't be |
162 # noisy and use ui.debug(). |
163 # noisy and use ui.debug(). |
163 ui.debug("no terminfo entry for %s\n" % e) |
164 ui.debug("no terminfo entry for %s\n" % e) |
164 del _terminfo_params[key] |
165 del ui._terminfoparams[key] |
165 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'): |
166 if not curses.tigetstr('setaf') or not curses.tigetstr('setab'): |
166 # Only warn about missing terminfo entries if we explicitly asked for |
167 # Only warn about missing terminfo entries if we explicitly asked for |
167 # terminfo mode. |
168 # terminfo mode. |
168 if mode == "terminfo": |
169 if mode == "terminfo": |
169 ui.warn(_("no terminfo entry for setab/setaf: reverting to " |
170 ui.warn(_("no terminfo entry for setab/setaf: reverting to " |
170 "ECMA-48 color\n")) |
171 "ECMA-48 color\n")) |
171 _terminfo_params.clear() |
172 ui._terminfoparams.clear() |
172 |
173 |
173 def setup(ui): |
174 def setup(ui): |
174 """configure color on a ui |
175 """configure color on a ui |
175 |
176 |
176 That function both set the colormode for the ui object and read |
177 That function both set the colormode for the ui object and read |
230 # a formatted terminal |
231 # a formatted terminal |
231 if mode == realmode and ui.formatted(): |
232 if mode == realmode and ui.formatted(): |
232 ui.warn(_('warning: failed to set color mode to %s\n') % mode) |
233 ui.warn(_('warning: failed to set color mode to %s\n') % mode) |
233 |
234 |
234 if realmode == 'win32': |
235 if realmode == 'win32': |
235 _terminfo_params.clear() |
236 ui._terminfoparams.clear() |
236 if not w32effects: |
237 if not w32effects: |
237 modewarn() |
238 modewarn() |
238 return None |
239 return None |
239 _effects.update(w32effects) |
240 _effects.update(w32effects) |
240 elif realmode == 'ansi': |
241 elif realmode == 'ansi': |
241 _terminfo_params.clear() |
242 ui._terminfoparams.clear() |
242 elif realmode == 'terminfo': |
243 elif realmode == 'terminfo': |
243 _terminfosetup(ui, mode) |
244 _terminfosetup(ui, mode) |
244 if not _terminfo_params: |
245 if not ui._terminfoparams: |
245 ## FIXME Shouldn't we return None in this case too? |
246 ## FIXME Shouldn't we return None in this case too? |
246 modewarn() |
247 modewarn() |
247 realmode = 'ansi' |
248 realmode = 'ansi' |
248 else: |
249 else: |
249 return None |
250 return None |
268 % (e, status)) |
269 % (e, status)) |
269 _styles[status] = ' '.join(good) |
270 _styles[status] = ' '.join(good) |
270 |
271 |
271 def valideffect(ui, effect): |
272 def valideffect(ui, effect): |
272 'Determine if the effect is valid or not.' |
273 'Determine if the effect is valid or not.' |
273 return ((not _terminfo_params and effect in _effects) |
274 return ((not ui._terminfoparams and effect in _effects) |
274 or (effect in _terminfo_params |
275 or (effect in ui._terminfoparams |
275 or effect[:-11] in _terminfo_params)) |
276 or effect[:-11] in ui._terminfoparams)) |
276 |
277 |
277 def _effect_str(ui, effect): |
278 def _effect_str(ui, effect): |
278 '''Helper function for render_effects().''' |
279 '''Helper function for render_effects().''' |
279 |
280 |
280 bg = False |
281 bg = False |
281 if effect.endswith('_background'): |
282 if effect.endswith('_background'): |
282 bg = True |
283 bg = True |
283 effect = effect[:-11] |
284 effect = effect[:-11] |
284 try: |
285 try: |
285 attr, val, termcode = _terminfo_params[effect] |
286 attr, val, termcode = ui._terminfoparams[effect] |
286 except KeyError: |
287 except KeyError: |
287 return '' |
288 return '' |
288 if attr: |
289 if attr: |
289 if termcode: |
290 if termcode: |
290 return termcode |
291 return termcode |
297 |
298 |
298 def _render_effects(ui, text, effects): |
299 def _render_effects(ui, text, effects): |
299 'Wrap text in commands to turn on each effect.' |
300 'Wrap text in commands to turn on each effect.' |
300 if not text: |
301 if not text: |
301 return text |
302 return text |
302 if _terminfo_params: |
303 if ui._terminfoparams: |
303 start = ''.join(_effect_str(ui, effect) |
304 start = ''.join(_effect_str(ui, effect) |
304 for effect in ['none'] + effects.split()) |
305 for effect in ['none'] + effects.split()) |
305 stop = _effect_str(ui, 'none') |
306 stop = _effect_str(ui, 'none') |
306 else: |
307 else: |
307 start = [str(_effects[e]) for e in ['none'] + effects.split()] |
308 start = [str(_effects[e]) for e in ['none'] + effects.split()] |