summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/container/__init__.py3
-rw-r--r--ranger/container/keybuffer.py176
-rw-r--r--ranger/container/keymap.py163
-rw-r--r--ranger/ext/keybinding_parser.py2
-rw-r--r--test/tc_newkeys.py1
5 files changed, 182 insertions, 163 deletions
diff --git a/ranger/container/__init__.py b/ranger/container/__init__.py
index c1bb8194..3351cc63 100644
--- a/ranger/container/__init__.py
+++ b/ranger/container/__init__.py
@@ -17,5 +17,6 @@
 used to manage stored data
 """
 from ranger.container.history import History
-from .keymap import KeyMap, KeyBuffer, KeyManager
+from .keymap import KeyMap, KeyManager
+from .keybuffer import KeyBuffer
 from .bookmarks import Bookmarks
diff --git a/ranger/container/keybuffer.py b/ranger/container/keybuffer.py
new file mode 100644
index 00000000..50914f84
--- /dev/null
+++ b/ranger/container/keybuffer.py
@@ -0,0 +1,176 @@
+# 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/>.
+
+import curses.ascii
+from collections import deque
+from string import digits
+from ranger.ext.keybinding_parser import parse_keybinding, \
+		DIRKEY, ANYKEY, PASSIVE_ACTION
+from ranger.container.keymap import Binding, KeyMap
+
+MAX_ALIAS_RECURSION = 20
+
+class KeyBuffer(object):
+	"""The evaluator and storage for pressed keys"""
+	def __init__(self, keymap, direction_keys):
+		self.assign(keymap, direction_keys)
+
+	def assign(self, keymap, direction_keys):
+		self.keymap = keymap
+		self.direction_keys = direction_keys
+
+	def add(self, key):
+		assert isinstance(key, int)
+		assert key >= 0
+		self.all_keys.append(key)
+		self.key_queue.append(key)
+		while self.key_queue:
+			key = self.key_queue.popleft()
+
+			# evaluate quantifiers
+			if self.eval_quantifier and self._do_eval_quantifier(key):
+				return
+
+			# evaluate the command
+			if self.eval_command and self._do_eval_command(key):
+				return
+
+			# evaluate (the first number of) the direction-quantifier
+			if self.eval_quantifier and self._do_eval_quantifier(key):
+				return
+
+			# evaluate direction keys {j,k,gg,pagedown,...}
+			if not self.eval_command:
+				self._do_eval_direction(key)
+
+	def _do_eval_direction(self, key):
+		try:
+			assert isinstance(self.dir_tree_pointer, dict)
+			self.dir_tree_pointer = self.dir_tree_pointer[key]
+		except KeyError:
+			self.failure = True
+		else:
+			self._direction_try_to_finish()
+
+	def _direction_try_to_finish(self):
+		if self.max_alias_recursion <= 0:
+			self.failure = True
+			return None
+		match = self.dir_tree_pointer
+		assert isinstance(match, (Binding, dict, KeyMap))
+		if isinstance(match, KeyMap):
+			self.dir_tree_pointer = self.dir_tree_pointer._tree
+			match = self.dir_tree_pointer
+		if isinstance(self.dir_tree_pointer, Binding):
+			if match.alias:
+				self.key_queue.extend(parse_keybinding(match.alias))
+				self.dir_tree_pointer = self.direction_keys._tree
+				self.max_alias_recursion -= 1
+			else:
+				direction = match.actions['dir'].copy()
+				if self.direction_quant is not None:
+					direction.multiply(self.direction_quant)
+				self.directions.append(direction)
+				self.direction_quant = None
+				self.eval_command = True
+				self._try_to_finish()
+
+	def _do_eval_quantifier(self, key):
+		if self.eval_command:
+			tree = self.tree_pointer
+		else:
+			tree = self.dir_tree_pointer
+		if chr(key) in digits and ANYKEY not in tree:
+			attr = self.eval_command and 'quant' or 'direction_quant'
+			if getattr(self, attr) is None:
+				setattr(self, attr, 0)
+			setattr(self, attr, getattr(self, attr) * 10 + key - 48)
+		else:
+			self.eval_quantifier = False
+			return None
+		return True
+
+	def _do_eval_command(self, key):
+		assert isinstance(self.tree_pointer, dict), self.tree_pointer
+		try:
+			self.tree_pointer = self.tree_pointer[key]
+		except TypeError:
+			self.failure = True
+			return None
+		except KeyError:
+			try:
+				chr(key) in digits or self.direction_keys._tree[key]
+				self.tree_pointer = self.tree_pointer[DIRKEY]
+			except KeyError:
+				try:
+					self.tree_pointer = self.tree_pointer[ANYKEY]
+				except KeyError:
+					self.failure = True
+					return None
+				else:
+					self.matches.append(key)
+					assert isinstance(self.tree_pointer, (Binding, dict))
+					self._try_to_finish()
+			else:
+				assert isinstance(self.tree_pointer, (Binding, dict))
+				self.eval_command = False
+				self.eval_quantifier = True
+				self.dir_tree_pointer = self.direction_keys._tree
+		else:
+			if isinstance(self.tree_pointer, dict):
+				try:
+					self.command = self.tree_pointer[PASSIVE_ACTION]
+				except (KeyError, TypeError):
+					self.command = None
+			self._try_to_finish()
+
+	def _try_to_finish(self):
+		if self.max_alias_recursion <= 0:
+			self.failure = True
+			return None
+		assert isinstance(self.tree_pointer, (Binding, dict, KeyMap))
+		if isinstance(self.tree_pointer, KeyMap):
+			self.tree_pointer = self.tree_pointer._tree
+		if isinstance(self.tree_pointer, Binding):
+			if self.tree_pointer.alias:
+				keys = parse_keybinding(self.tree_pointer.alias)
+				self.key_queue.extend(keys)
+				self.tree_pointer = self.keymap._tree
+				self.max_alias_recursion -= 1
+			else:
+				self.command = self.tree_pointer
+				self.done = True
+
+	def clear(self):
+		self.max_alias_recursion = MAX_ALIAS_RECURSION
+		self.failure = False
+		self.done = False
+		self.quant = None
+		self.matches = []
+		self.command = None
+		self.direction_quant = None
+		self.directions = []
+		self.all_keys = []
+		self.tree_pointer = self.keymap._tree
+		self.dir_tree_pointer = self.direction_keys._tree
+
+		self.key_queue = deque()
+
+		self.eval_quantifier = True
+		self.eval_command = True
+
+	def __str__(self):
+		"""returns a concatenation of all characters"""
+		return "".join("{0:c}".format(c) for c in self.all_keys)
diff --git a/ranger/container/keymap.py b/ranger/container/keymap.py
index 60272be0..167ba160 100644
--- a/ranger/container/keymap.py
+++ b/ranger/container/keymap.py
@@ -13,16 +13,10 @@
 # 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 curses.ascii
-from collections import deque
-from string import digits
-from inspect import isfunction, getargspec
 from ranger.ext.tree import Tree
 from ranger.ext.direction import Direction
-from ranger.ext.keybinding_parser import parse_keybinding, \
-		DIRKEY, ANYKEY, PASSIVE_ACTION
+from ranger.ext.keybinding_parser import parse_keybinding, DIRKEY, ANYKEY
 
-MAX_ALIAS_RECURSION = 20
 FUNC = 'func'
 DIRARG = 'dir'
 ALIASARG = 'alias'
@@ -52,7 +46,7 @@ class KeyMap(Tree):
 		if keywords:
 			return self._add_binding(*args, **keywords)
 		firstarg = args[-1]
-		if isfunction(firstarg):
+		if hasattr(firstarg, '__call__'):
 			keywords[FUNC] = firstarg
 			return self._add_binding(*args[:-1], **keywords)
 		def decorator_function(func):
@@ -151,156 +145,3 @@ class Binding(object):
 			self.alias = None
 		else:
 			self.alias = tuple(parse_keybinding(alias))
-
-class KeyBuffer(object):
-	"""The evaluator and storage for pressed keys"""
-	def __init__(self, keymap, direction_keys):
-		self.assign(keymap, direction_keys)
-
-	def assign(self, keymap, direction_keys):
-		self.keymap = keymap
-		self.direction_keys = direction_keys
-
-	def add(self, key):
-		assert isinstance(key, int)
-		assert key >= 0
-		self.all_keys.append(key)
-		self.key_queue.append(key)
-		while self.key_queue:
-			key = self.key_queue.popleft()
-
-			# evaluate quantifiers
-			if self.eval_quantifier and self._do_eval_quantifier(key):
-				return
-
-			# evaluate the command
-			if self.eval_command and self._do_eval_command(key):
-				return
-
-			# evaluate (the first number of) the direction-quantifier
-			if self.eval_quantifier and self._do_eval_quantifier(key):
-				return
-
-			# evaluate direction keys {j,k,gg,pagedown,...}
-			if not self.eval_command:
-				self._do_eval_direction(key)
-
-	def _do_eval_direction(self, key):
-		try:
-			assert isinstance(self.dir_tree_pointer, dict)
-			self.dir_tree_pointer = self.dir_tree_pointer[key]
-		except KeyError:
-			self.failure = True
-		else:
-			self._direction_try_to_finish()
-
-	def _direction_try_to_finish(self):
-		if self.max_alias_recursion <= 0:
-			self.failure = True
-			return None
-		match = self.dir_tree_pointer
-		assert isinstance(match, (Binding, dict, KeyMap))
-		if isinstance(match, KeyMap):
-			self.dir_tree_pointer = self.dir_tree_pointer._tree
-			match = self.dir_tree_pointer
-		if isinstance(self.dir_tree_pointer, Binding):
-			if match.alias:
-				self.key_queue.extend(parse_keybinding(match.alias))
-				self.dir_tree_pointer = self.direction_keys._tree
-				self.max_alias_recursion -= 1
-			else:
-				direction = match.actions['dir'].copy()
-				if self.direction_quant is not None:
-					direction.multiply(self.direction_quant)
-				self.directions.append(direction)
-				self.direction_quant = None
-				self.eval_command = True
-				self._try_to_finish()
-
-	def _do_eval_quantifier(self, key):
-		if self.eval_command:
-			tree = self.tree_pointer
-		else:
-			tree = self.dir_tree_pointer
-		if chr(key) in digits and ANYKEY not in tree:
-			attr = self.eval_command and 'quant' or 'direction_quant'
-			if getattr(self, attr) is None:
-				setattr(self, attr, 0)
-			setattr(self, attr, getattr(self, attr) * 10 + key - 48)
-		else:
-			self.eval_quantifier = False
-			return None
-		return True
-
-	def _do_eval_command(self, key):
-		assert isinstance(self.tree_pointer, dict), self.tree_pointer
-		try:
-			self.tree_pointer = self.tree_pointer[key]
-		except TypeError:
-			self.failure = True
-			return None
-		except KeyError:
-			try:
-				chr(key) in digits or self.direction_keys._tree[key]
-				self.tree_pointer = self.tree_pointer[DIRKEY]
-			except KeyError:
-				try:
-					self.tree_pointer = self.tree_pointer[ANYKEY]
-				except KeyError:
-					self.failure = True
-					return None
-				else:
-					self.matches.append(key)
-					assert isinstance(self.tree_pointer, (Binding, dict))
-					self._try_to_finish()
-			else:
-				assert isinstance(self.tree_pointer, (Binding, dict))
-				self.eval_command = False
-				self.eval_quantifier = True
-				self.dir_tree_pointer = self.direction_keys._tree
-		else:
-			if isinstance(self.tree_pointer, dict):
-				try:
-					self.command = self.tree_pointer[PASSIVE_ACTION]
-				except (KeyError, TypeError):
-					self.command = None
-			self._try_to_finish()
-
-	def _try_to_finish(self):
-		if self.max_alias_recursion <= 0:
-			self.failure = True
-			return None
-		assert isinstance(self.tree_pointer, (Binding, dict, KeyMap))
-		if isinstance(self.tree_pointer, KeyMap):
-			self.tree_pointer = self.tree_pointer._tree
-		if isinstance(self.tree_pointer, Binding):
-			if self.tree_pointer.alias:
-				keys = parse_keybinding(self.tree_pointer.alias)
-				self.key_queue.extend(keys)
-				self.tree_pointer = self.keymap._tree
-				self.max_alias_recursion -= 1
-			else:
-				self.command = self.tree_pointer
-				self.done = True
-
-	def clear(self):
-		self.max_alias_recursion = MAX_ALIAS_RECURSION
-		self.failure = False
-		self.done = False
-		self.quant = None
-		self.matches = []
-		self.command = None
-		self.direction_quant = None
-		self.directions = []
-		self.all_keys = []
-		self.tree_pointer = self.keymap._tree
-		self.dir_tree_pointer = self.direction_keys._tree
-
-		self.key_queue = deque()
-
-		self.eval_quantifier = True
-		self.eval_command = True
-
-	def __str__(self):
-		"""returns a concatenation of all characters"""
-		return "".join("{0:c}".format(c) for c in self.all_keys)
diff --git a/ranger/ext/keybinding_parser.py b/ranger/ext/keybinding_parser.py
index 58d8fe5c..c33ac12f 100644
--- a/ranger/ext/keybinding_parser.py
+++ b/ranger/ext/keybinding_parser.py
@@ -13,7 +13,7 @@
 # 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 curses
+import curses.ascii
 from string import ascii_lowercase
 
 def parse_keybinding(obj):
diff --git a/test/tc_newkeys.py b/test/tc_newkeys.py
index 9bfb43b0..8aa043ae 100644
--- a/test/tc_newkeys.py
+++ b/test/tc_newkeys.py
@@ -19,6 +19,7 @@ from unittest import TestCase, main
 
 from ranger.ext.tree import Tree
 from ranger.container.keymap import *
+from ranger.container.keybuffer import KeyBuffer
 from ranger.ext.keybinding_parser import parse_keybinding
 
 import sys