diff options
author | 5hir0kur0 <12101162+5hir0kur0@users.noreply.github.com> | 2020-03-06 16:09:11 +0100 |
---|---|---|
committer | 5hir0kur0 <12101162+5hir0kur0@users.noreply.github.com> | 2020-03-06 16:25:33 +0100 |
commit | efa32996173ee50cb2dbf4eb3d0cc2af998d6f3a (patch) | |
tree | 9e3bb98991041fa1f3043b514fe32b02aeee01af /ranger | |
parent | f65e6f08bcf63b7d915d2a2e98d1f6f891cd30de (diff) | |
download | ranger-efa32996173ee50cb2dbf4eb3d0cc2af998d6f3a.tar.gz |
trash: Don't call the File() constructor
Previously the File() constructor was called for every path (if the paths to be moved to trash were supplied after the command instead of deleting the selection, e.g. ":trash a b c"). This commit adds a method paths_to_filesystem_objects() to find the existing objects that ranger has in memory and use those instead.
Diffstat (limited to 'ranger')
-rwxr-xr-x | ranger/config/commands.py | 42 |
1 files changed, 40 insertions, 2 deletions
diff --git a/ranger/config/commands.py b/ranger/config/commands.py index a2d13542..ecbb2fe1 100755 --- a/ranger/config/commands.py +++ b/ranger/config/commands.py @@ -722,14 +722,15 @@ class trash(Command): def execute(self): import shlex from functools import partial - from ranger.container.file import File def is_directory_with_files(path): return os.path.isdir(path) and not os.path.islink(path) and len(os.listdir(path)) > 0 if self.rest(1): file_names = shlex.split(self.rest(1)) - files = [File(name) for name in file_names] + files = self.paths_to_filesystem_objects(file_names) + if files is None: + return many_files = (len(files) > 1 or is_directory_with_files(files[0].path)) else: cwd = self.fm.thisdir @@ -754,6 +755,43 @@ class trash(Command): # no need for a confirmation, just delete self.fm.execute_file(files, label='trash') + @staticmethod + def group_paths_by_dirname(paths): + """ + Groups the paths into a dictionary with their dirnames as keys and a set of + basenames as entries. + """ + groups = dict() + for path in paths: + abspath = os.path.abspath(os.path.expanduser(path)) + dirname, basename = os.path.split(abspath) + groups.setdefault(dirname, set()).add(basename) + return groups + + def paths_to_filesystem_objects(self, paths): + """ + Find FileSystemObjects corresponding to the paths if they are already in + memory and load those that are not. + """ + result = [] + # Grouping the files by dirname avoids the potentially quadratic running time of doing + # a linear search in the directory for each entry name that is supposed to be deleted. + groups = trash.group_paths_by_dirname(paths) + for dirname, basenames in groups.items(): + directory = self.fm.get_directory(dirname) + directory.load_content_if_outdated() + for entry in directory.files_all: + if entry.basename in basenames: + result.append(entry) + basenames.remove(entry.basename) + if basenames != set(): + # Abort the operation with an error message if there are entries + # that weren't found. + names = ', '.join(basenames) + self.fm.notify('Error: No such file or directory: {}'.format(names), bad=True) + return None + return result + def tab(self, tabnum): return self._tab_directory_content() |