summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/container/environment.py4
-rw-r--r--ranger/container/keybuffer.py57
-rw-r--r--ranger/defaults/keys.py39
-rw-r--r--ranger/gui/ui.py9
-rw-r--r--ranger/gui/widgets/console.py2
5 files changed, 92 insertions, 19 deletions
diff --git a/ranger/container/environment.py b/ranger/container/environment.py
index b766a4c9..1b26d48e 100644
--- a/ranger/container/environment.py
+++ b/ranger/container/environment.py
@@ -36,11 +36,11 @@ class Environment(SettingsAware):
 	def key_append(self, key):
 		"""Append a key to the keybuffer"""
 		from ranger import log
-		self.keybuffer = KeyBuffer(self.keybuffer + (key, ))
+		self.keybuffer.append(key)
 
 	def key_clear(self):
 		"""Clear the keybuffer"""
-		self.keybuffer = KeyBuffer()
+		self.keybuffer.clear()
 	
 	def at_level(self, level):
 		"""Returns the FileSystemObject at the given level.
diff --git a/ranger/container/keybuffer.py b/ranger/container/keybuffer.py
index 10c9c40c..048a5083 100644
--- a/ranger/container/keybuffer.py
+++ b/ranger/container/keybuffer.py
@@ -1,11 +1,56 @@
-class KeyBuffer(tuple):
-	"""Extension of tuple suited to be used as a keybuffer"""
-	def __str__(self):
-		"""returns a concatenation of all characters"""
-		return "".join( map( to_string, self ) )
-
 def to_string(i):
 	try:
 		return chr(i)
 	except ValueError:
 		return '?'
+
+from collections import deque
+from curses.ascii import ascii
+
+ZERO = ord('0')
+NINE = ord('9')
+
+class KeyBuffer(object):
+	def __init__(self):
+		self.number = None
+		self.queue = deque()
+		self.queue_with_numbers = deque()
+	
+	def clear(self):
+		"""Clear the keybuffer and restore the initial state"""
+		self.number = None
+		self.queue.clear()
+		self.queue_with_numbers.clear()
+	
+	def append(self, key):
+		"""
+		Append a key to the keybuffer, or initial numbers to
+		the number attribute.
+		"""
+		self.queue_with_numbers.append(key)
+
+		if not self.queue and key >= ZERO and key <= NINE:
+			if self.number is None:
+				self.number = 0
+			try:
+				self.number = self.number * 10 + int(chr(key))
+			except ValueError:
+				return
+		else:
+			self.queue.append(key)
+	
+	def tuple_with_numbers(self):
+		"""Get a tuple of ascii codes."""
+		return tuple(self.queue_with_numbers)
+
+	def tuple_without_numbers(self):
+		"""
+		Get a tuple of ascii codes.
+		If the keybuffer starts with numbers, those will
+		be left out. To access them, use keybuffer.number
+		"""
+		return tuple(self.queue)
+
+	def __str__(self):
+		"""returns a concatenation of all characters"""
+		return "".join( map( to_string, self.queue_with_numbers ) )
diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py
index 98ecd6c1..e3be795d 100644
--- a/ranger/defaults/keys.py
+++ b/ranger/defaults/keys.py
@@ -1,12 +1,10 @@
 import curses
 from curses.ascii import *
 from ranger import RANGERDIR
+from ranger import log
 from ranger.gui.widgets.console import Console
 from ranger.container.bookmarks import ALLOWED_KEYS as ALLOWED_BOOKMARK_KEYS
 
-def do(method, *args, **kw):
-	return lambda fm: getattr(fm, method)(*args, **kw)
-
 # syntax for binding keys: bind(*keys, fnc)
 # fnc is a function which is called with the FM instance,
 # keys are one or more key-combinations which are either:
@@ -20,6 +18,9 @@ def do(method, *args, **kw):
 def initialize_commands(command_list):
 	"""Initialize the commands for the main user interface"""
 
+	def do(method, *args, **kw):
+		return lambda fm, n: getattr(fm, method)(*args, **kw)
+
 	def bind(*args):
 		command_list.bind(args[-1], *args[:-1])
 
@@ -28,15 +29,12 @@ def initialize_commands(command_list):
 	bind(curses.KEY_ENTER, ctrl('j'), do('move_right', mode=1))
 	bind('H', do('history_go', -1))
 	bind('L', do('history_go',  1))
-	bind('j', do('move_pointer', relative = 1))
 	bind('J', do('move_pointer_by_pages', 0.5))
-	bind('k', do('move_pointer', relative = -1))
 	bind('K', do('move_pointer_by_pages', -0.5))
-	bind('gg', do('move_pointer', absolute = 0))
-	bind('G', do('move_pointer', absolute = -1))
 	bind('E', do('edit_file'))
 	bind('o', do('force_load_preview'))
 
+
 	bind('yy', 'cp', do('copy'))
 	bind('cut', do('cut'))
 	bind('p', do('paste'))
@@ -85,11 +83,33 @@ def initialize_commands(command_list):
 	bind('!', do('open_console', '!'))
 	bind('r', do('open_console', '@'))
 
-	def test(fm):
+
+	# definitions which require their own function:
+	def test(fm, n):
 		from ranger import log
 		log(fm.bookmarks.dct)
 	bind('x', test)
 
+	def ggG(default):
+		# moves to an absolute point, or to a predefined default
+		# if no number is specified.
+		return lambda fm, n: \
+				fm.move_pointer(absolute=(n or default))
+
+	bind('gg', ggG(0))
+	bind('G', ggG(-1))
+
+	bind('%', lambda fm, n: fm.move_pointer_by_percentage(absolute=n or 0))
+
+	def jk(direction):
+		# moves up or down by the specified number or one, in
+		# the predefined direction
+		return lambda fm, n: \
+				fm.move_pointer(relative=(n or 1) * direction)
+
+	bind('j', jk(1))
+	bind('k', jk(-1))
+
 	command_list.rebuild_paths()
 
 
@@ -99,6 +119,9 @@ def initialize_console_commands(command_list):
 	def bind(*args):
 		command_list.bind(args[-1], *args[:-1])
 
+	def do(method, *args, **kw):
+		return lambda fm: getattr(fm, method)(*args, **kw)
+
 	def do_fm(method, *args, **kw):
 		return lambda con: getattr(con.fm, method)(*args, **kw)
 
diff --git a/ranger/gui/ui.py b/ranger/gui/ui.py
index da633698..cdb58ad5 100644
--- a/ranger/gui/ui.py
+++ b/ranger/gui/ui.py
@@ -111,7 +111,12 @@ class UI(DisplayableContainer):
 			return
 
 		try:
-			cmd = self.commandlist[tuple(self.env.keybuffer)]
+			tup = self.env.keybuffer.tuple_without_numbers()
+
+			if tup:
+				cmd = self.commandlist[tup]
+			else:
+				return
 		except KeyError:
 			self.env.key_clear()
 			return
@@ -119,7 +124,7 @@ class UI(DisplayableContainer):
 		if cmd == self.commandlist.dummy_object:
 			return
 
-		cmd.execute(self.fm)
+		cmd.execute(self.fm, self.env.keybuffer.number)
 		self.env.key_clear()
 
 	def get_next_key(self):
diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py
index bed9f031..f2c15426 100644
--- a/ranger/gui/widgets/console.py
+++ b/ranger/gui/widgets/console.py
@@ -79,7 +79,7 @@ class Console(Widget):
 		from curses.ascii import ctrl, ESC
 
 		try:
-			cmd = self.commandlist[self.env.keybuffer]
+			cmd = self.commandlist[self.env.keybuffer.tuple_with_numbers()]
 		except KeyError:
 			self.env.key_clear()
 			return
a> ^
4cdbd52 ^
238dd5d ^
4cdbd52 ^









879241c ^





















6d5f67a ^


5a03daf ^
6d5f67a ^



6d5f67a ^




















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
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185