about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authornfnty <git@nfnty.se>2017-02-05 08:56:06 +0100
committernfnty <git@nfnty.se>2017-02-05 08:58:57 +0100
commit3fe5f92984e1361d06170e3b6a420ec93a041aaa (patch)
tree940c855b3a8685e497627a8004af051276cb4cb3
parent2841f7b86b1d464eb5280a9c9e5c29c4f4fda249 (diff)
downloadranger-3fe5f92984e1361d06170e3b6a420ec93a041aaa.tar.gz
Add setting `wrap_scroll`: Visual mode
-rw-r--r--ranger/core/actions.py61
-rw-r--r--ranger/core/fm.py4
-rw-r--r--ranger/ext/direction.py7
3 files changed, 45 insertions, 27 deletions
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index d3bbce7c..597b3279 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -82,14 +82,14 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
         if mode == self.mode:  # pylint: disable=access-member-before-definition
             return
         if mode == 'visual':
-            self._visual_start = self.thisdir.pointed_obj
-            self._visual_start_pos = self.thisdir.pointer
+            self._visual_pos_start = self.thisdir.pointer
+            self._visual_move_cycles = 0
             self._previous_selection = set(self.thisdir.marked_items)
             self.mark_files(val=not self._visual_reverse, movedown=False)
         elif mode == 'normal':
             if self.mode == 'visual':  # pylint: disable=access-member-before-definition
-                self._visual_start = None
-                self._visual_start_pos = None
+                self._visual_pos_start = None
+                self._visual_move_cycles = None
                 self._previous_selection = None
         else:
             return
@@ -439,7 +439,8 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
     # -- Moving Around
     # --------------------------
 
-    def move(self, narg=None, **kw):  # pylint: disable=too-many-locals,too-many-branches
+    def move(self,  # pylint: disable=too-many-locals,too-many-branches,too-many-statements
+             narg=None, **kw):
         """A universal movement method.
 
         Accepts these parameters:
@@ -479,37 +480,49 @@ class Actions(  # pylint: disable=too-many-instance-attributes,too-many-public-m
                 if result in (False, ASK_COMMAND):
                     self.open_console('open_with ')
         elif direction.vertical() and cwd.files:
-            newpos = direction.move(
+            pos_new = direction.move(
                 direction=direction.down(),
                 override=narg,
                 maximum=len(cwd),
                 current=cwd.pointer,
                 pagesize=self.ui.browser.hei)
-            cwd.move(to=newpos)
+            cwd.move(to=pos_new)
             if self.mode == 'visual':
-                try:
-                    startpos = cwd.files.index(self._visual_start)
-                except ValueError:
-                    self._visual_start = None
-                    startpos = min(self._visual_start_pos, len(cwd))
-                # The files between here and _visual_start_pos
-                targets = set(cwd.files[min(startpos, newpos):(max(startpos, newpos) + 1)])
-                # The selection before activating visual mode
-                old = self._previous_selection
+                pos_start = min(self._visual_pos_start, (len(cwd.files) - 1))
+                self._visual_move_cycles += direction.move_cycles()
+
+                # Haven't cycled
+                if self._visual_move_cycles == 0:
+                    targets = set(cwd.files[min(pos_start, pos_new):(max(pos_start, pos_new) + 1)])
+                # Cycled down once
+                elif self._visual_move_cycles == 1:
+                    if pos_new >= pos_start:
+                        targets = set(cwd.files)
+                    else:
+                        targets = set(cwd.files[:(pos_new + 1)] + cwd.files[pos_start:])
+                # Cycled up once
+                elif self._visual_move_cycles == -1:
+                    if pos_new <= pos_start:
+                        targets = set(cwd.files)
+                    else:
+                        targets = set(cwd.files[:(pos_start + 1)] + cwd.files[pos_new:])
+                # Cycled more than once
+                else:
+                    targets = set(cwd.files)
+
                 # The current selection
                 current = set(cwd.marked_items)
-
                 # Set theory anyone?
-                if not self._visual_reverse:
-                    for fobj in targets - current:
-                        cwd.mark_item(fobj, True)
-                    for fobj in current - old - targets:
-                        cwd.mark_item(fobj, False)
-                else:
+                if self._visual_reverse:
                     for fobj in targets & current:
                         cwd.mark_item(fobj, False)
-                    for fobj in old - current - targets:
+                    for fobj in self._previous_selection - current - targets:
                         cwd.mark_item(fobj, True)
+                else:
+                    for fobj in targets - current:
+                        cwd.mark_item(fobj, True)
+                    for fobj in current - self._previous_selection - targets:
+                        cwd.mark_item(fobj, False)
             if self.ui.pager.visible:
                 self.display_file()
 
diff --git a/ranger/core/fm.py b/ranger/core/fm.py
index 9e703327..a879ffad 100644
--- a/ranger/core/fm.py
+++ b/ranger/core/fm.py
@@ -41,8 +41,8 @@ class FM(Actions,  # pylint: disable=too-many-instance-attributes
 
     _previous_selection = None
     _visual_reverse = False
-    _visual_start = None
-    _visual_start_pos = None
+    _visual_pos_start = None
+    _visual_move_cycles = None
 
     def __init__(self, ui=None, bookmarks=None, tags=None, paths=None):
         """Initialize FM."""
diff --git a/ranger/ext/direction.py b/ranger/ext/direction.py
index 2bc58395..bbb69c9b 100644
--- a/ranger/ext/direction.py
+++ b/ranger/ext/direction.py
@@ -140,9 +140,14 @@ class Direction(dict):
         else:
             pos += current
         if self.cycle():
-            return minimum + pos % (maximum + offset - minimum)
+            cycles, pos = divmod(pos, (maximum + offset - minimum))
+            self['_move_cycles'] = int(cycles)
+            return int(minimum + pos)
         return int(max(min(pos, maximum + offset - 1), minimum))
 
+    def move_cycles(self):
+        return self.get('_move_cycles', 0)
+
     def select(self, lst, current, pagesize, override=None, offset=1):
         dest = self.move(direction=self.down(), override=override,
                          current=current, pagesize=pagesize, minimum=0, maximum=len(lst) + 1)