about summary refs log tree commit diff
path: root/ranger
diff options
context:
space:
mode:
Diffstat (limited to 'ranger')
-rw-r--r--ranger/.config/ranger/commands.py9
-rw-r--r--ranger/.config/ranger/commands_full.py356
-rw-r--r--ranger/.config/ranger/rc.conf102
-rw-r--r--ranger/.config/ranger/rifle.conf45
-rwxr-xr-xranger/.config/ranger/scope.sh56
5 files changed, 323 insertions, 245 deletions
diff --git a/ranger/.config/ranger/commands.py b/ranger/.config/ranger/commands.py
index 2df405f..1386e84 100644
--- a/ranger/.config/ranger/commands.py
+++ b/ranger/.config/ranger/commands.py
@@ -8,13 +8,15 @@
 from ranger.api.commands import *
 
 # A simple command for demonstration purposes follows.
-#------------------------------------------------------------------------------
+# -----------------------------------------------------------------------------
 
 # You can import any python module as needed.
 import os
 
 # Any class that is a subclass of "Command" will be integrated into ranger as a
 # command.  Try typing ":my_edit<ENTER>" in ranger!
+
+
 class my_edit(Command):
     # The so-called doc-string of the class will be visible in the built-in
     # help that is accessible by typing "?c" inside ranger.
@@ -37,7 +39,7 @@ class my_edit(Command):
             # reference to the currently selected file.
             target_filename = self.fm.thisfile.path
 
-        # This is a generic function to print text in ranger.  
+        # This is a generic function to print text in ranger.
         self.fm.notify("Let's edit the file " + target_filename + "!")
 
         # Using bad=True in fm.notify allows you to print error messages:
@@ -52,7 +54,8 @@ class my_edit(Command):
 
     # The tab method is called when you press tab, and should return a list of
     # suggestions that the user will tab through.
-    def tab(self):
+    # tabnum is 1 for <TAB> and -1 for <S-TAB> by default
+    def tab(self, tabnum):
         # This is a generic tab-completion function that iterates through the
         # content of the current directory.
         return self._tab_directory_content()
diff --git a/ranger/.config/ranger/commands_full.py b/ranger/.config/ranger/commands_full.py
index cb62a62..a384f42 100644
--- a/ranger/.config/ranger/commands_full.py
+++ b/ranger/.config/ranger/commands_full.py
@@ -21,10 +21,12 @@
 # ===================================================================
 # Every class defined here which is a subclass of `Command' will be used as a
 # command in ranger.  Several methods are defined to interface with ranger:
-#   execute(): called when the command is executed.
-#   cancel():  called when closing the console.
-#   tab():     called when <TAB> is pressed.
-#   quick():   called after each keypress.
+#   execute():   called when the command is executed.
+#   cancel():    called when closing the console.
+#   tab(tabnum): called when <TAB> is pressed.
+#   quick():     called after each keypress.
+#
+# tab() argument tabnum is 1 for <TAB> and -1 for <S-TAB> by default
 #
 # The return values for tab() can be either:
 #   None: There is no tab completion
@@ -83,6 +85,7 @@
 
 from ranger.api.commands import *
 
+
 class alias(Command):
     """:alias <newcommand> <oldcommand>
 
@@ -98,6 +101,16 @@ class alias(Command):
         else:
             self.fm.commands.alias(self.arg(1), self.rest(2))
 
+
+class echo(Command):
+    """:echo <text>
+
+    Display the text in the statusbar.
+    """
+    def execute(self):
+        self.fm.notify(self.rest(1))
+
+
 class cd(Command):
     """:cd [-r] <dirname>
 
@@ -125,7 +138,7 @@ class cd(Command):
         else:
             self.fm.cd(destination)
 
-    def tab(self):
+    def tab(self, tabnum):
         import os
         from os.path import dirname, basename, expanduser, join
 
@@ -133,7 +146,7 @@ class cd(Command):
         rel_dest = self.rest(1)
 
         bookmarks = [v.path for v in self.fm.bookmarks.dct.values()
-                if rel_dest in v.path ]
+                if rel_dest in v.path]
 
         # expand the tilde into the user directory
         if rel_dest.startswith('~'):
@@ -153,7 +166,7 @@ class cd(Command):
             # are we in the middle of the filename?
             else:
                 _, dirnames, _ = next(os.walk(abs_dirname))
-                dirnames = [dn for dn in dirnames \
+                dirnames = [dn for dn in dirnames
                         if dn.startswith(rel_basename)]
         except (OSError, StopIteration):
             # os.walk found nothing
@@ -182,7 +195,7 @@ class chain(Command):
     Calls multiple commands at once, separated by semicolons.
     """
     def execute(self):
-        for command in self.rest(1).split(";"):
+        for command in [s.strip() for s in self.rest(1).split(";")]:
             self.fm.execute_console(command)
 
 
@@ -197,14 +210,10 @@ class shell(Command):
             flags = ''
             command = self.rest(1)
 
-        if not command and 'p' in flags:
-            command = 'cat %f'
         if command:
-            if '%' in command:
-                command = self.fm.substitute_macros(command, escape=True)
             self.fm.execute_command(command, flags=flags)
 
-    def tab(self):
+    def tab(self, tabnum):
         from ranger.ext.get_executables import get_executables
         if self.arg(1) and self.arg(1)[0] == '-':
             command = self.rest(2)
@@ -215,7 +224,7 @@ class shell(Command):
         try:
             position_of_last_space = command.rindex(" ")
         except ValueError:
-            return (start + program + ' ' for program \
+            return (start + program + ' ' for program
                     in get_executables() if program.startswith(command))
         if position_of_last_space == len(command) - 1:
             selection = self.fm.thistab.get_selection()
@@ -225,20 +234,21 @@ class shell(Command):
                 return self.line + '%s '
         else:
             before_word, start_of_word = self.line.rsplit(' ', 1)
-            return (before_word + ' ' + file.shell_escaped_basename \
-                    for file in self.fm.thisdir.files \
+            return (before_word + ' ' + file.shell_escaped_basename
+                    for file in self.fm.thisdir.files or []
                     if file.shell_escaped_basename.startswith(start_of_word))
 
+
 class open_with(Command):
     def execute(self):
         app, flags, mode = self._get_app_flags_mode(self.rest(1))
         self.fm.execute_file(
-                files = [f for f in self.fm.thistab.get_selection()],
-                app = app,
-                flags = flags,
-                mode = mode)
+                files=[f for f in self.fm.thistab.get_selection()],
+                app=app,
+                flags=flags,
+                mode=mode)
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_through_executables()
 
     def _get_app_flags_mode(self, string):
@@ -328,26 +338,32 @@ class set_(Command):
     """:set <option name>=<python expression>
 
     Gives an option a new value.
+
+    Use `:set <option>!` to toggle or cycle it, e.g. `:set flush_input!`
     """
     name = 'set'  # don't override the builtin set class
+
     def execute(self):
         name = self.arg(1)
-        name, value, _ = self.parse_setting_line()
-        self.fm.set_option_from_string(name, value)
+        name, value, _, toggle = self.parse_setting_line_v2()
+        if toggle:
+            self.fm.toggle_option(name)
+        else:
+            self.fm.set_option_from_string(name, value)
 
-    def tab(self):
+    def tab(self, tabnum):
         from ranger.gui.colorscheme import get_all_colorschemes
         name, value, name_done = self.parse_setting_line()
         settings = self.fm.settings
         if not name:
             return sorted(self.firstpart + setting for setting in settings)
         if not value and not name_done:
-            return (self.firstpart + setting for setting in settings \
+            return sorted(self.firstpart + setting for setting in settings
                     if setting.startswith(name))
         if not value:
             # Cycle through colorschemes when name, but no value is specified
             if name == "colorscheme":
-                return (self.firstpart + colorscheme for colorscheme \
+                return sorted(self.firstpart + colorscheme for colorscheme
                         in get_all_colorschemes())
             return self.firstpart + str(settings[name])
         if bool in settings.types_of(name):
@@ -357,16 +373,17 @@ class set_(Command):
                 return self.firstpart + 'False'
         # Tab complete colorscheme values if incomplete value is present
         if name == "colorscheme":
-            return (self.firstpart + colorscheme for colorscheme \
+            return sorted(self.firstpart + colorscheme for colorscheme
                     in get_all_colorschemes() if colorscheme.startswith(value))
 
 
 class setlocal(set_):
-    """:setlocal path=<python string> <option name>=<python expression>
+    """:setlocal path=<regular expression> <option name>=<python expression>
 
     Gives an option a new value.
     """
     PATH_RE = re.compile(r'^\s*path="?(.*?)"?\s*$')
+
     def execute(self):
         import os.path
         match = self.PATH_RE.match(self.arg(1))
@@ -432,7 +449,7 @@ class default_linemode(Command):
             for col in self.fm.ui.browser.columns:
                 col.need_redraw = True
 
-    def tab(self):
+    def tab(self, tabnum):
         mode = self.arg(1)
         return (self.arg(0) + " " + linemode
                 for linemode in self.fm.thisfile.linemode_dict.keys()
@@ -476,20 +493,15 @@ class terminal(Command):
     Spawns an "x-terminal-emulator" starting in the current directory.
     """
     def execute(self):
-        import os
-        from ranger.ext.get_executables import get_executables
-        command = os.environ.get('TERMCMD', os.environ.get('TERM'))
-        if command not in get_executables():
-            command = 'x-terminal-emulator'
-        if command not in get_executables():
-            command = 'xterm'
-        self.fm.run(command, flags='f')
+        from ranger.ext.get_executables import get_term
+        self.fm.run(get_term(), flags='f')
 
 
 class delete(Command):
     """:delete
 
-    Tries to delete the selection.
+    Tries to delete the selection or the files passed in arguments (if any).
+    The arguments use a shell-like escaping.
 
     "Selection" is defined as all the "marked files" (by default, you
     can mark files with space or v). If there are no marked files,
@@ -500,41 +512,49 @@ class delete(Command):
     """
 
     allow_abbrev = False
+    escape_macros_for_shell = True
 
     def execute(self):
         import os
+        import shlex
+        from functools import partial
+        from ranger.container.file import File
+
+        def is_directory_with_files(f):
+            import os.path
+            return (os.path.isdir(f) and not os.path.islink(f)
+                and len(os.listdir(f)) > 0)
+
         if self.rest(1):
-            self.fm.notify("Error: delete takes no arguments! It deletes "
-                    "the selected file(s).", bad=True)
-            return
+            files = shlex.split(self.rest(1))
+            many_files = (len(files) > 1 or is_directory_with_files(files[0]))
+        else:
+            cwd = self.fm.thisdir
+            cf = self.fm.thisfile
+            if not cwd or not cf:
+                self.fm.notify("Error: no file selected for deletion!", bad=True)
+                return
 
-        cwd = self.fm.thisdir
-        cf = self.fm.thisfile
-        if not cwd or not cf:
-            self.fm.notify("Error: no file selected for deletion!", bad=True)
-            return
+            # relative_path used for a user-friendly output in the confirmation.
+            files = [f.relative_path for f in self.fm.thistab.get_selection()]
+            many_files = (cwd.marked_items or is_directory_with_files(cf.path))
 
         confirm = self.fm.settings.confirm_on_delete
-        many_files = (cwd.marked_items or (cf.is_directory and not cf.is_link \
-                and len(os.listdir(cf.path)) > 0))
-
         if confirm != 'never' and (confirm != 'multiple' or many_files):
+            filename_list = files
             self.fm.ui.console.ask("Confirm deletion of: %s (y/N)" %
-                ', '.join(f.basename for f in self.fm.thistab.get_selection()),
-                self._question_callback, ('n', 'N', 'y', 'Y'))
+                ', '.join(files),
+                partial(self._question_callback, files), ('n', 'N', 'y', 'Y'))
         else:
             # no need for a confirmation, just delete
-            for f in self.fm.tags.tags:
-                if str(f).startswith(self.fm.thisfile.path):
-                    self.fm.tags.remove(f)
-            self.fm.delete()
+            self.fm.delete(files)
+
+    def tab(self, tabnum):
+        return self._tab_directory_content()
 
-    def _question_callback(self, answer):
+    def _question_callback(self, files, answer):
         if answer == 'y' or answer == 'Y':
-            for f in self.fm.tags.tags:
-                if str(f).startswith(self.fm.thisfile.path):
-                    self.fm.tags.remove(f)
-            self.fm.delete()
+            self.fm.delete(files)
 
 
 class mark_tag(Command):
@@ -547,8 +567,8 @@ class mark_tag(Command):
 
     def execute(self):
         cwd = self.fm.thisdir
-        tags = self.rest(1).replace(" ","")
-        if not self.fm.tags:
+        tags = self.rest(1).replace(" ", "")
+        if not self.fm.tags or not cwd.files:
             return
         for fileobj in cwd.files:
             try:
@@ -572,7 +592,7 @@ class console(Command):
             try:
                 position = int(self.arg(1)[2:])
                 self.shift()
-            except:
+            except Exception:
                 pass
         self.fm.open_console(self.rest(1), position=position)
 
@@ -583,16 +603,17 @@ class load_copy_buffer(Command):
     Load the copy buffer from confdir/copy_buffer
     """
     copy_buffer_filename = 'copy_buffer'
+
     def execute(self):
         from ranger.container.file import File
         from os.path import exists
         try:
             fname = self.fm.confpath(self.copy_buffer_filename)
             f = open(fname, 'r')
-        except:
-            return self.fm.notify("Cannot open %s" % \
+        except Exception:
+            return self.fm.notify("Cannot open %s" %
                     (fname or self.copy_buffer_filename), bad=True)
-        self.fm.copy_buffer = set(File(g) \
+        self.fm.copy_buffer = set(File(g)
             for g in f.read().split("\n") if exists(g))
         f.close()
         self.fm.ui.redraw_main_column()
@@ -604,13 +625,14 @@ class save_copy_buffer(Command):
     Save the copy buffer to confdir/copy_buffer
     """
     copy_buffer_filename = 'copy_buffer'
+
     def execute(self):
         fname = None
         try:
             fname = self.fm.confpath(self.copy_buffer_filename)
             f = open(fname, 'w')
-        except:
-            return self.fm.notify("Cannot open %s" % \
+        except Exception:
+            return self.fm.notify("Cannot open %s" %
                     (fname or self.copy_buffer_filename), bad=True)
         f.write("\n".join(f.path for f in self.fm.copy_buffer))
         f.close()
@@ -641,7 +663,7 @@ class mkdir(Command):
         else:
             self.fm.notify("file/directory exists!", bad=True)
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_directory_content()
 
 
@@ -660,7 +682,7 @@ class touch(Command):
         else:
             self.fm.notify("file/directory exists!", bad=True)
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_directory_content()
 
 
@@ -676,7 +698,7 @@ class edit(Command):
         else:
             self.fm.edit_file(self.rest(1))
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_directory_content()
 
 
@@ -733,7 +755,7 @@ class rename(Command):
         new_name = self.rest(1)
 
         tagged = {}
-        old_name = self.fm.thisfile.basename
+        old_name = self.fm.thisfile.relative_path
         for f in self.fm.tags.tags:
             if str(f).startswith(self.fm.thisfile.path):
                 tagged[f] = self.fm.tags.tags[f]
@@ -742,7 +764,7 @@ class rename(Command):
         if not new_name:
             return self.fm.notify('Syntax: rename <newname>', bad=True)
 
-        if new_name == self.fm.thisfile.basename:
+        if new_name == old_name:
             return
 
         if access(new_name, os.F_OK):
@@ -750,15 +772,24 @@ class rename(Command):
 
         if self.fm.rename(self.fm.thisfile, new_name):
             f = File(new_name)
+            # Update bookmarks that were pointing on the previous name
+            obsoletebookmarks = [b for b in self.fm.bookmarks
+                                 if b[1].path == self.fm.thisfile]
+            if obsoletebookmarks:
+                for key, _ in obsoletebookmarks:
+                    self.fm.bookmarks[key] = f
+                self.fm.bookmarks.update_if_outdated()
+
             self.fm.thisdir.pointed_obj = f
             self.fm.thisfile = f
             for t in tagged:
-                self.fm.tags.tags[t.replace(old_name,new_name)] = tagged[t]
+                self.fm.tags.tags[t.replace(old_name, new_name)] = tagged[t]
                 self.fm.tags.dump()
 
-    def tab(self):
+    def tab(self, tabnum):
         return self._tab_directory_content()
 
+
 class rename_append(Command):
     """:rename_append
 
@@ -767,10 +798,12 @@ class rename_append(Command):
 
     def execute(self):
         cf = self.fm.thisfile
-        if cf.basename.find('.') != 0 and cf.basename.rfind('.') != -1 and not cf.is_directory:
-            self.fm.open_console('rename ' + cf.basename, position=(7 + cf.basename.rfind('.')))
+        path = cf.relative_path.replace("%", "%%")
+        if path.find('.') != 0 and path.rfind('.') != -1 and not cf.is_directory:
+            self.fm.open_console('rename ' + path, position=(7 + path.rfind('.')))
         else:
-            self.fm.open_console('rename ' + cf.basename)
+            self.fm.open_console('rename ' + path)
+
 
 class chmod(Command):
     """:chmod <octal number>
@@ -807,7 +840,7 @@ class chmod(Command):
             # reloading directory.  maybe its better to reload the selected
             # files only.
             self.fm.thisdir.load_content()
-        except:
+        except Exception:
             pass
 
 
@@ -852,7 +885,7 @@ class bulkrename(Command):
         script_lines = []
         script_lines.append("# This file will be executed when you close the editor.\n")
         script_lines.append("# Please double-check everything, clear the file to abort.\n")
-        script_lines.extend("mv -vi -- %s %s\n" % (esc(old), esc(new)) \
+        script_lines.extend("mv -vi -- %s %s\n" % (esc(old), esc(new))
                 for old, new in zip(filenames, new_filenames) if old != new)
         script_content = "".join(script_lines)
         if py3:
@@ -889,6 +922,7 @@ class bulkrename(Command):
         else:
             fm.notify("files have not been retagged")
 
+
 class relink(Command):
     """:relink <newpath>
 
@@ -905,7 +939,7 @@ class relink(Command):
             return self.fm.notify('Syntax: relink <newpath>', bad=True)
 
         if not cf.is_link:
-            return self.fm.notify('%s is not a symlink!' % cf.basename, bad=True)
+            return self.fm.notify('%s is not a symlink!' % cf.relative_path, bad=True)
 
         if new_path == os.readlink(cf.path):
             return
@@ -920,9 +954,9 @@ class relink(Command):
         self.fm.thisdir.pointed_obj = cf
         self.fm.thisfile = cf
 
-    def tab(self):
+    def tab(self, tabnum):
         if not self.rest(1):
-            return self.line+os.readlink(self.fm.thisfile.path)
+            return self.line + os.readlink(self.fm.thisfile.path)
         else:
             return self._tab_directory_content()
 
@@ -933,6 +967,7 @@ class help_(Command):
     Display ranger's manual page.
     """
     name = 'help'
+
     def execute(self):
         def callback(answer):
             if answer == "q":
@@ -1090,6 +1125,7 @@ class scout(Command):
     -m = mark the matching files after pressing enter
     -M = unmark the matching files after pressing enter
     -p = permanent filter: hide non-matching files after pressing enter
+    -r = interpret pattern as a regular expression pattern
     -s = smart case; like -i unless pattern contains upper case letters
     -t = apply filter and search pattern as you type
     -v = inverts the match
@@ -1127,14 +1163,14 @@ class scout(Command):
         self.fm.thistab.last_search = regex
         self.fm.set_search_method(order="search")
 
-        if self.MARK in flags or self.UNMARK in flags:
+        if (self.MARK in flags or self.UNMARK in flags) and thisdir.files:
             value = flags.find(self.MARK) > flags.find(self.UNMARK)
             if self.FILTER in flags:
                 for f in thisdir.files:
                     thisdir.mark_item(f, value)
             else:
                 for f in thisdir.files:
-                    if regex.search(f.basename):
+                    if regex.search(f.relative_path):
                         thisdir.mark_item(f, value)
 
         if self.PERM_FILTER in flags:
@@ -1176,8 +1212,8 @@ class scout(Command):
             return True
         return False
 
-    def tab(self):
-        self._count(move=True, offset=1)
+    def tab(self, tabnum):
+        self._count(move=True, offset=tabnum)
 
     def _build_regex(self):
         if self._regex is not None:
@@ -1215,13 +1251,13 @@ class scout(Command):
             regex = "^(?:(?!%s).)*$" % regex
 
         # Compile Regular Expression
-        options = re.LOCALE | re.UNICODE
+        options = re.UNICODE
         if self.IGNORE_CASE in flags or self.SMART_CASE in flags and \
                 pattern.islower():
             options |= re.IGNORECASE
         try:
             self._regex = re.compile(regex, options)
-        except:
+        except Exception:
             self._regex = re.compile("")
         return self._regex
 
@@ -1230,7 +1266,7 @@ class scout(Command):
         cwd     = self.fm.thisdir
         pattern = self.pattern
 
-        if not pattern:
+        if not pattern or not cwd.files:
             return 0
         if pattern == '.':
             return 0
@@ -1242,7 +1278,7 @@ class scout(Command):
         i = offset
         regex = self._build_regex()
         for fsobj in deq:
-            if regex.search(fsobj.basename):
+            if regex.search(fsobj.relative_path):
                 count += 1
                 if move and count == 1:
                     cwd.move(to=(cwd.pointer + i) % len(cwd.files))
@@ -1295,130 +1331,75 @@ class grep(Command):
             self.fm.execute_command(action, flags='p')
 
 
-# Version control commands
-# --------------------------------
-class stage(Command):
-    """
-    :stage
-
-    Stage selected files for the corresponding version control system
+class flat(Command):
     """
-    def execute(self):
-        from ranger.ext.vcs import VcsError
-
-        filelist = [f.path for f in self.fm.thistab.get_selection()]
-        self.fm.thisdir.vcs_outdated = True
-#        for f in self.fm.thistab.get_selection():
-#            f.vcs_outdated = True
-
-        try:
-            self.fm.thisdir.vcs.add(filelist)
-        except VcsError:
-            self.fm.notify("Could not stage files.")
-
-        self.fm.reload_cwd()
+    :flat <level>
 
+    Flattens the directory view up to the specified level.
 
-class unstage(Command):
+        -1 fully flattened
+         0 remove flattened view
     """
-    :unstage
 
-    Unstage selected files for the corresponding version control system
-    """
     def execute(self):
-        from ranger.ext.vcs import VcsError
-
-        filelist = [f.path for f in self.fm.thistab.get_selection()]
-        self.fm.thisdir.vcs_outdated = True
-#        for f in self.fm.thistab.get_selection():
-#            f.vcs_outdated = True
-
         try:
-            self.fm.thisdir.vcs.reset(filelist)
-        except VcsError:
-            self.fm.notify("Could not unstage files.")
+            level = self.rest(1)
+            level = int(level)
+        except ValueError:
+            level = self.quantifier
+        if level < -1:
+            self.fm.notify("Need an integer number (-1, 0, 1, ...)", bad=True)
+        self.fm.thisdir.unload()
+        self.fm.thisdir.flat = level
+        self.fm.thisdir.load_content()
 
-        self.fm.reload_cwd()
+# Version control commands
+# --------------------------------
 
 
-class diff(Command):
+class stage(Command):
     """
-    :diff
+    :stage
 
-    Displays a diff of selected files against the last committed version
+    Stage selected files for the corresponding version control system
     """
     def execute(self):
         from ranger.ext.vcs import VcsError
-        import tempfile
-
-        L = self.fm.thistab.get_selection()
-        if len(L) == 0: return
-
-        filelist = [f.path for f in L]
-        vcs = L[0].vcs
-
-        diff = vcs.get_raw_diff(filelist=filelist)
-        if len(diff.strip()) > 0:
-            tmp = tempfile.NamedTemporaryFile()
-            tmp.write(diff.encode('utf-8'))
-            tmp.flush()
 
-            pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER)
-            self.fm.run([pager, tmp.name])
+        if self.fm.thisdir.vcs and self.fm.thisdir.vcs.track:
+            filelist = [f.path for f in self.fm.thistab.get_selection()]
+            try:
+                self.fm.thisdir.vcs.action_add(filelist)
+            except VcsError as error:
+                self.fm.notify('Unable to stage files: {0:s}'.format(str(error)))
+            self.fm.ui.vcsthread.process(self.fm.thisdir)
         else:
-            raise Exception("diff is empty")
+            self.fm.notify('Unable to stage files: Not in repository')
 
 
-class log(Command):
+class unstage(Command):
     """
-    :log
+    :unstage
 
-    Displays the log of the current repo or files
+    Unstage selected files for the corresponding version control system
     """
     def execute(self):
         from ranger.ext.vcs import VcsError
-        import tempfile
-
-        L = self.fm.thistab.get_selection()
-        if len(L) == 0: return
-
-        filelist = [f.path for f in L]
-        vcs = L[0].vcs
-
-        log = vcs.get_raw_log(filelist=filelist)
-        tmp = tempfile.NamedTemporaryFile()
-        tmp.write(log.encode('utf-8'))
-        tmp.flush()
-
-        pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER)
-        self.fm.run([pager, tmp.name])
-
-class flat(Command):
-    """
-    :flat <level>
-
-    Flattens the directory view up to the specified level.
-
-        -1 fully flattened
-         0 remove flattened view
-    """
-
-    def execute(self):
-        try:
-            level = self.rest(1)
-            level = int(level)
-        except ValueError:
-            level = self.quantifier
-        if level < -1:
-            self.fm.notify("Need an integer number (-1, 0, 1, ...)", bad=True)
-        self.fm.thisdir.unload()
-        self.fm.thisdir.flat = level
-        self.fm.thisdir.load_content()
 
+        if self.fm.thisdir.vcs and self.fm.thisdir.vcs.track:
+            filelist = [f.path for f in self.fm.thistab.get_selection()]
+            try:
+                self.fm.thisdir.vcs.action_reset(filelist)
+            except VcsError as error:
+                self.fm.notify('Unable to unstage files: {0:s}'.format(str(error)))
+            self.fm.ui.vcsthread.process(self.fm.thisdir)
+        else:
+            self.fm.notify('Unable to unstage files: Not in repository')
 
 # Metadata commands
 # --------------------------------
 
+
 class prompt_metadata(Command):
     """
     :prompt_metadata <key1> [<key2> [<key3> ...]]
@@ -1428,6 +1409,7 @@ class prompt_metadata(Command):
 
     _command_name = "meta"
     _console_chain = None
+
     def execute(self):
         prompt_metadata._console_chain = self.args[1:]
         self._process_command_stack()
@@ -1467,7 +1449,7 @@ class meta(prompt_metadata):
             self.fm.metadata.set_metadata(f.path, update_dict)
         self._process_command_stack()
 
-    def tab(self):
+    def tab(self, tabnum):
         key = self.arg(1)
         metadata = self.fm.metadata.get_metadata(self.fm.thisfile.path)
         if key in metadata and metadata[key]:
diff --git a/ranger/.config/ranger/rc.conf b/ranger/.config/ranger/rc.conf
index 3cc4c42..36e431e 100644
--- a/ranger/.config/ranger/rc.conf
+++ b/ranger/.config/ranger/rc.conf
@@ -1,3 +1,4 @@
+# ===================================================================
 # This file contains the default startup commands for ranger.
 # To change them, it is recommended to create the file
 # ~/.config/ranger/rc.conf and add your custom commands there.
@@ -12,8 +13,18 @@
 # Each line is a command that will be run before the user interface
 # is initialized.  As a result, you can not use commands which rely
 # on the UI such as :delete or :mark.
+# ===================================================================
 
-# Options
+# ===================================================================
+# == Options
+# ===================================================================
+
+# Which viewmode should be used?  Possible values are:
+#     miller: Use miller columns which show multiple levels of the hierarchy
+#     multipane: Midnight-commander like multipane view showing all tabs next
+#                to each other
+set viewmode miller
+#set viewmode multipane
 
 # How many columns are there, and what are their relative widths?
 set column_ratios 1,1
@@ -27,7 +38,7 @@ set show_hidden false
 # Ask for a confirmation when running the "delete" command?
 # Valid values are "always", "never", "multiple" (default)
 # With "multiple", ranger will ask only if you delete multiple files at once.
-set confirm_on_delete multiple
+set confirm_on_delete always
 
 # Which script is used to generate file previews?
 # ranger ships with scope.sh, a script that calls external programs (see
@@ -35,7 +46,7 @@ set confirm_on_delete multiple
 set preview_script ~/.config/ranger/scope.sh
 
 # Use the external preview script or display simple plain text or image previews?
-set use_preview_script false
+set use_preview_script true
 
 # Automatically count files in the directory, even before entering them?
 set automatically_count_files true
@@ -68,10 +79,18 @@ set preview_images true
 #   Preview images in full color using iTerm2 image previews
 #   (http://iterm2.com/images.html). This requires using iTerm2 compiled
 #   with image preview support.
+#
+# * urxvt:
+#   Preview images in full color using urxvt image backgrounds. This
+#   requires using urxvt compiled with pixbuf support.
+#
+# * urxvt-full:
+#   The same as urxvt but utilizing not only the preview pane but the
+#   whole terminal window.
 set preview_images_method w3m
 
 # Use a unicode "..." character to mark cut-off filenames?
-set unicode_ellipsis true
+set unicode_ellipsis false
 
 # Show dotfiles in the bookmark preview box?
 set show_hidden_bookmarks true
@@ -132,12 +151,12 @@ set max_console_history_size 50
 # Try to keep so much space between the top/bottom border when scrolling:
 set scroll_offset 8
 
-# Flush the input after each key hit?  (Noticable when ranger lags)
+# Flush the input after each key hit?  (Noticeable when ranger lags)
 set flushinput true
 
 # Padding on the right when there's no preview?
 # This allows you to click into the space to run the file.
-set padding_right true
+set padding_right false
 
 # Save bookmarks (used with mX and `X) instantly?
 # This helps to synchronize bookmarks between multiple ranger
@@ -187,13 +206,23 @@ set idle_delay 2000
 # check all directories above the current one as well?
 set metadata_deep_search false
 
-# Local Options
+# Clear all existing filters when leaving a directory
+set clear_filters_on_dir_change false
+
+# Disable displaying line numbers in main column
+set line_numbers true
+
+# ===================================================================
+# == Local Options
+# ===================================================================
 # You can set local options that only affect a single directory.
 
 # Examples:
 # setlocal path=~/downloads sort mtime
 
-# Command Aliases in the Console
+# ===================================================================
+# == Command Aliases in the Console
+# ===================================================================
 
 alias e    edit
 alias q    quit
@@ -210,7 +239,9 @@ alias search     scout -rs
 alias search_inc scout -rts
 alias travel     scout -aefiklst
 
-# Define keys for the browser
+# ===================================================================
+# == Define keys for the browser
+# ===================================================================
 
 # Basic
 map     Q quit!
@@ -222,6 +253,7 @@ map <C-r> reset
 map <C-l> redraw_window
 map <C-c> abort
 map <esc> change_mode normal
+map ~ set viewmode!
 
 map i display_file
 map ? help
@@ -235,14 +267,16 @@ map !  console shell%space
 map @  console -p6 shell  %%s
 map #  console shell -p%space
 map s  console shell%space
-map r  chain draw_possible_programs; console open_with%space
+map r  chain draw_possible_programs; console open_with%%space
 map f  console find%space
 map cd console cd%space
 
 # Change the line mode
 map Mf linemode filename
 map Mi linemode fileinfo
+map Mm linemode mtime
 map Mp linemode permissions
+map Ms linemode sizemtime
 map Mt linemode metatitle
 
 # Tagging / Marking
@@ -329,11 +363,13 @@ map =  chmod
 
 map cw console rename%space
 map a  rename_append
-map A  eval fm.open_console('rename ' + fm.thisfile.basename)
-map I  eval fm.open_console('rename ' + fm.thisfile.basename, position=7)
+map A  eval fm.open_console('rename ' + fm.thisfile.relative_path.replace("%", "%%"))
+map I  eval fm.open_console('rename ' + fm.thisfile.relative_path.replace("%", "%%"), position=7)
 
 map pp paste
 map po paste overwrite=True
+map pP paste append=True
+map pO paste overwrite=True append=True
 map pl paste_symlink relative=False
 map pL paste_symlink relative=True
 map phl paste_hardlink
@@ -345,11 +381,13 @@ map dd cut
 map ud uncut
 map da cut mode=add
 map dr cut mode=remove
+map dt cut mode=toggle
 
 map yy copy
 map uy uncut
 map ya copy mode=add
 map yr copy mode=remove
+map yt copy mode=toggle
 
 # Temporary workarounds
 map dgg eval fm.cut(dirarg=dict(to=0), narg=quantifier)
@@ -395,7 +433,7 @@ map <a-8>     tab_open 8
 map <a-9>     tab_open 9
 
 # Sorting
-map or toggle_option sort_reverse
+map or set sort_reverse!
 map oz set sort=random
 map os chain set sort=size;      set sort_reverse=False
 map ob chain set sort=basename;  set sort_reverse=False
@@ -418,17 +456,18 @@ map oE chain set sort=extension; set sort_reverse=True
 map dc get_cumulative_size
 
 # Settings
-map zc    toggle_option collapse_preview
-map zd    toggle_option sort_directories_first
-map zh    toggle_option show_hidden
-map <C-h> toggle_option show_hidden
-map zi    toggle_option flushinput
-map zm    toggle_option mouse_enabled
-map zp    toggle_option preview_files
-map zP    toggle_option preview_directories
-map zs    toggle_option sort_case_insensitive
-map zu    toggle_option autoupdate_cumulative_size
-map zv    toggle_option use_preview_script
+map zc    set collapse_preview!
+map zd    set sort_directories_first!
+map zh    set show_hidden!
+map <C-h> set show_hidden!
+map zI    set flushinput!
+map zi    set preview_images!
+map zm    set mouse_enabled!
+map zp    set preview_files!
+map zP    set preview_directories!
+map zs    set sort_case_insensitive!
+map zu    set autoupdate_cumulative_size!
+map zv    set use_preview_script!
 map zf    console filter%space
 
 # Bookmarks
@@ -453,7 +492,9 @@ eval for arg in "rwxXst": cmd("map -o{0} shell -f chmod o-{0} %s".format(arg))
 eval for arg in "rwxXst": cmd("map -a{0} shell -f chmod a-{0} %s".format(arg))
 eval for arg in "rwxXst": cmd("map -{0}  shell -f chmod u-{0} %s".format(arg))
 
-# Define keys for the console
+# ===================================================================
+# == Define keys for the console
+# ===================================================================
 # Note: Unmapped keys are passed directly to the console.
 
 # Basic
@@ -473,11 +514,14 @@ cmap <left>  eval fm.ui.console.move(left=1)
 cmap <right> eval fm.ui.console.move(right=1)
 cmap <home>  eval fm.ui.console.move(right=0, absolute=True)
 cmap <end>   eval fm.ui.console.move(right=-1, absolute=True)
+cmap <a-left>   eval fm.ui.console.move_word(left=1)
+cmap <a-right>  eval fm.ui.console.move_word(right=1)
 
 # Line Editing
 cmap <backspace>  eval fm.ui.console.delete(-1)
 cmap <delete>     eval fm.ui.console.delete(0)
 cmap <C-w>        eval fm.ui.console.delete_word()
+cmap <A-d>        eval fm.ui.console.delete_word(backward=False)
 cmap <C-k>        eval fm.ui.console.delete_rest(1)
 cmap <C-u>        eval fm.ui.console.delete_rest(-1)
 cmap <C-y>        eval fm.ui.console.paste()
@@ -499,7 +543,9 @@ copycmap <backspace> <backspace2>
 # This special expression allows typing in numerals:
 cmap <allow_quantifiers> false
 
-# Pager Keybindings
+# ===================================================================
+# == Pager Keybindings
+# ===================================================================
 
 # Movement
 pmap  <down>      pager_move  down=1
@@ -530,7 +576,9 @@ pmap     <ESC> pager_close
 copypmap <ESC> q Q i <F3>
 pmap E      edit_file
 
-# Taskview Keybindings
+# ===================================================================
+# == Taskview Keybindings
+# ===================================================================
 
 # Movement
 tmap <up>        taskview_move up=1
diff --git a/ranger/.config/ranger/rifle.conf b/ranger/.config/ranger/rifle.conf
index 33cc939..aadc2f2 100644
--- a/ranger/.config/ranger/rifle.conf
+++ b/ranger/.config/ranger/rifle.conf
@@ -57,10 +57,12 @@
 ext x?html?, has surf,           X, flag f = surf -- file://"$1"
 ext x?html?, has vimprobable,    X, flag f = vimprobable -- "$@"
 ext x?html?, has vimprobable2,   X, flag f = vimprobable2 -- "$@"
+ext x?html?, has qutebrowser,    X, flag f = qutebrowser -- "$@"
 ext x?html?, has dwb,            X, flag f = dwb -- "$@"
 ext x?html?, has jumanji,        X, flag f = jumanji -- "$@"
 ext x?html?, has luakit,         X, flag f = luakit -- "$@"
 ext x?html?, has uzbl,           X, flag f = uzbl -- "$@"
+ext x?html?, has uzbl-tabbed,    X, flag f = uzbl-tabbed -- "$@"
 ext x?html?, has uzbl-browser,   X, flag f = uzbl-browser -- "$@"
 ext x?html?, has uzbl-core,      X, flag f = uzbl-core -- "$@"
 ext x?html?, has midori,         X, flag f = midori -- "$@"
@@ -83,8 +85,8 @@ ext x?html?, has w3m,             terminal = w3m "$@"
 # Define the "editor" for text files as first action
 mime ^text,  label editor = $EDITOR -- "$@"
 mime ^text,  label pager  = "$PAGER" -- "$@"
-!mime ^text, label editor, ext xml|csv|tex|py|pl|rb|js|sh|php = $EDITOR -- "$@"
-!mime ^text, label pager,  ext xml|csv|tex|py|pl|rb|js|sh|php = "$PAGER" -- "$@"
+!mime ^text, label editor, ext xml|json|csv|tex|py|pl|rb|js|sh|php = $EDITOR -- "$@"
+!mime ^text, label pager,  ext xml|json|csv|tex|py|pl|rb|js|sh|php = "$PAGER" -- "$@"
 
 ext 1                         = man "$1"
 ext s[wmf]c, has zsnes, X     = zsnes "$1"
@@ -96,7 +98,7 @@ name ^[mM]akefile$            = make
 #--------------------------------------------
 # Code
 #-------------------------------------------
-ext py  = python3 -- "$1"
+ext py  = python -- "$1"
 ext pl  = perl -- "$1"
 ext rb  = ruby -- "$1"
 ext js  = node -- "$1"
@@ -106,9 +108,9 @@ ext php = php -- "$1"
 #--------------------------------------------
 # Audio without X
 #-------------------------------------------
-mime ^audio|ogg$, terminal, has mplayer  = mplayer -- "$@"
-mime ^audio|ogg$, terminal, has mplayer2 = mplayer2 -- "$@"
 mime ^audio|ogg$, terminal, has mpv      = mpv -- "$@"
+mime ^audio|ogg$, terminal, has mplayer2 = mplayer2 -- "$@"
+mime ^audio|ogg$, terminal, has mplayer  = mplayer -- "$@"
 ext midi?,        terminal, has wildmidi = wildmidi -- "$@"
 
 #--------------------------------------------
@@ -138,7 +140,8 @@ mime ^video, terminal, !X, has mplayer   = mplayer -- "$@"
 #-------------------------------------------
 ext pdf, has llpp,     X, flag f = llpp "$@"
 ext pdf, has zathura,  X, flag f = zathura -- "$@"
-ext pdf, has mupdf,    X, flag f = mupdf -- "$@"
+ext pdf, has mupdf,    X, flag f = mupdf "$@"
+ext pdf, has mupdf-x11,X, flag f = mupdf-x11 "$@"
 ext pdf, has apvlv,    X, flag f = apvlv -- "$@"
 ext pdf, has xpdf,     X, flag f = xpdf -- "$@"
 ext pdf, has evince,   X, flag f = evince -- "$@"
@@ -147,7 +150,7 @@ ext pdf, has okular,   X, flag f = okular -- "$@"
 ext pdf, has epdfview, X, flag f = epdfview -- "$@"
 ext pdf, has qpdfview, X, flag f = qpdfview "$@"
 
-#ext docx?, has catdoc,       terminal = catdoc -- "$@" | "$PAGER"
+ext docx?, has catdoc,       terminal = catdoc -- "$@" | "$PAGER"
 
 ext                        sxc|xlsx?|xlt|xlw|gnm|gnumeric, has gnumeric,    X, flag f = gnumeric -- "$@"
 ext                        sxc|xlsx?|xlt|xlw|gnm|gnumeric, has kspread,     X, flag f = kspread -- "$@"
@@ -155,13 +158,17 @@ ext pptx?|od[dfgpst]|docx?|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has libreoffice, X, f
 ext pptx?|od[dfgpst]|docx?|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has soffice,     X, flag f = soffice "$@"
 ext pptx?|od[dfgpst]|docx?|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has ooffice,     X, flag f = ooffice "$@"
 
+ext djvu, has zathura,X, flag f = zathura -- "$@"
 ext djvu, has evince, X, flag f = evince -- "$@"
 ext djvu, has atril,  X, flag f = atril -- "$@"
 
 #-------------------------------------------
 # Image Viewing:
 #-------------------------------------------
-mime ^image, has viewnior,  X, flag f = viewnior -- "$@"
+mime ^image/svg, has inkscape, X, flag f = inkscape -- "$@"
+mime ^image/svg, has display,  X, flag f = display -- "$@"
+
+mime ^image, has pqiv,      X, flag f = pqiv -- "$@"
 mime ^image, has sxiv,      X, flag f = sxiv -- "$@"
 mime ^image, has feh,       X, flag f = feh -- "$@"
 mime ^image, has mirage,    X, flag f = mirage -- "$@"
@@ -174,8 +181,11 @@ ext xcf,                    X, flag f = gimp -- "$@"
 #-------------------------------------------
 # Archives
 #-------------------------------------------
+
+# avoid password prompt by providing empty password
+ext 7z, has 7z = 7z -p l "$@" | "$PAGER"
 # This requires atool
-ext 7z|ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz,  has als     = als -- "$@" | "$PAGER"
+ext ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz,  has als     = als -- "$@" | "$PAGER"
 ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has als     = als -- "$@" | "$PAGER"
 ext 7z|ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz,  has aunpack = aunpack -- "$@"
 ext iso|jar|msi|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has aunpack = aunpack -- "$@"
@@ -187,12 +197,15 @@ ext tar|gz, has tar = tar vvxf "$@"
 #-------------------------------------------
 # Misc
 #-------------------------------------------
-label wallpaper, number 11, mime ^image, X = feh --bg-scale "$1"
-label wallpaper, number 12, mime ^image, X = feh --bg-tile "$1"
-label wallpaper, number 13, mime ^image, X = feh --bg-center "$1"
-label wallpaper, number 14, mime ^image, X = feh --bg-fill "$1"
+label wallpaper, number 11, mime ^image, has feh, X = feh --bg-scale "$1"
+label wallpaper, number 12, mime ^image, has feh, X = feh --bg-tile "$1"
+label wallpaper, number 13, mime ^image, has feh, X = feh --bg-center "$1"
+label wallpaper, number 14, mime ^image, has feh, X = feh --bg-fill "$1"
 
 # Define the editor for non-text files + pager as last action
-              !mime ^text, !ext xml|csv|tex|py|pl|rb|js|sh|php  = ask
-label editor, !mime ^text, !ext xml|csv|tex|py|pl|rb|js|sh|php  = $EDITOR -- "$@"
-label pager,  !mime ^text, !ext xml|csv|tex|py|pl|rb|js|sh|php  = "$PAGER" -- "$@"
+              !mime ^text, !ext xml|json|csv|tex|py|pl|rb|js|sh|php  = ask
+label editor, !mime ^text, !ext xml|json|csv|tex|py|pl|rb|js|sh|php  = $EDITOR -- "$@"
+label pager,  !mime ^text, !ext xml|json|csv|tex|py|pl|rb|js|sh|php  = "$PAGER" -- "$@"
+
+# The very last action, so that it's never triggered accidentally, is to execute a program:
+mime application/x-executable = "$1"
diff --git a/ranger/.config/ranger/scope.sh b/ranger/.config/ranger/scope.sh
index ce9ee57..a0fb2ec 100755
--- a/ranger/.config/ranger/scope.sh
+++ b/ranger/.config/ranger/scope.sh
@@ -17,18 +17,20 @@
 # 4    | fix height | success. Don't reload when height changes
 # 5    | fix both   | success. Don't ever reload
 # 6    | image      | success. display the image $cached points to as an image preview
+# 7    | image      | success. display the file directly as an image
 
 # Meaningful aliases for arguments:
-path="$1"    # Full path of the selected file
-width="$2"   # Width of the preview pane (number of fitting characters)
-height="$3"  # Height of the preview pane (number of fitting characters)
-cached="$4"  # Path that should be used to cache image previews
+path="$1"            # Full path of the selected file
+width="$2"           # Width of the preview pane (number of fitting characters)
+height="$3"          # Height of the preview pane (number of fitting characters)
+cached="$4"          # Path that should be used to cache image previews
+preview_images="$5"  # "True" if image previews are enabled, "False" otherwise.
 
 maxln=200    # Stop after $maxln lines.  Can be used like ls | head -n $maxln
 
 # Find out something about the file:
 mimetype=$(file --mime-type -Lb "$path")
-extension=$(/bin/echo -E "${path##*.}" | tr "[:upper:]" "[:lower:]")
+extension=$(/bin/echo "${path##*.}" | awk '{print tolower($0)}')
 
 # Functions:
 # runs a command and saves its output into $output.  Useful if you need
@@ -36,24 +38,45 @@ extension=$(/bin/echo -E "${path##*.}" | tr "[:upper:]" "[:lower:]")
 try() { output=$(eval '"$@"'); }
 
 # writes the output of the previously used "try" command
-dump() { /bin/echo -E "$output"; }
+dump() { /bin/echo "$output"; }
 
 # a common post-processing function used after most commands
 trim() { head -n "$maxln"; }
 
 # wraps highlight to treat exit code 141 (killed by SIGPIPE) as success
-highlight() { command highlight "$@"; test $? = 0 -o $? = 141; }
+safepipe() { "$@"; test $? = 0 -o $? = 141; }
+
+# Image previews, if enabled in ranger.
+if [ "$preview_images" = "True" ]; then
+    case "$mimetype" in
+        # Image previews for SVG files, disabled by default.
+        ###image/svg+xml)
+        ###   convert "$path" "$cached" && exit 6 || exit 1;;
+        # Image previews for image files. w3mimgdisplay will be called for all
+        # image files (unless overriden as above), but might fail for
+        # unsupported types.
+        image/*)
+            exit 7;;
+        # Image preview for video, disabled by default.:
+        ###video/*)
+        ###    ffmpegthumbnailer -i "$path" -o "$cached" -s 0 && exit 6 || exit 1;;
+    esac
+fi
 
 case "$extension" in
     # Archive extensions:
-    7z|a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\
+    a|ace|alz|arc|arj|bz|bz2|cab|cpio|deb|gz|jar|lha|lz|lzh|lzma|lzo|\
     rpm|rz|t7z|tar|tbz|tbz2|tgz|tlz|txz|tZ|tzo|war|xpi|xz|Z|zip)
         try als "$path" && { dump | trim; exit 0; }
         try acat "$path" && { dump | trim; exit 3; }
         try bsdtar -lf "$path" && { dump | trim; exit 0; }
         exit 1;;
     rar)
+        # avoid password prompt by providing empty password
         try unrar -p- lt "$path" && { dump | trim; exit 0; } || exit 1;;
+    7z)
+        # avoid password prompt by providing empty password
+        try 7z -p l "$path" && { dump | trim; exit 0; } || exit 1;;
     # PDF documents:
     pdf)
         try pdftotext -l 10 -nopgbrk -q "$path" - && \
@@ -61,6 +84,9 @@ case "$extension" in
     # BitTorrent Files
     torrent)
         try transmission-show "$path" && { dump | trim; exit 5; } || exit 1;;
+    # ODT Files
+    odt|ods|odp|sxw)
+        try odt2txt "$path" && { dump | trim; exit 5; } || exit 1;;
     # HTML Pages:
     htm|html|xhtml)
         try w3m    -dump "$path" && { dump | trim | fmt -s -w $width; exit 4; }
@@ -72,13 +98,19 @@ esac
 case "$mimetype" in
     # Syntax highlight for text files:
     text/* | */xml)
-        try highlight --out-format=ansi "$path" && { dump | trim; exit 5; } || exit 2;;
+        if [ "$(tput colors)" -ge 256 ]; then
+            pygmentize_format=terminal256
+            highlight_format=xterm256
+        else
+            pygmentize_format=terminal
+            highlight_format=ansi
+        fi
+        try safepipe highlight --out-format=${highlight_format} "$path" && { dump | trim; exit 5; }
+        try safepipe pygmentize -f ${pygmentize_format} "$path" && { dump | trim; exit 5; }
+        exit 2;;
     # Ascii-previews of images:
     image/*)
         img2txt --gamma=0.6 --width="$width" "$path" && exit 4 || exit 1;;
-    # Image preview for videos, disabled by default:
-    # video/*)
-    #     ffmpegthumbnailer -i "$path" -o "$cached" -s 0 && exit 6 || exit 1;;
     # Display information about media files:
     video/* | audio/*)
         exiftool "$path" && exit 5