blob: 4306836d07c78651da6cca692e31d076ad030aaf [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
David Pursehouse819827a2020-02-12 15:20:19 +090027
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070028class Editor(object):
29 """Manages the user's preferred text editor."""
30
31 _editor = None
32 globalConfig = None
33
34 @classmethod
35 def _GetEditor(cls):
36 if cls._editor is None:
37 cls._editor = cls._SelectEditor()
38 return cls._editor
39
40 @classmethod
41 def _SelectEditor(cls):
42 e = os.getenv('GIT_EDITOR')
43 if e:
44 return e
45
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070046 if cls.globalConfig:
47 e = cls.globalConfig.GetString('core.editor')
48 if e:
49 return e
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070050
51 e = os.getenv('VISUAL')
52 if e:
53 return e
54
55 e = os.getenv('EDITOR')
56 if e:
57 return e
58
59 if os.getenv('TERM') == 'dumb':
Sarah Owenscecd1d82012-11-01 22:59:27 -070060 print(
David Pursehouseabdf7502020-02-12 14:58:39 +090061 """No editor specified in GIT_EDITOR, core.editor, VISUAL or EDITOR.
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070062Tried to fall back to vi but terminal is dumb. Please configure at
Sarah Owenscecd1d82012-11-01 22:59:27 -070063least one of these before using this command.""", file=sys.stderr)
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070064 sys.exit(1)
65
66 return 'vi'
67
68 @classmethod
69 def EditString(cls, data):
70 """Opens an editor to edit the given content.
71
Mike Frysinger70c54dc2019-11-15 01:19:03 -050072 Args:
73 data: The text to edit.
Sarah Owenscecd1d82012-11-01 22:59:27 -070074
Mike Frysinger70c54dc2019-11-15 01:19:03 -050075 Returns:
76 New value of edited text.
77
78 Raises:
79 EditorError: The editor failed to run.
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070080 """
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070081 editor = cls._GetEditor()
82 if editor == ':':
83 return data
84
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070085 fd, path = tempfile.mkstemp()
86 try:
Mike Frysinger70c54dc2019-11-15 01:19:03 -050087 os.write(fd, data.encode('utf-8'))
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -070088 os.close(fd)
89 fd = None
90
Renaud Paquaycd892a32016-11-03 15:59:05 -070091 if platform_utils.isWindows():
92 # Split on spaces, respecting quoted strings
93 import shlex
94 args = shlex.split(editor)
95 shell = False
96 elif re.compile("^.*[$ \t'].*$").match(editor):
Patrick Dubroyb715b142010-07-29 17:10:47 -070097 args = [editor + ' "$@"', 'sh']
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -070098 shell = True
99 else:
100 args = [editor]
101 shell = False
102 args.append(path)
103
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700104 try:
Shawn O. Pearce1dcb58a2009-07-02 12:45:47 -0700105 rc = subprocess.Popen(args, shell=shell).wait()
Sarah Owensa5be53f2012-09-09 15:37:57 -0700106 except OSError as e:
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700107 raise EditorError('editor failed, %s: %s %s'
David Pursehouseabdf7502020-02-12 14:58:39 +0900108 % (str(e), editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700109 if rc != 0:
110 raise EditorError('editor failed with exit status %d: %s %s'
David Pursehouseabdf7502020-02-12 14:58:39 +0900111 % (rc, editor, path))
Shawn O. Pearce54fccd72009-06-24 07:09:51 -0700112
Mike Frysinger70c54dc2019-11-15 01:19:03 -0500113 with open(path, mode='rb') as fd2:
114 return fd2.read().decode('utf-8')
The Android Open Source Projectcf31fe92008-10-21 07:00:00 -0700115 finally:
116 if fd:
117 os.close(fd)
Renaud Paquay010fed72016-11-11 14:25:29 -0800118 platform_utils.remove(path)