| 1 | import re |
| 2 | |
| 3 | class Scale(str): |
| 4 | def __len__(self): |
| 5 | ''' |
| 6 | This ensures that you will always get the actual length of the string, |
| 7 | minus the extended characters. Which is of course important, when you |
| 8 | are calculating output field sizes. Requires the re module. |
| 9 | ''' |
| 10 | tmp = self[:] |
| 11 | cnt = 0 |
| 12 | for i in re.sub('\\x1b[\[0-9;]*m', '', tmp): |
| 13 | cnt += 1 |
| 14 | return(cnt) |
| 15 | |
| 16 | def __getattr__(self, method): |
| 17 | ''' |
| 18 | This is essentially an implimentation of Ruby's .method_missing |
| 19 | that shortens the code dramatically, and allows for simply extending |
| 20 | to support other escape codes. As a note, the modifier methods like |
| 21 | .bold() and .underline() and such, need to come before the color |
| 22 | methods. The color should always be the last modifier. |
| 23 | ''' |
| 24 | method_map = { |
| 25 | 'black': {'color': True, 'value': 30, 'mode': 'm'}, |
| 26 | 'red': {'color': True, 'value': 31, 'mode': 'm'}, |
| 27 | 'green': {'color': True, 'value': 32, 'mode': 'm'}, |
| 28 | 'yellow': {'color': True, 'value': 33, 'mode': 'm'}, |
| 29 | 'blue': {'color': True, 'value': 34, 'mode': 'm'}, |
| 30 | 'purple': {'color': True, 'value': 35, 'mode': 'm'}, |
| 31 | 'cyan': {'color': True, 'value': 36, 'mode': 'm'}, |
| 32 | 'white': {'color': True, 'value': 37, 'mode': 'm'}, |
| 33 | 'clean': {'color': False, 'value': 0, 'mode': 'm'}, |
| 34 | 'bold': {'color': False, 'value': 1, 'mode': 'm'}, |
| 35 | 'underline': {'color': False, 'value': 4, 'mode': 'm'}, |
| 36 | 'blink': {'color': False, 'value': 5, 'mode': 'm'}, |
| 37 | 'reverse': {'color': False, 'value': 7, 'mode': 'm'}, |
| 38 | 'conceal': {'color': False, 'value': 8, 'mode': 'm'}, |
| 39 | } |
| 40 | |
| 41 | def get(self, **kwargs): |
| 42 | if method_map[method]['color']: |
| 43 | reset='[0m' |
| 44 | else: |
| 45 | reset='' |
| 46 | |
| 47 | return( |
| 48 | Scale('%s[%s%s%s%s' % ( |
| 49 | reset, |
| 50 | method_map[method]['value'], |
| 51 | method_map[method]['mode'], |
| 52 | self, |
| 53 | reset |
| 54 | ) |
| 55 | )) |
| 56 | |
| 57 | if method in method_map: |
| 58 | return get.__get__(self) |
| 59 | else: |
| 60 | raise(AttributeError, method) |