diff --git a/archinstall/applications/editor.py b/archinstall/applications/editor.py new file mode 100644 index 0000000000..f3b31d8040 --- /dev/null +++ b/archinstall/applications/editor.py @@ -0,0 +1,32 @@ +from typing import TYPE_CHECKING + +from archinstall.lib.models.application import Editor, EditorConfiguration +from archinstall.lib.output import debug + +if TYPE_CHECKING: + from archinstall.lib.installer import Installer + + +class EditorApp: + def get_editor_binary(self, editor: Editor) -> str: + # use the value directly + return editor.value + + def install( + self, + install_session: 'Installer', + editor_config: EditorConfiguration, + ) -> None: + debug(f'Installing editor: {editor_config.editor.value}') + + install_session.add_additional_packages(editor_config.editor.value) + + editor_binary = self.get_editor_binary(editor_config.editor) + # special handling for shorter names needs to happen after pkg has been added above as 'neovim' + editor_binary_short = {'neovim': 'nvim'}.get(editor_binary, editor_binary) + environment_path = install_session.target / 'etc' / 'environment' + + debug(f'Setting EDITOR={editor_binary_short} in {environment_path}') + + with open(environment_path, 'a') as f: + f.write(f'EDITOR={editor_binary_short}\n') diff --git a/archinstall/default_profiles/desktop.py b/archinstall/default_profiles/desktop.py index ab582186e1..fa3129ca2d 100644 --- a/archinstall/default_profiles/desktop.py +++ b/archinstall/default_profiles/desktop.py @@ -25,8 +25,6 @@ def __init__(self, current_selection: list[Profile] = []) -> None: @override def packages(self) -> list[str]: return [ - 'nano', - 'vim', 'openssh', 'htop', 'wget', diff --git a/archinstall/lib/applications/application_handler.py b/archinstall/lib/applications/application_handler.py index e7d16058d5..7053e6f0a2 100644 --- a/archinstall/lib/applications/application_handler.py +++ b/archinstall/lib/applications/application_handler.py @@ -2,6 +2,7 @@ from archinstall.applications.audio import AudioApp from archinstall.applications.bluetooth import BluetoothApp +from archinstall.applications.editor import EditorApp from archinstall.applications.firewall import FirewallApp from archinstall.applications.power_management import PowerManagementApp from archinstall.applications.print_service import PrintServiceApp @@ -43,5 +44,11 @@ def install_applications(self, install_session: 'Installer', app_config: Applica app_config.firewall_config, ) + if app_config.editor_config: + EditorApp().install( + install_session, + app_config.editor_config, + ) + application_handler = ApplicationHandler() diff --git a/archinstall/lib/applications/application_menu.py b/archinstall/lib/applications/application_menu.py index 7dd56e9871..587f76b275 100644 --- a/archinstall/lib/applications/application_menu.py +++ b/archinstall/lib/applications/application_menu.py @@ -7,6 +7,8 @@ Audio, AudioConfiguration, BluetoothConfiguration, + Editor, + EditorConfiguration, Firewall, FirewallConfiguration, PowerManagement, @@ -78,6 +80,12 @@ def _define_menu_options(self) -> list[MenuItem]: preview_action=self._prev_firewall, key='firewall_config', ), + MenuItem( + text=tr('Editor'), + action=select_editor, + preview_action=self._prev_editor, + key='editor_config', + ), ] def _prev_power_management(self, item: MenuItem) -> str | None: @@ -116,6 +124,12 @@ def _prev_firewall(self, item: MenuItem) -> str | None: return f'{tr("Firewall")}: {config.firewall.value}' return None + def _prev_editor(self, item: MenuItem) -> str | None: + if item.value is not None: + config: EditorConfiguration = item.value + return f'{tr("Editor")}: {config.editor.value}' + return None + def select_power_management(preset: PowerManagementConfiguration | None = None) -> PowerManagementConfiguration | None: group = MenuItemGroup.from_enum(PowerManagement) @@ -240,3 +254,29 @@ def select_firewall(preset: FirewallConfiguration | None = None) -> FirewallConf return FirewallConfiguration(firewall=result.get_value()) case ResultType.Reset: return None + + +def select_editor(preset: EditorConfiguration | None = None) -> EditorConfiguration | None: + group = MenuItemGroup.from_enum(Editor) + + header = tr('Would you like to set an editor globally?') + '\n' + + if preset: + group.set_focus_by_value(preset.editor) + + result = SelectMenu[Editor]( + group, + header=header, + allow_skip=True, + alignment=Alignment.CENTER, + allow_reset=True, + frame=FrameProperties.min(tr('Editor')), + ).run() + + match result.type_: + case ResultType.Skip: + return preset + case ResultType.Selection: + return EditorConfiguration(editor=result.get_value()) + case ResultType.Reset: + return None diff --git a/archinstall/lib/global_menu.py b/archinstall/lib/global_menu.py index e8a5884331..7c609ce3d5 100644 --- a/archinstall/lib/global_menu.py +++ b/archinstall/lib/global_menu.py @@ -341,6 +341,11 @@ def _prev_applications(self, item: MenuItem) -> str | None: output += f'{tr("Power management")}: {power_management_config.power_management.value}' output += '\n' + if app_config.editor_config: + editor_config = app_config.editor_config + output += f'{tr("Editor")}: {editor_config.editor.value}' + output += '\n' + return output return None diff --git a/archinstall/lib/models/application.py b/archinstall/lib/models/application.py index 7ecb7a0717..602528840a 100644 --- a/archinstall/lib/models/application.py +++ b/archinstall/lib/models/application.py @@ -38,6 +38,19 @@ class FirewallConfigSerialization(TypedDict): firewall: str +class Editor(StrEnum): + NANO = auto() + MICRO = auto() + VI = auto() + VIM = auto() + NEOVIM = auto() + EMACS = auto() + + +class EditorConfigSerialization(TypedDict): + editor: str + + class ZramAlgorithm(StrEnum): ZSTD = 'zstd' LZO_RLE = 'lzo-rle' @@ -52,6 +65,7 @@ class ApplicationSerialization(TypedDict): power_management_config: NotRequired[PowerManagementConfigSerialization] print_service_config: NotRequired[PrintServiceConfigSerialization] firewall_config: NotRequired[FirewallConfigSerialization] + editor_config: NotRequired[EditorConfigSerialization] @dataclass @@ -126,6 +140,22 @@ def parse_arg(arg: dict[str, Any]) -> 'FirewallConfiguration': ) +@dataclass +class EditorConfiguration: + editor: Editor + + def json(self) -> EditorConfigSerialization: + return { + 'editor': self.editor.value, + } + + @staticmethod + def parse_arg(arg: dict[str, Any]) -> 'EditorConfiguration': + return EditorConfiguration( + Editor(arg['editor']), + ) + + @dataclass(frozen=True) class ZramConfiguration: enabled: bool @@ -148,6 +178,7 @@ class ApplicationConfiguration: power_management_config: PowerManagementConfiguration | None = None print_service_config: PrintServiceConfiguration | None = None firewall_config: FirewallConfiguration | None = None + editor_config: EditorConfiguration | None = None @staticmethod def parse_arg( @@ -175,6 +206,9 @@ def parse_arg( if args and (firewall_config := args.get('firewall_config')) is not None: app_config.firewall_config = FirewallConfiguration.parse_arg(firewall_config) + if args and (editor_config := args.get('editor_config')) is not None: + app_config.editor_config = EditorConfiguration.parse_arg(editor_config) + return app_config def json(self) -> ApplicationSerialization: @@ -195,4 +229,7 @@ def json(self) -> ApplicationSerialization: if self.firewall_config: config['firewall_config'] = self.firewall_config.json() + if self.editor_config: + config['editor_config'] = self.editor_config.json() + return config