1# Emacs {#sec-emacs}
2
3## Configuring Emacs {#sec-emacs-config}
4
5The Emacs package comes with some extra helpers to make it easier to configure. `emacs.pkgs.withPackages` allows you to manage packages from ELPA. This means that you will not have to install those packages from within Emacs. For instance, if you wanted to use `company`, `counsel`, `flycheck`, `ivy`, `magit`, `projectile`, and `use-package`, you could use this as a `~/.config/nixpkgs/config.nix` override:
6
7```nix
8{
9 packageOverrides =
10 pkgs: with pkgs; {
11 myEmacs = emacs.pkgs.withPackages (
12 epkgs:
13 (with epkgs.melpaStablePackages; [
14 company
15 counsel
16 flycheck
17 ivy
18 magit
19 projectile
20 use-package
21 ])
22 );
23 };
24}
25```
26
27You can install it like any other package via `nix-env -iA myEmacs`. However, this will only install those packages. It will not `configure` them for us. To do this, we need to provide a configuration file. Luckily, it is possible to do this from within Nix! By modifying the above example, we can make Emacs load a custom config file. The key is to create a package that provides a `default.el` file in `/share/emacs/site-start/`. Emacs knows to load this file automatically when it starts.
28
29```nix
30{
31 packageOverrides = pkgs: {
32 myEmacsConfig = pkgs.writeText "default.el" ''
33 (eval-when-compile
34 (require 'use-package))
35
36 ;; load some packages
37
38 (use-package company
39 :bind ("<C-tab>" . company-complete)
40 :diminish company-mode
41 :commands (company-mode global-company-mode)
42 :defer 1
43 :config
44 (global-company-mode))
45
46 (use-package counsel
47 :commands (counsel-descbinds)
48 :bind (([remap execute-extended-command] . counsel-M-x)
49 ("C-x C-f" . counsel-find-file)
50 ("C-c g" . counsel-git)
51 ("C-c j" . counsel-git-grep)
52 ("C-c k" . counsel-ag)
53 ("C-x l" . counsel-locate)
54 ("M-y" . counsel-yank-pop)))
55
56 (use-package flycheck
57 :defer 2
58 :config (global-flycheck-mode))
59
60 (use-package ivy
61 :defer 1
62 :bind (("C-c C-r" . ivy-resume)
63 ("C-x C-b" . ivy-switch-buffer)
64 :map ivy-minibuffer-map
65 ("C-j" . ivy-call))
66 :diminish ivy-mode
67 :commands ivy-mode
68 :config
69 (ivy-mode 1))
70
71 (use-package magit
72 :defer
73 :if (executable-find "git")
74 :bind (("C-x g" . magit-status)
75 ("C-x G" . magit-dispatch-popup))
76 :init
77 (setq magit-completing-read-function 'ivy-completing-read))
78
79 (use-package projectile
80 :commands projectile-mode
81 :bind-keymap ("C-c p" . projectile-command-map)
82 :defer 5
83 :config
84 (projectile-global-mode))
85 '';
86
87 myEmacs = emacs.pkgs.withPackages (
88 epkgs:
89 (with epkgs.melpaStablePackages; [
90 (runCommand "default.el" { } ''
91 mkdir -p $out/share/emacs/site-lisp
92 cp ${myEmacsConfig} $out/share/emacs/site-lisp/default.el
93 '')
94 company
95 counsel
96 flycheck
97 ivy
98 magit
99 projectile
100 use-package
101 ])
102 );
103 };
104}
105```
106
107This provides a fairly full Emacs start file. It will load in addition to the user's personal config. You can always disable it by passing `-q` to the Emacs command.
108
109Sometimes `emacs.pkgs.withPackages` is not enough, as this package set has some priorities imposed on packages (with the lowest priority assigned to GNU-devel ELPA, and the highest for packages manually defined in `pkgs/applications/editors/emacs/elisp-packages/manual-packages`). But you can't control these priorities when some package is installed as a dependency. You can override it on a per-package-basis, providing all the required dependencies manually, but it's tedious and there is always a possibility that an unwanted dependency will sneak in through some other package. To completely override such a package, you can use `overrideScope`.
110
111```nix
112let
113 overrides = self: super: rec {
114 haskell-mode = self.melpaPackages.haskell-mode;
115 # ...
116 };
117in
118((emacsPackagesFor emacs).overrideScope overrides).withPackages (
119 p: with p; [
120 # here both these package will use haskell-mode of our own choice
121 ghc-mod
122 dante
123 ]
124)
125```
126}