about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/fsobject/file.py59
-rw-r--r--ranger/fsobject/fsobject.py9
-rw-r--r--ranger/gui/widgets/browsercolumn.py64
3 files changed, 76 insertions, 56 deletions
diff --git a/ranger/fsobject/file.py b/ranger/fsobject/file.py
index 4618df33..1d25e7d8 100644
--- a/ranger/fsobject/file.py
+++ b/ranger/fsobject/file.py
@@ -13,11 +13,47 @@
 # 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 re
+import stat
+import zipfile
+from StringIO import StringIO
+
 N_FIRST_BYTES = 20
 control_characters = set(chr(n) for n in
 		set(range(0, 9)) | set(range(14, 32)))
 
 from ranger.fsobject import FileSystemObject
+
+# Don't even try to preview files which mach this regular expression:
+PREVIEW_BLACKLIST = re.compile(r"""
+		# look at the extension:
+		\.(
+			# one character extensions:
+				[oa]
+			# media formats:
+				| avi | [mj]pe?g | mp\d | og[gmv] | wm[av] | mkv | flv
+				| png | bmp | vob | wav | mpc | flac | divx? | xcf | pdf
+			# binary files:
+				| torrent | class | so | img | py[co] | dmg
+			# containers:
+				| iso | rar | 7z | tar | gz | bz2 | tgz
+		)
+		# ignore filetype-independent suffixes:
+			(\.part|\.bak|~)?
+		# ignore fully numerical file extensions:
+			(\.\d+)*?
+		$
+""", re.VERBOSE | re.IGNORECASE)
+
+PREVIEW_WHITELIST = re.compile(r"""
+		\.(
+			txt | py | c
+		)
+		# ignore filetype-independent suffixes:
+			(\.part|\.bak|~)?
+		$
+""", re.VERBOSE | re.IGNORECASE)
+
 class File(FileSystemObject):
 	is_file = True
 
@@ -38,3 +74,26 @@ class File(FileSystemObject):
 		if self.firstbytes and control_characters & set(self.firstbytes):
 			return True
 		return False
+
+	def has_preview(self):
+		if not (self.is_file \
+				and self.accessible \
+				and self.stat \
+				and not self.is_device \
+				and not self.stat.st_mode & stat.S_IFIFO):
+			return False
+
+		if PREVIEW_WHITELIST.search(self.basename):
+			return True
+		if PREVIEW_BLACKLIST.search(self.basename):
+			return False
+		if self.extension not in ('zip',) and self.is_binary():
+			return False
+		return True
+
+	def get_preview_source(self):
+		if self.extension == 'zip':
+			contents = '\n'.join(zipfile.ZipFile(self.path).namelist())
+			return StringIO(contents)
+		return open(self.path, 'r')
+
diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py
index afef48e4..d570d009 100644
--- a/ranger/fsobject/fsobject.py
+++ b/ranger/fsobject/fsobject.py
@@ -19,7 +19,7 @@ CONTAINER_EXTENSIONS = ('7z', 'ace', 'ar', 'arc', 'bz', 'bz2', 'cab', 'cpio',
 
 from os import access, listdir, lstat, readlink, stat
 from time import time
-from os.path import abspath, basename, dirname, realpath
+from os.path import abspath, basename, dirname, realpath, splitext, extsep
 from . import BAD_INFO
 from ranger.shared import MimeTypeAware, FileManagerAware
 from ranger.ext.shell_escape import shell_escape
@@ -76,6 +76,7 @@ class FileSystemObject(MimeTypeAware, FileManagerAware):
 		self.path = path
 		self.basename = basename(path)
 		self.basename_lower = self.basename.lower()
+		self.extension = splitext(self.basename)[1].lstrip(extsep) or None
 		self.dirname = dirname(path)
 		self.realpath = self.path
 		self.preload = preload
@@ -300,3 +301,9 @@ class FileSystemObject(MimeTypeAware, FileManagerAware):
 			self.load()
 			return True
 		return False
+
+	def get_preview_source(self):
+		"""
+		Override this to get a file object for a preview pane, or None for
+		no preview.
+		"""
diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py
index 1e24e2dd..b8657ae3 100644
--- a/ranger/gui/widgets/browsercolumn.py
+++ b/ranger/gui/widgets/browsercolumn.py
@@ -14,7 +14,6 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 """The BrowserColumn widget displays the contents of a directory or file."""
-import re
 import stat
 from time import time
 
@@ -22,36 +21,6 @@ from . import Widget
 from .pager import Pager
 from ranger.fsobject import BAD_INFO
 
-# Don't even try to preview files which mach this regular expression:
-PREVIEW_BLACKLIST = re.compile(r"""
-		# look at the extension:
-		\.(
-			# one character extensions:
-				[oa]
-			# media formats:
-				| avi | [mj]pe?g | mp\d | og[gmv] | wm[av] | mkv | flv
-				| png | bmp | vob | wav | mpc | flac | divx? | xcf | pdf
-			# binary files:
-				| torrent | class | so | img | py[co] | dmg
-			# containers:
-				| iso | rar | zip | 7z | tar | gz | bz2 | tgz
-		)
-		# ignore filetype-independent suffixes:
-			(\.part|\.bak|~)?
-		# ignore fully numerical file extensions:
-			(\.\d+)*?
-		$
-""", re.VERBOSE | re.IGNORECASE)
-
-PREVIEW_WHITELIST = re.compile(r"""
-		\.(
-			txt | py | c
-		)
-		# ignore filetype-independent suffixes:
-			(\.part|\.bak|~)?
-		$
-""", re.VERBOSE | re.IGNORECASE)
-
 class BrowserColumn(Pager):
 	main_column = False
 	display_infostring = False
@@ -123,11 +92,11 @@ class BrowserColumn(Pager):
 		return True
 
 	def has_preview(self):
-		if self.target is None:
+		if self.target is None or self.settings.preview_files == False:
 			return False
 
 		if self.target.is_file:
-			if not self._preview_this_file(self.target):
+			if not self.target.has_preview():
 				return False
 
 		if self.target.is_directory:
@@ -173,24 +142,6 @@ class BrowserColumn(Pager):
 			self.need_redraw = False
 			self.last_redraw_time = time()
 
-	def _preview_this_file(self, target):
-		if not (target \
-				and self.settings.preview_files \
-				and target.is_file \
-				and target.accessible \
-				and target.stat \
-				and not target.is_device \
-				and not target.stat.st_mode & stat.S_IFIFO):
-			return False
-
-		if PREVIEW_WHITELIST.search(target.basename):
-			return True
-		if PREVIEW_BLACKLIST.search(target.basename):
-			return False
-		if target.is_binary():
-			return False
-		return True
-
 	def _draw_file(self):
 		"""Draw a preview of the file, if the settings allow it"""
 		self.win.move(0, 0)
@@ -199,17 +150,20 @@ class BrowserColumn(Pager):
 			Pager.close(self)
 			return
 
-		if not self._preview_this_file(self.target):
+		if self.target is None or not self.target.has_preview():
 			Pager.close(self)
 			return
 
 		try:
-			f = open(self.target.path, 'r')
+			f = self.target.get_preview_source()
 		except:
 			Pager.close(self)
 		else:
-			self.set_source(f)
-			Pager.draw(self)
+			if f is None:
+				Pager.close(self)
+			else:
+				self.set_source(f)
+				Pager.draw(self)
 
 	def _draw_directory(self):
 		"""Draw the contents of a directory"""