Home Explore Blog CI



nix

4th chunk of `doc/manual/source/command-ref/nix-shell.md`
9eeb3976bc78097504d57b69e73bd65226d6c24cf7ded41b0000000100000db2
initialised the environment, and *packages* are the attribute names of
the dependencies in Nixpkgs.

The lines starting with `#! nix-shell` specify `nix-shell` options (see
above). Note that you cannot write `#! /usr/bin/env nix-shell -i ...`
because many operating systems only allow one argument in `#!` lines.

For example, here is a Python script that depends on Python and the
`prettytable` package:

```python
#! /usr/bin/env nix-shell
#! nix-shell -i python3 --packages python3 python3Packages.prettytable

import prettytable

# Print a simple table.
t = prettytable.PrettyTable(["N", "N^2"])
for n in range(1, 10): t.add_row([n, n * n])
print(t)
```

Similarly, the following is a Perl script that specifies that it
requires Perl and the `HTML::TokeParser::Simple`, `LWP` and
`LWP::Protocol::Https` packages:

```perl
#! /usr/bin/env nix-shell
#! nix-shell -i perl 
#! nix-shell --packages perl 
#! nix-shell --packages perlPackages.HTMLTokeParserSimple 
#! nix-shell --packages perlPackages.LWP
#! nix-shell --packages perlPackages.LWPProtocolHttps

use HTML::TokeParser::Simple;

# Fetch nixos.org and print all hrefs.
my $p = HTML::TokeParser::Simple->new(url => 'https://nixos.org/');

while (my $token = $p->get_tag("a")) {
    my $href = $token->get_attr("href");
    print "$href\n" if $href;
}
```

Sometimes you need to pass a simple Nix expression to customize a
package like Terraform:

```bash
#! /usr/bin/env nix-shell
#! nix-shell -i bash --packages 'terraform.withPlugins (plugins: [ plugins.openstack ])'

terraform apply
```

> **Note**
>
> You must use single or double quotes (`'`, `"`) when passing a simple Nix expression
> in a nix-shell shebang.

Finally, using the merging of multiple nix-shell shebangs the following
Haskell script uses a specific branch of Nixpkgs/NixOS (the 20.03 stable
branch):

```haskell
#! /usr/bin/env nix-shell
#! nix-shell -i runghc --packages 'haskellPackages.ghcWithPackages (ps: [ps.download-curl ps.tagsoup])'
#! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/nixos-20.03.tar.gz

import Network.Curl.Download
import Text.HTML.TagSoup
import Data.Either
import Data.ByteString.Char8 (unpack)

-- Fetch nixos.org and print all hrefs.
main = do
  resp <- openURI "https://nixos.org/"
  let tags = filter (isTagOpenName "a") $ parseTags $ unpack $ fromRight undefined resp
  let tags' = map (fromAttrib "href") tags
  mapM_ putStrLn $ filter (/= "") tags'
```

If you want to be even more precise, you can specify a specific revision
of Nixpkgs:

    #! nix-shell -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/0672315759b3e15e2121365f067c1c8c56bb4722.tar.gz

The examples above all used `-p` to get dependencies from Nixpkgs. You
can also use a Nix expression to build your own dependencies. For
example, the Python example could have been written as:

```python
#! /usr/bin/env nix-shell
#! nix-shell deps.nix -i python
```

where the file `deps.nix` in the same directory as the `#!`-script
contains:

```nix
with import <nixpkgs> {};

runCommand "dummy" { buildInputs = [ python3 python3Packages.prettytable ]; } ""
```

The script's file name is passed as the first argument to the interpreter specified by the `-i` flag.

Aside from the very first line, which is a directive to the operating system, the additional `#! nix-shell` lines do not need to be at the beginning of the file.
This allows wrapping them in block comments for languages where `#` does not start a comment, such as ECMAScript, Erlang, PHP, or Ruby.

Title: Examples of Using nix-shell as a Script Interpreter with Python, Perl, Terraform, and Haskell
Summary
This section provides detailed examples of using `nix-shell` as a script interpreter for various languages like Python, Perl, Terraform, and Haskell. It demonstrates how to specify dependencies using `#! nix-shell` directives, including package names and specific Nix expressions. The examples cover fetching packages from Nixpkgs, customizing packages, using specific Nixpkgs revisions, and using a `deps.nix` file to define dependencies. It also explains that `#! nix-shell` directives can be placed within block comments for languages where '#' is not a comment character.