diff options
author | hut <hut@lavabit.com> | 2011-10-31 20:33:40 +0100 |
---|---|---|
committer | hut <hut@lavabit.com> | 2011-10-31 20:33:40 +0100 |
commit | 83c8d324492263c9aadc3098e1ebccc8d2dd1d91 (patch) | |
tree | be3f8bde171b3712f53468ca2ddb3004d1ea83a5 | |
parent | 975be325388b00cca3c0aa2bb0a70ef0a57d2f93 (diff) | |
download | ranger-83c8d324492263c9aadc3098e1ebccc8d2dd1d91.tar.gz |
core.actions: implement visual mode
-rw-r--r-- | ranger/core/actions.py | 77 | ||||
-rw-r--r-- | ranger/defaults/rc.conf | 4 | ||||
-rw-r--r-- | ranger/gui/widgets/statusbar.py | 5 |
3 files changed, 76 insertions, 10 deletions
diff --git a/ranger/core/actions.py b/ranger/core/actions.py index 00fd2179..77f064f2 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -42,6 +42,11 @@ class _MacroTemplate(string.Template): class Actions(FileManagerAware, EnvironmentAware, SettingsAware): search_method = 'ctime' + mode = 'normal' # either 'normal' or 'visual'. + _visual_reverse = False + _visual_start = None + _visual_start_pos = None + _previous_selection = None # -------------------------- # -- Basic Commands @@ -57,6 +62,32 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): self.previews = {} self.env.garbage_collect(-1, self.tabs) self.enter_dir(old_path) + self.change_mode('normal') + + def change_mode(self, mode): + if mode == self.mode: + return + if mode == 'visual': + self._visual_start = self.env.cwd.pointed_obj + self._visual_start_pos = self.env.cwd.pointer + self._previous_selection = set(self.env.cwd.marked_items) + self.mark_files(val=not self._visual_reverse, movedown=False) + elif mode == 'normal': + if self.mode == 'visual': + self._visual_start = None + self._visual_start_pos = None + self._previous_selection = None + else: + return + self.mode = mode + self.ui.status.request_redraw() + + def toggle_visual_mode(self, reverse=False): + if self.mode == 'normal': + self._visual_reverse = reverse + self.change_mode('visual') + else: + self.change_mode('normal') def reload_cwd(self): try: @@ -312,6 +343,7 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): except: return self.env.enter_dir(directory) + self.change_mode('normal') if cwd and cwd.accessible and cwd.content_loaded: if 'right' in direction: mode = 0 @@ -330,8 +362,34 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): current=cwd.pointer, pagesize=self.ui.browser.hei) cwd.move(to=newpos) + if self.mode == 'visual': + try: + startpos = cwd.index(self._visual_start) + except: + 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 + # The current selection + current = set(cwd.marked_items) + + # Set theory anyone? + if not self._visual_reverse: + for f in targets - current: + cwd.mark_item(f, True) + for f in current - old - targets: + cwd.mark_item(f, False) + else: + for f in targets & current: + cwd.mark_item(f, False) + for f in old - current - targets: + cwd.mark_item(f, True) def move_parent(self, n, narg=None): + self.change_mode('normal') if narg is not None: n *= narg parent = self.env.at_level(-1) @@ -360,18 +418,20 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): def enter_dir(self, path, remember=False, history=True): """Enter the directory at the given path""" - if remember: - cwd = self.env.cwd - result = self.env.enter_dir(path, history=history) - self.bookmarks.remember(cwd) - return result - return self.env.enter_dir(path, history=history) + cwd = self.env.cwd + result = self.env.enter_dir(path, history=history) + if cwd != self.env.cwd: + if remember: + self.bookmarks.remember(cwd) + self.change_mode('normal') + return result def cd(self, path, remember=True): """enter the directory at the given path, remember=True""" self.enter_dir(path, remember=remember) def traverse(self): + self.change_mode('normal') cf = self.env.cf cwd = self.env.cwd if cf is not None and cf.is_directory: @@ -768,13 +828,14 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware): # directory paths only. def tab_open(self, name, path=None): - do_emit_signal = name != self.current_tab + tab_has_changed = name != self.current_tab self.current_tab = name if path or (name in self.tabs): self.enter_dir(path or self.tabs[name]) else: self._update_current_tab() - if do_emit_signal: + if tab_has_changed: + self.change_mode('normal') self.signal_emit('tab.change') def tab_close(self, name=None): diff --git a/ranger/defaults/rc.conf b/ranger/defaults/rc.conf index b8106663..1ecbc398 100644 --- a/ranger/defaults/rc.conf +++ b/ranger/defaults/rc.conf @@ -39,6 +39,7 @@ map R reload_cwd map <C-r> reset map <C-l> redraw_window map <C-c> abort +map <esc> change_mode normal map i display_file map ? help @@ -62,8 +63,9 @@ map T tag_remove map "<any> tag_toggle tag=%any map <Space> mark_files toggle=True map v mark_files all=True toggle=True -map V mark_files all=True val=False map uv mark_files all=True val=False +map V toggle_visual_mode +map uV toggle_visual_mode reverse=True # For the nostalgics: Midnight Commander bindings map <F1> help diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py index b7a238da..a7d3fc73 100644 --- a/ranger/gui/widgets/statusbar.py +++ b/ranger/gui/widgets/statusbar.py @@ -159,7 +159,10 @@ class StatusBar(Widget): if stat is None: return - perms = target.get_permission_string() + if self.fm.mode != 'normal': + perms = '--%s--' % self.fm.mode.upper() + else: + perms = target.get_permission_string() how = getuid() == stat.st_uid and 'good' or 'bad' left.add(perms, 'permissions', how) left.add_space() |