Skip to content

Commit

Permalink
Support CJK text alignment (#2012)
Browse files Browse the repository at this point in the history
* Add functions for unicode string alignment

* use unicode alignment function to show menu

* Allow table content to support unicode text alignment
  • Loading branch information
yetist committed Sep 16, 2023
1 parent c9e2027 commit 47ed711
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 22 deletions.
21 changes: 2 additions & 19 deletions archinstall/lib/menu/abstract_menu.py
Original file line number Diff line number Diff line change
@@ -1,32 +1,15 @@
from __future__ import annotations
import unicodedata

from typing import Callable, Any, List, Iterator, Tuple, Optional, Dict, TYPE_CHECKING

from .menu import Menu, MenuSelectionType
from ..output import error
from ..output import unicode_ljust
from ..translationhandler import TranslationHandler, Language

if TYPE_CHECKING:
_: Any

def count_cjk_chars(string):
"Count the total number of CJK characters contained in a string"
return sum(unicodedata.east_asian_width(c) in 'FW' for c in string)

def cjkljust(string, width, fillbyte=' '):
"""Support left alignment of Chinese, Japanese, Korean text
>>> cjkljust('Hello', 15, '*')
'Hello**********'
>>> cjkljust('你好', 15, '*')
'你好***********'
>>> cjkljust('안녕하세요', 15, '*')
'안녕하세요*****'
>>> cjkljust('こんにちは', 15, '*')
'こんにちは*****'
"""
return string.ljust(width - count_cjk_chars(string), fillbyte)

class Selector:
def __init__(
self,
Expand Down Expand Up @@ -145,7 +128,7 @@ def menu_text(self, padding: int = 0) -> str:

if current:
padding += 5
description = cjkljust(str(self._description), padding, ' ')
description = unicode_ljust(str(self._description), padding, ' ')
current = current
else:
description = self._description
Expand Down
37 changes: 34 additions & 3 deletions archinstall/lib/output.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import logging
import os
import sys
import unicodedata
from enum import Enum

from pathlib import Path
Expand Down Expand Up @@ -83,7 +84,7 @@ def as_table(
if capitalize:
key = key.capitalize()

key_list.append(key.ljust(width))
key_list.append(unicode_ljust(key, width))

output += ' | '.join(key_list) + '\n'
output += '-' * len(output) + '\n'
Expand All @@ -99,9 +100,9 @@ def as_table(
value = '*' * width

if isinstance(value, (int, float)) or (isinstance(value, str) and value.isnumeric()):
obj_data.append(str(value).rjust(width))
obj_data.append(unicode_rjust(str(value), width))
else:
obj_data.append(str(value).ljust(width))
obj_data.append(unicode_ljust(str(value), width))

output += ' | '.join(obj_data) + '\n'

Expand Down Expand Up @@ -326,3 +327,33 @@ def log(
if level != logging.DEBUG or storage.get('arguments', {}).get('verbose', False):
sys.stdout.write(f"{text}\n")
sys.stdout.flush()

def _count_wchars(string: str) -> int:
"Count the total number of wide characters contained in a string"
return sum(unicodedata.east_asian_width(c) in 'FW' for c in string)

def unicode_ljust(string: str, width: int, fillbyte: str = ' ') -> str:
"""Return a left-justified unicode string of length width.
>>> unicode_ljust('Hello', 15, '*')
'Hello**********'
>>> unicode_ljust('你好', 15, '*')
'你好***********'
>>> unicode_ljust('안녕하세요', 15, '*')
'안녕하세요*****'
>>> unicode_ljust('こんにちは', 15, '*')
'こんにちは*****'
"""
return string.ljust(width - _count_wchars(string), fillbyte)

def unicode_rjust(string: str, width: int, fillbyte: str = ' ') -> str:
"""Return a right-justified unicode string of length width.
>>> unicode_rjust('Hello', 15, '*')
'**********Hello'
>>> unicode_rjust('你好', 15, '*')
'***********你好'
>>> unicode_rjust('안녕하세요', 15, '*')
'*****안녕하세요'
>>> unicode_rjust('こんにちは', 15, '*')
'*****こんにちは'
"""
return string.rjust(width - _count_wchars(string), fillbyte)

0 comments on commit 47ed711

Please sign in to comment.