# Copyright (C) 2009, 2010 Roman Zimbelmann <romanz@lavabit.com>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
This is the default ranger configuration file for filetype detection
and application handling.
You can place this file in your ~/.config/ranger/ directory and it will be used
instead of this one. Though, to minimize your effort when upgrading ranger,
you may want to subclass CustomApplications rather than making a full copy.
This example modifies the behaviour of "feh" and adds a custom media player:
#### start of the ~/.config/ranger/apps.py example
from ranger.defaults.apps import CustomApplications as DefaultApps
from ranger.api.apps import *
class CustomApplications(DefaultApps):
def app_kaffeine(self, context):
return 'kaffeine', context
def app_feh_fullscreen_by_default(self, context):
return 'feh', '-F', context
def app_default(self, context):
f = context.file #shortcut
if f.video or f.audio:
return self.app_kaffeine(context)
if f.image and context.mode == 0:
return self.app_feh_fullscreen_by_default(context)
return DefaultApps.app_default(self, context)
#### end of the example
"""
import ranger
from ranger.api.apps import *
from ranger.ext.get_executables import get_executables
class CustomApplications(Applications):
def app_default(self, c):
"""How to determine the default application?"""
f = c.file
# ranger can act as a file chooser when running with --choosefile=...
if ranger.arg.choosefile:
open(ranger.arg.choosefile, 'w').write(f.path)
raise SystemExit()
if f.basename.lower() == 'makefile':
return self.either(c, 'make')
if f.extension is not None:
if f.extension in ('pdf', ):
return self.either(c, 'evince', 'zathura', 'apvlv')
if f.extension == 'djvu':
return self.either(c, 'evince')
if f.extension in ('xml', ):
return self.either(c, 'editor')
if f.extension in ('html', 'htm', 'xhtml'):
return self.either(c, 'firefox', 'opera', 'jumanji',
'luakit', 'elinks', 'lynx')
if f.extension == 'swf':
return self.either(c, 'firefox', 'opera', 'jumanji', 'luakit')
if f.extension == 'nes':
return self.either(c, 'fceux')
if f.extension in ('swc', 'smc'):
return self.either(c, 'zsnes')
if f.extension in ('odt', 'ods', 'odp', 'odf', 'odg',
'doc', 'xls'):
return self.either(c, 'libreoffice', 'soffice', 'ooffice')
if f.mimetype is not None:
if INTERPRETED_LANGUAGES.match(f.mimetype):
return self.either(c, 'edit_or_run')
if f.container:
return self.either(c, 'aunpack', 'file_roller')
if f.video or f.audio:
if f.video:
c.flags += 'd'
return self.either(c, 'mplayer', 'smplayer', 'vlc', 'totem')
if f.image:
if c.mode in (11, 12, 13, 14):
return self.either(c, 'set_bg_with_feh')
else:
return self.either(c, 'sxiv', 'feh', 'eog', 'mirage')
if f.document or f.filetype.startswith('text') or f.size == 0:
return self.either(c, 'editor')
# You can put this at the top of the function and mimeopen will
# always be used for every file.
return self.either(c, 'mimeopen')
# ----------------------------------------- application definitions
# Note: Trivial application definitions are at the bottom
def app_pager(self, c):
return 'less', '-R', c
def app_editor(self, c):
try:
default_editor = os.environ['EDITOR']
except KeyError:
pass
else:
parts = default_editor.split()
exe_name = os.path.basename(parts[0])
if exe_name in get_executables():
return tuple(parts) + tuple(c)
return self.either(c, 'vim', 'emacs', 'nano')
def app_edit_or_run(self, c):
if c.mode is 1:
return self.app_self(c)
return self.app_editor(c)
@depends_on('mplayer')
def app_mplayer(self, c):
if c.mode is 1:
return 'mplayer', '-fs', c
elif c.mode is 2:
args = "mplayer -fs -sid 0 -vfm ffmpeg -lavdopts " \
"lowres=1:fast:skiploopfilter=all:threads=8".split()
args.extend(c)
return args
elif c.mode is 3:
return 'mplayer', '-mixer', 'software', c
else:
return 'mplayer', c
@depends_on('feh')
def app_set_bg_with_feh(self, c):
c.flags += 'd'
arg = {11: '--bg-scale', 12: '--bg-tile', 13: '--bg-center',
14: '--bg-fill'}
if c.mode in arg:
return 'feh', arg[c.mode], c.file.path
return 'feh', arg[11], c.file.path
@depends_on('feh')
def app_feh(self, c):
c.flags += 'd'
if c.mode is 0 and len(c.files) is 1: # view all files in the cwd
images = (f.basename for f in self.fm.env.cwd.files if f.image)
return 'feh', '--start-at', c.file.basename, images
return 'feh', c
@depends_on('sxiv')
def app_sxiv(self, c):
c.flags = 'd' + c.flags
if len(c.files) is 1:
images = [f.basename for f in self.fm.env.cwd.files if f.image]
try:
position = images.index(c.file.basename) + 1
except:
return None
return 'sxiv', '-n', str(position), images
return 'sxiv', c
@depends_on('aunpack')
def app_aunpack(self, c):
if c.mode is 0:
c.flags += 'p'
return 'aunpack', '-l', c.file.path
return 'aunpack', c.file.path
@depends_on('file-roller')
def app_file_roller(self, c):
c.flags += 'd'
return 'file-roller', c.file.path
@depends_on('make')
def app_make(self, c):
if c.mode is 0:
return "make"
if c.mode is 1:
return "make", "install"
if c.mode is 2:
return "make", "clear"
@depends_on('java')
def app_java(self, c):
def strip_extensions(file):
if '.' in file.basename:
return file.path[:file.path.index('.')]
return file.path
files_without_extensions = map(strip_extensions, c.files)
return "java", files_without_extensions
@depends_on('totem')
def app_totem(self, c):
if c.mode is 0:
return "totem", c
if c.mode is 1:
return "totem", "--fullscreen", c
@depends_on('mimeopen')
def app_mimeopen(self, c):
if c.mode is 0:
return "mimeopen", c
if c.mode is 1:
# Will ask user to select program
# aka "Open with..."
return "mimeopen", "--ask", c
# Often a programs invocation is trivial. For example:
# vim test.py readme.txt [...]
# This could be implemented like:
# @depends_on("vim")
# def app_vim(self, context):
# return "vim", context
# Instead of creating such a generic function for each program, just add
# its name here and it will be automatically done for you.
CustomApplications.generic('vim', 'fceux', 'elinks', 'wine',
'zsnes', 'javac')
# By setting flags='d', this programs will not block ranger's terminal:
CustomApplications.generic('opera', 'firefox', 'apvlv', 'evince',
'zathura', 'gimp', 'mirage', 'eog', flags='d')
# What filetypes are recognized as scripts for interpreted languages?
# This regular expression is used in app_default()
INTERPRETED_LANGUAGES = re.compile(r'''
^(text|application)/x-(
haskell|perl|python|ruby|sh
)$''', re.VERBOSE)