summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/defaults/keys.py4
-rw-r--r--ranger/fsobject/directory.py21
-rw-r--r--ranger/fsobject/fsobject.py13
3 files changed, 22 insertions, 16 deletions
diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py
index 21beebeb..e62ae9ae 100644
--- a/ranger/defaults/keys.py
+++ b/ranger/defaults/keys.py
@@ -203,11 +203,11 @@ map('zf', fm.open_console('filter '))
 
 # ------------------------------------------------------------ sort
 map('o<bg>', 'O<bg>', fm.hint("*s*ize *b*asename *m*time" \
-	" *t*ype *r*everse *n*umeric"))
+	" *t*ype *r*everse *n*atural"))
 sort_dict = {
 	's': 'size',
 	'b': 'basename',
-	'n': 'numeric',
+	'n': 'natural',
 	'm': 'mtime',
 	't': 'type',
 }
diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py
index ab12734f..ac628ff0 100644
--- a/ranger/fsobject/directory.py
+++ b/ranger/fsobject/directory.py
@@ -15,7 +15,6 @@
 
 import os.path
 import stat
-import re
 from stat import S_ISLNK, S_ISDIR
 from os import stat as os_stat, lstat as os_lstat
 from os.path import join, isdir, basename
@@ -40,17 +39,11 @@ def sort_by_directory(path):
 	"""returns 0 if path is a directory, otherwise 1 (for sorting)"""
 	return 1 - path.is_directory
 
-def sort_by_number(path):
-	try:
-		return float(re.search(r'\d+', path.basename).group(0))
-	except:
-		return path.basename
+def sort_naturally(path):
+	return path.basename_natural
 
-def sort_by_number_icase(path):
-	try:
-		return float(re.search(r'\d+', path.basename).group(0))
-	except:
-		return path.basename_lower
+def sort_naturally_icase(path):
+	return path.basename_natural_lower
 
 def accept_file(fname, hidden_filter, name_filter):
 	if hidden_filter:
@@ -89,7 +82,7 @@ class Directory(FileSystemObject, Accumulator, SettingsAware):
 
 	sort_dict = {
 		'basename': sort_by_basename,
-		'numeric': sort_by_number,
+		'natural': sort_naturally,
 		'size': lambda path: -path.size,
 		'mtime': lambda path: -(path.stat and path.stat.st_mtime or 1),
 		'type': lambda path: path.mimetype,
@@ -310,8 +303,8 @@ class Directory(FileSystemObject, Accumulator, SettingsAware):
 			sort_func = sort_by_basename_icase
 
 		if self.settings.sort_case_insensitive and \
-				sort_func == sort_by_number:
-			sort_func = sort_by_number_icase
+				sort_func == sort_naturally:
+			sort_func = sort_naturally_icase
 
 		self.files.sort(key = sort_func)
 
diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py
index 4ca5a6c8..63a64029 100644
--- a/ranger/fsobject/fsobject.py
+++ b/ranger/fsobject/fsobject.py
@@ -17,6 +17,7 @@ CONTAINER_EXTENSIONS = ('7z', 'ace', 'ar', 'arc', 'bz', 'bz2', 'cab', 'cpio',
 	'cpt', 'dgc', 'dmg', 'gz', 'iso', 'jar', 'msi', 'pkg', 'rar', 'shar',
 	'tar', 'tbz', 'tgz', 'xar', 'xz', 'zip')
 
+import re
 from os import access, listdir, lstat, readlink, stat
 from time import time
 from os.path import abspath, basename, dirname, realpath, splitext, extsep
@@ -27,6 +28,8 @@ from ranger.ext.spawn import spawn
 from ranger.ext.lazy_property import lazy_property
 from ranger.ext.human_readable import human_readable
 
+_extract_number_re = re.compile(r'(\d+)')
+
 class FileSystemObject(MimeTypeAware, FileManagerAware):
 	(basename,
 	basename_lower,
@@ -98,6 +101,16 @@ class FileSystemObject(MimeTypeAware, FileManagerAware):
 		except OSError:
 			return ""
 
+	@lazy_property
+	def basename_natural(self):
+		return [int(c) if c.isdigit() else c \
+			for c in _extract_number_re.split(self.basename)]
+
+	@lazy_property
+	def basename_natural_lower(self):
+		return [int(c) if c.isdigit() else c \
+			for c in _extract_number_re.split(self.basename_lower)]
+
 	def __str__(self):
 		"""returns a string containing the absolute path"""
 		return str(self.path)