1
1
mirror of https://github.com/tweag/nickel.git synced 2024-09-19 07:28:22 +03:00
Better configuration for less
Go to file
dependabot[bot] 272baab2b9
chore(deps): bump cachix/install-nix-action from 17 to 18
Bumps [cachix/install-nix-action](https://github.com/cachix/install-nix-action) from 17 to 18.
- [Release notes](https://github.com/cachix/install-nix-action/releases)
- [Commits](https://github.com/cachix/install-nix-action/compare/v17...v18)

---
updated-dependencies:
- dependency-name: cachix/install-nix-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2022-10-13 00:23:33 +00:00
.github chore(deps): bump cachix/install-nix-action from 17 to 18 2022-10-13 00:23:33 +00:00
.vscode Fix problem with the client not starting up 2021-09-23 19:40:03 +03:00
benches fix mantis benchmark by changing "priority" var (became a reserved keyword in 7a758f83) 2022-10-04 13:23:00 +02:00
doc/manual Rephrase correctness documentation 2022-09-21 16:47:43 +02:00
examples Cosmetic fix of merge example with priorities 2022-09-16 16:56:23 +02:00
lsp Move CompletionExtra to a struct. 2022-10-10 16:35:27 +01:00
nickel-wasm-repl Bump version to 0.2.1 2022-08-08 15:31:44 +02:00
notes Fix typo 2022-05-20 23:45:10 +01:00
rfcs Markdownlint on RFC002 2022-08-04 18:37:00 +02:00
src Merge pull request #856 from tweag/fix/lang-server-wildcard 2022-10-11 15:13:19 +01:00
stdlib added doc for polarity change 2022-09-16 11:45:43 +01:00
tests Fix testlib ignoring last test 2022-10-11 12:28:24 +02:00
utilities Cargo fmt 2022-10-10 10:11:24 +02:00
.gitignore Remove Makam specification 2022-06-24 16:46:36 +02:00
.markdownlint.json Enable markdown linting 2022-08-05 11:55:21 +02:00
.vscodeignore Move lsp to subfolder 2021-09-23 17:21:45 +03:00
build.rs Move grammar.lalrpop to /parser 2022-08-05 15:26:47 +02:00
Cargo.lock rewrite the Identifier Interner to store strings in an arena and Ident to have symbols 2022-09-20 13:43:09 +02:00
Cargo.toml rewrite the Identifier Interner to store strings in an arena and Ident to have symbols 2022-09-20 13:43:09 +02:00
CONTRIBUTING.md Fix markdown lint warnings for CONTRIBUTING.md 2022-08-04 18:37:00 +02:00
default.nix Make it easier to build the project without using flakes 2021-11-03 08:57:55 +01:00
flake.lock flake.lock: Update 2022-09-06 15:20:51 +02:00
flake.nix Enable markdown linting 2022-08-05 11:55:21 +02:00
HACKING.md Fix markdown lint warnings for HACKING.md 2022-08-04 18:37:00 +02:00
LICENSE Set the license to Tweag's MIT 2020-08-10 09:54:03 +02:00
RATIONALE.md flake.lock: Update 2022-08-31 11:09:00 +02:00
README.md Fix markdown lint warnings on README 2022-08-04 18:37:00 +02:00
RELEASES.md Add release notes for 0.2.0 2022-08-08 15:31:44 +02:00
shell.nix Add flake.nix 2020-07-03 14:22:21 +02:00
wasm-bindgen-api-Cargo.lock Use overlay to pin wasm-bindgen-cli 2022-01-14 22:47:05 +01:00

Nickel

Continuous integration Website

Nickel is the cheap configuration language.

Its purpose is to automate the generation of static configuration files - think JSON, YAML, XML, or your favorite data representation language - that are then fed to another system. It is designed to have a simple, well-understood core: it is in essence JSON with functions.

Nickel's salient traits are:

  • Lightweight: Nickel is easy to embed. An interpreter should be simple to implement. The reference interpreter can be called from many programming languages.
  • Composable code: the basic building blocks for computing are functions. They are first-class citizens, which can be passed around, called and composed.
  • Composable data: the basic building blocks for data are records (called objects in JSON). In Nickel, records can be merged at will, including associated metadata (documentation, default values, type contracts, etc).
  • Typed, but only when it helps: static types improve code quality, serve as documentation and eliminate bugs early. But application-specific self-contained code will always evaluate to the same value, so type errors will show up at runtime anyway. Some JSON is hard to type. There, types are only a burden. Whereas reusable code - that is, functions - is evaluated on potentially infinitely many different inputs, and is impossible to test exhaustively. There, types are precious. Nickel has types, but you get to choose when you want it or not, and it handles safely the interaction between the typed and the untyped world.
  • Design by contract: complementary to the type system, contracts are a principled approach to checking assertions. The interpreter automatically inserts assertions at the boundary between typed and untyped code. Nickel lets users add arbitrary assertions of their own and easily understand why when assertions fail.

The motto guiding Nickel's design is:

Great defaults, design for extensibility

There should be a standard, clear path for common things. There should be no arbitrary restrictions that limit what you can do you the one day you need to go beyond.

Use cases

Nickel is a good fit in any situation where you need to generate a complex configuration, be it for a single app, a machine, whole infrastructure, or a build system.

The motivating use cases are in particular:

  • The Nix package manager: Nix is a declarative package manager using its own language for specifying packages. Nickel is an evolution of the Nix language, while trying to overcome some of its limitations.
  • Infrastructure as code: infrastructure is becoming increasingly complex, requiring a rigorous approach to deployment, modification and configuration. This is where a declarative approach also shines, as adopted by Terraform, NixOps or Kubernetes, all requiring potentially complex generation of configuration.
  • Build systems: build systems (like Bazel) need a specification of the dependency graph.

Most aforementioned projects have their own bespoke configuration language. See Related projects and inspirations. In general, application-specific languages might suffer from feature creep, lack of abstractions or just feel ad hoc. Nickel buys you more for less.

Getting started

Please follow the getting started guide for Nickel users on the nickel-lang website. The instructions below are either reproduced for this document to be relatively self-sufficient, or because they are aimed toward hacking on the Nickel interpreter itself (e.g. building the nickel-lang crate documentation).

Run

  1. Start Nickel

    • with flake-enabled Nix directly with nix run nickel (which pulls it from the global flakes registry), or with nix run github:tweag/nickel (which pulls it from the repo). You can use our binary cache to prevent rebuilding a lot of packages. You pass in arguments with an extra -- as in nix run nickel -- repl,
    • with ./nickel, after building this repo, depending on the location of the executable and passing in arguments directly,
    • or with cargo run after building, passing in arguments with an extra -- as in cargo run -- -f program.ncl.
  2. Run your first program:

    $ ./nickel <<< 'let x = 2 in x + x'
    4
    

    Or load it from a file:

    $ echo 'let s = "world" in "Hello, " ++ s' > program.ncl
    $ ./nickel -f program.ncl
    "Hello, world"
    
  3. Start a REPL:

    $ ./nickel repl
    nickel> let x = 2 in x + x
    4
    
    nickel>
    

    Use :help for a list of available commands.

  4. Export your configuration to JSON, YAML or TOML:

$ ./nickel export --format json <<< '{foo = "Hello, world!"}'
{
  "foo": "Hello, world!"
}

Use nickel help for a list of subcommands, and nickel help <subcommand> for help about a specific subcommand.

Editor Setup

Nickel has syntax highlighting plugins for Vim/Neovim, and VSCode. In-editor diagnostics, type hints, and auto-completion are provided by the Nickel Language Server. Please follow this guide to setup syntax highlighting and NLS.

Build

  1. Download build dependencies:

    • With Nix: If you have Nix installed:

      nix-shell shell.nix
      

      to be dropped in a shell, ready to build. You can use our binary cache to prevent rebuilding a lot of packages.

    • Without Nix: otherwise, follow this guide to install Rust and Cargo first.

  2. Build Nickel:

    cargo build
    

    And voilà! Generated files are placed in target/debug.

  3. (optional) make a symbolic link to the executable:

ln -S nickel target/debug/nickel

Tests

cargo test

Documentation

The user manual is available on the nickel-lang.org website, and in this repository as a collection of Markdown files in doc/manual.

To get the documentation of the nickel-lang codebase itself:

  1. Build the doc:

    cargo doc --no-deps
    
  2. Open the file target/doc/nickel/index.html in your browser.

Examples

You can find examples in the ./examples directory.

Current state and roadmap

Nickel has been released in version 0.1. This version should be functional, it is intended to gather feedback and real-life testing. Nickel 0.1 isn't intended to be used in production. The next steps we plan to work on are:

  • Nix integration: being able to seamlessly use Nickel to write shells, packages and NixOS modules.
  • Custom merge functions and priorities (second part of the overriding proposal)
  • Performance improvements
  • CUE is a configuration language with a focus on data validation. It introduces a new constraint system backed by a solid theory which ensures strong guarantees about your code. It allows for very elegant schema specifications. In return, the cost to pay is to abandon functions and Turing-completeness. Nickel's merge system is inspired by the one of CUE, even if since Nickel does have general functions and is Turing-complete, they are necessarily different.
  • Nix: The Nix language, or Nix expressions, is one of the main inspirations for Nickel. It is a very simple yet powerful lazy functional language. We strive to retain this simplicity, while adding typing capabilities, modularity, and detaching the language from the Nix package manager.
  • Dhall is a statically typed configuration language. It is also inspired by Nix, to which it adds a powerful static type system. However, this forces the programmer to annotate all of their code with types.
  • Jsonnet is another language which could be dubbed as "JSON with functions" (and others things as well). It is a lazy functional language with object oriented features, among which inheritance is similar to Nickel's merge system. One big difference with Nickel is the absence of typing.
  • Pulumi is not a language in itself, but a cloud tool (like Terraform) where you can use your preferred language for describing your infrastructure. This is a different approach to the problem, with different trade-offs.
  • Starlark is the language of Bazel, which is a dialect of Python. It does not have types and recursion is forbidden, making it not Turing-complete.

See RATIONALE.md for the design rationale and a more detailed comparison with a selection of these languages.