Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
cf42da6
Migrate single selection menus
dgirtler Nov 8, 2025
912c832
Merge branch 'migrate-textual' of github.com:svartkanin/archinstall i…
dgirtler Nov 8, 2025
2752599
Update
dgirtler Nov 9, 2025
b7022d9
Update
dgirtler Nov 17, 2025
d04f44d
Update
dgirtler Nov 19, 2025
2cafde1
Fix input form alignment
dgirtler Nov 22, 2025
d871b8c
Merge remote-tracking branch 'origin/master' into migrate-textual
dgirtler Nov 23, 2025
8ddd4f7
Migrate more menus
dgirtler Nov 24, 2025
3cd2a36
Merge remote-tracking branch 'origin/master' into migrate-textual
dgirtler Nov 29, 2025
ce6b05e
Update
dgirtler Dec 1, 2025
24c20dc
Merge remote-tracking branch 'origin/master' into migrate-textual
dgirtler Dec 8, 2025
1c9597b
Update
dgirtler Dec 8, 2025
4c6609c
Add scrollbar
dgirtler Dec 10, 2025
bd5c4dc
Update
dgirtler Dec 10, 2025
3866834
Update
dgirtler Dec 10, 2025
bfe5423
Update
dgirtler Dec 10, 2025
2dd56e2
Update
dgirtler Dec 11, 2025
014e98f
Update
dgirtler Dec 11, 2025
b83570f
update
dgirtler Dec 11, 2025
77fbcd0
update
dgirtler Dec 11, 2025
4b2b1b3
update
dgirtler Dec 11, 2025
3c877a9
Update
dgirtler Dec 15, 2025
aafd4ba
Update
dgirtler Dec 15, 2025
bd4398c
Update
dgirtler Dec 15, 2025
95316d0
Update
dgirtler Dec 15, 2025
41be806
Update
dgirtler Dec 15, 2025
648120e
Update
dgirtler Dec 15, 2025
63d1de0
Update
dgirtler Dec 15, 2025
3a54663
Update
dgirtler Dec 15, 2025
abad73b
Update
dgirtler Dec 15, 2025
fdb002f
Update
dgirtler Dec 15, 2025
c0fcbbb
Updaet
dgirtler Dec 15, 2025
8868173
Merge remote-tracking branch 'origin/master' into migrate-textual
dgirtler Dec 16, 2025
fefe292
Update linting
dgirtler Dec 16, 2025
ec2d342
Update
dgirtler Dec 16, 2025
210d7fa
Update
dgirtler Dec 16, 2025
4a00bf1
Update github action
dgirtler Dec 16, 2025
ee3251f
Update
dgirtler Dec 16, 2025
8a7a464
Update wifi
dgirtler Dec 16, 2025
c4cc00b
Update wifi
dgirtler Dec 16, 2025
68b3cd8
Update
dgirtler Dec 17, 2025
c8e4141
Update
dgirtler Dec 17, 2025
30598e4
Update color scheme
dgirtler Dec 27, 2025
35b9d60
Update color scheme
dgirtler Dec 27, 2025
c0b3abd
Merge remote-tracking branch 'origin/master' into migrate-textual
dgirtler Dec 28, 2025
b01ee57
test espeakup
dgirtler Dec 30, 2025
34cc9dc
test espeakup
dgirtler Jan 1, 2026
f9fcff2
test espeakup
dgirtler Jan 1, 2026
cedde5f
test espeakup
dgirtler Jan 1, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/python-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
pacman --noconfirm -Sy archlinux-keyring
pacman --noconfirm -Syyu
pacman --noconfirm -Sy python-uv python-setuptools python-pip
pacman --noconfirm -Sy python-pyparted python-pydantic
pacman --noconfirm -Sy python-pyparted python-pydantic python-textual
- name: Remove existing archinstall (if any)
run:
uv pip uninstall archinstall --break-system-packages --system
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,4 @@ requirements.txt
/actions-runner
/cmd_output.txt
uv.lock
pyrightconfig.json
16 changes: 5 additions & 11 deletions archinstall/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,14 @@
from archinstall.lib.network.wifi_handler import wifi_handler
from archinstall.lib.networking import ping
from archinstall.lib.packages.packages import check_package_upgrade
from archinstall.tui.ui.components import tui as ttui
from archinstall.tui.ui.components import tui as tui

from .lib.general import running_from_host
from .lib.hardware import SysInfo
from .lib.output import FormattedOutput, debug, error, info, log, warn
from .lib.pacman import Pacman
from .lib.plugins import load_plugin, plugins
from .lib.translationhandler import Language, tr, translation_handler
from .tui.curses_menu import Tui


# @archinstall.plugin decorator hook to programmatically add
Expand Down Expand Up @@ -76,8 +75,9 @@ def check_version_upgrade() -> str | None:
debug('No archinstall upgrades found')
return None

debug(f'Archinstall latest: {upgrade}')

text = tr('New version available') + f': {upgrade}'
info(text)
return text


Expand All @@ -97,7 +97,7 @@ def main() -> int:

_log_sys_info()

ttui.global_header = 'Archinstall'
tui.global_header = 'Archinstall'

if not arch_config_handler.args.offline:
_check_online()
Expand All @@ -107,9 +107,7 @@ def main() -> int:
new_version = check_version_upgrade()

if new_version:
ttui.global_header = f'{ttui.global_header} {new_version}'
info(new_version)
time.sleep(3)
tui.global_header = f'{tui.global_header} ({new_version})'

if running_from_host():
# log which mode we are using
Expand All @@ -135,9 +133,6 @@ def run_as_a_module() -> None:
except Exception as e:
exc = e
finally:
# restore the terminal to the original state
Tui.shutdown()

if exc:
err = ''.join(traceback.format_exception(exc))
error(err)
Expand All @@ -159,7 +154,6 @@ def run_as_a_module() -> None:
'Language',
'Pacman',
'SysInfo',
'Tui',
'arch_config_handler',
'debug',
'disk_layouts',
Expand Down
17 changes: 7 additions & 10 deletions archinstall/default_profiles/desktop.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from typing import TYPE_CHECKING, override

from archinstall.default_profiles.profile import GreeterType, Profile, ProfileType, SelectResult
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.output import info
from archinstall.lib.profile.profiles_handler import profile_handler
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
from archinstall.tui.types import FrameProperties, PreviewStyle
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType

if TYPE_CHECKING:
from archinstall.lib.installer import Installer
Expand Down Expand Up @@ -60,23 +59,21 @@ def do_on_select(self) -> SelectResult:
MenuItem(
p.name,
value=p,
preview_action=lambda x: x.value.preview_text(),
preview_action=lambda x: x.value.preview_text() if x.value else None,
)
for p in profile_handler.get_desktop_profiles()
]

group = MenuItemGroup(items, sort_items=True, sort_case_sensitive=False)
group.set_selected_by_value(self.current_selection)

result = SelectMenu[Profile](
result = Selection[Profile](
group,
multi=True,
allow_reset=True,
allow_skip=True,
preview_style=PreviewStyle.RIGHT,
preview_size='auto',
preview_frame=FrameProperties.max('Info'),
).run()
preview_location='right',
).show()

match result.type_:
case ResultType.Selection:
Expand Down
13 changes: 5 additions & 8 deletions archinstall/default_profiles/desktops/hyprland.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
from archinstall.default_profiles.desktops import SeatAccess
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.translationhandler import tr
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
from archinstall.tui.types import Alignment, FrameProperties
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType


class HyprlandProfile(XorgProfile):
Expand Down Expand Up @@ -57,13 +56,11 @@ def _ask_seat_access(self) -> None:
default = self.custom_settings.get('seat_access', None)
group.set_default_by_value(default)

result = SelectMenu[SeatAccess](
result = Selection[SeatAccess](
group,
header=header,
allow_skip=False,
frame=FrameProperties.min(tr('Seat access')),
alignment=Alignment.CENTER,
).run()
).show()

if result.type_ == ResultType.Selection:
self.custom_settings['seat_access'] = result.get_value().value
Expand Down
13 changes: 5 additions & 8 deletions archinstall/default_profiles/desktops/labwc.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
from archinstall.default_profiles.desktops import SeatAccess
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.translationhandler import tr
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
from archinstall.tui.types import Alignment, FrameProperties
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType


class LabwcProfile(XorgProfile):
Expand Down Expand Up @@ -54,13 +53,11 @@ def _ask_seat_access(self) -> None:
default = self.custom_settings.get('seat_access', None)
group.set_default_by_value(default)

result = SelectMenu[SeatAccess](
result = Selection[SeatAccess](
group,
header=header,
allow_skip=False,
frame=FrameProperties.min(tr('Seat access')),
alignment=Alignment.CENTER,
).run()
).show()

if result.type_ == ResultType.Selection:
self.custom_settings['seat_access'] = result.get_value().value
Expand Down
13 changes: 5 additions & 8 deletions archinstall/default_profiles/desktops/niri.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
from archinstall.default_profiles.desktops import SeatAccess
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.translationhandler import tr
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
from archinstall.tui.types import Alignment, FrameProperties
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType


class NiriProfile(XorgProfile):
Expand Down Expand Up @@ -62,13 +61,11 @@ def _ask_seat_access(self) -> None:
default = self.custom_settings.get('seat_access', None)
group.set_default_by_value(default)

result = SelectMenu[SeatAccess](
result = Selection[SeatAccess](
group,
header=header,
allow_skip=False,
frame=FrameProperties.min(tr('Seat access')),
alignment=Alignment.CENTER,
).run()
).show()

if result.type_ == ResultType.Selection:
self.custom_settings['seat_access'] = result.get_value().value
Expand Down
13 changes: 5 additions & 8 deletions archinstall/default_profiles/desktops/sway.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
from archinstall.default_profiles.desktops import SeatAccess
from archinstall.default_profiles.profile import GreeterType, ProfileType
from archinstall.default_profiles.xorg import XorgProfile
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.translationhandler import tr
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
from archinstall.tui.types import Alignment, FrameProperties
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType


class SwayProfile(XorgProfile):
Expand Down Expand Up @@ -64,13 +63,11 @@ def _ask_seat_access(self) -> None:
default = self.custom_settings.get('seat_access', None)
group.set_default_by_value(default)

result = SelectMenu[SeatAccess](
result = Selection[SeatAccess](
group,
header=header,
allow_skip=False,
frame=FrameProperties.min(tr('Seat access')),
alignment=Alignment.CENTER,
).run()
).show()

if result.type_ == ResultType.Selection:
self.custom_settings['seat_access'] = result.get_value().value
Expand Down
17 changes: 7 additions & 10 deletions archinstall/default_profiles/server.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from typing import TYPE_CHECKING, override

from archinstall.default_profiles.profile import Profile, ProfileType, SelectResult
from archinstall.lib.menu.helpers import Selection
from archinstall.lib.output import info
from archinstall.lib.profile.profiles_handler import profile_handler
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
from archinstall.tui.types import FrameProperties, PreviewStyle
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType

if TYPE_CHECKING:
from archinstall.lib.installer import Installer
Expand All @@ -26,23 +25,21 @@ def do_on_select(self) -> SelectResult:
MenuItem(
p.name,
value=p,
preview_action=lambda x: x.value.preview_text(),
preview_action=lambda x: x.value.preview_text() if x.value else None,
)
for p in profile_handler.get_server_profiles()
]

group = MenuItemGroup(items, sort_items=True)
group.set_selected_by_value(self.current_selection)

result = SelectMenu[Profile](
result = Selection[Profile](
group,
allow_reset=True,
allow_skip=True,
preview_style=PreviewStyle.RIGHT,
preview_size='auto',
preview_frame=FrameProperties.max('Info'),
multi=True,
).run()
preview_location='right',
).show()

match result.type_:
case ResultType.Selection:
Expand Down
53 changes: 17 additions & 36 deletions archinstall/lib/applications/application_menu.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
from typing import override

from archinstall.lib.menu.abstract_menu import AbstractSubMenu
from archinstall.lib.menu.helpers import Confirmation, Selection
from archinstall.lib.models.application import ApplicationConfiguration, Audio, AudioConfiguration, BluetoothConfiguration, PrintServiceConfiguration
from archinstall.lib.translationhandler import tr
from archinstall.tui.curses_menu import SelectMenu
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.result import ResultType
from archinstall.tui.types import Alignment, FrameProperties, Orientation
from archinstall.tui.ui.menu_item import MenuItem, MenuItemGroup
from archinstall.tui.ui.result import ResultType


class ApplicationMenu(AbstractSubMenu[ApplicationConfiguration]):
Expand Down Expand Up @@ -82,55 +81,38 @@ def _prev_print_service(self, item: MenuItem) -> str | None:


def select_bluetooth(preset: BluetoothConfiguration | None) -> BluetoothConfiguration | None:
group = MenuItemGroup.yes_no()
group.focus_item = MenuItem.no()

if preset is not None:
group.set_selected_by_value(preset.enabled)

header = tr('Would you like to configure Bluetooth?') + '\n'
preset_val = preset.enabled if preset else False

result = SelectMenu[bool](
group,
result = Confirmation(
header=header,
alignment=Alignment.CENTER,
columns=2,
orientation=Orientation.HORIZONTAL,
allow_skip=True,
).run()
preset=preset_val,
).show()

match result.type_:
case ResultType.Selection:
enabled = result.item() == MenuItem.yes()
return BluetoothConfiguration(enabled)
return BluetoothConfiguration(result.get_value())
case ResultType.Skip:
return preset
case _:
raise ValueError('Unhandled result type')


def select_print_service(preset: PrintServiceConfiguration | None) -> PrintServiceConfiguration | None:
group = MenuItemGroup.yes_no()
group.focus_item = MenuItem.no()

if preset is not None:
group.set_selected_by_value(preset.enabled)

header = tr('Would you like to configure the print service?') + '\n'
preset_val = preset.enabled if preset else False

result = SelectMenu[bool](
group,
result = Confirmation(
header=header,
alignment=Alignment.CENTER,
columns=2,
orientation=Orientation.HORIZONTAL,
allow_skip=True,
).run()
preset=preset_val,
).show()

match result.type_:
case ResultType.Selection:
enabled = result.item() == MenuItem.yes()
return PrintServiceConfiguration(enabled)
result.get_value()
return PrintServiceConfiguration(result.get_value())
case ResultType.Skip:
return preset
case _:
Expand All @@ -144,12 +126,11 @@ def select_audio(preset: AudioConfiguration | None = None) -> AudioConfiguration
if preset:
group.set_focus_by_value(preset.audio)

result = SelectMenu[Audio](
result = Selection[Audio](
group,
header=tr('Select audio configuration'),
allow_skip=True,
alignment=Alignment.CENTER,
frame=FrameProperties.min(tr('Audio')),
).run()
).show()

match result.type_:
case ResultType.Skip:
Expand Down
Loading