[clang-format] Fix a bug in aligning comments above PPDirective (#72791)
[llvm-project.git] / clang / tools / scan-view / share / startfile.py
blobd63e69280e90dde3354ce277b3fa18e51e6181e6
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
4 """Utility for opening a file using the default application in a cross-platform
5 manner. Modified from http://code.activestate.com/recipes/511443/.
6 """
8 __version__ = "1.1x"
9 __all__ = ["open"]
11 import os
12 import sys
13 import webbrowser
14 import subprocess
16 _controllers = {}
17 _open = None
20 class BaseController(object):
21 """Base class for open program controllers."""
23 def __init__(self, name):
24 self.name = name
26 def open(self, filename):
27 raise NotImplementedError
30 class Controller(BaseController):
31 """Controller for a generic open program."""
33 def __init__(self, *args):
34 super(Controller, self).__init__(os.path.basename(args[0]))
35 self.args = list(args)
37 def _invoke(self, cmdline):
38 if sys.platform[:3] == "win":
39 closefds = False
40 startupinfo = subprocess.STARTUPINFO()
41 startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
42 else:
43 closefds = True
44 startupinfo = None
46 if (
47 os.environ.get("DISPLAY")
48 or sys.platform[:3] == "win"
49 or sys.platform == "darwin"
51 inout = file(os.devnull, "r+")
52 else:
53 # for TTY programs, we need stdin/out
54 inout = None
56 # if possible, put the child precess in separate process group,
57 # so keyboard interrupts don't affect child precess as well as
58 # Python
59 setsid = getattr(os, "setsid", None)
60 if not setsid:
61 setsid = getattr(os, "setpgrp", None)
63 pipe = subprocess.Popen(
64 cmdline,
65 stdin=inout,
66 stdout=inout,
67 stderr=inout,
68 close_fds=closefds,
69 preexec_fn=setsid,
70 startupinfo=startupinfo,
73 # It is assumed that this kind of tools (gnome-open, kfmclient,
74 # exo-open, xdg-open and open for OSX) immediately exit after launching
75 # the specific application
76 returncode = pipe.wait()
77 if hasattr(self, "fixreturncode"):
78 returncode = self.fixreturncode(returncode)
79 return not returncode
81 def open(self, filename):
82 if isinstance(filename, basestring):
83 cmdline = self.args + [filename]
84 else:
85 # assume it is a sequence
86 cmdline = self.args + filename
87 try:
88 return self._invoke(cmdline)
89 except OSError:
90 return False
93 # Platform support for Windows
94 if sys.platform[:3] == "win":
96 class Start(BaseController):
97 """Controller for the win32 start program through os.startfile."""
99 def open(self, filename):
100 try:
101 os.startfile(filename)
102 except WindowsError:
103 # [Error 22] No application is associated with the specified
104 # file for this operation: '<URL>'
105 return False
106 else:
107 return True
109 _controllers["windows-default"] = Start("start")
110 _open = _controllers["windows-default"].open
113 # Platform support for MacOS
114 elif sys.platform == "darwin":
115 _controllers["open"] = Controller("open")
116 _open = _controllers["open"].open
119 # Platform support for Unix
120 else:
122 try:
123 from commands import getoutput
124 except ImportError:
125 from subprocess import getoutput
127 # @WARNING: use the private API of the webbrowser module
128 from webbrowser import _iscommand
130 class KfmClient(Controller):
131 """Controller for the KDE kfmclient program."""
133 def __init__(self, kfmclient="kfmclient"):
134 super(KfmClient, self).__init__(kfmclient, "exec")
135 self.kde_version = self.detect_kde_version()
137 def detect_kde_version(self):
138 kde_version = None
139 try:
140 info = getoutput("kde-config --version")
142 for line in info.splitlines():
143 if line.startswith("KDE"):
144 kde_version = line.split(":")[-1].strip()
145 break
146 except (OSError, RuntimeError):
147 pass
149 return kde_version
151 def fixreturncode(self, returncode):
152 if returncode is not None and self.kde_version > "3.5.4":
153 return returncode
154 else:
155 return os.EX_OK
157 def detect_desktop_environment():
158 """Checks for known desktop environments
160 Return the desktop environments name, lowercase (kde, gnome, xfce)
161 or "generic"
165 desktop_environment = "generic"
167 if os.environ.get("KDE_FULL_SESSION") == "true":
168 desktop_environment = "kde"
169 elif os.environ.get("GNOME_DESKTOP_SESSION_ID"):
170 desktop_environment = "gnome"
171 else:
172 try:
173 info = getoutput("xprop -root _DT_SAVE_MODE")
174 if ' = "xfce4"' in info:
175 desktop_environment = "xfce"
176 except (OSError, RuntimeError):
177 pass
179 return desktop_environment
181 def register_X_controllers():
182 if _iscommand("kfmclient"):
183 _controllers["kde-open"] = KfmClient()
185 for command in ("gnome-open", "exo-open", "xdg-open"):
186 if _iscommand(command):
187 _controllers[command] = Controller(command)
189 def get():
190 controllers_map = {
191 "gnome": "gnome-open",
192 "kde": "kde-open",
193 "xfce": "exo-open",
196 desktop_environment = detect_desktop_environment()
198 try:
199 controller_name = controllers_map[desktop_environment]
200 return _controllers[controller_name].open
202 except KeyError:
203 if "xdg-open" in _controllers:
204 return _controllers["xdg-open"].open
205 else:
206 return webbrowser.open
208 if os.environ.get("DISPLAY"):
209 register_X_controllers()
210 _open = get()
213 def open(filename):
214 """Open a file or a URL in the registered default application."""
216 return _open(filename)