* nix-mode User Manual

** Introduction

nix-mode started out as a simple major mode to edit Nix expressions.
It still provides this, but, recently there has been an effort to
provide more than just the .nix major mode. This documentation will
provide some guidance in how to setup and use these new
configurations.

** Installation

*** Installing from MELPA

nix-mode is available from MELPA. You can set up MELPA by modifying
package-archives in your ~/.emacs.d/init.el,

#+BEGIN_SRC emacs-lisp
(require 'package)
(add-to-list 'package-archives
             '("melpa" . "https://melpa.org/packages/") t)
#+END_SRC

Once the above has been executed, you can refresh your package cache
with,

#+BEGIN_SRC text
M-x package-refresh-contents RET
#+END_SRC

Once this is done, you can install nix-mode with,

#+BEGIN_SRC text
M-x package-install RET nix-mode RET
#+END_SRC

*** Installing from Nix

It is also possible to install nix-mode from Nix itself. This requires
some knowledge of how to write a Nix expression. If you would like to
see an example see nix-mode.nix in this Git repo. This file is an
expression that contains a bundled Emacs with nix-mode preinstalled.

*** Installing from Git

You can also setup nix-mode through the Git repo directly. This is
recommended if you are interested in contributing to nix-mode.

#+BEGIN_SRC sh
$ mkdir -p ~/.emacs.d/site-lisp
$ git clone https://github.com/matthewbauer/nix-mode.git ~/.emacs.d/site-lisp/nix-mode
$ cd ~/.emacs.d/site-lisp/nix-mode
#+END_SRC

Then compile the lisp files and generate the manuals,

#+BEGIN_SRC sh
$ make
#+END_SRC

Finally to have Emacs detect your Git version of nix-mode, you add the
following your ~/.emacs.d/init.el configuration,

#+BEGIN_SRC emacs-lisp
(add-to-list 'load-path "~/.emacs.d/site-lisp/nix-mode/")

(with-eval-after-load 'info
  (info-initialize)
  (add-to-list 'Info-directory-list
               "~/.emacs.d/site-lisp/nix-mode/"))
#+END_SRC

** Configuration

Users can install & configure nix-mode through use-package. Here is a
recommended configuration,

#+BEGIN_SRC emacs-lisp
  (use-package nix-mode
    :mode ("\\.nix\\'" "\\.nix.in\\'"))
  (use-package nix-drv-mode
    :ensure nix-mode
    :mode "\\.drv\\'")
  (use-package nix-shell
    :ensure nix-mode
    :commands (nix-shell-unpack nix-shell-configure nix-shell-build))
  (use-package nix-repl
    :ensure nix-mode
    :commands (nix-repl))
#+END_SRC

You can also use the traditional require usage, but use-package
provides many useful helpers for our purposes. In the next sections,
some of the things provided will be explained. This snippet will work
to set up just nix-mode without use-package:

#+BEGIN_SRC emacs-lisp
(require 'nix-mode)
(add-to-list 'auto-mode-alist '("\\.nix\\'" . nix-mode))
#+END_SRC

** Modes

*** nix-mode

This is a major mode for editing Nix expressions. It provides syntax
highlighting, sane defaults, and experimental indentation support.

You can set it up to handle .nix files with,

#+BEGIN_SRC emacs-lisp
  (use-package nix-mode
    :mode ("\\.nix\\'" "\\.nix.in\\'"))
#+END_SRC

To turn on the experimental “electric” style Nix indent, you have to
set the custom variable, nix-indent-function. This can be set by
typing,

#+BEGIN_SRC text
M-x customize-variable RET nix-indent-function RET
#+END_SRC

There are three possible values for nix-mode. They are:

- indent-relative
- smie-indent-line (default)
- nix-indent-line

Starting in version 1.4.0, SMIE is the default and it works very well
(kudos to @j-piecuch on GitHub). You can restore the old behavior by
setting =nix-indent-function= to =indent-relative=.

*** nix-drv-mode

nix-drv-mode is a simple major mode for viewing Nix’s .drv files. If
you have use-package installed, you can set it up to handle .drv files
with this in your configuration file,

#+BEGIN_SRC emacs-lisp
  (use-package nix-drv-mode
    :ensure nix-mode
    :mode "\\.drv\\'")
#+END_SRC

nix-drv-mode works by running “nix show-derivation” and showing you
the prettified .json file produced.

*** nix-repl

nix-repl.el has two purposes. First, it provides an interface for
completion, used by nix-company.el. Second, it provides an interactive
function to open an repl. You can open this with:

#+BEGIN_SRC text
M-x nix-repl<RET>
#+END_SRC

This is the same prompt you would get from running “nix repl” on the
command line. A recommended configuration is provided below,

#+BEGIN_SRC emacs-lisp
  (use-package nix-repl
    :ensure nix-mode
    :commands (nix-repl))
#+END_SRC

*** nix-shell

nix-shell provides a few interactive commands to make it easier to
make calls to nix-shell from Emacs. Recommended configuration is
provided below.

#+BEGIN_SRC emacs-lisp
  (use-package nix-shell
    :ensure nix-mode
    :commands (nix-shell-unpack nix-shell-configure nix-shell-build))
#+END_SRC

First, there are 3 commands that run Nix phases for you.

- nix-shell-unpack
- nix-shell-configure
- nix-shell-build

You can run any one of these to invoke the corresponding Nix phase. For
instance, to unpack the source for Emacs, let’s start from a dired
buffer,

#+BEGIN_SRC text
C-x C-f ~ RET
#+END_SRC

#+BEGIN_SRC text
M-x nix-shell-unpack RET emacs RET
#+END_SRC

This will unpack the Emacs source code. It may take a minute or two to
unpack. After that, we can enter the Emacs directory with find-file,

#+BEGIN_SRC text
C-x C-f emacs-26.1 RET
#+END_SRC

Now that we are in the Emacs directory, we can run the configure
scripts. This is as simple as,

#+BEGIN_SRC text
M-x nix-shell-configure RET <nixpkgs> RET emacs RET
#+END_SRC

This, again, will take a few minutes. After that, though, we can build 

#+BEGIN_SRC text
M-x nix-shell-build RET <nixpkgs> RET emacs RET
#+END_SRC

If you want to avoid entering your Nix files and attributes again and
again, you can set the values automatically through dir-locals.el.
Still in the Emacs directory, run the following two commands,

#+BEGIN_SRC text
M-x add-dir-local-variable RET nil RET nix-file RET "<nixpkgs>" RET
M-x add-dir-local-variable RET nil RET nix-attr RET "emacs" RET
#+END_SRC

*** nix.el

nix.el also provides some basic functions for interfacing with Nix.
Some variables are provided to point to the Nix binaries that can be
used in Lisp code:

- nix-executable
- nix-build-executable
- nix-instantiate-executable
- nix-store-executable
- nix-shell-executable

Other useful functions for Lisp scripts are provided as well:

- nix-system - Get the current system, detected by Nix

*** Miscellaneous

There are a few more Emacs Lisp files provided in nix-mode that have
not been explained here. They are mostly experimental. We always
welcome more contributions from interested developers.

** Customization

** Origins

This repository is based off of the nix-mode.el file originally
located in the [[https://github.com/NixOS/nix][Nix repository]] at [[https://github.com/NixOS/nix/blob/master/misc/emacs/nix-mode.el][misc/emacs/nix-mode.el]].

** Changelog

Please see [[https://github.com/NixOS/nix-mode/blob/master/CHANGELOG.md][the CHANGELOG file]] a list of changes.

** Other Emacs packages

@shlevy has an excellent package for integrating nix-shell into emacs.
It is available at [[https://github.com/shlevy/nix-buffer][shlevy/nix-buffer]].

@travisbhartwell also has some package dealing with Nix. They are
available at [[https://github.com/travisbhartwell/nix-emacs][travisbhartwell/nix-emacs]].
** Contributing

Please submit pull requests at https://github.com/NixOS/nix-mode/pulls
and issues at https://github.com/NixOS/nix-mode/issues. All
contributions are welcome!
