diff options
-rw-r--r-- | ranger/colorschemes/default.py | 7 | ||||
-rw-r--r-- | ranger/colorschemes/jungle.py | 7 | ||||
-rw-r--r-- | ranger/fsobject/fsobject.py | 23 | ||||
-rw-r--r-- | ranger/gui/colorscheme.py | 3 | ||||
-rw-r--r-- | ranger/gui/defaultui.py | 11 | ||||
-rw-r--r-- | ranger/gui/widgets/statusbar.py | 138 |
6 files changed, 187 insertions, 2 deletions
diff --git a/ranger/colorschemes/default.py b/ranger/colorschemes/default.py index b35aa8e1..ab2b71d3 100644 --- a/ranger/colorschemes/default.py +++ b/ranger/colorschemes/default.py @@ -55,4 +55,11 @@ class Default(ColorScheme): elif context.link: fg = cyan + elif context.in_statusbar: + if context.permissions: + if context.allowed: + fg = cyan + elif context.denied: + fg = magenta + return fg, bg, attr diff --git a/ranger/colorschemes/jungle.py b/ranger/colorschemes/jungle.py index 41e2d912..d2b9efd2 100644 --- a/ranger/colorschemes/jungle.py +++ b/ranger/colorschemes/jungle.py @@ -52,4 +52,11 @@ class Default(ColorScheme): fg = yellow attr = normal + elif context.in_statusbar: + if context.permissions: + if context.allowed: + fg = cyan + elif context.denied: + fg = magenta + return fg, bg, attr diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py index 30261c2c..728ff46d 100644 --- a/ranger/fsobject/fsobject.py +++ b/ranger/fsobject/fsobject.py @@ -126,6 +126,29 @@ and caches it for later use""" self.exists = False self.runnable = False self.accessible = False + + def get_permission_string(self): + if self.permissions is not None: + return self.permissions + + import stat + perms = '-' + mode = self.stat.st_mode + + if stat.S_ISDIR(mode): + perms = 'd' + elif stat.S_ISLNK(mode): + perms = 'l' + + for who in "USR", "GRP", "OTH": + for what in "R", "W", "X": + if mode & getattr(stat,"S_I"+what+who): + perms=perms+what.lower() + else: + perms=perms+"-" + + self.permissions = perms + return perms def load_once(self): """calls load() if it has not been called at least once yet""" diff --git a/ranger/gui/colorscheme.py b/ranger/gui/colorscheme.py index a69ed75b..537f4458 100644 --- a/ranger/gui/colorscheme.py +++ b/ranger/gui/colorscheme.py @@ -4,6 +4,9 @@ CONTEXT_KEYS = [ 'reset', 'error', 'executable', 'media', 'link', 'video', 'audio', 'image', 'media', 'document', 'container', 'broken', 'selected', 'empty', 'maindisplay', + 'allowed', 'denied', + 'space', 'permissions', 'owner', 'group', 'mtime', 'nlink', + 'scroll', 'all', 'bot', 'top', 'percentage', 'keybuffer'] # colorscheme specification: diff --git a/ranger/gui/defaultui.py b/ranger/gui/defaultui.py index 5b32690d..93bfe248 100644 --- a/ranger/gui/defaultui.py +++ b/ranger/gui/defaultui.py @@ -8,6 +8,7 @@ class DefaultUI(UI): from ranger.gui.widgets.filelistcontainer import FileListContainer from ranger.gui.widgets.titlebar import TitleBar from ranger.gui.widgets.console import Console + from ranger.gui.widgets.statusbar import StatusBar self.titlebar = TitleBar(self.win) self.add_obj(self.titlebar) @@ -15,25 +16,31 @@ class DefaultUI(UI): self.add_obj(self.filelist_container) self.main_filelist = self.filelist_container.main_filelist + self.status = StatusBar(self.win, self.main_filelist) + self.add_obj(self.status) self.console = Console(self.win) self.add_obj(self.console) + self.console.visible = False def update_size(self): """resize all widgets""" UI.update_size(self) y, x = self.env.termsize - self.filelist_container.resize(1, 0, y-2, x) + self.filelist_container.resize(1, 0, y - 2, x) self.titlebar.resize(0, 0, 1, x) - self.console.resize(y-1, 0, 1, x) + self.status.resize(y - 1, 0, 1, x) + self.console.resize(y - 1, 0, 1, x) def open_console(self, mode): if self.console.open(mode): self.console.on_close = self.close_console self.console.visible = True + self.status.visible = False def close_console(self): self.console.visible = False + self.status.visible = True def scroll(self, relative): if self.main_filelist: diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py new file mode 100644 index 00000000..6153101c --- /dev/null +++ b/ranger/gui/widgets/statusbar.py @@ -0,0 +1,138 @@ +"""The StatusBar displays information about the currently selected file +in the same form as the "ls -l" command on the left side, and +some additional info about the current directory on the right side. +""" + +from . import Widget +from ranger import log +from pwd import getpwuid +from grp import getgrgid +from os import getuid +from time import strftime, localtime + +class StatusBar(Widget): + __doc__ = __doc__ + owners = {} + groups = {} + timeformat = '%Y-%m-%d %H:%M' + + def __init__(self, win, filelist=None): + Widget.__init__(self, win) + self.filelist = filelist + + def draw(self): + left = self._get_left_part() + right = self._get_right_part() + self._print_result(self._combine_parts(left, right)) + + def _get_left_part(self): + part = [] + + target = self.env.at_level(0).pointed_file + if target is None: + return part + + perms = target.get_permission_string() + color = ['permissions'] + if getuid() == target.stat.st_uid: + color.append('allowed') + else: + color.append('denied') + part.append([color, perms]) + + part.append([['space'], " "]) + part.append([['nlink'], str(target.stat.st_nlink)]) + part.append([['space'], " "]) + part.append([['owner'], self._get_owner(target)]) + part.append([['space'], " "]) + part.append([['group'], self._get_group(target)]) + part.append([['space'], " "]) + part.append([['mtime'], strftime(self.timeformat, \ + localtime(target.stat.st_mtime))]) + return part + + def _get_owner(self, target): + uid = target.stat.st_uid + + try: + return self.owners[uid] + except KeyError: + try: + self.owners[uid] = getpwuid(uid)[0] + return self.owners[uid] + except KeyError: + return str(uid) + + def _get_group(self, target): + gid = target.stat.st_gid + + try: + return self.groups[gid] + except KeyError: + try: + self.groups[gid] = getgrgid(gid)[0] + return self.groups[gid] + except KeyError: + return str(gid) + + def _get_right_part(self): + part = [] + target = self.env.at_level(0) + + if self.filelist is not None: + pos = target.scroll_begin + max_pos = len(target) - self.filelist.hei + + if max_pos > 0: + if pos == 0: + part.append([['scroll', 'top'], 'Top']) + elif pos >= max_pos: + part.append([['scroll', 'bot'], 'Bot']) + else: + part.append([['scroll', 'percentage'], \ + '{0:0>.0f}%'.format(100.0*pos/max_pos)]) + else: + part.append([['scroll', 'all'], 'All']) + return part + + + def _combine_parts(self, left, right): + """Combines left and right, filling the middle with spaces and +removing elements which don't have enough room to fit in. +<left> will be turned into the result (which is also returned). +""" + + leftsize = sum(len(part[1]) for part in left) + rightsize = sum(len(part[1]) for part in right) + sumsize = leftsize + rightsize + + # remove elemets from the left until it fits + if sumsize > self.wid: + while len(left) > 0: + leftsize -= len(left.pop(-1)[1]) + if leftsize + rightsize <= self.wid: + break + sumsize = leftsize + rightsize + + # remove elemets from the right until it fits + if sumsize > self.wid: + while len(right) > 0: + rightsize -= len(right.pop(0)[1]) + if leftsize + rightsize <= self.wid: + break + sumsize = leftsize + rightsize + + if sumsize < self.wid: + left.append([ ['space'], " " * (self.wid - sumsize) ]) + left.extend(right) + return left + + def _print_result(self, result): + import _curses + self.win.move(self.y, self.x) + for part in result: + self.color('in_statusbar', *part[0]) + try: + self.win.addstr(part[1]) + except _curses.error: + pass |