summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rwxr-xr-xranger.py4
-rw-r--r--ranger/applications.py12
-rw-r--r--ranger/gui/widgets/console.py56
3 files changed, 69 insertions, 3 deletions
diff --git a/ranger.py b/ranger.py
index 64ea365e..a81d0422 100755
--- a/ranger.py
+++ b/ranger.py
@@ -30,8 +30,8 @@ return 1
 __doc__ = """Ranger - file browser for the unix terminal"""
 
 
-# Importing of the main method may fail if the ranger directory
-# neither is in the same directory as this file, nor in one of
+# Importing the main method may fail if the ranger directory
+# is neither in the same directory as this file, nor in one of
 # pythons global import paths.
 try:
 	from ranger import main
diff --git a/ranger/applications.py b/ranger/applications.py
index c9f2ec18..d5c0f5fb 100644
--- a/ranger/applications.py
+++ b/ranger/applications.py
@@ -1,3 +1,11 @@
+"""
+List of allowed flags:
+s: silent mode. output will be discarded.
+d: detach the process.
+p: redirect output to the pager
+
+An uppercase key ensures that a certain flag will not be used.
+"""
 ALLOWED_FLAGS = 'sdpSDP'
 
 class Applications(object):
@@ -35,6 +43,10 @@ def run(*args, **kw):
 	popen_kw = {}
 	popen_kw['stdout'] = sys.stderr
 
+	for word in ('shell', 'stdout', 'stdin', 'stderr'):
+		if word in kw:
+			popen_kw[word] = kw[word]
+
 	if kw['stdin'] is not None:
 		popen_kw['stdin'] = kw['stdin']
 
diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py
index 2a4e24d9..2a69ea85 100644
--- a/ranger/gui/widgets/console.py
+++ b/ranger/gui/widgets/console.py
@@ -8,6 +8,7 @@ from collections import deque
 DEFAULT_HISTORY = 0
 SEARCH_HISTORY = 1
 QUICKOPEN_HISTORY = 2
+OPEN_HISTORY = 3
 
 class Console(Widget):
 	mode = None
@@ -28,10 +29,11 @@ class Console(Widget):
 		self.commandlist = CommandList()
 		self.settings.keys.initialize_console_commands(self.commandlist)
 		self.clear()
-		self.histories = [None] * 3
+		self.histories = [None] * 4
 		self.histories[DEFAULT_HISTORY] = History()
 		self.histories[SEARCH_HISTORY] = History()
 		self.histories[QUICKOPEN_HISTORY] = History()
+		self.histories[OPEN_HISTORY] = History()
 	
 	def init(self):
 		"""override this. Called directly after class change"""
@@ -263,8 +265,60 @@ class SearchConsole(Console):
 
 
 class OpenConsole(Console):
+	"""
+	The OpenConsole allows you to execute shell commands:
+	!vim *         will run vim and open all files in the directory.
+
+	There is a special syntax for more control:
+
+	!d! mplayer    will run mplayer with flags (d means detached)
+	!@ mplayer     will open the selected files with mplayer
+
+	those two can be combinated:
+
+	!d!@mplayer    will open the selection with a detached mplayer
+
+	For a list of other flags than "d", look at the documentation
+	of ranger.applications.
+	"""
 	prompt = '!'
 
+	def init(self):
+		self.history = self.histories[OPEN_HISTORY]
+	
+	def execute(self):
+		from ranger.applications import run
+		from subprocess import STDOUT, PIPE
+		command, flags = self._parse()
+		if command:
+			run(command, flags=flags, fm=self.fm,
+					mode=0, shell=True, stdin=None,
+					apps=self.fm.apps, stderr=STDOUT)
+		Console.execute(self)
+	
+	def _parse(self):
+		if '!' in self.line:
+			flags, cmd = self.line.split('!', 1)
+		else:
+			flags, cmd = '', self.line
+
+		add_selection = False
+		if cmd.startswith('@'):
+			cmd = cmd[1:]
+			add_selection = True
+		elif flags.startswith('@'):
+			flags = flags[1:]
+			add_selection = True
+
+		if add_selection:
+			cmd += ' ' + ' '.join(tuple(map(self._shellify,
+					self.env.get_selection())))
+
+		return (cmd, flags)
+
+	def _shellify(self, string):
+		return "'" + str(string).replace("'","'\"'\"'") + "'"
+
 
 class QuickOpenConsole(Console):
 	"""