guix-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Draft new Guix Cookbook section on Emacs


From: Mekeor Melire
Subject: Draft new Guix Cookbook section on Emacs
Date: Sun, 04 Jun 2023 23:32:44 +0000

Hello :)

I'd like to contribute to the Guix Cookbook.

The Cookbook is written in Texinfo format but as I'm not fluent in it, I decided I'd first draft my contribution in Org-Mode which I'd later export as Texinfo and adapt appropriately. I'm sorry that this also means that the hereby submitted draft does not come as a Git patch for now.

Find below a first draft of a new chapter entitled "Emacs", including two subchapters, "Beginners Guide to the Perfect Setup" and "Mu4e".

Regarding the Perfect Setup, I'm convinced that it makes sense to have a more beginner-friendly tutorial supplementing the instructions which are already present in the Guix manual. It's meant to have more background information and more, non-essential configuration tips, as well as details on usage, including keybindings.

Regarding emails, in the long-term, I'd also like to contribute a new chapter on how to use the mailing-lists, elaborating on how to get local maildir copies of the mailing-lists with tools like isync/mbsync or public-inbox etc. But that's for the future!

I'm looking forward to your feedback.

Kindly
Mekeor

* Emacs

** Beginners Guide to the Perfect Setup

# Why this tutorial?

The GNU Guix manual includes contains a chapter on "The Perfect Setup" of Emacs 
for hacking on Guix. It is the primary and main resource on this topic. In 
contrast, this tutorial is just a supplement, dedicated towards beginners as it 
offers more background information, details on usage as well as non-essential, 
optional configuration.

# What is Emacs and why is it well suited for Guix?

GNU Emacs is a text editor and, at its core, an interpreter of its own Lisp 
dialect, Emacs-Lisp. It's well suited for hacking on Guix (and Guix-related) 
code because of its advanced Lisp editing features and since as part of the GNU 
project, it's free software, just like GNU Guix.

# Do you have to use Emacs for hacking on Guix?

Using Emacs is not a precondition for hacking on Guix(-related) code. For 
example, there's at least one Guix maintainer who rather uses Vim. But if 
you're interested in Emacs or already using it, keep on reading.

# Installation

To install Emacs into your Guix user profile, run:

#+begin_src sh
guix install emacs
#+end_src

*** Geiser

# What is Geiser?

Geiser is a package for GNU Emacs that helps with editing code written in the 
Scheme programming language. In particular, it supports the GNU Guile Scheme 
interpreter on which GNU Guix is heavily based.

# Why Geiser?

Using Geiser is recommended not only because it enhances your Scheme editing 
experience with features like automatic documentation, but also it works with 
the ~guix-devel-mode~ described later on.

# Installation

To install Geiser into your Guix user profile, run:

#+begin_src sh
guix install emacs-geiser emacs-geiser-guile
#+end_src

Afterwards, (re)start Emacs in order to make sure that Geiser finds its way 
into Emacs' ~load-path~.

**** Load Geiser

To load Geiser by default add this to your Emacs initialization file:

#+begin_src elisp
(require 'geiser)
#+end_src

Note that this not only loads Geiser but – through Geiser's autoloads – also 
hooks Geiser minor-mode onto ~scheme-mode~. I.e. Geiser will start when you 
open any Scheme file.

**** Geiser Guile Load Path

If you maintain a local clone of the Guix source code repository, it already 
contains a =.dir-locals.el= file which ensures that the path of your local 
clone is added to ~geiser-guile-load-path~ whenever you open a Scheme file in 
there. But nevertheless, it makes sense to add the path to your local Guix 
repository to ~geiser-guile-load-path~ in your Emacs initialization file so 
that it's set correctly in other directories as well.

Make sure that the compiled files in your local Guix repository are up-to-date. 
I.e. whenever your local working directory of the repository changes (for 
example, after running ~git pull~), rebuild Guix as described in the Guix 
manual. Otherwise, Guile would auto-compile all Guix sources which leads to 
misconfiguration[fn:1] and likely hits Geiser's timeout. Consider having two 
Git worktree of the Guix repository, keeping one always compiled.

If you have other Guix-related source code directories on your machine (and you 
want to load Guile modules from there), you need to put those in the 
~geiser-guile-load-path~ variable. (Geiser will then add those paths to Guile's 
~%load-path~ and ~%load-compiled-path~ variables.)

#+begin_src elisp
(setq geiser-guile-load-path
  (list
    "~/src/guix"
    "~/src/some/channel"))
#+end_src

**** REPL Configuration

You may find handy to make Geiser automatically start a REPL 
(read-eval-print-loop) in the background when a Scheme file is opened:

#+begin_src elisp
(setq geiser-mode-start-repl-p t)
#+end_src

If you want to speed up Geiser, let it open a single REPL per project (instead 
of per file) and forgo version compatibility checks:

#+begin_src elisp
(setq geiser-repl-per-project-p t)
(setq geiser-repl-skip-version-check-p nil)
#+end_src

**** Using Multiple Schemes

If you not only have =emacs-geiser-guile= installed, but also Geiser backends 
for other Scheme implementations, adjust the ~geiser-implementations-alist~ 
variable. For example:

#+begin_src elisp
(setq geiser-implementations-alist
  '(
     ((regexp "/minlog/") chez)
     ((regexp "\\.scm$") guile)))
#+end_src

*** Emacs-Guix

=emacs-guix= is a package for interacting with Guix through Emacs. It has been 
originally developed by Alex Kost and is now maintained within the Guix 
project. It not only offers an interactive interface to Guix features, but also 
ships some modes for viewing and editing Guix-related files, which are covered 
in the following.

To install Emacs-Guix into your Guix user profile, run:

#+begin_src sh
guix install emacs-guix
#+end_src

**** Guix Development Mode

=guix-devel-mode= offers Guix-specific syntax highlighting, linting and 
loading, by utilizing Geiser. To enable it in all Scheme buffers, put this in 
your Emacs initialization file:

#+begin_src elisp
(require 'guix-devel)
(require 'scheme)

(add-hook 'scheme-mode-hook #'guix-devel-mode)
#+end_src

But if you occasionally open Scheme files in Emacs that are unrelated to Guix, 
you might instead enable ~guix-devel-mode~ conditionally, for example like this:

#+begin_src elisp
(require 'guix-devel)
(require 'scheme)

(defun maybe-turn-on-guix-devel-mode ()
  (when
    (string-match-p "guix" (buffer-file-name))
    (guix-devel-mode)))

(add-hook 'scheme-mode-hook #'maybe-turn-on-guix-devel-mode)
#+end_src

**** Other Modes

Emacs-Guix ships with a many more mode that are useful when hacking on Guix, 
including ~guix-build-log-mode~, ~guix-derivation-mode~ and 
~guix-prettify-mode~. Check out Emacs-Guix' Info manual for more information.

# TODO: perhaps add more usage instructions about these modes here.

*** Snippets

There are many Emacs packages for managing and inserting code snippets. The 
Guix repository includes snippets for two of them: Tempel and Yasnippet. Both 
are distributed through the GNU ELPA (Emacs Lisp Package Archive).

Pick and use just one of them. There's no advantage of setting up both snippet 
packages since the Guix repository offers almost equal snippets for them. (As 
of writing, there are slightly more snippets for Tempel.) Generally speaking, 
the biggest difference between them is that Tempel uses ~lisp-data-mode~ to 
define snippets while Yasnippet uses a its own format that embeds Emacs-Lisp 
into plain text.

For both packages, the list of available snippets depends on the current major 
mode. The Guix source code repository offers snippets for ~scheme-mode~ and for 
editing Git commit messages.

**** Tempel

To install Tempel into your Guix user profile, run:

#+begin_src sh
guix install emacs-tempel
#+end_src

In your Emacs initialization file, load the =tempel= feature and add the path 
to Guix' proper Tempel snippets to the ~tempel-path~ variable.

#+begin_src elisp
(require 'tempel)
;; ensure that tempel-path is a list because it may also be a string:
(setq tempel-path (ensure-list tempel-path))
(add-to-list 'tempel-path "~/src/guix/etc/snippets/tempel/*"))
#+end_src

There are many further configuration options described by Tempel itself. (Type 
=C-x P tempel RET= (~describe-package~) to read them in Emacs.)

The most important commands are ~tempel-complete~ (for completing possibly 
incomplete input at point), ~tempel-expand~ (for completing exactly matching 
input at point), ~tempel-insert~ (for inserting a snippet chosen in 
minibuffer). For example, in a Scheme buffer, type =pack= and call =M-x 
tempel-complete RET=. This will replace =pack= with a snippet for package 
definition. This snippet is interactive. It has some logic implemented in it. 
E.g. when you specify ~git-fetch~ as method for fetching the packages source 
code, Tempel automatically adapts the ~uri~ field to a S-expression around 
~git-reference~. By default, you can move point to previous or next snippet 
field with =M-UP= and =M-DOWN= keys (~tempel-previous~ and ~tempel-next~) 
respectively.

**** Yasnippet

To install Yasnippet into your Guix user profile, run:

#+begin_src sh
guix install emacs-yasnippet
#+end_src

In your Emacs initialization file, load the =yasnippet= feature; make sure the 
respective snippets directory from your local Guix repository is member of the 
~yas-snippet-dirs~ variable; and somehow turn on Yasnippet mode, e.g. globally. 
Here's an example:

#+begin_src elisp
(require 'yasnippet)
(add-to-list 'yas-snippet-dirs "~/src/guix/etc/snippets/yas")
(yas-global-mode 1)
#+end_src

To choose and insert a snippet, type =C-c & C-s=, bound to ~yas-insert-snippet~.

Snippets have a short "key". When there's a valid Yasnippet key before point, 
pressing =TAB= (~yas-expand~) will expand it to the full snippet. E.g. when 
editing a Git commit message, you can type =a d d TAB= to insert a snippet that 
describes the addition of a new package according to Guix' commit conventions.

If you use completion frameworks like Consult.el, Helm or Ivy, search the web 
for packages that integrate Yasnippet into it.

*** Usage

Let's assume you opened a Guix-related Scheme file in Emacs and ~scheme-mode~, 
~geiser-mode~ and ~guix-devel-mode~ are turned on. Let's further assume 
~geiser-autodoc-mode~ has been enabled, as Geiser does by default.

To load the Guile module, that is defined by the current file, into the 
Geiser's Guile REPL, type =C-c . u= which runs ~guix-devel-use-module~.

Similarly, when editing a package definition, =C-c . l= will lint current 
package definition at point using =guix lint=. Thus, it will also run some 
security checks and make sure the package builds etc.

Now, move the point to Guix-related identifiers and Geiser Autodoc Mode will 
echo helpful information. For more detailed information on the symbol at point, 
type =C-c C-d d= (or =C-c C-d C-d=), bound to ~geiser-doc-symbol-at-point~.

To view a full list of keybindings, e.g. for linting, type =C-h b=.

** Mu4e

Mu is a tool for dealing with maildirs. Mu4e is integrates Mu into Emacs as 
mail reader. To install Mu and Mu4e into your Guix user profile, run:

#+begin_src sh
guix install mu
#+end_src

Mu4e includes an /action/ to apply a Git patch that is attached to the email 
that you are viewing. The action is not enabled by default. In order to enable 
it, put the following in your Emacs initialization file:

#+begin_src elisp
(add-to-list 'mu4e-view-actions
  '("apply git patch" . mu4e-action-git-apply-mbox))
#+end_src

Now, you can apply the patch by typing =a a=.

* Footnotes

[fn:1] Guile might compile the Scheme code into its own cache instead of 
putting the resulting =.go= files next to their sources. You might then remove 
the ~/.cache/guile~ directory.

reply via email to

[Prev in Thread] Current Thread [Next in Thread]