# -*- org-confirm-babel-evaluate: nil -*-
#+TITLE: Phundrak-flavored Arch Linux
#+setupfile: headers
#+OPTIONS: auto-id:t
#+HTML_HEAD_EXTRA: <meta name="description" content="Phundrak-flavored Arch Linux" />
#+HTML_HEAD_EXTRA: <meta property="og:title" content="Phundrak-flavored Arch Linux" />
#+HTML_HEAD_EXTRA: <meta property="og:description" content="How to install a Phundrak-flavored Arch Linux" />
#+PROPERTY: header-args :tangle no :exports none
#+PROPERTY: header-args:sh :tangle no :exports code
#+PROPERTY: header-args:fish :exports code :noweb yes
#+PROPERTY: header-args:emacs-lisp :exports none :noweb yes :tangle no :cache yes

* Introduction
  :PROPERTIES:
  :CUSTOM_ID: Introduction-cd5792cd
  :END:
  Here will be  presented what I do to  get my system up and running  on a fresh
  Arch Linux install.  These installation instructions were written  in order to
  get an Arch  Linux distribution up and running with  the same configuration as
  my main computer’s and my travelling laptop’s configuration.

* Install Arch Linux
  :PROPERTIES:
  :CUSTOM_ID: Install_Arch_Linux-ac7ad3b2
  :END:
  I usually install Arch  from the [[https://www.archlinux.org/download/][vanilla ISO]], however I  began using [[https://github.com/MatMoul/archfi][archfi]] to
  install easily  the distro (I’ve done  it so many  times, I know how  it works
  now). Usually,  my distros will be  installed on at least  two partitions, one
  dedicated to =/home=, the other to the root partition =/=.

  If the computer supports EFI bootloaders, the EFI partition will be mounted on
  =/boot=.  I generally  use rEFInd  as my  boot manager,  but if  you are  more
  comfortable with another one, just install what you want. Be aware that if you
  format your =/boot= partition, you will  delete all boot managers that already
  exist;  so, if  you are  dual-booting, *DO  NOT FORMAT  IT*. Yes,  I made  the
  mistake of wiping the Windows boot manager.

  The swap partition is always at least 4GB  large, and I should have a total of
  12GB of combined RAM  and swap. This means on my main computer  I have 16GB of
  RAM and 4GB of swap, but on my thinkpad I have 4GB of RAM and 8GB of swap.

** Get the latest live system with fast mirrors
   :PROPERTIES:
   :CUSTOM_ID: Install_Arch_Linux-Get_the_latest_live_system_with_fast_mirrors-59d2a90d
   :END:
   When you boot into the live ISO, execute the following command:
   #+BEGIN_SRC sh :exports code
     pacman -Sy reflector
     reflector -c France -c Germany -l 200 -p http -p https --sort rate \
               --save /etc/pacman.d/mirrorlist --verbose
   #+END_SRC
   This will update the  packages from your live ISO, and you  will get the best
   mirrors for your installation. Of course, change the countries accordingly to
   your location.

** Install the system
   :PROPERTIES:
   :CUSTOM_ID: Install_Arch_Linux-Install_the_system-3ff49aa6
   :END:
   Then you can use a custom script to  ease your installation of Arch if you do
   not wish to do it manually. Personally, I’ve done it several times already, I
   know  how the  distro works,  I just  want to  be able  to install  my distro
   quickly now.
   #+BEGIN_SRC sh
     wget archfi.sf.net/archfi
     # Or from matmoul.github.io/archfi if SourceForge is down
     sh archfi
   #+END_SRC
   Then, follow the instructions and install Arch Linux. Take the opportunity to
   install as many packages as you need,  mainly =yay= which I use as my package
   manager  (it   is  just  a  wrapper   for  =pacman=)  and  AUR   helper,  and
   =pacman-contrib= which will help us installing some packages later.

   Once your system is installed, reboot and remove your installation media from
   your computer.

* Install basic packages
  :PROPERTIES:
  :CUSTOM_ID: Install_basic_packages-c2cfb42d
  :END:
  We will need some basic packages in order to run the bootstrap file. So, let’s
  install =fish= (our shell running the script) and =git=.
  #+BEGIN_SRC sh
    yay -Sy fish git yadm
  #+END_SRC

* Execute bootstrap
  :PROPERTIES:
  :HEADER-ARGS: :tangle ~/.config/yadm/bootstrap
  :HEADER-ARGS:python: :tangle no
  :CUSTOM_ID: Execute_bootstrap-e37054ef
  :END:
  =yadm=  comes with  a very  handy  feature: its  bootstrap script.  It can  be
  executed automatically once the dotfiles are cloned with yadm:
  #+BEGIN_SRC fish :tangle no
    yadm clone https://labs.phundrak.com/phundrak/dotfiles
    # or if labs.phundrak.com is down or too slow for you
    yadm clone https://github.com/phundrak/dotfiles
  #+END_SRC

  Notice these two header files, we can see  this is a fish script, hence why we
  need fish (which is my daily shell anyway).
  #+BEGIN_SRC fish
    #!/usr/bin/fish
    # -*- mode: fish -*-
  #+END_SRC
  Let’s take a look at what it does.

** Decrypt private yadm files
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Decrypt_private_yadm_files-68af7157
   :END:
   Some  private  files are  stored  encrypted  in  the  repository of  my  yadm
   dotfiles. I will need them later on during the bootstrap execution.
   #+BEGIN_SRC fish
   yadm decrypt
   #+END_SRC

** Get a correct keyboard layout
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Get_a_correct_keyboard_layout-77d24b30
   :END:
   I use  mainly the [[https://bepo.fr/wiki/Accueil][bépo]]  layout, a French  keyboard layout inspired  by Dvorak
   layouts,  however I  sometimes need  to switch  back to  the standard  French
   AZERTY or the American  QWERTY layout, so I make it so  the Menu key switches
   for me my layout between these three.  This makes it so my xorg configuration
   of my keyboard looks like this:
   #+BEGIN_SRC fish
     set keyboardconf \
     'Section "InputClass"
             Identifier "system-keyboard"
             MatchIsKeyboard "on"
             Option "XkbLayout" "fr"
             Option "XkbModel" "pc104"
             Option "XkbVariant" "bepo_afnor"
             Option "XkbOptions" "caps:ctrl_modifier"
     EndSection'
   #+END_SRC
   So, let’s set it as our keyboard configuration.
   #+BEGIN_SRC fish
     printf "\n# Set keyboard layout #########################################################\n\n"
     echo $keyboardconf | sudo tee /etc/X11/xorg.conf.d/00-keyboard.conf
   #+END_SRC

** Set our locale
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Set_our_locale-e74d772a
   :END:
   I use two main  locales, the French and US UTF-8 locales, and  I like to keep
   the Japanese locale activated just in case.
   #+BEGIN_SRC fish
     set mylocales "en_US.UTF-8 UTF-8" "fr_FR.UTF-8 UTF-8" "ja_JP.UTF-8 UTF-8"
   #+END_SRC
   Let’s enable these.
   #+BEGIN_SRC fish
     printf "\n# Set locale ##################################################################\n\n"
     for item in $mylocales
         if test (grep -e "#$item" /etc/locale.gen)
             sudo sed -i "/$item/s/^#//g" /etc/locale.gen
         end
     end
   #+END_SRC

   This is my configuration I usually use when it comes to my locale.
   #+BEGIN_SRC fish
     set localeconf "LANG=en_US.UTF-8
     LC_COLLATE=C
     LC_NAME=fr_FR.UTF-8
     LC_NUMERIC=fr_FR.UTF-8
     LC_IDENTIFICATION=fr_FR.UTF-8
     LC_TELEPHONE=fr_FR.UTF-8
     LC_MONETARY=fr_FR.UTF-8
     LC_PAPER=fr_FR.UTF-8
     LC_ADDRESS=fr_FR.UTF-8
     LC_TIME=fr_FR.UTF-8
     LC_MEASUREMENT=fr_FR.UTF-8"
   #+END_SRC
   Let’s set it as our system’s locale.
   #+BEGIN_SRC fish
     echo $localeconf | sudo tee /etc/locale.conf
   #+END_SRC
   Now we can generate our locale!
   #+BEGIN_SRC fish
     printf "\n# Generate locale #############################################################\n\n"
     sudo locale-gen
   #+END_SRC

** Create some folders
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Create_some_folders-bf701387
   :END:
   Let’s create  some folders  we might  need for  mounting our  drives, Android
   devices and CDs.
   #+BEGIN_SRC fish
     printf "\n# Create directories for mounting #############################################\n\n"
     sudo mkdir -p /mnt/{USB,CD,Android}
     sudo chown $USER:(id -g $USER) /mnt/{USB,CD,Android}
   #+END_SRC

   We also need the following folder for our nano backups.
   #+BEGIN_SRC fish
     mkdir -p $HOME/.cache/nano/backups
   #+END_SRC

** Set user’s shell to fish
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Set_user’s_shell_to_fish-1a794be2
   :END:
   First of all, the bootstrap shell will set the user’s shell to fish.
   #+BEGIN_SRC fish
     printf "\n# Set fish as the default shell ###############################################\n\n"
     if not test "$SHELL" = "/usr/bin/fish"
         chsh -s /usr/bin/fish
     end
   #+END_SRC

** Install =yay= if it isn’t already installed
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Install_=yay=_if_it_isn’t_already_installed-1e777b8b
   :END:
   Now we’ll need to be sure =yay=,  our AUR helper, is installed on our system.
   If it is, we  don’t need to to anything. However, if  it isn’t, we’ll install
   it manually.
   #+BEGIN_SRC fish
     if ! test (which yay)
         printf "\n# Installing yay ##############################################################\n\n"
         cd
         mkdir -p ~/fromGIT
         cd ~/fromGIT
         git clone https://aur.archlinux.org/yay.git
         cd yay
         makepkg -si --noconfirm
     else
         printf "\n# yay already installed #######################################################\n\n"
     end
   #+END_SRC

** Install basic packages
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Install_basic_packages-17173316
   :END:
   Let’s set in a custom varible what packages we’ll be needing.
   #+BEGIN_SRC fish
     set PACKAGES \
     acpilight adobe-source-han-sans-jp-fonts arc-gtk-theme asar ascii aspell-en \
     aspell-fr awesome awesome-terminal-fonts awesome-freedesktop-git base-devel \
     bashtop bat biber bitwarden-bin bluez-firmware bluez-utils bookworm bzip2 \
     chicken chromium clisp corrupter-git cppcheck cppreference \
     cppreference-devhelp cpupower discord-canary discount docker docker-compose \
     dockerfile-language-server-bin doxygen emacs emacs-org-mode exa exfat-utils \
     farbfeld fd ffmpegthumbnailer findutils firefox flake8 flat-remix-gtk freeglut \
     fzf gcc-libs gdb gimp gnome-disk-utility gnome-epub-thumbnailer gnu-free-fonts \
     gnuplot go go-tools golangci-lint-bin graphviz htop i3lock-color inetutils \
     isync inter-font javascript-typescript-langserver js-beautify jfsutils jmtpfs \
     lain-git libxft-bgra linux-headers lldb logrotate ly meson minted man-db \
     man-pages mpc mpd mpd-rich-presence-discord-git mpv mupdf-tools nano ncdu \
     ncmpcpp nemo-fileroller nemo-preview neofetch netctl networkmanager \
     networkmanager-openvpn nitrogen nm-connection-editor nodejs-vmd nomacs \
     nordic-theme-git nordvpn-bin noto-fonts-emoji npm ntfs-3g numlockx obs-studio \
     openssh otf-fandol otf-ipafont p7zip pacman-contrib pandoc-bin pass \
     pavucontrol pdfpc picom-ibhagwan-git powerline-fonts prettier \
     pulseaudio-bluetooth python-autoflake python-envtpl-git python-epc \
     python-importmagic python-language-server python-nose python-pip python-ptvsd \
     python-pytest qt5-imageformats qemu r raw-thumbnailer reflector ripgrep rofi \
     rsync rtv ruby-rb-fsevent ruby-sass rustup samba scrot sent shadow siji-git \
     simplescreenrecorder sshfs st-luke-git sxiv texlive-bin texlive-langchinese \
     texlive-langcyrillic texlive-langgreek texlive-langjapanese texlive-langkorean \
     texlive-latexextra texlive-localmanager-git texlive-most tmux tree \
     ttf-arphic-uming ttf-baekmuk ttf-charis-sil ttf-dejavu \
     ttf-google-fonts-opinionated-git ttf-hanazono ttf-joypixels ttf-koruri \
     ttf-liberation ttf-monapo ttf-sazanami ttf-tibetan-machine typescript \
     typescript-language-server-bin unicode-emoji unrar usbutils valgrind \
     vscode-css-languageserver-bin vscode-html-languageserver-bin w3m wget \
     x11-ssh-askpass xclip xdg-user-dirs-gtk xfsprogs xorg-drivers xorg-server \
     xorg-xinit xss-lock xvkbd yaml-language-server-bin yapf zeal
   #+END_SRC

   These are the  minimum I would have  in my own installation. You  can edit it
   however you want. Let’s install those.
   #+BEGIN_SRC fish
     printf "\n# Installing needed packages ##################################################\n\n"
     sudo pacman -Syu
     for pkg in $PACKAGES
         yay -S --needed $pkg
     end
   #+END_SRC

** Tangle configuration files from Org files
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Tangle_configuration_files_from_Org_files-cc524361
   :END:
   Before tangling our  configuration files, we need to  create some directories
   first so our files can be properly tangled. Here’s the list of directories we
   need to create:
   #+NAME: dirs-tangled-files
   | $HOME/.config/awesome       |
   | $HOME/.config/awesome/theme |
   | $HOME/.config/emacs/private |
   | $HOME/.config/fish          |
   | $HOME/.config/gtk-2.0       |
   | $HOME/.config/gtk-3.0       |
   | $HOME/.config/i3            |
   | $HOME/.config/nano          |
   | $HOME/.config/ncmpcpp       |
   | $HOME/.config/neofetch      |
   | $HOME/.config/picom         |
   | $HOME/.config/polybar       |
   | $HOME/.config/yadm          |
   | $HOME/.local/bin            |
   | $HOME/org/capture           |

   #+NAME: gen-dirs-tangle
   #+BEGIN_SRC emacs-lisp :var dirs=dirs-tangled-files
     (mapconcat (lambda (x) (format "mkdir -p %s" (car x)))
                dirs
                "\n")
   #+END_SRC

   Our code to generate such directories looks like this:
   #+BEGIN_SRC fish :noweb yes
     <<gen-dirs-tangle()>>
   #+END_SRC

   The next step is  to tangle all the Org files. Here is the list of files that
   are to be tangled:
   #+NAME: tangled-files
   | filename      |
   |---------------|
   | awesome.org   |
   | bin.org       |
   | fish.org      |
   | i3.org        |
   | index.org     |
   | nano.org      |
   | picom.org     |
   | polybar.org   |
   | rustfmt.org   |
   | spacemacs.org |
   | tmux.org      |

   #+NAME: generate-tangle
   #+BEGIN_SRC emacs-lisp :var files=tangled-files[,0]
     (mapconcat (lambda (x) (concat
                             (format "printf '\\n\\n==== Tangling %s\\n\\n' && \\\n" x)
                             (concat "emacs -q --batch --eval '(require \\'ob-tangle)' \\\n"
                                     "--eval '(setq org-confirm-babel-evaluate nil)' \\\n"
                                     "--eval '(org-babel-do-load-languages \\'org-babel-load-languages \\'((python . t)))' \\\n"
                                     (format "--eval '(org-babel-tangle-file \"~/org/config/%s\")'\n" x))))
                files
                "\n")
   #+END_SRC

   #+RESULTS[5a74a8854c2ed55bea68930073468d18d04bea08]: generate-tangle
   #+begin_example
   printf '\n\n==== Tangling bin.org\n\n' && \
   emacs -q --batch --eval '(require \'ob-tangle)' \
   --eval '(setq org-confirm-babel-evaluate nil)' \
   --eval '(org-babel-do-load-languages \'org-babel-load-languages \'((python . t)))' \
   --eval '(org-babel-tangle-file "~/org/config/bin.org")'

   printf '\n\n==== Tangling fish.org\n\n' && \
   emacs -q --batch --eval '(require \'ob-tangle)' \
   --eval '(setq org-confirm-babel-evaluate nil)' \
   --eval '(org-babel-do-load-languages \'org-babel-load-languages \'((python . t)))' \
   --eval '(org-babel-tangle-file "~/org/config/fish.org")'

   printf '\n\n==== Tangling i3.org\n\n' && \
   emacs -q --batch --eval '(require \'ob-tangle)' \
   --eval '(setq org-confirm-babel-evaluate nil)' \
   --eval '(org-babel-do-load-languages \'org-babel-load-languages \'((python . t)))' \
   --eval '(org-babel-tangle-file "~/org/config/i3.org")'

   printf '\n\n==== Tangling index.org\n\n' && \
   emacs -q --batch --eval '(require \'ob-tangle)' \
   --eval '(setq org-confirm-babel-evaluate nil)' \
   --eval '(org-babel-do-load-languages \'org-babel-load-languages \'((python . t)))' \
   --eval '(org-babel-tangle-file "~/org/config/index.org")'

   printf '\n\n==== Tangling nano.org\n\n' && \
   emacs -q --batch --eval '(require \'ob-tangle)' \
   --eval '(setq org-confirm-babel-evaluate nil)' \
   --eval '(org-babel-do-load-languages \'org-babel-load-languages \'((python . t)))' \
   --eval '(org-babel-tangle-file "~/org/config/nano.org")'

   printf '\n\n==== Tangling polybar.org\n\n' && \
   emacs -q --batch --eval '(require \'ob-tangle)' \
   --eval '(setq org-confirm-babel-evaluate nil)' \
   --eval '(org-babel-do-load-languages \'org-babel-load-languages \'((python . t)))' \
   --eval '(org-babel-tangle-file "~/org/config/polybar.org")'

   printf '\n\n==== Tangling spacemacs.org\n\n' && \
   emacs -q --batch --eval '(require \'ob-tangle)' \
   --eval '(setq org-confirm-babel-evaluate nil)' \
   --eval '(org-babel-do-load-languages \'org-babel-load-languages \'((python . t)))' \
   --eval '(org-babel-tangle-file "~/org/config/spacemacs.org")'

   printf '\n\n==== Tangling tmux.org\n\n' && \
   emacs -q --batch --eval '(require \'ob-tangle)' \
   --eval '(setq org-confirm-babel-evaluate nil)' \
   --eval '(org-babel-do-load-languages \'org-babel-load-languages \'((python . t)))' \
   --eval '(org-babel-tangle-file "~/org/config/tmux.org")'
   #+end_example

   #+BEGIN_SRC fish :noweb yes
     printf "\n# Tangling org files ##########################################################\n\n"
     <<generate-tangle()>>
   #+END_SRC

   Let’s also make  sure the exported files that are  supposed to be executables
   are indeed executables.
   #+BEGIN_SRC fish
     find ~/.local/bin -type f -exec chmod +x {} +
   #+END_SRC

** Setting up Emacs: Installing Spacemacs
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Setting_up_Emacs:_Installing_Spacemacs-0b3d44b2
   :END:
   Now,  the first  thing we  want to  do with  Emacs is  install its  Spacemacs
   distribution.  We’ll clone  its =develop=  branch into  =~/.config/emacs=. We
   need to  do this prior  to our dotfiles’  cloning because of  some submodules
   that are cloned within our =~/.config/emacs=  directory, and git won’t let us
   clone Spacemacs in an already existing  and non-empty directory. To make sure
   it  isn’t  one,  let’s  delete  any  potentially  existing  =~/.config/emacs=
   directory:
   #+BEGIN_SRC fish
     printf "\n# Installing Spacemacs ########################################################\n\n"
     rm -rf ~/.config/emacs
   #+END_SRC
   Now we can clone Spacemacs:
   #+BEGIN_SRC fish
     git clone --single-branch --branch develop https://github.com/syl20bnr/spacemacs ~/.config/emacs
   #+END_SRC
   And we can  restore what might have been deleted  in our =~/.emacs.d/private=
   directory:
   #+BEGIN_SRC fish
     yadm checkout -- ~/.config/emacs/private/
   #+END_SRC

** Set up dotfiles
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Set_up_dotfiles-ab372bd9
   :END:
*** Update our dotfiles’ remotes
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Set_up_dotfiles-Update_our_dotfiles’_remotes-5a0fe6f7
    :END:
    This line in the bootstrap script will  test if the current user is using my
    username. If yes, it’s probably me.
    #+BEGIN_SRC fish
      if ! test (echo "phundrak" | sed -e "s/^.*$USER//I")
    #+END_SRC
    If it is  me installing and using  these dotfiles, I want the  remotes of my
    dotfiles to be set to ssh remotes using my ssh keys.
    #+BEGIN_SRC fish
      printf "\n# Update yadm’s remotes #######################################################\n\n"
      yadm remote set-url origin git@labs.phundrak.com:phundrak/dotfiles.git
      yadm remote add github git@github.com:phundrak/dotfiles.git
    #+END_SRC
    I will also want to decrypt my encrypted files, such as said ssh keys.
    #+BEGIN_SRC fish
      printf "\n# Decrypt encrypted dotfiles ##################################################\n\n"
      yadm decrypt
    #+END_SRC
    Finally, let’s close this =if= statement.
    #+BEGIN_SRC fish
      end
    #+END_SRC

*** Get =envtpl=
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Set_up_dotfiles-Get_=envtpl=-fdf53f64
    :END:
    Before  we set  our  dotfiles  up, let’s  make  sure  =envtpl= is  correctly
    installed. This package will be needed for generating our alt dotfiles.
    #+BEGIN_SRC fish
      printf '\n# Install envtpl ##############################################################\n\n'
      yay -Syu --needed python-envtpl-git
    #+END_SRC

*** Update our submodules
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Set_up_dotfiles-Update_our_submodules-3e921579
    :END:
    Now we  can download  the various  dependencies of our  dotfiles. To  do so,
    let’s run the following command:
    #+BEGIN_SRC fish
      printf "\n# Getting yadm susbmodules ####################################################\n\n"
      yadm submodule update --init --recursive
    #+END_SRC

** Enable some services
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Enable_some_services-3d38d98e
   :END:
   We have  installed some packages  which require  some services to  run. Let’s
   enable them.

*** Systemd-timesyncd
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Enable_some_services-Systemd-timesyncd-d887e45b
    :END:
    This service enables time syncing with the NTP protocol, so I can be sure my
    computer’s time is correct. The service first needs to be enabled:
    #+BEGIN_SRC fish
      printf "\n# Enabling timesync ###########################################################\n\n"
      sudo systemctl enable --now systemd-timesyncd
    #+END_SRC

    Now, let systemd know  I want to use the NTP protocol  to keep my computer’s
    time synced.
    #+BEGIN_SRC fish
      sudo timedatectl set-ntp true
    #+END_SRC

*** Docker
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Enable_some_services-Docker-305e8309
    :END:
    First, let’s activate Docker.
    #+BEGIN_SRC fish
      printf "\n# Enabling and starting Docker ################################################\n\n"
      sudo systemctl enable --now docker
    #+END_SRC

    Now, if we wish  it, we can be added to the =docker=  group so we won’t have
    to type =sudo= each time we call Docker or Docker Compose.
    #+BEGIN_SRC fish
      read --prompt "echo 'Do you wish to be added to the `docker` group? (Y/n): ' " -l adddockergroup
      if test $adddockergroup = 'y' || test $adddockergroup = "Y" || test $adddockergroup = ''
          sudo usermod -aG docker $USER
      end
    #+END_SRC

*** Emacs
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Enable_some_services-Emacs-c7785c21
    :END:
    Emacs will run as a user service,  which means it won’t be launched until we
    log in.
    #+BEGIN_SRC fish
      printf "\n# Enabling Emacs as user service ##############################################\n\n"
      systemctl --user enable --now emacs
    #+END_SRC

*** Mpd
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Enable_some_services-Mpd-f0f5b9b7
    :END:
    Mpd will  also use as a  user service in order  to get rid of  some lines of
    code in my configuration.
    #+BEGIN_SRC fish
      printf "\n# Enabling Mpd as a user service ##############################################\n\n"
      mkdir -p ~/.config/mpd/playlists
      systemctl --user enable --now mpd
    #+END_SRC

*** SSH server
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Enable_some_services-SSH_server-204f5997
    :END:
    Maybe we want to activate an SSH server on our machine. If so, we can enable
    it. Let’s ask the question.
    #+BEGIN_SRC fish
      read --prompt "echo 'Do you want to activate the ssh server? (Y/n): ' " -l sshdserver
      if test $sshdserver = 'y' || test $sshdserver = "Y" || test $sshdserver = ''
          printf "\n# Enabling ssh server #########################################################\n\n"
          sudo systemctl enable --now sshd
      end
    #+END_SRC

*** Ly
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Enable_some_services-Ly-f4b161c0
    :END:
    Ly is a display manager based on ncurses  which I find nice enough for me to
    use (I  generally don’t like using  display managers). Let’s enable  it, and
    let’s disable tty2 while we’re at it (Ly uses it to run X).
    #+BEGIN_SRC fish
      sudo systemctl enable --now ly
      sudo systemctl disable getty@tty2
    #+END_SRC

*** Acpilight
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Enable_some_services-Acpilight-39152794
    :END:
    =acpilight= is our  utility managing the brightness of our  screen. There is
    actually no service to  enable here, but we must ensure the  user is part of
    the =video=  group so  we can  modify the brightness  of our  screen without
    using =sudo=.
    #+BEGIN_SRC fish
      sudo usermod -aG video $USER
    #+END_SRC

*** NordVPN
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Enable_some_services-NordVPN-75c1bd88
    :END:
    Thanks  to the  AUR  package ~nordvpn-bin~,  I no  longer  have to  manually
    maintain my  VPN connections manually  with OpenVPN. However, it  requires a
    service that we should activate:
    #+BEGIN_SRC fish
    sudo systemctl enable --now nordvpnd
    #+END_SRC

** Symlink some system config files
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Symlink_some_system_config_files-1dd95175
   :END:
   We have some files in [[file:ect/][etc/]] that are to be symlinked to =/etc=.
   #+BEGIN_SRC fish
     for f in (find ~/.etc -type f)
         set dest (echo $f | sed -n 's/^.*etc\(.*\)$/\/etc\1/p')
         sudo ln -s $f $dest
     end
   #+END_SRC

   We may also want  to symlink our [[file:.nanorc][nanorc]] to the =/root=  directory for when we
   use =nano= as =sudo=.
   #+BEGIN_SRC fish
     read --prompt "echo 'Symlink .nanorc to root’s .nanorc? (Y/n): ' " -l nanoroot
     if test $nanoroot = 'y' || test $nanoroot = "Y" || test $nanoroot = ''
         printf "\n# Symlinking .nanorc to root’s .nanorc ########################################\n\n"
         sudo ln -s $HOME/.nanorc /root/.nanorc
     end
   #+END_SRC

** Install packages from git
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Install_packages_from_git-7c6a6ea4
   :END:
   Now, let’s install some packages from git directly.
   #+BEGIN_SRC fish
     mkdir -p ~/fromGIT
   #+END_SRC

*** Polybar Battery
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Install_packages_from_git-Polybar_Battery-074a2cf5
    :END:
    Now let’s install =polybar-battery=. This is a binary that I’ll use in my [[file:.config/i3/config][i3
    config]] to  indicate my battery  level. It also  sends a notification  on low
    battery and on charging completed.
    #+BEGIN_SRC fish
      printf "\n# Install polybar-battery #####################################################\n\n"
      cd ~/fromGIT
      git clone https://github.com/drdeimos/polybar_another_battery.git
      cd polybar_another_battery
      go get -u github.com/distatus/battery/cmd/battery
      make build
    #+END_SRC

    Now, we  have our binary,  let’s symlink it  in our local  binary directory,
    =~/.local/bin=.
    #+BEGIN_SRC fish
      cd ~/.local/bin
      ln -s ~/fromGIT/polybar_another_battery/polybar-ab polybar-ab
    #+END_SRC

*** Reveal.JS
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Install_packages_from_git-Reveal.JS-bb4da0bf
    :END:
    I sometimes use  Reveal.JS to make presentations, and I  set its location in
    my [[file:.spacemacs][dotspacemacs]] file to be in =~/fromGIT=, so let’s clone it there.
    #+BEGIN_SRC fish
      printf "\n# Install Reveal.JS ###########################################################\n\n"
      cd ~/fromGIT
      git clone https://github.com/hakimel/reveal.js.git
    #+END_SRC

*** Install powerline fonts
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Install_packages_from_git-Install_powerline_fonts-293f256c
    :END:
    I also need some powerline fonts for my terminal theme.
    #+BEGIN_SRC fish
      printf "\n# Install powerline fonts #####################################################\n\n"
      cd ~/fromGIT
      git clone https://github.com/powerline/fonts.git --depth=1
      cd fonts
      ./install.sh
      fc-cache -vf
    #+END_SRC

** Install Rust
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Install_Rust-1839c4d0
   :END:
*** Install the toolchains
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Install_Rust-Install_the_toolchains-3480764a
    :END:
    When using rust, I bounce between two toolchains, the =stable= toolchain and
    the =nightly=  toolchain. To  install them,  I will  use =rustup=  which has
    already been installed.
    #+BEGIN_SRC fish
      printf "\n# Install the rust toolchains, nightly is the default one #####################\n\n"
      rustup default nightly
    #+END_SRC
    This will both download the nightly toolchain and set it as the default one.
    Yup, I like to live dangerously.  Now to install the stable toolchain, let’s
    run this:
    #+BEGIN_SRC fish
      rustup toolchain install stable
    #+END_SRC

*** Install some utilities
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Install_Rust-Install_some_utilities-c4a7c785
    :END:
    We’ll need some utilities when  developing Rust from Emacs, namely =rustfmt=
    and =racer=. Let’s install them with =cargo=.
    #+BEGIN_SRC fish
      printf "\n# Add rust utilities ##########################################################\n\n"
      cargo install rustfmt racer
    #+END_SRC

    We will also need some components for development purposes:
    #+BEGIN_SRC fish
      rustup component add rust-src
      rustup component add rls
    #+END_SRC

** Install some python packages
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Install_some_python_packages-a4447a6f
   :END:
   Some  packages will  be needed  from  pip in  order  to get  our Emacs  setup
   correctly working. Let’s install them locally for our user:
   #+BEGIN_SRC fish
     printf "\n# Installing Python packages ##################################################\n\n"
     pip install --user pyls-isort pyls-mypy
   #+END_SRC

** Install go packages
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Install_go_packages-fe3e2ff5
   :END:
   For go development from Emacs, the  Spacemacs go and lsp layers requires some
   packages to be installed.
   #+BEGIN_SRC fish
     printf "\n# Installing Go packages ######################################################\n\n"
     go get -v golang.org/x/tools/gopls@latest
     go get -u -v golang.org/x/tools/cmd/godoc
     go get -u -v golang.org/x/tools/cmd/goimports
     go get -u -v golang.org/x/tools/cmd/gorename
     go get -u -v golang.org/x/tools/cmd/guru
     go get -u -v github.com/cweill/gotests/...
     go get -u -v github.com/davidrjenni/reftools/cmd/fillstruct
     go get -u -v github.com/fatih/gomodifytags
     go get -u -v github.com/godoctor/godoctor
     go get -u -v github.com/golangci/golangci-lint/cmd/golangci-lint
     go get -u -v github.com/haya14busa/gopkgs/cmd/gopkgs
     go get -u -v github.com/josharian/impl
     go get -u -v github.com/mdempsky/gocode
     go get -u -v github.com/rogpeppe/godef
     go get -u -v github.com/zmb3/gogetdoc
     go get -u -v golang.org/x/tools/gopls
   #+END_SRC

** Set up Chicken (Scheme interpreter/compiler)
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Set_up_Chicken_(Scheme_interpreter-compiler)-3c1a3c4a
   :END:
   Chicken needs to be  set up before being used. First, we  need to install its
   documentation.
   #+BEGIN_SRC fish
     printf "\n# Setting up Chicken ##########################################################\n\n"
     chicken-install -s apropos chicken-doc
   #+END_SRC

   Then, we’ll complete the documentation like so:
   #+BEGIN_SRC fish
     cd (chicken-csi -b -e "(import (chicken platform))" -p "(chicken-home)")
     curl https://3e8.org/pub/chicken-doc/chicken-doc-repo.tgz | sudo tar zx
   #+END_SRC

** Clean the =pacman= and =yay= cache
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Clean_the_=pacman=_and_=yay=_cache-646cbe36
   :END:
   Finally, we are almost done! Let’s clean the cache of =pacman= and =yay=.
   #+BEGIN_SRC fish
     printf "\n# Clean the pacman and yay cache ##############################################\n\n"
     yay -Sc --noconfirm
   #+END_SRC

** Set up our fish shell
   :PROPERTIES:
   :CUSTOM_ID: Execute_bootstrap-Set_up_our_fish_shell-f0741c22
   :END:
   The last thing we want to do is to set up our fish shell with some extensions
   in order to improve the user experience.

*** Install =fisher=
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Set_up_our_fish_shell-Install_=fisher=-3a44531b
    :END:
    We will be using =fisher= as  our extensions manager for Fish. Let’s install
    it.
    #+BEGIN_SRC fish
      printf "\n# Installing fisher ###########################################################\n\n"
      curl https://git.io/fisher --create-dirs -sLo ~/.config/fish/functions/fisher.fish
    #+END_SRC

*** Install our extensions
    :PROPERTIES:
    :CUSTOM_ID: Execute_bootstrap-Set_up_our_fish_shell-Install_our_extensions-188e4566
    :END:
    I generally use the following extensions in my Fish shell.
    #+NAME: fish-extensions
    #+CAPTION: Fish extensions managed by Fisher
    | Package name              | Description                                                      |
    |---------------------------+------------------------------------------------------------------|
    | fishpkg/fish-prompt-metro | Fast, git-aware, space-conscious, Powerline prompt               |
    | jorgebucaran/fish-bax     | Run bash scripts, replaying environment changes in fish          |
    | franciscolourenco/done    | Automatically receive notifications when a long process finishes |
    | jethrokuan/fzf            | Improved key bindings for [[https://github.com/junegunn/fzf][junegunn/fzf]]                           |
    | jethrokuan/z              | Pure-fish [[https://github.com/rupa/z][rupa/z]]-like directory jumping                          |
    | jorgebucaran/fish-getopts | CLI options parser; alternative to the [[https://fishshell.com/docs/current/commands.html#argparse][argparse]] fish builtin     |
    | laughedelic/pisces        | Autoclose parentheses, braces, quotes and other paired symbols   |
    | acomagu/fish-async-prompt | Make your prompt asynchronous to increase it reactivity          |

    #+NAME: fish-ext-py
    #+BEGIN_SRC emacs-lisp :exports none :tangle no :var extensions=fish-extensions[,0]
      (mapconcat (lambda (x) (format "fisher add %s" x))
                 extensions
                 "\n")
    #+END_SRC

    #+RESULTS[e8afa907b582d6c8c9cb206a5a6be9a3f0f5f657]: fish-ext-py
    : fisher add fishpkg/fish-prompt-metro
    : fisher add jorgebucaran/fish-bax
    : fisher add franciscolourenco/done
    : fisher add jethrokuan/fzf
    : fisher add jethrokuan/z
    : fisher add jorgebucaran/fish-getopts
    : fisher add laughedelic/pisces
    : fisher add acomagu/fish-async-prompt

    #+BEGIN_SRC fish :noweb yes
      printf "\n# Installing Fisher Extensions ################################################\n\n"
      <<fish-ext-py()>>
    #+END_SRC
