summary refs log tree commit diff stats
path: root/ranger/gui
diff options
context:
space:
mode:
Diffstat (limited to 'ranger/gui')
-rw-r--r--ranger/gui/ui.py77
-rw-r--r--ranger/gui/widgets/browsercolumn.py12
-rw-r--r--ranger/gui/widgets/browserview.py8
-rw-r--r--ranger/gui/widgets/console.py72
-rw-r--r--ranger/gui/widgets/pager.py119
-rw-r--r--ranger/gui/widgets/taskview.py44
6 files changed, 170 insertions, 162 deletions
diff --git a/ranger/gui/ui.py b/ranger/gui/ui.py
index cdaf6cde..41acb39f 100644
--- a/ranger/gui/ui.py
+++ b/ranger/gui/ui.py
@@ -20,8 +20,8 @@ import curses
 import _curses
 
 from .displayable import DisplayableContainer
+from ranger.container.keymap import CommandArgs
 from .mouse_event import MouseEvent
-from ranger.container import CommandList
 
 TERMINALS_WITH_TITLE = ("xterm", "xterm-256color", "rxvt",
 		"rxvt-256color", "rxvt-unicode", "aterm", "Eterm",
@@ -47,7 +47,7 @@ def _setup_mouse(signal):
 class UI(DisplayableContainer):
 	is_set_up = False
 	load_mode = False
-	def __init__(self, commandlist=None, env=None, fm=None):
+	def __init__(self, env=None, fm=None):
 		self._draw_title = os.environ["TERM"] in TERMINALS_WITH_TITLE
 		os.environ['ESCDELAY'] = '25'   # don't know a cleaner way
 
@@ -56,13 +56,9 @@ class UI(DisplayableContainer):
 		if fm is not None:
 			self.fm = fm
 
-
-		if commandlist is None:
-			self.commandlist = CommandList()
-			self.settings.keys.initialize_commands(self.commandlist)
-		else:
-			self.commandlist = commandlist
 		self.win = curses.initscr()
+		self.env.keymanager.use_context('general')
+		self.env.keybuffer.clear()
 
 		DisplayableContainer.__init__(self, None)
 
@@ -136,41 +132,68 @@ class UI(DisplayableContainer):
 		if hasattr(self, 'hint'):
 			self.hint()
 
-		self.env.key_append(key)
+		if key < 0:
+			self.env.keybuffer.clear()
+			return
 
 		if DisplayableContainer.press(self, key):
 			return
 
-		try:
-			tup = self.env.keybuffer.tuple_without_numbers()
+		self.env.keymanager.use_context('general')
+		self.env.key_append(key)
+		kbuf = self.env.keybuffer
+		cmd = kbuf.command
 
-			if tup:
-				cmd = self.commandlist[tup]
-			else:
-				return
-		except KeyError:
-			self.env.key_clear()
+		self.fm.hide_bookmarks()
+
+		if kbuf.failure:
+			kbuf.clear()
+			return
+		elif not cmd:
 			return
 
 		self.env.cmd = cmd
 
-		if hasattr(cmd, 'show_obj') and hasattr(cmd.show_obj, 'hint'):
-			if hasattr(self, 'hint'):
-				self.hint(cmd.show_obj.hint)
-		elif hasattr(cmd, 'execute'):
+		if cmd.function:
 			try:
-				cmd.execute_wrap(self)
+				cmd.function(CommandArgs.from_widget(self.fm))
 			except Exception as error:
 				self.fm.notify(error)
-			self.env.key_clear()
+			if kbuf.done:
+				kbuf.clear()
+		else:
+			kbuf.clear()
 
-	def get_next_key(self):
-		"""Waits for key input and returns the pressed key"""
+	def handle_input(self):
 		key = self.win.getch()
-		if key is not -1:
+		if key is 27 or key >= 128 and key < 256:
+			# Handle special keys like ALT+X or unicode here:
+			keys = [key]
+			previous_load_mode = self.load_mode
+			self.set_load_mode(True)
+			for n in range(4):
+				getkey = self.win.getch()
+				if getkey is not -1:
+					keys.append(getkey)
+			if len(keys) == 1:
+				keys.append(-1)
+			for key in keys:
+				self.handle_key(key)
+			self.set_load_mode(previous_load_mode)
+			if self.settings.flushinput:
+				curses.flushinp()
+		else:
+			# Handle simple key presses, CTRL+X, etc here:
 			if self.settings.flushinput:
 				curses.flushinp()
-		return key
+			if key > 0:
+				if key == curses.KEY_MOUSE:
+					self.handle_mouse()
+				elif key == curses.KEY_RESIZE:
+					self.update_size()
+				else:
+					if not self.fm.input_is_blocked():
+						self.handle_key(key)
 
 	def setup(self):
 		"""
diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py
index 8301d26a..8cf8990c 100644
--- a/ranger/gui/widgets/browsercolumn.py
+++ b/ranger/gui/widgets/browsercolumn.py
@@ -102,7 +102,7 @@ class BrowserColumn(Pager):
 					self.fm.enter_dir(self.target.path)
 
 				if index < len(self.target):
-					self.fm.move_pointer(absolute = index)
+					self.fm.move(to=index)
 			elif event.pressed(3):
 				try:
 					clicked_file = self.target.files[index]
@@ -112,7 +112,7 @@ class BrowserColumn(Pager):
 
 		else:
 			if self.level > 0:
-				self.fm.move_right()
+				self.fm.move(right=0)
 
 		return True
 
@@ -361,11 +361,11 @@ class BrowserColumn(Pager):
 		self.scroll_begin = self._get_scroll_begin()
 		self.target.scroll_begin = self.scroll_begin
 
-	def scroll(self, relative):
-		"""scroll by n lines"""
+	def scroll(self, n):
+		"""scroll down by n lines"""
 		self.need_redraw = True
-		self.target.move(relative=relative)
-		self.target.scroll_begin += 3 * relative
+		self.target.move(down=n)
+		self.target.scroll_begin += 3 * n
 
 	def __str__(self):
 		return self.__class__.__name__ + ' at level ' + str(self.level)
diff --git a/ranger/gui/widgets/browserview.py b/ranger/gui/widgets/browserview.py
index 7f2ea5fb..466e23eb 100644
--- a/ranger/gui/widgets/browserview.py
+++ b/ranger/gui/widgets/browserview.py
@@ -25,6 +25,7 @@ class BrowserView(Widget, DisplayableContainer):
 	ratios = None
 	preview = True
 	preview_available = True
+	draw_bookmarks = False
 	stretch_ratios = None
 	need_clear = False
 
@@ -89,10 +90,9 @@ class BrowserView(Widget, DisplayableContainer):
 		self.need_clear = True
 
 	def draw(self):
-		try:
-			if self.env.cmd.show_obj.draw_bookmarks:
-				self._draw_bookmarks()
-		except AttributeError:
+		if self.draw_bookmarks:
+			self._draw_bookmarks()
+		else:
 			if self.need_clear:
 				self.win.erase()
 				self.need_redraw = True
diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py
index 7a3546e9..a27e1956 100644
--- a/ranger/gui/widgets/console.py
+++ b/ranger/gui/widgets/console.py
@@ -27,6 +27,7 @@ from ranger.defaults import commands
 from ranger.gui.widgets.console_mode import is_valid_mode, mode_to_class
 from ranger import log, relpath_conf
 from ranger.ext.shell_escape import shell_quote
+from ranger.container.keymap import CommandArgs
 from ranger.ext.get_executables import get_executables
 from ranger.ext.direction import Direction
 import ranger
@@ -58,10 +59,8 @@ class Console(Widget):
 	historypaths = []
 
 	def __init__(self, win):
-		from ranger.container import CommandList, History
+		from ranger.container import History
 		Widget.__init__(self, win)
-		self.commandlist = CommandList()
-		self.settings.keys.initialize_console_commands(self.commandlist)
 		self.clear()
 		self.histories = []
 		# load histories from files
@@ -156,38 +155,37 @@ class Console(Widget):
 		self.line = ''
 
 	def press(self, key):
-		from curses.ascii import ctrl, ESC
+		self.env.keymanager.use_context('console')
+		self.env.key_append(key)
+		kbuf = self.env.keybuffer
+		cmd = kbuf.command
 
-		keytuple = self.env.keybuffer.tuple_with_numbers()
-		try:
-			cmd = self.commandlist[keytuple]
-		except KeyError:
-			# An unclean hack to allow unicode input.
-			# This whole part should be replaced.
-			try:
-				chrkey = chr(keytuple[0])
-			except:
-				pass
-			else:
-				self.type_key(chrkey)
-			finally:
-				self.env.key_clear()
-				return
-
-		if cmd == self.commandlist.dummy_object:
+		if kbuf.failure:
+			kbuf.clear()
+			return
+		elif not cmd:
 			return
 
-		try:
-			cmd.execute_wrap(self)
-		except Exception as error:
-			self.fm.notify(error)
-		self.env.key_clear()
+		self.env.cmd = cmd
+
+		if cmd.function:
+			try:
+				cmd.function(CommandArgs.from_widget(self))
+			except Exception as error:
+				self.fm.notify(error)
+			if kbuf.done:
+				kbuf.clear()
+		else:
+			kbuf.clear()
 
 	def type_key(self, key):
 		self.tab_deque = None
 
 		if isinstance(key, int):
-			key = chr(key)
+			try:
+				key = chr(key)
+			except ValueError:
+				return
 
 		if self.pos == len(self.line):
 			self.line += key
@@ -216,14 +214,16 @@ class Console(Widget):
 		self.history.fast_forward()
 		self.history.modify(self.line)
 
-	def move(self, relative = 0, absolute = None):
-		if absolute is not None:
-			if absolute < 0:
-				self.pos = len(self.line) + 1 + absolute
-			else:
-				self.pos = absolute
-
-		self.pos = min(max(0, self.pos + relative), len(self.line))
+	def move(self, **keywords):
+		from ranger import log
+		log(keywords)
+		direction = Direction(keywords)
+		if direction.horizontal():
+			self.pos = direction.move(
+					direction=direction.right(),
+					minimum=0,
+					maximum=len(self.line) + 1,
+					current=self.pos)
 
 	def delete_rest(self, direction):
 		self.tab_deque = None
@@ -262,7 +262,7 @@ class Console(Widget):
 		pos = self.pos + mod
 
 		self.line = self.line[0:pos] + self.line[pos+1:]
-		self.move(relative = mod)
+		self.move(right=mod)
 		self.on_line_change()
 
 	def execute(self):
diff --git a/ranger/gui/widgets/pager.py b/ranger/gui/widgets/pager.py
index 2fc8ecda..85022a01 100644
--- a/ranger/gui/widgets/pager.py
+++ b/ranger/gui/widgets/pager.py
@@ -18,8 +18,8 @@ The pager displays text and allows you to scroll inside it.
 """
 import re
 from . import Widget
-from ranger.container.commandlist import CommandList
-from ranger.ext.move import move_between
+from ranger.ext.direction import Direction
+from ranger.container.keymap import CommandArgs
 
 BAR_REGEXP = re.compile(r'\|\d+\?\|')
 QUOTES_REGEXP = re.compile(r'"[^"]+?"')
@@ -41,14 +41,9 @@ class Pager(Widget):
 		self.markup = None
 		self.lines = []
 
-		self.commandlist = CommandList()
-
-		if embedded:
-			keyfnc = self.settings.keys.initialize_embedded_pager_commands
-		else:
-			keyfnc = self.settings.keys.initialize_pager_commands
-
-		keyfnc(self.commandlist)
+	def move_horizontal(self, *a, **k):
+		"""For compatibility"""
+		self.fm.notify("Your keys.py is out of date. Can't scroll!", bad=True)
 
 	def open(self):
 		self.scroll_begin = 0
@@ -116,68 +111,50 @@ class Pager(Widget):
 			if TITLE_REGEXP.match(line):
 				self.color_at(i, 0, -1, 'title', *baseclr)
 
-
-	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 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:
-			self._get_line(i+self.hei)
-
-		length = len(self.lines) - self.hei
-		if i >= length:
-			i = length
-
-		if i < 0:
-			i = 0
-
-		self.scroll_begin = i
-
-	def move_horizontal(self, relative=0, absolute=None, narg=None):
-		if narg is not None:
-			if absolute is None:
-				relative = relative < 0 and -narg or narg
-			else:
-				absolute = narg
-
-		self.startx = move_between(
-				current=self.startx,
-				minimum=0,
-				maximum=999,
-				relative=relative,
-				absolute=absolute)
+	def move(self, narg=None, **kw):
+		direction = Direction(kw)
+		if direction.horizontal():
+			self.startx = direction.move(
+					direction=direction.right(),
+					override=narg,
+					maximum=self._get_max_width(),
+					current=self.startx,
+					pagesize=self.wid,
+					offset=-self.wid)
+		if direction.vertical():
+			if self.source_is_stream:
+				self._get_line(self.scroll_begin + self.hei * 2)
+			self.scroll_begin = direction.move(
+					direction=direction.down(),
+					override=narg,
+					maximum=len(self.lines),
+					current=self.scroll_begin,
+					pagesize=self.hei,
+					offset=-self.hei)
 
 	def press(self, key):
-		try:
-			tup = self.env.keybuffer.tuple_without_numbers()
-			if tup:
-				cmd = self.commandlist[tup]
-			else:
-				return
+		self.env.keymanager.use_context(self.embedded and 'embedded_pager' or 'pager')
+		self.env.key_append(key)
+		kbuf = self.env.keybuffer
+		cmd = kbuf.command
 
-		except KeyError:
-			self.env.key_clear()
+		if kbuf.failure:
+			kbuf.clear()
+			return
+		elif not cmd:
+			return
+
+		self.env.cmd = cmd
+
+		if cmd.function:
+			try:
+				cmd.function(CommandArgs.from_widget(self))
+			except Exception as error:
+				self.fm.notify(error)
+			if kbuf.done:
+				kbuf.clear()
 		else:
-			if hasattr(cmd, 'execute'):
-				try:
-					cmd.execute_wrap(self)
-				except Exception as error:
-					self.fm.notify(error)
-				self.env.key_clear()
+			kbuf.clear()
 
 	def set_source(self, source, strip=False):
 		if self.source and self.source_is_stream:
@@ -207,10 +184,11 @@ class Pager(Widget):
 		n = event.ctrl() and 1 or 3
 		direction = event.mouse_wheel_direction()
 		if direction:
-			self.move(relative=direction)
+			self.move(down=direction * n)
 		return True
 
 	def _get_line(self, n, attempt_to_read=True):
+		assert isinstance(n, int), n
 		try:
 			return self.lines[n]
 		except (KeyError, IndexError):
@@ -237,3 +215,6 @@ class Pager(Widget):
 			except IndexError:
 				raise StopIteration
 			i += 1
+
+	def _get_max_width(self):
+		return max(len(line) for line in self.lines)
diff --git a/ranger/gui/widgets/taskview.py b/ranger/gui/widgets/taskview.py
index 6e86465c..475b903c 100644
--- a/ranger/gui/widgets/taskview.py
+++ b/ranger/gui/widgets/taskview.py
@@ -22,7 +22,7 @@ from collections import deque
 
 from . import Widget
 from ranger.ext.accumulator import Accumulator
-from ranger.container import CommandList
+from ranger.container.keymap import CommandArgs
 
 class TaskView(Widget, Accumulator):
 	old_lst = None
@@ -31,8 +31,6 @@ class TaskView(Widget, Accumulator):
 		Widget.__init__(self, win)
 		Accumulator.__init__(self)
 		self.scroll_begin = 0
-		self.commandlist = CommandList()
-		self.settings.keys.initialize_taskview_commands(self.commandlist)
 
 	def draw(self):
 		base_clr = deque()
@@ -90,29 +88,35 @@ class TaskView(Widget, Accumulator):
 
 		self.fm.loader.remove(index=i)
 
-	def task_move(self, absolute, i=None):
+	def task_move(self, to, i=None):
 		if i is None:
 			i = self.pointer
 
-		self.fm.loader.move(_from=i, to=absolute)
+		self.fm.loader.move(_from=i, to=to)
 
 	def press(self, key):
-		try:
-			tup = self.env.keybuffer.tuple_without_numbers()
-			if tup:
-				cmd = self.commandlist[tup]
-			else:
-				return
-
-		except KeyError:
-			self.env.key_clear()
+		self.env.keymanager.use_context('taskview')
+		self.env.key_append(key)
+		kbuf = self.env.keybuffer
+		cmd = kbuf.command
+
+		if kbuf.failure:
+			kbuf.clear()
+			return
+		elif not cmd:
+			return
+
+		self.env.cmd = cmd
+
+		if cmd.function:
+			try:
+				cmd.function(CommandArgs.from_widget(self))
+			except Exception as error:
+				self.fm.notify(error)
+			if kbuf.done:
+				kbuf.clear()
 		else:
-			if hasattr(cmd, 'execute'):
-				try:
-					cmd.execute_wrap(self)
-				except Exception as error:
-					self.fm.notify(error)
-				self.env.key_clear()
+			kbuf.clear()
 
 	def get_list(self):
 		return self.fm.loader.queue