summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorhut <hut@lavabit.com>2010-01-03 20:33:11 +0100
committerhut <hut@lavabit.com>2010-01-03 20:33:11 +0100
commit847010930a11791c87845a011cd968b2f0861155 (patch)
tree1f0718e746b491c545d3e98e0339187d07e3f9c1
parent0b4e0c5bc5a30bfd6a97507eef1b697e57ff27c9 (diff)
downloadranger-847010930a11791c87845a011cd968b2f0861155.tar.gz
keyapi: a different approach to passing through typed numbers
-rw-r--r--ranger/actions.py15
-rw-r--r--ranger/defaults/keys.py60
-rw-r--r--ranger/ext/accumulator.py15
-rw-r--r--ranger/gui/widgets/pager.py15
-rw-r--r--ranger/keyapi.py94
5 files changed, 116 insertions, 83 deletions
diff --git a/ranger/actions.py b/ranger/actions.py
index bc6da7b8..8209c9ab 100644
--- a/ranger/actions.py
+++ b/ranger/actions.py
@@ -137,10 +137,10 @@ class Actions(EnvironmentAware, SettingsAware):
 		"""Delete the bookmark with the name <key>"""
 		self.bookmarks.delete(key)
 
-	def move_left(self, n=1):
+	def move_left(self, narg=1):
 		"""Enter the parent directory"""
 		try:
-			directory = os.path.join(*(['..'] * n))
+			directory = os.path.join(*(['..'] * narg))
 		except:
 			return
 		self.env.enter_dir(directory)
@@ -237,20 +237,25 @@ class Actions(EnvironmentAware, SettingsAware):
 		if hasattr(self.ui, 'open_console'):
 			self.ui.open_console(mode, string)
 
-	def move_pointer(self, relative = 0, absolute = None):
+	def move_pointer(self, relative = 0, absolute = None, narg=None):
 		"""Move the pointer down by <relative> or to <absolute>"""
-		self.env.pwd.move(relative, absolute)
+		self.env.pwd.move(relative=relative,
+				absolute=absolute, narg=narg)
 
 	def move_pointer_by_pages(self, relative):
 		"""Move the pointer down by <relative> pages"""
 		self.env.pwd.move(relative=int(relative * self.env.termsize[0]))
 
-	def move_pointer_by_percentage(self, relative=0, absolute=None):
+	def move_pointer_by_percentage(self, relative=0, absolute=None, narg=None):
 		"""Move the pointer down by <relative>% or to <absolute>%"""
 		try:
 			factor = len(self.env.pwd) / 100.0
 		except:
 			return
+
+		if narg is not None:
+			absolute = narg
+
 		self.env.pwd.move(
 				relative=int(relative * factor),
 				absolute=int(absolute * factor))
diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py
index 5f7691e2..02438cbc 100644
--- a/ranger/defaults/keys.py
+++ b/ranger/defaults/keys.py
@@ -26,6 +26,7 @@ def system_functions(command_list):
 
 	bind(KEY_RESIZE, fm.resize())
 	bind(KEY_MOUSE, fm.handle_mouse())
+	bind('Q', fm.exit())
 	bind(ctrl('L'), fm.redraw_window())
 
 def initialize_commands(command_list):
@@ -33,7 +34,15 @@ def initialize_commands(command_list):
 
 	bind, hint = make_abbreviations(command_list)
 
+	bind('j', KEY_DOWN, fm.move_pointer(relative=1))
+	bind('k', KEY_UP, fm.move_pointer(relative=-1))
 	bind('l', KEY_RIGHT, fm.move_right())
+	bind('h', KEY_LEFT, KEY_BACKSPACE, DEL, fm.move_left(1))
+
+	bind('gg', fm.move_pointer(absolute=0))
+	bind('G', fm.move_pointer(absolute=-1))
+	bind('%', fm.move_pointer_by_percentage(absolute=50))
+
 	bind(KEY_END, fm.move_pointer(absolute=-1))
 	bind(KEY_HOME, fm.move_pointer(absolute=0))
 	bind(KEY_ENTER, ctrl('j'), fm.move_right(mode=1))
@@ -132,7 +141,7 @@ def initialize_commands(command_list):
 
 	# system functions
 	system_functions(command_list)
-	bind('Q', 'ZZ', fm.exit())
+	bind('ZZ', fm.exit())
 	bind(ctrl('R'), fm.reset())
 	bind(ctrl('C'), fm.interrupt())
 	bind(':', ';', fm.open_console(cmode.COMMAND))
@@ -143,29 +152,6 @@ def initialize_commands(command_list):
 	bind('r', fm.open_console(cmode.OPEN_QUICK))
 
 	# definitions which require their own function:
-	def ggG(default):
-		# moves to an absolute point, or to a predefined default
-		# if no number is specified.
-		return lambda arg: \
-				arg.fm.move_pointer(absolute=(arg.n or default)-1)
-
-	bind('gg', ggG(1))
-	bind('G', ggG(0))
-
-	bind('%', lambda arg: \
-			arg.fm.move_pointer_by_percentage(absolute=arg.n or 50))
-
-	def jk(direction):
-		# moves up or down by the specified number or one, in
-		# the predefined direction
-		return lambda arg: \
-				arg.fm.move_pointer(relative=(arg.n or 1) * direction)
-
-	bind('j', KEY_DOWN, jk(1))
-	bind('k', KEY_UP, jk(-1))
-
-	bind('h', KEY_LEFT, KEY_BACKSPACE, DEL, lambda arg: \
-			arg.fm.move_left(arg.n or 1))
 
 	bind('w', lambda arg: arg.fm.ui.open_taskview())
 
@@ -214,15 +200,15 @@ def initialize_taskview_commands(command_list):
 	system_functions(command_list)
 	bind, hint = make_abbreviations(command_list)
 
-	bind('j', KEY_DOWN, nwrap.move(relative=1))
-	bind('k', KEY_UP, nwrap.move(relative=-1))
-	bind('gg', nwrap.move(absolute=0))
-	bind('G', nwrap.move(absolute=-1))
+	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('K', wdg.task_move(0))
 	bind('J', wdg.task_move(-1))
 
 	bind('dd', wdg.task_remove())
-	bind('w', ESC, ctrl('d'), ctrl('c'),
+	bind('w', 'q', ESC, ctrl('d'), ctrl('c'),
 			lambda arg: arg.fm.ui.close_taskview())
 
 	command_list.rebuild_paths()
@@ -238,14 +224,14 @@ def initialize_embedded_pager_commands(command_list):
 	system_functions(command_list)
 	bind, hint = make_abbreviations(command_list)
 
-	bind('j', KEY_DOWN, nwrap.move(relative=1))
-	bind('k', KEY_UP, nwrap.move(relative=-1))
-	bind('gg', KEY_HOME, nwrap.move(absolute=0))
-	bind('G', KEY_END, nwrap.move(absolute=-1))
-	bind('J', ctrl('d'), nwrap.move(relative=0.5, pages=True))
-	bind('K', ctrl('u'), nwrap.move(relative=-0.5, pages=True))
-	bind(KEY_NPAGE, ctrl('f'), nwrap.move(relative=1, pages=True))
-	bind(KEY_PPAGE, ctrl('b'), nwrap.move(relative=-1, pages=True))
+	bind('j', KEY_DOWN, wdg.move(relative=1))
+	bind('k', KEY_UP, wdg.move(relative=-1))
+	bind('gg', KEY_HOME, wdg.move(absolute=0))
+	bind('G', KEY_END, wdg.move(absolute=-1))
+	bind('J', ctrl('d'), wdg.move(relative=0.5, pages=True))
+	bind('K', ctrl('u'), wdg.move(relative=-0.5, pages=True))
+	bind(KEY_NPAGE, ctrl('f'), wdg.move(relative=1, pages=True))
+	bind(KEY_PPAGE, ctrl('b'), wdg.move(relative=-1, pages=True))
 	bind('E', fm.edit_file())
 
 	bind('h', wdg.move_horizontal(relative=-4))
diff --git a/ranger/ext/accumulator.py b/ranger/ext/accumulator.py
index 6513bee2..5aee54de 100644
--- a/ranger/ext/accumulator.py
+++ b/ranger/ext/accumulator.py
@@ -3,7 +3,7 @@ class Accumulator(object):
 		self.pointer = 0
 		self.pointed_obj = None
 
-	def move(self, relative=0, absolute=None, pages=False):
+	def move(self, relative=0, absolute=None, pages=None, narg=None):
 		i = self.pointer
 		lst = self.get_list()
 		if not lst:
@@ -11,16 +11,19 @@ class Accumulator(object):
 		length = len(lst)
 
 		if isinstance(absolute, int):
+			if isinstance(narg, int):
+				absolute = narg
 			if absolute < 0: # wrap
 				i = absolute + length
 			else:
 				i = absolute
 
-		if pages:
-			i += relative * self.get_height()
-		else:
-			i += relative
-		i = int(i)
+		if relative != 0:
+			if isinstance(pages, int):
+				relative *= pages * self.get_height()
+			if isinstance(narg, int):
+				relative *= narg
+		i = int(i + relative)
 
 		if i >= length:
 			i = length - 1
diff --git a/ranger/gui/widgets/pager.py b/ranger/gui/widgets/pager.py
index 0e13ecbd..5e9ef3c8 100644
--- a/ranger/gui/widgets/pager.py
+++ b/ranger/gui/widgets/pager.py
@@ -60,19 +60,22 @@ class Pager(Widget):
 					pass
 			self.need_redraw = False
 	
-	def move(self, relative=0, absolute=None, pages=False):
+	def move(self, relative=0, absolute=None, pages=None, narg=None):
 		i = self.scroll_begin
 		if isinstance(absolute, int):
+			if isinstance(narg, int):
+				absolute = narg
 			if absolute < 0:
 				i = absolute + len(self.lines)
 			else:
 				i = absolute
 
-		if pages:
-			i += relative * self.hei
-		else:
-			i += relative
-		i = int(i)
+		if relative != 0:
+			if isinstance(pages, int):
+				relative *= pages * self.hei
+			if isinstance(narg, int):
+				relative *= narg
+		i = int(i + relative)
 
 		length = len(self.lines) - self.hei
 		if i >= length:
diff --git a/ranger/keyapi.py b/ranger/keyapi.py
index 82f1495d..e5d6f367 100644
--- a/ranger/keyapi.py
+++ b/ranger/keyapi.py
@@ -1,5 +1,7 @@
 from curses import *
 from curses.ascii import *
+from inspect import getargspec, ismethod
+
 from ranger import RANGERDIR
 from ranger.gui.widgets import console_mode as cmode
 from ranger.container.bookmarks import ALLOWED_KEYS as ALLOWED_BOOKMARK_KEYS
@@ -18,18 +20,18 @@ class Wrapper(object):
 		self.__firstattr__ = firstattr
 
 	def __getattr__(self, attr):
-		def wrapper(*args, **keywords):
-			def bla(command_argument):
+		def wrapper(*real_args, **real_keywords):
+			def function(command_argument):
+				args, kws = real_args, real_keywords
+				number = command_argument.n
 				obj = getattr(command_argument, self.__firstattr__)
-				if obj is None:
-					return
-				return getattr(obj, attr)(*args, **keywords)
-			return bla
+				fnc = getattr(obj, attr)
+				if number is not None:
+					args, kws = replace_narg(number, fnc, args, kws)
+				return fnc(*args, **kws)
+			return function
 		return wrapper
 
-fm = Wrapper('fm')
-wdg = Wrapper('wdg')
-
 # fm.enter_dir('~') is translated into lambda arg: arg.fm.enter_dir('~')
 # this makes things like this possible:
 # bind('gh', fm.enter_dir('~'))
@@ -39,25 +41,59 @@ wdg = Wrapper('wdg')
 #
 # for something like that, use the long version:
 # bind('H', lambda arg: arg.fm.history.go(-1))
+#
+# If the method has an argument named "narg", pressing a number before
+# the key will pass that number as the narg argument. If you want the
+# same behaviour in a custom lambda function, you can write:
+# bind('gg', fm.move_pointer(absolute=0))
+# as:
+# bind('gg', lambda arg: narg(arg.n, arg.fm.move_pointer, absolute=0))
+
+fm = Wrapper('fm')
+wdg = Wrapper('wdg')
+
+
+NARG_KEYWORD = 'narg'
+
+def narg(number_, function_, *args_, **keywords_):
+	"""
+	This applies the replace_narg function to the arguments and keywords
+	and directly runs this function.
+
+	Example:
+	def foo(xyz, narg): return hash((xyz, narg))
+
+	narg(50, foo, 123) == foo(123, narg=50)
+	"""
+	args, keywords = replace_narg(number_, function_, args_, keywords_)
+	print(args, keywords)
+	return function_(*args, **keywords)
+
+def replace_narg(number, function, args, keywords):
+	"""
+	This function returns (args, keywords) with one little change:
+	if <function> has a named argument called "narg", args and keywords
+	will be modified so that the value of "narg" will be <number>.
+
+	def foo(xyz, narg): pass
+
+	replace_narg(666, foo, (), {'narg': 10, 'xyz': 5})
+	=> (), {'narg': 666, 'xyz': 5}
 
+	replace_narg(666, foo, (1, 2), {})
+	=> (1, 666), {}
+	"""
+	argspec = getargspec(function).args
+	if NARG_KEYWORD in argspec:
+		try:
+			# is narg in args?
+			args = list(args)
+			index = argspec.index(NARG_KEYWORD)
+			if ismethod(function):
+				index -= 1  # because of 'self'
+			args[index] = number
+		except (ValueError, IndexError):
+			# is narg in keywords?
+			keywords[NARG_KEYWORD] = number
+	return args, keywords
 
-# Another wrapper for common actions which use a numerical argument:
-class nwrap(object):
-	@staticmethod
-	def move(relative=0, absolute=None, pages=False):
-		if absolute is None:
-			def fnc(arg):
-				if arg.n is not None:
-					if relative >= 0:
-						arg.wdg.move(relative=arg.n, pages=pages)
-					else:
-						arg.wdg.move(relative=-arg.n, pages=pages)
-				else:
-					arg.wdg.move(relative=relative, pages=pages)
-		else:
-			def fnc(arg):
-				if arg.n is not None:
-					arg.wdg.move(absolute=arg.n, relative=relative, pages=pages)
-				else:
-					arg.wdg.move(absolute=absolute, relative=relative, pages=pages)
-		return fnc
href='#n400'>400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512