summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ranger/api/keys.py1
-rw-r--r--ranger/container/tags.py60
-rw-r--r--ranger/core/actions.py6
-rw-r--r--ranger/data/mime.types1
-rw-r--r--ranger/defaults/keys.py3
-rw-r--r--ranger/fsobject/directory.py1
-rw-r--r--ranger/gui/widgets/browsercolumn.py8
7 files changed, 59 insertions, 21 deletions
diff --git a/ranger/api/keys.py b/ranger/api/keys.py
index 7ba05c73..75de6237 100644
--- a/ranger/api/keys.py
+++ b/ranger/api/keys.py
@@ -21,6 +21,7 @@ from inspect import getargspec, ismethod
 from ranger import RANGERDIR
 from ranger.api import *
 from ranger.container.bookmarks import ALLOWED_KEYS as ALLOWED_BOOKMARK_KEYS
+from ranger.container.tags import ALLOWED_KEYS as ALLOWED_TAGS_KEYS
 from ranger.container.keymap import KeyMap, Direction, KeyMapWithDirections
 
 # A dummy that allows the generation of docstrings in ranger.defaults.keys
diff --git a/ranger/container/tags.py b/ranger/container/tags.py
index 9ef8a1b2..c2fe3067 100644
--- a/ranger/container/tags.py
+++ b/ranger/container/tags.py
@@ -14,8 +14,13 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from os.path import isdir, exists, dirname, abspath, realpath, expanduser
+import string
+
+ALLOWED_KEYS = string.ascii_letters + string.digits + string.punctuation
 
 class Tags(object):
+	default_tag = '*'
+
 	def __init__(self, filename):
 
 		self._filename = realpath(abspath(expanduser(filename)))
@@ -28,33 +33,47 @@ class Tags(object):
 	def __contains__(self, item):
 		return item in self.tags
 
-	def add(self, *items):
+	def add(self, *items, **others):
+		if 'tag' in others:
+			tag = others['tag']
+		else:
+			tag = self.defautag
 		self.sync()
 		for item in items:
-			self.tags.add(item)
+			self.tags[item] = tag
 		self.dump()
 
 	def remove(self, *items):
 		self.sync()
 		for item in items:
 			try:
-				self.tags.remove(item)
+				del(self.tags[item])
 			except KeyError:
 				pass
 		self.dump()
 
-	def toggle(self, *items):
+	def toggle(self, *items, **others):
+		if 'tag' in others:
+			tag = others['tag']
+		else:
+			tag = self.default_tag
 		self.sync()
 		for item in items:
-			if item in self:
-				try:
-					self.tags.remove(item)
-				except KeyError:
-					pass
-			else:
-				self.tags.add(item)
+			try:
+				if item in self and tag in (self.tags[item], self.default_tag):
+					del(self.tags[item])
+				else:
+					self.tags[item] = tag
+			except KeyError:
+				pass
 		self.dump()
 
+	def marker(self, item):
+		if item in self.tags:
+			return self.tags[item]
+		else:
+			return self.default_tag
+
 	def sync(self):
 		try:
 			f = open(self._filename, 'r')
@@ -74,13 +93,24 @@ class Tags(object):
 			f.close()
 
 	def _compile(self, f):
-		for line in self.tags:
-			f.write(line + '\n')
+		for path, tag in self.tags.items():
+			if tag == self.default_tag:
+				# COMPAT: keep the old format if the default tag is used
+				f.write(path + '\n')
+			elif tag in ALLOWED_KEYS:
+				f.write('{0}:{1}\n'.format(tag, path))
 
 	def _parse(self, f):
-		result = set()
+		result = dict()
 		for line in f:
-			result.add(line.strip())
+			line = line.strip()
+			if len(line) > 2 and line[1] == ':':
+				tag, path = line[0], line[2:]
+				if tag in ALLOWED_KEYS:
+					result[path] = tag
+			else:
+				result[line] = self.default_tag
+
 		return result
 
 	def __nonzero__(self):
diff --git a/ranger/core/actions.py b/ranger/core/actions.py
index 89bd9389..cb692d4c 100644
--- a/ranger/core/actions.py
+++ b/ranger/core/actions.py
@@ -430,7 +430,7 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 	# Tags are saved in ~/.config/ranger/tagged and simply mark if a
 	# file is important to you in any context.
 
-	def tag_toggle(self, paths=None, value=None, movedown=None):
+	def tag_toggle(self, paths=None, value=None, movedown=None, tag=None):
 		if not self.tags:
 			return
 		if paths is None:
@@ -438,11 +438,11 @@ class Actions(FileManagerAware, EnvironmentAware, SettingsAware):
 		else:
 			tags = [realpath(path) for path in paths]
 		if value is True:
-			self.tags.add(*tags)
+			self.tags.add(*tags, tag=tag or self.tags.default_tag)
 		elif value is False:
 			self.tags.remove(*tags)
 		else:
-			self.tags.toggle(*tags)
+			self.tags.toggle(*tags, tag=tag or self.tags.default_tag)
 
 		if movedown is None:
 			movedown = len(tags) == 1 and paths is None
diff --git a/ranger/data/mime.types b/ranger/data/mime.types
index 22d8dec7..14c35a9a 100644
--- a/ranger/data/mime.types
+++ b/ranger/data/mime.types
@@ -16,6 +16,7 @@ audio/ogg					oga ogg spx
 audio/wavpack				wv wvc
 
 video/mkv					mkv
+video/webm					webm
 video/flash					flv
 video/ogg					ogv ogm
 video/divx					div divx
diff --git a/ranger/defaults/keys.py b/ranger/defaults/keys.py
index 8448e6ad..cd1c5d07 100644
--- a/ranger/defaults/keys.py
+++ b/ranger/defaults/keys.py
@@ -159,6 +159,8 @@ map('L', fm.history_go(1))
 # ----------------------------------------------- tagging / marking
 map('t', fm.tag_toggle())
 map('T', fm.tag_remove())
+for key in ALLOWED_TAGS_KEYS:
+		map('"' + key, fm.tag_toggle(tag=key))
 
 map(' ', fm.mark(toggle=True))
 map('v', fm.mark(all=True, toggle=True))
@@ -219,6 +221,7 @@ sort_dict = {
 	'b': 'basename',
 	'n': 'natural',
 	'm': 'mtime',
+	'c': 'ctime',
 	't': 'type',
 }
 
diff --git a/ranger/fsobject/directory.py b/ranger/fsobject/directory.py
index 7b8a7563..e0623e23 100644
--- a/ranger/fsobject/directory.py
+++ b/ranger/fsobject/directory.py
@@ -87,6 +87,7 @@ class Directory(FileSystemObject, Accumulator, Loadable, SettingsAware):
 		'natural': sort_naturally,
 		'size': lambda path: -path.size,
 		'mtime': lambda path: -(path.stat and path.stat.st_mtime or 1),
+		'ctime': lambda path: -(path.stat and path.stat.st_ctime or 1),
 		'type': lambda path: path.mimetype or '',
 	}
 
diff --git a/ranger/gui/widgets/browsercolumn.py b/ranger/gui/widgets/browsercolumn.py
index 2928af23..801b79fd 100644
--- a/ranger/gui/widgets/browsercolumn.py
+++ b/ranger/gui/widgets/browsercolumn.py
@@ -27,7 +27,6 @@ class BrowserColumn(Pager):
 	display_infostring = False
 	scroll_begin = 0
 	target = None
-	tagged_marker = '*'
 	last_redraw_time = -1
 	ellipsis = { False: '~', True: '…' }
 
@@ -228,6 +227,9 @@ class BrowserColumn(Pager):
 			text = drawn.basename
 			tagged = self.fm.tags and drawn.realpath in self.fm.tags
 
+			if tagged:
+				tagged_marker = self.fm.tags.marker(drawn.realpath)
+
 			space = self.wid - len(infostring)
 			if self.main_column:
 				space -= 2
@@ -248,7 +250,7 @@ class BrowserColumn(Pager):
 			if tagged:
 				this_color.append('tagged')
 				if self.main_column or self.settings.display_tags_in_all_columns:
-					text = self.tagged_marker + text
+					text = tagged_marker + text
 
 			if drawn.is_directory:
 				this_color.append('directory')
@@ -301,7 +303,7 @@ class BrowserColumn(Pager):
 			if (self.main_column or self.settings.display_tags_in_all_columns) \
 					and tagged and self.wid > 2:
 				this_color.append('tag_marker')
-				self.color_at(line, 0, len(self.tagged_marker), this_color)
+				self.color_at(line, 0, len(tagged_marker), this_color)
 
 			self.color_reset()