summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/api/apps.py7
-rw-r--r--ranger/colorschemes/default.py3
-rw-r--r--ranger/core/actions.py7
-rw-r--r--ranger/core/fm.py6
-rw-r--r--ranger/defaults/apps.py3
-rw-r--r--ranger/defaults/keys.py1
-rw-r--r--ranger/ext/get_all_modules.py23
-rw-r--r--ranger/ext/get_executables.py33
-rw-r--r--ranger/ext/waitpid_no_intr.py9
-rw-r--r--ranger/fsobject/directory.py5
-rw-r--r--ranger/gui/context.py2
-rw-r--r--ranger/gui/widgets/browsercolumn.py3
-rw-r--r--ranger/gui/widgets/browserview.py2
-rw-r--r--ranger/gui/widgets/console.py9
-rw-r--r--ranger/gui/widgets/statusbar.py11
15 files changed, 68 insertions, 56 deletions
diff --git a/ranger/api/apps.py b/ranger/api/apps.py
index a17a6601..309c0db6 100644
--- a/ranger/api/apps.py
+++ b/ranger/api/apps.py
@@ -20,6 +20,7 @@ This module provides helper functions/classes for ranger.apps.
 import os, sys, re
 from subprocess import Popen, PIPE
 from ranger.ext.iter_tools import flatten
+from ranger.ext.get_executables import get_executables
 from ranger.shared import FileManagerAware
 
 
@@ -68,7 +69,7 @@ class Applications(FileManagerAware):
 			if hasattr(dep, 'dependencies') \
 			and not self._meets_dependencies(dep):
 				return False
-			if dep not in self.fm.executables:
+			if dep not in get_executables():
 				return False
 
 		return True
@@ -78,7 +79,7 @@ class Applications(FileManagerAware):
 			try:
 				application_handler = getattr(self, 'app_' + app)
 			except AttributeError:
-				if app in self.fm.executables:
+				if app in get_executables():
 					return tup(app, *context)
 				continue
 			if self._meets_dependencies(application_handler):
@@ -101,7 +102,7 @@ class Applications(FileManagerAware):
 		try:
 			handler = getattr(self, 'app_' + app)
 		except AttributeError:
-			if app in self.fm.executables:
+			if app in get_executables():
 				return tup(app, *context)  # generic app
 			handler = self.app_default
 		return handler(context)
diff --git a/ranger/colorschemes/default.py b/ranger/colorschemes/default.py
index 24f8ab91..ca8456e7 100644
--- a/ranger/colorschemes/default.py
+++ b/ranger/colorschemes/default.py
@@ -59,6 +59,9 @@ class Default(ColorScheme):
 					fg = white
 				else:
 					fg = red
+			if not context.selected and (context.cut or context.copied):
+				fg = black
+				attr |= bold
 			if context.main_column:
 				if context.selected:
 					attr |= bold
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index b0ec289f..a07b4ae0 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -538,16 +538,23 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 	# -- File System Operations
 	# --------------------------
 
+	def uncut(self):
+		self.env.copy = set()
+		self.env.cut = False
+		self.ui.browser.main_column.request_redraw()
+
 	def copy(self):
 		"""Copy the selected items"""
 
 		selected = self.env.get_selection()
 		self.env.copy = set(f for f in selected if f in self.env.cwd.files)
 		self.env.cut = False
+		self.ui.browser.main_column.request_redraw()
 
 	def cut(self):
 		self.copy()
 		self.env.cut = True
+		self.ui.browser.main_column.request_redraw()
 
 	def paste_symlink(self):
 		from os import symlink, getcwd
diff --git a/ranger/core/fm.py b/ranger/core/fm.py
index ae815fbf..459620c6 100644
--- a/ranger/core/fm.py
+++ b/ranger/core/fm.py
@@ -50,7 +50,6 @@ class FM(Actions, SignalDispatcher):
 		self.tabs = {}
 		self.current_tab = 1
 		self.loader = Loader()
-		self._executables = None
 		self.apps = self.settings.apps.CustomApplications()
 
 		def mylogfunc(text):
@@ -67,9 +66,8 @@ class FM(Actions, SignalDispatcher):
 
 	@property
 	def executables(self):
-		if self._executables is None:
-			self._executables = sorted(get_executables())
-		return self._executables
+		"""For compatibility. Calls get_executables()"""
+		return get_executables()
 
 	def initialize(self):
 		"""If ui/bookmarks are None, they will be initialized here."""
diff --git a/ranger/defaults/apps.py b/ranger/defaults/apps.py
index b3500c0d..45f2ace3 100644
--- a/ranger/defaults/apps.py
+++ b/ranger/defaults/apps.py
@@ -46,6 +46,7 @@ This example modifies the behaviour of "feh" and adds a custom media player:
 """
 
 from ranger.api.apps import *
+from ranger.ext.get_executables import get_executables
 
 INTERPRETED_LANGUAGES = re.compile(r'''
 	^(text|application)\/x-(
@@ -103,7 +104,7 @@ class CustomApplications(Applications):
 		else:
 			parts = default_editor.split()
 			exe_name = os.path.basename(parts[0])
-			if exe_name in self.fm.executables:
+			if exe_name in get_executables():
 				return tuple(parts) + tuple(c)
 
 		return self.either(c, 'vim', 'emacs', 'nano')
diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py
index 81ebfea0..c181857e 100644
--- a/ranger/defaults/keys.py
+++ b/ranger/defaults/keys.py
@@ -133,6 +133,7 @@ map('V', fm.mark(all=True, val=False))
 # ------------------------------------------ file system operations
 map('yy', 'y<dir>', fm.copy())
 map('dd', 'd<dir>', fm.cut())
+map('ud', fm.uncut())
 map('pp', fm.paste())
 map('po', fm.paste(overwrite=True))
 map('pl', fm.paste_symlink())
diff --git a/ranger/ext/get_all_modules.py b/ranger/ext/get_all_modules.py
deleted file mode 100644
index 62c81437..00000000
--- a/ranger/ext/get_all_modules.py
+++ /dev/null
@@ -1,23 +0,0 @@
-# Copyright (C) 2009, 2010  Roman Zimbelmann <romanz@lavabit.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
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# 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 get_all_modules(dirname):
-	"""returns a list of strings containing the names of modules in a directory"""
-	import os
-	result = []
-	for filename in os.listdir(dirname):
-		if filename.endswith('.py') and not filename.startswith('_'):
-			result.append(filename[0:filename.index('.')])
-	return result
diff --git a/ranger/ext/get_executables.py b/ranger/ext/get_executables.py
index 9eeb3345..22c08eb9 100644
--- a/ranger/ext/get_executables.py
+++ b/ranger/ext/get_executables.py
@@ -13,12 +13,28 @@
 # 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 stat
-import os
-from os.path import isfile, join, exists
+from stat import S_IXOTH, S_IFREG
 from ranger.ext.iter_tools import unique
+from os import listdir, environ, stat
+from os.path import join
 
-def get_executables(*paths):
+
+_cached_executables = None
+
+
+def get_executables():
+	"""
+	Return all executable files in each of the given directories.
+
+	Looks in $PATH by default.
+	"""
+	global _cached_executables
+	if _cached_executables is None:
+		_cached_executables = sorted(get_executables_uncached())
+	return _cached_executables
+
+
+def get_executables_uncached(*paths):
 	"""
 	Return all executable files in each of the given directories.
 
@@ -26,7 +42,7 @@ def get_executables(*paths):
 	"""
 	if not paths:
 		try:
-			pathstring = os.environ['PATH']
+			pathstring = environ['PATH']
 		except KeyError:
 			return ()
 		paths = unique(pathstring.split(':'))
@@ -34,15 +50,16 @@ def get_executables(*paths):
 	executables = set()
 	for path in paths:
 		try:
-			content = os.listdir(path)
+			content = listdir(path)
 		except:
 			continue
 		for item in content:
 			abspath = join(path, item)
 			try:
-				filestat = os.stat(abspath)
+				filestat = stat(abspath)
 			except:
 				continue
-			if filestat.st_mode & (stat.S_IXOTH | stat.S_IFREG):
+			if filestat.st_mode & (S_IXOTH | S_IFREG):
 				executables.add(item)
 	return executables
+
diff --git a/ranger/ext/waitpid_no_intr.py b/ranger/ext/waitpid_no_intr.py
index c14fa5b9..12fbcbce 100644
--- a/ranger/ext/waitpid_no_intr.py
+++ b/ranger/ext/waitpid_no_intr.py
@@ -13,17 +13,18 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+from errno import EINTR
+from os import waitpid
+
 def waitpid_no_intr(pid):
 	"""catch interrupts which occur while using os.waitpid"""
-	import os, errno
-
 	while True:
 		try:
-			return os.waitpid(pid, 0)
+			return waitpid(pid, 0)
 		except KeyboardInterrupt:
 			continue
 		except OSError as e:
-			if e.errno == errno.EINTR:
+			if e.errno == EINTR:
 				continue
 			else:
 				raise
diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py
index bf626004..3574f329 100644
--- a/ranger/fsobject/directory.py
+++ b/ranger/fsobject/directory.py
@@ -237,6 +237,7 @@ class Directory(FileSystemObject, Accumulator, SettingsAware):
 		Loads the contents of the directory. Use this sparingly since
 		it takes rather long.
 		"""
+		self.content_outdated = False
 
 		if not self.loading:
 			self.load_once()
@@ -370,8 +371,7 @@ class Directory(FileSystemObject, Accumulator, SettingsAware):
 
 		if self.load_content_once(*a, **k): return True
 
-		if self.content_outdated:
-			self.content_outdated = False
+		if self.files is None or self.content_outdated:
 			self.load_content(*a, **k)
 			return True
 
@@ -403,6 +403,7 @@ class Directory(FileSystemObject, Accumulator, SettingsAware):
 		"""The number of containing files"""
 		if not self.accessible or not self.content_loaded:
 			raise ranger.fsobject.NotLoadedYet()
+		assert self.files is not None
 		return len(self.files)
 
 	def __eq__(self, other):
diff --git a/ranger/gui/context.py b/ranger/gui/context.py
index 4ea50714..d4c1c94d 100644
--- a/ranger/gui/context.py
+++ b/ranger/gui/context.py
@@ -23,7 +23,7 @@ CONTEXT_KEYS = ['reset', 'error',
 		'good', 'bad',
 		'space', 'permissions', 'owner', 'group', 'mtime', 'nlink',
 		'scroll', 'all', 'bot', 'top', 'percentage',
-		'marked', 'tagged', 'tag_marker',
+		'marked', 'tagged', 'tag_marker', 'cut', 'copied',
 		'help_markup',
 		'seperator', 'key', 'special', 'border',
 		'title', 'text', 'highlight', 'bars', 'quotes', 'tab',
diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py
index 4e93ed3e..8cf8990c 100644
--- a/ranger/gui/widgets/browsercolumn.py
+++ b/ranger/gui/widgets/browsercolumn.py
@@ -281,6 +281,9 @@ class BrowserColumn(Pager):
 				if stat.S_ISSOCK(mode):
 					this_color.append('socket')
 
+			if self.env.copy and drawn in self.env.copy:
+				this_color.append('cut' if self.env.cut else 'copied')
+
 			if drawn.islink:
 				this_color.append('link')
 				this_color.append(drawn.exists and 'good' or 'bad')
diff --git a/ranger/gui/widgets/browserview.py b/ranger/gui/widgets/browserview.py
index 1995b714..466e23eb 100644
--- a/ranger/gui/widgets/browserview.py
+++ b/ranger/gui/widgets/browserview.py
@@ -264,7 +264,7 @@ class BrowserView(Widget, DisplayableContainer):
 	def poke(self):
 		DisplayableContainer.poke(self)
 		if self.settings.collapse_preview and self.preview:
-			has_preview = self.columns[-2].has_preview()
+			has_preview = self.columns[-1].has_preview()
 			if self.preview_available != has_preview:
 				self.preview_available = has_preview
 				self.resize(self.y, self.x, self.hei, self.wid)
diff --git a/ranger/gui/widgets/console.py b/ranger/gui/widgets/console.py
index 0e949d3b..a27e1956 100644
--- a/ranger/gui/widgets/console.py
+++ b/ranger/gui/widgets/console.py
@@ -27,8 +27,9 @@ from ranger.defaults import commands
 from ranger.gui.widgets.console_mode import is_valid_mode, mode_to_class
 from ranger import log, relpath_conf
 from ranger.ext.shell_escape import shell_quote
-from ranger.ext.direction import Direction
 from ranger.container.keymap import CommandArgs
+from ranger.ext.get_executables import get_executables
+from ranger.ext.direction import Direction
 import ranger
 
 DEFAULT_HISTORY = 0
@@ -443,8 +444,8 @@ class OpenConsole(ConsoleWithTab):
 		try:
 			position_of_last_space = line.rindex(" ")
 		except ValueError:
-			return (start + program + ' ' for program in self.fm.executables \
-					if program.startswith(line))
+			return (start + program + ' ' for program \
+					in get_executables() if program.startswith(line))
 		if position_of_last_space == len(line) - 1:
 			return self.line + '%s '
 		else:
@@ -613,7 +614,7 @@ class QuickOpenConsole(ConsoleWithTab):
 
 	def _is_app(self, arg):
 		return self.fm.apps.has(arg) or \
-			(not self._is_flags(arg) and arg in self.fm.executables)
+			(not self._is_flags(arg) and arg in get_executables())
 
 	def _is_flags(self, arg):
 		from ranger.core.runner import ALLOWED_FLAGS
diff --git a/ranger/gui/widgets/statusbar.py b/ranger/gui/widgets/statusbar.py
index 75fbbe89..78666a3d 100644
--- a/ranger/gui/widgets/statusbar.py
+++ b/ranger/gui/widgets/statusbar.py
@@ -146,10 +146,9 @@ class StatusBar(Widget):
 		else:
 			target = self.env.at_level(0).pointed_obj
 
-		if target is None:
-			return
-
-		if target.accessible is False:
+		if target is None \
+				or not target.accessible \
+				or (target.is_directory and target.files is None):
 			return
 
 		perms = target.get_permission_string()
@@ -208,7 +207,9 @@ class StatusBar(Widget):
 		if target is None:
 			return
 
-		if not target.content_loaded or not target.accessible:
+		if target is None \
+				or not target.accessible \
+				or (target.is_directory and target.files is None):
 			return
 
 		pos = target.scroll_begin
akspecs/ranger/blame/TODO?h=v1.9.2&id=e6710b99555c3a7e0d80c0c19f8474ac4a5dcc0a'>^
d994d0d6 ^
01c89bb5 ^
c776804d ^
dab4db44 ^
cc4210ff ^
34c131ef ^
66c5bb93 ^
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96

       

                                      
                               
                                         
                                                    



       
                                                    
                                           
                                     
                                                                

                                                                  
                            
                                                               
                                                        
                                                        
                                       
                                 
                                                             
                                       
                                                  
                                                                        
                                             
                                                                      
                                                           
                                                           
                                        
                                                
                                                              
                                                                     
                                            
                                                  
                                                                          
                                         
                                                     

                                                                        

                                                              
                                                      
                                                      

                                                
                                                   
                                                
                                                           
                                     
                                                    



    
                                                           
                                                              
                                               
                                                                   
                                                                 
                                                              
                                                                              

                                                   
                                                                
                                                           
                                        
                                                          
                                                             
                                            
                                                     
                                                                                  
                                           
                                                              
                                                                        
                                            
                                                                           




                                                               
                                  
                                                                     
                                                                
                                                 
                                                           
                                              
                                                         
                                                                
                                         
                                                   
                                                       
 
Console

   (X) #0   09/12/06  console commands
   (X) #1   09/12/06  quick find
   (X) #2   09/12/06  open with
   (X) #4   09/12/06  history for console
   (X) #13  09/12/27  display docstring of a command


General

   (X) #5   09/12/06  move code from fm into objects
   (X) #6   09/12/06  move main to __init__
   (X) #7   09/12/06  cooler titlebar
   (X) #8   09/12/17  Add operations to modify files/directories
   (X) #9   09/12/24  add a widget for managing running operations
   (X) #10  09/12/24  sorting
   (X) #11  09/12/27  filter
   (X) #12  09/12/27  jump through the list in a specific order
   (X) #14  09/12/29  make filelists inherit from pagers
   (X) #15  09/12/29  better way of running processes!!~
   (X) #16  10/01/01  list of bookmarks
   (X) #21  10/01/01  write help!
   (X) #22  10/01/03  add getopt options to change flags/mode
   (X) #29  10/01/06  add chmod command
   (X) #30  10/01/06  add a way to create symlinks
   (X) #32  10/01/08  place the (hidden) cursor to a meaningful position
   (X) #34  10/01/09  display free disk space
   (X) #35  10/01/09  display disk usage of files in current directory
   ( ) #36  10/01/11  help coloring is terribly inefficient
   (X) #37  10/01/13  better tab completion for OpenConsole
   ( ) #38  10/01/16  searching in pager
   (X) #39  10/01/17  flushinput not always good
   (X) #42  10/01/17  memorize directory for `` when using :cd
   (X) #43  10/01/18  internally treat the bookmarks ` and ' the same
   ( ) #44  10/01/18  more error messages :P
   (X) #47  10/01/19  less restricive auto preview
   (X) #48  10/01/19  abbreviate commands with first unambiguous substring
   ( ) #50  10/01/19  add more unit tests
   ( ) #51  10/01/21  remove directory.marked_items ?
   (X) #55  10/01/24  allow change of filename when pasting
          you're given the choice between overwriting or appending a "_"
   ( ) #56  10/01/30  warn before deleting mount points
   ( ) #57  10/01/30  warn before deleting unseen marked files
   (X) #58  10/02/04  change the title of the terminal
   (X) #61  10/02/09  show sum of size of marked files
   (X) #63  10/02/15  limit filesize in previews
   ( ) #64  10/02/25  scroll in previews
   (X) #66  10/02/28  explain how colorschemes work
   (X) #70  10/03/14  mouse handler for titlebar
   (X) #71  10/03/21  previews: black/whitelist + read file
   (X) #79  10/04/08  tab number zero
   ( ) #80  10/04/08  when closing tabs, avoid gaps?


Bugs

   (X) #17  10/01/01  why do bookmarks disappear sometimes?
   (X) #18  10/01/01  fix notify widget (by adding a LogView?)
   (X) #19  10/01/01  resizing after pressing g
   (X) #23  10/01/04  stop dir loading with ^C -> wont load anymore
   (X) #25  10/01/06  directories sometimes dont reload correctly
   (X) #26  10/01/06  :delete on symlinks of directories fails
   (X) #31  10/01/06  ^C breaks cd-after-exit by stopping sourced shell script
   (X) #40  10/01/17  freeze with unavailable sshfs
          Not rangers fault (?)
   (X) #41  10/01/17  capital file extensions are not recognized
   (X) #46  10/01/19  old username displayed after using su
   (X) #49  10/01/19  fix unit tests :'(
   (X) #52  10/01/23  special characters in tab completion
   (X) #54  10/01/23  max_dirsize_for_autopreview not working
   ( ) #60  10/02/05  utf support improvable
   (X) #62  10/02/15  curs_set can raise an exception
   ( ) #65  10/02/16  "source ranger ranger some/file.txt" shouldn't cd after exit
   (X) #67  10/03/08  terminal title in tty
   (X) #69  10/03/11  tab-completion breaks with Apps subclass
   (X) #73  10/03/21  when clicking on the first column, it goes 1x down
   (X) #74  10/03/21  console doesn't scroll
   ( ) #78  10/03/31  broken preview when deleting all files in a directory


Ideas

   ( ) #20  10/01/01  use inotify to monitor filesystem changes
   ( ) #24  10/01/06  progress bar
   (X) #27  10/01/06  hide bookmarks in list which contain hidden dir
   (X) #28  10/01/06  use regexp instead of string for searching
   ( ) #33  10/01/08  accelerate mousewheel speed
   (X) #45  10/01/18  hooks for events like setting changes
   ( ) #53  10/01/23  merge fm and environment
   ( ) #68  10/03/10  threads, to seperate ui and loading
   ( ) #72  10/03/21  ranger daemon which does the slow io tasks
   ( ) #75  10/03/28  navigate in history
   (X) #76  10/03/28  save history between sessions
   (X) #77  10/03/28  colorscheme overlay in options.py