summary refs log tree commit diff stats
path: root/ranger
diff options
context:
space:
mode:
authorrage311 <rage311@users.noreply.github.com>2017-06-27 13:15:37 -0600
committerGitHub <noreply@github.com>2017-06-27 13:15:37 -0600
commit747bb88e9ccf4b47b2dccbe9dc0ebcbceeeff03a (patch)
tree6696f067172c606ac363f614679c558d445483cb /ranger
parentb5f5ffe69d0ae3668c34ffa14f907e98977d5e35 (diff)
parent086074db6f08af058ffdced7319287715a88d42a (diff)
downloadranger-747bb88e9ccf4b47b2dccbe9dc0ebcbceeeff03a.tar.gz
Merge branch 'master' into master
Diffstat (limited to 'ranger')
-rwxr-xr-xranger/config/commands.py90
-rw-r--r--ranger/config/rc.conf11
-rw-r--r--ranger/container/directory.py32
-rw-r--r--ranger/container/settings.py1
-rw-r--r--ranger/core/main.py6
-rw-r--r--ranger/core/runner.py4
-rw-r--r--ranger/gui/widgets/statusbar.py6
-rw-r--r--ranger/gui/widgets/view_base.py1
8 files changed, 130 insertions, 21 deletions
diff --git a/ranger/config/commands.py b/ranger/config/commands.py
index 4cedc4e1..be0bbe3e 100755
--- a/ranger/config/commands.py
+++ b/ranger/config/commands.py
@@ -1469,6 +1469,22 @@ class scout(Command):
         return count == 1
 
 
+class narrow(Command):
+    """
+    :narrow
+
+    Show only the files selected right now. If no files are selected,
+    disable narrowing.
+    """
+    def execute(self):
+        if self.fm.thisdir.marked_items:
+            selection = [f.basename for f in self.fm.thistab.get_selection()]
+            self.fm.thisdir.narrow_filter = selection
+        else:
+            self.fm.thisdir.narrow_filter = None
+        self.fm.thisdir.refilter()
+
+
 class filter_inode_type(Command):
     """
     :filter_inode_type [dfl]
@@ -1480,22 +1496,12 @@ class filter_inode_type(Command):
         f display files
         l display links
     """
-    # pylint: disable=bad-whitespace
-    FILTER_DIRS  = 'd'
-    FILTER_FILES = 'f'
-    FILTER_LINKS = 'l'
-    # pylint: enable=bad-whitespace
 
     def execute(self):
         if not self.arg(1):
-            self.fm.thisdir.inode_type_filter = None
+            self.fm.thisdir.inode_type_filter = ""
         else:
-            self.fm.thisdir.inode_type_filter = lambda file: (
-                True if (
-                    (self.FILTER_DIRS in self.arg(1) and file.is_directory) or
-                    (self.FILTER_FILES in self.arg(1) and file.is_file and not file.is_link) or
-                    (self.FILTER_LINKS in self.arg(1) and file.is_link)
-                ) else False)
+            self.fm.thisdir.inode_type_filter = self.arg(1)
         self.fm.thisdir.refilter()
 
 
@@ -1670,3 +1676,63 @@ class linemode(default_linemode):
         # Ask the browsercolumns to redraw
         for col in self.fm.ui.browser.columns:
             col.need_redraw = True
+
+
+class yank(Command):
+    """:yank [name|dir|path]
+
+    Copies the file's name (default), directory or path into both the primary X
+    selection and the clipboard.
+    """
+
+    modes = {
+        '': 'basename',
+        'name': 'basename',
+        'dir': 'dirname',
+        'path': 'path',
+    }
+
+    def execute(self):
+        import subprocess
+
+        def clipboards():
+            from ranger.ext.get_executables import get_executables
+            clipboard_managers = {
+                'xclip': [
+                    ['xclip'],
+                    ['xclip', '-selection', 'clipboard'],
+                ],
+                'xsel': [
+                    ['xsel'],
+                    ['xsel', '-b'],
+                ],
+                'pbcopy': [
+                    ['pbcopy'],
+                ],
+            }
+            ordered_managers = ['pbcopy', 'xclip', 'xsel']
+            executables = get_executables()
+            for manager in ordered_managers:
+                if manager in executables:
+                    return clipboard_managers[manager]
+            return []
+
+        clipboard_commands = clipboards()
+
+        selection = self.get_selection_attr(self.modes[self.arg(1)])
+        new_clipboard_contents = "\n".join(selection)
+        for command in clipboard_commands:
+            process = subprocess.Popen(command, universal_newlines=True,
+                                       stdin=subprocess.PIPE)
+            process.communicate(input=new_clipboard_contents)
+
+    def get_selection_attr(self, attr):
+        return [getattr(item, attr) for item in
+                self.fm.thistab.get_selection()]
+
+    def tab(self, tabnum):
+        return (
+            self.start(1) + mode for mode
+            in sorted(self.modes.keys())
+            if mode
+        )
diff --git a/ranger/config/rc.conf b/ranger/config/rc.conf
index 9af5a953..e088b660 100644
--- a/ranger/config/rc.conf
+++ b/ranger/config/rc.conf
@@ -228,6 +228,10 @@ set save_tabs_on_exit false
 # the top and vice versa.
 set wrap_scroll false
 
+# Set the global_inode_type_filter to nothing.  Possible options: d, f and l for
+# directories, files and symlinks respectively.
+set global_inode_type_filter
+
 # ===================================================================
 # == Local Options
 # ===================================================================
@@ -375,10 +379,9 @@ map g? cd /usr/share/doc/ranger
 map E  edit
 map du shell -p du --max-depth=1 -h --apparent-size
 map dU shell -p du --max-depth=1 -h --apparent-size | sort -rh
-map yp shell -f echo -n %d/%f     | xsel -i && xsel -o | xsel -i -b
-map yd shell -f echo -n %d        | xsel -i && xsel -o | xsel -i -b
-map yn shell -f echo -n %f        | xsel -i && xsel -o | xsel -i -b
-map ys shell -f printf '%%s\n' %s | xsel -i && xsel -o | xsel -i -b
+map yp yank path
+map yd yank dir
+map yn yank name
 
 # Filesystem Operations
 map =  chmod
diff --git a/ranger/container/directory.py b/ranger/container/directory.py
index 168a46c7..fbbf4d22 100644
--- a/ranger/container/directory.py
+++ b/ranger/container/directory.py
@@ -93,6 +93,12 @@ def mtimelevel(path, level):
     return mtime
 
 
+class InodeFilterConstants(object):  # pylint: disable=too-few-public-methods
+    DIRS = 'd'
+    FILES = 'f'
+    LINKS = 'l'
+
+
 class Directory(  # pylint: disable=too-many-instance-attributes,too-many-public-methods
         FileSystemObject, Accumulator, Loadable):
     is_directory = True
@@ -108,6 +114,7 @@ class Directory(  # pylint: disable=too-many-instance-attributes,too-many-public
     files_all = None
     filter = None
     temporary_filter = None
+    narrow_filter = None
     inode_type_filter = None
     marked_items = None
     scroll_begin = 0
@@ -252,11 +259,32 @@ class Directory(  # pylint: disable=too-many-instance-attributes,too-many-public
                         return False
                 return True
             filters.append(hidden_filter_func)
+        if self.narrow_filter:
+            # pylint: disable=unsupported-membership-test
+
+            # Pylint complains that self.narrow_filter is by default
+            # None but the execution won't reach this line if it is
+            # still None.
+            filters.append(lambda fobj: fobj.basename in self.narrow_filter)
+        if self.settings.global_inode_type_filter or self.inode_type_filter:
+            def inode_filter_func(obj):
+                # Use local inode_type_filter if present, global otherwise
+                inode_filter = self.inode_type_filter or self.settings.global_inode_type_filter
+                # Apply filter
+                if InodeFilterConstants.DIRS in inode_filter and \
+                        obj.is_directory:
+                    return True
+                elif InodeFilterConstants.FILES in inode_filter and \
+                        obj.is_file and not obj.is_link:
+                    return True
+                elif InodeFilterConstants.LINKS in inode_filter and \
+                        obj.is_link:
+                    return True
+                return False
+            filters.append(inode_filter_func)
         if self.filter:
             filter_search = self.filter.search
             filters.append(lambda fobj: filter_search(fobj.basename))
-        if self.inode_type_filter:
-            filters.append(self.inode_type_filter)
         if self.temporary_filter:
             temporary_filter_search = self.temporary_filter.search
             filters.append(lambda fobj: temporary_filter_search(fobj.basename))
diff --git a/ranger/container/settings.py b/ranger/container/settings.py
index 70e299c7..00563772 100644
--- a/ranger/container/settings.py
+++ b/ranger/container/settings.py
@@ -41,6 +41,7 @@ ALLOWED_SETTINGS = {
     'draw_borders': bool,
     'draw_progress_bar_in_status_bar': bool,
     'flushinput': bool,
+    'global_inode_type_filter': str,
     'hidden_filter': str,
     'idle_delay': int,
     'line_numbers': str,
diff --git a/ranger/core/main.py b/ranger/core/main.py
index 9a0fe59f..3f4f068a 100644
--- a/ranger/core/main.py
+++ b/ranger/core/main.py
@@ -119,6 +119,10 @@ def main(
         FileManagerAware.fm_set(fm)
         load_settings(fm, args.clean)
 
+        if args.show_only_dirs:
+            from ranger.container.directory import InodeFilterConstants
+            fm.settings.global_inode_type_filter = InodeFilterConstants.DIRS
+
         if args.list_unused_keys:
             from ranger.ext.keybinding_parser import (special_keys,
                                                       reversed_special_keys)
@@ -274,6 +278,8 @@ def parse_arguments():
     parser.add_option('--choosedir', type='string', metavar='PATH',
                       help="Makes ranger act like a directory chooser. When ranger quits"
                       ", it will write the name of the last visited directory to PATH")
+    parser.add_option('--show-only-dirs', action='store_true',
+                      help="Show only directories, no files or links")
     parser.add_option('--selectfile', type='string', metavar='filepath',
                       help="Open ranger with supplied file selected.")
     parser.add_option('--list-unused-keys', action='store_true',
diff --git a/ranger/core/runner.py b/ranger/core/runner.py
index 8c3e3162..bb4e512a 100644
--- a/ranger/core/runner.py
+++ b/ranger/core/runner.py
@@ -27,7 +27,7 @@ from __future__ import (absolute_import, division, print_function)
 import logging
 import os
 import sys
-from subprocess import Popen, PIPE
+from subprocess import Popen, PIPE, STDOUT
 from ranger.ext.get_executables import get_executables, get_term
 from ranger.ext.popen_forked import Popen_forked
 
@@ -185,7 +185,7 @@ class Runner(object):  # pylint: disable=too-few-public-methods
 
         if 'p' in context.flags:
             popen_kws['stdout'] = PIPE
-            popen_kws['stderr'] = PIPE
+            popen_kws['stderr'] = STDOUT
             toggle_ui = False
             pipe_output = True
             context.wait = False
diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py
index eb2250ae..980945dc 100644
--- a/ranger/gui/widgets/statusbar.py
+++ b/ranger/gui/widgets/statusbar.py
@@ -234,7 +234,7 @@ class StatusBar(Widget):  # pylint: disable=too-many-instance-attributes
             except KeyError:
                 return str(gid)
 
-    def _get_right_part(self, bar):  # pylint: disable=too-many-branches
+    def _get_right_part(self, bar):  # pylint: disable=too-many-branches,too-many-statements
         right = bar.right
         if self.column is None:
             return
@@ -256,6 +256,10 @@ class StatusBar(Widget):  # pylint: disable=too-many-instance-attributes
             right.add(str(self.fm.thisdir.flat), base, 'flat')
             right.add(", ", "space")
 
+        if self.fm.thisdir.narrow_filter:
+            right.add("narrowed")
+            right.add(", ", "space")
+
         if self.fm.thisdir.filter:
             right.add("f=`", base, 'filter')
             right.add(self.fm.thisdir.filter.pattern, base, 'filter')
diff --git a/ranger/gui/widgets/view_base.py b/ranger/gui/widgets/view_base.py
index 5cdb2615..cb205d92 100644
--- a/ranger/gui/widgets/view_base.py
+++ b/ranger/gui/widgets/view_base.py
@@ -109,6 +109,7 @@ class ViewBase(Widget, DisplayableContainer):  # pylint: disable=too-many-instan
 
     def _draw_hints(self):
         self.columns[-1].clear_image(force=True)
+        self.color_reset()
         self.need_clear = True
         hints = []
         for key, value in self.fm.ui.keybuffer.pointer.items():