#!/bin/bash ############################################################# # Author: Taryel Hlontsi, 2023 # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see ############################################################# ############################################################# # SETUP SECTION, use "sudo" to run the script ############################################################# LOG_DIR="/home/${SUDO_USER}" LOG="${LOG_DIR}/log.txt" PREFIX="/home/${SUDO_USER}/.local" ############################################################# # HELPER FUNCTIONS ############################################################# info() { GREEN='\033[1;32m' NC='\033[0m' echo -e "${GREEN}$1${NC}" echo -e "INFO:\t$1" >> $LOG } trace() { YELLOW='\033[1;33m' NC='\033[0m' echo -e "${YELLOW}$1${NC}" echo -e "TRACE:\t$1" >> $LOG } warn() { PURPLE='\033[1;35m' NC='\033[0m' echo -e "${PURPLE}$1${NC}" echo -e "WARN:\t$1" >> $LOG } error() { RED='\033[1;31m' NC='\033[0m' echo -e "${RED}$1${NC}" echo -e "ERROR:\t$1" >> $LOG } ############################################################# # 1 - INSTALL ESSENTIAL PACKAGES ############################################################# install_essential_packages() { local step_name='STEP 1 Installing essential packages' warn "Press enter to proceed with $step_name"; read info "$step_name" apt install -y \ git \ apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common \ unzip [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } info "done" } ############################################################# # 2 - INSTALL BUILD DEPENDENCIES FOR EMASC ############################################################# install_emacs_build_dependencies() { local step_name='STEP 2 Installing essential packages for building Emacs and tree-sitter' warn "Press enter to proceed with $step_name"; read info "$step_name" apt install -y \ build-essential \ autoconf \ automake \ texinfo \ libtool \ libgtk-3-dev \ libgtk2.0-dev \ libxpm-dev \ libjpeg-dev \ libgif-dev \ libtiff5-dev \ libpng-dev \ librsvg2-dev \ libgnutls28-dev \ libncurses-dev \ libxml2-dev \ libgpm-dev \ libdbus-1-dev \ libotf-dev \ libm17n-dev \ libmagickcore-dev \ libmagickwand-dev \ libglib2.0-dev \ libgirepository1.0-dev \ gir1.2-gtk-3.0 \ libgtk-3-dev \ libacl1-dev \ libwebkit2gtk-4.1-dev [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } info "done" } ############################################################# # 3 - CLONE AND BUILD TREE_SITTER ############################################################# clone_and_build_tree_sitter() { local step_name='STEP 3 Installing tree-sitter from source' warn "Press enter to proceed with $step_name"; read info "$step_name" # Alternative solution might be just installing via apt: # sudo apt install libtree-sitter-dev git clone https://github.com/tree-sitter/tree-sitter.git cd tree-sitter make -j$(nproc) make install # if emacs fails to build becasue of tree-sitter not found # this step might help: # export LD_LIBRARY_PATH=/usr/local/lib/ [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } cd .. info "done" } ############################################################# # 4 - INSTALL PDF SUPPORT DEPENDENCIES ############################################################# install_pdf_support_dependencies() { local step_name='STEP 4 Installing PDF support dependencies' warn "Press enter to proceed with $step_name"; read info "$step_name" apt install -y mupdf mupdf-tools [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } info "done" } ############################################################# # 5 - INSTALL NATIVE JIT COMPILATION DEPENDENCIES ############################################################# install_native_jit_compilation_dependencies() { local step_name='STEP 5 Installing native JIT compilation support dependencies' warn "Press enter to proceed with $step_name"; read info "$step_name" # apt install build-essential will install gcc-12, so matching libgccjit for it will be: apt -y install libgccjit-12-dev [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } info "done" } ############################################################# # 6 - INSTALL NATIVE JSON SERIALIZATION DEPENDENCIES ############################################################# install_native_json_serialization_dependencies() { local step_name='STEP 6 Installing native JSON serialization support dependencies' warn "Press enter to proceed with $step_name"; read info "$step_name" # speeds up LSP communication apt install -y libjansson4 libjansson-dev [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } info "done" } ############################################################# # 7 - INSTALL IMAGE DYNAMIC RESIZING DEPENDENCIES ############################################################# install_image_dynamic_resizing_dependencies() { local step_name='STEP 7 Installing image dynamic resizing dependencies' warn "Press enter to proceed with $step_name"; read info "$step_name" apt install -y libmagickcore-dev libmagick++-dev [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } info "done" } ############################################################# # 8 - CLONE AND BUILD EMACS ############################################################# clone_and_build_emacs() { local step_name='STEP 8 Building Emacs from source [./configure --help]' warn "Press enter to proceed with $step_name"; read info "$step_name" git clone https://git.savannah.gnu.org/git/emacs.git -b emacs-29 cd emacs ./autogen.sh ./configure \ --with-native-compilation=aot \ --with-json \ --with-tree-sitter \ --with-imagemagick \ --with-rsvg \ --with-xwidgets \ --with-pgtk \ --with-x-toolkit=gtk3 \ --disable-silent-rules \ --exec_prefix=$PREFIX \ --prefix=$PREFIX make -j$(nproc) make install [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } cd .. info "done" } ############################################################# # 9 - INSTALL FONTS ############################################################# install_fonts() { local step_name='STEP 9 Installing fonts' warn "Press enter to proceed with $step_name"; read info "$step_name" VICTOR_MONO="https://github.com/ryanoasis/nerd-fonts/releases/download/v3.1.1/VictorMono.zip" FONTS_DIR="/home/${SUDO_USER}/.local/share/fonts/" mkdir -p $FONTS_DIR && \ wget --continue $VICTOR_MONO --output-document victor-mono.zip && \ unzip -qq victor-mono.zip -d victor-mono && \ rm victor-mono.zip && \ mv victor-mono $FONTS_DIR && \ chown -Rv $SUDO_USER:$SUDO_USER $FONTS_DIR && \ chmod -Rv 755 $FONTS_DIR [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } info "done" } ############################################################# # 10 - INSTALL PYENV ############################################################# install_pyenv() { local step_name='STEP 10 Installing pyenv' warn "Press enter to proceed with $step_name"; read info "$step_name" BASHRC="/home/${SUDO_USER}/.bashrc" PROFILE="/home/${SUDO_USER}/.profile" LOCAL_BIN="/home/${SUDO_USER}/.local/bin/" PYENV="/home/${SUDO_USER}/.pyenv" mkdir -p $LOCAL_BIN $PYENV git clone https://github.com/pyenv/pyenv.git $PYENV echo 'export PATH="$PATH:$HOME/.local/bin"' >> $BASHRC echo 'export PYENV_ROOT="$HOME/.pyenv"' >> $BASHRC echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> $BASHRC echo 'eval "$(pyenv init -)"' >> $BASHRC echo 'export PYENV_ROOT="$HOME/.pyenv"' >> $PROFILE echo 'command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"' >> $PROFILE echo 'eval "$(pyenv init -)"' >> $PROFILE [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } chown -Rv $SUDO_USER:$SUDO_USER $LOCAL_BIN $PYENV && \ chmod -Rv 755 $LOCAL_BIN trace "installing dependencies for pyenv to be able to build python" # dependencies to build python (should be already installed) # apt install -y make \ # build-essential \ # zlib1g-dev \ # libbz2-dev \ # wget \ # curl \ # xz-utils \ # libxml2-dev \ # libffi-dev \ # liblzma-dev # dependencies to build python apt install -y libssl-dev \ libreadline-dev \ libsqlite3-dev \ llvm \ libncursesw5-dev \ tk-dev \ libxmlsec1-dev trace "usage: pyenv install -l | pyenv versions | pyenv install 3.12 | pyenv global 3.12" info "done" } ############################################################# # 11 - INSTALL PYTHON PACKAGES FOR EMACS ############################################################# install_python_packages() { local step_name='STEP 11 Installing python packages' warn "Press enter to proceed with $step_name"; read info "$step_name" apt install -y python3-pip \ python3-jedi \ python3-flake8 \ python3-yapf \ python3-autopep8 \ python3-importmagic \ python3-venv \ black \ flake8 [[ $? -gt 0 ]] && { error "$step_name failed, stopping now"; exit 1; } trace "Ensure the following in ~/emacs.d/init.el" trace "to use the system stuff rather than the eply's virtual environment:" trace "(setq elpy-rpc-virtualenv-path 'current)" info "done" } ############################################################# # 12 - CLONE EMACS CONFIG ############################################################# clone_emacs_config() { local step_name='STEP 12 Cloning emacs config to ~/.emacs.d' warn "Press enter to proceed with $step_name"; read info "$step_name" EMACS_DIR="/home/${SUDO_USER}/.emacs.d/" mkdir -p $EMACS_DIR && \ git clone https://gittar.crabdance.com/tar/.emacs.d.git $EMACS_DIR [[ $? -gt 0 ]] && { error 'cloning emacs config failed, stopping now'; exit 1; } chown -R $SUDO_USER:$SUDO_USER $EMACS_DIR trace "Emacs will throw a lot of compilation warnings on first startup - that's ok" trace "To install the icons you need to run: M-x nerd-icons-install-fonts" info "done" } ############################################################# # RUN SECTION ############################################################# user=$(whoami) if [ $user != root ]; then error "You are using a non-privileged account" exit 1 fi echo $(date +'%Y-%m-%d %H:%M') > $LOG info "Hiya!" sudo apt update sudo apt upgrade -y install_essential_packages install_emacs_build_dependencies clone_and_build_tree_sitter install_pdf_support_dependencies install_native_jit_compilation_dependencies install_native_json_serialization_dependencies install_image_dynamic_resizing_dependencies clone_and_build_emacs install_fonts install_pyenv install_python_packages clone_emacs_config info "Reboot (!) before starting Emacs" info "Bye!" info "PS. Log is here: ${LOG}" exit 0