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.
We give three alternative ways of obtaining a running Nickel executable:If you have neither of these tools, Nix is the preferred way. If you don't have Nix but you are a user of Cargo or Docker, you may prefer the corresponding installation method.Get a Nickel binary using Nix
Run
With a recent version of Nix (> 2.4.0), you can build and run Nickel in one shot. If you haven't installed Nix yet, please follow this installation guide. Once Nix is installed, use nix run
to start Nickel and append -- args
to pass arguments to the Nickel executable (here we launch an REPL session)
nix run --experimental-features "flakes nix-command" github:tweag/nickel/stable -- repl
nickel>
Install
If you are planning to try Nickel a bit more extensively, you can install the Nickel binary using nix profile
:
nix profile install github:tweag/nickel/stable
nickel repl
nickel>
Get a Nickel binary using Cargo
If you are a Rust developer, the Cargo build tool is an alternative way to install a Nickel binary:
cargo install nickel-lang-cli
nickel repl
nickel>
Install with Homebrew
If you're running macOS you can use Homebrew to install the Nickel binary.
brew install nickel
nickel repl
nickel>
Get a Docker image
A last alternative is to use Docker image:
docker run --rm -it ghcr.io/tweag/nickel:1.4.0 repl
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's write a manifest of a fictional app:
{
name = "example",
description = m%"
This is an awesome software I'm developing.
Please use it!
"%,
version = "0.1.1",
main = "index.js",
keywords = ["example", "config"],
scripts = {
test = m%"
test.sh --option --install example --version "0.1.1"
"%,
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"
}
}
{
and }
. In general, Nickel values map directly to 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 sequencesm%"
and"%
delimit multiline strings. - Numbers.
- Arrays, delimited by
[
and]
and separated by,
.
- Writing 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.
- Writing strings with special characters without having to escape them.
"
.Export & Import
The ultimate goal of a Nickel program is to produce a static configuration. To do so, save the example above to example.ncl
and run nickel export
:
nickel export example.ncl --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 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. Importing an existing configuration into a Nickel one is as easy as writing import "something.yaml"
. For example, if our contributor data is already stored in a YAML file contributors.yaml
and we want to gradually migrate the manifest to Nickel, we could import contributors.yaml
as a first step:
{
# [...]
scripts = {
test = m%"
test.sh --option --install example --version "0.1.1"
"%,
do_stuff = "do_stuff.sh subcommand",
},
contributors = import "contributors.yaml",
# [...]
}
Reuse
Nickel is a programming language. This allows you to not only describe, but 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"
"%,
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 with 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}"
"%,
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! To explore further, read the user manual. In particular, the last section is a slighty more advanced tutorial. You will also find examples in the repository. For an overview of Nickel and the motivations behind it, see the README and the design rationale document.