Example #1
0
    def get_mimetype(self, fname):
        # Spawn "file" to determine the mime-type of the given file.
        if self._mimetype:
            return self._mimetype

        import mimetypes
        if not mimetypes.inited:
            mimetypes.init(mimetypes.knownfiles + self._mimetype_known_files)
        self._mimetype, _ = mimetypes.guess_type(fname)

        if not self._mimetype:
            with Popen23(["file", "--mime-type", "-Lb", fname],
                         stdout=PIPE,
                         stderr=PIPE) as process:
                mimetype, _ = process.communicate()
            self._mimetype = mimetype.decode(ENCODING).strip()
            if self._mimetype == 'application/octet-stream':
                try:
                    with Popen23(
                        ["mimetype", "--output-format", "%m", fname],
                            stdout=PIPE,
                            stderr=PIPE,
                    ) as process:
                        mimetype, _ = process.communicate()
                    self._mimetype = mimetype.decode(ENCODING).strip()
                except OSError:
                    pass
        return self._mimetype
Example #2
0
def check_output(popenargs, **kwargs):
    """Runs a program, waits for its termination and returns its output

    This function is functionally identical to python 2.7's subprocess.check_output,
    but is favored due to python 2.6 compatibility.

    Will be run through a shell if `popenargs` is a string, otherwise the command
    is executed directly.

    The keyword argument `decode` determines if the output shall be decoded
    with the encoding UTF-8.

    Further keyword arguments are passed to Popen.
    """

    do_decode = kwargs.pop('decode', True)
    kwargs.setdefault('stdout', PIPE)
    kwargs.setdefault('shell', isinstance(popenargs, str))

    if 'stderr' in kwargs:
        with Popen23(popenargs, **kwargs) as process:
            stdout, _ = process.communicate()
    else:
        with open(devnull, mode='w', encoding="utf-8") as fd_devnull:
            with Popen23(popenargs, stderr=fd_devnull, **kwargs) as process:
                stdout, _ = process.communicate()

    if process.returncode != 0:
        error = CalledProcessError(process.returncode, popenargs)
        error.output = stdout
        raise error

    if do_decode and stdout is not None:
        stdout = stdout.decode(ENCODING)

    return stdout
Example #3
0
    def _get_font_dimensions(self):
        # Get the height and width of a character displayed in the terminal in
        # pixels.
        if self.binary_path is None:
            self.binary_path = self._find_w3mimgdisplay_executable()
        farg = struct.pack("HHHH", 0, 0, 0, 0)
        fd_stdout = sys.stdout.fileno()
        fretint = fcntl.ioctl(fd_stdout, termios.TIOCGWINSZ, farg)
        rows, cols, xpixels, ypixels = struct.unpack("HHHH", fretint)
        if xpixels == 0 and ypixels == 0:
            with Popen23(
                [self.binary_path, "-test"],
                    stdout=PIPE,
                    universal_newlines=True,
            ) as process:
                output, _ = process.communicate()
            output = output.split()
            xpixels, ypixels = int(output[0]), int(output[1])
            # adjust for misplacement
            xpixels += 2
            ypixels += 2

        return (xpixels // cols), (ypixels // rows)
Example #4
0
def main():  # pylint: disable=too-many-locals
    """The main function which is run when you start this program directly."""

    # Evaluate arguments
    from optparse import OptionParser  # pylint: disable=deprecated-module
    parser = OptionParser(usage="%prog [-fhlpw] [files]", version=__version__)
    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")
    parser.add_option(
        '-c',
        type='string',
        default=None,
        metavar="CONFIG_FILE",
        help="read config from specified file instead of default")
    options, positional = parser.parse_args()
    if not positional:
        parser.print_help()
        raise SystemExit(1)

    if options.c is None:
        conf_path = find_conf_path()
        if not conf_path:
            raise SystemExit(1)
    else:
        try:
            conf_path = os.path.abspath(options.c)
        except OSError as ex:
            sys.stderr.write(
                "Unable to access specified configuration file: {0}\n".format(
                    ex))
            raise SystemExit(1)
        if not os.path.isfile(conf_path):
            sys.stderr.write(
                "Specified configuration file not found: {0}\n".format(
                    conf_path))
            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:
        with Popen23([options.w] + list(positional)) as process:
            process.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:
            result = rifle.execute(positional,
                                   number=number,
                                   label=label,
                                   flags=options.f)
            if result == ASK_COMMAND:
                # TODO: implement interactive asking for file type?
                print("Unknown file type: %s" %
                      rifle.get_mimetype(positional[0]))
Example #5
0
    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 Popen23(cmd, env=self.hook_environment(
                            os.environ)) as process:
                        process.wait()
            finally:
                self.hook_after_executing(command, self._mimetype,
                                          self._app_flags)

        return None