summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/__init__.py2
-rw-r--r--ranger/container/settingobject.py1
-rw-r--r--ranger/core/actions.py5
-rw-r--r--ranger/defaults/apps.py44
-rw-r--r--ranger/defaults/options.py6
-rw-r--r--ranger/defaults/rc.conf3
-rw-r--r--ranger/ext/human_readable.py24
-rw-r--r--ranger/fsobject/directory.py48
-rw-r--r--ranger/fsobject/fsobject.py3
-rw-r--r--ranger/gui/widgets/statusbar.py8
10 files changed, 112 insertions, 32 deletions
diff --git a/ranger/__init__.py b/ranger/__init__.py
index df413a2c..df759dc8 100644
--- a/ranger/__init__.py
+++ b/ranger/__init__.py
@@ -36,7 +36,7 @@ TIME_BEFORE_FILE_BECOMES_GARBAGE = 1200
 MACRO_DELIMITER = '%'
 LOGFILE = '/tmp/ranger_errorlog'
 USAGE = '%prog [options] [path/filename]'
-STABLE = True
+STABLE = False
 
 # If the environment variable XDG_CONFIG_HOME is non-empty, CONFDIR is ignored
 # and the configuration directory will be $XDG_CONFIG_HOME/ranger instead.
diff --git a/ranger/container/settingobject.py b/ranger/container/settingobject.py
index 5c24d663..51c12c6e 100644
--- a/ranger/container/settingobject.py
+++ b/ranger/container/settingobject.py
@@ -19,6 +19,7 @@ from ranger.core.shared import FileManagerAware
 
 ALLOWED_SETTINGS = {
 	'autosave_bookmarks': bool,
+	'autoupdate_cumulative_size': bool,
 	'collapse_preview': bool,
 	'colorscheme_overlay': (type(None), type(lambda:0)),
 	'colorscheme': str,
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index c8922734..5364f391 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -87,6 +87,11 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 			self.notify("Aborting: " + item.get_description())
 			self.loader.remove(index=0)
 
+	def get_cumulative_size(self):
+		for f in self.env.get_selection() or ():
+			f.look_up_cumulative_size()
+		self.ui.redraw_main_column()
+
 	def redraw_window(self):
 		"""Redraw the window"""
 		self.ui.redraw_window()
diff --git a/ranger/defaults/apps.py b/ranger/defaults/apps.py
index 3ec6bff2..a53e2c8b 100644
--- a/ranger/defaults/apps.py
+++ b/ranger/defaults/apps.py
@@ -97,23 +97,35 @@ class CustomApplications(Applications):
 
 		if f.extension is not None:
 			if f.extension in ('pdf', ):
-				return self.either(c, 'evince', 'zathura', 'apvlv')
+				return self.either(c, 'evince', 'zathura', 'apvlv', 'okular')
 			if f.extension == 'djvu':
 				return self.either(c, 'evince')
-			if f.extension in ('xml', ):
+			if f.extension in ('xml', 'csv'):
 				return self.either(c, 'editor')
+			if f.extension in ('html', 'htm', 'xhtml') or f.extension == 'swf':
+				c.flags += 'd'
+				handler = self.either(c,
+						'luakit', 'uzbl', 'vimprobable', 'vimprobable2', 'jumanji',
+						'firefox', 'seamonkey', 'iceweasel', 'opera',
+						'surf', 'midori', 'epiphany', 'konqueror')
+				# Only return if some program was found:
+				if handler:
+					return handler
 			if f.extension in ('html', 'htm', 'xhtml'):
-				return self.either(c, 'firefox', 'opera', 'jumanji',
-						'luakit', 'elinks', 'lynx')
-			if f.extension == 'swf':
-				return self.either(c, 'firefox', 'opera', 'jumanji', 'luakit')
+				# These browsers can't handle flash, so they're not called above.
+				c.flags += 'D'
+				return self.either(c, 'elinks', 'links', 'links2', 'lynx', 'w3m')
 			if f.extension == 'nes':
 				return self.either(c, 'fceux')
 			if f.extension in ('swc', 'smc', 'sfc'):
 				return self.either(c, 'zsnes')
-			if f.extension in ('odt', 'ods', 'odp', 'odf', 'odg',
-					'doc', 'xls'):
-				return self.either(c, 'libreoffice', 'soffice', 'ooffice')
+			if f.extension == 'doc':
+				return self.either(c, 'abiword', 'libreoffice',
+						'soffice', 'ooffice')
+			if f.extension in ('odt', 'ods', 'odp', 'odf', 'odg', 'sxc',
+					'stc', 'xls', 'xlsx', 'xlt', 'xlw', 'gnm', 'gnumeric'):
+				return self.either(c, 'gnumeric', 'kspread',
+						'libreoffice', 'soffice', 'ooffice')
 
 		if f.mimetype is not None:
 			if INTERPRETED_LANGUAGES.match(f.mimetype):
@@ -125,8 +137,8 @@ class CustomApplications(Applications):
 		if f.video or f.audio:
 			if f.video:
 				c.flags += 'd'
-			return self.either(c, 'mplayer2', 'mplayer', 'smplayer', 'vlc',
-					'totem')
+			return self.either(c, 'smplayer', 'gmplayer', 'mplayer2',
+					'mplayer', 'vlc', 'totem')
 
 		if f.image:
 			if c.mode in (11, 12, 13, 14):
@@ -281,8 +293,14 @@ class CustomApplications(Applications):
 CustomApplications.generic('fceux', 'wine', 'zsnes', deps=['X'])
 
 # Add those which should only run in X AND should be detached/forked here:
-CustomApplications.generic('opera', 'firefox', 'apvlv', 'evince',
-		'zathura', 'gimp', 'mirage', 'eog', 'jumanji',
+CustomApplications.generic(
+	'luakit', 'uzbl', 'vimprobable', 'vimprobable2', 'jumanji',
+	'firefox', 'seamonkey', 'iceweasel', 'opera',
+	'surf', 'midori', 'epiphany', 'konqueror',
+	'evince', 'zathura', 'apvlv', 'okular',
+	'eog', 'mirage', 'gimp',
+	'libreoffice', 'soffice', 'ooffice', 'gnumeric', 'kspread', 'abiword',
+	'gmplayer', 'smplayer', 'vlc',
 			flags='d', deps=['X'])
 
 # What filetypes are recognized as scripts for interpreted languages?
diff --git a/ranger/defaults/options.py b/ranger/defaults/options.py
index 3b44d4f6..92b9ada9 100644
--- a/ranger/defaults/options.py
+++ b/ranger/defaults/options.py
@@ -104,6 +104,12 @@ padding_right = True
 # When false, bookmarks are saved when ranger is exited.
 autosave_bookmarks = True
 
+# You can display the "real" cumulative size of directories by using the
+# command :get_cumulative_size or typing "dc".  The size is expensive to
+# calculate and will not be updated automatically.  You can choose
+# to update it automatically though by turning on this option:
+autoupdate_cumulative_size = False
+
 # Makes sense for screen readers:
 show_cursor = False
 
diff --git a/ranger/defaults/rc.conf b/ranger/defaults/rc.conf
index a9e64622..b8106663 100644
--- a/ranger/defaults/rc.conf
+++ b/ranger/defaults/rc.conf
@@ -216,6 +216,8 @@ map oC chain set sort=ctime;     set sort_reverse=True
 map oA chain set sort=atime;     set sort_reverse=True
 map oT chain set sort="type";    set sort_reverse=True
 
+map dc get_cumulative_size
+
 # Settings
 map zc    toggle_option collapse_preview
 map zd    toggle_option sort_directories_first
@@ -226,6 +228,7 @@ map zm    toggle_option mouse_enabled
 map zp    toggle_option preview_files
 map zP    toggle_option preview_directories
 map zs    toggle_option sort_case_insensitive
+map zu    toggle_option autoupdate_cumulative_size
 map zv    toggle_option use_preview_script
 map zf    console filter 
 
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/fsobject/directory.py b/ranger/fsobject/directory.py
index b3a35a0a..bc09b080 100644
--- a/ranger/fsobject/directory.py
+++ b/ranger/fsobject/directory.py
@@ -25,6 +25,7 @@ from ranger.fsobject import File, FileSystemObject
 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
 
 def sort_by_basename(path):
 	"""returns path.basename (for sorting)"""
@@ -79,6 +80,8 @@ class Directory(FileSystemObject, Accumulator, Loadable, SettingsAware):
 	content_outdated = False
 	content_loaded = False
 
+	_cumulative_size_calculated = False
+
 	sort_dict = {
 		'basename': sort_by_basename,
 		'natural': sort_naturally,
@@ -185,8 +188,25 @@ class Directory(FileSystemObject, Accumulator, Loadable, SettingsAware):
 				hidden_filter = not self.settings.show_hidden \
 						and self.settings.hidden_filter
 				filelist = os.listdir(mypath)
-				self.size = len(filelist)
-				self.infostring = ' %d' % self.size
+
+				if self._cumulative_size_calculated:
+					# If self.content_loaded is true, this is not the first
+					# time loading.  So I can't really be sure if the
+					# size has changed and I'll add a "?".
+					if self.content_loaded:
+						if self.fm.settings.autoupdate_cumulative_size:
+							self.look_up_cumulative_size()
+						else:
+							self.infostring = ' %s' % human_readable(
+								self.size, separator='? ')
+					else:
+						self.infostring = ' %s' % human_readable(self.size)
+				else:
+					self.size = len(filelist)
+					self.infostring = ' %d' % self.size
+				if self.is_link:
+					self.infostring = '->' + self.infostring
+
 				filenames = [mypath + (mypath == '/' and fname or '/' + fname)\
 						for fname in filelist if accept_file(
 							fname, mypath, hidden_filter, self.filter)]
@@ -327,6 +347,30 @@ class Directory(FileSystemObject, Accumulator, Loadable, SettingsAware):
 		else:
 			self.correct_pointer()
 
+	def _get_cumulative_size(self):
+		if self.size == 0:
+			return 0
+		cum = 0
+		realpath = os.path.realpath
+		for dirpath, dirnames, filenames in os.walk(self.path,
+				onerror=lambda _: None):
+			for file in filenames:
+				try:
+					if dirpath == self.path:
+						stat = os_stat(realpath(dirpath + "/" + file))
+					else:
+						stat = os_stat(dirpath + "/" + file)
+					cum += stat.st_size
+				except:
+					pass
+		return cum
+
+	def look_up_cumulative_size(self):
+		self._cumulative_size_calculated = True
+		self.size = self._get_cumulative_size()
+		self.infostring = ('-> ' if self.is_link else ' ') + \
+				human_readable(self.size)
+
 	@lazy_property
 	def size(self):
 		try:
diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py
index d74b21c1..51e49808 100644
--- a/ranger/fsobject/fsobject.py
+++ b/ranger/fsobject/fsobject.py
@@ -117,6 +117,9 @@ class FileSystemObject(FileManagerAware):
 	def use(self):
 		"""Used in garbage-collecting.  Override in Directory"""
 
+	def look_up_cumulative_size(self):
+		pass # normal files have no cumulative size
+
 	def set_mimetype(self):
 		"""assign attributes such as self.video according to the mimetype"""
 		basename = self.basename
diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py
index 1e2e2520..b7a238da 100644
--- a/ranger/gui/widgets/statusbar.py
+++ b/ranger/gui/widgets/statusbar.py
@@ -231,17 +231,17 @@ class StatusBar(Widget):
 
 		if target.marked_items:
 			if len(target.marked_items) == len(target.files):
-				right.add(human_readable(target.disk_usage, seperator=''))
+				right.add(human_readable(target.disk_usage, separator=''))
 			else:
 				right.add(human_readable(sum(f.size \
 					for f in target.marked_items \
-					if f.is_file), seperator=''))
+					if f.is_file), separator=''))
 			right.add("/" + str(len(target.marked_items)))
 		else:
-			right.add(human_readable(target.disk_usage, seperator='') +
+			right.add(human_readable(target.disk_usage, separator='') +
 					" sum, ")
 			right.add(human_readable(self.env.get_free_space( \
-					target.mount_path), seperator='') + " free")
+					target.mount_path), separator='') + " free")
 		right.add("  ", "space")
 
 		if target.marked_items: