[formatter] implement slice operator as format specifier
this allows using a slice operator alongside other (special) format
specifiers like J, to first join list elements to a string and then
trimming that with a slice.
{tags:J, /[:50]}
This commit is contained in:
@@ -139,6 +139,12 @@ Format specifiers can be used for advanced formatting by using the options provi
|
|||||||
<td><code>{empty:?[/]/}</code></td>
|
<td><code>{empty:?[/]/}</code></td>
|
||||||
<td><code></code></td>
|
<td><code></code></td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><code>[<start>:<stop>]</code></td>
|
||||||
|
<td>Applies a <a href="https://python-reference.readthedocs.io/en/latest/docs/brackets/slicing.html">Slicing</a> operation to the current value, similar to <a href="#field-names">Field Names</a></td>
|
||||||
|
<td><code>{foo:[1:-1]}</code></td>
|
||||||
|
<td><code>oo Ba</code></td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td rowspan="2"><code>L<maxlen>/<repl>/</code></td>
|
<td rowspan="2"><code>L<maxlen>/<repl>/</code></td>
|
||||||
<td rowspan="2">Replaces the entire output with <code><repl></code> if its length exceeds <code><maxlen></code></td>
|
<td rowspan="2">Replaces the entire output with <code><repl></code> if its length exceeds <code><maxlen></code></td>
|
||||||
|
|||||||
@@ -232,12 +232,7 @@ def parse_field_name(field_name):
|
|||||||
func = operator.itemgetter
|
func = operator.itemgetter
|
||||||
try:
|
try:
|
||||||
if ":" in key:
|
if ":" in key:
|
||||||
start, _, stop = key.partition(":")
|
key = _slice(key)
|
||||||
stop, _, step = stop.partition(":")
|
|
||||||
start = int(start) if start else None
|
|
||||||
stop = int(stop) if stop else None
|
|
||||||
step = int(step) if step else None
|
|
||||||
key = slice(start, stop, step)
|
|
||||||
except TypeError:
|
except TypeError:
|
||||||
pass # key is an integer
|
pass # key is an integer
|
||||||
|
|
||||||
@@ -246,6 +241,16 @@ def parse_field_name(field_name):
|
|||||||
return first, funcs
|
return first, funcs
|
||||||
|
|
||||||
|
|
||||||
|
def _slice(indices):
|
||||||
|
start, _, stop = indices.partition(":")
|
||||||
|
stop, _, step = stop.partition(":")
|
||||||
|
return slice(
|
||||||
|
int(start) if start else None,
|
||||||
|
int(stop) if stop else None,
|
||||||
|
int(step) if step else None,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def parse_format_spec(format_spec, conversion):
|
def parse_format_spec(format_spec, conversion):
|
||||||
fmt = build_format_func(format_spec)
|
fmt = build_format_func(format_spec)
|
||||||
if not conversion:
|
if not conversion:
|
||||||
@@ -283,6 +288,8 @@ def build_format_func(format_spec):
|
|||||||
fmt = format_spec[0]
|
fmt = format_spec[0]
|
||||||
if fmt == "?":
|
if fmt == "?":
|
||||||
return _parse_optional(format_spec)
|
return _parse_optional(format_spec)
|
||||||
|
if fmt == "[":
|
||||||
|
return _parse_slice(format_spec)
|
||||||
if fmt == "L":
|
if fmt == "L":
|
||||||
return _parse_maxlen(format_spec)
|
return _parse_maxlen(format_spec)
|
||||||
if fmt == "J":
|
if fmt == "J":
|
||||||
@@ -305,6 +312,16 @@ def _parse_optional(format_spec):
|
|||||||
return optional
|
return optional
|
||||||
|
|
||||||
|
|
||||||
|
def _parse_slice(format_spec):
|
||||||
|
indices, _, format_spec = format_spec.partition("]")
|
||||||
|
slice = _slice(indices[1:])
|
||||||
|
fmt = build_format_func(format_spec)
|
||||||
|
|
||||||
|
def apply_slice(obj):
|
||||||
|
return fmt(obj[slice])
|
||||||
|
return apply_slice
|
||||||
|
|
||||||
|
|
||||||
def _parse_maxlen(format_spec):
|
def _parse_maxlen(format_spec):
|
||||||
maxlen, replacement, format_spec = format_spec.split("/", 2)
|
maxlen, replacement, format_spec = format_spec.split("/", 2)
|
||||||
maxlen = text.parse_int(maxlen[1:])
|
maxlen = text.parse_int(maxlen[1:])
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
# Copyright 2021 Mike Fährmann
|
# Copyright 2021-2022 Mike Fährmann
|
||||||
#
|
#
|
||||||
# This program is free software; you can redistribute it and/or modify
|
# This program is free software; you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License version 2 as
|
# it under the terms of the GNU General Public License version 2 as
|
||||||
@@ -135,6 +135,21 @@ class TestFormatter(unittest.TestCase):
|
|||||||
self._run_test("{a[:50:2]}", v[:50:2])
|
self._run_test("{a[:50:2]}", v[:50:2])
|
||||||
self._run_test("{a[::]}" , v)
|
self._run_test("{a[::]}" , v)
|
||||||
|
|
||||||
|
self._run_test("{a:[1:10]}" , v[1:10])
|
||||||
|
self._run_test("{a:[-10:-1]}", v[-10:-1])
|
||||||
|
self._run_test("{a:[5:]}" , v[5:])
|
||||||
|
self._run_test("{a:[50:]}", v[50:])
|
||||||
|
self._run_test("{a:[:5]}" , v[:5])
|
||||||
|
self._run_test("{a:[:50]}", v[:50])
|
||||||
|
self._run_test("{a:[:]}" , v)
|
||||||
|
self._run_test("{a:[1:10:2]}" , v[1:10:2])
|
||||||
|
self._run_test("{a:[-10:-1:2]}", v[-10:-1:2])
|
||||||
|
self._run_test("{a:[5::2]}" , v[5::2])
|
||||||
|
self._run_test("{a:[50::2]}", v[50::2])
|
||||||
|
self._run_test("{a:[:5:2]}" , v[:5:2])
|
||||||
|
self._run_test("{a:[:50:2]}", v[:50:2])
|
||||||
|
self._run_test("{a:[::]}" , v)
|
||||||
|
|
||||||
def test_maxlen(self):
|
def test_maxlen(self):
|
||||||
v = self.kwdict["a"]
|
v = self.kwdict["a"]
|
||||||
self._run_test("{a:L5/foo/}" , "foo")
|
self._run_test("{a:L5/foo/}" , "foo")
|
||||||
@@ -177,6 +192,9 @@ class TestFormatter(unittest.TestCase):
|
|||||||
# join-and-replace
|
# join-and-replace
|
||||||
self._run_test("{l:J-/Rb/E/}", "a-E-c")
|
self._run_test("{l:J-/Rb/E/}", "a-E-c")
|
||||||
|
|
||||||
|
# join and slice
|
||||||
|
self._run_test("{l:J-/[1:-1]}", "-b-")
|
||||||
|
|
||||||
# optional-and-maxlen
|
# optional-and-maxlen
|
||||||
self._run_test("{d[a]:?</>/L1/too long/}", "<too long>")
|
self._run_test("{d[a]:?</>/L1/too long/}", "<too long>")
|
||||||
self._run_test("{d[c]:?</>/L5/too long/}", "")
|
self._run_test("{d[c]:?</>/L5/too long/}", "")
|
||||||
|
|||||||
Reference in New Issue
Block a user