about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorhut <hut@lavabit.com>2009-12-25 02:40:40 +0100
committerhut <hut@lavabit.com>2009-12-25 02:40:40 +0100
commitddf828fb5ce5a539e01d968aee5817ad1c921a01 (patch)
treeaffeda319a74d2f418a50a42f68285f8e2d77310
parentb37c2b62a11da70f9a2fcc369701fe3d70df1494 (diff)
downloadranger-ddf828fb5ce5a539e01d968aee5817ad1c921a01.tar.gz
added process manager which lists running load processes
-rw-r--r--ranger/colorschemes/default.py8
-rw-r--r--ranger/defaults/keys.py22
-rw-r--r--ranger/ext/accumulator.py93
-rw-r--r--ranger/fsobject/fsobject.py3
-rw-r--r--ranger/gui/colorscheme.py4
-rw-r--r--ranger/gui/defaultui.py16
-rw-r--r--ranger/gui/widgets/process_manager.py114
7 files changed, 258 insertions, 2 deletions
diff --git a/ranger/colorschemes/default.py b/ranger/colorschemes/default.py
index e3cdb766..69397800 100644
--- a/ranger/colorschemes/default.py
+++ b/ranger/colorschemes/default.py
@@ -83,4 +83,12 @@ class Default(ColorScheme):
 			if context.highlight:
 				attr |= reverse
 
+		if context.in_pman:
+			if context.title:
+				attr |= reverse
+				fg = cyan
+
+			if context.selected:
+				attr |= reverse
+
 		return fg, bg, attr
diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py
index 5586a4a4..2a775ab9 100644
--- a/ranger/defaults/keys.py
+++ b/ranger/defaults/keys.py
@@ -137,6 +137,8 @@ def initialize_commands(command_list):
 	bind('h', KEY_LEFT, KEY_BACKSPACE, DEL, lambda fm, n: \
 			fm.move_left(n or 1))
 
+	bind('P', lambda fm, n: fm.ui.open_pman())
+
 	command_list.rebuild_paths()
 
 
@@ -182,3 +184,23 @@ def initialize_console_commands(command_list):
 		bind(i, type_key(i))
 
 	command_list.rebuild_paths()
+
+def initialize_process_manager_commands(command_list):
+	"""Initialize the commands for the process manager widget"""
+
+	from ranger.gui.widgets.process_manager import KeyWrapper as wdg
+
+	def bind(*args):
+		command_list.bind(args[-1], *args[:-1])
+
+	def do_fm(method, *args, **kw):
+		return lambda con: getattr(con.fm, method)(*args, **kw)
+
+	bind('j', KEY_DOWN, wdg.move(relative=1))
+	bind('k', KEY_UP, wdg.move(relative=-1))
+	bind('gg', wdg.move(absolute=0))
+	bind('G', wdg.move(absolute=-1))
+
+	bind('P', ESC, ctrl('d'), lambda wdg, n: wdg.fm.ui.close_pman())
+
+	command_list.rebuild_paths()
diff --git a/ranger/ext/accumulator.py b/ranger/ext/accumulator.py
new file mode 100644
index 00000000..7fed72dd
--- /dev/null
+++ b/ranger/ext/accumulator.py
@@ -0,0 +1,93 @@
+class Accumulator(object):
+	def __init__(self):
+		self.pointer = 0
+		self.pointed_obj = None
+
+	def move(self, relative=0, absolute=None):
+		i = self.pointer
+		lst = self.get_list()
+		length = len(lst)
+
+		if isinstance(absolute, int):
+			if absolute < 0: # wrap
+				i = absolute + length
+			else:
+				i = absolute
+
+		if isinstance(relative, int):
+			i += relative
+
+		if i >= length:
+			i = length - 1
+		if i < 0:
+			i = 0
+
+		self.pointer = i
+		self.correct_pointer()
+	
+	def move_to_obj(self, arg, attr=None):
+		if not arg:
+			return
+
+		lst = self.get_list()
+
+		if not lst:
+			return
+
+		do_get_attr = isinstance(attr, str)
+
+		good = arg
+		if do_get_attr:
+			try:
+				good = getattr(arg, attr)
+			except (TypeError, AttributeError):
+				pass
+
+		for obj, i in zip(lst, range(len(lst))):
+			if do_get_attr:
+				try:
+					test = getattr(obj, attr)
+				except AttributeError:
+					continue
+			else:
+				test = obj
+
+			if test == good:
+				self.move(absolute=i)
+				return True
+
+		return self.move(absolute=self.pointer)
+
+	def correct_pointer(self):
+		lst = self.get_list()
+
+		if not lst:
+			self.pointer = 0
+			self.pointed_obj = None
+
+		else:
+			i = self.pointer
+
+			if i is None:
+				i = 0
+			if i >= len(lst):
+				i = len(lst) - 1
+			if i < 0:
+				i = 0
+
+			self.pointer = i
+			self.pointed_obj = lst[i]
+
+	def pointer_is_synced(self):
+		lst = self.get_list()
+		try:
+			return lst[self.pointer] == self.pointed_obj
+		except (IndexError, KeyError):
+			return False
+	
+	def sync_index(self, **kw):
+		self.move_to_obj(self.pointed_obj, **kw)
+
+	def get_list(self):
+		"""OVERRIDE THIS"""
+		return []
diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py
index 1864a7fc..f7d9772c 100644
--- a/ranger/fsobject/fsobject.py
+++ b/ranger/fsobject/fsobject.py
@@ -57,6 +57,9 @@ class FileSystemObject(MimeTypeAware, FileManagerAware):
 
 		self.set_mimetype()
 		self.use()
+
+	def get_description(self):
+		return "Loading " + str(self)
 	
 	def __str__(self):
 		"""returns a string containing the absolute path"""
diff --git a/ranger/gui/colorscheme.py b/ranger/gui/colorscheme.py
index 4fdcaad2..227051f9 100644
--- a/ranger/gui/colorscheme.py
+++ b/ranger/gui/colorscheme.py
@@ -1,6 +1,6 @@
 CONTEXT_KEYS = [ 'reset', 'error',
 		'in_display', 'in_statusbar', 'in_titlebar', 'in_console',
-		'in_notify',
+		'in_notify', 'in_pman',
 		'directory', 'file', 'hostname',
 		'executable', 'media', 'link',
 		'video', 'audio', 'image', 'media', 'document', 'container',
@@ -9,7 +9,7 @@ CONTEXT_KEYS = [ 'reset', 'error',
 		'space', 'permissions', 'owner', 'group', 'mtime', 'nlink',
 		'scroll', 'all', 'bot', 'top', 'percentage',
 		'marked',
-		'text', 'highlight',
+		'title', 'text', 'highlight',
 		'keybuffer']
 
 # colorscheme specification:
diff --git a/ranger/gui/defaultui.py b/ranger/gui/defaultui.py
index 2b1fa188..31049178 100644
--- a/ranger/gui/defaultui.py
+++ b/ranger/gui/defaultui.py
@@ -10,6 +10,7 @@ class DefaultUI(UI):
 		from ranger.gui.widgets.titlebar import TitleBar
 		from ranger.gui.widgets.console import Console
 		from ranger.gui.widgets.statusbar import StatusBar
+		from ranger.gui.widgets.process_manager import ProcessManager
 		from ranger.gui.widgets.notify import Notify
 		self.titlebar = TitleBar(self.win)
 		self.add_obj(self.titlebar)
@@ -24,6 +25,10 @@ class DefaultUI(UI):
 		self.add_obj(self.console)
 		self.console.visible = False
 
+		self.pman = ProcessManager(self.win)
+		self.pman.visible = False
+		self.add_obj(self.pman)
+
 		self.notify = Notify(self.win)
 		self.add_obj(self.notify)
 
@@ -36,6 +41,7 @@ class DefaultUI(UI):
 #		log(notify_hei)
 
 		self.filelist_container.resize(1, 0, y - 2 - notify_hei, x)
+		self.pman.resize(1, 0, y - 2 - notify_hei, x)
 		self.notify.resize(y - 1 - notify_hei, 0, notify_hei, x)
 		self.titlebar.resize(0, 0, 1, x)
 		self.status.resize(y - 1, 0, 1, x)
@@ -59,6 +65,16 @@ class DefaultUI(UI):
 		self.console.visible = False
 		self.status.visible = True
 
+	def open_pman(self):
+		self.filelist_container.visible = False
+		self.pman.visible = True
+		self.pman.focused = True
+
+	def close_pman(self):
+		self.pman.visible = False
+		self.filelist_container.visible = True
+		self.pman.focused = False
+
 	def scroll(self, relative):
 		if self.main_filelist:
 			self.main_filelist.scroll(relative)
diff --git a/ranger/gui/widgets/process_manager.py b/ranger/gui/widgets/process_manager.py
new file mode 100644
index 00000000..ae372112
--- /dev/null
+++ b/ranger/gui/widgets/process_manager.py
@@ -0,0 +1,114 @@
+"""
+The process manager allows you to modify what the loader is doing.
+"""
+
+import curses
+
+from . import Widget
+from ranger.ext.accumulator import Accumulator
+from ranger import log
+from ranger.container import CommandList
+from collections import deque
+
+class DummyLoadObject(object):
+	def __init__(self, txt):
+		self.get_description = lambda: txt
+		self.load_generator = range(100)
+
+
+class DummyLoader(object):
+	def __init__(self):
+		self.queue = deque()
+		self.queue.append(DummyLoadObject("blub"))
+		self.queue.append(DummyLoadObject("foo"))
+		self.queue.append(DummyLoadObject("asfkljflk"))
+		self.queue.append(DummyLoadObject("g$%GKSERJgsldflj"))
+
+
+class ProcessManager(Widget, Accumulator):
+	def __init__(self, win):
+		Widget.__init__(self, win)
+		Accumulator.__init__(self)
+		self.scroll_begin = 0
+		self.commandlist = CommandList()
+		self.settings.keys.initialize_process_manager_commands( \
+				self.commandlist)
+
+		# ---- dummy loader for testing purposes
+		self.loader = DummyLoader()
+	
+	def draw(self):
+		base_clr = deque()
+		base_clr.append('in_pman')
+		lst = self.get_list()
+
+		if not self.pointer_is_synced():
+			self.sync_index()
+
+		self.win.addnstr(self.y, self.x, "  Process Manager", self.wid)
+		self.color_at(self.y, self.x, self.wid, base_clr, 'title')
+
+		if lst:
+			for i in range(self.hei - 1):
+				i += self.scroll_begin
+				try:
+					obj = lst[i]
+				except IndexError:
+					break
+				y, x = self.y + i + 1, self.x
+				clr = deque(base_clr)
+
+				if self.pointer == i:
+					clr.append('selected')
+
+				descr = obj.get_description()
+				self.win.addnstr(y, x, descr, self.wid)
+				self.color_at(y, x, self.wid, clr)
+
+		else:
+			if self.hei > 1:
+				self.win.addnstr(self.y + 1, self.x,\
+						"No processes running", self.wid)
+				self.color_at(self.y + 1, self.x, self.wid, base_clr, 'error')
+
+		self.color_reset()
+
+	def press(self, key):
+		try:
+			tup = self.env.keybuffer.tuple_without_numbers()
+			if tup:
+				cmd = self.commandlist[tup]
+			else:
+				return
+				
+		except KeyError:
+			self.env.key_clear()
+		else:
+			if hasattr(cmd, 'execute'):
+				cmd.execute(self, self.env.keybuffer.number)
+				self.env.key_clear()
+	
+	def get_list(self):
+		return self.fm.loader.queue
+		return self.loader.queue
+
+
+class KeyWrapper(object):
+	@staticmethod
+	def move(relative=0, absolute=None):
+		if absolute is None:
+			def fnc(wdg, n):
+				if n is not None:
+					if relative >= 0:
+						wdg.move(relative=n)
+					else:
+						wdg.move(relative=-n)
+				else:
+					wdg.move(relative=relative)
+		else:
+			def fnc(wdg, n):
+				if n is not None:
+					wdg.move(absolute=n, relative=relative)
+				else:
+					wdg.move(absolute=absolute, relative=relative)
+		return fnc