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 + if basename_is_rel_to == None: self.basename = basename(path) + self.drawn_basename = self.basename else: - self.basename = relpath(path, getcwd()) - self.basename_lower = self.basename.lower() + self.basename = basename(path) + self.drawn_basename = relpath(path, basename_is_rel_to) + self.basename_lower = self.drawn_basename.lower() self.extension = splitext(self.basename)[1].lstrip(extsep) or None self.dirname = dirname(path) self.preload = preload @@ -140,7 +142,7 @@ class FileSystemObject(FileManagerAware, SettingsAware): @lazy_property def basename_natural(self): return [c if i % 3 == 1 else (int(c) if c else 0) for i, c in \ - enumerate(_extract_number_re.split(self.basename))] + enumerate(_extract_number_re.split(self.drawn_basename))] @lazy_property def basename_natural_lower(self): diff --git a/ranger/core/fm.py b/ranger/core/fm.py index 3497f20c..6bb4fd22 100644 --- a/ranger/core/fm.py +++ b/ranger/core/fm.py @@ -258,17 +258,13 @@ class FM(Actions, SignalDispatcher): """returns the path relative to rangers library directory""" return os.path.join(ranger.RANGERDIR, *paths) - def get_directory(self, path, basename_is_rel = False): + def get_directory(self, path): """Get the directory object at the given path""" path = os.path.abspath(path) try: - directory = self.directories[path] - if directory.basename_is_rel != basename_is_rel: - del self.directories[path] - raise KeyError - return directory + return self.directories[path] except KeyError: - obj = Directory(path, basename_is_rel = basename_is_rel) + obj = Directory(path) self.directories[path] = obj return obj diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py index b2159339..5eabe2c6 100644 --- a/ranger/gui/widgets/browsercolumn.py +++ b/ranger/gui/widgets/browsercolumn.py @@ -274,10 +274,10 @@ class BrowserColumn(Pager): else: text = paperinfo.title if use_linemode == "filename": - text = drawn.basename + text = drawn.drawn_basename elif use_linemode == "permissions": text = "%s %s %s %s" % (drawn.get_permission_string(), - drawn.user, drawn.group, drawn.basename) + drawn.user, drawn.group, drawn.drawn_basename) if drawn.marked and (self.main_column or \ diff --git a/ranger/gui/widgets/titlebar.py b/ranger/gui/widgets/titlebar.py index fa10a744..25edd5e4 100644 --- a/ranger/gui/widgets/titlebar.py +++ b/ranger/gui/widgets/titlebar.py @@ -117,7 +117,7 @@ class TitleBar(Widget): if self.fm.thisfile is not None and \ self.settings.show_selection_in_titlebar: - bar.add(self.fm.thisfile.basename, 'file') + bar.add(self.fm.thisfile.drawn_basename, 'file') def _get_right_part(self, bar): # TODO: fix that pressed keys are cut off when chaining CTRL keys |