summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAbdó Roig-Maranges <abdo.roig@gmail.com>2012-12-06 15:12:54 +0100
committerhut <hut@lavabit.com>2012-12-09 15:16:45 +0100
commit864331a0edd73b364c22985bbb1aa7f55dcf25f4 (patch)
tree831b060f839eb11d34b17a58293b4220ff1800ff
parenta45403b7f5c055ecac308c6b6adb1fe3f892f6eb (diff)
downloadranger-864331a0edd73b364c22985bbb1aa7f55dcf25f4.tar.gz
Implement local per-directory settings
SettingObject can store settings local to a directory. Then LocalSettingObject
choses the right settings according to context.
-rw-r--r--ranger/container/settingobject.py92
-rw-r--r--ranger/core/actions.py6
-rw-r--r--ranger/fsobject/directory.py5
3 files changed, 78 insertions, 25 deletions
diff --git a/ranger/container/settingobject.py b/ranger/container/settingobject.py
index 780b6365..23bf10ba 100644
--- a/ranger/container/settingobject.py
+++ b/ranger/container/settingobject.py
@@ -51,43 +51,53 @@ DEFAULT_VALUES = {
 	str: "",
 	int: 0,
 	list: [],
+	tuple: tuple([]),
 }
 
 class SettingObject(SignalDispatcher, FileManagerAware):
 	def __init__(self):
 		SignalDispatcher.__init__(self)
+		self.__dict__['_localsettings'] = dict()
 		self.__dict__['_settings'] = dict()
 		for name in ALLOWED_SETTINGS:
 			self.signal_bind('setopt.'+name,
 					self._raw_set_with_signal, priority=0.2)
 
+	def set(self, name, value, path=None):
+   		assert name in ALLOWED_SETTINGS, "No such setting: {0}!".format(name)
+   		if name not in self._settings:
+   			previous = None
+   		else:
+   			previous=self._settings[name]
+   		assert self._check_type(name, value)
+   		kws = dict(setting=name, value=value, previous=previous, path=path, fm=self.fm)
+   		self.signal_emit('setopt', **kws)
+   		self.signal_emit('setopt.'+name, **kws)
+
+	def get(self, name, path=None):
+		assert name in ALLOWED_SETTINGS, "No such setting: {0}!".format(name)
+		if path and path in self._localsettings and name in self._localsettings[path]:
+			return self._localsettings[path][name]
+		elif name in self._settings:
+			return self._settings[name]
+		else:
+			type_ = self.types_of(name)[0]
+			value = DEFAULT_VALUES[type_]
+			self._raw_set(name, value, None)
+			self.__setattr__(name, value)
+			return self._settings[name]
+
 	def __setattr__(self, name, value):
-		if name[0] == '_':
+		if name.startswith('_'):
 			self.__dict__[name] = value
 		else:
-			assert name in ALLOWED_SETTINGS, "No such setting: {0}!".format(name)
-			if name not in self._settings:
-				previous = None
-			else:
-				previous=self._settings[name]
-			assert self._check_type(name, value)
-			kws = dict(setting=name, value=value, previous=previous, fm=self.fm)
-			self.signal_emit('setopt', **kws)
-			self.signal_emit('setopt.'+name, **kws)
+			self.set(name, value, None)
 
 	def __getattr__(self, name):
-		assert name in ALLOWED_SETTINGS or name in self._settings, \
-				"No such setting: {0}!".format(name)
 		if name.startswith('_'):
 			return self.__dict__[name]
-		try:
-			return self._settings[name]
-		except:
-			type_ = self.types_of(name)[0]
-			value = DEFAULT_VALUES[type_]
-			self._raw_set(name, value)
-			self.__setattr__(name, value)
-			return self._settings[name]
+		else:
+			return self.get(name, None)
 
 	def __iter__(self):
 		for x in self._settings:
@@ -121,8 +131,44 @@ class SettingObject(SignalDispatcher, FileManagerAware):
 	__getitem__ = __getattr__
 	__setitem__ = __setattr__
 
-	def _raw_set(self, name, value):
-		self._settings[name] = value
+	def _raw_set(self, name, value, path):
+		if path:
+			if not path in self._localsettings:
+				self._localsettings[path] = dict()
+			self._localsettings[path][name] = value
+
+			# make sure name is in _settings, so __iter__ runs through local settigns too.
+			if not name in self._settings:
+				type_ = self.types_of(name)[0]
+				value = DEFAULT_VALUES[type_]
+				self._settings[name] = value
+		else:
+			self._settings[name] = value
 
 	def _raw_set_with_signal(self, signal):
-		self._settings[signal.setting] = signal.value
+		self._raw_set(signal.setting, signal.value, signal.path)
+
+
+class LocalSettingObject():
+	def __init__(self, path, parent):
+		self.__dict__['_parent'] = parent
+		self.__dict__['_path'] = path
+
+	def __setattr__(self, name, value):
+		if name.startswith('_'):
+			self.__dict__[name] = value
+		else:
+			self._parent.set(name, value, self._path)
+
+	def __getattr__(self, name):
+		if name.startswith('_'):
+			return self.__dict__[name]
+		else:
+			return self._parent.get(name, self._path)
+
+	def __iter__(self):
+		for x in self._parent._settings:
+			yield x
+
+	__getitem__ = __getattr__
+	__setitem__ = __setattr__
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index 6df73cdf..0b4948a0 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -67,13 +67,15 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 		self.mode = mode
 		self.ui.status.request_redraw()
 
-	def set_option_from_string(self, option_name, value):
+	def set_option_from_string(self, option_name, value, localpath=None):
 		if option_name not in ALLOWED_SETTINGS:
 			raise ValueError("The option named `%s' does not exist" %
 					option_name)
 		if not isinstance(value, str):
 			raise ValueError("The value for an option needs to be a string.")
-		self.settings[option_name] = self._parse_option_value(option_name, value)
+
+		self.settings.set(option_name, self._parse_option_value(option_name, value), localpath)
+
 
 	def _parse_option_value(self, name, value):
 		types = self.fm.settings.types_of(name)
diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py
index a58201c0..f8271b6d 100644
--- a/ranger/fsobject/directory.py
+++ b/ranger/fsobject/directory.py
@@ -3,6 +3,7 @@
 
 import os.path
 import re
+
 from os import stat as os_stat, lstat as os_lstat
 from collections import deque
 from time import time
@@ -15,6 +16,7 @@ from ranger.core.shared import SettingsAware
 from ranger.ext.accumulator import Accumulator
 from ranger.ext.lazy_property import lazy_property
 from ranger.ext.human_readable import human_readable
+from ranger.container.settingobject import LocalSettingObject
 
 def sort_by_basename(path):
 	"""returns path.basename (for sorting)"""
@@ -99,6 +101,9 @@ class Directory(FileSystemObject, Accumulator, Loadable, SettingsAware):
 		for opt in ('hidden_filter', 'show_hidden'):
 			self.settings.signal_bind('setopt.' + opt,
 				self.request_reload, weak=True, autosort=False)
+
+		self.settings = LocalSettingObject(path, self.settings)
+
 		self.use()
 
 	def request_resort(self):