xref: /minix3/external/bsd/llvm/dist/clang/tools/scan-view/startfile.py (revision f4a2713ac843a11c696ec80c0a5e3e5d80b4d338)
1*f4a2713aSLionel Sambuc"""Utility for opening a file using the default application in a cross-platform
2*f4a2713aSLionel Sambucmanner. Modified from http://code.activestate.com/recipes/511443/.
3*f4a2713aSLionel Sambuc"""
4*f4a2713aSLionel Sambuc
5*f4a2713aSLionel Sambuc__version__ = '1.1x'
6*f4a2713aSLionel Sambuc__all__ = ['open']
7*f4a2713aSLionel Sambuc
8*f4a2713aSLionel Sambucimport os
9*f4a2713aSLionel Sambucimport sys
10*f4a2713aSLionel Sambucimport webbrowser
11*f4a2713aSLionel Sambucimport subprocess
12*f4a2713aSLionel Sambuc
13*f4a2713aSLionel Sambuc_controllers = {}
14*f4a2713aSLionel Sambuc_open = None
15*f4a2713aSLionel Sambuc
16*f4a2713aSLionel Sambuc
17*f4a2713aSLionel Sambucclass BaseController(object):
18*f4a2713aSLionel Sambuc    '''Base class for open program controllers.'''
19*f4a2713aSLionel Sambuc
20*f4a2713aSLionel Sambuc    def __init__(self, name):
21*f4a2713aSLionel Sambuc        self.name = name
22*f4a2713aSLionel Sambuc
23*f4a2713aSLionel Sambuc    def open(self, filename):
24*f4a2713aSLionel Sambuc        raise NotImplementedError
25*f4a2713aSLionel Sambuc
26*f4a2713aSLionel Sambuc
27*f4a2713aSLionel Sambucclass Controller(BaseController):
28*f4a2713aSLionel Sambuc    '''Controller for a generic open program.'''
29*f4a2713aSLionel Sambuc
30*f4a2713aSLionel Sambuc    def __init__(self, *args):
31*f4a2713aSLionel Sambuc        super(Controller, self).__init__(os.path.basename(args[0]))
32*f4a2713aSLionel Sambuc        self.args = list(args)
33*f4a2713aSLionel Sambuc
34*f4a2713aSLionel Sambuc    def _invoke(self, cmdline):
35*f4a2713aSLionel Sambuc        if sys.platform[:3] == 'win':
36*f4a2713aSLionel Sambuc            closefds = False
37*f4a2713aSLionel Sambuc            startupinfo = subprocess.STARTUPINFO()
38*f4a2713aSLionel Sambuc            startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
39*f4a2713aSLionel Sambuc        else:
40*f4a2713aSLionel Sambuc            closefds = True
41*f4a2713aSLionel Sambuc            startupinfo = None
42*f4a2713aSLionel Sambuc
43*f4a2713aSLionel Sambuc        if (os.environ.get('DISPLAY') or sys.platform[:3] == 'win' or
44*f4a2713aSLionel Sambuc                                                    sys.platform == 'darwin'):
45*f4a2713aSLionel Sambuc            inout = file(os.devnull, 'r+')
46*f4a2713aSLionel Sambuc        else:
47*f4a2713aSLionel Sambuc            # for TTY programs, we need stdin/out
48*f4a2713aSLionel Sambuc            inout = None
49*f4a2713aSLionel Sambuc
50*f4a2713aSLionel Sambuc        # if possible, put the child precess in separate process group,
51*f4a2713aSLionel Sambuc        # so keyboard interrupts don't affect child precess as well as
52*f4a2713aSLionel Sambuc        # Python
53*f4a2713aSLionel Sambuc        setsid = getattr(os, 'setsid', None)
54*f4a2713aSLionel Sambuc        if not setsid:
55*f4a2713aSLionel Sambuc            setsid = getattr(os, 'setpgrp', None)
56*f4a2713aSLionel Sambuc
57*f4a2713aSLionel Sambuc        pipe = subprocess.Popen(cmdline, stdin=inout, stdout=inout,
58*f4a2713aSLionel Sambuc                                stderr=inout, close_fds=closefds,
59*f4a2713aSLionel Sambuc                                preexec_fn=setsid, startupinfo=startupinfo)
60*f4a2713aSLionel Sambuc
61*f4a2713aSLionel Sambuc        # It is assumed that this kind of tools (gnome-open, kfmclient,
62*f4a2713aSLionel Sambuc        # exo-open, xdg-open and open for OSX) immediately exit after lauching
63*f4a2713aSLionel Sambuc        # the specific application
64*f4a2713aSLionel Sambuc        returncode = pipe.wait()
65*f4a2713aSLionel Sambuc        if hasattr(self, 'fixreturncode'):
66*f4a2713aSLionel Sambuc            returncode = self.fixreturncode(returncode)
67*f4a2713aSLionel Sambuc        return not returncode
68*f4a2713aSLionel Sambuc
69*f4a2713aSLionel Sambuc    def open(self, filename):
70*f4a2713aSLionel Sambuc        if isinstance(filename, basestring):
71*f4a2713aSLionel Sambuc            cmdline = self.args + [filename]
72*f4a2713aSLionel Sambuc        else:
73*f4a2713aSLionel Sambuc            # assume it is a sequence
74*f4a2713aSLionel Sambuc            cmdline = self.args + filename
75*f4a2713aSLionel Sambuc        try:
76*f4a2713aSLionel Sambuc            return self._invoke(cmdline)
77*f4a2713aSLionel Sambuc        except OSError:
78*f4a2713aSLionel Sambuc            return False
79*f4a2713aSLionel Sambuc
80*f4a2713aSLionel Sambuc
81*f4a2713aSLionel Sambuc# Platform support for Windows
82*f4a2713aSLionel Sambucif sys.platform[:3] == 'win':
83*f4a2713aSLionel Sambuc
84*f4a2713aSLionel Sambuc    class Start(BaseController):
85*f4a2713aSLionel Sambuc        '''Controller for the win32 start progam through os.startfile.'''
86*f4a2713aSLionel Sambuc
87*f4a2713aSLionel Sambuc        def open(self, filename):
88*f4a2713aSLionel Sambuc            try:
89*f4a2713aSLionel Sambuc                os.startfile(filename)
90*f4a2713aSLionel Sambuc            except WindowsError:
91*f4a2713aSLionel Sambuc                # [Error 22] No application is associated with the specified
92*f4a2713aSLionel Sambuc                # file for this operation: '<URL>'
93*f4a2713aSLionel Sambuc                return False
94*f4a2713aSLionel Sambuc            else:
95*f4a2713aSLionel Sambuc                return True
96*f4a2713aSLionel Sambuc
97*f4a2713aSLionel Sambuc    _controllers['windows-default'] = Start('start')
98*f4a2713aSLionel Sambuc    _open = _controllers['windows-default'].open
99*f4a2713aSLionel Sambuc
100*f4a2713aSLionel Sambuc
101*f4a2713aSLionel Sambuc# Platform support for MacOS
102*f4a2713aSLionel Sambucelif sys.platform == 'darwin':
103*f4a2713aSLionel Sambuc    _controllers['open']= Controller('open')
104*f4a2713aSLionel Sambuc    _open = _controllers['open'].open
105*f4a2713aSLionel Sambuc
106*f4a2713aSLionel Sambuc
107*f4a2713aSLionel Sambuc# Platform support for Unix
108*f4a2713aSLionel Sambucelse:
109*f4a2713aSLionel Sambuc
110*f4a2713aSLionel Sambuc    import commands
111*f4a2713aSLionel Sambuc
112*f4a2713aSLionel Sambuc    # @WARNING: use the private API of the webbrowser module
113*f4a2713aSLionel Sambuc    from webbrowser import _iscommand
114*f4a2713aSLionel Sambuc
115*f4a2713aSLionel Sambuc    class KfmClient(Controller):
116*f4a2713aSLionel Sambuc        '''Controller for the KDE kfmclient program.'''
117*f4a2713aSLionel Sambuc
118*f4a2713aSLionel Sambuc        def __init__(self, kfmclient='kfmclient'):
119*f4a2713aSLionel Sambuc            super(KfmClient, self).__init__(kfmclient, 'exec')
120*f4a2713aSLionel Sambuc            self.kde_version = self.detect_kde_version()
121*f4a2713aSLionel Sambuc
122*f4a2713aSLionel Sambuc        def detect_kde_version(self):
123*f4a2713aSLionel Sambuc            kde_version = None
124*f4a2713aSLionel Sambuc            try:
125*f4a2713aSLionel Sambuc                info = commands.getoutput('kde-config --version')
126*f4a2713aSLionel Sambuc
127*f4a2713aSLionel Sambuc                for line in info.splitlines():
128*f4a2713aSLionel Sambuc                    if line.startswith('KDE'):
129*f4a2713aSLionel Sambuc                        kde_version = line.split(':')[-1].strip()
130*f4a2713aSLionel Sambuc                        break
131*f4a2713aSLionel Sambuc            except (OSError, RuntimeError):
132*f4a2713aSLionel Sambuc                pass
133*f4a2713aSLionel Sambuc
134*f4a2713aSLionel Sambuc            return kde_version
135*f4a2713aSLionel Sambuc
136*f4a2713aSLionel Sambuc        def fixreturncode(self, returncode):
137*f4a2713aSLionel Sambuc            if returncode is not None and self.kde_version > '3.5.4':
138*f4a2713aSLionel Sambuc                return returncode
139*f4a2713aSLionel Sambuc            else:
140*f4a2713aSLionel Sambuc                return os.EX_OK
141*f4a2713aSLionel Sambuc
142*f4a2713aSLionel Sambuc    def detect_desktop_environment():
143*f4a2713aSLionel Sambuc        '''Checks for known desktop environments
144*f4a2713aSLionel Sambuc
145*f4a2713aSLionel Sambuc        Return the desktop environments name, lowercase (kde, gnome, xfce)
146*f4a2713aSLionel Sambuc        or "generic"
147*f4a2713aSLionel Sambuc
148*f4a2713aSLionel Sambuc        '''
149*f4a2713aSLionel Sambuc
150*f4a2713aSLionel Sambuc        desktop_environment = 'generic'
151*f4a2713aSLionel Sambuc
152*f4a2713aSLionel Sambuc        if os.environ.get('KDE_FULL_SESSION') == 'true':
153*f4a2713aSLionel Sambuc            desktop_environment = 'kde'
154*f4a2713aSLionel Sambuc        elif os.environ.get('GNOME_DESKTOP_SESSION_ID'):
155*f4a2713aSLionel Sambuc            desktop_environment = 'gnome'
156*f4a2713aSLionel Sambuc        else:
157*f4a2713aSLionel Sambuc            try:
158*f4a2713aSLionel Sambuc                info = commands.getoutput('xprop -root _DT_SAVE_MODE')
159*f4a2713aSLionel Sambuc                if ' = "xfce4"' in info:
160*f4a2713aSLionel Sambuc                    desktop_environment = 'xfce'
161*f4a2713aSLionel Sambuc            except (OSError, RuntimeError):
162*f4a2713aSLionel Sambuc                pass
163*f4a2713aSLionel Sambuc
164*f4a2713aSLionel Sambuc        return desktop_environment
165*f4a2713aSLionel Sambuc
166*f4a2713aSLionel Sambuc
167*f4a2713aSLionel Sambuc    def register_X_controllers():
168*f4a2713aSLionel Sambuc        if _iscommand('kfmclient'):
169*f4a2713aSLionel Sambuc            _controllers['kde-open'] = KfmClient()
170*f4a2713aSLionel Sambuc
171*f4a2713aSLionel Sambuc        for command in ('gnome-open', 'exo-open', 'xdg-open'):
172*f4a2713aSLionel Sambuc            if _iscommand(command):
173*f4a2713aSLionel Sambuc                _controllers[command] = Controller(command)
174*f4a2713aSLionel Sambuc
175*f4a2713aSLionel Sambuc    def get():
176*f4a2713aSLionel Sambuc        controllers_map = {
177*f4a2713aSLionel Sambuc            'gnome': 'gnome-open',
178*f4a2713aSLionel Sambuc            'kde': 'kde-open',
179*f4a2713aSLionel Sambuc            'xfce': 'exo-open',
180*f4a2713aSLionel Sambuc        }
181*f4a2713aSLionel Sambuc
182*f4a2713aSLionel Sambuc        desktop_environment = detect_desktop_environment()
183*f4a2713aSLionel Sambuc
184*f4a2713aSLionel Sambuc        try:
185*f4a2713aSLionel Sambuc            controller_name = controllers_map[desktop_environment]
186*f4a2713aSLionel Sambuc            return _controllers[controller_name].open
187*f4a2713aSLionel Sambuc
188*f4a2713aSLionel Sambuc        except KeyError:
189*f4a2713aSLionel Sambuc            if _controllers.has_key('xdg-open'):
190*f4a2713aSLionel Sambuc                return _controllers['xdg-open'].open
191*f4a2713aSLionel Sambuc            else:
192*f4a2713aSLionel Sambuc                return webbrowser.open
193*f4a2713aSLionel Sambuc
194*f4a2713aSLionel Sambuc
195*f4a2713aSLionel Sambuc    if os.environ.get("DISPLAY"):
196*f4a2713aSLionel Sambuc        register_X_controllers()
197*f4a2713aSLionel Sambuc    _open = get()
198*f4a2713aSLionel Sambuc
199*f4a2713aSLionel Sambuc
200*f4a2713aSLionel Sambucdef open(filename):
201*f4a2713aSLionel Sambuc    '''Open a file or an URL in the registered default application.'''
202*f4a2713aSLionel Sambuc
203*f4a2713aSLionel Sambuc    return _open(filename)
204