Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support CJK text alignment #2012

Merged
merged 3 commits into from
Sep 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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)