summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/actions.py28
-rw-r--r--ranger/colorschemes/default.py3
-rw-r--r--ranger/container/tags.py68
-rw-r--r--ranger/defaults/keys.py2
-rw-r--r--ranger/fm.py7
-rw-r--r--ranger/fsobject/fsobject.py3
-rw-r--r--ranger/gui/colorscheme.py2
-rw-r--r--ranger/gui/widgets/filelist.py19
8 files changed, 124 insertions, 8 deletions
diff --git a/ranger/actions.py b/ranger/actions.py
index b9ec2204..d500f18a 100644
--- a/ranger/actions.py
+++ b/ranger/actions.py
@@ -39,6 +39,34 @@ class Actions(EnvironmentAware, SettingsAware):
 		"""Enter the directory at the given path"""
 		return self.env.enter_dir(path)
 
+	def tag_toggle(self, movedown=None):
+		try:
+			toggle = self.tags.toggle
+		except AttributeError:
+			return
+
+		sel = self.env.get_selection()
+		toggle(*tuple(map(lambda x: x.realpath, sel)))
+
+		if movedown is None:
+			movedown = len(sel) == 1
+		if movedown:
+			self.move_pointer(relative=1)
+	
+	def tag_remove(self, movedown=None):
+		try:
+			remove = self.tags.remove
+		except AttributeError:
+			return
+
+		sel = self.env.get_selection()
+		remove(*tuple(map(lambda x: x.realpath, sel)))
+
+		if movedown is None:
+			movedown = len(sel) == 1
+		if movedown:
+			self.move_pointer(relative=1)
+
 	def enter_bookmark(self, key):
 		"""Enter the bookmark with the name <key>"""
 		from ranger.container.bookmarks import NonexistantBookmark
diff --git a/ranger/colorschemes/default.py b/ranger/colorschemes/default.py
index e4c81e14..65441393 100644
--- a/ranger/colorschemes/default.py
+++ b/ranger/colorschemes/default.py
@@ -40,6 +40,9 @@ class Default(ColorScheme):
 			if context.link:
 				fg = context.good and cyan or magenta
 
+			if context.tag_marker and not context.selected:
+				attr |= bold
+
 			if context.maindisplay:
 				if context.selected:
 					attr |= bold
diff --git a/ranger/container/tags.py b/ranger/container/tags.py
new file mode 100644
index 00000000..7a941843
--- /dev/null
+++ b/ranger/container/tags.py
@@ -0,0 +1,68 @@
+class Tags(object):
+	def __init__(self, filename):
+		from os.path import isdir, exists, dirname, abspath, realpath, expanduser
+
+		self._filename = realpath(abspath(expanduser(filename)))
+
+		if isdir(dirname(self._filename)) and not exists(self._filename):
+			open(self._filename, 'w')
+
+		self.sync()
+	
+	def __contains__(self, item):
+		return item in self.tags
+
+	def add(self, *items):
+		self.sync()
+		for item in items:
+			self.tags.add(item)
+		self.dump()
+
+	def remove(self, *items):
+		self.sync()
+		for item in items:
+			try:
+				self.tags.remove(item)
+			except KeyError:
+				pass
+		self.dump()
+
+	def toggle(self, *items):
+		self.sync()
+		for item in items:
+			if item in self:
+				try:
+					self.tags.remove(item)
+				except KeyError:
+					pass
+			else:
+				self.tags.add(item)
+		self.dump()
+	
+	def sync(self):
+		try:
+			f = open(self._filename, 'r')
+		except OSError:
+			pass
+		else:
+			self.tags = self._parse(f)
+			f.close()
+	
+	def dump(self):
+		try:
+			f = open(self._filename, 'w')
+		except OSError:
+			pass
+		else:
+			self._compile(f)
+			f.close()
+	
+	def _compile(self, f):
+		for line in self.tags:
+			f.write(line + '\n')
+
+	def _parse(self, f):
+		result = set()
+		for line in f:
+			result.add(line.strip())
+		return result
diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py
index 9fbc5b96..faa85388 100644
--- a/ranger/defaults/keys.py
+++ b/ranger/defaults/keys.py
@@ -33,6 +33,8 @@ def initialize_commands(command_list):
 	bind('K', do('move_pointer_by_pages', -0.5))
 	bind('E', do('edit_file'))
 #	bind('o', do('force_load_preview'))
+	bind('i', do('tag_toggle'))
+	bind('I', do('tag_remove'))
 
 	bind(' ', do('mark', toggle=True))
 	bind('v', do('mark', all=True, toggle=True))
diff --git a/ranger/fm.py b/ranger/fm.py
index a68c0f15..45a419a5 100644
--- a/ranger/fm.py
+++ b/ranger/fm.py
@@ -13,11 +13,12 @@ class FM(Actions):
 	input_blocked = False
 	input_blocked_until = 0
 	stderr_to_out = False
-	def __init__(self, ui = None, bookmarks = None):
+	def __init__(self, ui=None, bookmarks=None, tags=None):
 		"""Initialize FM."""
 		Actions.__init__(self)
 		self.ui = ui
 		self.bookmarks = bookmarks
+		self.tags = tags
 		self.loader = Loader()
 		self.apps = self.settings.apps.CustomApplications()
 
@@ -38,6 +39,10 @@ class FM(Actions):
 		else:
 			self.bookmarks = bookmarks
 
+		from ranger.container.tags import Tags
+		if self.tags is None:
+			self.tags = Tags('~/.ranger/tagged')
+
 		if self.ui is None:
 			from ranger.gui.defaultui import DefaultUI
 			self.ui = DefaultUI()
diff --git a/ranger/fsobject/fsobject.py b/ranger/fsobject/fsobject.py
index f7d9772c..28ef5c5b 100644
--- a/ranger/fsobject/fsobject.py
+++ b/ranger/fsobject/fsobject.py
@@ -43,12 +43,13 @@ class FileSystemObject(MimeTypeAware, FileManagerAware):
 		if type(self) == FileSystemObject:
 			raise TypeError("Cannot initialize abstract class FileSystemObject")
 
-		from os.path import basename, dirname
+		from os.path import basename, dirname, realpath
 
 		self.path = path
 		self.basename = basename(path)
 		self.basename_lower = self.basename.lower()
 		self.dirname = dirname(path)
+		self.realpath = realpath(path)
 
 		try:
 			self.extension = self.basename[self.basename.rindex('.') + 1:]
diff --git a/ranger/gui/colorscheme.py b/ranger/gui/colorscheme.py
index 227051f9..bf8194ea 100644
--- a/ranger/gui/colorscheme.py
+++ b/ranger/gui/colorscheme.py
@@ -8,7 +8,7 @@ CONTEXT_KEYS = [ 'reset', 'error',
 		'good', 'bad',
 		'space', 'permissions', 'owner', 'group', 'mtime', 'nlink',
 		'scroll', 'all', 'bot', 'top', 'percentage',
-		'marked',
+		'marked', 'tagged', 'tag_marker',
 		'title', 'text', 'highlight',
 		'keybuffer']
 
diff --git a/ranger/gui/widgets/filelist.py b/ranger/gui/widgets/filelist.py
index 457c9856..c6b654b4 100644
--- a/ranger/gui/widgets/filelist.py
+++ b/ranger/gui/widgets/filelist.py
@@ -170,6 +170,8 @@ class FileList(Widget):
 				break
 
 			this_color = base_color + list(drawed.mimetype_tuple)
+			text = drawed.basename
+			tagged = drawed.realpath in self.fm.tags
 
 			if i == selected_i:
 				this_color.append('selected')
@@ -177,6 +179,11 @@ class FileList(Widget):
 			if drawed.marked:
 				this_color.append('marked')
 
+			if tagged:
+				this_color.append('tagged')
+				if self.main_display:
+					text = '* ' + text
+
 			if isinstance(drawed, Directory):
 				this_color.append('directory')
 			else:
@@ -192,12 +199,10 @@ class FileList(Widget):
 			string = drawed.basename
 			if self.main_display:
 				if self.wid > 2:
-					self.win.addnstr(
-							self.y + line, self.x + 1,
-							drawed.basename, self.wid - 2)
+					self.win.addnstr(self.y + line, self.x + 1,
+							text, self.wid - 2)
 			else:
-				self.win.addnstr(
-						self.y + line, self.x, drawed.basename, self.wid)
+				self.win.addnstr(self.y + line, self.x, text, self.wid)
 
 			if self.display_infostring and drawed.infostring:
 				info = drawed.infostring
@@ -207,6 +212,10 @@ class FileList(Widget):
 
 			self.color_at(self.y + line, self.x, self.wid, this_color)
 
+			if self.main_display and tagged and self.wid > 2:
+				this_color.append('tag_marker')
+				self.color_at(self.y + line, self.x + 1, 1, this_color)
+
 			self.color_reset()
 
 	def get_scroll_begin(self):