archinstall/archinstall/lib/general/general_menu.py

201 lines
5.7 KiB
Python

from enum import Enum
from pathlib import Path
from archinstall.lib.locale.utils import list_timezones
from archinstall.lib.menu.helpers import Confirmation, Input, Selection
from archinstall.lib.output import warn
from archinstall.lib.translationhandler import Language, tr
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType
class PostInstallationAction(Enum):
EXIT = tr('Exit archinstall')
REBOOT = tr('Reboot system')
CHROOT = tr('chroot into installation for post-installation configurations')
async def select_ntp(preset: bool = True) -> bool:
header = tr('Would you like to use automatic time synchronization (NTP) with the default time servers?\n') + '\n'
header += (
tr(
'Hardware time and other post-configuration steps might be required in order for NTP to work.\nFor more information, please check the Arch wiki',
)
+ '\n'
)
result = await Confirmation(
header=header,
allow_skip=True,
preset=preset,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return result.item() == MenuItem.yes()
case _:
raise ValueError('Unhandled return type')
async def select_hostname(preset: str | None = None) -> str | None:
result = await Input(
header=tr('Enter a hostname'),
allow_skip=True,
default_value=preset,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
hostname = result.get_value()
if len(hostname) < 1:
return None
return hostname
case ResultType.Reset:
raise ValueError('Unhandled result type')
async def select_timezone(preset: str | None = None) -> str | None:
default = 'UTC'
timezones = list_timezones()
items = [MenuItem(tz, value=tz) for tz in timezones]
group = MenuItemGroup(items, sort_items=True)
group.set_selected_by_value(preset)
group.set_default_by_value(default)
result = await Selection[str](
group,
header=tr('Select timezone'),
allow_reset=True,
allow_skip=True,
enable_filter=True,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Reset:
return default
case ResultType.Selection:
return result.get_value()
async def select_language(preset: str | None = None) -> str | None:
from archinstall.lib.locale.locale_menu import select_kb_layout
# We'll raise an exception in an upcoming version.
# from ..exceptions import Deprecated
# raise Deprecated("select_language() has been deprecated, use select_kb_layout() instead.")
# No need to translate this i feel, as it's a short lived message.
warn('select_language() is deprecated, use select_kb_layout() instead. select_language() will be removed in a future version')
return await select_kb_layout(preset)
async def select_archinstall_language(languages: list[Language], preset: Language) -> Language:
# these are the displayed language names which can either be
# the english name of a language or, if present, the
# name of the language in its own language
items = [MenuItem(lang.display_name, lang) for lang in languages]
group = MenuItemGroup(items, sort_items=True)
group.set_focus_by_value(preset)
title = 'NOTE: Console font will be set automatically for supported languages.\n'
title += 'For other languages, fonts can be found in "/usr/share/kbd/consolefonts"\n'
title += 'and set manually with: setfont <fontname>\n'
result = await Selection[Language](
header=title,
group=group,
allow_reset=False,
allow_skip=True,
).show()
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Selection:
return result.get_value()
case ResultType.Reset:
raise ValueError('Language selection not handled')
async def add_number_of_parallel_downloads(preset: int = 1) -> int | None:
max_recommended = 5
header = tr('This option enables the number of parallel downloads that can occur during package downloads') + '\n'
header += tr(' - Maximum recommended value : {} ( Allows {} parallel downloads at a time )').format(max_recommended, max_recommended) + '\n\n'
header += tr('Enter the number of parallel downloads to be enabled')
def validator(s: str) -> str | None:
try:
value = int(s)
if 1 <= value <= max_recommended:
return None
return tr('Value must be between 1 and {}').format(max_recommended)
except Exception:
return tr('Please enter a valid number')
result = await Input(
header=header,
allow_skip=True,
allow_reset=True,
validator_callback=validator,
default_value=str(preset),
).show()
downloads = 1
match result.type_:
case ResultType.Skip:
return preset
case ResultType.Reset:
return downloads
case ResultType.Selection:
downloads = int(result.get_value())
pacman_conf_path = Path('/etc/pacman.conf')
with pacman_conf_path.open() as f: # noqa: ASYNC230
pacman_conf = f.read().split('\n')
with pacman_conf_path.open('w') as fwrite: # noqa: ASYNC230
for line in pacman_conf:
if 'ParallelDownloads' in line:
fwrite.write(f'ParallelDownloads = {downloads}\n')
else:
fwrite.write(f'{line}\n')
return downloads
async def select_post_installation(elapsed_time: float | None = None) -> PostInstallationAction:
header = 'Installation completed'
if elapsed_time is not None:
minutes = int(elapsed_time // 60)
seconds = int(elapsed_time % 60)
header += f' in {minutes}m{seconds}s' + '\n'
header += tr('What would you like to do next?') + '\n'
items = [MenuItem(action.value, value=action) for action in PostInstallationAction]
group = MenuItemGroup(items)
result = await Selection[PostInstallationAction](
group,
header=header,
allow_skip=False,
).show()
match result.type_:
case ResultType.Selection:
return result.get_value()
case _:
raise ValueError('Post installation action not handled')