diff --git a/docs/formatting.md b/docs/formatting.md index f188a538..9ed3ae22 100644 --- a/docs/formatting.md +++ b/docs/formatting.md @@ -192,6 +192,12 @@ Format specifiers can be used for advanced formatting by using the options provi {foo:Ro/()/} F()() Bar + + C<conversion(s)>/ + Apply Conversions to the current value + {tags:CSgc/} + "Sun-tree-water" + S<order>/ Sort a list. <order> can be either ascending or descending/reverse. (default: a) diff --git a/gallery_dl/formatter.py b/gallery_dl/formatter.py index 0b212d5e..43ee756c 100644 --- a/gallery_dl/formatter.py +++ b/gallery_dl/formatter.py @@ -325,6 +325,26 @@ def _parse_slice(format_spec, default): return apply_slice +def _parse_conversion(format_spec, default): + conversions, _, format_spec = format_spec.partition(_SEPARATOR) + convs = [_CONVERSIONS[c] for c in conversions[1:]] + fmt = _build_format_func(format_spec, default) + + if len(conversions) <= 2: + + def convert_one(obj): + return fmt(conv(obj)) + conv = _CONVERSIONS[conversions[1]] + return convert_one + + def convert_many(obj): + for conv in convs: + obj = conv(obj) + return fmt(obj) + convs = [_CONVERSIONS[c] for c in conversions[1:]] + return convert_many + + def _parse_maxlen(format_spec, default): maxlen, replacement, format_spec = format_spec.split(_SEPARATOR, 2) maxlen = text.parse_int(maxlen[1:]) @@ -447,6 +467,7 @@ _CONVERSIONS = { _FORMAT_SPECIFIERS = { "?": _parse_optional, "[": _parse_slice, + "C": _parse_conversion, "D": _parse_datetime, "L": _parse_maxlen, "J": _parse_join, diff --git a/test/test_formatter.py b/test/test_formatter.py index 73e958cc..4c74a441 100644 --- a/test/test_formatter.py +++ b/test/test_formatter.py @@ -267,6 +267,11 @@ class TestFormatter(unittest.TestCase): "{a:Sort-reverse}", # starts with 'S', contains 'r' "['w', 'r', 'o', 'l', 'h', 'd', 'O', 'L', 'L', 'E', ' ']") + def test_specifier_conversions(self): + self._run_test("{a:Cl}" , "hello world") + self._run_test("{h:CHC}" , "Foo & Bar") + self._run_test("{l:CSulc}", "A, b, c") + def test_chain_special(self): # multiple replacements self._run_test("{a:Rh/C/RE/e/RL/l/}", "Cello wOrld")