|
| 1 | +# -*- coding: utf-8 -*- |
| 2 | + |
| 3 | +import sublime, sublime_plugin |
| 4 | +import os |
| 5 | +import re |
| 6 | + |
| 7 | +NONE_COMMAND = (None, None, 0) |
| 8 | + |
| 9 | +class UpperTable(dict): |
| 10 | + def __missing__(self, key): |
| 11 | + return u'\\u%04X' % key |
| 12 | + |
| 13 | +class LowerTable(dict): |
| 14 | + def __missing__(self, key): |
| 15 | + return u'\\u%04x' % key |
| 16 | + |
| 17 | +MAP = map(unichr, range(0x7f)) |
| 18 | +UPPER_TABLE = UpperTable(enumerate(MAP)) |
| 19 | +LOWER_TABLE = LowerTable(enumerate(MAP)) |
| 20 | +IS_UPPER = re.compile('\\u([A-F][A-Z0-9]{3,3}|[0-9][A-F][A-F0-9]{2,2}|[0-9]{2,2}[A-F][A-F0-9]|[0-9]{3,3}[A-F])') |
| 21 | + |
| 22 | +class JavaPropertiesEditorListener(sublime_plugin.EventListener): |
| 23 | + def check_properties(self, view): |
| 24 | + file_name = view.file_name() |
| 25 | + result = file_name and file_name.endswith('.properties') |
| 26 | + if result: |
| 27 | + view.settings().set('is_properties', True) |
| 28 | + return result |
| 29 | + |
| 30 | + def replace_content(self, view, regions, contents): |
| 31 | + sel = view.sel() |
| 32 | + rs = [x for x in sel] |
| 33 | + vp = view.viewport_position() |
| 34 | + view.set_viewport_position(tuple([0, 0])) |
| 35 | + edit = view.begin_edit() |
| 36 | + view.replace(edit, regions, contents) |
| 37 | + view.end_edit(edit) |
| 38 | + sel.clear() |
| 39 | + for x in rs: |
| 40 | + sel.add(sublime.Region(x.a, x.b)) |
| 41 | + view.set_viewport_position(vp) |
| 42 | + view.set_scratch(True) |
| 43 | + view.settings().set('set_scratch', True) |
| 44 | + |
| 45 | + def on_load(self, view): |
| 46 | + if not self.check_properties(view): |
| 47 | + return |
| 48 | + regions = sublime.Region(0, view.size()) |
| 49 | + orignal_contents = view.substr(regions) |
| 50 | + contents = orignal_contents.encode('iso-8859-1', 'replace').decode('unicode_escape') |
| 51 | + if contents == orignal_contents: |
| 52 | + return |
| 53 | + if IS_UPPER.search(orignal_contents) == None: |
| 54 | + view.settings().set('use_lower', True) |
| 55 | + self.replace_content(view, regions, contents) |
| 56 | + |
| 57 | + def on_modified(self, view): |
| 58 | + if not view.settings().get('is_properties'): |
| 59 | + return |
| 60 | + if view.settings().get('set_scratch'): |
| 61 | + view.settings().erase('set_scratch') |
| 62 | + return |
| 63 | + cmd0 = view.command_history(-1) |
| 64 | + cmd = view.command_history(0) |
| 65 | + if cmd == NONE_COMMAND: |
| 66 | + # no more command, redo it |
| 67 | + view.run_command('redo') |
| 68 | + elif cmd0 == NONE_COMMAND: |
| 69 | + # undo to open |
| 70 | + view.set_scratch(True) |
| 71 | + else: |
| 72 | + view.set_scratch(False) |
| 73 | + |
| 74 | + def on_pre_save(self, view): |
| 75 | + # check again in case the file was newly created |
| 76 | + if not self.check_properties(view): |
| 77 | + return |
| 78 | + regions = sublime.Region(0, view.size()) |
| 79 | + contents = view.substr(regions) |
| 80 | + tab = LOWER_TABLE if view.settings().get('use_lower') else UPPER_TABLE |
| 81 | + orignal_contents = contents.translate(tab) |
| 82 | + if contents == orignal_contents: |
| 83 | + return |
| 84 | + self.contents = contents |
| 85 | + self.replace_content(view, regions, orignal_contents) |
| 86 | + |
| 87 | + def on_post_save(self, view): |
| 88 | + if not view.settings().get('is_properties'): |
| 89 | + return |
| 90 | + if not hasattr(self, 'contents'): |
| 91 | + return |
| 92 | + contents = self.contents |
| 93 | + del self.contents |
| 94 | + regions = sublime.Region(0, view.size()) |
| 95 | + self.replace_content(view, regions, contents) |
0 commit comments