blob: b84a42d416b7db99434179a89f6838e4eb877c8b [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001# Copyright (C) 2008 The Android Open Source Project
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import os
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070016import re
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070017import sys
18import subprocess
19import tempfile
20
21from error import EditorError
Renaud Paquay010fed72016-11-11 14:25:29 -080022import platform_utils
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070023
David Pursehouse819827a2020-02-12 15:20:19 +090024
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070025class Editor(object):
26 """Manages the user's preferred text editor."""
27
28 _editor = None
29 globalConfig = None
30
31 @classmethod
32 def _GetEditor(cls):
33 if cls._editor is None:
34 cls._editor = cls._SelectEditor()
35 return cls._editor
36
37 @classmethod
38 def _SelectEditor(cls):
39 e = os.getenv('GIT_EDITOR')
40 if e:
41 return e
42
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070043 if cls.globalConfig:
44 e = cls.globalConfig.GetString('core.editor')
45 if e:
46 return e
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070047
48 e = os.getenv('VISUAL')
49 if e:
50 return e
51
52 e = os.getenv('EDITOR')
53 if e:
54 return e
55
56 if os.getenv('TERM') == 'dumb':
Sarah Owenscecd1d82012-11-01 22:59:27 -070057 print(
David Pursehouseabdf7502020-02-12 14:58:39 +090058 """No editor specified in GIT_EDITOR, core.editor, VISUAL or EDITOR.
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070059Tried to fall back to vi but terminal is dumb. Please configure at
Sarah Owenscecd1d82012-11-01 22:59:27 -070060least one of these before using this command.""", file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070061 sys.exit(1)
62
63 return 'vi'
64
65 @classmethod
66 def EditString(cls, data):
67 """Opens an editor to edit the given content.
68
Mike Frysinger70c54dc2019-11-15 01:19:03 -050069 Args:
70 data: The text to edit.
Sarah Owenscecd1d82012-11-01 22:59:27 -070071
Mike Frysinger70c54dc2019-11-15 01:19:03 -050072 Returns:
73 New value of edited text.
74
75 Raises:
76 EditorError: The editor failed to run.
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070077 """
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070078 editor = cls._GetEditor()
79 if editor == ':':
80 return data
81
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070082 fd, path = tempfile.mkstemp()
83 try:
Mike Frysinger70c54dc2019-11-15 01:19:03 -050084 os.write(fd, data.encode('utf-8'))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070085 os.close(fd)
86 fd = None
87
Renaud Paquaycd892a32016-11-03 15:59:05 -070088 if platform_utils.isWindows():
89 # Split on spaces, respecting quoted strings
90 import shlex
91 args = shlex.split(editor)
92 shell = False
93 elif re.compile("^.*[$ \t'].*$").match(editor):
Patrick Dubroyb715b142010-07-29 17:10:47 -070094 args = [editor + ' "$@"', 'sh']
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070095 shell = True
96 else:
97 args = [editor]
98 shell = False
99 args.append(path)
100
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700101 try:
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -0700102 rc = subprocess.Popen(args, shell=shell).wait()
Sarah Owensa5be53f2012-09-09 15:37:57 -0700103 except OSError as e:
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700104 raise EditorError('editor failed, %s: %s %s'
David Pursehouseabdf7502020-02-12 14:58:39 +0900105 % (str(e), editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700106 if rc != 0:
107 raise EditorError('editor failed with exit status %d: %s %s'
David Pursehouseabdf7502020-02-12 14:58:39 +0900108 % (rc, editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700109
Mike Frysinger70c54dc2019-11-15 01:19:03 -0500110 with open(path, mode='rb') as fd2:
111 return fd2.read().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700112 finally:
113 if fd:
114 os.close(fd)
Renaud Paquay010fed72016-11-11 14:25:29 -0800115 platform_utils.remove(path)