summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/ext/signal_dispatcher.py53
-rw-r--r--test/tc_signal.py44
2 files changed, 96 insertions, 1 deletions
diff --git a/ranger/ext/signal_dispatcher.py b/ranger/ext/signal_dispatcher.py
index 542fb472..95bc11f3 100644
--- a/ranger/ext/signal_dispatcher.py
+++ b/ranger/ext/signal_dispatcher.py
@@ -13,6 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+import re
+
 class Signal(dict):
 	stopped = False
 	def __init__(self, **keywords):
@@ -25,6 +27,7 @@ class Signal(dict):
 
 class SignalHandler(object):
 	active = True
+	regexp = None
 	def __init__(self, signal_name, function, priority, pass_signal):
 		self.priority = max(0, min(1, priority))
 		self.signal_name = signal_name
@@ -77,3 +80,53 @@ class SignalDispatcher(object):
 					handler.function()
 				if signal.stopped:
 					return
+
+class RegexpSignalDispatcher(SignalDispatcher):
+	"""
+	A subclass of SignalDispatcher with regexp matching.
+	"""
+
+	def __init__(self):
+		SignalDispatcher.__init__(self)
+		self._signal_regexes = list()
+	_signal_clear = __init__
+
+	def signal_bind(self, signal_name, function, priority=0.5):
+		try:
+			handlers = self._signals[signal_name]
+		except:
+			handlers = self._signals[signal_name] = []
+			for handler in self._signal_regexes:
+				if handler.regexp.match(signal_name):
+					handlers.append(handler)
+		return SignalDispatcher.signal_bind(self, signal_name, \
+				function, priority)
+
+	def signal_bind_regexp(self, regexp, function, priority=0.5):
+		if isinstance(regexp, str):
+			regexp = re.compile(regexp)
+		handler = self.signal_bind('dynamic', function, priority)
+		handler.regexp = regexp
+		self._signal_regexes.append(handler)
+		for signal_name, handlers in self._signals.items():
+			if regexp.match(signal_name):
+				handlers.append(handler)
+			handlers.sort(key=lambda handler: -handler.priority)
+		return handler
+
+	def signal_unbind(self, handler):
+		self._signal_regexes.remove(handler)
+		for handlers in self._signals.values():
+			try:
+				handlers.remove(handler)
+			except ValueError:
+				pass
+
+	def signal_emit(self, signal_name, **kw):
+		assert isinstance(signal_name, str)
+		if not signal_name in self._signals:
+			handlers = self._signals[signal_name] = []
+			for handler in self._signal_regexes:
+				if handler.regexp.match(signal_name):
+					handlers.append(handler)
+		SignalDispatcher.signal_emit(self, signal_name, **kw)
diff --git a/test/tc_signal.py b/test/tc_signal.py
index 67625505..a585a86b 100644
--- a/test/tc_signal.py
+++ b/test/tc_signal.py
@@ -15,7 +15,7 @@
 
 if __name__ == '__main__': from __init__ import init; init()
 import unittest
-from ranger.ext.signal_dispatcher import SignalDispatcher
+from ranger.ext.signal_dispatcher import *
 
 class TestSignal(unittest.TestCase):
 	def setUp(self):
@@ -75,5 +75,47 @@ class TestSignal(unittest.TestCase):
 		sd.signal_emit('setnumber', number=100)
 		self.assertEqual(None, lst[-1])
 
+	def test_regexp_signals(self):
+		sd = RegexpSignalDispatcher()
+		lst = []
+		def modify(s):
+			s.number = 5
+		def set_number(s):
+			lst.append(s.number)
+		def stopit(s):
+			s.stop()
+
+		h1 = sd.signal_bind_regexp('.*ar', modify, priority=1)
+
+		sd.signal_bind('xyz', set_number)
+		sd.signal_bind('foobar', set_number)
+
+		sd.signal_emit('xyz', number=10)
+		self.assertEqual(10, lst[-1])
+		sd.signal_emit('foobar', number=10)
+		self.assertEqual(5, lst[-1])
+
+		h2 = sd.signal_bind_regexp('x.z', modify, priority=1)
+#		print(sd._signals)
+
+		sd.signal_emit('xyz', number=10)
+		self.assertEqual(5, lst[-1])
+		sd.signal_emit('foobar', number=10)
+		self.assertEqual(5, lst[-1])
+
+		sd.signal_unbind(h2)
+
+		sd.signal_emit('xyz', number=10)
+		self.assertEqual(10, lst[-1])
+		sd.signal_emit('foobar', number=10)
+		self.assertEqual(5, lst[-1])
+
+		sd.signal_unbind(h1)
+
+		sd.signal_emit('xyz', number=10)
+		self.assertEqual(10, lst[-1])
+		sd.signal_emit('foobar', number=10)
+		self.assertEqual(10, lst[-1])
+
 if __name__ == '__main__':
 	unittest.main()
ram <vc@akkartik.com> 2018-10-21 20:36:43 -0700 4712' href='/akkartik/mu/commit/subx/opcodes?h=hlt&id=417a05ee7dbecbf846c54cd1e186e000415fb0a3'>417a05ee ^
62a3c1b4 ^
f9f419af ^

bb3ce6cd ^

f15fcfe8 ^

bb3ce6cd ^





4c3a867b ^

15655a12 ^

4c3a867b ^





417a05ee ^
bb3ce6cd ^


f13576b5 ^
bb3ce6cd ^









924ed08a ^
417a05ee ^


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136