From 1c2a52c0ca265dcd1ef22b0b9f52c3f1bc8e9d80 Mon Sep 17 00:00:00 2001 From: Milan Svoboda Date: Sat, 1 Nov 2014 12:50:42 +0100 Subject: implement flat command --- ranger/config/commands.py | 21 +++++++++++++++++++++ ranger/container/directory.py | 41 ++++++++++++++++++++++++++++++++--------- ranger/container/fsobject.py | 14 ++++++++++---- ranger/core/fm.py | 10 +++++++--- 4 files changed, 70 insertions(+), 16 deletions(-) diff --git a/ranger/config/commands.py b/ranger/config/commands.py index 51bff937..2c5babba 100644 --- a/ranger/config/commands.py +++ b/ranger/config/commands.py @@ -1261,3 +1261,24 @@ class log(Command): pager = os.environ.get('PAGER', ranger.DEFAULT_PAGER) self.fm.run([pager, tmp.name]) + +class flat(Command): + """ + :flat + + Flattens the directory view up to level specified. + -1 fully flattened + 0 remove flattened view + """ + + def execute(self): + try: + level = self.rest(1) + level = int(level) + except ValueError: + self.fm.notify("Need an integer number (-1, 0, 1, ...)", bad=True) + return + self.fm.thisdir.unload() + self.fm.thisdir.flat = level + self.fm.thisdir.load_content() + diff --git a/ranger/container/directory.py b/ranger/container/directory.py index de69c467..c6987a76 100644 --- a/ranger/container/directory.py +++ b/ranger/container/directory.py @@ -52,6 +52,7 @@ class Directory(FileSystemObject, Accumulator, Loadable): cycle_list = None loading = False progressbar_supported = True + flat = 0 filenames = None files = None @@ -182,7 +183,7 @@ class Directory(FileSystemObject, Accumulator, Loadable): self.move_to_obj(self.pointed_obj) # XXX: Check for possible race conditions - def load_bit_by_bit(self): + def load_bit_by_bit(self, flat=0): """An iterator that loads a part on every next() call Returns a generator which load a part of the directory @@ -193,6 +194,18 @@ class Directory(FileSystemObject, Accumulator, Loadable): self.percent = 0 self.load_if_outdated() + basename_is_rel = True if flat else False + + def walklevel(some_dir, level): + some_dir = some_dir.rstrip(os.path.sep) + assert os.path.isdir(some_dir) + num_sep = some_dir.count(os.path.sep) + for root, dirs, files in os.walk(some_dir): + yield root, dirs, files + num_sep_this = root.count(os.path.sep) + if level != -1 and num_sep + level <= num_sep_this: + del dirs[:] + try: if self.runnable: yield @@ -200,7 +213,17 @@ class Directory(FileSystemObject, Accumulator, Loadable): self.mount_path = mount_path(mypath) - filelist = os.listdir(mypath) + if flat: + filelist = [] + for dirpath, dirnames, filenames in walklevel(mypath, flat): + filelist += [os.path.join("/", dirpath, d) for d in dirnames + if dirpath.count(os.path.sep) - mypath.count(os.path.sep) == flat] + filelist += [os.path.join("/", dirpath, f) for f in filenames] + filenames = [os.path.relpath(name, mypath) for name in filelist] + else: + filelist = os.listdir(mypath) + filenames = [mypath + (mypath == '/' and fname or '/' + fname) + for fname in filelist] if self._cumulative_size_calculated: # If self.content_loaded is true, this is not the first @@ -220,8 +243,6 @@ class Directory(FileSystemObject, Accumulator, Loadable): if self.is_link: self.infostring = '->' + self.infostring - filenames = [mypath + (mypath == '/' and fname or '/' + fname) - for fname in filelist] yield self.load_content_mtime = os.stat(mypath).st_mtime @@ -249,14 +270,16 @@ class Directory(FileSystemObject, Accumulator, Loadable): is_a_dir = False if is_a_dir: try: - item = self.fm.get_directory(name) + item = self.fm.get_directory(name, + basename_is_rel=basename_is_rel) item.load_if_outdated() except: - item = Directory(name, preload=stats, - path_is_abs=True) + item = Directory(name, preload=stats, path_is_abs=True, + basename_is_rel=basename_is_rel) item.load() else: - item = File(name, preload=stats, path_is_abs=True) + item = File(name, preload=stats, path_is_abs=True, + basename_is_rel=basename_is_rel) item.load() disk_usage += item.size @@ -327,7 +350,7 @@ class Directory(FileSystemObject, Accumulator, Loadable): schedule = True # was: self.size > 30 if self.load_generator is None: - self.load_generator = self.load_bit_by_bit() + self.load_generator = self.load_bit_by_bit(flat=self.flat) if schedule and self.fm: self.fm.loader.add(self) diff --git a/ranger/container/fsobject.py b/ranger/container/fsobject.py index 86730fae..5acf9f5f 100644 --- a/ranger/container/fsobject.py +++ b/ranger/container/fsobject.py @@ -13,8 +13,8 @@ DOCUMENT_BASENAMES = ('bugs', 'bugs', 'changelog', 'copying', 'credits', BAD_INFO = '?' import re -from os import lstat, stat -from os.path import abspath, basename, dirname, realpath, splitext, extsep +from os import lstat, stat, getcwd +from os.path import abspath, basename, dirname, realpath, splitext, extsep, relpath from ranger.core.shared import FileManagerAware, SettingsAware from ranger.ext.shell_escape import shell_escape from ranger.ext.spawn import spawn @@ -78,11 +78,17 @@ class FileSystemObject(FileManagerAware, SettingsAware): vcs_outdated = False vcs_enabled = False - def __init__(self, path, preload=None, path_is_abs=False): + basename_is_rel = False + + def __init__(self, path, preload=None, path_is_abs=False, basename_is_rel=False): if not path_is_abs: path = abspath(path) self.path = path - self.basename = basename(path) + self.basename_is_rel = basename_is_rel + if not basename_is_rel: + self.basename = basename(path) + else: + self.basename = relpath(path, getcwd()) self.basename_lower = self.basename.lower() self.extension = splitext(self.basename)[1].lstrip(extsep) or None self.dirname = dirname(path) diff --git a/ranger/core/fm.py b/ranger/core/fm.py index 2a9ce315..d567bf24 100644 --- a/ranger/core/fm.py +++ b/ranger/core/fm.py @@ -252,13 +252,17 @@ class FM(Actions, SignalDispatcher): """returns the path relative to rangers library directory""" return os.path.join(ranger.RANGERDIR, *paths) - def get_directory(self, path): + def get_directory(self, path, basename_is_rel = False): """Get the directory object at the given path""" path = os.path.abspath(path) try: - return self.directories[path] + directory = self.directories[path] + if directory.basename_is_rel != basename_is_rel: + del self.directories[path] + raise KeyError + return directory except KeyError: - obj = Directory(path) + obj = Directory(path, basename_is_rel = basename_is_rel) self.directories[path] = obj return obj -- cgit 1.4.1-2-gfad0