From 67011cf67937f39c46b61629c08db6e45ab1a26c Mon Sep 17 00:00:00 2001 From: KarimAziev Date: Wed, 27 Nov 2024 12:12:22 +0200 Subject: [PATCH] feat: Add interactive (-i) mode and non-interactive default behavior MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Introduced a new `-i` flag for interactive mode, which prompts the user for confirmation at each step. - Changed the default behavior to run in non-interactive mode (`SKIP_PROMPT="yes"`) and execute all steps without prompting. - Revised the script’s help and examples to make the default behavior more intuitive and align with typical automation expectations. --- README.md | 180 ++++++++++++++++++++++++++----------------------- build-emacs.sh | 70 ++++++++++++------- 2 files changed, 140 insertions(+), 110 deletions(-) diff --git a/README.md b/README.md index 98b249b..76de3f3 100644 --- a/README.md +++ b/README.md @@ -1,161 +1,171 @@ # About -This is a bash script to automate the installation of Emacs on Ubuntu 22 with Wayland. +This is a Bash script that automates the process of building and installing the latest version of Emacs from source on `Ubuntu 22` with either `Wayland` or `X11` display servers. -You can run the script with different flags to modify its behavior. The available options are: +The script can be customized to execute or skip specific steps, use a custom installation directory, or include additional configuration options. -- `-h`: Display the help message and exit. -- `-p DIRECTORY`: Specify the Emacs installation directory. The default is `$HOME/emacs`. -- `-u URL`: Specify the remote URL of the Emacs Git repository. The default is . -- `-y`: Skip all prompts and directly proceed with the installation and configuration steps. -- `-s [OPTIONS]`: Specify the exact steps to execute. Available steps are: `install_deps`, `kill_emacs`, `remove_emacs`, `pull_emacs`, `build_emacs`, `install_emacs`, `fix_emacs_xwidgets`, `copy_emacs_icon`. Steps should be separated by commas. By default, all steps are enabled. -- `-n [OPTIONS]`: Specifies the steps to skip. Available steps are the same as listed for the `-s` option. -- `-c OPTIONS`: Specify additional configure options for building Emacs. Options should be separated by commas. + -# Emacs Installer Script for Ubuntu 22 +**Table of Contents** > - [About](#about) > - [Requirements](#requirements) -> - [Steps](#steps) -> - [Usage](#usage) -> - [Prompt Every Step (Default)](#prompt-every-step-default) -> - [Execute All Steps Without Prompt](#execute-all-steps-without-prompt) +> - [Steps Performed by the Script](#steps-performed-by-the-script) +> - [Run All Steps in Non-Interactive Mode (Default)](#run-all-steps-in-non-interactive-mode-default) +> - [Run All Steps in Interactive Mode](#run-all-steps-in-interactive-mode) > - [Execute Specific Steps](#execute-specific-steps) > - [Skip Certain Steps](#skip-certain-steps) -> - [Use a Custom Directory](#use-a-custom-directory) -> - [Override Default Configure Options](#override-default-configure-options) +> - [Use a Custom Installation Directory](#use-a-custom-installation-directory) +> - [Add or Override Configuration Options](#add-or-override-configuration-options) +> - [Display Help](#display-help) > - [List of packages that will be installed](#list-of-packages-that-will-be-installed) > - [Disclaimer](#disclaimer) + + ## Requirements -This script requires that you have `bash`, `git`, and `sudo` privilege. -It's designed to work on `Ubuntu 22`. +- **Bash**: Required to run the script. +- **Git**: The Emacs source is cloned from a remote Git repository. +- **Sudo Privileges**: Many operations, such as installing packages and configuring system files, require elevated permissions. + +--- -## Steps +## Steps Performed by the Script -Here are the steps that this script will perform in order: +> [!TIP] +> By default, the script executes all installation steps **non-interactively** in sequence. If you prefer to confirm each step manually, you can opt into **interactive mode** with the `-i` flag. -1. `install_deps`: Install the necessary - [dependencies](#list-of-packages-that-will-be-installed) for Emacs. -2. `kill_emacs`: Kill any running Emacs process. -3. `remove_emacs`: Uninstall Emacs and perform a clean up. -4. `pull_emacs`: Pull the latest Emacs source code. -5. `build_emacs`: Build Emacs from the source code. -6. `install_emacs`: Install Emacs from the built source code. -7. `fix_emacs_xwidgets`: Fix - [issue](https://git.savannah.gnu.org/cgit/emacs.git/tree/etc/PROBLEMS?h=master#n181) - related to Emacs XWidgets. -8. `copy_emacs_icon`: Download and replace the default Emacs Icon with - the [Spacemacs logo](https://github.com/nashamri/spacemacs-logo) by - Nasser Alshammari. +Here are the steps the script performs sequentially: -## Usage +1. `install_deps`: Installs all the required [system packages](#list-of-packages-that-will-be-installed) (e.g., build tools and libraries). +2. `kill_emacs`: Ensures that no running Emacs process is active. +3. `remove_emacs`: Cleans up any previous Emacs installation (if applicable). +4. `pull_emacs`: Clones or updates the Emacs source repository to the latest version. +5. `build_emacs`: Configures and builds Emacs using the specified options. +6. `install_emacs`: Installs Emacs to the system (e.g., `/usr/local`). +7. `fix_emacs_xwidgets`: Fixes known [issue](https://git.savannah.gnu.org/cgit/emacs.git/tree/etc/PROBLEMS?h=master#n181) with XWidgets. +8. `copy_emacs_icon`: Replaces the default Emacs icon with a new icon (the [Spacemacs logo](https://github.com/nashamri/spacemacs-logo)). -### Prompt Every Step (Default) +### Run All Steps in Non-Interactive Mode (Default) -To execute the build and installation script step-by-step, use the -following command: +By default, the script runs **all steps non-interactively**. You can simply execute it without any options: -```shell +```bash bash -c "$(wget -qO- https://raw.githubusercontent.com/KarimAziev/build-emacs/main/build-emacs.sh)" ``` -If you have already downloaded the script, simply execute: +Or, if you’ve downloaded the script locally: -```shell +```bash ./build-emacs.sh ``` -### Execute All Steps Without Prompt +> [!IMPORTANT] +> This mode assumes "yes" to all prompts and ensures a fully automated installation. + +--- + +### Run All Steps in Interactive Mode + +If you prefer to review and confirm each step before it is executed, use the `-i` flag to enable **interactive mode**: -To execute all steps without prompting, use the `-y` argument (which -assumes "yes") to each question. +```bash +bash -c "$(wget -qO- https://raw.githubusercontent.com/KarimAziev/build-emacs/main/build-emacs.sh) -i" +``` + +Or, if you’ve downloaded the script locally: -```shell -bash -c "$(wget -qO- https://raw.githubusercontent.com/KarimAziev/build-emacs/main/build-emacs.sh) -y" +```bash +./build-emacs.sh -i ``` -Or, if you have the script downloaded: +In this mode, you will be prompted for confirmation before each step. For example: -```shell -./build-emacs.sh -y +``` +Execute install_deps? [Y/n] ``` +--- + ### Execute Specific Steps -To execute specific steps, use the `-s` argument with the desired steps, -separated by commas. For instance, to only compile (`build_emacs`) and -install (`install_emacs`) Emacs skipping other steps: +Use the `-s` flag to specify exact steps you want to execute, separated by commas (`,`). For example, to only clone the Emacs repository, build it, and install it: -```shell -bash -c "$(wget -qO- https://raw.githubusercontent.com/KarimAziev/build-emacs/main/build-emacs.sh) -s build_emacs,install_emacs" +```bash +bash -c "$(wget -qO- https://raw.githubusercontent.com/KarimAziev/build-emacs/main/build-emacs.sh) -s pull_emacs,build_emacs,install_emacs" ``` -Or, if you have the script downloaded: +Or, if you've downloaded the script locally: -```shell -./build-emacs.sh -s build_emacs,install_emacs +```bash +./build-emacs.sh -s pull_emacs,build_emacs,install_emacs ``` -### Skip Certain Steps +--- -You can also skip certain steps using the `-n` argument, followed by the -steps you wish to omit. +### Skip Certain Steps -The example below will execute all steps except installing dependencies -(`install_deps`). +The `-n` flag lets you omit specific steps. For instance, to skip installing dependencies (`install_deps`) and pulling the Emacs source (`pull_emacs`): -```shell -bash -c "$(wget -qO- https://raw.githubusercontent.com/KarimAziev/build-emacs/main/build-emacs.sh) -n install_deps" +```bash +./build-emacs.sh -n install_deps,pull_emacs ``` -Or, if you have the script downloaded: +This will run all steps except `install_deps` and `pull_emacs`. -```shell -./build-emacs.sh -n install_deps -``` +--- -### Use a Custom Directory +### Use a Custom Installation Directory -To build in a custom directory, use the `-p` argument, followed by the -path to your directory: +To specify a directory where Emacs should be cloned and built, use the `-p` flag followed by the path: -```shell +```bash bash -c "$(wget -qO- https://raw.githubusercontent.com/KarimAziev/build-emacs/main/build-emacs.sh) -p $HOME/myemacs" ``` -Or, if you have the script downloaded: +Or, if you've downloaded the script locally: -```shell +```bash ./build-emacs.sh -p $HOME/myemacs ``` -### Override Default Configure Options +The default directory is `$HOME/emacs`. + +--- -The script uses the following default configure options for building Emacs: +### Add or Override Configuration Options + +The script uses the following default build options: - `--with-pgtk` -- `--with-xwidgets` (if the installed version of `libwebkit2gtk-4.1-0` is between `2.12` (inclusive) and `2.41.92` (exclusive)) - `--with-native-compilation=aot` - `--without-compress-install` - `--with-tree-sitter` - `--with-mailutils` -You can override these options or add new ones using the `-c` argument. Options should be separated by commas. +If `libwebkit2gtk-4.1` is installed and meets the required version, `--with-xwidgets` will also be added automatically. -For example, to disable native compilation and PGTK, you can use: +You can append or override these with the `-c` flag. For instance: -```shell -bash -c "$(wget -qO- https://raw.githubusercontent.com/KarimAziev/build-emacs/main/build-emacs.sh) -c --with-native-compilation=no,--without-pgtk" +```bash +./build-emacs.sh -c --with-native-compilation=no,--without-pgtk ``` -Or, if you have the script downloaded: +This example disables both native compilation and PGTK. -```shell -./build-emacs.sh -c --with-native-compilation=no,--without-pgtk +--- + +### Display Help + +To see all available options, use the `-h` flag: + +```bash +./build-emacs.sh -h ``` +--- + ## List of packages that will be installed | Package | Description | @@ -324,6 +334,4 @@ Or, if you have the script downloaded: ## Disclaimer -Please review the script before running it. I take no responsibility for -any adverse effects it may have on your system. Always ensure you have a -backup of your important data. +Please review the script before running it. I take no responsibility for any adverse effects it may have on your system. Always ensure you have a backup of your important data. diff --git a/build-emacs.sh b/build-emacs.sh index f128362..e3fc6c2 100755 --- a/build-emacs.sh +++ b/build-emacs.sh @@ -9,7 +9,7 @@ if [ "${VERBOSE}" = "true" ]; then set -x fi -SKIP_PROMPT="false" +SKIP_PROMPT=${SKIP_PROMPT:-yes} EMACS_DIRECTORY="$HOME/emacs" EMACS_REMOTE_URL="https://git.savannah.gnu.org/git/emacs.git" CONFIGURE_OPTIONS="" @@ -63,17 +63,29 @@ usage() { echo echo "Options:" echo " -h Display this help message and exit." + echo " -i Run in interactive mode, prompting for confirmation at each step." + echo " -y Run in non-interactive mode (default) and execute all steps without prompting." echo " -p DIRECTORY Specify the Emacs installation directory. Default is '\$HOME/emacs'." echo " -u URL Specify the remote URL of the Emacs Git repository. Default is https://git.savannah.gnu.org/git/emacs.git." - echo " -y Skip all prompts and directly proceed with the installation and configuration steps." - echo " -s [install_deps,kill_emacs,remove_emacs,pull_emacs,build_emacs,install_emacs,fix_emacs_xwidgets,copy_emacs_icon] Specify the exact steps to execute. Steps should be separated by commas. By default, all steps are enabled." - echo " -n [install_deps,kill_emacs,remove_emacs,pull_emacs,build_emacs,install_emacs,fix_emacs_xwidgets,copy_emacs_icon] Specify the steps to skip. Steps should be separated by commas." + echo " -s STEPS Specify the exact steps to execute. Steps should be separated by commas." + echo " Available steps: install_deps, kill_emacs, remove_emacs, pull_emacs," + echo " build_emacs, install_emacs, fix_emacs_xwidgets, copy_emacs_icon." + echo " -n STEPS Specify the steps to skip. Steps should be separated by commas." + echo " Available steps: install_deps, kill_emacs, remove_emacs, pull_emacs," + echo " build_emacs, install_emacs, fix_emacs_xwidgets, copy_emacs_icon." + echo " By default, all steps are enabled." echo " -c OPTIONS Specify additional configure options for building Emacs. Options should be separated by commas." echo echo "Examples:" - echo " $0 -p \$HOME/myemacs -s pull_emacs,build_emacs,install_emacs - Perform only the pull, build, and install steps." - echo " $0 -p \$HOME/myemacs -n install_deps,pull_emacs - Skip installing dependencies and pulling the Emacs source, using the directory \$HOME/myemacs." - echo " $0 -c --with-native-compilation=no,--without-pgtk - Specify additional configure options for building Emacs." + echo " $0 Run all steps in non-interactive mode (default)." + echo " $0 -i Run all steps in interactive mode, prompting for confirmation at each step." + echo " $0 -y Explicitly run all steps in non-interactive mode (same as default)." + echo " $0 -p \$HOME/myemacs -s pull_emacs,build_emacs,install_emacs" + echo " Perform only the pull, build, and install steps in non-interactive mode." + echo " $0 -p \$HOME/myemacs -n install_deps,pull_emacs" + echo " Skip installing dependencies and pulling the Emacs source." + echo " $0 -c --with-native-compilation=no,--without-pgtk" + echo " Specify additional configure options for building Emacs." exit 0 } @@ -102,18 +114,32 @@ set_steps() { } parse_arguments() { - while getopts ":hn:p:ys:u:c:" OPTION; do + mode="default" + while getopts ":hin:p:ys:u:c:" OPTION; do case $OPTION in h) usage exit 0 ;; - p) - EMACS_DIRECTORY=$(readlink -f "$OPTARG") + i) + if [ "$mode" = "non-interactive" ]; then + echo >&2 "Error: Cannot use -i (interactive) and -y (non-interactive) together." + exit 1 + fi + mode="interactive" + SKIP_PROMPT="no" ;; y) + if [ "$mode" = "interactive" ]; then + echo >&2 "Error: Cannot use -i (interactive) and -y (non-interactive) together." + exit 1 + fi + mode="non-interactive" SKIP_PROMPT="yes" ;; + p) + EMACS_DIRECTORY=$(readlink -f "$OPTARG") + ;; n) filter_steps "$OPTARG" ;; @@ -156,26 +182,24 @@ cleanup() { main() { parse_arguments "$@" + echo "Running in $([ "$SKIP_PROMPT" = "yes" ] && echo 'non-interactive' || echo 'interactive') mode." + echo "Steps to execute: ${steps[*]}" + process_configure_options - # Update the user's cached credentials - sudo -v + sudo -v # Update the user's cached credentials refresh_sudo trap cleanup EXIT for step in "${steps[@]}"; do - if [ $SKIP_PROMPT == "yes" ]; then - $step - else + if [ "$SKIP_PROMPT" = "no" ]; then read -r -p "Execute $step? [Y/n] " answer - case ${answer:-Y} in # Set default to Y - [yY]*) - $step - ;; - *) - echo "Skipping $step" - ;; + case ${answer:-Y} in + [yY]*) $step ;; + *) echo "Skipping $step" ;; esac + else + $step fi done } @@ -191,8 +215,6 @@ copy_emacs_icon() { echo "Loading emacs icon" mkdir -p "$download_dir" - echo "Loading emacs icon" - wget -O "$download_dir/emacs.svg" "$icon_url" \ && sudo sed -i "s|^\(Icon=\).*|\1$download_dir/emacs.svg|" "$emacs_desktop_filename" fi