diff --git a/docs/formatting.md b/docs/formatting.md index 9ed3ae22..bf88d275 100644 --- a/docs/formatting.md +++ b/docs/formatting.md @@ -180,6 +180,16 @@ Format specifiers can be used for advanced formatting by using the options provi {foo:L3/long/} long + + X<maxlen>/<ext>/ + Limit output to <maxlen> characters. Cut output and add <ext> to its end if its length exceeds <maxlen> + {foo:X15/ .../} + Foo Bar + + + {foo:L6/ .../} + Fo ... + J<separator>/ Concatenates elements of a list with <separator> using str.join() diff --git a/gallery_dl/formatter.py b/gallery_dl/formatter.py index 43ee756c..ec1c926a 100644 --- a/gallery_dl/formatter.py +++ b/gallery_dl/formatter.py @@ -423,6 +423,19 @@ def _parse_sort(format_spec, default): return sort_asc +def _parse_limit(format_spec, default): + limit, hint, format_spec = format_spec.split(_SEPARATOR, 2) + limit = int(limit[1:]) + limit_hint = limit - len(hint) + fmt = _build_format_func(format_spec, default) + + def apply_limit(obj): + if len(obj) > limit: + obj = obj[:limit_hint] + hint + return fmt(obj) + return apply_limit + + def _default_format(format_spec, default): def wrap(obj): return format(obj, format_spec) @@ -469,9 +482,10 @@ _FORMAT_SPECIFIERS = { "[": _parse_slice, "C": _parse_conversion, "D": _parse_datetime, - "L": _parse_maxlen, "J": _parse_join, + "L": _parse_maxlen, "O": _parse_offset, "R": _parse_replace, "S": _parse_sort, + "X": _parse_limit, } diff --git a/test/test_formatter.py b/test/test_formatter.py index 4c74a441..e00af854 100644 --- a/test/test_formatter.py +++ b/test/test_formatter.py @@ -272,6 +272,13 @@ class TestFormatter(unittest.TestCase): self._run_test("{h:CHC}" , "Foo & Bar") self._run_test("{l:CSulc}", "A, b, c") + def test_specifier_limit(self): + self._run_test("{a:X20/ */}", "hElLo wOrLd") + self._run_test("{a:X10/ */}", "hElLo wO *") + + with self.assertRaises(ValueError): + self._run_test("{a:Xfoo/ */}", "hello wo *") + def test_chain_special(self): # multiple replacements self._run_test("{a:Rh/C/RE/e/RL/l/}", "Cello wOrld")