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