summary refs log tree commit diff stats
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
parentb5f5ffe69d0ae3668c34ffa14f907e98977d5e35 (diff)
parent086074db6f08af058ffdced7319287715a88d42a (diff)
downloadranger-747bb88e9ccf4b47b2dccbe9dc0ebcbceeeff03a.tar.gz
Merge branch 'master' into master
-rw-r--r--doc/ranger.17
-rw-r--r--doc/ranger.pod6
-rw-r--r--examples/rc_emacs.conf1
-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
11 files changed, 143 insertions, 22 deletions
diff --git a/doc/ranger.1 b/doc/ranger.1
index 940ffc0a..045d8b95 100644
--- a/doc/ranger.1
+++ b/doc/ranger.1
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "RANGER 1"
-.TH RANGER 1 "ranger-1.9.0b5" "2017-03-23" "ranger manual"
+.TH RANGER 1 "ranger-1.9.0b5" "2017-06-16" "ranger manual"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -143,6 +143,7 @@ ranger \- visual file manager
 [\fB\-\-copy\-config\fR=\fIwhich\fR]
 [\fB\-\-choosefile\fR=\fItarget\fR] [\fB\-\-choosefiles\fR=\fItarget\fR]
 [\fB\-\-choosedir\fR=\fItarget\fR] [\fB\-\-selectfile\fR=\fIfilepath\fR]
+[\fB\-\-show\-only\-dirs\fR]
 [\fB\-\-list\-unused\-keys\fR] [\fB\-\-list\-tagged\-files\fR=\fItag\fR]
 [\fB\-\-profile\fR] [\fB\-\-cmd\fR=\fIcommand\fR] [\fIpath\fR]
 .SH "DESCRIPTION"
@@ -225,6 +226,10 @@ write the last visited directory into \fItargetfile\fR.
 .IP "\fB\-\-selectfile\fR=\fItargetfile\fR" 14
 .IX Item "--selectfile=targetfile"
 Open ranger with \fItargetfile\fR selected.
+.IP "\fB\-\-show\-only\-dirs\fR" 14
+.IX Item "--show-only-dirs"
+Display only the directories. May be used in conjunction with
+\&\fB\-\-choosedir\fR=\fItargetfile\fR.
 .IP "\fB\-\-list\-unused\-keys\fR" 14
 .IX Item "--list-unused-keys"
 List common keys which are not bound to any action in the \*(L"browser\*(R" context.
diff --git a/doc/ranger.pod b/doc/ranger.pod
index ebeeafbe..d9dd6b3d 100644
--- a/doc/ranger.pod
+++ b/doc/ranger.pod
@@ -12,6 +12,7 @@ B<ranger> [B<--version>] [B<--help>] [B<--debug>] [B<--clean>]
 [B<--copy-config>=I<which>]
 [B<--choosefile>=I<target>] [B<--choosefiles>=I<target>]
 [B<--choosedir>=I<target>] [B<--selectfile>=I<filepath>]
+[B<--show-only-dirs>]
 [B<--list-unused-keys>] [B<--list-tagged-files>=I<tag>]
 [B<--profile>] [B<--cmd>=I<command>] [I<path>]
 
@@ -118,6 +119,11 @@ write the last visited directory into I<targetfile>.
 
 Open ranger with I<targetfile> selected.
 
+=item B<--show-only-dirs>
+
+Display only the directories. May be used in conjunction with
+B<--choosedir>=I<targetfile>.
+
 =item B<--list-unused-keys>
 
 List common keys which are not bound to any action in the "browser" context.
diff --git a/examples/rc_emacs.conf b/examples/rc_emacs.conf
index d3707a12..26074a42 100644
--- a/examples/rc_emacs.conf
+++ b/examples/rc_emacs.conf
@@ -406,6 +406,7 @@ map <C-x>zs    toggle_option sort_case_insensitive
 map <C-x>zu    toggle_option autoupdate_cumulative_size
 map <C-x>zv    toggle_option use_preview_script
 map <C-x>zf    console filter%space
+map <C-x>nn    narrow
 
 # Bookmarks
 map <C-x>rb<any> enter_bookmark %any
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():