예제 #1
0
파일: rifle.py 프로젝트: joshy/ranger
    def execute(
            self,
            files,  # noqa: E501 pylint: disable=too-many-branches,too-many-statements,too-many-locals
            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)
                if cmd == ASK_COMMAND:
                    return ASK_COMMAND
                command = self._build_command(files, cmd, flags + flgs)
                flags = self._app_flags
                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:  # pylint: disable=too-many-nested-blocks
            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:
                if 'r' in flags:
                    prefix = ['sudo', '-E', 'su', '-mc']
                else:
                    prefix = ['/bin/sh', '-c']

                cmd = prefix + [command]
                if 't' in flags:
                    if 'TERMCMD' not in os.environ:
                        term = os.environ['TERM']
                        if term.startswith('rxvt-unicode'):
                            term = 'urxvt'
                        elif term.startswith('rxvt-'):
                            # Sometimes urxvt calls itself "rxvt-256color"
                            if 'rxvt' in get_executables():
                                term = 'rxvt'
                            else:
                                term = 'urxvt'
                        if term not in get_executables():
                            self.hook_logger(
                                "Can not determine terminal command.  "
                                "Please set $TERMCMD manually.")
                            # A fallback terminal that is likely installed:
                            term = 'xterm'
                        os.environ['TERMCMD'] = term
                    cmd = [os.environ['TERMCMD'], '-e'] + cmd
                if 'f' in flags or 't' in flags:
                    Popen_forked(cmd, env=self.hook_environment(os.environ))
                else:
                    process = Popen(cmd, env=self.hook_environment(os.environ))
                    process.wait()
            finally:
                self.hook_after_executing(command, self._mimetype,
                                          self._app_flags)

        return None
예제 #2
0
파일: runner.py 프로젝트: y-lu/ranger
    def __call__(
            # pylint: disable=too-many-branches,too-many-statements
            # pylint: disable=too-many-arguments,too-many-locals
            self, action=None, try_app_first=False,
            app='default', files=None, mode=0,
            flags='', wait=True, **popen_kws):
        """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.
        """

        # Find an action if none was supplied by
        # creating a Context object and passing it to
        # an Application object.

        context = Context(app=app, files=files, mode=mode, fm=self.fm,
                          flags=flags, wait=wait, popen_kws=popen_kws,
                          file=files and files[0] or None)

        if action is None:
            return self._log("No way of determining the action!")

        # Preconditions

        context.squash_flags()
        popen_kws = context.popen_kws  # shortcut

        toggle_ui = True
        pipe_output = False
        wait_for_enter = False
        devnull = None

        if 'shell' not in popen_kws:
            popen_kws['shell'] = isinstance(action, str)

        # Set default shell for Popen
        if popen_kws['shell']:
            # This doesn't work with fish, see #300
            if 'fish' not in os.environ['SHELL']:
                popen_kws['executable'] = os.environ['SHELL']

        if 'stdout' not in popen_kws:
            popen_kws['stdout'] = sys.stdout
        if 'stderr' not in popen_kws:
            popen_kws['stderr'] = sys.stderr

        # Evaluate the flags to determine keywords
        # for Popen() and other variables

        if 'p' in context.flags:
            popen_kws['stdout'] = PIPE
            popen_kws['stderr'] = PIPE
            toggle_ui = False
            pipe_output = True
            context.wait = False
        if 's' in context.flags:
            devnull_writable = open(os.devnull, 'w')
            devnull_readable = open(os.devnull, 'r')
            for key in ('stdout', 'stderr'):
                popen_kws[key] = devnull_writable
            toggle_ui = False
            popen_kws['stdin'] = devnull_readable
        if 'f' in context.flags:
            toggle_ui = False
            context.wait = False
        if 'w' in context.flags:
            if not pipe_output and context.wait:  # <-- sanity check
                wait_for_enter = True
        if 'r' in context.flags:
            # TODO: make 'r' flag work with pipes
            if 'sudo' not in get_executables():
                return self._log("Can not run with 'r' flag, sudo is not installed!")
            f_flag = ('f' in context.flags)
            if isinstance(action, str):
                action = 'sudo ' + (f_flag and '-b ' or '') + action
            else:
                action = ['sudo'] + (f_flag and ['-b'] or []) + action
            toggle_ui = True
            context.wait = True
        if 't' in context.flags:
            if 'DISPLAY' not in os.environ:
                return self._log("Can not run with 't' flag, no display found!")
            term = get_term()
            if isinstance(action, str):
                action = term + ' -e ' + action
            else:
                action = [term, '-e'] + action
            toggle_ui = False
            context.wait = False

        popen_kws['args'] = action
        # Finally, run it

        if toggle_ui:
            self._activate_ui(False)
        try:
            error = None
            process = None
            self.fm.signal_emit('runner.execute.before',
                                popen_kws=popen_kws, context=context)
            try:
                if 'f' in context.flags:
                    # This can fail and return False if os.fork() is not
                    # supported, but we assume it is, since curses is used.
                    Popen_forked(**popen_kws)
                else:
                    process = Popen(**popen_kws)
            except OSError as ex:
                error = ex
                self._log("Failed to run: %s\n%s" % (str(action), str(ex)))
            else:
                if context.wait:
                    process.wait()
                elif process:
                    self.zombies.add(process)
                if wait_for_enter:
                    press_enter()
        finally:
            self.fm.signal_emit('runner.execute.after',
                                popen_kws=popen_kws, context=context, error=error)
            if devnull:
                devnull.close()
            if toggle_ui:
                self._activate_ui(True)
            if pipe_output and process:
                return self(action='less', app='pager',  # pylint: disable=lost-exception
                            try_app_first=True, stdin=process.stdout)
            return process  # pylint: disable=lost-exception
예제 #3
0
파일: rifle.py 프로젝트: EdwardBetts/ranger
    def execute(self, files,  # noqa: E501 pylint: disable=too-many-branches,too-many-statements,too-many-locals
                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)
                if cmd == ASK_COMMAND:
                    return ASK_COMMAND
                command = self._build_command(files, cmd, flags + flgs)
                flags = self._app_flags
                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:  # pylint: disable=too-many-nested-blocks
            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'] = os.environ.get('VISUAL', DEFAULT_EDITOR)
            command = self.hook_command_postprocessing(command)
            self.hook_before_executing(command, self._mimetype, self._app_flags)
            try:
                if 'r' in flags:
                    prefix = ['sudo', '-E', 'su', 'root', '-mc']
                else:
                    prefix = ['/bin/sh', '-c']

                cmd = prefix + [command]
                if 't' in flags:
                    term = os.environ.get('TERMCMD', os.environ['TERM'])

                    # Handle aliases of xterm and urxvt, rxvt and st and
                    # termite
                    # Match 'xterm', 'xterm-256color'
                    if term in ['xterm', 'xterm-256color']:
                        term = 'xterm'
                    if term in ['xterm-kitty']:
                        term = 'kitty'
                    if term in ['xterm-termite']:
                        term = 'termite'
                    if term in ['st', 'st-256color']:
                        term = 'st'
                    if term in ['urxvt', 'rxvt-unicode',
                                'rxvt-unicode-256color']:
                        term = 'urxvt'
                    if term in ['rxvt', 'rxvt-256color']:
                        if 'rxvt' in get_executables():
                            term = 'rxvt'
                        else:
                            term = 'urxvt'

                    if term not in get_executables():
                        self.hook_logger("Can not determine terminal command, "
                                         "using rifle to determine fallback.  "
                                         "Please set $TERMCMD manually or "
                                         "change fallbacks in rifle.conf.")
                        self._mimetype = 'ranger/x-terminal-emulator'
                        self.execute(
                            files=[command.split(';')[1].split('--')[0].strip()]
                            + files, flags='f',
                            mimetype='ranger/x-terminal-emulator')
                        return None

                    # Choose correct cmdflag accordingly
                    if term in ['xfce4-terminal', 'mate-terminal',
                                'terminator']:
                        cmdflag = '-x'
                    elif term in ['xterm', 'urxvt', 'rxvt', 'lxterminal',
                                  'konsole', 'lilyterm', 'cool-retro-term',
                                  'terminology', 'pantheon-terminal', 'termite',
                                  'st', 'stterm']:
                        cmdflag = '-e'
                    elif term in ['gnome-terminal', 'kitty']:
                        cmdflag = '--'
                    elif term in ['tilda', ]:
                        cmdflag = '-c'
                    else:
                        cmdflag = '-e'

                    os.environ['TERMCMD'] = term

                    # These terms don't work with the '/bin/sh set --' scheme.
                    # A temporary fix.
                    if term in ['tilda', 'pantheon-terminal', 'terminology',
                                'termite']:

                        target = command.split(';')[0].split('--')[1].strip()
                        app = command.split(';')[1].split('--')[0].strip()
                        cmd = [os.environ['TERMCMD'], cmdflag, '%s %s'
                               % (app, target)]
                    elif term in ['guake']:
                        cmd = [os.environ['TERMCMD'], '-n', '${PWD}', cmdflag] + cmd
                    else:
                        cmd = [os.environ['TERMCMD'], cmdflag] + cmd

                    # self.hook_logger('cmd: %s' %cmd)

                if 'f' in flags or 't' in flags:
                    Popen_forked(cmd, env=self.hook_environment(os.environ))
                else:
                    with Popen(
                        cmd, env=self.hook_environment(os.environ)
                    ) as process:
                        process.wait()
            finally:
                self.hook_after_executing(command, self._mimetype, self._app_flags)

        return None