#+title: Emacs — Package Manager
#+setupfile: ../headers
#+property: header-args:emacs-lisp  :mkdirp yes :lexical t :exports code
#+property: header-args:emacs-lisp+ :tangle ~/.config/emacs/lisp/package-manager.el
#+property: header-args:emacs-lisp+ :mkdirp yes :noweb no-export

* Package Manager
** Repositories
By default, only GNU’s repositories are available to the package
managers of Emacs. I also want to use Melpa and org-mode’s repository,
so let’s add them! Note that the stock /elpa/ repository is renamed to
/gnu/ due to the addition of another Elpa repository, /nongnu/, which will
hosts packages that do not conform to the FSF’s copyright assignment.
Both the /gnu/ and the /nonfree/ repositories are Elpa repositories now,
and they are renamed here in order to avoid any confusion between the
two of them. Melpa is a community-maintained repository which contains
an absurd amount of Emacs packages.
#+begin_src emacs-lisp
(setq package-archives '(("melpa"  . "https://melpa.org/packages/")
                         ("gnu"    . "https://elpa.gnu.org/packages/")
                         ("nongnu" . "https://elpa.nongnu.org/nongnu/")))
#+end_src

** Straight
For my package management, I prefer to use ~straight~ ([[https://github.com/raxod502/straight.el][GitHub]]). This is
due to its capacity of integrating nicely with ~use-package~, which also
supports ~general~ which I use for my keybindings (see below), but also
because with it, I can specify where to retrieve packages that are not
on MELPA or ELPA but on GitHub and other online Git repositories too.
First, let’s bootstrap straight.
#+begin_src emacs-lisp
(defvar bootstrap-version)
(defvar comp-deferred-compilation-deny-list ()) ; workaround, otherwise straight shits itself
(let ((bootstrap-file
       (expand-file-name "straight/repos/straight.el/bootstrap.el" user-emacs-directory))
      (bootstrap-version 5))
  (unless (file-exists-p bootstrap-file)
    (with-current-buffer
        (url-retrieve-synchronously
         "https://raw.githubusercontent.com/raxod502/straight.el/develop/install.el"
         'silent 'inhibit-cookies)
      (goto-char (point-max))
      (eval-print-last-sexp)))
  (load bootstrap-file nil 'nomessage))
#+end_src

Now, we can refresh our package list in order to be able to install
stuff.
#+begin_src emacs-lisp
(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))
#+end_src

From time to time, I fork some packages either because I’m trying to
implement something new in said package, or because the package is
unmaintained, and I want to continue developing it a bit more. Straight
provides a nice feature for using forks of a package with its ~:fork~
option. If set to ~t~, then straight will attempt to retrieve the
package with the same name but with a different username on the same
host. This username is retrieved through the following variable:
#+begin_src emacs-lisp
(setq straight-host-usernames
      '((github . "Phundrak")
        (gitlab . "Phundrak")))
#+end_src

The huge advantage of straight is it clones through git the packages
it installs. This means development can be done directly on the
downloaded package. However, Forge (a Magit extension for interacting
with websites such as GitHub, GitLab, and such) interacts by default
with the forge described by the =origin= remote, which isn’t necessarily
the one I want Forge to interact with by default. Therefore,
=straight.el= will name all default remotes =straight= to avoid any name
collision with my regular development flow.
#+begin_src emacs-lisp
(setq straight-vc-git-default-remote-name "straight")
#+end_src

We finally come to the ~use-package~ installation. This is done like so:
#+begin_src emacs-lisp
(straight-use-package '(use-package :build t))
(setq use-package-always-ensure t)
#+end_src
