diff options
-rw-r--r-- | doc/ranger.pod | 7 | ||||
-rw-r--r-- | ranger/config/commands.py | 7 | ||||
-rw-r--r-- | ranger/container/directory.py | 74 | ||||
-rw-r--r-- | ranger/container/fsobject.py | 16 | ||||
-rw-r--r-- | ranger/core/fm.py | 10 | ||||
-rw-r--r-- | ranger/gui/widgets/browsercolumn.py | 4 | ||||
-rw-r--r-- | ranger/gui/widgets/titlebar.py | 2 |
7 files changed, 72 insertions, 48 deletions
diff --git a/doc/ranger.pod b/doc/ranger.pod index 7a6de447..c556c63c 100644 --- a/doc/ranger.pod +++ b/doc/ranger.pod @@ -831,6 +831,7 @@ ranger. For your convenience, this is a list of the "public" commands including eval [-q] python_code filter [string] find pattern + flat level grep pattern linemode linemodename load_copy_buffer @@ -997,6 +998,12 @@ be run immediately. (Or entered, if it's a directory.) This command is based on the I<scout> command and supports all of its options. +=item flat level + +Flattens the directory view up to the specified level. Level -1 means infinite +level. Level 0 means standard view without flattened directory view. Level +values -2 and less are invalid. + =item grep I<pattern> Looks for a string in all marked files or directories. diff --git a/ranger/config/commands.py b/ranger/config/commands.py index 49d8f213..4e82fb0f 100644 --- a/ranger/config/commands.py +++ b/ranger/config/commands.py @@ -1303,9 +1303,10 @@ class flat(Command): """ :flat <level> - Flattens the directory view up to level specified. + Flattens the directory view up to the specified level. + -1 fully flattened - 0 remove flattened view + 0 remove flattened view """ def execute(self): @@ -1314,6 +1315,8 @@ class flat(Command): level = int(level) except ValueError: level = self.quantifier + if level < -1: + self.fm.notify("Need an integer number (-1, 0, 1, ...)", bad=True) 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 c331053a..7bef379d 100644 --- a/ranger/container/directory.py +++ b/ranger/container/directory.py @@ -20,7 +20,7 @@ from ranger.container.settings import LocalSettings def sort_by_basename(path): """returns path.basename (for sorting)""" - return path.basename + return path.drawn_basename def sort_by_basename_icase(path): """returns case-insensitive path.basename (for sorting)""" @@ -45,6 +45,25 @@ def accept_file(fname, directory, hidden_filter, name_filter): return False return True +def walklevel(some_dir, level): + some_dir = some_dir.rstrip(os.path.sep) + followlinks = True if level > 0 else False + assert os.path.isdir(some_dir) + num_sep = some_dir.count(os.path.sep) + for root, dirs, files in os.walk(some_dir, followlinks=followlinks): + yield root, dirs, files + num_sep_this = root.count(os.path.sep) + if level != -1 and num_sep + level <= num_sep_this: + del dirs[:] + +def mtimelevel(path, level): + mtime = os.stat(path).st_mtime + for dirpath, dirnames, filenames in walklevel(path, level): + dirlist = [os.path.join("/", dirpath, d) for d in dirnames + if level == -1 or dirpath.count(os.path.sep) - path.count(os.path.sep) <= level] + mtime = max(mtime, max([-1] + [os.stat(d).st_mtime for d in dirlist])) + return mtime + class Directory(FileSystemObject, Accumulator, Loadable): is_directory = True enterable = False @@ -183,7 +202,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, flat=0): + def load_bit_by_bit(self): """An iterator that loads a part on every next() call Returns a generator which load a part of the directory @@ -194,17 +213,7 @@ 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[:] + basename_is_rel_to = self.path if self.flat else None try: if self.runnable: @@ -213,17 +222,20 @@ class Directory(FileSystemObject, Accumulator, Loadable): self.mount_path = mount_path(mypath) - if flat: + if self.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] + for dirpath, dirnames, filenames in walklevel(mypath, self.flat): + dirlist = [os.path.join("/", dirpath, d) for d in dirnames + if self.flat == -1 or dirpath.count(os.path.sep) - mypath.count(os.path.sep) <= self.flat] + filelist += dirlist filelist += [os.path.join("/", dirpath, f) for f in filenames] - filenames = [os.path.relpath(name, mypath) for name in filelist] + filenames = filelist + self.load_content_mtime = mtimelevel(mypath, self.flat) else: filelist = os.listdir(mypath) filenames = [mypath + (mypath == '/' and fname or '/' + fname) for fname in filelist] + self.load_content_mtime = os.stat(mypath).st_mtime if self._cumulative_size_calculated: # If self.content_loaded is true, this is not the first @@ -245,8 +257,6 @@ class Directory(FileSystemObject, Accumulator, Loadable): yield - self.load_content_mtime = os.stat(mypath).st_mtime - marked_paths = [obj.path for obj in self.marked_items] files = [] @@ -269,17 +279,20 @@ class Directory(FileSystemObject, Accumulator, Loadable): stats = None is_a_dir = False if is_a_dir: - try: - item = self.fm.get_directory(name, - basename_is_rel=basename_is_rel) - item.load_if_outdated() - except: + if self.flat: item = Directory(name, preload=stats, path_is_abs=True, - basename_is_rel=basename_is_rel) + basename_is_rel_to=basename_is_rel_to) item.load() + else: + try: + item = self.fm.get_directory(name) + item.load_if_outdated() + except: + item = Directory(name, preload=stats, path_is_abs=True) + item.load() else: item = File(name, preload=stats, path_is_abs=True, - basename_is_rel=basename_is_rel) + basename_is_rel_to=basename_is_rel_to) item.load() disk_usage += item.size @@ -350,7 +363,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(flat=self.flat) + self.load_generator = self.load_bit_by_bit() if schedule and self.fm: self.fm.loader.add(self) @@ -530,7 +543,10 @@ class Directory(FileSystemObject, Accumulator, Loadable): return True try: - real_mtime = os.stat(self.path).st_mtime + if self.flat: + real_mtime = mtimelevel(self.path, self.flat) + else: + real_mtime = os.stat(self.path).st_mtime except OSError: real_mtime = None return False diff --git a/ranger/container/fsobject.py b/ranger/container/fsobject.py index 59e23f6b..020721d8 100644 --- a/ranger/container/fsobject.py +++ b/ranger/container/fsobject.py @@ -83,20 +83,22 @@ class FileSystemObject(FileManagerAware, SettingsAware): vcs_outdated = False vcs_enabled = False - basename_is_rel = False + basename_is_rel_to = None _linemode = DEFAULT_LINEMODE - 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_to=None): if not path_is_abs: path = abspath(path) self.path = path - self.basename_is_rel = basename_is_rel - if not basename_is_rel: + self.basename_is_rel_to = basename_is_rel_to |