summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/api/apps.py168
-rw-r--r--ranger/core/fm.py3
-rw-r--r--ranger/core/helper.py25
-rw-r--r--ranger/core/main.py13
-rw-r--r--ranger/core/runner.py13
-rw-r--r--ranger/defaults/apps.py325
-rw-r--r--ranger/defaults/commands.py12
7 files changed, 12 insertions, 547 deletions
diff --git a/ranger/api/apps.py b/ranger/api/apps.py
deleted file mode 100644
index 8fd5d870..00000000
--- a/ranger/api/apps.py
+++ /dev/null
@@ -1,168 +0,0 @@
-# Copyright (C) 2009, 2010, 2011  Roman Zimbelmann <romanz@lavabit.com>
-# This software is distributed under the terms of the GNU GPL version 3.
-
-import os, sys, re
-from ranger.api import *
-from ranger.ext.iter_tools import flatten
-from ranger.ext.get_executables import get_executables
-from ranger.core.runner import Context
-from ranger.core.shared import FileManagerAware
-
-
-class Applications(FileManagerAware):
-	"""
-	This class contains definitions on how to run programs and should
-	be extended in ranger.apps
-
-	The user can decide what program to run, and if he uses eg. 'vim', the
-	function app_vim() will be called.  However, usually the user
-	simply wants to "start" the file without specific instructions.
-	In such a case, app_default() is called, where you should examine
-	the context and decide which program to use.
-
-	All app functions have a name starting with app_ and return a string
-	containing the whole command or a tuple containing a list of the
-	arguments. They are supplied with one argument, which is the
-	AppContext instance.
-
-	You should define at least app_default, app_pager and app_editor since
-	internal functions depend on those.  Here are sample implementations:
-
-	def app_default(self, context):
-		if context.file.media:
-			if context.file.video:
-				# detach videos from the filemanager
-				context.flags += 'd'
-			return self.app_mplayer(context)
-		else:
-			return self.app_editor(context)
-
-	def app_pager(self, context):
-		return 'less', context
-
-	def app_editor(self, context):
-		return ('vim', context)
-	"""
-
-	def _meets_dependencies(self, fnc):
-		try:
-			deps = fnc.dependencies
-		except AttributeError:
-			return True
-
-		for dep in deps:
-			if dep == 'X':
-				if 'DISPLAY' not in os.environ or not os.environ['DISPLAY']:
-					return False
-				continue
-			if hasattr(dep, 'dependencies') \
-			and not self._meets_dependencies(dep):
-				return False
-			if dep not in get_executables():
-				return False
-
-		return True
-
-	def either(self, context, *args):
-		for app in args:
-			try:
-				application_handler = getattr(self, 'app_' + app)
-			except AttributeError:
-				if app in get_executables():
-					return _generic_app(app, context)
-				continue
-			if self._meets_dependencies(application_handler):
-				return application_handler(context)
-
-	def app_self(self, context):
-		"""Run the file itself"""
-		return "./" + context.file.basename
-
-	def get(self, app):
-		"""Looks for an application, returns app_default if it doesn't exist"""
-		try:
-			return getattr(self, 'app_' + app)
-		except AttributeError:
-			return self.app_default
-
-	def apply(self, app, context):
-		if not app:
-			app = 'default'
-		try:
-			handler = getattr(self, 'app_' + app)
-		except AttributeError:
-			if app in get_executables():
-				return [app] + list(context)
-			handler = self.app_default
-		arguments = handler(context)
-		# flatten
-		if isinstance(arguments, str):
-			return arguments
-		if arguments is None:
-			return None
-		result = []
-		for obj in arguments:
-			if isinstance(obj, (tuple, list, Context)):
-				result.extend(obj)
-			else:
-				result.append(obj)
-		return result
-
-	def has(self, app):
-		"""Returns whether an application is defined"""
-		return hasattr(self, 'app_' + app)
-
-	def all(self):
-		"""Returns a list with all application functions"""
-		result = set()
-		# go through all the classes in the mro (method resolution order)
-		# so subclasses will return the apps of their superclasses.
-		for cls in self.__class__.__mro__:
-			result |= set(m[4:] for m in cls.__dict__ if m.startswith('app_'))
-		return sorted(result)
-
-	@classmethod
-	def generic(cls, *args, **keywords):
-		flags = 'flags' in keywords and keywords['flags'] or ""
-		deps = 'deps' in keywords and keywords['deps'] or ()
-		for name in args:
-			assert isinstance(name, str)
-			if not hasattr(cls, "app_" + name):
-				fnc = _generic_wrapper(name, flags=flags)
-				fnc = depends_on(*deps)(fnc)
-				setattr(cls, "app_" + name, fnc)
-
-
-def tup(*args):
-	"""
-	This helper function creates a tuple out of the arguments.
-
-	('a', ) + tuple(some_iterator)
-	is equivalent to:
-	tup('a', *some_iterator)
-	"""
-	return args
-
-
-def depends_on(*args):
-	args = tuple(flatten(args))
-	def decorator(fnc):
-		try:
-			fnc.dependencies += args
-		except:
-			fnc.dependencies  = args
-		return fnc
-	return decorator
-
-
-def _generic_app(name, context, flags=''):
-	"""Use this function when no other information is given"""
-	context.flags += flags
-	return name, context
-
-
-def _generic_wrapper(name, flags=''):
-	"""Wraps _generic_app into a method for Applications"""
-	assert isinstance(name, str)
-	return depends_on(name)(lambda self, context:
-			_generic_app(name, context, flags))
diff --git a/ranger/core/fm.py b/ranger/core/fm.py
index 77c0d7cc..1e134854 100644
--- a/ranger/core/fm.py
+++ b/ranger/core/fm.py
@@ -81,8 +81,7 @@ class FM(Actions, SignalDispatcher):
 
 		def mylogfunc(text):
 			self.notify(text, bad=True)
-		self.run = Runner(ui=self.ui, apps=self.apps,
-				logfunc=mylogfunc, fm=self)
+		self.run = Runner(ui=self.ui, logfunc=mylogfunc, fm=self)
 
 		self.env.signal_bind('cd', self._update_current_tab)
 
diff --git a/ranger/core/helper.py b/ranger/core/helper.py
index 07c5f0b5..31fa8623 100644
--- a/ranger/core/helper.py
+++ b/ranger/core/helper.py
@@ -29,7 +29,7 @@ def parse_arguments():
 			help="don't touch/require any config files. ")
 	parser.add_option('--copy-config', type='string', metavar='which',
 			help="copy the default configs to the local config directory. "
-			"Possible values: all, rc, apps, commands, options, scope")
+			"Possible values: all, rc, rifle, commands, options, scope")
 	parser.add_option('--fail-unless-cd', action='store_true',
 			help="experimental: return the exit code 1 if ranger is" \
 					"used to run a file (with `ranger filename`)")
@@ -95,13 +95,6 @@ def load_settings(fm, clean):
 		except ImportError:
 			pass
 
-		# Load apps
-		try:
-			import apps
-		except ImportError:
-			from ranger.defaults import apps
-		fm.apps = apps.CustomApplications()
-
 		# Load rc.conf
 		custom_conf = fm.confpath('rc.conf')
 		default_conf = fm.relpath('defaults', 'rc.conf')
@@ -138,25 +131,9 @@ def load_settings(fm, clean):
 
 		allow_access_to_confdir(ranger.arg.confdir, False)
 	else:
-		from ranger.defaults import apps
-		fm.apps = apps.CustomApplications()
 		fm.source(fm.relpath('defaults', 'rc.conf'))
 
 
-def load_apps(fm, clean):
-	import ranger
-	if not clean:
-		allow_access_to_confdir(ranger.arg.confdir, True)
-		try:
-			import apps
-		except ImportError:
-			from ranger.defaults import apps
-		allow_access_to_confdir(ranger.arg.confdir, False)
-	else:
-		from ranger.defaults import apps
-	fm.apps = apps.CustomApplications()
-
-
 def allow_access_to_confdir(confdir, allow):
 	if allow:
 		try:
diff --git a/ranger/core/main.py b/ranger/core/main.py
index 87bf8235..bf6c7426 100644
--- a/ranger/core/main.py
+++ b/ranger/core/main.py
@@ -73,12 +73,15 @@ def main():
 		elif os.path.isfile(target):
 			def print_function(string):
 				print(string)
-			from ranger.core.runner import Runner
-			from ranger.fsobject import File
+			from ranger.ext.rifle import Rifle
 			fm = FM()
-			runner = Runner(logfunc=print_function, fm=fm)
-			load_apps(runner, arg.clean)
-			runner(files=[File(target)], mode=arg.mode, flags=arg.flags)
+			if not arg.clean and os.path.isfile(fm.confpath('rifle.conf')):
+				rifleconf = fm.confpath('rifle.conf')
+			else:
+				rifleconf = fm.relpath('defaults/rifle.conf')
+			rifle = Rifle(rifleconf)
+			rifle.reload_config()
+			rifle.execute(targets)
 			return 1 if arg.fail_unless_cd else 0
 
 	crash_traceback = None
diff --git a/ranger/core/runner.py b/ranger/core/runner.py
index 7491e49c..0f2bc9c7 100644
--- a/ranger/core/runner.py
+++ b/ranger/core/runner.py
@@ -85,11 +85,10 @@ class Context(object):
 
 
 class Runner(object):
-	def __init__(self, ui=None, logfunc=None, apps=None, fm=None):
+	def __init__(self, ui=None, logfunc=None, fm=None):
 		self.ui = ui
 		self.fm = fm
 		self.logfunc = logfunc
-		self.apps = apps
 		self.zombies = set()
 
 	def _log(self, text):
@@ -128,16 +127,6 @@ class Runner(object):
 				flags=flags, wait=wait, popen_kws=popen_kws,
 				file=files and files[0] or None)
 
-		if self.apps:
-			if try_app_first and action is not None:
-				test = self.apps.apply(app, context)
-				if test:
-					action = test
-			if action is None:
-				action = self.apps.apply(app, context)
-				if action is None:
-					return self._log("No action found!")
-
 		if action is None:
 			return self._log("No way of determining the action!")
 
diff --git a/ranger/defaults/apps.py b/ranger/defaults/apps.py
deleted file mode 100644
index 1619eb1e..00000000
--- a/ranger/defaults/apps.py
+++ /dev/null
@@ -1,325 +0,0 @@
-# -*- coding: utf-8 -*-
-# Copyright (C) 2009, 2010, 2011  Roman Zimbelmann <romanz@lavabit.com>
-# This configuration file is licensed under the same terms as ranger.
-# ===================================================================
-# This is the configuration file for file type detection and application
-# handling.  It's all in python; lines beginning with # are comments.
-#
-# You can customize this in the file ~/.config/ranger/apps.py.
-# It has the same syntax as this file.  In fact, you can just copy this
-# file there with `ranger --copy-config=apps' and make your modifications.
-# But make sure you update your configs when you update ranger.
-#
-# In order to add application definitions "on top of" the default ones
-# in your ~/.config/ranger/apps.py, you should subclass the class defined
-# here like this:
-#
-#   from ranger.defaults.apps import CustomApplications as DefaultApps
-#   class CustomApplications(DeafultApps):
-#       <your definitions here>
-#
-# To override app_defaults, you can write something like:
-#
-#       def app_defaults(self, c):
-#           f = c.file
-#           if f.extension == 'lol':
-#               return "lolopener", c
-#           return DefaultApps.app_default(self, c)
-#
-# ===================================================================
-# This system is based on things called MODES and FLAGS.  You can read
-# in the man page about them.  To remind you, here's a list of all flags.
-# An uppercase flag inverts previous flags of the same name.
-#     s   Silent mode.  Output will be discarded.
-#     d   Detach the process.  (Run in background)
-#     p   Redirect output to the pager
-#     w   Wait for an Enter-press when the process is done
-#     c   Run the current file only, instead of the selection
-#     r   Run application with root privilege 
-#     t   Run application in a new terminal window
-#
-# To implement flags in this file, you could do this:
-#     context.flags += "d"
-# Another example:
-#     context.flags += "Dw"
-#
-# To implement modes in this file, you can do something like:
-#     if context.mode == 1:
-#         <run in one way>
-#     elif context.mode == 2:
-#         <run in another way>
-#
-# ===================================================================
-# The methods are called with a "context" object which provides some
-# attributes that transfer information.  Relevant attributes are:
-#
-# mode -- a number, mainly used in determining the action in app_xyz()
-# flags -- a string with flags which change the way programs are run
-# files -- a list containing files, mainly used in app_xyz
-# filepaths -- a list of the paths of each file
-# file -- an arbitrary file from that list (or None)
-# fm -- the filemanager instance
-# popen_kws -- keyword arguments which are directly passed to Popen
-#
-# ===================================================================
-# The return value of the functions should be either:
-# 1. A reference to another app, like:
-#     return self.app_editor(context)
-#
-# 2. A call to the "either" method, which uses the first program that
-# is installed on your system.  If none are installed, None is returned.
-#     return self.either(context, "libreoffice", "soffice", "ooffice")
-#
-# 3. A tuple of arguments that should be run.
-#     return "mplayer", "-fs", context.file.path
-# If you use lists instead of strings, they will be flattened:
-#     args = ["-fs", "-shuf"]
-#     return "mplayer", args, context.filepaths
-# "context.filepaths" can, and will often be abbreviated with just "context":
-#     return "mplayer", context
-#
-# 4. "None" to indicate that no action was found.
-#     return None
-#
-# ===================================================================
-# When using the "either" method, ranger determines which program to
-# pick by looking at its dependencies.  You can set dependencies by
-# adding the decorator "depends_on":
-#     @depends_on("vim")
-#     def app_vim(self, context):
-#         ....
-# There is a special keyword which you can use as a dependence: "X"
-# This ensures that the program will only run when X is running.
-# ===================================================================
-
-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
-
-		if f.basename.lower() == 'makefile' and c.mode == 1:
-			made = self.either(c, 'make')
-			if made: return made
-
-		if f.extension is not None:
-			if f.extension in ('pdf', ):
-				return self.either(c, 'llpp', 'zathura', 'mupdf', 'apvlv',
-						'evince', 'okular', 'epdfview')
-			if f.extension == 'djvu':
-				return self.either(c, 'evince')
-			if f.extension in ('xml', 'csv'):
-				return self.either(c, 'editor')
-			if f.extension == 'mid':
-				return self.either(c, 'wildmidi')
-			if f.extension in ('html', 'htm', 'xhtml') or f.extension == 'swf':
-				c.flags += 'd'
-				handler = self.either(c,
-						'luakit', 'uzbl', 'vimprobable', 'vimprobable2', 'jumanji',
-						'firefox', 'seamonkey', 'iceweasel', 'opera',
-						'surf', 'midori', 'epiphany', 'konqueror')
-				# Only return if some program was found:
-				if handler:
-					return handler
-			if f.extension in ('html', 'htm', 'xhtml'):
-				# These browsers can't handle flash, so they're not called above.
-				c.flags += 'D'
-				return self.either(c, 'elinks', 'links', 'links2', 'lynx', 'w3m')
-			if f.extension == 'nes':
-				return self.either(c, 'fceux')
-			if f.extension in ('swc', 'smc', 'sfc'):
-				return self.either(c, 'zsnes')
-			if f.extension == 'doc':
-				return self.either(c, 'abiword', 'libreoffice',
-						'soffice', 'ooffice')
-			if f.extension in ('odt', 'ods', 'odp', 'odf', 'odg', 'sxc',
-					'stc', 'xls', 'xlsx', 'xlt', 'xlw', 'gnm', 'gnumeric'):
-				return self.either(c, 'gnumeric', 'kspread',
-						'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, 'smplayer', 'gmplayer', 'mplayer2',
-					'mplayer', '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('mplayer2')
-	def app_mplayer2(self, c):
-		args = list(self.app_mplayer(c))
-		args[0] += '2'
-		return args
-
-	# A dependence on "X" means: this programs requires a running X server!
-	@depends_on('feh', 'X')
-	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', 'X')
-	def app_feh(self, c):
-		c.flags += 'd'
-		if c.mode is 0 and len(c.files) is 1 and self.fm.env.cwd:
-			# 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', 'X')
-	def app_sxiv(self, c):
-		c.flags = 'd' + c.flags
-		if len(c.files) is 1 and self.fm.env.cwd:
-			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', 'X')
-	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', 'X')
-	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
-#
-# But this is redundant and ranger does this automatically.  However, sometimes
-# you want to change some properties like flags or dependencies.
-# The method "generic" defines a generic method for the given programs which
-# looks like the one above, but you can add dependencies and flags here.
-# Add programs (that are not defined yet) here if they should only run in X:
-CustomApplications.generic('fceux', 'wine', 'zsnes', deps=['X'])
-
-# Add those which should only run in X AND should be detached/forked here:
-CustomApplications.generic(
-	'luakit', 'uzbl', 'vimprobable', 'vimprobable2', 'jumanji',
-	'firefox', 'seamonkey', 'iceweasel', 'opera',
-	'surf', 'midori', 'epiphany', 'konqueror',
-	'evince', 'zathura', 'apvlv', 'okular', 'epdfview', 'mupdf', 'llpp',
-	'eog', 'mirage', 'gimp',
-	'libreoffice', 'soffice', 'ooffice', 'gnumeric', 'kspread', 'abiword',
-	'gmplayer', 'smplayer', 'vlc',
-			flags='d', deps=['X'])
-
-# 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)
diff --git a/ranger/defaults/commands.py b/ranger/defaults/commands.py
index a89dd0f7..054bb020 100644
--- a/ranger/defaults/commands.py
+++ b/ranger/defaults/commands.py
@@ -311,18 +311,8 @@ class open_with(Command):
 
 		return app, flags, int(mode)
 
-	def tab(self):
-		data = self.rest(1)
-		if ' ' not in data:
-			all_apps = self.fm.apps.all()
-			if all_apps:
-				return (self.firstpart + app for app in all_apps if app.startswith(data))
-
-		return None
-
 	def _is_app(self, arg):
-		return self.fm.apps.has(arg) or \
-			(not self._is_flags(arg) and arg in get_executables())
+		return (not self._is_flags(arg) and arg in get_executables())
 
 	def _is_flags(self, arg):
 		return all(x in ALLOWED_FLAGS for x in arg)