summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile16
-rwxr-xr-xranger.py14
-rw-r--r--ranger/__init__.py15
-rw-r--r--ranger/api/apps.py180
-rw-r--r--ranger/api/commands.py14
-rw-r--r--ranger/api/options.py14
-rw-r--r--ranger/colorschemes/default.py14
-rw-r--r--ranger/colorschemes/default88.py14
-rw-r--r--ranger/colorschemes/jungle.py14
-rw-r--r--ranger/colorschemes/snow.py14
-rw-r--r--ranger/container/bookmarks.py14
-rw-r--r--ranger/container/history.py14
-rw-r--r--ranger/container/settingobject.py14
-rw-r--r--ranger/container/tags.py14
-rw-r--r--ranger/core/actions.py62
-rw-r--r--ranger/core/environment.py14
-rw-r--r--ranger/core/fm.py45
-rw-r--r--ranger/core/helper.py42
-rw-r--r--ranger/core/loader.py53
-rw-r--r--ranger/core/main.py30
-rw-r--r--ranger/core/runner.py31
-rw-r--r--ranger/core/shared.py14
-rw-r--r--ranger/defaults/apps.py325
-rw-r--r--ranger/defaults/commands.py12
-rw-r--r--ranger/defaults/rc.conf2
-rw-r--r--ranger/defaults/rifle.conf181
-rw-r--r--ranger/ext/accumulator.py14
-rw-r--r--ranger/ext/cached_function.py14
-rw-r--r--ranger/ext/curses_interrupt_handler.py14
-rw-r--r--ranger/ext/direction.py14
-rw-r--r--ranger/ext/get_executables.py20
-rw-r--r--ranger/ext/human_readable.py14
-rw-r--r--ranger/ext/iter_tools.py14
-rw-r--r--ranger/ext/keybinding_parser.py14
-rw-r--r--ranger/ext/mount_path.py14
-rw-r--r--ranger/ext/next_available_filename.py14
-rw-r--r--ranger/ext/openstruct.py14
-rw-r--r--ranger/ext/relative_symlink.py14
-rwxr-xr-xranger/ext/rifle.py387
-rw-r--r--ranger/ext/shell_escape.py14
-rw-r--r--ranger/ext/signals.py14
-rw-r--r--ranger/ext/spawn.py14
-rw-r--r--ranger/ext/widestring.py14
-rw-r--r--ranger/fsobject/directory.py14
-rw-r--r--ranger/fsobject/file.py14
-rw-r--r--ranger/fsobject/fsobject.py14
-rw-r--r--ranger/gui/ansi.py14
-rw-r--r--ranger/gui/bar.py14
-rw-r--r--ranger/gui/color.py14
-rw-r--r--ranger/gui/colorscheme.py14
-rw-r--r--ranger/gui/context.py14
-rw-r--r--ranger/gui/curses_shortcuts.py14
-rw-r--r--ranger/gui/displayable.py14
-rw-r--r--ranger/gui/mouse_event.py14
-rw-r--r--ranger/gui/ui.py14
-rw-r--r--ranger/gui/widgets/browsercolumn.py14
-rw-r--r--ranger/gui/widgets/browserview.py30
-rw-r--r--ranger/gui/widgets/console.py15
-rw-r--r--ranger/gui/widgets/pager.py14
-rw-r--r--ranger/gui/widgets/statusbar.py14
-rw-r--r--ranger/gui/widgets/taskview.py14
-rw-r--r--ranger/gui/widgets/titlebar.py14
-rwxr-xr-xsetup.py17
63 files changed, 756 insertions, 1337 deletions
diff --git a/Makefile b/Makefile
index f13de38d..20cf6f25 100644
--- a/Makefile
+++ b/Makefile
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 NAME = ranger
 VERSION = $(shell grep -m 1 -o '[0-9][0-9.]\+' README)
@@ -72,7 +60,7 @@ doc: cleandoc
 test:
 	@for FILE in $(shell grep -IHm 1 doctest -r ranger | cut -d: -f1); do \
 		echo "Testing $$FILE..."; \
-		PYTHONPATH=".:"$$PYTHONPATH ${PYTHON} $$FILE; \
+		RANGER_DOCTEST=1 PYTHONPATH=".:"$$PYTHONPATH ${PYTHON} $$FILE; \
 	done
 
 man:
diff --git a/ranger.py b/ranger.py
index c763a8d9..efd81f4d 100755
--- a/ranger.py
+++ b/ranger.py
@@ -1,19 +1,7 @@
 #!/usr/bin/python -O
 # ranger - a vim-inspired file manager for the console  (coding: utf-8)
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 # =====================
 # This embedded bash script can be executed by sourcing this file.
diff --git a/ranger/__init__.py b/ranger/__init__.py
index ae9229b3..735ed527 100644
--- a/ranger/__init__.py
+++ b/ranger/__init__.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 A console file manager with VI key bindings.
@@ -34,6 +22,7 @@ RANGERDIR = os.path.dirname(__file__)
 TICKS_BEFORE_COLLECTING_GARBAGE = 100
 TIME_BEFORE_FILE_BECOMES_GARBAGE = 1200
 MACRO_DELIMITER = '%'
+DEFAULT_PAGER = 'less'
 LOGFILE = '/tmp/ranger_errorlog'
 USAGE = '%prog [options] [path/filename]'
 STABLE = True
diff --git a/ranger/api/apps.py b/ranger/api/apps.py
deleted file mode 100644
index 56f8afd2..00000000
--- a/ranger/api/apps.py
+++ /dev/null
@@ -1,180 +0,0 @@
-# Copyright (C) 2009, 2010, 2011  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/>.
-
-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/api/commands.py b/ranger/api/commands.py
index a2501c7f..c3317939 100644
--- a/ranger/api/commands.py
+++ b/ranger/api/commands.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 # TODO: Add an optional "!" to all commands and set a flag if it's there
 
diff --git a/ranger/api/options.py b/ranger/api/options.py
index e2558ffb..3691fe94 100644
--- a/ranger/api/options.py
+++ b/ranger/api/options.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import re
 from re import compile as regexp
diff --git a/ranger/colorschemes/default.py b/ranger/colorschemes/default.py
index fb46dd43..fa1d92bc 100644
--- a/ranger/colorschemes/default.py
+++ b/ranger/colorschemes/default.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from ranger.gui.colorscheme import ColorScheme
 from ranger.gui.color import *
diff --git a/ranger/colorschemes/default88.py b/ranger/colorschemes/default88.py
index 8bf33807..2a2d4825 100644
--- a/ranger/colorschemes/default88.py
+++ b/ranger/colorschemes/default88.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 The default colorscheme, using 88 colors.
diff --git a/ranger/colorschemes/jungle.py b/ranger/colorschemes/jungle.py
index ea2e0d94..4f2b30ba 100644
--- a/ranger/colorschemes/jungle.py
+++ b/ranger/colorschemes/jungle.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from ranger.gui.color import *
 from ranger.colorschemes.default import Default
diff --git a/ranger/colorschemes/snow.py b/ranger/colorschemes/snow.py
index a8125ee6..c5940cc8 100644
--- a/ranger/colorschemes/snow.py
+++ b/ranger/colorschemes/snow.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from ranger.gui.colorscheme import ColorScheme
 from ranger.gui.color import *
diff --git a/ranger/container/bookmarks.py b/ranger/container/bookmarks.py
index 750515c5..4d692989 100644
--- a/ranger/container/bookmarks.py
+++ b/ranger/container/bookmarks.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import string
 import re
diff --git a/ranger/container/history.py b/ranger/container/history.py
index dd511d0e..1f2c5a4b 100644
--- a/ranger/container/history.py
+++ b/ranger/container/history.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 class HistoryEmptyException(Exception):
 	pass
diff --git a/ranger/container/settingobject.py b/ranger/container/settingobject.py
index e7ded15e..cbc56278 100644
--- a/ranger/container/settingobject.py
+++ b/ranger/container/settingobject.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from inspect import isfunction
 from ranger.ext.signals import SignalDispatcher
diff --git a/ranger/container/tags.py b/ranger/container/tags.py
index c08abdaa..7212345e 100644
--- a/ranger/container/tags.py
+++ b/ranger/container/tags.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from os.path import isdir, exists, dirname, abspath, realpath, expanduser
 import string
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index 4e72de77..2102cf2d 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import codecs
 import os
@@ -29,6 +17,7 @@ from ranger.ext.relative_symlink import relative_symlink
 from ranger.ext.keybinding_parser import key_to_string, construct_keybinding
 from ranger.ext.shell_escape import shell_quote
 from ranger.ext.next_available_filename import next_available_filename
+from ranger.ext.rifle import squash_flags
 from ranger.core.shared import FileManagerAware, EnvironmentAware, \
 		SettingsAware
 from ranger.fsobject import File
@@ -285,8 +274,10 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 		mode is a positive integer.
 		Both flags and mode specify how the program is run."""
 
+		mode = kw['mode'] if 'mode' in kw else 0
+
 		# ranger can act as a file chooser when running with --choosefile=...
-		if ('mode' not in kw or kw['mode'] == 0) and 'app' not in kw:
+		if mode == 0 and 'label' not in kw:
 			if ranger.arg.choosefile:
 				open(ranger.arg.choosefile, 'w').write(self.fm.env.cf.path)
 
@@ -302,16 +293,16 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 		elif type(files) not in (list, tuple):
 			files = [files]
 
-		if 'flags' in kw:
-			from ranger.core.runner import Context
-			context = Context(files=list(files), flags=kw['flags'])
-			context.squash_flags()
-			if 'c' in context.flags:
-				files = [self.fm.env.cf]
+		flags = kw.get('flags', '')
+		if 'c' in squash_flags(flags):
+			files = [self.fm.env.cf]
 
 		self.signal_emit('execute.before', keywords=kw)
+		filenames = [f.path for f in files]
+		mimetype = files[0].mimetype if files else None
+		label = kw.get('label', kw.get('app', None))
 		try:
-			return self.run(files=list(files), **kw)
+			return self.rifle.execute(filenames, mode, label, flags, mimetype)
 		finally:
 			self.signal_emit('execute.after')
 
@@ -463,6 +454,9 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 	def taskview_move(self, narg=None, **kw):
 		self.ui.taskview.move(narg=narg, **kw)
 
+	def pause_tasks(self):
+		self.loader.pause(-1)
+
 	def pager_close(self):
 		if self.ui.pager.visible:
 			self.ui.close_pager()
@@ -479,14 +473,14 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 		return self.run(cmd, **kw)
 
 	def edit_file(self, file=None):
-		"""Calls execute_file with the current file and app='editor'"""
+		"""Calls execute_file with the current file and label='editor'"""
 		if file is None:
 			file = self.env.cf
 		elif isinstance(file, str):
 			file = File(os.path.expanduser(file))
 		if file is None:
 			return
-		self.execute_file(file, app = 'editor')
+		self.execute_file(file, label='editor')
 
 	def toggle_option(self, string):
 		"""Toggle a boolean option named <string>"""
@@ -691,6 +685,19 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 	def hide_bookmarks(self):
 		self.ui.browser.draw_bookmarks = False
 
+	def draw_possible_programs(self):
+		try:
+			target = self.env.get_selection()[0]
+		except:
+			self.ui.browser.draw_info = []
+			return
+		programs = self.rifle.list_commands([target.path], target.mimetype)
+		programs = ['%s | %s' % program[0:2] for program in programs]
+		self.ui.browser.draw_info = programs
+
+	def hide_console_info(self):
+		self.ui.browser.draw_info = False
+
 	# --------------------------
 	# -- Pager
 	# --------------------------
@@ -905,7 +912,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 			write("\n")
 
 		temporary_file.flush()
-		self.run(app='pager', files=[File(temporary_file.name)])
+		pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER)
+		self.run([pager, temporary_file.name])
 
 	def dump_commands(self):
 		temporary_file = tempfile.NamedTemporaryFile()
@@ -927,7 +935,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 				write("    :%s\n" % cmd.get_name())
 
 		temporary_file.flush()
-		self.run(app='pager', files=[File(temporary_file.name)])
+		pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER)
+		self.run([pager, temporary_file.name])
 
 	def dump_settings(self):
 		from ranger.container.settingobject import ALLOWED_SETTINGS
@@ -939,7 +948,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 			write("%30s = %s\n" % (setting, getattr(self.settings, setting)))
 
 		temporary_file.flush()
-		self.run(app='pager', files=[File(temporary_file.name)])
+		pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER)
+		self.run([pager, temporary_file.name])
 
 	# --------------------------
 	# -- File System Operations
diff --git a/ranger/core/environment.py b/ranger/core/environment.py
index b5ab223d..29ebcdf0 100644
--- a/ranger/core/environment.py
+++ b/ranger/core/environment.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import curses
 import os
diff --git a/ranger/core/fm.py b/ranger/core/fm.py
index 20327a71..50c22067 100644
--- a/ranger/core/fm.py
+++ b/ranger/core/fm.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 The File Manager, putting the pieces together
@@ -25,13 +13,13 @@ import stat
 import sys
 
 import ranger
-from ranger import *
 from ranger.core.actions import Actions
 from ranger.container.tags import Tags
 from ranger.gui.ui import UI
 from ranger.container.bookmarks import Bookmarks
 from ranger.core.runner import Runner
 from ranger.ext.get_executables import get_executables
+from ranger.ext.rifle import Rifle
 from ranger.fsobject import Directory
 from ranger.ext.signals import SignalDispatcher
 from ranger import __version__
@@ -64,6 +52,14 @@ class FM(Actions, SignalDispatcher):
 
 	def initialize(self):
 		"""If ui/bookmarks are None, they will be initialized here."""
+
+		if not ranger.arg.clean and os.path.isfile(self.confpath('rifle.conf')):
+			rifleconf = self.confpath('rifle.conf')
+		else:
+			rifleconf = self.relpath('defaults/rifle.conf')
+		self.rifle = Rifle(rifleconf)
+		self.rifle.reload_config()
+
 		if self.bookmarks is None:
 			if ranger.arg.clean:
 				bookmarkfile = None
@@ -82,10 +78,13 @@ class FM(Actions, SignalDispatcher):
 			self.ui = UI()
 			self.ui.initialize()
 
+		self.rifle.hook_before_executing = lambda a, b, flags: self.ui.suspend() if 'f' not in flags else None
+		self.rifle.hook_after_executing = lambda a, b, flags: self.ui.initialize() if 'f' not in flags else None
+		self.rifle.hook_logger = self.notify
+
 		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)
 
@@ -130,8 +129,8 @@ class FM(Actions, SignalDispatcher):
 					shutil.copy(self.relpath(_from), self.confpath(to))
 				except Exception as e:
 					sys.stderr.write("  ERROR: %s\n" % str(e))
-		if which == 'apps' or which == 'all':
-			copy('defaults/apps.py', 'apps.py')
+		if which == 'rifle' or which == 'all':
+			copy('defaults/rifle.conf', 'rifle.conf')
 		if which == 'commands' or which == 'all':
 			copy('defaults/commands.py', 'commands.py')
 		if which == 'rc' or which == 'all':
@@ -143,7 +142,7 @@ class FM(Actions, SignalDispatcher):
 			os.chmod(self.confpath('scope.sh'),
 				os.stat(self.confpath('scope.sh')).st_mode | stat.S_IXUSR)
 		if which not in \
-				('all', 'apps', 'scope', 'commands', 'rc', 'options'):
+				('all', 'rifle', 'scope', 'commands', 'rc', 'options'):
 			sys.stderr.write("Unknown config file `%s'\n" % which)
 
 	def confpath(self, *paths):
@@ -190,7 +189,7 @@ class FM(Actions, SignalDispatcher):
 
 				ui.redraw()
 
-				ui.set_load_mode(loader.has_work())
+				ui.set_load_mode(not loader.paused and loader.has_work())
 
 				ui.handle_input()
 
@@ -200,10 +199,10 @@ class FM(Actions, SignalDispatcher):
 							zombies.remove(zombie)
 
 				gc_tick += 1
-				if gc_tick > TICKS_BEFORE_COLLECTING_GARBAGE:
+				if gc_tick > ranger.TICKS_BEFORE_COLLECTING_GARBAGE:
 					gc_tick = 0
-					env.garbage_collect(TIME_BEFORE_FILE_BECOMES_GARBAGE,
-							self.tabs)
+					env.garbage_collect(
+						ranger.TIME_BEFORE_FILE_BECOMES_GARBAGE, self.tabs)
 
 		except KeyboardInterrupt:
 			# this only happens in --debug mode. By default, interrupts
diff --git a/ranger/core/helper.py b/ranger/core/helper.py
index c556b9bd..233f1b8a 100644
--- a/ranger/core/helper.py
+++ b/ranger/core/helper.py
@@ -1,29 +1,16 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """Helper functions"""
 
 from errno import EEXIST
 import os.path
 import sys
-from ranger import *
+from ranger import CONFDIR, USAGE, STABLE, __version__
 
 def parse_arguments():
 	"""Parse the program arguments"""
 	from optparse import OptionParser
-	from ranger import __version__
 	from ranger.ext.openstruct import OpenStruct
 	from os.path import expanduser
 
@@ -41,7 +28,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`)")
@@ -107,13 +94,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')
@@ -150,25 +130,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/loader.py b/ranger/core/loader.py
index 59d3e6c0..777ce0f2 100644
--- a/ranger/core/loader.py
+++ b/ranger/core/loader.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from collections import deque
 from time import time, sleep
@@ -123,8 +111,8 @@ class CommandLoader(Loadable, SignalDispatcher, FileManagerAware):
 				self.process.send_signal(20)
 			except:
 				pass
-		Loadable.pause(self)
-		self.signal_emit('pause', process=self.process, loader=self)
+			Loadable.pause(self)
+			self.signal_emit('pause', process=self.process, loader=self)
 
 	def unpause(self):
 		if not self.finished and self.paused:
@@ -132,8 +120,8 @@ class CommandLoader(Loadable, SignalDispatcher, FileManagerAware):
 				self.process.send_signal(18)
 			except:
 				pass
-		Loadable.unpause(self)
-		self.signal_emit('unpause', process=self.process, loader=self)
+			Loadable.unpause(self)
+			self.signal_emit('unpause', process=self.process, loader=self)
 
 	def destroy(self):
 		self.signal_emit('destroy', process=self.process, loader=self)
@@ -154,6 +142,8 @@ def safeDecode(string):
 class Loader(FileManagerAware):
 	seconds_of_work_time = 0.03
 	throbber_chars = r'/-\|'
+	throbber_paused = '#'
+	paused = False
 
 	def __init__(self):
 		self.queue = deque()
@@ -178,6 +168,10 @@ class Loader(FileManagerAware):
 		while obj in self.queue:
 			self.queue.remove(obj)
 		self.queue.appendleft(obj)
+		if self.paused:
+			obj.pause()
+		else:
+			obj.unpause()
 
 	def move(self, _from, to):
 		try:
@@ -213,11 +207,34 @@ class Loader(FileManagerAware):
 			item.destroy()
 			del self.queue[index]
 
+	def pause(self, state):
+		"""
+		Change the pause-state to 1 (pause), 0 (no pause) or -1 (toggle)
+		"""
+		if state == -1:
+			state = not self.paused
+		elif state == self.paused:
+			return
+
+		self.paused = state
+
+		if not self.queue:
+			return
+
+		if state:
+			self.queue[0].pause()
+		else:
+			self.queue[0].unpause()
+
 	def work(self):
 		"""
 		Load items from the queue if there are any.
 		Stop after approximately self.seconds_of_work_time.
 		"""
+		if self.paused:
+			self.status = self.throbber_paused
+			return
+
 		while True:
 			# get the first item with a proper load_generator
 			try:
@@ -229,6 +246,8 @@ class Loader(FileManagerAware):
 			except IndexError:
 				return
 
+		item.unpause()
+
 		self.rotate()
 		if item != self.old_item:
 			if self.old_item:
diff --git a/ranger/core/main.py b/ranger/core/main.py
index b4629801..37cdc586 100644
--- a/ranger/core/main.py
+++ b/ranger/core/main.py
@@ -1,24 +1,10 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 The main function responsible to initialize the FM object and stuff.
 """
 
-from ranger.core.helper import *
-
 def main():
 	"""initialize objects and run the filemanager"""
 	import locale
@@ -28,6 +14,7 @@ def main():
 	from ranger.core.shared import (EnvironmentAware, FileManagerAware,
 			SettingsAware)
 	from ranger.core.fm import FM
+	from ranger.core.helper import parse_arguments, load_settings
 
 	if not sys.stdin.isatty():
 		sys.stderr.write("Error: Must run ranger from terminal\n")
@@ -85,12 +72,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, number=ranger.arg.mode, flags=ranger.arg.flags)
 			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 17cdcca5..52c0b669 100644
--- a/ranger/core/runner.py
+++ b/ranger/core/runner.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 This module is an abstract layer over subprocess.Popen
@@ -41,7 +29,9 @@ from subprocess import Popen, PIPE
 from ranger.ext.get_executables import get_executables
 
 
-ALLOWED_FLAGS = 'sdpwcrtSDPWCRT'
+# TODO: Remove unused parts of runner.py
+#ALLOWED_FLAGS = 'sdpwcrtSDPWCRT'
+ALLOWED_FLAGS = 'cfrtCFRT'
 
 
 def press_enter():
@@ -97,11 +87,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):
@@ -140,16 +129,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/core/shared.py b/ranger/core/shared.py
index 9da79578..dae83b78 100644
--- a/ranger/core/shared.py
+++ b/ranger/core/shared.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """Shared objects contain singleton variables which can be
 inherited, essentially acting like global variables."""
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..52a1d30e 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 not arg.isdigit()
 
 	def _is_flags(self, arg):
 		return all(x in ALLOWED_FLAGS for x in arg)
diff --git a/ranger/defaults/rc.conf b/ranger/defaults/rc.conf
index 77ffa5c3..5ac2763a 100644
--- a/ranger/defaults/rc.conf
+++ b/ranger/defaults/rc.conf
@@ -53,7 +53,7 @@ map !  console shell
 map @  console -p6 shell  %%s
 map #  console shell -p 
 map s  console shell 
-map r  console open_with 
+map r  chain draw_possible_programs; console open_with 
 map f  console find 
 map cd console cd 
 
diff --git a/ranger/defaults/rifle.conf b/ranger/defaults/rifle.conf
new file mode 100644
index 00000000..9ee15b25
--- /dev/null
+++ b/ranger/defaults/rifle.conf
@@ -0,0 +1,181 @@
+# vim: ft=cfg
+#
+# This is the configuration file of "rifle", ranger's file executor/opener.
+# Each line consists of conditions and a command.  For each line the conditions
+# are checked and if they are met, the respective command is run.
+#
+# Syntax:
+#   <condition1> , <condition2> , ... = command
+#
+# The command can contain these environment variables:
+#   $1-$9 | The n-th selected file
+#   $@    | All selected files
+#
+# Prefixing a condition with "!" will negate its result.
+# These conditions are currently supported:
+#   match <regexp> | The regexp matches $1
+#   ext <regexp>   | The regexp matches the extension of $1
+#   mime <regexp>  | The regexp matches the mime type of $1
+#   name <regexp>  | The regexp matches the basename of $1
+#   path <regexp>  | The regexp matches the absolute path of $1
+#   has <program>  | The program is installed (i.e. located in $PATH)
+#   file           | $1 is a file
+#   directory      | $1 is a directory
+#   number <n>     | change the number of this command to n
+#   terminal       | stdin, stderr and stdout are connected to a terminal
+#   X              | $DISPLAY is not empty (i.e. Xorg runs)
+#
+# There are also pseudo-conditions which have a "side effect":
+#   flag <flags>  | Change how the program is run. See below.
+#   label <label> | Assign a label or name to the command so it can
+#                 | be started with :open_with <label> in ranger
+#                 | or `rifle -p <label>` in the standalone executable.
+#   else          | Always true.
+#
+# Flags are single characters which slightly transform the command:
+#   f | Fork the program, make it run in the background.
+#     |   New command = setsid $command >& /dev/null &
+#   r | Execute the command with root permissions
+#     |   New command = sudo $command
+#   t | Run the program in a new terminal.  If $TERMCMD is not defined,
+#     | rifle will attempt to extract it from $TERM.
+#     |   New command = $TERMCMD -e $command
+#
+# NOTE: FLAGS DO NOT WORK PROPERLY WHEN PIPES ARE IN THE COMMAND
+
+#-------------------------------------------
+# Websites
+#-------------------------------------------
+# Rarely installed browsers get higher priority; It is assumed that if you
+# install a rare browser, you probably use it.  Firefox/konqueror/w3m on the
+# other hand are often only installed as fallback browsers.
+ext x?html?, has surf,           X, flag f = surf -- file://"$1"
+ext x?html?, has vimprobable,    X, flag f = vimprobable -- "$@"
+ext x?html?, has vimprobable2,   X, flag f = vimprobable2 -- "$@"
+ext x?html?, has jumanji,        X, flag f = jumanji -- "$@"
+ext x?html?, has luakit,         X, flag f = luakit -- "$@"
+ext x?html?, has uzbl,           X, flag f = uzbl -- "$@"
+ext x?html?, has uzbl-browser,   X, flag f = uzbl-browser -- "$@"
+ext x?html?, has uzbl-core,      X, flag f = uzbl-core -- "$@"
+ext x?html?, has midori,         X, flag f = midori -- "$@"
+ext x?html?, has opera,          X, flag f = opera -- "$@"
+ext x?html?, has firefox,        X, flag f = firefox -- "$@"
+ext x?html?, has seamonkey,      X, flag f = seamonkey -- "$@"
+ext x?html?, has iceweasel,      X, flag f = iceweasel -- "$@"
+ext x?html?, has epiphany,       X, flag f = epiphany -- "$@"
+ext x?html?, has konqueror,      X, flag f = konqueror -- "$@"
+ext x?html?, has elinks,          terminal = elinks "$@"
+ext x?html?, has links2,          terminal = links2 "$@"
+ext x?html?, has links,           terminal = links "$@"
+ext x?html?, has lynx,            terminal = lynx -- "$@"
+ext x?html?, has w3m,             terminal = w3m "$@"
+
+#-------------------------------------------
+# Misc
+#-------------------------------------------
+# Define the "editor" for text files as first action
+mime ^text,      label editor = "$EDITOR" -- "$@"
+ext xml|csv|tex, label editor = "$EDITOR" -- "$@"
+mime ^text,      label pager  = "$PAGER" -- "$@"
+ext xml|csv|tex, label pager  = "$PAGER" -- "$@"
+
+ext 1                         = man "$1"
+ext s[wmf]c, has zsnes, X     = zsnes "$1"
+ext nes, has fceux, X         = fceux "$1"
+ext exe                       = wine "$1"
+name ^[mM]akefile$            = make
+
+#--------------------------------------------
+# Code
+#-------------------------------------------
+ext py  = python -- "$1"
+ext pl  = perl -- "$1"
+ext rb  = ruby -- "$1"
+ext sh  = bash -- "$1"
+ext php = php -- "$1"
+
+#--------------------------------------------
+# Audio without X
+#-------------------------------------------
+mime ^audio, terminal, has mplayer  = mplayer -- "$@"
+mime ^audio, terminal, has mplayer2 = mplayer2 -- "$@"
+ext midi?,   terminal, has wildmidi = wildmidi -- "$@"
+
+#--------------------------------------------
+# Video/Audio with a GUI
+#-------------------------------------------
+mime ^video|audio, has gmplayer, X, flag f = gmplayer -- "$@"
+mime ^video|audio, has smplayer, X, flag f = smplayer -- "$@"
+mime ^video,       has mplayer2, X, flag f = mplayer2 -- "$@"
+mime ^video,       has mplayer2, X, flag f = mplayer2 -fs -- "$@"
+mime ^video,       has mplayer,  X, flag f = mplayer -- "$@"
+mime ^video,       has mplayer,  X, flag f = mplayer -fs -- "$@"
+mime ^video|audio, has vlc,      X, flag f = vlc -- "$@"
+mime ^video|audio, has totem,    X, flag f = totem -- "$@"
+mime ^video|audio, has totem,    X, flag f = totem --fullscreen -- "$@"
+
+#--------------------------------------------
+# Video without X:
+#-------------------------------------------
+mime ^video, terminal, !X, has mplayer2  = mplayer2 -- "$@"
+mime ^video, terminal, !X, has mplayer   = mplayer -- "$@"
+
+#-------------------------------------------
+# Image Viewing:
+#-------------------------------------------
+mime ^image, has eog,    X, flag f = eog -- "$@"
+mime ^image, has sxiv,   X, flag f = sxiv -- "$@"
+mime ^image, has feh,    X, flag f = feh -- "$@"
+mime ^image, has mirage, X, flag f = mirage -- "$@"
+mime ^image, has gimp,   X, flag f = gimp -- "$@"
+ext xcf,                 X, flag f = gimp -- "$@"
+
+#-------------------------------------------
+# Documents
+#-------------------------------------------
+ext pdf, has llpp,     X, flag f = llpp "$@"
+ext pdf, has zathura,  X, flag f = zathura -- "$@"
+ext pdf, has mupdf,    X, flag f = mupdf -- "$@"
+ext pdf, has apvlv,    X, flag f = apvlv -- "$@"
+ext pdf, has xpdf,     X, flag f = xpdf -- "$@"
+ext pdf, has evince,   X, flag f = evince -- "$@"
+ext pdf, has okular,   X, flag f = okular -- "$@"
+ext pdf, has epdfview, X, flag f = epdfview -- "$@"
+
+ext           sxc|xlsx?|xlt|xlw|gnm|gnumeric, has gnumeric,    X, flag f = gnumeric -- "$@"
+ext           sxc|xlsx?|xlt|xlw|gnm|gnumeric, has kspread,     X, flag f = kspread -- "$@"
+ext od[tspfg]|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has libreoffice, X, flag f = libreoffice -- "$@"
+ext od[tspfg]|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has soffice,     X, flag f = soffice -- "$@"
+ext od[tspfg]|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has ooffice,     X, flag f = ooffice -- "$@"
+
+ext docx?, has catdoc,       terminal = catdoc -- "$@" | "$PAGER"
+ext docx?, has libreoffice, X, flag f = libreoffice -- "$@"
+ext docx?, has soffice,     X, flag f = soffice -- "$@"
+ext docx?, has ooffice,     X, flag f = ooffice -- "$@"
+
+ext djvu, has evince, X, flag f = evince -- "$@"
+
+#-------------------------------------------
+# Archives
+#-------------------------------------------
+# This requires atool
+ext 7z|ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz,  has als     = als -- "$@" | "$PAGER"
+ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has als     = als -- "$@" | "$PAGER"
+ext 7z|ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz,  has aunpack = aunpack -- "$@"
+ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has aunpack = aunpack -- "$@"
+
+# Fallback:
+ext tar|gz, has tar = tar vvtf "$@" | "$PAGER"
+ext tar|gz, has tar = tar vvxf "$@"
+
+#-------------------------------------------
+# Misc
+#-------------------------------------------
+label wallpaper, number 11, mime ^image, X = feh --bg-scale "$1"
+label wallpaper, number 12, mime ^image, X = feh --bg-tile "$1"
+label wallpaper, number 13, mime ^image, X = feh --bg-center "$1"
+label wallpaper, number 14, mime ^image, X = feh --bg-fill "$1"
+
+# Define the editor for non-text files + pager as last action
+label editor, !mime ^text, !ext xml|csv|tex  = "$EDITOR" -- "$@"
+label pager,  !mime ^text  !ext xml|csv|tex  = "$PAGER" -- "$@"
diff --git a/ranger/ext/accumulator.py b/ranger/ext/accumulator.py
index d68bc656..7665c99f 100644
--- a/ranger/ext/accumulator.py
+++ b/ranger/ext/accumulator.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from ranger.ext.direction import Direction
 
diff --git a/ranger/ext/cached_function.py b/ranger/ext/cached_function.py
index 4d9ded18..ad7c5c11 100644
--- a/ranger/ext/cached_function.py
+++ b/ranger/ext/cached_function.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2012  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 software is distributed under the terms of the GNU GPL version 3.
 
 def cached_function(fnc):
   cache = {}
diff --git a/ranger/ext/curses_interrupt_handler.py b/ranger/ext/curses_interrupt_handler.py
index 7c5b153e..eb86e0a9 100644
--- a/ranger/ext/curses_interrupt_handler.py
+++ b/ranger/ext/curses_interrupt_handler.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 This module can catch interrupt signals which would otherwise
diff --git a/ranger/ext/direction.py b/ranger/ext/direction.py
index 8a37c54a..742f54da 100644
--- a/ranger/ext/direction.py
+++ b/ranger/ext/direction.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 Directions provide convenient methods for movement operations.
diff --git a/ranger/ext/get_executables.py b/ranger/ext/get_executables.py
index 03f438dd..0c01ffd6 100644
--- a/ranger/ext/get_executables.py
+++ b/ranger/ext/get_executables.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from stat import S_IXOTH, S_IFREG
 from ranger.ext.iter_tools import unique
@@ -23,13 +11,11 @@ _cached_executables = None
 
 def get_executables():
 	"""
-	Return all executable files in each of the given directories.
-
-	Looks in $PATH by default.
+	Return all executable files in $PATH. Cached version.
 	"""
 	global _cached_executables
 	if _cached_executables is None:
-		_cached_executables = sorted(get_executables_uncached())
+		_cached_executables = get_executables_uncached()
 	return _cached_executables
 
 
diff --git a/ranger/ext/human_readable.py b/ranger/ext/human_readable.py
index 1a667519..9667421a 100644
--- a/ranger/ext/human_readable.py
+++ b/ranger/ext/human_readable.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 def human_readable(byte, separator=' '):
 	"""
diff --git a/ranger/ext/iter_tools.py b/ranger/ext/iter_tools.py
index e515fa07..341230f4 100644
--- a/ranger/ext/iter_tools.py
+++ b/ranger/ext/iter_tools.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from collections import deque
 
diff --git a/ranger/ext/keybinding_parser.py b/ranger/ext/keybinding_parser.py
index 295855fb..eed85a2b 100644
--- a/ranger/ext/keybinding_parser.py
+++ b/ranger/ext/keybinding_parser.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import sys
 import copy
diff --git a/ranger/ext/mount_path.py b/ranger/ext/mount_path.py
index 31d6c602..19747eba 100644
--- a/ranger/ext/mount_path.py
+++ b/ranger/ext/mount_path.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from os.path import realpath, abspath, dirname, ismount
 
diff --git a/ranger/ext/next_available_filename.py b/ranger/ext/next_available_filename.py
index 696063cf..705e1558 100644
--- a/ranger/ext/next_available_filename.py
+++ b/ranger/ext/next_available_filename.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import os.path
 
diff --git a/ranger/ext/openstruct.py b/ranger/ext/openstruct.py
index b538d384..fa521d34 100644
--- a/ranger/ext/openstruct.py
+++ b/ranger/ext/openstruct.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 # prepend __ to arguments because one might use "args"
 # or "keywords" as a keyword argument.
diff --git a/ranger/ext/relative_symlink.py b/ranger/ext/relative_symlink.py
index 420f186c..de1cb908 100644
--- a/ranger/ext/relative_symlink.py
+++ b/ranger/ext/relative_symlink.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from os import symlink, sep
 
diff --git a/ranger/ext/rifle.py b/ranger/ext/rifle.py
new file mode 100755
index 00000000..1080ecec
--- /dev/null
+++ b/ranger/ext/rifle.py
@@ -0,0 +1,387 @@
+#!/usr/bin/python -S
+# Copyright (C) 2012  Roman Zimbelmann <romanz@lavabit.com>
+# This software is distributed under the terms of the GNU GPL version 3.
+
+"""
+rifle, the file executor/opener of ranger
+
+This can be used as a standalone program or can be embedded in python code.
+When used together with ranger, it doesn't have to be installed to $PATH.
+
+Example usage:
+
+	rifle = Rifle("rilfe.conf")
+	rifle.reload_config()
+	rifle.execute(["file1", "file2"])
+"""
+
+import os.path
+import re
+from subprocess import Popen, PIPE
+import sys
+
+DEFAULT_PAGER = 'less'
+DEFAULT_EDITOR = 'nano'
+ENCODING = 'utf-8'
+
+try:
+	from ranger.ext.get_executables import get_executables
+except ImportError:
+	_cached_executables = None
+
+	def get_executables():
+		"""
+		Return all executable files in $PATH + Cache them.
+		"""
+		global _cached_executables
+		if _cached_executables is not None:
+			return _cached_executables
+
+		if 'PATH' in os.environ:
+			paths = os.environ['PATH'].split(':')
+		else:
+			paths = ['/usr/bin', '/bin']
+
+		from stat import S_IXOTH, S_IFREG
+		paths_seen = set()
+		_cached_executables = set()
+		for path in paths:
+			if path in paths_seen:
+				continue
+			paths_seen.add(path)
+			try:
+				content = listdir(path)
+			except:
+				continue
+			for item in content:
+				abspath = path + '/' + item
+				try:
+					filestat = stat(abspath)
+				except:
+					continue
+				if filestat.st_mode & (S_IXOTH | S_IFREG):
+					_cached_executables.add(item)
+		return _cached_executables
+
+
+def _is_terminal():
+	# Check if stdin (file descriptor 0), stdout (fd 1) and
+	# stderr (fd 2) are connected to a terminal
+	try:
+		os.ttyname(0)
+		os.ttyname(1)
+		os.ttyname(2)
+	except:
+		return False
+	return True
+
+
+def squash_flags(flags):
+	"""
+	Remove lowercase flags if the respective uppercase flag exists
+
+	>>> squash_flags('abc')
+	'abc'
+	>>> squash_flags('abcC')
+	'ab'
+	>>> squash_flags('CabcAd')
+	'bd'
+	"""
+	exclude = ''.join(f.upper() + f.lower() for f in flags if f == f.upper())
+	return ''.join(f for f in flags if f not in exclude)
+
+
+class Rifle(object):
+	delimiter1 = '='
+	delimiter2 = ','
+
+	def hook_before_executing(self, command, mimetype, flags):
+		pass
+
+	def hook_after_executing(self, command, mimetype, flags):
+		pass
+
+	def hook_command_preprocessing(self, command):
+		return command
+
+	def hook_command_postprocessing(self, command):
+		return command
+
+	def hook_environment(self, env):
+		return env
+
+	def hook_logger(self, string):
+		sys.stderr.write(string + "\n")
+
+	def __init__(self, config_file):
+		self.config_file = config_file
+		self._app_flags = ''
+		self._app_label = None
+
+	def reload_config(self, config_file=None):
+		"""Replace the current configuration with the one in config_file"""
+		if config_file is None:
+			config_file = self.config_file
+		f = open(config_file, 'r')
+		self.rules = []
+		lineno = 1
+		for line in f:
+			if line.startswith('#') or line == '\n':
+				continue
+			line = line.strip()
+			try:
+				if self.delimiter1 not in line:
+					raise Exception("Line without delimiter")
+				tests, command = line.split(self.delimiter1, 1)
+				tests = tests.split(self.delimiter2)
+				tests = tuple(tuple(f.strip().split(None, 1)) for f in tests)
+				command = command.strip()
+				self.rules.append((command, tests))
+			except Exception as e:
+				self.hook_logger("Syntax error in %s line %d (%s)" % \
+					(config_file, lineno, str(e)))
+			lineno += 1
+		f.close()
+
+	def _eval_condition(self, condition, files, label):
+		# Handle the negation of conditions starting with an exclamation mark,
+		# then pass on the arguments to _eval_condition2().
+
+		if not condition:
+			return True
+		if condition[0].startswith('!'):
+			new_condition = tuple([condition[0][1:]]) + tuple(condition[1:])
+			return not self._eval_condition2(new_condition, files, label)
+		return self._eval_condition2(condition, files, label)
+
+	def _eval_condition2(self, rule, files, label):
+		# This function evaluates the condition, after _eval_condition() handled
+		# negation of conditions starting with a "!".
+
+		if not files:
+			return False
+
+		function = rule[0]
+		argument = rule[1] if len(rule) > 1 else ''
+
+		if function == 'ext':
+			extension = os.path.basename(files[0]).rsplit('.', 1)[-1]
+			return bool(re.search('^(' + argument + ')$', extension))
+		elif function == 'name':
+			return bool(re.search(argument, os.path.basename(files[0])))
+		elif function == 'match':
+			return bool(re.search(argument, files[0]))
+		elif function == 'file':
+			return os.path.isfile(files[0])
+		elif function == 'directory':
+			return os.path.isdir(files[0])
+		elif function == 'path':
+			return bool(re.search(argument, os.path.abspath(files[0])))
+		elif function == 'mime':
+			return bool(re.search(argument, self._get_mimetype(files[0])))
+		elif function == 'has':
+			return argument in get_executables()
+		elif function == 'terminal':
+			return _is_terminal()
+		elif function == 'number':
+			if argument.isdigit():
+				self._skip = int(argument)
+			return True
+		elif function == 'label':
+			self._app_label = argument
+			if label:
+				return argument == label
+			return True
+		elif function == 'flag':
+			self._app_flags = argument
+			return True
+		elif function == 'X':
+			return 'DISPLAY' in os.environ
+		elif function == 'else':
+			return True
+
+	def _get_mimetype(self, fname):
+		# Spawn "file" to determine the mime-type of the given file.
+		if self._mimetype:
+			return self._mimetype
+		process = Popen(["file", "--mime-type", "-Lb", fname],
+				stdout=PIPE, stderr=PIPE)
+		mimetype, _ = process.communicate()
+		self._mimetype = mimetype.decode(ENCODING)
+		return self._mimetype
+
+	def _build_command(self, files, action, flags):
+		# Get the flags
+		if isinstance(flags, str):
+			self._app_flags += flags
+		self._app_flags = squash_flags(self._app_flags)
+		flags = self._app_flags
+
+		_filenames = "' '".join(f.replace("'", "'\\\''") for f in files
+				if "\x00" not in f)
+		command = "set -- '%s'" % _filenames + '\n'
+
+		# Apply flags
+		command += self._apply_flags(action, flags)
+		return command
+
+	def _apply_flags(self, action, flags):
+		# FIXME: Flags do not work properly when pipes are in the command.
+		if 'r' in flags:
+			action = 'sudo ' + action
+		if 't' in flags:
+			if 'TERMCMD' not in os.environ:
+				term = os.environ['TERM']
+				if term.startswith('rxvt-unicode'):
+					term = 'urxvt'
+				if term not in get_executables():
+					self.hook_logger("Can not determine terminal command.  "
+						"Please set $TERMCMD manually.")
+				os.environ['TERMCMD'] = term
+			action = "$TERMCMD -e %s" % action
+		if 'f' in flags:
+			if 'setsid' in get_executables():
+				action = "setsid %s > /dev/null 2> /dev/null &" % action
+			else:
+				action = "nohup %s > /dev/null 2> /dev/null &" % action
+		return action
+
+	def list_commands(self, files, mimetype=None):
+		"""
+		Returns one 4-tuple for all currently applicable commands
+		The 4-tuple contains (count, command, label, flags).
+		count is the index, counted from 0 upwards,
+		command is the command that will be executed.
+		label and flags are the label and flags specified in the rule.
+		"""
+		self._mimetype = mimetype
+		count = -1
+		for cmd, tests in self.rules:
+			self._skip = None
+			self._app_flags = ''
+			self._app_label = None
+			for test in tests:
+				if not self._eval_condition(test, files, None):
+					break
+			else:
+				if self._skip is None:
+					count += 1
+				else:
+					count = self._skip
+				yield (count, cmd, self._app_label, self._app_flags)
+
+	def execute(self, files, number=0, label=None, flags="", mimetype=None):
+		"""
+		Executes the given list of files.
+
+		By default, this executes the first command where all conditions apply,
+		but by specifying number=N you can run the 1+Nth command.
+
+		If a label is specified, only rules with this label will be considered.
+
+		If you specify the mimetype, rifle will not try to determine it itself.
+
+		By specifying a flag, you extend the flag that is defined in the rule.
+		Uppercase flags negate the respective lowercase flags.
+		For example: if the flag in the rule is "pw" and you specify "Pf", then
+		the "p" flag is negated and the "f" flag is added, resulting in "wf".
+		"""
+		command = None
+		found_at_least_one = None
+
+		# Determine command
+		for count, cmd, lbl, flgs in self.list_commands(files, mimetype):
+			if label and label == lbl or not label and count == number:
+				cmd = self.hook_command_preprocessing(cmd)
+				command = self._build_command(files, cmd, flags + flgs)
+				break
+			else:
+				found_at_least_one = True
+		else:
+			if label and label in get_executables():
+				cmd = '%s "$@"' % label
+				command = self._build_command(files, cmd, flags)
+
+		# Execute command
+		if command is None:
+			if found_at_least_one:
+				if label:
+					self.hook_logger("Label '%s' is undefined" % label)
+				else:
+					self.hook_logger("Method number %d is undefined." % number)
+			else:
+				self.hook_logger("No action found.")
+		else:
+			if 'PAGER' not in os.environ:
+				os.environ['PAGER'] = DEFAULT_PAGER
+			if 'EDITOR' not in os.environ:
+				os.environ['EDITOR'] = DEFAULT_EDITOR
+			command = self.hook_command_postprocessing(command)
+			self.hook_before_executing(command, self._mimetype, self._app_flags)
+			try:
+				p = Popen(command, env=self.hook_environment(os.environ), shell=True)
+				p.wait()
+			finally:
+				self.hook_after_executing(command, self._mimetype, self._app_flags)
+
+
+def main():
+	"""The main function which is run when you start this program direectly."""
+	import sys
+
+	# Find configuration file path
+	if 'XDG_CONFIG_HOME' in os.environ and os.environ['XDG_CONFIG_HOME']:
+		conf_path = os.environ['XDG_CONFIG_HOME'] + '/ranger/rifle.conf'
+	else:
+		conf_path = os.path.expanduser('~/.config/ranger/rifle.conf')
+	if not os.path.isfile(conf_path):
+		conf_path = os.path.normpath(os.path.join(os.path.dirname(__file__),
+			'../defaults/rifle.conf'))
+
+	# Evaluate arguments
+	from optparse import OptionParser
+	parser = OptionParser(usage="%prog [-fhlpw] [files]")
+	parser.add_option('-f', type="string", default="", metavar="FLAGS",
+			help="use additional flags: f=fork, r=root, t=terminal. "
+			"Uppercase flag negates respective lowercase flags.")
+	parser.add_option('-l', action="store_true",
+			help="list possible ways to open the files (id:label:flags:command)")
+	parser.add_option('-p', type='string', default='0', metavar="KEYWORD",
+			help="pick a method to open the files.  KEYWORD is either the "
+			"number listed by 'rifle -l' or a string that matches a label in "
+			"the configuration file")
+	parser.add_option('-w', type='string', default=None, metavar="PROGRAM",
+			help="open the files with PROGRAM")
+	options, positional = parser.parse_args()
+	if not positional:
+		parser.print_help()
+		raise SystemExit(1)
+
+	if options.p.isdigit():
+		number = int(options.p)
+		label = None
+	else:
+		number = 0
+		label = options.p
+
+	if options.w is not None and not options.l:
+		p = Popen([options.w] + list(positional))
+		p.wait()
+	else:
+		# Start up rifle
+		rifle = Rifle(conf_path)
+		rifle.reload_config()
+		#print(rifle.list_commands(sys.argv[1:]))
+		if options.l:
+			for count, cmd, label, flags in rifle.list_commands(positional):
+				print("%d:%s:%s:%s" % (count, label or '', flags, cmd))
+		else:
+			rifle.execute(positional, number=number, label=label, flags=options.f)
+
+
+if __name__ == '__main__':
+	if 'RANGER_DOCTEST' in os.environ:
+		import doctest
+		doctest.testmod()
+	else:
+		main()
diff --git a/ranger/ext/shell_escape.py b/ranger/ext/shell_escape.py
index b68afc33..c9a22074 100644
--- a/ranger/ext/shell_escape.py
+++ b/ranger/ext/shell_escape.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 Functions to escape metacharacters of arguments for shell commands.
diff --git a/ranger/ext/signals.py b/ranger/ext/signals.py
index 0df39fe0..c3e546e3 100644
--- a/ranger/ext/signals.py
+++ b/ranger/ext/signals.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 An efficient and minimalistic signaling/hook module.
diff --git a/ranger/ext/spawn.py b/ranger/ext/spawn.py
index 5e5d6a95..0f3a629a 100644
--- a/ranger/ext/spawn.py
+++ b/ranger/ext/spawn.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from subprocess import Popen, PIPE
 ENCODING = 'utf-8'
diff --git a/ranger/ext/widestring.py b/ranger/ext/widestring.py
index 525e1bc1..44972c9c 100644
--- a/ranger/ext/widestring.py
+++ b/ranger/ext/widestring.py
@@ -1,18 +1,6 @@
 # -*- encoding: utf8 -*-
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import sys
 from unicodedata import east_asian_width
diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py
index 81e50ed9..1abd6ddd 100644
--- a/ranger/fsobject/directory.py
+++ b/ranger/fsobject/directory.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import os.path
 from os import stat as os_stat, lstat as os_lstat
diff --git a/ranger/fsobject/file.py b/ranger/fsobject/file.py
index 66bc549b..39146cd5 100644
--- a/ranger/fsobject/file.py
+++ b/ranger/fsobject/file.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import re
 from ranger.fsobject import FileSystemObject
diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py
index 943c8aa4..9c20a18f 100644
--- a/ranger/fsobject/fsobject.py
+++ b/ranger/fsobject/fsobject.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 CONTAINER_EXTENSIONS = ('7z', 'ace', 'ar', 'arc', 'bz', 'bz2', 'cab', 'cpio',
 	'cpt', 'deb', 'dgc', 'dmg', 'gz', 'iso', 'jar', 'msi', 'pkg', 'rar',
diff --git a/ranger/gui/ansi.py b/ranger/gui/ansi.py
index 65038120..96b95669 100644
--- a/ranger/gui/ansi.py
+++ b/ranger/gui/ansi.py
@@ -1,18 +1,6 @@
 # Copyright (C) 2010 David Barnett <davidbarnett2@gmail.com>
 # Copyright (C) 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 A library to help to convert ANSI codes to curses instructions.
diff --git a/ranger/gui/bar.py b/ranger/gui/bar.py
index 40218fb1..ae07dd35 100644
--- a/ranger/gui/bar.py
+++ b/ranger/gui/bar.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from ranger.ext.widestring import WideString, utf_char_width
 import sys
diff --git a/ranger/gui/color.py b/ranger/gui/color.py
index 889f9e9a..037ff5c1 100644
--- a/ranger/gui/color.py
+++ b/ranger/gui/color.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 Contains abbreviations to curses color/attribute constants.
diff --git a/ranger/gui/colorscheme.py b/ranger/gui/colorscheme.py
index cc72d6a8..c77c1500 100644
--- a/ranger/gui/colorscheme.py
+++ b/ranger/gui/colorscheme.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 Colorschemes define colors for specific contexts.
diff --git a/ranger/gui/context.py b/ranger/gui/context.py
index 3e7ca505..0227b6bc 100644
--- a/ranger/gui/context.py
+++ b/ranger/gui/context.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 CONTEXT_KEYS = ['reset', 'error', 'badinfo',
 		'in_browser', 'in_statusbar', 'in_titlebar', 'in_console',
diff --git a/ranger/gui/curses_shortcuts.py b/ranger/gui/curses_shortcuts.py
index a383ab4c..43b583a6 100644
--- a/ranger/gui/curses_shortcuts.py
+++ b/ranger/gui/curses_shortcuts.py
@@ -1,18 +1,6 @@
 # Copyright (C) 2009, 2010, 2011  Roman Zimbelmann <romanz@lavabit.com>
 # Copyright (C) 2010 David Barnett <davidbarnett2@gmail.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 software is distributed under the terms of the GNU GPL version 3.
 
 import curses
 import _curses
diff --git a/ranger/gui/displayable.py b/ranger/gui/displayable.py
index 5e9562a7..8888d8bf 100644
--- a/ranger/gui/displayable.py
+++ b/ranger/gui/displayable.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 from ranger.core.shared import FileManagerAware, EnvironmentAware
 from ranger.gui.curses_shortcuts import CursesShortcuts
diff --git a/ranger/gui/mouse_event.py b/ranger/gui/mouse_event.py
index cb697d8d..ed370e54 100644
--- a/ranger/gui/mouse_event.py
+++ b/ranger/gui/mouse_event.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import curses
 
diff --git a/ranger/gui/ui.py b/ranger/gui/ui.py
index 69b8463b..b0d3edc6 100644
--- a/ranger/gui/ui.py
+++ b/ranger/gui/ui.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import os
 import sys
diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py
index e9c08439..eb02c1f3 100644
--- a/ranger/gui/widgets/browsercolumn.py
+++ b/ranger/gui/widgets/browsercolumn.py
@@ -1,18 +1,6 @@
 # -*- encoding: utf8 -*-
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """The BrowserColumn widget displays the contents of a directory or file."""
 import stat
diff --git a/ranger/gui/widgets/browserview.py b/ranger/gui/widgets/browserview.py
index ea04c1e0..89d099ea 100644
--- a/ranger/gui/widgets/browserview.py
+++ b/ranger/gui/widgets/browserview.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """The BrowserView manages a set of BrowserColumns."""
 import curses
@@ -31,6 +19,7 @@ class BrowserView(Widget, DisplayableContainer):
 	need_clear = False
 	old_collapse = False
 	draw_hints = False
+	draw_info = False
 
 	def __init__(self, win, ratios, preview = True):
 		DisplayableContainer.__init__(self, win)
@@ -110,6 +99,8 @@ class BrowserView(Widget, DisplayableContainer):
 			self._draw_bookmarks()
 		elif self.draw_hints:
 			self._draw_hints()
+		elif self.draw_info:
+			self._draw_info(self.draw_info)
 
 	def finalize(self):
 		if self.pager.visible:
@@ -197,6 +188,19 @@ class BrowserView(Widget, DisplayableContainer):
 
 		self.win.chgat(ystart - 1, 0, curses.A_UNDERLINE)
 
+	def _draw_info(self, lines):
+		self.need_clear = True
+		hei = min(self.hei - 1, len(lines))
+		ystart = self.hei - hei
+		i = ystart
+		whitespace = " " * self.wid
+		for line in lines:
+			if i >= self.hei:
+				break
+			self.addstr(i, 0, whitespace)
+			self.addnstr(i, 0, line, self.wid)
+			i += 1
+
 	def _draw_hints(self):
 		self.need_clear = True
 		hints = []
diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py
index 2376ba5a..06552ef6 100644
--- a/ranger/gui/widgets/console.py
+++ b/ranger/gui/widgets/console.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 The Console widget implements a vim-like console for entering
@@ -131,6 +119,7 @@ class Console(Widget):
 			except:
 				pass
 			self.last_cursor_mode = None
+		self.fm.hide_console_info()
 		self.add_to_history()
 		self.tab_deque = None
 		self.clear()
diff --git a/ranger/gui/widgets/pager.py b/ranger/gui/widgets/pager.py
index 38451781..566c5ff1 100644
--- a/ranger/gui/widgets/pager.py
+++ b/ranger/gui/widgets/pager.py
@@ -1,18 +1,6 @@
 # Copyright (C) 2009, 2010, 2011  Roman Zimbelmann <romanz@lavabit.com>
 # Copyright (C) 2010 David Barnett <davidbarnett2@gmail.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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 The pager displays text and allows you to scroll inside it.
diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py
index 1ffb9fa3..20bc7c60 100644
--- a/ranger/gui/widgets/statusbar.py
+++ b/ranger/gui/widgets/statusbar.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 The statusbar displays information about the current file and directory.
diff --git a/ranger/gui/widgets/taskview.py b/ranger/gui/widgets/taskview.py
index a3f8e314..59e99679 100644
--- a/ranger/gui/widgets/taskview.py
+++ b/ranger/gui/widgets/taskview.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 The TaskView allows you to modify what the loader is doing.
diff --git a/ranger/gui/widgets/titlebar.py b/ranger/gui/widgets/titlebar.py
index 2b5e836b..f4f4cb77 100644
--- a/ranger/gui/widgets/titlebar.py
+++ b/ranger/gui/widgets/titlebar.py
@@ -1,17 +1,5 @@
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 """
 The titlebar is the widget at the top, giving you broad overview.
diff --git a/setup.py b/setup.py
index ec782794..40681290 100755
--- a/setup.py
+++ b/setup.py
@@ -1,18 +1,6 @@
 #!/usr/bin/env python
 # Copyright (C) 2009, 2010, 2011  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 software is distributed under the terms of the GNU GPL version 3.
 
 import distutils.core
 import ranger
@@ -29,7 +17,8 @@ if __name__ == '__main__':
 		url='http://savannah.nongnu.org/projects/ranger',
 		scripts=['ranger/data/ranger'],
 		data_files=[('share/man/man1', ['doc/ranger.1'])],
-		package_data={'ranger': ['data/*', 'defaults/rc.conf']},
+		package_data={'ranger': ['data/*', 'defaults/rc.conf',
+			'defaults/rifle.conf']},
 		packages=('ranger',
 		          'ranger.api',
 		          'ranger.colorschemes',