summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorWojciech Siewierski <wojciech.siewierski@onet.pl>2018-03-05 18:21:33 +0100
committerGitHub <noreply@github.com>2018-03-05 18:21:33 +0100
commit87620eea4dab4f76df3ed2fa01a05673412ef206 (patch)
treed0e1e3cb49b565d8be86d3d92e0f154fa0d83b8c
parentfb3c1a21231b7f4dc0a1190332c55a73dba2bab9 (diff)
parent72ea7926b30e0842ac213aab23d9f94df1cdbb50 (diff)
downloadranger-87620eea4dab4f76df3ed2fa01a05673412ef206.tar.gz
Merge pull request #1103 from Vifon/full-hints
Show the full keybindings in the key hints
-rw-r--r--doc/ranger.16
-rw-r--r--doc/ranger.pod5
-rw-r--r--ranger/config/rc.conf4
-rw-r--r--ranger/container/settings.py1
-rw-r--r--ranger/gui/widgets/view_base.py66
5 files changed, 71 insertions, 11 deletions
diff --git a/doc/ranger.1 b/doc/ranger.1
index fca30604..ded6a5d6 100644
--- a/doc/ranger.1
+++ b/doc/ranger.1
@@ -129,7 +129,7 @@
 .\" ========================================================================
 .\"
 .IX Title "RANGER 1"
-.TH RANGER 1 "ranger-1.9.1" "02/22/2018" "ranger manual"
+.TH RANGER 1 "ranger-1.9.1" "03/04/2018" "ranger manual"
 .\" For nroff, turn off justification.  Always turn off hyphenation; it makes
 .\" way too many mistakes in technical documents.
 .if n .ad l
@@ -800,6 +800,10 @@ this pattern will hide all files that start with a dot or end with a tilde.
 .Vb 1
 \& set hidden_filter ^\e.|~$
 .Ve
+.IP "hint_collapse_threshold [int]" 4
+.IX Item "hint_collapse_threshold [int]"
+The key hint lists up to this size have their sublists expanded.
+Otherwise the submaps are replaced with \*(L"...\*(R".
 .IP "idle_delay [integer]" 4
 .IX Item "idle_delay [integer]"
 The delay that ranger idly waits for user input, in milliseconds, with a
diff --git a/doc/ranger.pod b/doc/ranger.pod
index 523d8d9d..71a9342d 100644
--- a/doc/ranger.pod
+++ b/doc/ranger.pod
@@ -791,6 +791,11 @@ this pattern will hide all files that start with a dot or end with a tilde.
 
  set hidden_filter ^\.|~$
 
+=item hint_collapse_threshold [int]
+
+The key hint lists up to this size have their sublists expanded.
+Otherwise the submaps are replaced with "...".
+
 =item idle_delay [integer]
 
 The delay that ranger idly waits for user input, in milliseconds, with a
diff --git a/ranger/config/rc.conf b/ranger/config/rc.conf
index 676090fb..fe00c7c0 100644
--- a/ranger/config/rc.conf
+++ b/ranger/config/rc.conf
@@ -216,6 +216,10 @@ set cd_tab_fuzzy false
 # disable this feature.
 set preview_max_size 0
 
+# The key hint lists up to this size have their sublists expanded.
+# Otherwise the submaps are replaced with "...".
+set hint_collapse_threshold 10
+
 # Add the highlighted file to the path in the titlebar
 set show_selection_in_titlebar true
 
diff --git a/ranger/container/settings.py b/ranger/container/settings.py
index d0b094d0..9f54f24d 100644
--- a/ranger/container/settings.py
+++ b/ranger/container/settings.py
@@ -45,6 +45,7 @@ ALLOWED_SETTINGS = {
     'freeze_files': bool,
     'global_inode_type_filter': str,
     'hidden_filter': str,
+    'hint_collapse_threshold': int,
     'hostname_in_titlebar': bool,
     'idle_delay': int,
     'iterm2_font_width': int,
diff --git a/ranger/gui/widgets/view_base.py b/ranger/gui/widgets/view_base.py
index cb205d92..80061004 100644
--- a/ranger/gui/widgets/view_base.py
+++ b/ranger/gui/widgets/view_base.py
@@ -112,16 +112,62 @@ class ViewBase(Widget, DisplayableContainer):  # pylint: disable=too-many-instan
         self.color_reset()
         self.need_clear = True
         hints = []
-        for key, value in self.fm.ui.keybuffer.pointer.items():
-            key = key_to_string(key)
-            if isinstance(value, dict):
-                text = '...'
-            else:
-                text = value
-            if text.startswith('hint') or text.startswith('chain hint'):
-                continue
-            hints.append((key, text))
-        hints.sort(key=lambda t: t[1])
+
+        def populate_hints(keymap, prefix=""):
+            for key, value in keymap.items():
+                key = prefix + key_to_string(key)
+                if isinstance(value, dict):
+                    populate_hints(value, key)
+                else:
+                    text = value
+                    if text.startswith('hint') or text.startswith('chain hint'):
+                        continue
+                    hints.append((key, text))
+        populate_hints(self.fm.ui.keybuffer.pointer)
+
+        def sort_hints(hints):
+            """Sort the hints by the action string but first group them by the
+            first key.
+
+            """
+            from itertools import groupby
+
+            # groupby needs the list to be sorted.
+            hints.sort(key=lambda t: t[0])
+
+            def group_hints(hints):
+                def first_key(hint):
+                    return hint[0][0]
+
+                def action_string(hint):
+                    return hint[1]
+
+                return (sorted(group, key=action_string)
+                        for _, group
+                        in groupby(
+                            hints,
+                            key=first_key))
+
+            grouped_hints = group_hints(hints)
+
+            # If there are too many hints, collapse the sublists.
+            if len(hints) > self.fm.settings.hint_collapse_threshold:
+                def first_key_in_group(group):
+                    return group[0][0][0]
+                grouped_hints = (
+                    [(first_key_in_group(hint_group), "...")]
+                    if len(hint_group) > 1
+                    else hint_group
+                    for hint_group in grouped_hints
+                )
+
+            # Sort by the first action in group.
+            grouped_hints = sorted(grouped_hints, key=lambda g: g[0][1])
+
+            def flatten(nested_list):
+                return [item for inner_list in nested_list for item in inner_list]
+            return flatten(grouped_hints)
+        hints = sort_hints(hints)
 
         hei = min(self.hei - 1, len(hints))
         ystart = self.hei - hei