diff options
-rw-r--r-- | ranger/actions.py | 5 | ||||
-rw-r--r-- | ranger/applications.py | 201 | ||||
-rw-r--r-- | ranger/commands.py | 3 | ||||
-rw-r--r-- | ranger/fm.py | 6 | ||||
-rw-r--r-- | ranger/gui/widgets/console.py | 2 |
5 files changed, 20 insertions, 197 deletions
diff --git a/ranger/actions.py b/ranger/actions.py index f773a79b..f02e3cb4 100644 --- a/ranger/actions.py +++ b/ranger/actions.py @@ -20,7 +20,6 @@ import ranger from ranger.shared import EnvironmentAware, SettingsAware from ranger import fsobject from ranger.gui.widgets import console_mode as cmode -from ranger.applications import run from ranger.fsobject import File class Actions(EnvironmentAware, SettingsAware): @@ -247,10 +246,10 @@ class Actions(EnvironmentAware, SettingsAware): elif type(files) not in (list, tuple): files = [files] - return run(fm=self, files=list(files), **kw) + return self.run(files=list(files), **kw) def execute_command(self, cmd, **kw): - return run(fm=self, action=cmd, **kw) + return self.run(cmd, **kw) def edit_file(self, file=None): """Calls execute_file with the current file and app='editor'""" diff --git a/ranger/applications.py b/ranger/applications.py index 736f562e..1847c6d0 100644 --- a/ranger/applications.py +++ b/ranger/applications.py @@ -13,19 +13,14 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ -This module faciliates starting of new processes. +This module provides helper functions/classes for ranger.defaults.apps. """ import os, sys -from ranger.ext.waitpid_no_intr import waitpid_no_intr from subprocess import Popen, PIPE -from ranger.ext.shell_escape import shell_escape from ranger.ext.iter_tools import flatten from ranger.shared import FileManagerAware -devnull = open(os.devnull, 'a') - -ALLOWED_FLAGS = 'sdpSDP' class Applications(FileManagerAware): """ @@ -96,6 +91,15 @@ class Applications(FileManagerAware): 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: + handler = self.app_default + return handler(context) def has(self, app): """Returns whether an application is defined""" @@ -107,190 +111,6 @@ class Applications(FileManagerAware): return [meth[4:] for meth in methods if meth.startswith('app_')] -class AppContext(object): - """ - An AppContext object abstracts the spawning of processes. - - At initialization of the object you can define many high-level options. - When you call the run() function, those options are evaluated and - translated into Popen() calls. - - An instances of this class is passed as the only argument to - app_xyz calls of the Applications object. - - Attributes: - action -- a string with a command or a list of arguments for - the Popen call. - app -- the name of the app function. ("vim" for app_vim.) - app is used to get an action if the user didn't specify one. - 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 - file -- an arbitrary file from that list (or None) - fm -- the filemanager instance - wait -- boolean, wait for the end or execute programs in parallel? - stdout -- directly passed to Popen - stderr -- directly passed to Popen - stdin -- directly passed to Popen - shell -- directly passed to Popen. Should the string be shell-interpreted? - - List of allowed flags: - s: silent mode. output will be discarded. - d: detach the process. - p: redirect output to the pager - - An uppercase key ensures that a certain flag will not be used. - """ - - def __init__(self, app='default', files=None, mode=0, flags='', fm=None, - stdout=None, stderr=None, stdin=None, shell=None, - wait=True, action=None): - """ - The necessary parameters are fm and action or app. - """ - - if files is None: - self.files = [] - else: - self.files = list(files) - - try: - self.file = self.files[0] - except IndexError: - self.file = None - - self.app = app - self.action = action - self.mode = mode - self.flags = flags - self.fm = fm - self.stdout = stdout - self.stderr = stderr - self.stdin = stdin - self.wait = wait - - if shell is None: - self.shell = isinstance(action, str) - else: - self.shell = shell - - def __iter__(self): - """Iterates over all file paths""" - if self.files: - for f in self.files: - yield f.path - - def squash_flags(self): - """Remove duplicates and lowercase counterparts of uppercase flags""" - for flag in self.flags: - if ord(flag) <= 90: - bad = flag + flag.lower() - self.flags = ''.join(c for c in self.flags if c not in bad) - - def get_action(self, apps=None): - """Get the action from app_xyz""" - if apps is None and self.fm: - apps = self.fm.apps - - if apps is None: - raise RuntimeError("AppContext has no source for applications!") - - app = apps.get(self.app) - self.action = app(self) - if isinstance(self.action, str): - self.shell = True - self.action = shell_escape(self.action) - else: - self.shell = False - - def run(self): - """ - Run the application in the way specified by the options. - - Returns False if nothing can be done, None if there was an error, - otherwise the process object returned by Popen(). - - This function tries to find an action if none is defined. - """ - - # Try to find an action - - if self.action is None: - self.get_action() - - if self.action is None: - return False - - # Define some preconditions - - toggle_ui = True - pipe_output = False - - self.squash_flags() - - kw = {} - kw['stdout'] = sys.stdout - kw['stderr'] = sys.stderr - kw['args'] = self.action - - for word in ('shell', 'stdout', 'stdin', 'stderr'): - if getattr(self, word) is not None: - kw[word] = getattr(self, word) - - # Evaluate the flags to determine keywords - # for Popen() and other variables - - if 's' in self.flags or 'd' in self.flags: - kw['stdout'] = kw['stderr'] = kw['stdin'] = devnull - - if 'p' in self.flags: - kw['stdout'] = PIPE - kw['stderr'] = PIPE - toggle_ui = False - pipe_output = True - self.wait = False - - if 'd' in self.flags: - toggle_ui = False - self.wait = False - - # Finally, run it - - if toggle_ui: - self._activate_ui(False) - - try: - process = None - try: - process = Popen(**kw) - except: - if self.fm: - self.fm.notify("Failed to run: " + \ - ' '.join(kw['args']), bad=True) - else: - if self.wait: - waitpid_no_intr(process.pid) - finally: - if toggle_ui: - self._activate_ui(True) - - if pipe_output and process: - return run(app='pager', stdin=process.stdout, fm=self.fm) - - return process - - def _activate_ui(self, boolean): - if self.fm and self.fm.ui: - if boolean: - self.fm.ui.initialize() - else: - self.fm.ui.suspend() - -def run(action=None, **kw): - """Shortcut for creating and immediately running an AppContext.""" - app = AppContext(action=action, **kw) - return app.run() - def tup(*args): """ This helper function creates a tuple out of the arguments. @@ -301,6 +121,7 @@ def tup(*args): """ return args + def depends_on(*args): args = tuple(flatten(args)) def decorator(fnc): diff --git a/ranger/commands.py b/ranger/commands.py index afb5d42c..3b552a22 100644 --- a/ranger/commands.py +++ b/ranger/commands.py @@ -390,13 +390,12 @@ class grep(Command): """ def execute(self): - from ranger.applications import run line = parse(self.line) if line.rest(1): action = ['grep', '--color=always', '--line-number'] action.extend(['-e', line.rest(1), '-r']) action.extend(map(lambda x: x.path, self.fm.env.get_selection())) - run(fm=self.fm, action=action, flags='p') + self.fm.execute_command(action, flags='p') # -------------------------------- rest diff --git a/ranger/fm.py b/ranger/fm.py index f8b0284c..06240b8b 100644 --- a/ranger/fm.py +++ b/ranger/fm.py @@ -17,6 +17,7 @@ from collections import deque from ranger.actions import Actions from ranger.container import Bookmarks +from ranger.runner import Runner from ranger.ext.relpath import relpath_conf from ranger.ext.get_executables import get_executables from ranger import __version__ @@ -40,6 +41,11 @@ class FM(Actions): self._executables = None self.apps = self.settings.apps.CustomApplications() + def mylogfunc(text): + self.notify(text, bad=True) + self.run = Runner(ui=self.ui, apps=self.apps, + logfunc=mylogfunc) + from ranger.shared import FileManagerAware FileManagerAware.fm = self diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py index b30b30b0..094a5c17 100644 --- a/ranger/gui/widgets/console.py +++ b/ranger/gui/widgets/console.py @@ -378,8 +378,6 @@ class OpenConsole(ConsoleWithTab): self.history = self.histories[OPEN_HISTORY] def execute(self): - from ranger.applications import run - from subprocess import STDOUT, PIPE command, flags = self._parse() if command: if _CustomTemplate.delimiter in command: |