Pie is a very simple Package Installer for Emacs. It has less features than Elpaca, Straight etc.
I used to use package.el
(and elpa/melpa etc.), but it has some drawbacks IMO, including:
- A single repository may be split into several packages. Some people like it, but not including me.
- It does not support optional dependencies. When I say optional dependency, I mean, for example, package A depends on B or C to get nearly identical functionality, but you don’t need them at the same time. But when using package + (m)elpa, you need to install both B and C. Some packages on melpa have this kind of problem, but I forget their names. But I must admit it’s a little unfair to compare package.el and pie in this way, because when using pie, you write recipes yourself, but when using package.el, you cannot control how a recipe of a package is written.
I’ve only tested/used it with Emacs 28.2 on Linux, maybe there are some problems on Windows and/or Mac.
Pie supports the following features:
- Support cloning a repository or downloading files (e.g. from emacswiki) directly.
- Support cloning a particular branch/tag/commit
- Support git’s shadow clone
- Support customized building logic
- Support specifying dependencies according to your actual needs
- Support generating autoloads files and loading it
Clone this repository to some directory and add it to load-path.
Here are some examples.
(require 'pie)
(setq pie-repos-directory "/path/to/repos/directory")
(setq pie-builds-directory "/path/to/builds/directory")
(pie "s"
"https://github.com/magnars/s.el"
:branch "1.13.0")
(pie "bash-completion"
"https://github.com/szermatt/emacs-bash-completion"
:rev "de2c844")
(pie "magit"
"https://github.com/magit/magit"
:lisp-dir "lisp"
:deps '("compat" "dash" "with-editor"))
(pie "lspce"
"https://bitbucket.org/zbelial/lspce"
:deps '("markdown-mode" "yasnippet")
:build #'(lambda (pp)
(let* ((name (pie-package-package pp))
(lisp-dir (pie-package-lisp-dir pp))
(default-directory lisp-dir)
(files (directory-files lisp-dir t "\\.el$"))
(autoloads (concat (file-name-nondirectory (directory-file-name lisp-dir)) "-autoloads.el")))
(shell-command "cargo clean && cargo build --release && ln -s target/release/liblspce_module.so lspce-module.so")
(cl-dolist (file files)
(when (not (string-suffix-p ".dir-locals.el" file))
(byte-compile-file file)))
(make-directory-autoloads lisp-dir autoloads))))
;; then you can call `pie-install-packages' to install all packages, or
;; use pie-use-package to install and config packages
;; pie-use-package mimics use-package, but has less features. Here is an example
(pie-use-package yafolding
:pie t ;; or use :pie yafolding
:when (eq system-type windows-nt)
:autoloads (yafolding-toggle-element-dwim)
:demand t
:init (progn
;; nothing
)
:config (progn
(add-hook 'prog-mode-hook #'yafolding-mode)
)
)
Symbol, optional.
Which BACKEND to clone. Should be 'http
or a VC backend in vc-handled-backends
.
If not specified, use pie-vc-heuristic-alist
to determine the value, (or pie-vc-default-backend
if no backend can be determined).
String, optional.
Which BRANCH or tag to check out.
String, optional.
Which REV to clone. Has higher priority than branch
.
t or a positve nubmer, optional.
Only works with git for now. If specified, the value should be t (all history), or a positive integer. If omitted, use pie-git-depth
.
Function, optional.
Specify how to build the package. If not specified, use pie-default-build
.
There are three different build functions built-in pie, pie-empty-build
, pie-autoloads-build
and pie-default-build
.
List of string or a function returning a list of string. Optional.
String, optional.
Subdirectory containing elisp files inside the repository.
If it’s 'repo
, then build the package in the repos directory, aka pie-repos-directory/<pkg>
.
Else, build it in the builds directory, aka pie-builds-directory/<pkg>
.
A function without any parameter, optional.
Only when it (if specified) returns t, this package will be installed.
disabled when pie load-path init config autoloads after demand
If you use/have used use-package, all but `pie` and `autoloads` will be familiar for you.
The value of this keyword can be t or a symbol. See the example above. If this keyword is present, pie-use-package will call `pie–install-package-by-name` to install this package.
Similiar to use-package’s commands.
Heuristic mapping URL regular expressions to VC backends.
Default: ‘Git.
Default VC backend used when cloning a package repository. If no repository type was specified or could be guessed by pie-vc-heuristic-alist
, this is the default VC backend used as fallback. The value must be a member of vc-handled-backends
and the named backend must implement the clone
function.
Default: 1.
Default depth used with git backend.
If no depth is specified explicitly, this value will be used.
Default: t.
Whether activite packages after installing them.
Default: ~/.emacs.d/pie/repos.
The directory used to store packages’ repos.
Default: ~/.emacs.d/pie/builds.
The directory used to store built packages.
Let’s use a package called A
to explain how pie works.
- It will clone the repository of
A
to a directoryrepos/A
- Then It will copy the repository directory into
builds/A
directory - Use the default/specified building function to build
A
, and generate a autoload file namedA-autoloads.el
Building happens in the directorybuilds/A
- Add
builds/A
toload-path
and load theA-autoloads
file. Actually, for some packages, the directory added toload-path
is what is specifed by :lisp-dir (see magit example above)
When I started this project, I was using Emacs 29.0.51.
Then I switched back to Emacs 28.2, leaving a function vc-clone
, which appeared first in Emacs 29, in the code. And pie will check its existence before using it.
I mean, pie should work well in older versions of Emacs, but if you use Emacs older than 29.0.50, pie only supports Git and Http.
GPLv3