summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/core/actions.py9
-rwxr-xr-xranger/ext/preview.sh21
-rw-r--r--ranger/fsobject/file.py21
-rw-r--r--ranger/gui/ansi.py17
-rw-r--r--ranger/gui/curses_shortcuts.py9
-rw-r--r--ranger/gui/widgets/pager.py20
6 files changed, 76 insertions, 21 deletions
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index 14f862c7..2db749cd 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -468,13 +468,8 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 		if not hasattr(self.ui, 'open_embedded_pager'):
 			return
 
-		try:
-			f = open(self.env.cf.path, 'r')
-		except:
-			pass
-		else:
-			pager = self.ui.open_embedded_pager()
-			pager.set_source(f)
+		pager = self.ui.open_embedded_pager()
+		pager.set_source(self.env.cf.get_preview_source())
 
 	# --------------------------
 	# -- Tabs
diff --git a/ranger/ext/preview.sh b/ranger/ext/preview.sh
new file mode 100755
index 00000000..80186e4d
--- /dev/null
+++ b/ranger/ext/preview.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+mimetype=$(file --mime-type -Lb "$1")
+basetype=$(echo "$mimetype" | grep -o '^[^/]\+')
+extension=$(echo "$1" | grep '\.' | grep -o '[^.]\+$')
+
+case "$basetype" in
+	text)
+		highlight --ansi "$1" || cat "$1"
+		exit 0;;
+	image)
+		img2txt "$1" || exit 1
+		exit 0;;
+esac
+
+case "$extension" in
+	zip|gz)
+		atool -l "$1"
+		exit 0;;
+esac
+
+exit 1
diff --git a/ranger/fsobject/file.py b/ranger/fsobject/file.py
index 2619fa35..25902f57 100644
--- a/ranger/fsobject/file.py
+++ b/ranger/fsobject/file.py
@@ -16,6 +16,9 @@
 import re
 import zipfile
 from ranger.fsobject import FileSystemObject
+from subprocess import Popen, PIPE
+from ranger.core.runner import devnull
+from ranger import relpath
 
 N_FIRST_BYTES = 20
 control_characters = set(chr(n) for n in
@@ -28,8 +31,8 @@ PREVIEW_BLACKLIST = re.compile(r"""
 			# 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
+				| avi | mpe?g | mp\d | og[gmv] | wm[av] | mkv | flv
+				| vob | wav | mpc | flac | divx? | xcf | pdf
 			# binary files:
 				| torrent | class | so | img | py[co] | dmg
 			# containers:
@@ -78,15 +81,21 @@ class File(FileSystemObject):
 			return False
 		if not self.accessible or self.is_fifo or self.is_device:
 			return False
+		if self.image or self.container:
+			return True
 		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():
+		if self.is_binary():
 			return False
 		return True
 
 	def get_preview_source(self):
-		if self.extension == 'zip':
-			return '\n'.join(zipfile.ZipFile(self.path).namelist())
-		return open(self.path, 'r')
+		try:
+			p = Popen([relpath('ext/preview.sh'), self.path],
+					stdout=PIPE, stderr=devnull)
+			if not p.poll():
+				return p.stdout
+		except:
+			return open(self.path, 'r')
diff --git a/ranger/gui/ansi.py b/ranger/gui/ansi.py
index fe0753a1..a9b37665 100644
--- a/ranger/gui/ansi.py
+++ b/ranger/gui/ansi.py
@@ -17,14 +17,15 @@
 from ranger.gui import color
 import re
 
-ansi_re = re.compile('(\033' + r'\[\d+(?:;\d+)*?[a-zA-Z])')
+ansi_re = re.compile('(\033' + r'\[\d*(?:;\d+)*?[a-zA-Z])')
+reset = '\033[0m'
 
 def split_ansi_from_text(ansi_text):
 	return ansi_re.split(ansi_text)
 
-def text_with_fg_bg(ansi_text):
+def text_with_fg_bg_attr(ansi_text):
 	for chunk in split_ansi_from_text(ansi_text):
-		if chunk[0] == '\033':
+		if chunk and chunk[0] == '\033':
 			if chunk[-1] != 'm':
 				continue
 			match = re.match(r'^.\[(.*).$', chunk)
@@ -33,9 +34,15 @@ def text_with_fg_bg(ansi_text):
 
 			# Convert arguments to attributes/colors
 			for arg in attr_args.split(';'):
-				n = int(arg)
+				try:
+					n = int(arg)
+				except:
+					if arg == '':
+						n = 0
+					else:
+						continue
 				if n == 0:
-					fg, bg, attr = 0, 0, 0
+					fg, bg, attr = -1, -1, 0
 				elif n == 1:
 					attr |= color.bold
 				elif n == 4:
diff --git a/ranger/gui/curses_shortcuts.py b/ranger/gui/curses_shortcuts.py
index 3df45700..42f9dada 100644
--- a/ranger/gui/curses_shortcuts.py
+++ b/ranger/gui/curses_shortcuts.py
@@ -1,4 +1,5 @@
 # Copyright (C) 2009, 2010  Roman Zimbelmann <romanz@lavabit.com>
+# Copyright (C) 2010 David Barnett <davidbarnett2@gmail.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
@@ -13,9 +14,11 @@
 # 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 curses
 import _curses
 
 from ranger.ext.iter_tools import flatten
+from ranger.gui.color import get_color
 from ranger.shared import SettingsAware
 
 def ascii_only(string):
@@ -95,6 +98,12 @@ class CursesShortcuts(SettingsAware):
 		except _curses.error:
 			pass
 
+	def set_fg_bg_attr(self, fg, bg, attr):
+		try:
+			self.win.attrset(curses.color_pair(get_color(fg, bg)) | attr)
+		except _curses.error:
+			pass
+
 	def color_reset(self):
 		"""Change the colors to the default colors"""
 		CursesShortcuts.color(self, 'reset')
diff --git a/ranger/gui/widgets/pager.py b/ranger/gui/widgets/pager.py
index c0bc98b4..58fcdfd1 100644
--- a/ranger/gui/widgets/pager.py
+++ b/ranger/gui/widgets/pager.py
@@ -1,4 +1,5 @@
 # Copyright (C) 2009, 2010  Roman Zimbelmann <romanz@lavabit.com>
+# Copyright (C) 2010 David Barnett <davidbarnett2@gmail.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
@@ -18,6 +19,7 @@ The pager displays text and allows you to scroll inside it.
 """
 import re
 from . import Widget
+from ranger.gui import ansi
 from ranger.ext.direction import Direction
 from ranger.container.keymap import CommandArgs
 
@@ -106,6 +108,13 @@ class Pager(Widget):
 
 			if TITLE_REGEXP.match(line):
 				self.color_at(i, 0, -1, 'title', *baseclr)
+		elif self.markup == 'ansi':
+			self.win.move(i, 0)
+			for chunk in ansi.text_with_fg_bg_attr(line):
+				if isinstance(chunk, tuple):
+					self.set_fg_bg_attr(*chunk)
+				else:
+					self.addstr(chunk)
 
 	def move(self, narg=None, **kw):
 		direction = Direction(kw)
@@ -158,12 +167,13 @@ class Pager(Widget):
 
 		if isinstance(source, str):
 			self.source_is_stream = False
-			self.lines = source.split('\n')
+			self.lines = source.splitlines()
 		elif hasattr(source, '__getitem__'):
 			self.source_is_stream = False
 			self.lines = source
 		elif hasattr(source, 'readline'):
 			self.source_is_stream = True
+			self.markup = 'ansi'
 			self.lines = []
 		else:
 			self.source = None
@@ -206,8 +216,12 @@ class Pager(Widget):
 		while True:
 			try:
 				line = self._get_line(i).expandtabs(4)
-				line = line[startx:self.wid + startx].rstrip()
-				yield line
+				if self.markup is 'ansi':
+					line = ansi.char_slice(line, startx, self.wid + startx) \
+							+ ansi.reset
+				else:
+					line = line[startx:self.wid + startx]
+				yield line.rstrip()
 			except IndexError:
 				raise StopIteration
 			i += 1