diff options
Diffstat (limited to 'editor.py')
-rw-r--r-- | editor.py | 184 |
1 files changed, 95 insertions, 89 deletions
@@ -23,93 +23,99 @@ import platform_utils | |||
23 | 23 | ||
24 | 24 | ||
25 | class Editor(object): | 25 | class Editor(object): |
26 | """Manages the user's preferred text editor.""" | 26 | """Manages the user's preferred text editor.""" |
27 | 27 | ||
28 | _editor = None | 28 | _editor = None |
29 | globalConfig = None | 29 | globalConfig = None |
30 | 30 | ||
31 | @classmethod | 31 | @classmethod |
32 | def _GetEditor(cls): | 32 | def _GetEditor(cls): |
33 | if cls._editor is None: | 33 | if cls._editor is None: |
34 | cls._editor = cls._SelectEditor() | 34 | cls._editor = cls._SelectEditor() |
35 | return cls._editor | 35 | return cls._editor |
36 | 36 | ||
37 | @classmethod | 37 | @classmethod |
38 | def _SelectEditor(cls): | 38 | def _SelectEditor(cls): |
39 | e = os.getenv('GIT_EDITOR') | 39 | e = os.getenv("GIT_EDITOR") |
40 | if e: | 40 | if e: |
41 | return e | 41 | return e |
42 | 42 | ||
43 | if cls.globalConfig: | 43 | if cls.globalConfig: |
44 | e = cls.globalConfig.GetString('core.editor') | 44 | e = cls.globalConfig.GetString("core.editor") |
45 | if e: | 45 | if e: |
46 | return e | 46 | return e |
47 | 47 | ||
48 | e = os.getenv('VISUAL') | 48 | e = os.getenv("VISUAL") |
49 | if e: | 49 | if e: |
50 | return e | 50 | return e |
51 | 51 | ||
52 | e = os.getenv('EDITOR') | 52 | e = os.getenv("EDITOR") |
53 | if e: | 53 | if e: |
54 | return e | 54 | return e |
55 | 55 | ||
56 | if os.getenv('TERM') == 'dumb': | 56 | if os.getenv("TERM") == "dumb": |
57 | print( | 57 | print( |
58 | """No editor specified in GIT_EDITOR, core.editor, VISUAL or EDITOR. | 58 | """No editor specified in GIT_EDITOR, core.editor, VISUAL or EDITOR. |
59 | Tried to fall back to vi but terminal is dumb. Please configure at | 59 | Tried to fall back to vi but terminal is dumb. Please configure at |
60 | least one of these before using this command.""", file=sys.stderr) | 60 | least one of these before using this command.""", # noqa: E501 |
61 | sys.exit(1) | 61 | file=sys.stderr, |
62 | 62 | ) | |
63 | return 'vi' | 63 | sys.exit(1) |
64 | 64 | ||
65 | @classmethod | 65 | return "vi" |
66 | def EditString(cls, data): | 66 | |
67 | """Opens an editor to edit the given content. | 67 | @classmethod |
68 | 68 | def EditString(cls, data): | |
69 | Args: | 69 | """Opens an editor to edit the given content. |
70 | data: The text to edit. | 70 | |
71 | 71 | Args: | |
72 | Returns: | 72 | data: The text to edit. |
73 | New value of edited text. | 73 | |
74 | 74 | Returns: | |
75 | Raises: | 75 | New value of edited text. |
76 | EditorError: The editor failed to run. | 76 | |
77 | """ | 77 | Raises: |
78 | editor = cls._GetEditor() | 78 | EditorError: The editor failed to run. |
79 | if editor == ':': | 79 | """ |
80 | return data | 80 | editor = cls._GetEditor() |
81 | 81 | if editor == ":": | |
82 | fd, path = tempfile.mkstemp() | 82 | return data |
83 | try: | 83 | |
84 | os.write(fd, data.encode('utf-8')) | 84 | fd, path = tempfile.mkstemp() |
85 | os.close(fd) | 85 | try: |
86 | fd = None | 86 | os.write(fd, data.encode("utf-8")) |
87 | 87 | os.close(fd) | |
88 | if platform_utils.isWindows(): | 88 | fd = None |
89 | # Split on spaces, respecting quoted strings | 89 | |
90 | import shlex | 90 | if platform_utils.isWindows(): |
91 | args = shlex.split(editor) | 91 | # Split on spaces, respecting quoted strings |
92 | shell = False | 92 | import shlex |
93 | elif re.compile("^.*[$ \t'].*$").match(editor): | 93 | |
94 | args = [editor + ' "$@"', 'sh'] | 94 | args = shlex.split(editor) |
95 | shell = True | 95 | shell = False |
96 | else: | 96 | elif re.compile("^.*[$ \t'].*$").match(editor): |
97 | args = [editor] | 97 | args = [editor + ' "$@"', "sh"] |
98 | shell = False | 98 | shell = True |
99 | args.append(path) | 99 | else: |
100 | 100 | args = [editor] | |
101 | try: | 101 | shell = False |
102 | rc = subprocess.Popen(args, shell=shell).wait() | 102 | args.append(path) |
103 | except OSError as e: | 103 | |
104 | raise EditorError('editor failed, %s: %s %s' | 104 | try: |
105 | % (str(e), editor, path)) | 105 | rc = subprocess.Popen(args, shell=shell).wait() |
106 | if rc != 0: | 106 | except OSError as e: |
107 | raise EditorError('editor failed with exit status %d: %s %s' | 107 | raise EditorError( |
108 | % (rc, editor, path)) | 108 | "editor failed, %s: %s %s" % (str(e), editor, path) |
109 | 109 | ) | |
110 | with open(path, mode='rb') as fd2: | 110 | if rc != 0: |
111 | return fd2.read().decode('utf-8') | 111 | raise EditorError( |
112 | finally: | 112 | "editor failed with exit status %d: %s %s" |
113 | if fd: | 113 | % (rc, editor, path) |
114 | os.close(fd) | 114 | ) |
115 | platform_utils.remove(path) | 115 | |
116 | with open(path, mode="rb") as fd2: | ||
117 | return fd2.read().decode("utf-8") | ||
118 | finally: | ||
119 | if fd: | ||
120 | os.close(fd) | ||
121 | platform_utils.remove(path) | ||