about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--Makefile4
-rw-r--r--doc/howto-publish-a-release.md2
-rw-r--r--doc/ranger.112
-rw-r--r--doc/ranger.pod8
-rwxr-xr-xranger/config/commands.py10
-rw-r--r--ranger/config/rc.conf4
-rw-r--r--ranger/config/rifle.conf4
-rw-r--r--ranger/core/actions.py26
-rw-r--r--ranger/core/filter_stack.py16
-rw-r--r--ranger/core/main.py2
-rw-r--r--ranger/core/tab.py8
-rw-r--r--ranger/ext/img_display.py18
-rw-r--r--ranger/gui/ui.py95
-rwxr-xr-xsetup.py16
14 files changed, 123 insertions, 102 deletions
diff --git a/Makefile b/Makefile
index d70728f6..82a6153a 100644
--- a/Makefile
+++ b/Makefile
@@ -8,9 +8,9 @@ VERSION_RIFLE = $(VERSION)
 SNAPSHOT_NAME ?= $(NAME)-$(VERSION)-$(shell git rev-parse HEAD | cut -b 1-8).tar.gz
 # Find suitable python version (need python >= 2.6 or 3.1):
 PYTHON ?= $(shell \
-	     (python -c 'import sys; sys.exit(sys.version < "2.6")' && \
+	     (which python3) \
+	     || (python -c 'import sys; sys.exit(sys.version < "2.6")' && \
 	      which python) \
-	     || (which python3) \
 	     || (python2 -c 'import sys; sys.exit(sys.version < "2.6")' && \
 	         which python2) \
 	   )
diff --git a/doc/howto-publish-a-release.md b/doc/howto-publish-a-release.md
index 6bd70047..c62a1908 100644
--- a/doc/howto-publish-a-release.md
+++ b/doc/howto-publish-a-release.md
@@ -62,7 +62,7 @@ Update the website
 Make a PyPI release
 -------------------
 * [ ] `git clean --force -d -x`
-* [ ] `SETUPTOOLS_USE=1 python setup.py sdist`
+* [ ] `python setup.py sdist`
 * [ ] `gpg --local-user 0x00000000 --detach-sign --armor dist/*`
 * [ ] `twine upload dist/*`
 
diff --git a/doc/ranger.1 b/doc/ranger.1
index 57646fc7..50d6bb0f 100644
--- a/doc/ranger.1
+++ b/doc/ranger.1
@@ -133,7 +133,7 @@
 .\" ========================================================================
 .\"
 .IX Title "RANGER 1"
-.TH RANGER 1 "ranger-1.9.3" "2019-12-31" "ranger manual"
+.TH RANGER 1 "ranger-1.9.3" "2020-02-22" "ranger manual"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -1731,9 +1731,9 @@ Creates an empty file with the name \fIfilename\fR, unless it already exists.
 .IX Item "trash"
 Move all files in the selection to the trash using rifle. Rifle tries to use a
 trash manager like \fItrash-cli\fR if available but will fall back to moving files
-to either \fI\f(CI$XDG_DATA_HOME\fI/ranger\-trash\fR or \fI~/.ranger/ranger\-trash\fR. This is
-a less permanent version of \fIdelete\fR, relying on the user to clear out the
-trash whenever it's convenient. While having the possibility of restoring
+to either \fI\f(CI$XDG_DATA_HOME\fI/ranger/trash\fR or \fI~/.local/share/ranger/trash\fR.
+This is a less permanent version of \fIdelete\fR, relying on the user to clear out
+the trash whenever it's convenient. While having the possibility of restoring
 trashed files until this happens. ranger will ask for a confirmation if you
 attempt to trash multiple (marked) files or non-empty directories. This can be
 changed by modifying the setting \*(L"confirm_on_delete\*(R".
@@ -1869,8 +1869,8 @@ the \*(L"S\*(R" key.  Defaults to \*(L"/bin/sh\*(R".
 .IX Item "TERMCMD"
 Defines the terminal emulator command that ranger is going to use with the
 :terminal command and the \*(L"t\*(R" run flag.  Defaults to \*(L"xterm\*(R".
-.IP "\s-1BAT_STYLE\s0" 8
-.IX Item "BAT_STYLE"
+.IP "\s-1BAT_THEME\s0" 8
+.IX Item "BAT_THEME"
 Specifies the theme to be used for syntax highlighting when \fIbat\fR is
 installed, unless \fIhighlight\fR is also installed. Find out possible values by
 running \f(CW\*(C`bat \-\-list\-themes\*(C'\fR.
diff --git a/doc/ranger.pod b/doc/ranger.pod
index ed347665..3f41467d 100644
--- a/doc/ranger.pod
+++ b/doc/ranger.pod
@@ -1879,9 +1879,9 @@ Creates an empty file with the name I<filename>, unless it already exists.
 
 Move all files in the selection to the trash using rifle. Rifle tries to use a
 trash manager like I<trash-cli> if available but will fall back to moving files
-to either F<$XDG_DATA_HOME/ranger-trash> or F<~/.ranger/ranger-trash>. This is
-a less permanent version of I<delete>, relying on the user to clear out the
-trash whenever it's convenient. While having the possibility of restoring
+to either F<$XDG_DATA_HOME/ranger/trash> or F<~/.local/share/ranger/trash>.
+This is a less permanent version of I<delete>, relying on the user to clear out
+the trash whenever it's convenient. While having the possibility of restoring
 trashed files until this happens. ranger will ask for a confirmation if you
 attempt to trash multiple (marked) files or non-empty directories. This can be
 changed by modifying the setting "confirm_on_delete".
@@ -2057,7 +2057,7 @@ the "S" key.  Defaults to "/bin/sh".
 Defines the terminal emulator command that ranger is going to use with the
 :terminal command and the "t" run flag.  Defaults to "xterm".
 
-=item BAT_STYLE
+=item BAT_THEME
 
 Specifies the theme to be used for syntax highlighting when I<bat> is
 installed, unless I<highlight> is also installed. Find out possible values by
diff --git a/ranger/config/commands.py b/ranger/config/commands.py
index 5defa677..7e244e6f 100755
--- a/ranger/config/commands.py
+++ b/ranger/config/commands.py
@@ -1124,6 +1124,12 @@ class bulkrename(Command):
     After you close it, it will be executed.
     """
 
+    def __init__(self, *args, **kwargs):
+        super(bulkrename, self).__init__(*args, **kwargs)
+        self.flags, _ = self.parse_flags()
+        if not self.flags:
+            self.flags = "w"
+
     def execute(self):
         # pylint: disable=too-many-locals,too-many-statements,too-many-branches
         import sys
@@ -1184,7 +1190,7 @@ class bulkrename(Command):
             script_was_edited = (script_content != cmdfile.read())
 
             # Do the renaming
-            self.fm.run(['/bin/sh', cmdfile.name], flags='w')
+            self.fm.run(['/bin/sh', cmdfile.name], flags=self.flags)
 
         # Retag the files, but only if the script wasn't changed during review,
         # because only then we know which are the source and destination files.
@@ -1704,7 +1710,7 @@ class filter_stack(Command):
             return
         else:
             self.fm.notify(
-                "Unknown subcommand: {}".format(subcommand),
+                "Unknown subcommand: {sub}".format(sub=subcommand),
                 bad=True
             )
             return
diff --git a/ranger/config/rc.conf b/ranger/config/rc.conf
index 9d08a6a7..e1ed1b73 100644
--- a/ranger/config/rc.conf
+++ b/ranger/config/rc.conf
@@ -25,7 +25,6 @@
 #     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,3,4
@@ -334,6 +333,7 @@ alias qall! quitall!
 alias setl  setlocal
 
 alias filter     scout -prts
+alias hide       scout -prtsv
 alias find       scout -aets
 alias mark       scout -mr
 alias unmark     scout -Mr
@@ -620,7 +620,7 @@ map m<any>  set_bookmark %any
 map um<any> unset_bookmark %any
 
 map m<bg>   draw_bookmarks
-copymap m<bg>  um<bg> `<bg> '<bg>
+copymap m<bg>  um<bg> `<bg> '<bg> p`<bg> p'<bg>
 
 # Generate all the chmod bindings with some python help:
 eval for arg in "rwxXst": cmd("map +u{0} shell -f chmod u+{0} %s".format(arg))
diff --git a/ranger/config/rifle.conf b/ranger/config/rifle.conf
index 80e4bdbc..6364e097 100644
--- a/ranger/config/rifle.conf
+++ b/ranger/config/rifle.conf
@@ -262,7 +262,7 @@ label wallpaper, number 14, mime ^image, has feh, X = feh --bg-fill "$1"
 #-------------------------------------------
 # Generic file openers
 #-------------------------------------------
-label open, has xdg-open = xdg-open -- "$@"
+label open, has xdg-open = xdg-open "$@"
 label open, has open     = open -- "$@"
 
 # Define the editor for non-text files + pager as last action
@@ -281,4 +281,4 @@ mime application/x-executable = "$1"
 
 # Move the file to trash using trash-cli.
 label trash, has trash-put = trash-put -- "$@"
-label trash = mkdir -p -- ${XDG_DATA_DIR:-$HOME/.ranger}/ranger-trash; mv -- "$@" ${XDG_DATA_DIR:-$HOME/.ranger}/ranger-trash
+label trash = mkdir -p -- "${XDG_DATA_HOME:-$HOME/.local/share}/ranger/trash"; mv -- "$@" "${XDG_DATA_HOME:-$HOME/.local/share}/ranger/trash"
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index c3d7de86..fe7d7e5e 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -16,8 +16,7 @@ import string
 import tempfile
 from inspect import cleandoc
 from stat import S_IEXEC
-from hashlib import sha1
-from sys import version_info
+from hashlib import sha512
 from logging import getLogger
 
 import ranger
@@ -35,7 +34,6 @@ from ranger.container.file import File
 from ranger.core.loader import CommandLoader, CopyLoader
 from ranger.container.settings import ALLOWED_SETTINGS, ALLOWED_VALUES
 
-
 MACRO_FAIL = "<\x01\x01MACRO_HAS_NO_VALUE\x01\01>"
 
 LOG = getLogger(__name__)
@@ -242,14 +240,14 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
 
         if cmd.resolve_macros and _MacroTemplate.delimiter in cmd.line:
             def any_macro(i, char):
-                return ('any{:d}'.format(i), key_to_string(char))
+                return ('any{0:d}'.format(i), key_to_string(char))
 
             def anypath_macro(i, char):
                 try:
                     val = self.fm.bookmarks[key_to_string(char)]
                 except KeyError:
                     val = MACRO_FAIL
-                return ('any_path{:d}'.format(i), val)
+                return ('any_path{0:d}'.format(i), val)
 
             macros = dict(f(i, char) for f in (any_macro, anypath_macro)
                           for i, char in enumerate(wildcards if wildcards
@@ -1049,11 +1047,12 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
         return True
 
     @staticmethod
-    def sha1_encode(path):
-        if version_info[0] < 3:
-            return os.path.join(ranger.args.cachedir, sha1(path).hexdigest()) + '.jpg'
-        return os.path.join(ranger.args.cachedir,
-                            sha1(path.encode('utf-8', 'backslashreplace')).hexdigest()) + '.jpg'
+    def sha512_encode(path):
+        stat_ = stat(path)
+        sha = sha512(stat_.st_dev)
+        sha.update(stat_.st_ino)
+        sha.update(stat_.st_mtime)
+        return '{0}.jpg'.format(sha.hexdigest())
 
     def get_preview(self, fobj, width, height):  # pylint: disable=too-many-return-statements
         pager = self.ui.get_pager()
@@ -1121,10 +1120,9 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
 
         if not os.path.exists(ranger.args.cachedir):
             os.makedirs(ranger.args.cachedir)
-        cacheimg = os.path.join(ranger.args.cachedir, self.sha1_encode(path))
+        cacheimg = os.path.join(ranger.args.cachedir, self.sha512_encode(path))
         if self.settings.preview_images and \
-                os.path.isfile(cacheimg) and \
-                os.path.getmtime(cacheimg) > os.path.getmtime(path):
+                os.path.isfile(cacheimg):
             data['foundpreview'] = True
             data['imagepreview'] = True
             pager.set_image(cacheimg)
@@ -1609,7 +1607,7 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
         # COMPAT: old command.py use fm.delete() without arguments
         if files is None:
             files = (fobj.path for fobj in self.thistab.get_selection())
-        self.notify("Deleting {}!".format(", ".join(files)))
+        self.notify("Deleting {fls}!".format(fls=", ".join(files)))
         files = [os.path.abspath(path) for path in files]
         for path in files:
             # Untag the deleted files.
diff --git a/ranger/core/filter_stack.py b/ranger/core/filter_stack.py
index bd63f2fe..58ce1a1c 100644
--- a/ranger/core/filter_stack.py
+++ b/ranger/core/filter_stack.py
@@ -55,7 +55,7 @@ class NameFilter(BaseFilter):
         return self.regex.search(fobj.relative_path)
 
     def __str__(self):
-        return "<Filter: name =~ /{}/>".format(self.pattern)
+        return "<Filter: name =~ /{pat}/>".format(pat=self.pattern)
 
 
 @stack_filter("mime")
@@ -71,7 +71,7 @@ class MimeFilter(BaseFilter):
         return self.regex.search(mimetype)
 
     def __str__(self):
-        return "<Filter: mimetype =~ /{}/>".format(self.pattern)
+        return "<Filter: mimetype =~ /{pat}/>".format(pat=self.pattern)
 
 
 @stack_filter("hash")
@@ -97,7 +97,7 @@ class HashFilter(BaseFilter, FileManagerAware):
         return True
 
     def __str__(self):
-        return "<Filter: hash {}>".format(self.filepath)
+        return "<Filter: hash {fp}>".format(fp=self.filepath)
 
 
 def group_by_hash(fsobjects):
@@ -192,7 +192,7 @@ class TypeFilter(BaseFilter):
         return self.type_to_function[self.filetype](fobj)
 
     def __str__(self):
-        return "<Filter: type == '{}'>".format(self.filetype)
+        return "<Filter: type == '{ft}'>".format(ft=self.filetype)
 
 
 @filter_combinator("or")
@@ -216,7 +216,8 @@ class OrFilter(BaseFilter):
         )
 
     def __str__(self):
-        return "<Filter: {}>".format(" or ".join(map(str, self.subfilters)))
+        return "<Filter: {comp}>".format(
+            comp=" or ".join(map(str, self.subfilters)))
 
     def decompose(self):
         return self.subfilters
@@ -236,7 +237,8 @@ class AndFilter(BaseFilter):
         return accept_file(fobj, self.subfilters)
 
     def __str__(self):
-        return "<Filter: {}>".format(" and ".join(map(str, self.subfilters)))
+        return "<Filter: {comp}>".format(
+            comp=" and ".join(map(str, self.subfilters)))
 
     def decompose(self):
         return self.subfilters
@@ -252,7 +254,7 @@ class NotFilter(BaseFilter):
         return not self.subfilter(fobj)
 
     def __str__(self):
-        return "<Filter: not {}>".format(str(self.subfilter))
+        return "<Filter: not {exp}>".format(exp=str(self.subfilter))
 
     def decompose(self):
         return [self.subfilter]
diff --git a/ranger/core/main.py b/ranger/core/main.py
index 5f7abaca..b16b6318 100644
--- a/ranger/core/main.py
+++ b/ranger/core/main.py
@@ -347,7 +347,7 @@ def parse_arguments():
             except Exception as ex:  # pylint: disable=broad-except
                 sys.stderr.write(
                     "Error during the temporary cache directory cleanup:\n"
-                    "{}\n".format(ex)
+                    "{ex}\n".format(ex=ex)
                 )
 
     else:
diff --git a/ranger/core/tab.py b/ranger/core/tab.py
index 1d5e69d4..7bb45d75 100644
--- a/ranger/core/tab.py
+++ b/ranger/core/tab.py
@@ -4,7 +4,7 @@
 from __future__ import (absolute_import, division, print_function)
 
 import os
-from os.path import abspath, normpath, join, expanduser, isdir
+from os.path import abspath, normpath, join, expanduser, isdir, dirname
 import sys
 
 from ranger.container import settings
@@ -123,9 +123,11 @@ class Tab(FileManagerAware, SettingsAware):  # pylint: disable=too-many-instance
 
         # get the absolute path
         path = normpath(join(self.path, expanduser(path)))
+        selectfile = None
 
         if not isdir(path):
-            return False
+            selectfile = path
+            path = dirname(path)
         new_thisdir = self.fm.get_directory(path)
 
         try:
@@ -155,6 +157,8 @@ class Tab(FileManagerAware, SettingsAware):  # pylint: disable=too-many-instance
         self.thisdir.sort_directories_first = self.fm.settings.sort_directories_first
         self.thisdir.sort_reverse = self.fm.settings.sort_reverse
         self.thisdir.sort_if_outdated()
+        if selectfile:
+            self.thisdir.move_to_obj(selectfile)
         if previous and previous.path != path:
             self.thisfile = self.thisdir.pointed_obj
         else:
diff --git a/ranger/ext/img_display.py b/ranger/ext/img_display.py
index ffaa4c07..70983bc7 100644
--- a/ranger/ext/img_display.py
+++ b/ranger/ext/img_display.py
@@ -233,7 +233,7 @@ class W3MImageDisplayer(ImageDisplayer, FileManagerAware):
         # max_height_pixels = (max_height - 1) * fonth - 2
 
         # get image size
-        cmd = "5;{}\n".format(path)
+        cmd = "5;{path}\n".format(path=path)
 
         self.process.stdin.write(cmd)
         self.process.stdin.flush()
@@ -590,7 +590,7 @@ class KittyImageDisplayer(ImageDisplayer, FileManagerAware):
             self.stream = True
         else:
             raise ImgDisplayUnsupportedException(
-                'kitty replied an unexpected response: {}'.format(resp))
+                'kitty replied an unexpected response: {r}'.format(r=resp))
 
         # get the image manipulation backend
         try:
@@ -616,7 +616,8 @@ class KittyImageDisplayer(ImageDisplayer, FileManagerAware):
         # a is the display command, with T going for immediate output
         # i is the id entifier for the image
         cmds = {'a': 'T', 'i': self.image_id}
-        # sys.stderr.write('{}-{}@{}x{}\t'.format(start_x, start_y, width, height))
+        # sys.stderr.write('{0}-{1}@{2}x{3}\t'.format(
+        #     start_x, start_y, width, height))
 
         # finish initialization if it is the first call
         if self.needs_late_init:
@@ -673,12 +674,13 @@ class KittyImageDisplayer(ImageDisplayer, FileManagerAware):
         if b'OK' in resp:
             return
         else:
-            raise ImageDisplayError('kitty replied "{}"'.format(resp))
+            raise ImageDisplayError('kitty replied "{r}"'.format(r=resp))
 
     def clear(self, start_x, start_y, width, height):
         # let's assume that every time ranger call this
         # it actually wants just to remove the previous image
-        # TODO: implement this using the actual x, y, since the protocol supports it
+        # TODO: implement this using the actual x, y, since the protocol
+        #       supports it
         cmds = {'a': 'd', 'i': self.image_id}
         for cmd_str in self._format_cmd_str(cmds):
             self.stdbout.write(cmd_str)
@@ -690,7 +692,8 @@ class KittyImageDisplayer(ImageDisplayer, FileManagerAware):
         self.fm.ui.win.refresh()
 
     def _format_cmd_str(self, cmd, payload=None, max_slice_len=2048):
-        central_blk = ','.join(["{}={}".format(k, v) for k, v in cmd.items()]).encode('ascii')
+        central_blk = ','.join(["{k}={v}".format(k=k, v=v)
+                                for k, v in cmd.items()]).encode('ascii')
         if payload is not None:
             # we add the m key to signal a multiframe communication
             # appending the end (m=0) key to a single message has no effect
@@ -706,7 +709,8 @@ class KittyImageDisplayer(ImageDisplayer, FileManagerAware):
             yield self.protocol_start + central_blk + b';' + self.protocol_end
 
     def quit(self):
-        # clear all remaining images, then check if all files went through or are orphaned
+        # clear all remaining images, then check if all files went through or
+        # are orphaned
         while self.image_id >= 1:
             self.clear(0, 0, 0, 0)
         # for k in self.temp_paths:
diff --git a/ranger/gui/ui.py b/ranger/gui/ui.py
index d2dbb759..a2ea7778 100644
--- a/ranger/gui/ui.py
+++ b/ranger/gui/ui.py
@@ -9,6 +9,7 @@ import threading
 import curses
 from subprocess import CalledProcessError
 
+from ranger.ext.get_executables import get_executables
 from ranger.ext.keybinding_parser import KeyBuffer, KeyMaps, ALT_KEY
 from ranger.ext.lazy_property import lazy_property
 from ranger.ext.signals import Signal
@@ -49,6 +50,16 @@ def _setup_mouse(signal):
         curses.mousemask(0)
 
 
+def _in_tmux():
+    return ('TMUX' in os.environ
+            and 'tmux' in get_executables())
+
+
+def _in_screen():
+    return ('screen' in os.environ['TERM']
+            and 'screen' in get_executables())
+
+
 class UI(  # pylint: disable=too-many-instance-attributes,too-many-public-methods
         DisplayableContainer):
     ALLOWED_VIEWMODES = 'miller', 'multipane'
@@ -73,8 +84,7 @@ class UI(  # pylint: disable=too-many-instance-attributes,too-many-public-method
         self.multiplexer = None
         self._draw_title = None
         self._tmux_automatic_rename = None
-        self._tmux_title = None
-        self._screen_title = None
+        self._multiplexer_title = None
         self.browser = None
 
         if fm is not None:
@@ -469,58 +479,63 @@ class UI(  # pylint: disable=too-many-instance-attributes,too-many-public-method
     # Handles window renaming behaviour of the terminal multiplexers
     # GNU Screen and Tmux
     def handle_multiplexer(self):
-        if self.settings.update_tmux_title:
-            if 'TMUX' in os.environ:
-                # Stores the automatic-rename setting
-                # prints out a warning if the allow-rename in tmux is not set
-                tmux_allow_rename = check_output(
-                    ['tmux', 'show-window-options', '-v',
-                     'allow-rename']).strip()
-                if tmux_allow_rename == 'off':
-                    self.fm.notify('Warning: allow-rename not set in Tmux!',
-                                   bad=True)
-                elif self._tmux_title is None:
-                    self._tmux_title = check_output(
-                        ['tmux', 'display-message', '-p', '#W']).strip()
-                else:
+        if (self.settings.update_tmux_title and not self._multiplexer_title):
+            try:
+                if _in_tmux():
+                    # Stores the automatic-rename setting
+                    # prints out a warning if allow-rename isn't set in tmux
                     try:
+                        tmux_allow_rename = check_output(
+                            ['tmux', 'show-window-options', '-v',
+                             'allow-rename']).strip()
+                    except CalledProcessError:
+                        tmux_allow_rename = 'off'
+                    if tmux_allow_rename == 'off':
+                        self.fm.notify('Warning: allow-rename not set in Tmux!',
+                                       bad=True)
+                    else:
+                        self._multiplexer_title = check_output(
+                            ['tmux', 'display-message', '-p', '#W']).strip()
                         self._tmux_automatic_rename = check_output(
                             ['tmux', 'show-window-options', '-v',
                              'automatic-rename']).strip()
                         if self._tmux_automatic_rename == 'on':
                             check_output(['tmux', 'set-window-option',
                                           'automatic-rename', 'off'])
-                    except CalledProcessError:
-                        pass
-            elif 'screen' in os.environ['TERM'] and self._screen_title is None:
-                # Stores the screen window name before renaming it
-                # gives out a warning if $TERM is not "screen"
-                try:
-                    self._screen_title = check_output(
+                elif _in_screen():
+                    # Stores the screen window name before renaming it
+                    # gives out a warning if $TERM is not "screen"
+                    self._multiplexer_title = check_output(
                         ['screen', '-Q', 'title']).strip()
-                except CalledProcessError:
-                    self._screen_title = None
+            except CalledProcessError:
+                self.fm.notify("Couldn't access previous multiplexer window"
+                               " name, won't be able to restore.",
+                               bad=False)
+            if not self._multiplexer_title:
+                self._multiplexer_title = os.path.basename(
+                    os.environ.get("SHELL", "shell"))
 
             sys.stdout.write("\033kranger\033\\")
             sys.stdout.flush()
 
     # Restore window name
     def restore_multiplexer_name(self):
-        try:
-            if 'TMUX' in os.environ:
-                if self._tmux_automatic_rename:
-                    check_output(['tmux', 'set-window-option',
-                                  'automatic-rename',
-                                  self._tmux_automatic_rename])
-                else:
-                    check_output(['tmux', 'set-window-option', '-u',
-                                  'automatic-rename'])
-                if self._tmux_title:
-                    check_output(['tmux', 'rename-window', self._tmux_title])
-            elif 'screen' in os.environ['TERM'] and self._screen_title:
-                check_output(['screen', '-X', 'title', self._screen_title])
-        except CalledProcessError:
-            self.fm.notify("Could not restore window-name!", bad=True)
+        if self._multiplexer_title:
+            try:
+                if _in_tmux():
+                    if self._tmux_automatic_rename:
+                        check_output(['tmux', 'set-window-option',
+                                      'automatic-rename',
+                                      self._tmux_automatic_rename])
+                    else:
+                        check_output(['tmux', 'set-window-option', '-u',
+                                      'automatic-rename'])
+            except CalledProcessError:
+                self.fm.notify("Could not restore multiplexer window name!",
+                               bad=True)
+
+            sys.stdout.write("\033k{}\033\\".format(self._multiplexer_title))
+            sys.stdout.flush()
 
     def hint(self, text=None):
         self.status.hint = text
diff --git a/setup.py b/setup.py
index edf48c4a..493deadd 100755
--- a/setup.py
+++ b/setup.py
@@ -4,11 +4,13 @@
 
 from __future__ import (absolute_import, division, print_function)
 
-from distutils import log  # pylint: disable=import-error,no-name-in-module
 from hashlib import sha512
 import os
 import shutil
 
+from setuptools import setup
+from setuptools.command.install_lib import install_lib
+
 import ranger
 
 
@@ -16,16 +18,6 @@ SCRIPTS_PATH = 'build_scripts'
 EXECUTABLES_PATHS = ['/ranger/data/scope.sh']
 
 
-# pylint: disable=import-error,no-name-in-module,ungrouped-imports
-if os.environ.get('SETUPTOOLS_USE'):
-    from setuptools import setup
-    from setuptools.command.install_lib import install_lib
-else:
-    from distutils.core import setup
-    from distutils.command.install_lib import install_lib
-# pylint: enable=import-error,no-name-in-module,ungrouped-imports
-
-
 def findall(directory):
     return [os.path.join(directory, f) for f in os.listdir(directory)
             if os.path.isfile(os.path.join(directory, f))]
@@ -59,7 +51,7 @@ class InstallLib(install_lib):
             for exe_path in EXECUTABLES_PATHS:
                 if path.endswith(exe_path):
                     mode = ((os.stat(path).st_mode) | 0o555) & 0o7777
-                    log.info('changing mode of %s to %o', path, mode)
+                    print('changing mode of %s to %o' % (path, mode))
                     os.chmod(path, mode)