diff options
Diffstat (limited to 'ranger/applications.py')
-rw-r--r-- | ranger/applications.py | 174 |
1 files changed, 106 insertions, 68 deletions
diff --git a/ranger/applications.py b/ranger/applications.py index beefba9f..499e8b2c 100644 --- a/ranger/applications.py +++ b/ranger/applications.py @@ -9,6 +9,9 @@ An uppercase key ensures that a certain flag will not be used. import os, sys from ranger.ext.waitpid_no_intr import waitpid_no_intr +from subprocess import Popen, PIPE + +devnull = open(os.devnull, 'a') ALLOWED_FLAGS = 'sdpSDP' @@ -26,79 +29,114 @@ class Applications(object): def all(self): """Returns a list with all application functions""" - return [x[4:] for x in self.__class__.__dict__ if x.startswith('app_')] + methods = self.__class__.__dict__ + return [meth[4:] for meth in methods if meth.startswith('app_')] -null = open(os.devnull, 'a') +class AppContext(object): + def __init__(self, app='default', files=None, mode=0, flags='', fm=None, + stdout=None, stderr=None, stdin=None, shell=None, + wait=True, action=None): -def run(*args, **kw): - """Run files with the specified parameters""" - from subprocess import Popen - from subprocess import PIPE + if files is None: + self.files = [] + else: + self.files = list(files) - flags, fm = kw['flags'], kw['fm'] - for flag in flags: - if ord(flag) <= 90: - bad = flag + flag.lower() - flags = ''.join(c for c in flags if c not in bad) + 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 __getitem__(self, key): + return self.files[key] + + def __iter__(self): + if self.files: + for f in self.files: + yield f.path + + def squash_flags(self): + 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): + 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) + self.shell = isinstance(self.action, str) + + def run(self): + self.squash_flags() + if self.action is None: + self.get_action() - args = map(str, args) - popen_kw = {} - popen_kw['stdout'] = sys.stderr - popen_kw['stderr'] = sys.stderr + # ---------------------------- determine keywords for Popen() - for word in ('shell', 'stdout', 'stdin', 'stderr'): - if word in kw: - popen_kw[word] = kw[word] + kw = {} + kw['stdout'] = sys.stderr + kw['stderr'] = sys.stderr + kw['args'] = self.action - if kw['stdin'] is not None: - popen_kw['stdin'] = kw['stdin'] + for word in ('shell', 'stdout', 'stdin', 'stderr'): + if getattr(self, word) is not None: + kw[word] = getattr(self, word) + + if 's' in self.flags or 'd' in self.flags: + kw['stdout'] = kw['stderr'] = kw['stdin'] = devnull + + # --------------------------- run them + if 'p' in self.flags: + kw['stdout'] = PIPE + kw['stderr'] = PIPE + process1 = Popen(**kw) + process2 = run(app='pager', stdin=process1.stdout, fm=self.fm) + return process2 + + elif 'd' in self.flags: + process = Popen(**kw) + return process - if 's' in flags or 'd' in flags: - popen_kw['stdout'] = popen_kw['stderr'] = popen_kw['stdin'] = null - - if 'p' in flags: - popen_kw['stdout'] = PIPE - process1 = Popen(args, **popen_kw) - kw['stdin'] = process1.stdout - kw['files'] = () - kw['flags'] = ''.join(f for f in kw['flags'] if f in 'd') - process2 = kw['apps'].app_pager(**kw) - return process2 - - if 'd' in flags: - process = Popen(args, **popen_kw) - return process - - else: - if fm.ui: - fm.ui.suspend() - try: - p = Popen(args, **popen_kw) - waitpid_no_intr(p.pid) - finally: - if fm.ui: - fm.ui.initialize() - return p - -def spawn(command, fm=None, suspend=True, wait=True): - from subprocess import Popen, STDOUT - from ranger.ext.waitpid_no_intr import waitpid_no_intr - - if suspend and fm and fm.ui: - fm.ui.suspend() - - try: - if wait: - kw = {} else: - kw = {'stdout':null, 'stderr':null, 'stdin':null} - - if fm and fm.stderr_to_out: - if 'stderr' not in kw: - kw['stderr'] = STDOUT - process = Popen(command, shell=True, **kw) - if wait: - waitpid_no_intr(process.pid) - finally: - if suspend and fm and fm.ui: - fm.ui.initialize() + self._activate_ui(False) + try: + p = Popen(**kw) + if self.wait: + waitpid_no_intr(p.pid) + finally: + self._activate_ui(True) + + 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): + app = AppContext(action=action, **kw) + return app.run() + +def tup(*args): + return tuple(args) |