diff options
-rw-r--r-- | ranger/colorschemes/default.py | 10 | ||||
-rw-r--r-- | ranger/core/actions.py | 1 | ||||
-rw-r--r-- | ranger/defaults/commands.py | 2 | ||||
-rw-r--r-- | ranger/fsobject/__init__.py | 2 | ||||
-rw-r--r-- | ranger/fsobject/fsobject.py | 81 | ||||
-rw-r--r-- | ranger/gui/context.py | 4 | ||||
-rw-r--r-- | ranger/gui/widgets/browsercolumn.py | 41 | ||||
-rw-r--r-- | ranger/gui/widgets/statusbar.py | 18 | ||||
-rw-r--r-- | ranger/gui/widgets/titlebar.py | 2 |
9 files changed, 99 insertions, 62 deletions
diff --git a/ranger/colorschemes/default.py b/ranger/colorschemes/default.py index ca8456e7..317e8258 100644 --- a/ranger/colorschemes/default.py +++ b/ranger/colorschemes/default.py @@ -49,8 +49,11 @@ class Default(ColorScheme): fg = green if context.socket: fg = magenta - if context.fifo: + attr |= bold + if context.fifo or context.device: fg = yellow + if context.device: + attr |= bold if context.link: fg = context.good and cyan or magenta if context.tag_marker and not context.selected: @@ -68,6 +71,11 @@ class Default(ColorScheme): if context.marked: attr |= bold fg = yellow + if context.badinfo: + if attr & reverse: + bg = magenta + else: + fg = magenta elif context.in_titlebar: attr |= bold diff --git a/ranger/core/actions.py b/ranger/core/actions.py index f96caeee..d7e33c9b 100644 --- a/ranger/core/actions.py +++ b/ranger/core/actions.py @@ -22,7 +22,6 @@ from inspect import cleandoc import ranger from ranger.ext.direction import Direction from ranger import fsobject -from ranger.ext.direction import Direction from ranger.shared import FileManagerAware, EnvironmentAware, SettingsAware from ranger.gui.widgets import console_mode as cmode from ranger.fsobject import File diff --git a/ranger/defaults/commands.py b/ranger/defaults/commands.py index 03fa1634..f04c4889 100644 --- a/ranger/defaults/commands.py +++ b/ranger/defaults/commands.py @@ -332,7 +332,7 @@ class delete(Command): cwd = self.fm.env.cwd cf = self.fm.env.cf - if cwd.marked_items or (cf.is_directory and not cf.islink \ + if cwd.marked_items or (cf.is_directory and not cf.is_link \ and len(os.listdir(cf.path)) > 0): # better ask for a confirmation, when attempting to # delete multiple files or a non-empty directory. diff --git a/ranger/fsobject/__init__.py b/ranger/fsobject/__init__.py index 5f727c87..6796f252 100644 --- a/ranger/fsobject/__init__.py +++ b/ranger/fsobject/__init__.py @@ -21,7 +21,7 @@ T_DIRECTORY = 'directory' T_UNKNOWN = 'unknown' T_NONEXISTANT = 'nonexistant' -BAD_INFO = None +BAD_INFO = '?' class NotLoadedYet(Exception): pass diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py index 1ab3addd..94729b9a 100644 --- a/ranger/fsobject/fsobject.py +++ b/ranger/fsobject/fsobject.py @@ -16,11 +16,18 @@ CONTAINER_EXTENSIONS = 'rar zip tar gz bz bz2 tgz 7z iso cab'.split() DOCUMENT_EXTENSIONS = 'pdf doc ppt odt'.split() DOCUMENT_BASENAMES = 'README TODO LICENSE COPYING INSTALL'.split() - -import time +DOCUMENT_EXTENSIONS = () +DOCUMENT_BASENAMES = () + +import stat +import os +from time import time +from subprocess import Popen, PIPE +from os.path import abspath, basename, dirname, realpath from . import T_FILE, T_DIRECTORY, T_UNKNOWN, T_NONEXISTANT, BAD_INFO from ranger.shared import MimeTypeAware, FileManagerAware from ranger.ext.shell_escape import shell_escape +from ranger.ext.human_readable import human_readable class FileSystemObject(MimeTypeAware, FileManagerAware): is_file = False @@ -40,7 +47,10 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): tagged = False loaded = False runnable = False - islink = False + is_link = False + is_device = False + is_socket = False + is_fifo = False readlink = None stat = None infostring = None @@ -62,20 +72,17 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): def __init__(self, path): MimeTypeAware.__init__(self) - if type(self) == FileSystemObject: - raise TypeError("Cannot initialize abstract class FileSystemObject") - - from os.path import abspath, basename, dirname, realpath path = abspath(path) self.path = path self.basename = basename(path) self.basename_lower = self.basename.lower() self.dirname = dirname(path) - self.realpath = realpath(path) + self.realpath = self.path try: - self.extension = self.basename[self.basename.rindex('.') + 1:].lower() + lastdot = self.basename.rindex('.') + 1 + self.extension = self.basename[lastdot:].lower() except ValueError: self.extension = None @@ -94,10 +101,9 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): @property def filetype(self): if self._filetype is None: - import subprocess try: - got = subprocess.Popen(["file", '-Lb', '--mime-type',\ - self.path], stdout=subprocess.PIPE).communicate()[0] + got = Popen(["file", '-Lb', '--mime-type', self.path], + stdout=PIPE).communicate()[0] except OSError: self._filetype = '' else: @@ -113,13 +119,13 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): def use(self): """mark the filesystem-object as used at the current time""" - self.last_used = time.time() + self.last_used = time() def is_older_than(self, seconds): """returns whether this object wasn't use()d in the last n seconds""" if seconds < 0: return True - return self.last_used + seconds < time.time() + return self.last_used + seconds < time() def set_mimetype(self): """assign attributes such as self.video according to the mimetype""" @@ -155,9 +161,6 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): reads useful information about the filesystem-object from the filesystem and caches it for later use """ - import os - import stat - from ranger.ext.human_readable import human_readable self.loaded = True @@ -165,10 +168,21 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): self.stat = os.lstat(self.path) except OSError: self.stat = None - self.islink = False + self.is_link = False self.accessible = False else: - self.islink = stat.S_ISLNK(self.stat.st_mode) + self.is_link = stat.S_ISLNK(self.stat.st_mode) + if self.is_link: + try: # try to resolve the link + self.readlink = os.readlink(self.path) + self.realpath = realpath(self.path) + self.stat = os.stat(self.path) + except: # it failed, so it must be a broken link + pass + mode = self.stat.st_mode + self.is_device = bool(stat.S_ISCHR(mode) or stat.S_ISBLK(mode)) + self.is_socket = bool(stat.S_ISSOCK(mode)) + self.is_fifo = bool(stat.S_ISFIFO(mode)) self.accessible = True if self.accessible and os.access(self.path, os.F_OK): @@ -191,10 +205,17 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): self.infostring = ' ' + human_readable(self.stat.st_size) else: self.type = T_UNKNOWN - self.infostring = None + if self.is_device: + self.infostring = 'dev' + elif self.is_fifo: + self.infostring = 'fifo' + elif self.is_socket: + self.infostring = 'sock' + else: + self.infostring = BAD_INFO else: - if self.islink: + if self.is_link: self.infostring = '->' else: self.infostring = None @@ -202,18 +223,14 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): self.exists = False self.runnable = False - if self.islink: - self.readlink = os.readlink(self.path) - def get_permission_string(self): if self.permissions is not None: return self.permissions - if self.accessible is False: - return '----------' - - import stat - mode = self.stat.st_mode + try: + mode = self.stat.st_mode + except: + return '----??----' if stat.S_ISDIR(mode): perms = ['d'] @@ -250,9 +267,8 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): Calls load() if the currently cached information is outdated or nonexistant. """ - if self.load_once(): return True - - import os + if self.load_once(): + return True try: real_mtime = os.lstat(self.path).st_mtime except OSError: @@ -261,7 +277,6 @@ class FileSystemObject(MimeTypeAware, FileManagerAware): cached_mtime = self.stat.st_mtime else: cached_mtime = 0 - if real_mtime != cached_mtime: self.load() return True diff --git a/ranger/gui/context.py b/ranger/gui/context.py index d4c1c94d..1e127a2e 100644 --- a/ranger/gui/context.py +++ b/ranger/gui/context.py @@ -13,11 +13,11 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. -CONTEXT_KEYS = ['reset', 'error', +CONTEXT_KEYS = ['reset', 'error', 'badinfo', 'in_browser', 'in_statusbar', 'in_titlebar', 'in_console', 'in_pager', 'in_taskview', 'directory', 'file', 'hostname', - 'executable', 'media', 'link', 'fifo', 'socket', + 'executable', 'media', 'link', 'fifo', 'socket', 'device', 'video', 'audio', 'image', 'media', 'document', 'container', 'selected', 'empty', 'main_column', 'message', 'background', 'good', 'bad', diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py index 8cf8990c..61c74e63 100644 --- a/ranger/gui/widgets/browsercolumn.py +++ b/ranger/gui/widgets/browsercolumn.py @@ -20,6 +20,7 @@ from time import time from . import Widget from .pager import Pager +from ranger.fsobject import BAD_INFO # Don't even try to preview files which mach this regular expression: PREVIEW_BLACKLIST = re.compile(r""" @@ -95,20 +96,21 @@ class BrowserColumn(Pager): pass elif self.target.type is T_DIRECTORY: - index = self.scroll_begin + event.y - self.y - - if event.pressed(1): - if not self.main_column: - self.fm.enter_dir(self.target.path) - - if index < len(self.target): - self.fm.move(to=index) - elif event.pressed(3): - try: - clicked_file = self.target.files[index] - self.fm.enter_dir(clicked_file.path) - except: - pass + if self.target.accessible and self.target.content_loaded: + index = self.scroll_begin + event.y - self.y + + if event.pressed(1): + if not self.main_column: + self.fm.enter_dir(self.target.path) + + if index < len(self.target): + self.fm.move(to=index) + elif event.pressed(3): + try: + clicked_file = self.target.files[index] + self.fm.enter_dir(clicked_file.path) + except: + pass else: if self.level > 0: @@ -173,6 +175,7 @@ class BrowserColumn(Pager): and target.is_file \ and target.accessible \ and target.stat \ + and not target.is_device \ and not target.stat.st_mode & stat.S_IFIFO): return False @@ -250,6 +253,7 @@ class BrowserColumn(Pager): except IndexError: break + bad_info_color = None this_color = base_color + list(drawn.mimetype_tuple) text = drawn.basename tagged = self.fm.tags and drawn.realpath in self.fm.tags @@ -280,11 +284,13 @@ class BrowserColumn(Pager): this_color.append('fifo') if stat.S_ISSOCK(mode): this_color.append('socket') + if drawn.is_device: + this_color.append('device') if self.env.copy and drawn in self.env.copy: this_color.append('cut' if self.env.cut else 'copied') - if drawn.islink: + if drawn.is_link: this_color.append('link') this_color.append(drawn.exists and 'good' or 'bad') @@ -302,6 +308,8 @@ class BrowserColumn(Pager): and self.settings.display_size_in_main_column: info = drawn.infostring x = self.wid - 1 - len(info) + if info is BAD_INFO: + bad_info_color = (x, len(str(info))) if x > self.x: self.win.addstr(line, x, str(info) + ' ') except: @@ -310,6 +318,9 @@ class BrowserColumn(Pager): pass self.color_at(line, 0, self.wid, this_color) + if bad_info_color: + start, wid = bad_info_color + self.color_at(line, start, wid, this_color, 'badinfo') if self.main_column and tagged and self.wid > 2: this_color.append('tag_marker') diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py index caf5786e..bff3d8ad 100644 --- a/ranger/gui/widgets/statusbar.py +++ b/ranger/gui/widgets/statusbar.py @@ -145,23 +145,27 @@ class StatusBar(Widget): target = self.column.target.pointed_obj else: target = self.env.at_level(0).pointed_obj - if target is None or not target.accessible: + try: + stat = target.stat + except: + return + if stat is None: return perms = target.get_permission_string() - how = getuid() == target.stat.st_uid and 'good' or 'bad' + how = getuid() == stat.st_uid and 'good' or 'bad' left.add(perms, 'permissions', how) - left.add_space() - left.add(str(target.stat.st_nlink), 'nlink') + left.add(str(stat.st_nlink), 'nlink') left.add_space() left.add(self._get_owner(target), 'owner') left.add_space() left.add(self._get_group(target), 'group') - if target.islink: + if target.is_link: how = target.exists and 'good' or 'bad' - left.add(' -> ' + target.readlink, 'link', how) + dest = target.readlink if target.readlink is not None else '?' + left.add(' -> ' + dest, 'link', how) else: if self.settings.display_size_in_status_bar and target.infostring: left.add(target.infostring) @@ -169,7 +173,7 @@ class StatusBar(Widget): left.add_space() left.add(strftime(self.timeformat, - localtime(target.stat.st_mtime)), 'mtime') + localtime(stat.st_mtime)), 'mtime') def _get_owner(self, target): uid = target.stat.st_uid diff --git a/ranger/gui/widgets/titlebar.py b/ranger/gui/widgets/titlebar.py index b815a07e..a949df05 100644 --- a/ranger/gui/widgets/titlebar.py +++ b/ranger/gui/widgets/titlebar.py @@ -118,7 +118,7 @@ class TitleBar(Widget): bar.add('~/', 'directory', fixed=True) for path in pathway: - if path.islink: + if path.is_link: clr = 'link' else: clr = 'directory' |