about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/actions.py28
-rw-r--r--ranger/applications.py4
-rw-r--r--ranger/container/commandlist.py36
-rw-r--r--ranger/defaults/keys.py9
-rw-r--r--ranger/environment.py14
-rw-r--r--ranger/fsobject/directory.py17
-rw-r--r--ranger/gui/colorscheme.py8
-rw-r--r--ranger/gui/mouse_event.py16
-rw-r--r--ranger/gui/ui.py43
-rw-r--r--ranger/gui/widgets/console.py2
-rw-r--r--ranger/gui/widgets/filelistcontainer.py5
11 files changed, 137 insertions, 45 deletions
diff --git a/ranger/actions.py b/ranger/actions.py
index a36b0c56..2435480b 100644
--- a/ranger/actions.py
+++ b/ranger/actions.py
@@ -2,16 +2,20 @@ from ranger.shared import EnvironmentAware, SettingsAware
 
 class Actions(EnvironmentAware, SettingsAware):
 	def search_forward(self):
+		"""Search forward for the regexp in self.env.last_search"""
 		if self.env.pwd:
 			if self.env.pwd.search(self.env.last_search):
 				self.env.cf = self.env.pwd.pointed_file
 
 	def search_backward(self):
+		"""Search backward for the regexp in self.env.last_search"""
 		if self.env.pwd:
 			if self.env.pwd.search(self.env.last_search, -1):
 				self.env.cf = self.env.pwd.pointed_file
 
 	def interrupt(self):
+		"""Waits a short time.
+If CTRL+C is pressed while waiting, the program will be exited"""
 		import time
 		self.env.key_clear()
 		try:
@@ -20,15 +24,19 @@ class Actions(EnvironmentAware, SettingsAware):
 			raise SystemExit()
 
 	def resize(self):
+		"""Update the size of the UI"""
 		self.ui.update_size()
 
 	def exit(self):
+		"""Exit the program"""
 		raise SystemExit()
 
 	def enter_dir(self, path):
+		"""Enter the directory at the given path"""
 		self.env.enter_dir(path)
 
 	def enter_bookmark(self, key):
+		"""Enter the bookmark with the name <key>"""
 		from ranger.container.bookmarks import NonexistantBookmark
 		try:
 			destination = self.bookmarks[key]
@@ -40,26 +48,38 @@ class Actions(EnvironmentAware, SettingsAware):
 			pass
 
 	def set_bookmark(self, key):
+		"""Set the bookmark with the name <key> to the current directory"""
 		self.bookmarks[key] = self.env.pwd.path
 
 	def unset_bookmark(self, key):
+		"""Delete the bookmark with the name <key>"""
 		self.bookmarks.delete(key)
 
 	def move_left(self):
+		"""Enter the parent directory"""
 		self.env.enter_dir('..')
 	
 	def move_right(self, mode = 0):
+		"""Enter the current directory or execute the current file"""
 		cf = self.env.cf
 		if not self.env.enter_dir(cf):
 			self.execute_file(cf, mode = mode)
 
 	def history_go(self, relative):
+		"""Move back and forth in the history"""
 		self.env.history_go(relative)
 	
 	def handle_mouse(self):
+		"""Handle mouse-buttons if one was pressed"""
 		self.ui.handle_mouse()
 
 	def execute_file(self, files, app = '', flags = '', mode = 0):
+		"""Execute a file.
+app is the name of a method in Applications, without the "app_"
+flags is a string consisting of applications.ALLOWED_FLAGS
+mode is a positive integer.
+Both flags and mode specify how the program is run."""
+
 		if type(files) not in (list, tuple):
 			files = [files]
 
@@ -73,35 +93,43 @@ class Actions(EnvironmentAware, SettingsAware):
 				apps = self.apps)
 	
 	def edit_file(self):
+		"""Calls execute_file with the current file and app='editor'"""
 		if self.env.cf is None:
 			return
 		self.execute_file(self.env.cf, app = 'editor')
 
 	def open_console(self, mode = ':'):
+		"""Open the console if the current UI supports that"""
 		if hasattr(self.ui, 'open_console'):
 			self.ui.open_console(mode)
 
 	def move_pointer(self, relative = 0, absolute = None):
+		"""Move the pointer down by <relative> or to <absolute>"""
 		self.env.cf = self.env.pwd.move_pointer(relative, absolute)
 
 	def move_pointer_by_pages(self, relative):
+		"""Move the pointer down by <relative> pages"""
 		self.env.cf = self.env.pwd.move_pointer(
 				relative = int(relative * self.env.termsize[0]))
 
 	def scroll(self, relative):
+		"""Scroll down by <relative> lines"""
 		if hasattr(self.ui, 'scroll'):
 			self.ui.scroll(relative)
 			self.env.cf = self.env.pwd.pointed_file
 
 	def redraw(self):
+		"""Redraw the window"""
 		self.ui.redraw()
 
 	def reset(self):
+		"""Reset the filemanager, clearing the directory buffer"""
 		old_path = self.env.pwd.path
 		self.env.directories = {}
 		self.enter_dir(old_path)
 
 	def toggle_boolean_option(self, string):
+		"""Toggle a boolean option named <string>"""
 		if isinstance(self.env.settings[string], bool):
 			self.env.settings[string] ^= True
 
diff --git a/ranger/applications.py b/ranger/applications.py
index 85dc50f5..39601e0e 100644
--- a/ranger/applications.py
+++ b/ranger/applications.py
@@ -2,21 +2,25 @@ ALLOWED_FLAGS = 'sdpSDP'
 
 class Applications(object):
 	def get(self, app):
+		"""Looks for an application, returns app_default if it doesn't exist"""
 		try:
 			return getattr(self, 'app_' + app)
 		except AttributeError:
 			return self.app_default
 
 	def has(self, app):
+		"""Returns whether an application is defined"""
 		return hasattr(self, 'app_' + app)
 
 	def all(self):
+		"""Returns a list with all application functions"""
 		return [x for x in self.__dict__ if x.startswith('app_')]
 
 import os
 null = open(os.devnull, 'a')
 
 def run(*args, **kw):
+	"""Run files with the specified parameters"""
 	from subprocess import Popen
 	from subprocess import PIPE
 	from ranger.ext.waitpid_no_intr import waitpid_no_intr
diff --git a/ranger/container/commandlist.py b/ranger/container/commandlist.py
index a252fea2..9c4c77a0 100644
--- a/ranger/container/commandlist.py
+++ b/ranger/container/commandlist.py
@@ -1,15 +1,25 @@
+"""CommandLists are dictionary-like objects which give you a command
+for a given key combination. CommandLists must be initialized
+before use."""
 class CommandList(object):
+	dummy_object = None
+	dummies_in_paths = False
+	paths = {}
+	commandlist = []
 	def __init__(self):
 		self.commandlist = []
 		self.paths = {}
-		self.dummies_in_paths = False
-		self.dummy_object = None
+	
+	def __getitem__(self, key):
+		"""Returns the command with the given key combination"""
+		return self.paths[key]
 
-	# We need to know when to clear the keybuffer (when a wrong key is pressed)
-	# and when to wait for the rest of the key combination. For "gg" we
-	# will assign "g" to a dummy which tells the program to do the latter.
 	def rebuild_paths(self):
-		""" fill the path dictionary with dummie objects """
+		"""Fill the path dictionary with dummie objects.
+We need to know when to clear the keybuffer (when a wrong key is pressed)
+and when to wait for the rest of the key combination. For "gg" we
+will assign "g" to a dummy which tells the program to do the latter
+and wait."""
 		if self.dummies_in_paths:
 			self.remove_dummies()
 		
@@ -22,7 +32,7 @@ class CommandList(object):
 		self.dummies_in_paths = True
 
 	def keypath(self, tup):
-		""" split a tuple like (a,b,c,d) into [(a,), (a,b), (a,b,c)] """
+		"""split a tuple like (a,b,c,d) into [(a,), (a,b), (a,b,c)]"""
 		length = len(tup)
 
 		if length == 0:
@@ -40,7 +50,7 @@ class CommandList(object):
 		return all
 
 	def remove_dummies(self):
-		""" remove dummie objects in case you have to rebuild a path dictionary which already contains dummie objects. """
+		"""remove dummie objects in case you have to rebuild a path dictionary which already contains dummie objects."""
 		for k in tuple(paths.keys()):
 			if paths[k] == self.dummy_object: del paths[k]
 		self.dummies_in_paths = False
@@ -58,21 +68,23 @@ class CommandList(object):
 			raise TypeError('need a str, int or tuple for str_to_tuple')
 	
 	def bind(self, fnc, *keys):
-		""" create a Command object and assign it to the given key combinations. """
+		"""create a Command object and assign it to the given key combinations."""
 		if len(keys) == 0: return
 
 		keys = tuple(map(self.str_to_tuple, keys))
 
 		cmd = Command(fnc, keys)
-		cmd.commandlist = self
 
 		self.commandlist.append(cmd)
 		for key in keys:
 			self.paths[key] = cmd
 	
 class Command(object):
+	keys = []
 	def __init__(self, fnc, keys):
-		self.execute = fnc
 		self.keys = keys
-		self.commandlist = None
+		self.execute = fnc
+	
+	def execute(self, *args):
+		"""Execute the command."""
 
diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py
index 7d6f7bd6..ffd37646 100644
--- a/ranger/defaults/keys.py
+++ b/ranger/defaults/keys.py
@@ -2,6 +2,7 @@ import curses
 from curses.ascii import ctrl, ESC
 
 def initialize_commands(command_list):
+	"""Initialize the commands for the main user interface"""
 	from ranger.actions import Actions as do
 	from ranger.container.bookmarks import ALLOWED_KEYS as ALLOWED_BOOKMARK_KEYS
 
@@ -89,15 +90,13 @@ def initialize_commands(command_list):
 
 
 def initialize_console_commands(command_list):
+	"""Initialize the commands for the console widget only"""
 	from ranger.actions import Actions as do
 	from ranger.gui.widgets.console import Console
 
 	def bind(fnc, *keys):
 		command_list.bind(fnc, *keys)
 
-	def type_key(key):
-		return lambda con: con.type_key(key)
-
 	# currying
 	def c(fnc, *args, **keywords):
 		return lambda con: fnc(con, *args, **keywords)
@@ -122,6 +121,10 @@ def initialize_console_commands(command_list):
 	bind(c_fm(do.redraw), ctrl('L'))
 	bind(c_fm(do.resize), curses.KEY_RESIZE)
 
+
+	def type_key(key):
+		return lambda con: con.type_key(key)
+
 	for i in range(ord(' '), ord('~')):
 		bind(type_key(i), i)
 
diff --git a/ranger/environment.py b/ranger/environment.py
index 9e2c2877..881e25e0 100644
--- a/ranger/environment.py
+++ b/ranger/environment.py
@@ -23,12 +23,18 @@ class Environment(SettingsAware):
 		EnvironmentAware.env = self
 
 	def key_append(self, key):
+		"""Append a key to the keybuffer"""
 		self.keybuffer = KeyBuffer(self.keybuffer + (key, ))
 
 	def key_clear(self):
+		"""Clear the keybuffer"""
 		self.keybuffer = KeyBuffer()
 	
 	def at_level(self, level):
+		"""Returns the FileSystemObject at the given level.
+level 1 => preview
+level 0 => current file/directory
+level <0 => parent directories"""
 		if level <= 0:
 			try:
 				return self.pathway[level - 1]
@@ -43,14 +49,16 @@ class Environment(SettingsAware):
 				return self.cf
 
 	def garbage_collect(self):
+		"""Delete unused directory objects"""
 		from ranger.fsobject.fsobject import FileSystemObject
 		for key in tuple(self.directories.keys()):
 			value = self.directories[key]
 			if isinstance(value, FileSystemObject):
-				if value.is_older_than(1):
+				if value.is_older_than(1200):
 					del self.directories[key]
 	
 	def get_directory(self, path):
+		"""Get the directory object at the given path"""
 		path = abspath(path)
 		try:
 			return self.directories[path]
@@ -59,7 +67,7 @@ class Environment(SettingsAware):
 			return self.directories[path]
 
 	def assign_correct_cursor_positions(self):
-		# Assign correct cursor positions for subdirectories
+		"""Assign correct cursor positions for subdirectories"""
 		last_path = None
 		for path in reversed(self.pathway):
 			if last_path is None:
@@ -70,11 +78,13 @@ class Environment(SettingsAware):
 			last_path = path
 	
 	def history_go(self, relative):
+		"""Move relative in history"""
 		if self.history:
 #			self.enter_dir(self.history.move(relative))
 			self.history.move(relative).go()
 
 	def enter_dir(self, path, history = True):
+		"""Enter given path"""
 		if path is None: return
 		path = str(path)
 
diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py
index cdcbc2ed..0ebfff13 100644
--- a/ranger/fsobject/directory.py
+++ b/ranger/fsobject/directory.py
@@ -44,6 +44,8 @@ class Directory(SuperClass, SettingsAware):
 		self.old_directories_first = self.settings.directories_first
 
 	def load_content(self):
+		"""Loads the contents of the directory. Use this sparingly since
+it takes rather long."""
 		from os.path import join, isdir, basename
 		from os import listdir
 
@@ -85,6 +87,7 @@ class Directory(SuperClass, SettingsAware):
 			self.infostring = BAD_INFO
 
 	def sort(self):
+		"""Sort the containing files"""
 		if self.files is None:
 			return
 
@@ -102,6 +105,7 @@ class Directory(SuperClass, SettingsAware):
 		self.old_directories_first = self.settings.directories_first
 	
 	def sort_if_outdated(self):
+		"""Sort the containing files if they are outdated"""
 		if self.old_directories_first != self.settings.directories_first:
 			self.sort()
 
@@ -109,6 +113,7 @@ class Directory(SuperClass, SettingsAware):
 	# modify the current directory with this function, make sure
 	# to update fm.env.cf aswell.
 	def move_pointer(self, relative=0, absolute=None):
+		"""Move the index pointer"""
 		if self.empty(): return
 		i = self.pointed_index
 		if isinstance(absolute, int):
@@ -124,6 +129,8 @@ class Directory(SuperClass, SettingsAware):
 		return self.pointed_file
 
 	def move_pointer_to_file_path(self, path):
+		"""Move the index pointer to the index of the file object
+with the given path."""
 		if path is None: return
 		try: path = path.path
 		except AttributeError: pass
@@ -140,6 +147,7 @@ class Directory(SuperClass, SettingsAware):
 		return False
 	
 	def search(self, arg, direction = 1):
+		"""Search for a regular expression"""
 		if self.empty() or arg is None:
 			return False
 		elif hasattr(arg, 'search'):
@@ -180,12 +188,15 @@ class Directory(SuperClass, SettingsAware):
 			self.pointed_file = self[i]
 		
 	def load_content_once(self):
+		"""Load the contents of the directory if not done yet"""
 		if not self.content_loaded:
 			self.load_content()
 			return True
 		return False
 
 	def load_content_if_outdated(self):
+		"""Load the contents of the directory if it's
+outdated or not done yet"""
 		if self.load_content_once(): return True
 
 		if self.old_show_hidden != self.settings.show_hidden:
@@ -203,21 +214,27 @@ class Directory(SuperClass, SettingsAware):
 		return False
 
 	def empty(self):
+		"""Is the directory empty?"""
 		return self.files is None or len(self.files) == 0
 
 	def __nonzero__(self):
+		"""Always True"""
 		return True
 
 	def __len__(self):
+		"""The number of containing files"""
 		if not self.accessible: raise ranger.fsobject.NotLoadedYet()
 		return len(self.files)
 	
 	def __getitem__(self, key):
+		"""Get the file by its index"""
 		if not self.accessible: raise ranger.fsobject.NotLoadedYet()
 		return self.files[key]
 
 	def __eq__(self, other):
+		"""Check for equality of the directories paths"""
 		return isinstance(other, Directory) and self.path == other.path
 
 	def __neq__(self, other):
+		"""Check for inequality of the directories paths"""
 		return not self.__eq__(other)
diff --git a/ranger/gui/colorscheme.py b/ranger/gui/colorscheme.py
index 38f4ac5a..a69ed75b 100644
--- a/ranger/gui/colorscheme.py
+++ b/ranger/gui/colorscheme.py
@@ -35,6 +35,7 @@ class ColorScheme(object):
 		self.cache = {}
 
 	def get(self, *keys):
+		"""Determine the (fg, bg, attr) tuple or get it from cache"""
 		try:
 			return self.cache[keys]
 
@@ -50,6 +51,7 @@ class ColorScheme(object):
 			return color
 
 	def get_attr(self, *keys):
+		"""Returns the curses attr integer for the specified keys"""
 		from ranger.gui.color import get_color
 		import curses
 
@@ -58,5 +60,9 @@ class ColorScheme(object):
 
 
 	def use(self, context):
-		return -1, -1, 0
+		"""Use the colorscheme to determine the (fg, bg, attr) tuple.
+This is a dummy function which always returns default_colors.
+Override this in your custom colorscheme!"""
+		from ranger.gui.color import default_colors
+		return default_colors
 
diff --git a/ranger/gui/mouse_event.py b/ranger/gui/mouse_event.py
index fa25f5f0..db98e1aa 100644
--- a/ranger/gui/mouse_event.py
+++ b/ranger/gui/mouse_event.py
@@ -1,5 +1,5 @@
+import curses
 class MouseEvent(object):
-	import curses
 	PRESSED = [ 0,
 			curses.BUTTON1_PRESSED,
 			curses.BUTTON2_PRESSED,
@@ -7,10 +7,24 @@ class MouseEvent(object):
 			curses.BUTTON4_PRESSED ]
 
 	def __init__(self, getmouse):
+		"""Creates a MouseEvent object from the result of win.getmouse()"""
 		_, self.x, self.y, _, self.bstate = getmouse
 	
 	def pressed(self, n):
+		"""Returns whether the mouse key n is pressed"""
 		try:
 			return (self.bstate & MouseEvent.PRESSED[n]) != 0
 		except:
 			return False
+
+	def ctrl(self):
+		return self.bstate & curses.BUTTON_CTRL
+
+	def alt(self):
+		return self.bstate & curses.BUTTON_ALT
+
+	def shift(self):
+		return self.bstate & curses.BUTTON_SHIFT
+
+	def key_invalid(self):
+		return self.bstate > curses.ALL_MOUSE_EVENTS
diff --git a/ranger/gui/ui.py b/ranger/gui/ui.py
index 7b7230fb..eb25d9ca 100644
--- a/ranger/gui/ui.py
+++ b/ranger/gui/ui.py
@@ -48,6 +48,18 @@ class UI(DisplayableContainer):
 			self.setup()
 		self.update_size()
 
+	def destroy(self):
+		"""Destroy all widgets and turn off curses"""
+#		DisplayableContainer.destroy(self)
+		from ranger import log
+		log("exiting ui!")
+		self.win.keypad(0)
+		curses.nocbreak()
+		curses.echo()
+		curses.curs_set(1)
+		curses.mousemask(0)
+		curses.endwin()
+
 	def handle_mouse(self):
 		"""Handles mouse input"""
 		try:
@@ -55,20 +67,17 @@ class UI(DisplayableContainer):
 		except:
 			return
 
+#		from ranger import log
+#		log('{0:0>28b} ({0})'.format(event.bstate))
+
 		if DisplayableContainer.click(self, event):
 			return
 
-#		if event.pressed(1) or event.pressed(3):
-#			for displayable in self.container:
-#				if displayable.contains_point(event.y, event.x):
-#					displayable.click(event)
-#					break
-
-#		if event.pressed(4) or event.pressed(2) or event.bstate & 134217728:
+		n = event.ctrl() and 1 or 3
 		if event.pressed(4):
-			self.fm.scroll(relative = -3)
-		elif event.pressed(2):
-			self.fm.scroll(relative = 3)
+			self.fm.scroll(relative = -n)
+		elif event.pressed(2) or event.key_invalid():
+			self.fm.scroll(relative = n)
 
 	def handle_key(self, key):
 		"""Handles key input"""
@@ -78,7 +87,7 @@ class UI(DisplayableContainer):
 			return
 
 		try:
-			cmd = self.commandlist.paths[tuple(self.env.keybuffer)]
+			cmd = self.commandlist[tuple(self.env.keybuffer)]
 		except KeyError:
 			self.env.key_clear()
 			return
@@ -119,15 +128,3 @@ Extend this method to resize all widgets!"""
 		"""Finalize every object in container and refresh the window"""
 		DisplayableContainer.finalize(self)
 		self.win.refresh()
-
-	def destroy(self):
-		"""Destroy all widgets and turn off curses"""
-#		DisplayableContainer.destroy(self)
-		from ranger import log
-		log("exiting ui!")
-		self.win.keypad(0)
-		curses.nocbreak()
-		curses.echo()
-		curses.curs_set(1)
-#		curses.mousemask(0)
-		curses.endwin()
diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py
index 17197a2e..f4b278c9 100644
--- a/ranger/gui/widgets/console.py
+++ b/ranger/gui/widgets/console.py
@@ -69,7 +69,7 @@ class Console(Widget):
 		from curses.ascii import ctrl, ESC
 
 		try:
-			cmd = self.commandlist.paths[self.env.keybuffer]
+			cmd = self.commandlist[self.env.keybuffer]
 		except KeyError:
 			self.env.key_clear()
 			return
diff --git a/ranger/gui/widgets/filelistcontainer.py b/ranger/gui/widgets/filelistcontainer.py
index ed5a36c4..9d95b389 100644
--- a/ranger/gui/widgets/filelistcontainer.py
+++ b/ranger/gui/widgets/filelistcontainer.py
@@ -19,7 +19,8 @@ class FileListContainer(Widget, DisplayableContainer):
 		if preview: offset += 1
 
 		for level in range(len(ratios)):
-			self.add_obj(FileList(win, level + offset))
+			fl = FileList(win, level + offset)
+			self.add_obj(fl)
 
 		try:
 			self.main_filelist = self.container[preview and -2 or -1]
@@ -32,7 +33,7 @@ class FileListContainer(Widget, DisplayableContainer):
 	def resize(self, y, x, hei, wid):
 		"""Resize all the filelists according to the given ratio"""
 		DisplayableContainer.resize(self, y, x, hei, wid)
-		left = self.y
+		left = self.x
 		for ratio, i in zip(self.ratios, range(len(self.ratios))):
 			wid = int(ratio * self.wid)
 			try: