Replace input with generic_select where necessary

Here are list of changes:
> From now on, `generic_select` will be called "Select function", for clarity

- Slightly updated select function
- Removed options output for some functions, where it's better to do with select function
- Added sorting for all lists passed to select function
- Replaced `dict.values()` with `dict` as options parameter
- Simplified input checking for all functions that use the select function
- Added temporary *(for now)* workaround for passing `?` and `help` inputs
- Merged fix for `partition.format()`
This commit is contained in:
SecondThundeR 2021-04-17 16:35:21 +03:00
parent 9991b19a06
commit a316846121
5 changed files with 56 additions and 93 deletions

View File

@ -154,9 +154,13 @@ def ask_to_configure_network():
# Optionally configure one network interface. # Optionally configure one network interface.
#while 1: #while 1:
# {MAC: Ifname} # {MAC: Ifname}
interfaces = {'ISO-CONFIG' : 'Copy ISO network configuration to installation','NetworkManager':'Use NetworkManager to control and manage your internet connection', **list_interfaces()} interfaces = {
'ISO-CONFIG' : 'Copy ISO network configuration to installation',
'NetworkManager':'Use NetworkManager to control and manage your internet connection',
**list_interfaces()
}
nic = generic_select(interfaces.values(), "Select one network interface to configure (leave blank to skip): ") nic = generic_select(interfaces, "Select one network interface to configure (leave blank to skip): ")
if nic and nic != 'Copy ISO network configuration to installation': if nic and nic != 'Copy ISO network configuration to installation':
if nic == 'Use NetworkManager to control and manage your internet connection': if nic == 'Use NetworkManager to control and manage your internet connection':
return {'nic': nic,'NetworkManager':True} return {'nic': nic,'NetworkManager':True}
@ -190,12 +194,12 @@ def ask_to_configure_network():
def ask_for_disk_layout(): def ask_for_disk_layout():
options = { options = {
'keep-existing' : 'Keep existing partition layout and select which ones to use where.', 'keep-existing' : 'Keep existing partition layout and select which ones to use where',
'format-all' : 'Format entire drive and setup a basic partition scheme.', 'format-all' : 'Format entire drive and setup a basic partition scheme',
'abort' : 'Abort the installation.' 'abort' : 'Abort the installation'
} }
value = generic_select(options.values(), "Found partitions on the selected drive, (select by number) what you want to do: ") value = generic_select(options, "Found partitions on the selected drive, (select by number) what you want to do: ", False)
return next((key for key, val in options.items() if val == value), None) return next((key for key, val in options.items() if val == value), None)
def ask_for_main_filesystem_format(): def ask_for_main_filesystem_format():
@ -206,7 +210,7 @@ def ask_for_main_filesystem_format():
'f2fs' : 'f2fs' 'f2fs' : 'f2fs'
} }
value = generic_select(options.values(), "Select which filesystem your main partition should use (by number or name): ") value = generic_select(options, "Select which filesystem your main partition should use (by number or name): ", False)
return next((key for key, val in options.items() if val == value), None) return next((key for key, val in options.items() if val == value), None)
def generic_select(options, input_text="Select one of the above by index or absolute value: ", allow_empty_input=True, options_output=True): def generic_select(options, input_text="Select one of the above by index or absolute value: ", allow_empty_input=True, options_output=True):
@ -215,9 +219,12 @@ def generic_select(options, input_text="Select one of the above by index or abso
other than the options and their indexes. As an example: other than the options and their indexes. As an example:
generic_select(["first", "second", "third option"]) generic_select(["first", "second", "third option"])
1: first 0: first
2: second 1: second
3: third option 2: third option
When the user has entered the option correctly,
this function returns an item from list, a string, or None
""" """
# Checking if options are different from `list` or `dict` # Checking if options are different from `list` or `dict`
@ -226,14 +233,14 @@ def generic_select(options, input_text="Select one of the above by index or abso
log(" * Here are the link: https://github.com/archlinux/archinstall/issues * ", fg='yellow') log(" * Here are the link: https://github.com/archlinux/archinstall/issues * ", fg='yellow')
raise RequirementError("generic_select() reqiures list or dictionary as options.") raise RequirementError("generic_select() reqiures list or dictionary as options.")
if type(options) == dict: options = sorted(list(options.values())) # To allow only `list` and `dict`, converting values of options and sorting them here. Therefore, now we can only provide the dictionary itself if type(options) == dict: options = sorted(list(options.values())) # To allow only `list` and `dict`, converting values of options and sorting them here. Therefore, now we can only provide the dictionary itself
# if sort: options = sorted(list(options)) # Moved sorting for dictionaries, as some lists are already sorted, when passed here
if len(options) == 0: if len(options) == 0:
log(" * It looks like there are no options to choose from. Maybe it's time to open an issue on GitHub! * ", fg='red') log(" * It looks like there are no options to choose from. Maybe it's time to open an issue on GitHub! * ", fg='red')
log(" * Here are the link: https://github.com/archlinux/archinstall/issues * ", fg='yellow') log(" * Here are the link: https://github.com/archlinux/archinstall/issues * ", fg='yellow')
raise RequirementError('generic_select() requires at least one option to operate.') raise RequirementError('generic_select() requires at least one option to operate.')
# Disable the output of options items, if another function displays something different from this # Added ability to disable the output of options items,
# if another function displays something different from this
if options_output: if options_output:
for index, option in enumerate(options): for index, option in enumerate(options):
print(f"{index}: {option}") print(f"{index}: {option}")
@ -282,18 +289,10 @@ def select_disk(dict_o_disks):
if len(drives) >= 1: if len(drives) >= 1:
for index, drive in enumerate(drives): for index, drive in enumerate(drives):
print(f"{index}: {drive} ({dict_o_disks[drive]['size'], dict_o_disks[drive].device, dict_o_disks[drive]['label']})") print(f"{index}: {drive} ({dict_o_disks[drive]['size'], dict_o_disks[drive].device, dict_o_disks[drive]['label']})")
drive = input('Select one of the above disks (by number or full path) or write /mnt to skip partitioning: ') drive = generic_select(drives, 'Select one of the above disks (by number or full path) or leave blank to skip partitioning: ', True, False)
if drive.strip() == '/mnt': if not drive:
return None return drive
elif drive.isdigit(): drive = dict_o_disks[drive]
drive = int(drive)
if drive >= len(drives):
raise DiskError(f'Selected option "{drive}" is out of range')
drive = dict_o_disks[drives[drive]]
elif drive in dict_o_disks:
drive = dict_o_disks[drive]
else:
raise DiskError(f'Selected drive does not exist: "{drive}"')
return drive return drive
raise DiskError('select_disk() requires a non-empty dictionary of disks to select from.') raise DiskError('select_disk() requires a non-empty dictionary of disks to select from.')
@ -312,24 +311,10 @@ def select_profile(options):
profiles = sorted(list(options)) profiles = sorted(list(options))
if len(profiles) >= 1: if len(profiles) >= 1:
for index, profile in enumerate(profiles): print(' -- The below list is a set of pre-programmed profiles. --')
print(f"{index}: {profile}")
print(' -- The above list is a set of pre-programmed profiles. --')
print(' -- They might make it easier to install things like desktop environments. --') print(' -- They might make it easier to install things like desktop environments. --')
print(' -- (Leave blank and hit enter to skip this step and continue) --')
selected_profile = input('Enter a pre-programmed profile name if you want to install one: ')
if len(selected_profile.strip()) <= 0:
return None
if selected_profile.isdigit() and (pos := int(selected_profile)) <= len(profiles)-1:
selected_profile = profiles[pos]
elif selected_profile in options:
selected_profile = options[options.index(selected_profile)]
else:
RequirementError("Selected profile does not exist.")
selected_profile = generic_select(profiles, 'Enter a pre-programmed profile name if you want to install one or leave blank to skip this step: ')
return Profile(None, selected_profile) return Profile(None, selected_profile)
raise RequirementError("Selecting profiles require a least one profile to be given as an option.") raise RequirementError("Selecting profiles require a least one profile to be given as an option.")
@ -359,12 +344,17 @@ def select_language(options, show_only_country_codes=True):
for index, language in enumerate(languages): for index, language in enumerate(languages):
print(f"{index}: {language}") print(f"{index}: {language}")
print(' -- You can enter ? or help to search for more languages, or skip to use US layout --') # Current workaround for passing `generic_select`,
selected_language = input('Select one of the above keyboard languages (by number or full name): ') # if these values are provided as input
languages.extend(['?', 'help'])
languages_length = len(languages)
if len(selected_language.strip()) == 0: print(f' -- You can enter ? ({languages_length - 2}) or help ({languages_length - 1}) to search for more languages, or skip to use US layout --')
selected_language = generic_select(languages, 'Select one of the above keyboard languages (by number or full name): ', True, False)
if not selected_language:
return DEFAULT_KEYBOARD_LANGUAGE return DEFAULT_KEYBOARD_LANGUAGE
elif selected_language.lower() in ('?', 'help'): elif selected_language in ('?', 'help'):
while True: while True:
filter_string = input('Search for layout containing (example: "sv-"): ') filter_string = input('Search for layout containing (example: "sv-"): ')
new_options = list(search_keyboard_layout(filter_string)) new_options = list(search_keyboard_layout(filter_string))
@ -375,18 +365,13 @@ def select_language(options, show_only_country_codes=True):
return select_language(new_options, show_only_country_codes=False) return select_language(new_options, show_only_country_codes=False)
elif selected_language.isdigit() and (pos := int(selected_language)) <= len(languages)-1:
selected_language = languages[pos]
return selected_language
# I'm leaving "options" on purpose here. # I'm leaving "options" on purpose here.
# Since languages possibly contains a filtered version of # Since languages possibly contains a filtered version of
# all possible language layouts, and we might want to write # all possible language layouts, and we might want to write
# for instance sv-latin1 (if we know that exists) without having to # for instance sv-latin1 (if we know that exists) without having to
# go through the search step. # go through the search step.
elif selected_language in languages:
return selected_language return selected_language
else:
raise RequirementError("Selected language does not exist.")
raise RequirementError("Selecting languages require a least one language to be given as an option.") raise RequirementError("Selecting languages require a least one language to be given as an option.")
@ -413,23 +398,17 @@ def select_mirror_regions(mirrors, show_top_mirrors=True):
print_large_list(regions, margin_bottom=4) print_large_list(regions, margin_bottom=4)
print(' -- You can skip this step by leaving the option blank --') print(' -- You can skip this step by leaving the option blank --')
selected_mirror = input('Select one of the above regions to download packages from (by number or full name): ') selected_mirror = generic_select(regions, 'Select one of the above regions to download packages from (by number or full name): ', True, False)
if len(selected_mirror.strip()) == 0: if not selected_mirror:
# Returning back empty options which can be both used to # Returning back empty options which can be both used to
# do "if x:" logic as well as do `x.get('mirror', {}).get('sub', None)` chaining # do "if x:" logic as well as do `x.get('mirror', {}).get('sub', None)` chaining
return {} return {}
elif selected_mirror.isdigit() and int(selected_mirror) <= len(regions)-1: # I'm leaving "mirrors" on purpose here.
# I'm leaving "mirrors" on purpose here. # Since region possibly contains a known region of
# Since region possibly contains a known region of # all possible regions, and we might want to write
# all possible regions, and we might want to write # for instance Sweden (if we know that exists) without having to
# for instance Sweden (if we know that exists) without having to # go through the search step.
# go through the search step.
region = regions[int(selected_mirror)]
selected_mirrors[region] = mirrors[region]
elif selected_mirror in mirrors:
selected_mirrors[selected_mirror] = mirrors[selected_mirror]
else:
raise RequirementError("Selected region does not exist.")
selected_mirrors[selected_mirror] = mirrors[selected_mirror]
return selected_mirrors return selected_mirrors

View File

@ -76,7 +76,9 @@ def ask_user_questions():
archinstall.log(f" ** The root would be a simple / and the boot partition /boot (as all paths are relative inside the installation). **") archinstall.log(f" ** The root would be a simple / and the boot partition /boot (as all paths are relative inside the installation). **")
while True: while True:
# Select a partition # Select a partition
partition = archinstall.generic_select(partition_mountpoints.keys(), # If we provide keys as options, it's better to convert them to list and sort before passing
mountpoints_list = sorted(list(partition_mountpoints.keys()))
partition = archinstall.generic_select(mountpoints_list,
"Select a partition by number that you want to set a mount-point for (leave blank when done): ") "Select a partition by number that you want to set a mount-point for (leave blank when done): ")
if not partition: if not partition:
break break
@ -106,7 +108,7 @@ def ask_user_questions():
# we have to check if we support it. We can do this by formatting /dev/null with the partitions filesystem. # we have to check if we support it. We can do this by formatting /dev/null with the partitions filesystem.
# There's a nice wrapper for this on the partition object itself that supports a path-override during .format() # There's a nice wrapper for this on the partition object itself that supports a path-override during .format()
try: try:
partition.format(new_filesystem, path='/dev/null', log_formating=False, allow_formatting=True) partition.format(new_filesystem, path='/dev/null', log_formatting=False, allow_formatting=True)
except archinstall.UnknownFilesystemFormat: except archinstall.UnknownFilesystemFormat:
archinstall.log(f"Selected filesystem is not supported yet. If you want archinstall to support '{new_filesystem}', please create a issue-ticket suggesting it on github at https://github.com/archlinux/archinstall/issues.") archinstall.log(f"Selected filesystem is not supported yet. If you want archinstall to support '{new_filesystem}', please create a issue-ticket suggesting it on github at https://github.com/archlinux/archinstall/issues.")
archinstall.log(f"Until then, please enter another supported filesystem.") archinstall.log(f"Until then, please enter another supported filesystem.")

View File

@ -17,7 +17,7 @@ def _prep_function(*args, **kwargs):
""" """
supported_desktops = ['gnome', 'kde', 'awesome', 'sway', 'cinnamon', 'xfce4', 'lxqt', 'i3', 'budgie', 'mate'] supported_desktops = ['gnome', 'kde', 'awesome', 'sway', 'cinnamon', 'xfce4', 'lxqt', 'i3', 'budgie', 'mate']
desktop = archinstall.generic_select(supported_desktops, 'Select your desired desktop environment: ') desktop = archinstall.generic_select(supported_desktops, 'Select your desired desktop environment: ', False)
# Temporarily store the selected desktop profile # Temporarily store the selected desktop profile
# in a session-safe location, since this module will get reloaded # in a session-safe location, since this module will get reloaded

View File

@ -17,7 +17,7 @@ def _prep_function(*args, **kwargs):
""" """
supported_configurations = ['i3-wm', 'i3-gaps'] supported_configurations = ['i3-wm', 'i3-gaps']
desktop = archinstall.generic_select(supported_configurations, 'Select your desired configuration: ') desktop = archinstall.generic_select(supported_configurations, 'Select your desired configuration: ', False)
# Temporarily store the selected desktop profile # Temporarily store the selected desktop profile
# in a session-safe location, since this module will get reloaded # in a session-safe location, since this module will get reloaded

View File

@ -33,10 +33,7 @@ def select_driver(options):
drivers = sorted(list(options)) drivers = sorted(list(options))
if len(drivers) >= 1: if len(drivers) >= 1:
for index, driver in enumerate(drivers): print(' -- The below list are supported graphic card drivers. --')
print(f"{index}: {driver}")
print(' -- The above list are supported graphic card drivers. --')
print(' -- You need to select (and read about) which one you need. --') print(' -- You need to select (and read about) which one you need. --')
lspci = archinstall.sys_command(f'/usr/bin/lspci') lspci = archinstall.sys_command(f'/usr/bin/lspci')
@ -47,7 +44,7 @@ def select_driver(options):
elif b'amd' in line.lower(): elif b'amd' in line.lower():
print(' ** AMD card detected, suggested driver: AMD / ATI **') print(' ** AMD card detected, suggested driver: AMD / ATI **')
selected_driver = input('Select your graphics card driver: ') selected_driver = archinstall.generic_select(drivers, 'Select your graphics card driver: ', False)
initial_option = selected_driver initial_option = selected_driver
# Disabled search for now, only a few profiles exist anyway # Disabled search for now, only a few profiles exist anyway
@ -57,29 +54,14 @@ def select_driver(options):
# filter_string = input('Search for layout containing (example: "sv-"): ') # filter_string = input('Search for layout containing (example: "sv-"): ')
# new_options = search_keyboard_layout(filter_string) # new_options = search_keyboard_layout(filter_string)
# return select_language(new_options) # return select_language(new_options)
if selected_driver.isdigit() and (pos := int(selected_driver)) <= len(drivers)-1:
selected_driver = options[drivers[pos]] selected_driver = options[selected_driver]
elif selected_driver in options:
selected_driver = options[options.index(selected_driver)]
elif len(selected_driver) == 0:
raise archinstall.RequirementError("At least one graphics driver is needed to support a graphical environment. Please restart the installer and try again.")
else:
raise archinstall.RequirementError("Selected driver does not exist.")
if type(selected_driver) == dict: if type(selected_driver) == dict:
driver_options = sorted(list(selected_driver)) driver_options = sorted(list(selected_driver))
for index, driver_package_group in enumerate(driver_options):
print(f"{index}: {driver_package_group}")
selected_driver_package_group = input(f'Which driver-type do you want for {initial_option}: ') selected_driver_package_group = archinstall.generic_select(driver_options, f'Which driver-type do you want for {initial_option}: ', False)
if selected_driver_package_group.isdigit() and (pos := int(selected_driver_package_group)) <= len(driver_options)-1: selected_driver_package_group = selected_driver[selected_driver_package_group]
selected_driver_package_group = selected_driver[driver_options[pos]]
elif selected_driver_package_group in selected_driver:
selected_driver_package_group = selected_driver[selected_driver.index(selected_driver_package_group)]
elif len(selected_driver_package_group) == 0:
raise archinstall.RequirementError(f"At least one driver package is required for a graphical environment using {selected_driver}. Please restart the installer and try again.")
else:
raise archinstall.RequirementError(f"Selected driver-type does not exist for {initial_option}.")
return selected_driver_package_group return selected_driver_package_group