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
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
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)
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]))
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