Move locales and cleanup menu (#1814)

* Cleanup imports and unused code

* Cleanup imports and unused code

* Update build check

* Keep deprecation exception

* Simplify logging

* Move locale into new sub-menu

---------

Co-authored-by: Daniel Girtler <girtler.daniel@gmail.com>
This commit is contained in:
Daniel Girtler 2023-06-05 18:02:49 +10:00 committed by GitHub
parent 5276d95339
commit 06eadb31d4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 374 additions and 187 deletions

View File

@ -213,8 +213,7 @@ def load_config():
"""
from .lib.models import NetworkConfiguration
arguments.setdefault('sys-language', 'en_US')
arguments.setdefault('sys-encoding', 'utf-8')
arguments['locale_config'] = locale.LocaleConfiguration.parse_arg(arguments)
if (archinstall_lang := arguments.get('archinstall-language', None)) is not None:
arguments['archinstall-language'] = TranslationHandler().get_language_by_name(archinstall_lang)

View File

@ -3,7 +3,7 @@ from __future__ import annotations
from enum import Enum, auto
from typing import List, Optional, Any, Dict, TYPE_CHECKING, TypeVar
from archinstall.lib.output import FormattedOutput
from archinstall.lib.utils.util import format_cols
if TYPE_CHECKING:
from archinstall.lib.installer import Installer
@ -185,17 +185,6 @@ class Profile:
return None
def packages_text(self) -> str:
text = str(_('Installed packages')) + ':\n'
nr_packages = len(self.packages)
if nr_packages <= 5:
col = 1
elif nr_packages <= 10:
col = 2
elif nr_packages <= 15:
col = 3
else:
col = 4
text += FormattedOutput.as_columns(self.packages, col)
return text
header = str(_('Installed packages'))
output = format_cols(self.packages, header)
return output

View File

@ -4,6 +4,7 @@ from typing import Any, List, Optional, Union, Dict, TYPE_CHECKING
from . import disk
from .general import secret
from .locale.locale_menu import LocaleConfiguration, LocaleMenu
from .menu import Selector, AbstractMenu
from .mirrors import MirrorConfiguration, MirrorMenu
from .models import NetworkConfiguration
@ -24,9 +25,7 @@ from .interactions import ask_to_configure_network
from .interactions import get_password, ask_for_a_timezone
from .interactions import select_additional_repositories
from .interactions import select_kernel
from .interactions import select_language
from .interactions import select_locale_enc
from .interactions import select_locale_lang
from .utils.util import format_cols
from .interactions import ask_ntp
from .interactions.disk_conf import select_disk_config
@ -36,6 +35,7 @@ if TYPE_CHECKING:
class GlobalMenu(AbstractMenu):
def __init__(self, data_store: Dict[str, Any]):
self._defined_text = str(_('Defined'))
super().__init__(data_store=data_store, auto_cursor=True, preview_size=0.3)
def setup_selection_menu_options(self):
@ -46,28 +46,19 @@ class GlobalMenu(AbstractMenu):
lambda x: self._select_archinstall_language(x),
display_func=lambda x: x.display_name,
default=self.translation_handler.get_language_by_abbr('en'))
self._menu_options['keyboard-layout'] = \
self._menu_options['locale_config'] = \
Selector(
_('Keyboard layout'),
lambda preset: select_language(preset),
default='us')
_('Locales'),
lambda preset: self._locale_selection(preset),
preview_func=self._prev_locale,
display_func=lambda x: self._defined_text if x else '')
self._menu_options['mirror_config'] = \
Selector(
_('Mirrors'),
lambda preset: self._mirror_configuration(preset),
display_func=lambda x: str(_('Defined')) if x else '',
display_func=lambda x: self._defined_text if x else '',
preview_func=self._prev_mirror_config
)
self._menu_options['sys-language'] = \
Selector(
_('Locale language'),
lambda preset: select_locale_lang(preset),
default='en_US')
self._menu_options['sys-encoding'] = \
Selector(
_('Locale encoding'),
lambda preset: select_locale_enc(preset),
default='UTF-8')
self._menu_options['disk_config'] = \
Selector(
_('Disk configuration'),
@ -103,32 +94,32 @@ class GlobalMenu(AbstractMenu):
Selector(
_('Root password'),
lambda preset:self._set_root_password(),
display_func=lambda x: secret(x) if x else 'None')
display_func=lambda x: secret(x) if x else '')
self._menu_options['!users'] = \
Selector(
_('User account'),
lambda x: self._create_user_account(x),
default=[],
display_func=lambda x: f'{len(x)} {_("User(s)")}' if len(x) > 0 else None,
display_func=lambda x: f'{len(x)} {_("User(s)")}' if len(x) > 0 else '',
preview_func=self._prev_users)
self._menu_options['profile_config'] = \
Selector(
_('Profile'),
lambda preset: self._select_profile(preset),
display_func=lambda x: x.profile.name if x else 'None',
display_func=lambda x: x.profile.name if x else '',
preview_func=self._prev_profile
)
self._menu_options['audio'] = \
Selector(
_('Audio'),
lambda preset: self._select_audio(preset),
display_func=lambda x: x if x else 'None',
display_func=lambda x: x if x else '',
default=None
)
self._menu_options['parallel downloads'] = \
Selector(
_('Parallel Downloads'),
add_number_of_parrallel_downloads,
lambda preset: add_number_of_parrallel_downloads(preset),
display_func=lambda x: x if x else '0',
default=0
)
@ -141,19 +132,20 @@ class GlobalMenu(AbstractMenu):
self._menu_options['packages'] = \
Selector(
_('Additional packages'),
# lambda x: ask_additional_packages_to_install(storage['arguments'].get('packages', None)),
ask_additional_packages_to_install,
lambda preset: ask_additional_packages_to_install(preset),
display_func=lambda x: self._defined_text if x else '',
preview_func=self._prev_additional_pkgs,
default=[])
self._menu_options['additional-repositories'] = \
Selector(
_('Optional repositories'),
select_additional_repositories,
lambda preset: select_additional_repositories(preset),
display_func=lambda x: ', '.join(x) if x else None,
default=[])
self._menu_options['nic'] = \
Selector(
_('Network configuration'),
ask_to_configure_network,
lambda preset: ask_to_configure_network(preset),
display_func=lambda x: self._display_network_conf(x),
preview_func=self._prev_network_config,
default={})
@ -177,12 +169,37 @@ class GlobalMenu(AbstractMenu):
self._menu_options['install'] = \
Selector(
self._install_text(),
exec_func=lambda n,v: True if len(self._missing_configs()) == 0 else False,
exec_func=lambda n, v: True if len(self._missing_configs()) == 0 else False,
preview_func=self._prev_install_missing_config,
no_store=True)
self._menu_options['abort'] = Selector(_('Abort'), exec_func=lambda n,v:exit(1))
def _missing_configs(self) -> List[str]:
def check(s):
return self._menu_options.get(s).has_selection()
def has_superuser() -> bool:
sel = self._menu_options['!users']
if sel.current_selection:
return any([u.sudo for u in sel.current_selection])
return False
mandatory_fields = dict(filter(lambda x: x[1].is_mandatory(), self._menu_options.items()))
missing = set()
for key, selector in mandatory_fields.items():
if key in ['!root-password', '!users']:
if not check('!root-password') and not has_superuser():
missing.add(
str(_('Either root-password or at least 1 user with sudo privileges must be specified'))
)
elif key == 'disk_config':
if not check('disk_config'):
missing.add(self._menu_options['disk_config'].description)
return list(missing)
def _update_install_text(self, name: str, value: str):
text = self._install_text()
self._menu_options['install'].update_description(text)
@ -216,6 +233,21 @@ class GlobalMenu(AbstractMenu):
disk_encryption = disk.DiskEncryptionMenu(mods, data_store, preset=preset).run()
return disk_encryption
def _locale_selection(self, preset: LocaleConfiguration) -> LocaleConfiguration:
data_store: Dict[str, Any] = {}
locale_config = LocaleMenu(data_store, preset).run()
return locale_config
def _prev_locale(self) -> Optional[str]:
selector = self._menu_options['locale_config']
if selector.has_selection():
config: LocaleConfiguration = selector.current_selection # type: ignore
output = '{}: {}\n'.format(str(_('Keyboard layout')), config.kb_layout)
output += '{}: {}\n'.format(str(_('Locale language')), config.sys_lang)
output += '{}: {}'.format(str(_('Locale encoding')), config.sys_enc)
return output
return None
def _prev_network_config(self) -> Optional[str]:
selector = self._menu_options['nic']
if selector.has_selection():
@ -224,6 +256,13 @@ class GlobalMenu(AbstractMenu):
return FormattedOutput.as_table(ifaces)
return None
def _prev_additional_pkgs(self):
selector = self._menu_options['packages']
if selector.has_selection():
packages: List[str] = selector.current_selection
return format_cols(packages, None)
return None
def _prev_disk_layouts(self) -> Optional[str]:
selector = self._menu_options['disk_config']
disk_layout_conf: Optional[disk.DiskLayoutConfiguration] = selector.current_selection

View File

@ -3,9 +3,9 @@ from functools import cached_property
from pathlib import Path
from typing import Optional, Dict, List
from .exceptions import SysCallError
from .general import SysCommand
from .networking import list_interfaces, enrich_iface_types
from .exceptions import SysCallError
from .output import debug
AVAILABLE_GFX_DRIVERS = {

View File

@ -12,6 +12,7 @@ from . import disk
from .exceptions import DiskError, ServiceException, RequirementError, HardwareIncompatibilityError, SysCallError
from .general import SysCommand
from .hardware import SysInfo
from .locale import LocaleConfiguration
from .locale import verify_keyboard_layout, verify_x11_keyboard_layout
from .luks import Luks2
from .mirrors import use_mirrors, MirrorConfiguration, add_custom_mirrors
@ -457,37 +458,36 @@ class Installer:
with open(f'{self.target}/etc/hostname', 'w') as fh:
fh.write(hostname + '\n')
def set_locale(self, locale :str, encoding :str = 'UTF-8', *args :str, **kwargs :str) -> bool:
if not len(locale):
return True
def set_locale(self, locale_config: LocaleConfiguration):
modifier = ''
lang = locale_config.sys_lang
encoding = locale_config.sys_enc
# This is a temporary patch to fix #1200
if '.' in locale:
locale, potential_encoding = locale.split('.', 1)
if '.' in locale_config.sys_lang:
lang, potential_encoding = locale_config.sys_lang.split('.', 1)
# Override encoding if encoding is set to the default parameter
# and the "found" encoding differs.
if encoding == 'UTF-8' and encoding != potential_encoding:
if locale_config.sys_enc == 'UTF-8' and locale_config.sys_enc != potential_encoding:
encoding = potential_encoding
# Make sure we extract the modifier, that way we can put it in if needed.
if '@' in locale:
locale, modifier = locale.split('@', 1)
if '@' in locale_config.sys_lang:
lang, modifier = locale_config.sys_lang.split('@', 1)
modifier = f"@{modifier}"
# - End patch
with open(f'{self.target}/etc/locale.gen', 'a') as fh:
fh.write(f'{locale}.{encoding}{modifier} {encoding}\n')
fh.write(f'{lang}.{encoding}{modifier} {encoding}\n')
with open(f'{self.target}/etc/locale.conf', 'w') as fh:
fh.write(f'LANG={locale}.{encoding}{modifier}\n')
fh.write(f'LANG={lang}.{encoding}{modifier}\n')
try:
SysCommand(f'/usr/bin/arch-chroot {self.target} locale-gen')
return True
except SysCallError:
return False
except SysCallError as e:
error(f'Failed to run locale-gen on target: {e}')
def set_timezone(self, zone :str, *args :str, **kwargs :str) -> bool:
if not zone:
@ -620,7 +620,7 @@ class Installer:
return True
def mkinitcpio(self, *flags :str) -> bool:
def mkinitcpio(self, flags: List[str], locale_config: LocaleConfiguration) -> bool:
for plugin in plugins.values():
if hasattr(plugin, 'on_mkinitcpio'):
# Allow plugins to override the usage of mkinitcpio altogether.
@ -630,7 +630,7 @@ class Installer:
# mkinitcpio will error out if there's no vconsole.
if (vconsole := Path(f"{self.target}/etc/vconsole.conf")).exists() is False:
with vconsole.open('w') as fh:
fh.write(f"KEYMAP={storage['arguments']['keyboard-layout']}\n")
fh.write(f"KEYMAP={locale_config.kb_layout}\n")
with open(f'{self.target}/etc/mkinitcpio.conf', 'w') as mkinit:
mkinit.write(f"MODULES=({' '.join(self.modules)})\n")
@ -658,7 +658,7 @@ class Installer:
testing: bool = False,
multilib: bool = False,
hostname: str = 'archinstall',
locales: List[str] = ['en_US.UTF-8 UTF-8']
locale_config: LocaleConfiguration = LocaleConfiguration.default()
):
for mod in self._disk_config.device_modifications:
for part in mod.partitions:
@ -734,12 +734,12 @@ class Installer:
# sys_command(f'/usr/bin/arch-chroot {self.target} ln -s /usr/share/zoneinfo/{localtime} /etc/localtime')
# sys_command('/usr/bin/arch-chroot /mnt hwclock --hctosys --localtime')
self.set_hostname(hostname)
self.set_locale(*locales[0].split())
self.set_locale(locale_config)
# TODO: Use python functions for this
SysCommand(f'/usr/bin/arch-chroot {self.target} chmod 700 /root')
self.mkinitcpio('-P')
self.mkinitcpio(['-P'], locale_config)
self.helper_flags['base'] = True

View File

@ -1,4 +1,3 @@
from .locale_conf import select_locale_lang, select_locale_enc
from .manage_users_conf import UserList, ask_for_additional_users
from .network_conf import ManualNetworkConfig, ask_to_configure_network
from .utils import get_password
@ -10,7 +9,7 @@ from .disk_conf import (
)
from .general_conf import (
ask_ntp, ask_hostname, ask_for_a_timezone, ask_for_audio_selection, select_language,
ask_ntp, ask_hostname, ask_for_a_timezone, ask_for_audio_selection,
select_archinstall_language, ask_additional_packages_to_install,
add_number_of_parrallel_downloads, select_additional_repositories
)

View File

@ -3,7 +3,7 @@ from __future__ import annotations
import pathlib
from typing import List, Any, Optional, TYPE_CHECKING
from ..locale import list_keyboard_languages, list_timezones
from ..locale import list_timezones, list_keyboard_languages
from ..menu import MenuSelectionType, Menu, TextInput
from ..output import warn
from ..packages.packages import validate_package_list
@ -119,18 +119,18 @@ def select_archinstall_language(languages: List[Language], preset: Language) ->
raise ValueError('Language selection not handled')
def ask_additional_packages_to_install(pre_set_packages: List[str] = []) -> List[str]:
def ask_additional_packages_to_install(preset: List[str] = []) -> List[str]:
# Additional packages (with some light weight error handling for invalid package names)
print(_('Only packages such as base, base-devel, linux, linux-firmware, efibootmgr and optional profile packages are installed.'))
print(_('If you desire a web browser, such as firefox or chromium, you may specify it in the following prompt.'))
def read_packages(already_defined: list = []) -> list:
display = ' '.join(already_defined)
def read_packages(p: List = []) -> list:
display = ' '.join(p)
input_packages = TextInput(_('Write additional packages to install (space separated, leave blank to skip): '), display).run().strip()
return input_packages.split() if input_packages else []
pre_set_packages = pre_set_packages if pre_set_packages else []
packages = read_packages(pre_set_packages)
preset = preset if preset else []
packages = read_packages(preset)
if not storage['arguments']['offline'] and not storage['arguments']['no_pkg_lookups']:
while True:

View File

@ -1,43 +0,0 @@
from typing import Any, TYPE_CHECKING, Optional
from ..locale import list_locales
from ..menu import Menu, MenuSelectionType
if TYPE_CHECKING:
_: Any
def select_locale_lang(preset: Optional[str] = None) -> Optional[str]:
locales = list_locales()
locale_lang = set([locale.split()[0] for locale in locales])
choice = Menu(
_('Choose which locale language to use'),
list(locale_lang),
sort=True,
preset_values=preset
).run()
match choice.type_:
case MenuSelectionType.Selection: return choice.single_value
case MenuSelectionType.Skip: return preset
return None
def select_locale_enc(preset: Optional[str] = None) -> Optional[str]:
locales = list_locales()
locale_enc = set([locale.split()[1] for locale in locales])
choice = Menu(
_('Choose which locale encoding to use'),
list(locale_enc),
sort=True,
preset_values=preset
).run()
match choice.type_:
case MenuSelectionType.Selection: return choice.single_value
case MenuSelectionType.Skip: return preset
return None

View File

@ -29,14 +29,14 @@ def select_kernel(preset: List[str] = []) -> List[str]:
sort=True,
multi=True,
preset_values=preset,
allow_reset=True,
allow_reset_warning_msg=warning
).run()
match choice.type_:
case MenuSelectionType.Skip: return preset
case MenuSelectionType.Reset: return []
case MenuSelectionType.Selection: return choice.value # type: ignore
case MenuSelectionType.Selection: return choice.single_value
return []
def ask_for_bootloader(preset: Bootloader) -> Bootloader:

View File

@ -0,0 +1,6 @@
from .locale_menu import LocaleConfiguration
from .locale import (
list_keyboard_languages, list_locales, list_x11_keyboard_languages,
verify_keyboard_layout, verify_x11_keyboard_layout, set_kb_layout,
list_timezones
)

View File

@ -0,0 +1,68 @@
from typing import Iterator, List
from ..exceptions import ServiceException, SysCallError
from ..general import SysCommand
from ..output import error
def list_keyboard_languages() -> Iterator[str]:
for line in SysCommand("localectl --no-pager list-keymaps", environment_vars={'SYSTEMD_COLORS': '0'}):
yield line.decode('UTF-8').strip()
def list_locales() -> List[str]:
with open('/etc/locale.gen', 'r') as fp:
locales = []
# before the list of locales begins there's an empty line with a '#' in front
# so we'll collect the localels from bottom up and halt when we're donw
entries = fp.readlines()
entries.reverse()
for entry in entries:
text = entry.replace('#', '').strip()
if text == '':
break
locales.append(text)
locales.reverse()
return locales
def list_x11_keyboard_languages() -> Iterator[str]:
for line in SysCommand("localectl --no-pager list-x11-keymap-layouts", environment_vars={'SYSTEMD_COLORS': '0'}):
yield line.decode('UTF-8').strip()
def verify_keyboard_layout(layout :str) -> bool:
for language in list_keyboard_languages():
if layout.lower() == language.lower():
return True
return False
def verify_x11_keyboard_layout(layout :str) -> bool:
for language in list_x11_keyboard_languages():
if layout.lower() == language.lower():
return True
return False
def set_kb_layout(locale :str) -> bool:
if len(locale.strip()):
if not verify_keyboard_layout(locale):
error(f"Invalid keyboard locale specified: {locale}")
return False
try:
SysCommand(f'localectl set-keymap {locale}')
except SysCallError as err:
raise ServiceException(f"Unable to set locale '{locale}' for console: {err}")
return True
return False
def list_timezones() -> Iterator[str]:
for line in SysCommand("timedatectl --no-pager list-timezones", environment_vars={'SYSTEMD_COLORS': '0'}):
yield line.decode('UTF-8').strip()

View File

@ -0,0 +1,155 @@
from dataclasses import dataclass
from typing import Dict, Any, TYPE_CHECKING, Optional
from .locale import set_kb_layout, list_keyboard_languages, list_locales
from ..menu import Selector, AbstractSubMenu, MenuSelectionType, Menu
if TYPE_CHECKING:
_: Any
@dataclass
class LocaleConfiguration:
kb_layout: str
sys_lang: str
sys_enc: str
@staticmethod
def default() -> 'LocaleConfiguration':
return LocaleConfiguration('us', 'en_US', 'UTF-8')
def json(self) -> Dict[str, str]:
return {
'kb_layout': self.kb_layout,
'sys_lang': self.sys_lang,
'sys_enc': self.sys_enc
}
@classmethod
def _load_config(cls, config: 'LocaleConfiguration', args: Dict[str, Any]) -> 'LocaleConfiguration':
if 'sys_lang' in args:
config.sys_lang = args['sys_lang']
if 'sys_enc' in args:
config.sys_enc = args['sys_enc']
if 'kb_layout' in args:
config.kb_layout = args['kb_layout']
return config
@classmethod
def parse_arg(cls, args: Dict[str, Any]) -> 'LocaleConfiguration':
default = cls.default()
if 'locale_config' in args:
default = cls._load_config(default, args['locale_config'])
else:
default = cls._load_config(default, args)
return default
class LocaleMenu(AbstractSubMenu):
def __init__(
self,
data_store: Dict[str, Any],
locele_conf: LocaleConfiguration
):
self._preset = locele_conf
super().__init__(data_store=data_store)
def setup_selection_menu_options(self):
self._menu_options['keyboard-layout'] = \
Selector(
_('Keyboard layout'),
lambda preset: self._select_kb_layout(preset),
default='us',
enabled=True)
self._menu_options['sys-language'] = \
Selector(
_('Locale language'),
lambda preset: select_locale_lang(preset),
default='en_US',
enabled=True)
self._menu_options['sys-encoding'] = \
Selector(
_('Locale encoding'),
lambda preset: select_locale_enc(preset),
default='UTF-8',
enabled=True)
def run(self, allow_reset: bool = True) -> LocaleConfiguration:
super().run(allow_reset=allow_reset)
return LocaleConfiguration(
self._data_store['keyboard-layout'],
self._data_store['sys-language'],
self._data_store['sys-encoding']
)
def _select_kb_layout(self, preset: Optional[str]) -> Optional[str]:
kb_lang = select_kb_layout(preset)
if kb_lang:
set_kb_layout(kb_lang)
return kb_lang
def select_locale_lang(preset: Optional[str] = None) -> Optional[str]:
locales = list_locales()
locale_lang = set([locale.split()[0] for locale in locales])
choice = Menu(
_('Choose which locale language to use'),
list(locale_lang),
sort=True,
preset_values=preset
).run()
match choice.type_:
case MenuSelectionType.Selection: return choice.single_value
case MenuSelectionType.Skip: return preset
return None
def select_locale_enc(preset: Optional[str] = None) -> Optional[str]:
locales = list_locales()
locale_enc = set([locale.split()[1] for locale in locales])
choice = Menu(
_('Choose which locale encoding to use'),
list(locale_enc),
sort=True,
preset_values=preset
).run()
match choice.type_:
case MenuSelectionType.Selection: return choice.single_value
case MenuSelectionType.Skip: return preset
return None
def select_kb_layout(preset: Optional[str] = None) -> Optional[str]:
"""
Asks the user to select a language
Usually this is combined with :ref:`archinstall.list_keyboard_languages`.
:return: The language/dictionary key of the selected language
:rtype: str
"""
kb_lang = list_keyboard_languages()
# sort alphabetically and then by length
sorted_kb_lang = sorted(sorted(list(kb_lang)), key=len)
choice = Menu(
_('Select keyboard layout'),
sorted_kb_lang,
preset_values=preset,
sort=False
).run()
match choice.type_:
case MenuSelectionType.Skip: return preset
case MenuSelectionType.Selection: return choice.single_value
return None

View File

@ -3,7 +3,6 @@ from __future__ import annotations
from typing import Callable, Any, List, Iterator, Tuple, Optional, Dict, TYPE_CHECKING
from .menu import Menu, MenuSelectionType
from ..locale import set_keyboard_language
from ..output import error
from ..translationhandler import TranslationHandler, Language
@ -130,7 +129,7 @@ class Selector:
if current:
padding += 5
description = str(self._description).ljust(padding, ' ')
current = str(_('set: {}').format(current))
current = current
else:
description = self._description
current = ''
@ -243,31 +242,6 @@ class AbstractMenu:
elif selector is not None and selector.has_selection():
self._data_store[selector_name] = selector.current_selection
def _missing_configs(self) -> List[str]:
def check(s):
return self._menu_options.get(s).has_selection()
def has_superuser() -> bool:
sel = self._menu_options['!users']
if sel.current_selection:
return any([u.sudo for u in sel.current_selection])
return False
mandatory_fields = dict(filter(lambda x: x[1].is_mandatory(), self._menu_options.items()))
missing = set()
for key, selector in mandatory_fields.items():
if key in ['!root-password', '!users']:
if not check('!root-password') and not has_superuser():
missing.add(
str(_('Either root-password or at least 1 user with sudo privileges must be specified'))
)
elif key == 'disk_config':
if not check('disk_config'):
missing.add(self._menu_options['disk_config'].description)
return list(missing)
def setup_selection_menu_options(self):
""" Define the menu options.
Menu options can be defined here in a subclass or done per program calling self.set_option()
@ -328,9 +302,6 @@ class AbstractMenu:
cursor_pos = None
while True:
# Before continuing, set the preferred keyboard layout/language in the current terminal.
# This will just help the user with the next following questions.
self._set_kb_language()
enabled_menus = self._menus_to_enable()
padding = self._get_menu_text_padding(list(enabled_menus.values()))
@ -425,13 +396,6 @@ class AbstractMenu:
return True
def _set_kb_language(self):
""" general for ArchInstall"""
# Before continuing, set the preferred keyboard layout/language in the current terminal.
# This will just help the user with the next following questions.
if self._data_store.get('keyboard-layout', None) and len(self._data_store['keyboard-layout']):
set_keyboard_language(self._data_store['keyboard-layout'])
def _verify_selection_enabled(self, selection_name: str) -> bool:
""" general """
if selection := self._menu_options.get(selection_name, None):

View File

@ -1,6 +1,7 @@
from pathlib import Path
from typing import Any, TYPE_CHECKING, Optional
from typing import Any, TYPE_CHECKING, Optional, List
from ..output import FormattedOutput
from ..output import info
if TYPE_CHECKING:
@ -28,3 +29,23 @@ def is_subpath(first: Path, second: Path):
return True
except ValueError:
return False
def format_cols(items: List[str], header: Optional[str]) -> str:
if header:
text = f'{header}:\n'
else:
text = ''
nr_items = len(items)
if nr_items <= 5:
col = 1
elif nr_items <= 10:
col = 2
elif nr_items <= 15:
col = 3
else:
col = 4
text += FormattedOutput.as_columns(items, col)
return text

View File

@ -5,6 +5,7 @@ from typing import Any, TYPE_CHECKING
import archinstall
from archinstall import info, debug
from archinstall import SysInfo
from archinstall.lib import locale
from archinstall.lib import disk
from archinstall.lib.global_menu import GlobalMenu
from archinstall.default_profiles.applications.pipewire import PipewireProfile
@ -42,14 +43,10 @@ def ask_user_questions():
global_menu.enable('archinstall-language')
global_menu.enable('keyboard-layout')
# Set which region to download packages from during the installation
global_menu.enable('mirror_config')
global_menu.enable('sys-language')
global_menu.enable('sys-encoding')
global_menu.enable('locale_config')
global_menu.enable('disk_config', mandatory=True)
@ -76,7 +73,7 @@ def ask_user_questions():
global_menu.enable('audio')
# Ask for preferred kernel:
global_menu.enable('kernels')
global_menu.enable('kernels', mandatory=True)
global_menu.enable('packages')
@ -114,9 +111,7 @@ def perform_installation(mountpoint: Path):
# Retrieve list of additional repositories and set boolean values appropriately
enable_testing = 'testing' in archinstall.arguments.get('additional-repositories', [])
enable_multilib = 'multilib' in archinstall.arguments.get('additional-repositories', [])
locale = f"{archinstall.arguments.get('sys-language', 'en_US')} {archinstall.arguments.get('sys-encoding', 'UTF-8').upper()}"
locale_config: locale.LocaleConfiguration = archinstall.arguments['locale_config']
disk_encryption: disk.DiskEncryption = archinstall.arguments.get('disk_encryption', None)
with Installer(
@ -147,7 +142,7 @@ def perform_installation(mountpoint: Path):
testing=enable_testing,
multilib=enable_multilib,
hostname=archinstall.arguments.get('hostname', 'archlinux'),
locales=[locale]
locale_config=locale_config
)
if mirror_config := archinstall.arguments.get('mirror_config', None):
@ -210,7 +205,7 @@ def perform_installation(mountpoint: Path):
# This step must be after profile installs to allow profiles_bck to install language pre-requisits.
# After which, this step will set the language both for console and x11 if x11 was installed for instance.
installation.set_keyboard_language(archinstall.arguments['keyboard-layout'])
installation.set_keyboard_language(locale_config.kb_layout)
if profile_config := archinstall.arguments.get('profile_config', None):
profile_config.profile.post_install(installation)

View File

@ -8,6 +8,7 @@ from archinstall import SysInfo, info, debug
from archinstall.lib import mirrors
from archinstall.lib import models
from archinstall.lib import disk
from archinstall.lib import locale
from archinstall.lib.networking import check_mirror_reachable
from archinstall.lib.profile.profiles_handler import profile_handler
from archinstall.lib import menu
@ -92,14 +93,14 @@ class SwissMainMenu(GlobalMenu):
match self._execution_mode:
case ExecutionMode.Full | ExecutionMode.Lineal:
options_list = [
'keyboard-layout', 'mirror_config', 'disk_config',
'mirror_config', 'disk_config',
'disk_encryption', 'swap', 'bootloader', 'hostname', '!root-password',
'!users', 'profile_config', 'audio', 'kernels', 'packages', 'additional-repositories', 'nic',
'timezone', 'ntp'
]
if archinstall.arguments.get('advanced', False):
options_list.extend(['sys-language', 'sys-encoding'])
options_list.extend(['locale_config'])
mandatory_list = ['disk_config', 'bootloader', 'hostname']
case ExecutionMode.Only_HD:
@ -107,7 +108,7 @@ class SwissMainMenu(GlobalMenu):
mandatory_list = ['disk_config']
case ExecutionMode.Only_OS:
options_list = [
'keyboard-layout', 'mirror_config','bootloader', 'hostname',
'mirror_config','bootloader', 'hostname',
'!root-password', '!users', 'profile_config', 'audio', 'kernels',
'packages', 'additional-repositories', 'nic', 'timezone', 'ntp'
]
@ -115,7 +116,7 @@ class SwissMainMenu(GlobalMenu):
mandatory_list = ['hostname']
if archinstall.arguments.get('advanced', False):
options_list += ['sys-language','sys-encoding']
options_list += ['locale_config']
case ExecutionMode.Minimal:
pass
case _:
@ -176,8 +177,7 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode):
enable_testing = 'testing' in archinstall.arguments.get('additional-repositories', [])
enable_multilib = 'multilib' in archinstall.arguments.get('additional-repositories', [])
locale = f"{archinstall.arguments.get('sys-language', 'en_US')} {archinstall.arguments.get('sys-encoding', 'UTF-8').upper()}"
locale_config: locale.LocaleConfiguration = archinstall.arguments['locale_config']
with Installer(
mountpoint,
@ -206,7 +206,7 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode):
testing=enable_testing,
multilib=enable_multilib,
hostname=archinstall.arguments.get('hostname', 'archlinux'),
locales=[locale]
locale_config=locale_config
)
if mirror_config := archinstall.arguments.get('mirror_config', None):
@ -263,7 +263,7 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode):
# This step must be after profile installs to allow profiles_bck to install language pre-requisits.
# After which, this step will set the language both for console and x11 if x11 was installed for instance.
installation.set_keyboard_language(archinstall.arguments['keyboard-layout'])
installation.set_keyboard_language(locale_config.kb_layout)
if profile_config := archinstall.arguments.get('profile_config', None):
profile_config.profile.post_install(installation)

View File

@ -10,6 +10,7 @@ from archinstall.default_profiles.applications.pipewire import PipewireProfile
from archinstall import disk
from archinstall import menu
from archinstall import models
from archinstall import locale
from archinstall import info, debug
if TYPE_CHECKING:
@ -21,14 +22,10 @@ def ask_user_questions():
global_menu.enable('archinstall-language')
global_menu.enable('keyboard-layout')
# Set which region to download packages from during the installation
global_menu.enable('mirror_config')
global_menu.enable('sys-language')
global_menu.enable('sys-encoding')
global_menu.enable('locale_config')
global_menu.enable('disk_config', mandatory=True)
@ -55,7 +52,7 @@ def ask_user_questions():
global_menu.enable('audio')
# Ask for preferred kernel:
global_menu.enable('kernels')
global_menu.enable('kernels', mandatory=True)
global_menu.enable('packages')
@ -93,9 +90,7 @@ def perform_installation(mountpoint: Path):
# Retrieve list of additional repositories and set boolean values appropriately
enable_testing = 'testing' in archinstall.arguments.get('additional-repositories', [])
enable_multilib = 'multilib' in archinstall.arguments.get('additional-repositories', [])
locale = f"{archinstall.arguments.get('sys-language', 'en_US')} {archinstall.arguments.get('sys-encoding', 'UTF-8').upper()}"
locale_config: locale.LocaleConfiguration = archinstall.arguments['locale_config']
disk_encryption: disk.DiskEncryption = archinstall.arguments.get('disk_encryption', None)
with Installer(
@ -126,7 +121,7 @@ def perform_installation(mountpoint: Path):
testing=enable_testing,
multilib=enable_multilib,
hostname=archinstall.arguments.get('hostname', 'archlinux'),
locales=[locale]
locale_config=locale_config
)
if mirror_config := archinstall.arguments.get('mirror_config', None):
@ -189,7 +184,7 @@ def perform_installation(mountpoint: Path):
# This step must be after profile installs to allow profiles_bck to install language pre-requisits.
# After which, this step will set the language both for console and x11 if x11 was installed for instance.
installation.set_keyboard_language(archinstall.arguments['keyboard-layout'])
installation.set_keyboard_language(locale_config.kb_layout)
if profile_config := archinstall.arguments.get('profile_config', None):
profile_config.profile.post_install(installation)