blob: 883a1a837bd51156015d9326d7b954f514122350 [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
24
25class 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(
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070058"""No editor specified in GIT_EDITOR, core.editor, VISUAL or EDITOR.
59Tried 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
69 Args:
70 data : the text to edit
Sarah Owenscecd1d82012-11-01 22:59:27 -070071
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070072 Returns:
73 new value of edited text; None if editing did not succeed
74 """
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070075 editor = cls._GetEditor()
76 if editor == ':':
77 return data
78
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070079 fd, path = tempfile.mkstemp()
80 try:
81 os.write(fd, data)
82 os.close(fd)
83 fd = None
84
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070085 if re.compile("^.*[$ \t'].*$").match(editor):
Patrick Dubroyb715b142010-07-29 17:10:47 -070086 args = [editor + ' "$@"', 'sh']
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070087 shell = True
88 else:
89 args = [editor]
90 shell = False
91 args.append(path)
92
Shawn O. Pearce54fccd72009-06-24 07:09:51 -070093 try:
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070094 rc = subprocess.Popen(args, shell=shell).wait()
Sarah Owensa5be53f2012-09-09 15:37:57 -070095 except OSError as e:
Shawn O. Pearce54fccd72009-06-24 07:09:51 -070096 raise EditorError('editor failed, %s: %s %s'
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070097 % (str(e), editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -070098 if rc != 0:
99 raise EditorError('editor failed with exit status %d: %s %s'
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -0700100 % (rc, editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700101
Shawn O. Pearcea8421a12009-04-18 16:57:46 -0700102 fd2 = open(path)
Shawn O. Pearce76ca9f82009-04-18 14:48:03 -0700103 try:
Shawn O. Pearcea8421a12009-04-18 16:57:46 -0700104 return fd2.read()
Shawn O. Pearce76ca9f82009-04-18 14:48:03 -0700105 finally:
Shawn O. Pearcea8421a12009-04-18 16:57:46 -0700106 fd2.close()
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700107 finally:
108 if fd:
109 os.close(fd)
110 os.remove(path)