# coding: utf-8
# This file is part of libdesktop
# The MIT License (MIT)
#
# Copyright (c) 2016 Bharadwaj Raju
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
import subprocess as sp
import tempfile
import os
import shlex
from libdesktop import desktopfile
from libdesktop import system
[docs]def mac_app_exists(app):
'''Check if 'app' is installed (OS X).
Check if the given applications is installed on this OS X system.
Args:
app (str): The application name.
Returns:
bool: Is the app installed or not?
'''
APP_CHECK_APPLESCRIPT = '''try
tell application "Finder"
set appname to name of application file id "%s"
return 0
end tell
on error err_msg number err_num
return 1
end try'''
with open('/tmp/app_check.AppleScript', 'w') as f:
f.write(APP_CHECK_APPLESCRIPT % app)
app_check_proc = sp.Popen(
['osascript', '-e', '/tmp/app_check.AppleScript'])
if app_check_proc.wait() != 0:
return False
else:
return True
[docs]def open_file_with_default_program(file_path,
background=False, return_cmd=False):
'''Opens a file with the default program for that type.
Open the file with the user's preferred application.
Args:
file_path (str) : Path to the file to be opened.
background (bool): Run the program in the background, instead of waiting for completion. Defaults to ``False``.
return_cmd (bool): Returns the command to run the program (str) instead of running it. Defaults to ``False``.
Returns:
str: Only if ``return_cmd``, the command to run the program is returned instead of running it. Else returns nothing.
'''
desktop_env = system.get_name()
if desktop_env == 'windows':
open_file_cmd = 'explorer.exe ' + "'%s'" % file_path
elif desktop_env == 'mac':
open_file_cmd = 'open ' + "'%s'" % file_path
else:
file_mime_type = system.get_cmd_out(
['xdg-mime', 'query', 'filetype', file_path])
desktop_file = system.get_cmd_out(
['xdg-mime', 'query', 'default', file_mime_type])
open_file_cmd = desktopfile.execute(desktopfile.locate(
desktop_file)[0], files=[file_path], return_cmd=True)
if return_cmd:
return open_file_cmd
else:
def_program_proc = sp.Popen(open_file_cmd, shell=True)
if not background:
def_program_proc.wait()
[docs]def terminal(exec_='', background=False, shell_after_cmd_exec=False,
keep_open_after_cmd_exec=False, return_cmd=False):
'''Start the default terminal emulator.
Start the user's preferred terminal emulator, optionally running a command in it.
**Order of starting**
Windows:
Powershell
Mac:
- iTerm2
- Terminal.app
Linux/Unix:
- ``$TERMINAL``
- ``x-terminal-emulator``
- Terminator
- Desktop environment's terminal
- gnome-terminal
- urxvt
- rxvt
- xterm
Args:
exec\_ (str) : An optional command to run in the opened terminal emulator. Defaults to empty (no command).
background (bool): Run the terminal in the background, instead of waiting for completion. Defaults to ``False``.
shell_after_cmd_exec (bool): Start the user's shell after running the command (see exec_). Defaults to `False`.
return_cmd (bool): Returns the command used to start the terminal (str) instead of running it. Defaults to ``False``.
Returns:
str: Only if ``return_cmd``, returns the command to run the terminal instead of running it. Else returns nothing.
'''
desktop_env = system.get_name()
if not exec_:
shell_after_cmd_exec = True
if desktop_env == 'windows':
terminal_cmd_str = 'start powershell.exe'
if desktop_env == 'mac':
# Try iTerm2 first, apparently most popular Mac Terminal
if mac_app_exists('iTerm2'):
terminal_cmd_str = 'open -a iTerm2'
else:
terminal_cmd_str = 'open -a Terminal'
else:
# sensible-terminal
if os.getenv('TERMINAL'):
# Not everywhere, but if user *really* has a preference, they will
# set this
terminal_cmd_str = os.getenv('TERMINAL')
elif system.is_in_path('x-terminal-emulator'):
# This is a convenience script that launches terminal based on
# user preferences.
# This is not available on some distros (but most have it)
# so try this first
terminal_cmd_str = 'x-terminal-emulator'
elif system.is_in_path('terminator'):
terminal_cmd_str = 'terminator'
elif desktop_env in ['gnome', 'unity', 'cinnamon', 'gnome2']:
terminal_cmd_str = 'gnome-terminal'
elif desktop_env == 'xfce4':
terminal_cmd_str = 'xfce4-terminal'
elif desktop_env == 'kde' or desktop_env == 'trinity':
terminal_cmd_str = 'konsole'
elif desktop_env == 'mate':
terminal_cmd_str = 'mate-terminal'
elif desktop_env == 'i3':
terminal_cmd_str = 'i3-sensible-terminal'
elif desktop_env == 'pantheon':
terminal_cmd_str = 'pantheon-terminal'
elif desktop_env == 'enlightenment':
terminal_cmd_str = 'terminology'
elif desktop_env == 'lxde' or desktop_env == 'lxqt':
terminal_cmd_str = 'lxterminal'
else:
if system.is_in_path('gnome-terminal'):
terminal_cmd_str = 'gnome-terminal'
elif system.is_in_path('urxvt'):
terminal_cmd_str = 'urxvt'
elif system.is_in_path('rxvt'):
terminal_cmd_str = 'rxvt'
elif system.is_in_path('xterm'):
terminal_cmd_str = 'xterm'
if exec_:
if desktop_env == 'windows':
if keep_open_after_cmd_exec and not shell_after_cmd_exec:
exec_ += '; pause'
if os.path.isfile(exec_):
terminal_cmd_str += exec_
else:
terminal_cmd_str += ' -Command ' + '"' + exec_ + '"'
if shell_after_cmd_exec:
terminal_cmd_str += ' -NoExit'
else:
if keep_open_after_cmd_exec and not shell_after_cmd_exec:
exec_ += '; read'
if shell_after_cmd_exec:
exec_ += '; ' + os.getenv('SHELL')
if desktop_env == 'mac':
terminal_cmd_str += ' sh -c {}'.format(shlex.quote(exec_))
else:
terminal_cmd_str += ' -e {}'.format(
shlex.quote('sh -c {}'.format(shlex.quote(exec_))))
if return_cmd:
return terminal_cmd_str
terminal_proc = sp.Popen([terminal_cmd_str], shell=True, stdout=sp.PIPE)
if not background:
# Wait for process to complete
terminal_proc.wait()
[docs]def text_editor(file='', background=False, return_cmd=False):
'''Starts the default graphical text editor.
Start the user's preferred graphical text editor, optionally with a file.
Args:
file (str) : The file to be opened with the editor. Defaults to an empty string (i.e. no file).
background (bool): Runs the editor in the background, instead of waiting for completion. Defaults to ``False``.
return_cmd (bool): Returns the command (str) to run the editor instead of running it. Defaults to ``False``.
Returns:
str: Only if ``return_cmd``, the command to run the editor is returned. Else returns nothing.
'''
desktop_env = system.get_name()
if desktop_env == 'windows':
editor_cmd_str = system.get_cmd_out(
['ftype', 'textfile']).split('=', 1)[1]
elif desktop_env == 'mac':
editor_cmd_str = 'open -a' + system.get_cmd_out(
['def',
'read',
'com.apple.LaunchServices',
'LSHandlers'
'-array'
'{LSHandlerContentType=public.plain-text;}']
)
else:
# Use def handler for MIME-type text/plain
editor_cmd_str = system.get_cmd_out(
['xdg-mime', 'query', 'default', 'text/plain'])
if '\n' in editor_cmd_str:
# Sometimes locate returns multiple results
# use first one
editor_cmd_str = editor_cmd_str.split('\n')[0]
if editor_cmd_str.endswith('.desktop'):
# We don't use desktopfile.execute() in order to have working
# return_cmd and background
editor_cmd_str = desktopfile.parse(
desktopfile.locate(editor_cmd_str)[0])['Exec']
for i in editor_cmd_str.split():
if i.startswith('%'):
# %-style formatters
editor_cmd_str = editor_cmd_str.replace(i, '')
if i == '--new-document':
# Gedit
editor_cmd_str = editor_cmd_str.replace(i, '')
if file:
editor_cmd_str += ' {}'.format(shlex.quote(file))
if return_cmd:
return editor_cmd_str
text_editor_proc = sp.Popen([editor_cmd_str], shell=True)
if not background:
text_editor_proc.wait()