summary refs log tree commit diff stats
path: root/ranger
diff options
context:
space:
mode:
authorhut <hut@lavabit.com>2010-03-30 04:50:38 +0200
committerhut <hut@lavabit.com>2010-03-30 04:50:38 +0200
commit1c1b6c31de513f0f056a915bf7d8e608c485ae50 (patch)
treeb2dd0153d058cdbcf0c24b033703ab6d7f0efa8e /ranger
parent489a1616407a3d6c588b1890c9ddbf795ae5724f (diff)
downloadranger-1c1b6c31de513f0f056a915bf7d8e608c485ae50.tar.gz
added SignalDispatcher class
Diffstat (limited to 'ranger')
-rw-r--r--ranger/core/fm.py4
-rw-r--r--ranger/ext/signal_dispatcher.py79
2 files changed, 82 insertions, 1 deletions
diff --git a/ranger/core/fm.py b/ranger/core/fm.py
index 94d0d85d..aef10150 100644
--- a/ranger/core/fm.py
+++ b/ranger/core/fm.py
@@ -26,18 +26,20 @@ from ranger.container import Bookmarks
 from ranger.core.runner import Runner
 from ranger import relpath_conf
 from ranger.ext.get_executables import get_executables
+from ranger.ext.signal_dispatcher import SignalDispatcher
 from ranger import __version__
 from ranger.fsobject import Loader
 
 CTRL_C = 3
 TICKS_BEFORE_COLLECTING_GARBAGE = 100
 
-class FM(Actions):
+class FM(Actions, SignalDispatcher):
 	input_blocked = False
 	input_blocked_until = 0
 	def __init__(self, ui=None, bookmarks=None, tags=None):
 		"""Initialize FM."""
 		Actions.__init__(self)
+		SignalDispatcher.__init__(self)
 		self.ui = ui
 		self.log = deque(maxlen=20)
 		self.bookmarks = bookmarks
diff --git a/ranger/ext/signal_dispatcher.py b/ranger/ext/signal_dispatcher.py
new file mode 100644
index 00000000..542fb472
--- /dev/null
+++ b/ranger/ext/signal_dispatcher.py
@@ -0,0 +1,79 @@
+# Copyright (C) 2009, 2010  Roman Zimbelmann <romanz@lavabit.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+class Signal(dict):
+	stopped = False
+	def __init__(self, **keywords):
+		dict.__init__(self, keywords)
+		self.__dict__ = self
+
+	def stop(self):
+		self.stopped = True
+
+
+class SignalHandler(object):
+	active = True
+	def __init__(self, signal_name, function, priority, pass_signal):
+		self.priority = max(0, min(1, priority))
+		self.signal_name = signal_name
+		self.function = function
+		self.pass_signal = pass_signal
+
+
+class SignalDispatcher(object):
+	def __init__(self):
+		self._signals = dict()
+
+	signal_clear = __init__
+
+	def signal_bind(self, signal_name, function, priority=0.5):
+		assert isinstance(signal_name, str)
+		try:
+			handlers = self._signals[signal_name]
+		except:
+			handlers = self._signals[signal_name] = []
+		nargs = function.__code__.co_argcount - hasattr(function, 'im_func')
+		handler = SignalHandler(signal_name, function, priority, nargs > 0)
+		handlers.append(handler)
+		handlers.sort(key=lambda handler: -handler.priority)
+		return handler
+
+	def signal_unbind(self, signal_handler):
+		try:
+			handlers = self._signals[signal_handler.signal_name]
+		except KeyError:
+			pass
+		else:
+			handlers.remove(signal_handler)
+
+	def signal_emit(self, signal_name, **kw):
+		assert isinstance(signal_name, str)
+		try:
+			handlers = self._signals[signal_name]
+		except:
+			return
+		if not handlers:
+			return
+
+		signal = Signal(origin=self, name=signal_name, **kw)
+
+		for handler in handlers:  # propagate
+			if handler.active:
+				if handler.pass_signal:
+					handler.function(signal)
+				else:
+					handler.function()
+				if signal.stopped:
+					return