Skip to content

Commit 035a31f

Browse files
committed
python: support W presentation type
Problem: Python does not take into account wide characters (i.e. emojis) when attempting to do output alignment. So when outputting wide characters in flux-jobs, the output can be poor due to the characters have different output widths. Solution: Add a new W presentation type that can adjust formatting of the form "(<|>)N", e.g. {id.emoji:>12W}. The output width will be adjusted given the number of wide characters that exist in the string.
1 parent 9a9b37d commit 035a31f

File tree

1 file changed

+23
-1
lines changed

1 file changed

+23
-1
lines changed

src/bindings/python/flux/util.py

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,9 @@
3030
from pathlib import Path, PurePosixPath
3131
from string import Formatter
3232
from typing import Mapping
33-
from wcwidth import wcswidth
3433

3534
import yaml
35+
from wcwidth import wcswidth
3636

3737
# tomllib added to standard library in Python 3.11
3838
# flux-core minimum is Python 3.6.
@@ -579,6 +579,26 @@ def format_field(self, value, spec):
579579
basecases = empty_outputs()
580580
value = "-" if str(value) in basecases else str(value)
581581
spec = spec[:-1] + "s"
582+
583+
# Normal python output will not consider emoji width with
584+
# width formatting. So we will adjust the output width of
585+
# field accordingly to account for it if the "W" modifier
586+
# is specified.
587+
if spec.endswith("W") and isinstance(value, str):
588+
match = re.search(r"^([<>])(\d+)W", spec)
589+
if match:
590+
align = match[1]
591+
width = int(match[2])
592+
display_width = wcswidth(value)
593+
normal_width = len(value)
594+
width_diff = display_width - normal_width
595+
if width_diff > 0 and width > width_diff:
596+
width -= width_diff
597+
spec = f"{align}{width}s"
598+
# if spec was not modified above, need to convert "W" to "s"
599+
if spec.endswith("W"):
600+
spec = spec[:-1] + "s"
601+
582602
retval = super().format_field(value, spec)
583603

584604
if denote_truncation and len(retval) < len(str(value)):
@@ -735,6 +755,7 @@ class FormatSpec:
735755
"precision_str",
736756
"type",
737757
"hyphen",
758+
"wide",
738759
"truncate",
739760
)
740761

@@ -759,6 +780,7 @@ def __init__(self, spec):
759780
r"(?:(?P<decimal>\.)(?P<precision_str>\d+))?"
760781
r"(?P<type>[bcdeEfFgGnosxX%])?"
761782
r"(?P<hyphen>h)?"
783+
r"(?P<wide>W)?"
762784
r"(?P<truncate>\+)?"
763785
)
764786
try:

0 commit comments

Comments
 (0)