about summary refs log tree commit diff stats
path: root/ranger/ext
diff options
context:
space:
mode:
authorhut <hut@lavabit.com>2012-03-05 11:56:05 +0100
committerhut <hut@lavabit.com>2012-03-05 11:56:05 +0100
commite1155824b39d584beb8c178ceca8999eb7783daf (patch)
tree22dae0662d03ce8562159d9196fd8c854d6af009 /ranger/ext
parent2bcfbe93584f3e9bdd4f80ff4cce43e39a545914 (diff)
parent23b7f16961a7b679dec16f6ee91401a6b8f6ca82 (diff)
downloadranger-e1155824b39d584beb8c178ceca8999eb7783daf.tar.gz
Merge branch 'master' into stable
Diffstat (limited to 'ranger/ext')
-rw-r--r--ranger/ext/cached_function.py27
-rw-r--r--ranger/ext/human_readable.py24
-rw-r--r--ranger/ext/next_available_filename.py30
-rw-r--r--ranger/ext/shell_escape.py7
-rw-r--r--ranger/ext/signals.py20
5 files changed, 92 insertions, 16 deletions
diff --git a/ranger/ext/cached_function.py b/ranger/ext/cached_function.py
new file mode 100644
index 00000000..4d9ded18
--- /dev/null
+++ b/ranger/ext/cached_function.py
@@ -0,0 +1,27 @@
+# Copyright (C) 2012  Roman Zimbelmann <romanz@lavabit.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+def cached_function(fnc):
+  cache = {}
+  def inner_cached_function(*args):
+    try:
+      return cache[args]
+    except:
+      value = fnc(*args)
+      cache[args] = value
+      return value
+  inner_cached_function._cache = cache
+  return inner_cached_function
+
diff --git a/ranger/ext/human_readable.py b/ranger/ext/human_readable.py
index 9cdce409..c5bd2aac 100644
--- a/ranger/ext/human_readable.py
+++ b/ranger/ext/human_readable.py
@@ -13,7 +13,7 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-def human_readable(byte, seperator=' '):
+def human_readable(byte, separator=' '):
 	"""
 	Convert a large number of bytes to an easily readable format.
 
@@ -27,27 +27,27 @@ def human_readable(byte, seperator=' '):
 	if byte <= 0:
 		return '0'
 	if byte < 2**10:
-		return '%d%sB'   % (byte, seperator)
+		return '%d%sB'   % (byte, separator)
 	if byte < 2**10 * 999:
-		return '%.3g%sK' % (byte / 2**10.0, seperator)
+		return '%.3g%sK' % (byte / 2**10.0, separator)
 	if byte < 2**20:
-		return '%.4g%sK' % (byte / 2**10.0, seperator)
+		return '%.4g%sK' % (byte / 2**10.0, separator)
 	if byte < 2**20 * 999:
-		return '%.3g%sM' % (byte / 2**20.0, seperator)
+		return '%.3g%sM' % (byte / 2**20.0, separator)
 	if byte < 2**30:
-		return '%.4g%sM' % (byte / 2**20.0, seperator)
+		return '%.4g%sM' % (byte / 2**20.0, separator)
 	if byte < 2**30 * 999:
-		return '%.3g%sG' % (byte / 2**30.0, seperator)
+		return '%.3g%sG' % (byte / 2**30.0, separator)
 	if byte < 2**40:
-		return '%.4g%sG' % (byte / 2**30.0, seperator)
+		return '%.4g%sG' % (byte / 2**30.0, separator)
 	if byte < 2**40 * 999:
-		return '%.3g%sT' % (byte / 2**40.0, seperator)
+		return '%.3g%sT' % (byte / 2**40.0, separator)
 	if byte < 2**50:
-		return '%.4g%sT' % (byte / 2**40.0, seperator)
+		return '%.4g%sT' % (byte / 2**40.0, separator)
 	if byte < 2**50 * 999:
-		return '%.3g%sP' % (byte / 2**50.0, seperator)
+		return '%.3g%sP' % (byte / 2**50.0, separator)
 	if byte < 2**60:
-		return '%.4g%sP' % (byte / 2**50.0, seperator)
+		return '%.4g%sP' % (byte / 2**50.0, separator)
 	return '>9000'
 
 if __name__ == '__main__':
diff --git a/ranger/ext/next_available_filename.py b/ranger/ext/next_available_filename.py
new file mode 100644
index 00000000..696063cf
--- /dev/null
+++ b/ranger/ext/next_available_filename.py
@@ -0,0 +1,30 @@
+# Copyright (C) 2011  Roman Zimbelmann <romanz@lavabit.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+import os.path
+
+def next_available_filename(fname, directory="."):
+	existing_files = os.listdir(directory)
+
+	if fname not in existing_files:
+		return fname
+	if not fname.endswith("_"):
+		fname += "_"
+		if fname not in existing_files:
+			return fname
+
+	for i in range(1, len(existing_files) + 1):
+		if fname + str(i) not in existing_files:
+			return fname + str(i)
diff --git a/ranger/ext/shell_escape.py b/ranger/ext/shell_escape.py
index 28a502bf..b68afc33 100644
--- a/ranger/ext/shell_escape.py
+++ b/ranger/ext/shell_escape.py
@@ -18,17 +18,20 @@ Functions to escape metacharacters of arguments for shell commands.
 """
 
 META_CHARS = (' ', "'", '"', '`', '&', '|', ';',
-		'$', '!', '(', ')', '[', ']', '<', '>')
+		'$', '!', '(', ')', '[', ']', '<', '>', '\t')
+UNESCAPABLE = set(map(chr, list(range(9)) + list(range(10, 32)) \
+		+ list(range(127, 256))))
 META_DICT = dict([(mc, '\\' + mc) for mc in META_CHARS])
 
 def shell_quote(string):
 	"""Escapes by quoting"""
 	return "'" + str(string).replace("'", "'\\''") + "'"
 
-
 def shell_escape(arg):
 	"""Escapes by adding backslashes"""
 	arg = str(arg)
+	if UNESCAPABLE & set(arg):
+		return shell_quote(arg)
 	arg = arg.replace('\\', '\\\\') # make sure this comes at the start
 	for k, v in META_DICT.items():
 		arg = arg.replace(k, v)
diff --git a/ranger/ext/signals.py b/ranger/ext/signals.py
index ecb48de3..0df39fe0 100644
--- a/ranger/ext/signals.py
+++ b/ranger/ext/signals.py
@@ -126,7 +126,7 @@ class SignalDispatcher(object):
 				handler._function = None
 		self._signals = dict()
 
-	def signal_bind(self, signal_name, function, priority=0.5, weak=False):
+	def signal_bind(self, signal_name, function, priority=0.5, weak=False, autosort=True):
 		"""
 		Bind a function to the signal.
 
@@ -162,9 +162,25 @@ class SignalDispatcher(object):
 
 		handler = SignalHandler(signal_name, function, priority, nargs > 0)
 		handlers.append(handler)
-		handlers.sort(key=lambda handler: -handler._priority)
+		if autosort:
+			handlers.sort(key=lambda handler: -handler._priority)
 		return handler
 
+	def signal_force_sort(self, signal_name=None):
+		"""
+		Forces a sorting of signal handlers by priority.
+
+		This is only necessary if you used signal_bind with autosort=False
+		after finishing to bind many signals at once.
+		"""
+		if signal_name is None:
+			for handlers in self._signals.values():
+				handlers.sort(key=lambda handler: -handler._priority)
+		elif signal_name in self._signals:
+			self._signals[signal_name].sort(key=lambda handler: -handler._priority)
+		else:
+			return False
+
 	def signal_unbind(self, signal_handler):
 		"""
 		Removes a signal binding.