| 1 | import json |
| 2 | import re |
| 3 | import os |
| 4 | import os.path |
| 5 | from collections import OrderedDict |
| 6 | |
| 7 | # Regular expression for comments in config file |
| 8 | comment_re = re.compile( |
| 9 | '(^)[^\S\n]*/(?:\*(.*?)\*/[^\S\n]*|/[^\n]*)($)?', |
| 10 | re.DOTALL | re.MULTILINE |
| 11 | ) |
| 12 | |
| 13 | # Config dictionary |
| 14 | c = {} |
| 15 | |
| 16 | def user_filepath(): |
| 17 | """ |
| 18 | Determine the user's config file location |
| 19 | """ |
| 20 | if 'RAINBOW_CONFIG' in os.environ: |
| 21 | return os.environ['RAINBOW_CONFIG'] |
| 22 | |
| 23 | return os.path.expanduser("~") + os.sep + '.rainbow_config.json' |
| 24 | |
| 25 | def fixup(adict, k, v): |
| 26 | """ |
| 27 | Fix up a key in json format |
| 28 | """ |
| 29 | for key in adict.keys(): |
| 30 | if key == k: |
| 31 | adict[key] = v |
| 32 | elif isinstance(adict[key], dict): |
| 33 | fixup(adict[key], k, v) |
| 34 | |
| 35 | |
| 36 | def load_config(filepath): |
| 37 | """ |
| 38 | Load config from filepath |
| 39 | """ |
| 40 | with open(filepath) as f: |
| 41 | content = ''.join(f.readlines()) |
| 42 | match = comment_re.search(content) |
| 43 | while match: |
| 44 | content = content[:match.start()] + content[match.end():] |
| 45 | match = comment_re.search(content) |
| 46 | return json.loads(content, object_pairs_hook=OrderedDict) |
| 47 | |
| 48 | |
| 49 | def get_all_config(): |
| 50 | """ |
| 51 | Get all config |
| 52 | """ |
| 53 | try: |
| 54 | path = user_filepath() |
| 55 | data = load_config(path) |
| 56 | # Hard to set from prompt |
| 57 | data.pop('ONLY_LIST', None) |
| 58 | data.pop('IGNORE_LIST', None) |
| 59 | data.pop('FORMAT', None) |
| 60 | data.pop('QUOTE_FORMAT', None) |
| 61 | data.pop('NOTIFY_FORMAT', None) |
| 62 | return data |
| 63 | except: |
| 64 | return [] |
| 65 | |
| 66 | |
| 67 | def get_default_config(key): |
| 68 | """ |
| 69 | Get default value of a config key |
| 70 | """ |
| 71 | try: |
| 72 | path = os.path.dirname(__file__) + '/colorset/config' |
| 73 | data = load_config(path) |
| 74 | return data[key] |
| 75 | except: |
| 76 | raise Exception('This config key does not exist in default.') |
| 77 | |
| 78 | |
| 79 | def get_config(key): |
| 80 | """ |
| 81 | Get current value of a config key |
| 82 | """ |
| 83 | return c[key] |
| 84 | |
| 85 | |
| 86 | def set_config(key, value): |
| 87 | """ |
| 88 | Set a config key with specific value |
| 89 | """ |
| 90 | # Modify value |
| 91 | if value.isdigit(): |
| 92 | value = int(value) |
| 93 | elif value.lower() == 'true': |
| 94 | value = True |
| 95 | elif value.lower() == 'false': |
| 96 | value = False |
| 97 | # Update global config |
| 98 | c[key] = value |
| 99 | # Load current user config |
| 100 | path = user_filepath() |
| 101 | data = {} |
| 102 | try: |
| 103 | data = load_config(path) |
| 104 | except: |
| 105 | return |
| 106 | # Update config file |
| 107 | if key in data: |
| 108 | fixup(data, key, value) |
| 109 | else: |
| 110 | data[key] = value |
| 111 | # Save |
| 112 | with open(path, 'w') as out: |
| 113 | json.dump(data, out, indent=4) |
| 114 | os.system('chmod 777 ' + path) |
| 115 | |
| 116 | |
| 117 | def delete_config(key): |
| 118 | """ |
| 119 | Delete a config key |
| 120 | """ |
| 121 | path = user_filepath() |
| 122 | try: |
| 123 | data = load_config(path) |
| 124 | except: |
| 125 | raise Exception('Config file is messed up.') |
| 126 | # Drop key |
| 127 | if key in data and key in c: |
| 128 | data.pop(key) |
| 129 | c.pop(key) |
| 130 | try: |
| 131 | data[key] = c[key] = get_default_config(key) |
| 132 | except: |
| 133 | pass |
| 134 | else: |
| 135 | raise Exception('No such config key.') |
| 136 | # Save |
| 137 | with open(path, 'w') as out: |
| 138 | json.dump(data, out, indent=4) |
| 139 | os.system('chmod 777 ' + path) |
| 140 | |
| 141 | |
| 142 | def reload_config(): |
| 143 | """ |
| 144 | Reload config |
| 145 | """ |
| 146 | try: |
| 147 | rainbow_config = user_filepath() |
| 148 | data = load_config(rainbow_config) |
| 149 | for d in data: |
| 150 | c[d] = data[d] |
| 151 | except: |
| 152 | raise Exception('Can not reload config file with wrong format.') |
| 153 | |
| 154 | |
| 155 | def init_config(): |
| 156 | """ |
| 157 | Init configuration |
| 158 | """ |
| 159 | # Load the initial config |
| 160 | config = os.path.dirname(__file__) + \ |
| 161 | '/colorset/config' |
| 162 | try: |
| 163 | data = load_config(config) |
| 164 | for d in data: |
| 165 | c[d] = data[d] |
| 166 | except: |
| 167 | pass |
| 168 | # Load user's config |
| 169 | rainbow_config = user_filepath() |
| 170 | try: |
| 171 | data = load_config(rainbow_config) |
| 172 | for d in data: |
| 173 | c[d] = data[d] |
| 174 | except (IOError, ValueError) as e: |
| 175 | c['USER_JSON_ERROR'] = str(e) |
| 176 | # Load default theme |
| 177 | theme_file = os.path.dirname(__file__) + \ |
| 178 | '/colorset/' + c['THEME'] + '.json' |
| 179 | try: |
| 180 | data = load_config(theme_file) |
| 181 | for d in data: |
| 182 | c[d] = data[d] |
| 183 | except: |
| 184 | pass |
| 185 | |
| 186 | |
| 187 | # Init config |
| 188 | init_config() |