about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/colorschemes/default.py7
-rw-r--r--ranger/colorschemes/jungle.py7
-rw-r--r--ranger/fsobject/fsobject.py23
-rw-r--r--ranger/gui/colorscheme.py3
-rw-r--r--ranger/gui/defaultui.py11
-rw-r--r--ranger/gui/widgets/statusbar.py138
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