blob: fcf163866d876f83cee683c669091fde0cc0e32b [file] [log] [blame]
Mike Frysingerf6013762019-06-13 02:30:51 -04001# -*- coding:utf-8 -*-
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -07002#
3# Copyright (C) 2008 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
Sarah Owenscecd1d82012-11-01 22:59:27 -070017from __future__ import print_function
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070018import os
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070019import re
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070020import sys
21import subprocess
22import tempfile
23
24from error import EditorError
Renaud Paquay010fed72016-11-11 14:25:29 -080025import platform_utils
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070026
27class Editor(object):
28 """Manages the user's preferred text editor."""
29
30 _editor = None
31 globalConfig = None
32
33 @classmethod
34 def _GetEditor(cls):
35 if cls._editor is None:
36 cls._editor = cls._SelectEditor()
37 return cls._editor
38
39 @classmethod
40 def _SelectEditor(cls):
41 e = os.getenv('GIT_EDITOR')
42 if e:
43 return e
44
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070045 if cls.globalConfig:
46 e = cls.globalConfig.GetString('core.editor')
47 if e:
48 return e
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070049
50 e = os.getenv('VISUAL')
51 if e:
52 return e
53
54 e = os.getenv('EDITOR')
55 if e:
56 return e
57
58 if os.getenv('TERM') == 'dumb':
Sarah Owenscecd1d82012-11-01 22:59:27 -070059 print(
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070060"""No editor specified in GIT_EDITOR, core.editor, VISUAL or EDITOR.
61Tried to fall back to vi but terminal is dumb. Please configure at
Sarah Owenscecd1d82012-11-01 22:59:27 -070062least one of these before using this command.""", file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070063 sys.exit(1)
64
65 return 'vi'
66
67 @classmethod
68 def EditString(cls, data):
69 """Opens an editor to edit the given content.
70
Mike Frysinger70c54dc2019-11-15 01:19:03 -050071 Args:
72 data: The text to edit.
Sarah Owenscecd1d82012-11-01 22:59:27 -070073
Mike Frysinger70c54dc2019-11-15 01:19:03 -050074 Returns:
75 New value of edited text.
76
77 Raises:
78 EditorError: The editor failed to run.
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070079 """
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070080 editor = cls._GetEditor()
81 if editor == ':':
82 return data
83
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070084 fd, path = tempfile.mkstemp()
85 try:
Mike Frysinger70c54dc2019-11-15 01:19:03 -050086 os.write(fd, data.encode('utf-8'))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070087 os.close(fd)
88 fd = None
89
Renaud Paquaycd892a32016-11-03 15:59:05 -070090 if platform_utils.isWindows():
91 # Split on spaces, respecting quoted strings
92 import shlex
93 args = shlex.split(editor)
94 shell = False
95 elif re.compile("^.*[$ \t'].*$").match(editor):
Patrick Dubroyb715b142010-07-29 17:10:47 -070096 args = [editor + ' "$@"', 'sh']
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070097 shell = True
98 else:
99 args = [editor]
100 shell = False
101 args.append(path)
102
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700103 try:
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -0700104 rc = subprocess.Popen(args, shell=shell).wait()
Sarah Owensa5be53f2012-09-09 15:37:57 -0700105 except OSError as e:
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700106 raise EditorError('editor failed, %s: %s %s'
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -0700107 % (str(e), editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700108 if rc != 0:
109 raise EditorError('editor failed with exit status %d: %s %s'
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -0700110 % (rc, editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700111
Mike Frysinger70c54dc2019-11-15 01:19:03 -0500112 with open(path, mode='rb') as fd2:
113 return fd2.read().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700114 finally:
115 if fd:
116 os.close(fd)
Renaud Paquay010fed72016-11-11 14:25:29 -0800117 platform_utils.remove(path)