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