blob: 7980f2b4314b03d6c75a405896fc6be3c5ad385a [file] [log] [blame]
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07001#
2# Copyright (C) 2008 The Android Open Source Project
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8# http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
Sarah Owenscecd1d82012-11-01 22:59:27 -070016from __future__ import print_function
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070017import os
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070018import re
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070019import sys
20import subprocess
21import tempfile
22
23from error import EditorError
Renaud Paquay010fed72016-11-11 14:25:29 -080024import platform_utils
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070025
26class Editor(object):
27 """Manages the user's preferred text editor."""
28
29 _editor = None
30 globalConfig = None
31
32 @classmethod
33 def _GetEditor(cls):
34 if cls._editor is None:
35 cls._editor = cls._SelectEditor()
36 return cls._editor
37
38 @classmethod
39 def _SelectEditor(cls):
40 e = os.getenv('GIT_EDITOR')
41 if e:
42 return e
43
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070044 if cls.globalConfig:
45 e = cls.globalConfig.GetString('core.editor')
46 if e:
47 return e
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070048
49 e = os.getenv('VISUAL')
50 if e:
51 return e
52
53 e = os.getenv('EDITOR')
54 if e:
55 return e
56
57 if os.getenv('TERM') == 'dumb':
Sarah Owenscecd1d82012-11-01 22:59:27 -070058 print(
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070059"""No editor specified in GIT_EDITOR, core.editor, VISUAL or EDITOR.
60Tried to fall back to vi but terminal is dumb. Please configure at
Sarah Owenscecd1d82012-11-01 22:59:27 -070061least one of these before using this command.""", file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070062 sys.exit(1)
63
64 return 'vi'
65
66 @classmethod
67 def EditString(cls, data):
68 """Opens an editor to edit the given content.
69
70 Args:
71 data : the text to edit
Sarah Owenscecd1d82012-11-01 22:59:27 -070072
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070073 Returns:
74 new value of edited text; None if editing did not succeed
75 """
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070076 editor = cls._GetEditor()
77 if editor == ':':
78 return data
79
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070080 fd, path = tempfile.mkstemp()
81 try:
82 os.write(fd, data)
83 os.close(fd)
84 fd = None
85
Renaud Paquaycd892a32016-11-03 15:59:05 -070086 if platform_utils.isWindows():
87 # Split on spaces, respecting quoted strings
88 import shlex
89 args = shlex.split(editor)
90 shell = False
91 elif re.compile("^.*[$ \t'].*$").match(editor):
Patrick Dubroyb715b142010-07-29 17:10:47 -070092 args = [editor + ' "$@"', 'sh']
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070093 shell = True
94 else:
95 args = [editor]
96 shell = False
97 args.append(path)
98
Shawn O. Pearce54fccd72009-06-24 07:09:51 -070099 try:
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -0700100 rc = subprocess.Popen(args, shell=shell).wait()
Sarah Owensa5be53f2012-09-09 15:37:57 -0700101 except OSError as e:
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700102 raise EditorError('editor failed, %s: %s %s'
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -0700103 % (str(e), editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700104 if rc != 0:
105 raise EditorError('editor failed with exit status %d: %s %s'
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -0700106 % (rc, editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700107
Shawn O. Pearcea8421a12009-04-18 16:57:46 -0700108 fd2 = open(path)
Shawn O. Pearce76ca9f82009-04-18 14:48:03 -0700109 try:
Shawn O. Pearcea8421a12009-04-18 16:57:46 -0700110 return fd2.read()
Shawn O. Pearce76ca9f82009-04-18 14:48:03 -0700111 finally:
Shawn O. Pearcea8421a12009-04-18 16:57:46 -0700112 fd2.close()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700113 finally:
114 if fd:
115 os.close(fd)
Renaud Paquay010fed72016-11-11 14:25:29 -0800116 platform_utils.remove(path)