Send patches - preferably formatted by git format-patch - to patches at archlinux32 dot org.
summaryrefslogtreecommitdiff
path: root/archinstall/lib/menu/selection_menu.py
diff options
context:
space:
mode:
Diffstat (limited to 'archinstall/lib/menu/selection_menu.py')
-rw-r--r--archinstall/lib/menu/selection_menu.py121
1 files changed, 89 insertions, 32 deletions
diff --git a/archinstall/lib/menu/selection_menu.py b/archinstall/lib/menu/selection_menu.py
index b2f99423..57e290f1 100644
--- a/archinstall/lib/menu/selection_menu.py
+++ b/archinstall/lib/menu/selection_menu.py
@@ -2,23 +2,27 @@ from __future__ import annotations
import logging
import sys
+import pathlib
from typing import Callable, Any, List, Iterator, Tuple, Optional, Dict, TYPE_CHECKING
-from .menu import Menu
+from .menu import Menu, MenuSelectionType
from ..locale_helpers import set_keyboard_language
from ..output import log
from ..translation import Translation
+from ..hsm.fido import get_fido2_devices
if TYPE_CHECKING:
_: Any
-def select_archinstall_language(default='English'):
+
+def select_archinstall_language(preset_value: str) -> Optional[Any]:
"""
copied from user_interaction/general_conf.py as a temporary measure
"""
- languages = Translation.get_all_names()
- language = Menu(_('Select Archinstall language'), languages, default_option=default).run()
- return language
+ languages = Translation.get_available_lang()
+ language = Menu(_('Archinstall language'), languages, preset_values=preset_value).run()
+ return language.value
+
class Selector:
def __init__(
@@ -91,6 +95,10 @@ class Selector:
self._no_store = no_store
@property
+ def description(self) -> str:
+ return self._description
+
+ @property
def dependencies(self) -> List:
return self._dependencies
@@ -115,7 +123,7 @@ class Selector:
def update_description(self, description :str):
self._description = description
- def menu_text(self) -> str:
+ def menu_text(self, padding: int = 0) -> str:
if self._description == '': # special menu option for __separator__
return ''
@@ -128,14 +136,14 @@ class Selector:
current = str(self._current_selection)
if current:
- padding = 35 - len(str(self._description))
- current = ' ' * padding + f'SET: {current}'
-
- return f'{self._description} {current}'
+ padding += 5
+ description = str(self._description).ljust(padding, ' ')
+ current = str(_('set: {}').format(current))
+ else:
+ description = self._description
+ current = ''
- @property
- def text(self):
- return self.menu_text()
+ return f'{description} {current}'
def set_current_selection(self, current :Optional[str]):
self._current_selection = current
@@ -262,8 +270,14 @@ class GeneralMenu:
return preview()
return None
+ def _get_menu_text_padding(self, entries: List[Selector]):
+ return max([len(str(selection.description)) for selection in entries])
+
def _find_selection(self, selection_name: str) -> Tuple[str, Selector]:
- option = [(k, v) for k, v in self._menu_options.items() if v.text.strip() == selection_name.strip()]
+ enabled_menus = self._menus_to_enable()
+ padding = self._get_menu_text_padding(list(enabled_menus.values()))
+ option = [(k, v) for k, v in self._menu_options.items() if v.menu_text(padding).strip() == selection_name.strip()]
+
if len(option) != 1:
raise ValueError(f'Selection not found: {selection_name}')
config_name = option[0][0]
@@ -275,14 +289,18 @@ class GeneralMenu:
# we synch all the options just in case
for item in self.list_options():
self.synch(item)
- self.post_callback # as all the values can vary i have to exec this callback
+
+ self.post_callback() # as all the values can vary i have to exec this callback
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()
- menu_options = [m.text for m in enabled_menus.values()]
+
+ padding = self._get_menu_text_padding(list(enabled_menus.values()))
+ menu_options = [m.menu_text(padding) for m in enabled_menus.values()]
selection = Menu(
_('Set/Modify the below options'),
@@ -291,18 +309,31 @@ class GeneralMenu:
cursor_index=cursor_pos,
preview_command=self._preview_display,
preview_size=self.preview_size,
- skip_empty_entries=True
+ skip_empty_entries=True,
+ skip=False
).run()
- if selection and self.auto_cursor:
- cursor_pos = menu_options.index(selection) + 1 # before the strip otherwise fails
- if cursor_pos >= len(menu_options):
- cursor_pos = len(menu_options) - 1
- selection = selection.strip()
- if selection:
- # if this calls returns false, we exit the menu. We allow for an callback for special processing on realeasing control
- if not self._process_selection(selection):
- break
+ if selection.type_ == MenuSelectionType.Selection:
+ value = selection.value
+
+ if self.auto_cursor:
+ cursor_pos = menu_options.index(value) + 1 # before the strip otherwise fails
+
+ # in case the new position lands on a "placeholder" we'll skip them as well
+ while True:
+ if cursor_pos >= len(menu_options):
+ cursor_pos = 0
+ if len(menu_options[cursor_pos]) > 0:
+ break
+ cursor_pos += 1
+
+ value = value.strip()
+
+ # if this calls returns false, we exit the menu
+ # we allow for an callback for special processing on realeasing control
+ if not self._process_selection(value):
+ break
+
if not self.is_context_mgr:
self.__exit__()
@@ -423,15 +454,41 @@ class GeneralMenu:
def mandatory_overview(self) -> Tuple[int, int]:
mandatory_fields = 0
mandatory_waiting = 0
- for field in self._menu_options:
- option = self._menu_options[field]
+ for field, option in self._menu_options.items():
if option.is_mandatory():
mandatory_fields += 1
if not option.has_selection():
mandatory_waiting += 1
return mandatory_fields, mandatory_waiting
- def _select_archinstall_language(self, default_lang):
- language = select_archinstall_language(default_lang)
- self._translation.activate(language)
- return language
+ def _select_archinstall_language(self, preset_value: str) -> str:
+ language = select_archinstall_language(preset_value)
+ if language is not None:
+ self._translation.activate(language)
+ return language
+
+ return preset_value
+
+ def _select_hsm(self, preset :Optional[pathlib.Path] = None) -> Optional[pathlib.Path]:
+ title = _('Select which partitions to mark for formatting:')
+ title += '\n'
+
+ fido_devices = get_fido2_devices()
+
+ indexes = []
+ for index, path in enumerate(fido_devices.keys()):
+ title += f"{index}: {path} ({fido_devices[path]['manufacturer']} - {fido_devices[path]['product']})"
+ indexes.append(f"{index}|{fido_devices[path]['product']}")
+
+ title += '\n'
+
+ choice = Menu(title, indexes, multi=False).run()
+
+ match choice.type_:
+ case MenuSelectionType.Esc: return preset
+ case MenuSelectionType.Selection:
+ selection: Any = choice.value
+ index = int(selection.split('|',1)[0])
+ return pathlib.Path(list(fido_devices.keys())[index])
+
+ return None