diff --git a/docs/formatting.md b/docs/formatting.md
index 53cba565..5420c69e 100644
--- a/docs/formatting.md
+++ b/docs/formatting.md
@@ -172,6 +172,12 @@ Format specifiers can be used for advanced formatting by using the options provi
{foo:Ro/()/} |
F()() Bar |
+
+ S<order>/ |
+ Sort a list. <order> can be either ascending or descending/reverse. (default: a) |
+ {tags:Sd} |
+ ['water', 'tree', 'sun'] |
+
D<format>/ |
Parse a string value to a datetime object according to <format> |
diff --git a/gallery_dl/formatter.py b/gallery_dl/formatter.py
index dd32b8a5..ca05fa5a 100644
--- a/gallery_dl/formatter.py
+++ b/gallery_dl/formatter.py
@@ -347,6 +347,20 @@ def _parse_offset(format_spec, default):
return off
+def _parse_sort(format_spec, default):
+ args, _, format_spec = format_spec.partition(_SEPARATOR)
+ fmt = _build_format_func(format_spec, default)
+
+ if "d" in args or "r" in args:
+ def sort_desc(obj):
+ return fmt(sorted(obj, reverse=True))
+ return sort_desc
+ else:
+ def sort_asc(obj):
+ return fmt(sorted(obj))
+ return sort_asc
+
+
def _default_format(format_spec, default):
def wrap(obj):
return format(obj, format_spec)
@@ -395,4 +409,5 @@ _FORMAT_SPECIFIERS = {
"J": _parse_join,
"O": _parse_offset,
"R": _parse_replace,
+ "S": _parse_sort,
}
diff --git a/gallery_dl/version.py b/gallery_dl/version.py
index 31dbc63f..dfbac9d8 100644
--- a/gallery_dl/version.py
+++ b/gallery_dl/version.py
@@ -6,4 +6,4 @@
# it under the terms of the GNU General Public License version 2 as
# published by the Free Software Foundation.
-__version__ = "1.24.0"
+__version__ = "1.24.1-dev"
diff --git a/test/test_formatter.py b/test/test_formatter.py
index b3353326..50e55a6c 100644
--- a/test/test_formatter.py
+++ b/test/test_formatter.py
@@ -219,6 +219,21 @@ class TestFormatter(unittest.TestCase):
time.timezone = orig_timezone
time.altzone = orig_altzone
+ def test_sort(self):
+ self._run_test("{l:S}" , "['a', 'b', 'c']")
+ self._run_test("{l:Sa}", "['a', 'b', 'c']")
+ self._run_test("{l:Sd}", "['c', 'b', 'a']")
+ self._run_test("{l:Sr}", "['c', 'b', 'a']")
+
+ self._run_test(
+ "{a:S}", "[' ', 'E', 'L', 'L', 'O', 'd', 'h', 'l', 'o', 'r', 'w']")
+ self._run_test(
+ "{a:S-asc}", # starts with 'S', contains 'a'
+ "[' ', 'E', 'L', 'L', 'O', 'd', 'h', 'l', 'o', 'r', 'w']")
+ self._run_test(
+ "{a:Sort-reverse}", # starts with 'S', contains 'r'
+ "['w', 'r', 'o', 'l', 'h', 'd', 'O', 'L', 'L', 'E', ' ']")
+
def test_chain_special(self):
# multiple replacements
self._run_test("{a:Rh/C/RE/e/RL/l/}", "Cello wOrld")
@@ -237,6 +252,9 @@ class TestFormatter(unittest.TestCase):
# parse and format datetime
self._run_test("{ds:D%Y-%m-%dT%H:%M:%S%z/%Y%m%d}", "20100101")
+ # sort and join
+ self._run_test("{a:S/J}", " ELLOdhlorw")
+
def test_separator(self):
orig_separator = formatter._SEPARATOR
try: