Skip to content

echawk/kiss.el

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

kiss.el

This is an implementation of the kiss package manager in Emacs lisp.

Currently is WIP, yet usable for my day-to-day use.

Setup/Configuration

Here’s a minimum viable init.el:

;; We require melpa because my tsort package is currently only available there.
(require 'package)
(setq package-archives '(("melpa" . "https://melpa.org/packages/")
                         ("elpa"  . "https://elpa.gnu.org/packages/")))

(package-initialize)
(unless package-archive-contents
  (package-refresh-contents))

(require 'use-package)
(use-package tsort :ensure t)

;; Now all of the dependencies are installed, we have to point
;; use-package to the directory where we cloned kiss.el

(setq kiss-site-elisp-dir
      "/path/to/cloned/kiss.el/")

(use-package kiss
  :ensure t
  :if (file-exists-p kiss-site-elisp-dir)
  :load-path kiss-site-elisp-dir)

Alternatively, you can use the following use-package declaration if you are using Emacs 30+:

(use-package kiss
  :ensure t
  :if (>= emacs-major-version 30)
  :vc (:url "https://github.com/ehawkvu/kiss.el"
            :rev :newest))

Once that (or the equivalent) has been setup inside of Emacs, you will now be able to use the functions defined in kiss.el.

Features Implemented:

  • [X] alternatives
  • [X] build
  • [X] checksum
  • [X] download
  • [X] fork
  • [X] install^*
  • [X] list
  • [X] preferred
  • [X] remove^*
  • [X] search
  • [X] update
  • [X] upgrade^*
  • [X] version
  • [X] hooks*

NOTE: Some of these features are partially supported.

Feel free to submit issues & PRs!

install, remove, and upgrade are all rather new in their implementations. They shouldn’t send your box to /dev/null, but not promises (yet!).

NOTE: The only three hooks which are not implemented are the pre-source, post-source, and queue-status hooks. This is because in order to support them, there would have to be the addition of some ugly hacks (PRs welcome if you can find a nice elegant way to integrate them), and I’m not entirely convinced of their usefulness…

Extensions

Here is a list of some of the extensions that are implemented in kiss.el that currently have no equivalent alternative in upstream kiss.

Sandboxed Builds

kiss.el supports performing builds within a temporary chroot that is generated on the fly from the currently running system. The correct files and directories are bound in such a way that the build script will still output files in all the usual spots on the host system, so there are no lost logs.

The two supported sandboxing utilities are bubblewrap and proot

Additionally, the actual creation of the chroot is also end-user customizable.

Variables of interest:

  • kiss-make-chroot-strategy
  • kiss-perform-build-in-sandbox
  • kiss-sandbox-utility

Mercurial/Fossil Sources & Repositories

kiss.el supports using mercurial and fossil as valid repositories and sources.

The format for fossil and mercurial sources is identical to that of git sources, except with git+ being replaced with fossil+ and hg+ respectively.

Build Env Hooks

This is an attempt to implement something resembling the old style kiss hooks, which took advantage of the fact that kiss was a shell script which could arbitrarily execute shell commands and set environment variables. As per the issue on codeberg here there is some interest in reviving a similar mechanism.

Instead of setting the kiss-hook variable, you need to set the kiss-build-env-hook variable with a list of all of the hooks that you would like to have set.

**WARNING** I’m not entirely sold on the current idea I have here, and I am liable to change the mechanism in the future. This will especially be the case should upstream change and implement similar functionality, as that mechanism will be preferred.

Docs

Each hook in kiss-build-env-hook will simply take a single argument, that being the package name.

The environment that each of these hooks could be overwritten by a hook that occurs later in the list.

The actual implementation of these hooks is done by simply adding eval $(/path/to/kiss-build-env-hook) to the appropriate part of the helper build script.

Packages via S-Expressions

Below illustrates some example code of how you can create a package entirely through using S-Expressions:

;; NOTE: we need to do all of this stuff w/ the build file, since
;; kiss.el expects it to be executable. This *may* change in the future
;; and be toggleable via a variable.
(let ((build-file (kiss--make-temp-file)))
  (kiss--write-text
   "#!/bin/sh -e
mkdir -p $1/usr/bin
cp -f kiss contrib/* $1/usr/bin/
"
   'utf-8
   build-file)
  (shell-command (concat "chmod +x " build-file))

  (kiss--package-build
   (kiss-package
    :name "kiss-el-test"
    :version "git"
    :release "1"
    :sources
    (list
     (kiss--string-to-source-obj "git+https://github.com/kiss-community/kiss"))
    :build-file build-file))

  (shell-command (concat "rm -v " build-file)))

;; NOTE: A potential *future* iteration may look like this:

(kiss--package-build
 (kiss-package
  :name "kiss-el-test"
  :version "git"
  :release "1"
  :sources
  (list
   (kiss--string-to-source-obj "git+https://github.com/kiss-community/kiss"))
  :build-file
  (string-join
   '("#!/bin/sh -e"
     "mkdir -p $1/usr/bin/"
     "cp -f kiss contrib/* $1/usr/bin/")
   "\n")))

Customization

Overriding functions

Since kiss.el is written in Emacs lisp, there are near infinite ways to customize the behavior of the code. In addition to supporting a great deal of variables, kiss.el also implements additional, “redundant” versions of functions that users can “opt-in” to using Emacs’ advice system. Here is an example showing how to use the “fast” version of kiss–get-potential-binary-files:

(advice-add #'kiss--get-potential-binary-files
            :override #'kiss--get-potential-binary-files-fast)

The boundaries in this area are endless, as with the advice system you can poke into the brain of any function.

Below illustrates how you can effectively “hold” packages from being updated:

;; This is not a perfect version of "hold", as you can still update the
;; package by explicitly building & installing it, but this will prevent
;; the package from showing up to be built by 'kiss-upgrade'.
(setq kiss-hold-pkgs '("emacs" "firefox" "icu"))
(advice-add
 #'kiss--get-out-of-date-pkgs
 :around
 (lambda (orig &rest args)
   "Hold all packages in 'kiss-hold-pkgs'."
   (seq-difference (apply orig args) kiss-hold-pkgs)))

Here is a way you can implement a provides system:

;; Here is an example of a somewhat hacky provides system.
;; This uses an alist for setting which packages are "provided"
;; by another.

;; Here we tell kiss that llvm-fat provides the packages
;; llvm, clang, and lld, and that rustup provides rust.
(setq kiss-provides-alist
      '(("llvm-fat" . ("llvm" "clang" "lld"))
        ("rustup"   . ("rust"))))

(advice-add
 #'kiss--pkg-is-installed-p
 :around
 (lambda (orig &rest args)
   (if (boundp 'kiss-provides-alist)
       (apply
        orig
        (if (member args (flatten-list kiss-provides-alist))
            (car
             (seq-filter
              (lambda (provider)
                (member args (assoc provider kiss-provides-alist)))
              (mapcar #'car kiss-provides-alist)))
          args))
     (apply orig args))))

Or, if you would like to use the typical kiss binary for a particular command (let’s say install), you can write the following:

(advice-add
 #'kiss-install
 :override
 (lambda (pkgs-l)
   (shell-command
    (concat "kiss install "
            (mapconcat #'identity (kiss--get-pkg-order pkgs-l) " ")))))

I highly recommend reading up on Emacs’ advice system if you want to have total control over kiss.el or any other Emacs package for that matter.

M-x info RET elisp - See the section on “Advising Functions”

Here is a good visual resource.

Adding custom compression commands

The kiss-compress-alist can be customized to allow you to use custom compression commands.

Here is an example adding lz4 support & setting it as the default to kiss.el:

(add-to-list kiss-valid-compress "lz4")
(setq kiss-compress "lz4")
(add-to-list kiss-compress-alist '("lz4" . "lz4 -c"))
(add-to-list kiss-decompress-alist `(,(rx "lz4" eol) . "lz4 -dc"))

Long-term Roadmap:

Some of these are far more pie-in-the-sky than others. I think that all of them would be cool to have though.

  • [X] Create a wrapper script that can be used from the command line
  • [X] Write an EIEIO class for packages
  • [X] Integrate said EIEIO class throughout the codebase
  • [X] Allow for packages to be defined via S-Expressions
  • [ ] Write an extensive unit & integration test suite
  • [ ] Get this published on MELPA
  • [ ] Stabilize the API/come to a consensus as to what is useful.
  • [ ] Make a TUI/Menu for installing/upgrading packages
  • [ ] Be able to build GUIX derivations
  • [ ] Port to Common Lisp
  • [ ] Rename to kisp? (once ported to Common Lisp)

About

The kiss package manager written in elisp

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published