Getting started

Nickel is still young and the installation process is not yet optimal. Sorry about that! We are focused on improving the experience, so stay tuned.

Build from source using Nix

Using Nix is the easiest way to get a Nickel executable running.

  1. Clone the Nickel repository and set it as the current directory:

    git clone git@github.com:tweag/nickel.git
    Cloning in 'nickel'...
    [..]
    cd nickel
  2. Invoke nix-build:

    nix-build
    [1 built, 0.0 MiB DL]
  3. If everything went right, a binary is now available in the result directory:

    ./result/bin/nickel -V
    nickel 0.1.0

Build from source without Nix

Please refer to the README of the Nickel repository for alternative ways of building Nickel.

Write your first configuration

Nickel has advanced features to help you handle and organize complex configurations (gradual typing, contracts, a merge system, and so on). But you'll only have to deal with any of this once you need to. Writing a basic configuration is as simple as writing JSON or YAML. Let us write a manifest of a fictional app:

{
  name = "example",
  description = m#"
    This is an awesome software I'm developing.
    Please use it!
  "#m,
  version = "0.1.1",
  main = "index.js",
  keywords = ["example", "config"],
  scripts = {
    test = m#"test.sh --option --install example --version "0.1.1""#m,
    do_stuff = "do_stuff.sh subcommand",
  },
  contributors = [{
      name = "John Doe",
      email = "johndoe@example.com"
    }, {
      name = "Ivy Lane",
      url = "https://example.com/ivylane"
    }],
  dependencies = {
    dep1 = "^1.0.0",
    dep3 = "6.7"
  }
}

This program is composed of record. A record is the same thing as an object in JSON. It is a list of key-value pairs delimited by { and }. In general, the values of Nickel map directly to corresponding values in JSON (excluding functions). Thus, the basic datatypes of Nickel are the same as in JSON:
  • Records (objects), delimited by { and }.
  • Strings, delimited by ". The sequence m#" and "#m delimits multiline strings.
  • Numbers
  • Lists, delimited by [ and ] and separated by ,.

Multiline strings are an alternative way of defining strings. Line 11 is an example of such a string. Without diving into the details, multiline strings are useful for:
  • Write strings spanning several lines, as their name suggests. Multiline strings can be indented at the same level as the surrounding code while still producing the expected result (the common indentation prefix is stripped).
  • Write strings with special characters without having to escape them.
In our example, using a multiline string saves us from escaping the recurring double quotes ".

Export

The ultimate goal of a Nickel program is to produce a static configuration. To do so, save the content of our example above in example.ncl and run nickel export:

./result/bin/nickel -f example.ncl export --format yaml
---
contributors:
  - email: johndoe@example.com
    name: John Doe
  - name: Ivy Lane
    url: https://example.com/ivylane
dependencies:
  dep1: ^1.0.0
  dep3: "6.7"
description: "This is an awesome software I'm developing.\nPlease use it!"
keywords:
  - example
  - config
main: index.js
name: example
scripts:
  do_stuff: do_stuff.sh subcommand
  test: "test.sh --option --install example --version \"0.1.1\""
version: 0.1.1

Nickel currently supports exporting to and importing from YAML, TOML and JSON.

Reuse

Nickel is a programming language. This allows you not only to describe, but to generate data. There's repetition in our previous example:

name = "example",
version = "0.1.1",
scripts = {
  test = m#"test.sh --option --install example --version "0.1.1""#m,

The version 0.1.1 appears both in version and scripts.test. The name example appears both in name and scripts.test as well. Pure aesthetics aside, a more serious issue is inconsistency. If you bump the version number in version, you may forget to do so in the scripts.test as well, ending up wih incoherent version numbers in the same configuration. To remedy the problem, let's have a single source of truth by reusing the value of name and version in scripts.test, using the string interpolation syntax #{expr}:

name = "example",
version = "0.1.1",
scripts = {
  test = m#"test.sh --option --install #{name} --version "#{version}""#m

Now, if we change version to 0.1.2 and export the result, the test script invocation is updated as well:

# [...]
scripts:
  do_stuff: do_stuff.sh subcommand
  test: "test.sh --option --install example --version \"0.1.2\""
  version: 0.1.2

Going further

This short introduction should get you started. Nickel is a full-fledged programming language, featuring higher-order functions, gradual typing, contracts, and more! Additional resources are to come on this website. In the meantime, you can find examples in the repository. You will also find more details on the language and its design in the README and in the design rationale.