"""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' override = None old_cf = None old_mtime = None old_wid = None result = None def __init__(self, win, filelist=None): Widget.__init__(self, win) self.filelist = filelist def draw(self): """Draw the statusbar""" # each item in the returned array looks like: # [ list_with_color_tags, string ] # [ ['permissions', 'allowed'], '-rwxr-xr-x' ] if self.override and isinstance(self.override, str): self._draw_message() else: try: mtime = self.env.cf.stat.st_mtime except: mtime = -1 if not self.result or self.old_cf != self.env.cf or \ mtime != self.old_mtime or self.old_wid != self.wid: self.old_mtime = mtime self.old_cf = self.env.cf self.old_wid = self.wid left = self._get_left_part() right = self._get_right_part() self.result = self._combine_parts(left, right) self._print_result(self.result) def _draw_message(self): highlight = True space_left = self.wid starting_point = self.x for string in self.override.split('//'): highlight = not highlight if highlight: self.color('in_statusbar', 'text', 'highlight') else: self.color('in_statusbar', 'text') try: self.win.addnstr(self.y, starting_point, string, space_left) except: break space_left -= len(string) starting_point += len(string) # if starting_point >= self.wid: # break def _get_left_part(self): part = [] if self.filelist is not None: target = self.filelist.target.pointed_obj else: target = self.env.at_level(0).pointed_obj if target is None: return part if target.accessible is False: return part perms = target.get_permission_string() color = ['permissions'] if getuid() == target.stat.st_uid: color.append('good') else: color.append('bad') 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'], " "]) if target.islink: color = ['link'] color.append(target.exists and 'good' or 'bad') part.append([color, '-> ' + target.readlink]) else: 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 = [] if self.filelist is None: return part target = self.filelist.target # target = self.env.at_level(0) if not target.content_loaded or not target.accessible: return part pos = target.scroll_begin max_pos = len(target) - self.filelist.hei if target.marked_items: part.append([['scroll', 'marked'], 'Mrk']) elif 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. 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