9 个稳定版本

1.7.0 2024年6月11日
1.6.0 2024年4月25日
1.5.0 2024年3月12日
1.4.1 2024年1月25日
1.1.1 2023年7月10日

108开发工具 中排名

MITLGPL-3.0-only

1.5MB
31K SLoC

镍语言

Continuous integration Website Discord

镍语言是一种低成本的配置语言。

它的目的是自动化生成静态配置文件(例如 JSON、YAML、XML 或您喜欢的数据表示语言),然后将其提供给另一个系统。它设计得简单易懂,核心是具有函数的 JSON。

镍语言的主要特点包括

  • 轻量级:镍语言易于嵌入。解释器应易于实现。参考解释器可以从许多编程语言中调用。
  • 可组合的代码:计算的基本构建块是函数。它们是一等公民,可以被传递、调用和组合。
  • 可组合的数据:数据的基本构建块是记录(在 JSON 中称为“对象”)。在镍语言中,记录可以随意合并,包括相关的元数据(文档、默认值、类型合约等)。
  • 类型化,但仅在需要时:静态类型可以提高代码质量,充当文档并早期消除错误。但是,特定应用的自我包含代码始终评估为相同的值,因此类型错误仍然会在运行时出现。某些 JSON 很难类型化。在那里,类型只是一个负担。而可重用的代码(即“函数”)在潜在无限多的不同输入上评估,无法彻底测试。在那里,类型是宝贵的。镍语言有类型,但您可以自己选择是否需要它,并且它安全地处理类型化和非类型化世界之间的交互。
  • 按合同设计:与类型系统相辅相成,合约是检查断言的原则性方法。解释器自动在类型化和非类型化代码的边界处插入断言。镍语言允许用户添加任意断言并轻松理解断言失败的原因。

镍的设计宗旨是:

良好的默认值,设计可扩展性

应该存在一条标准、清晰的路径,用于处理常见事物。不应该有任何随意的限制,限制你在需要超越的那一刻所能做的事情。

用例

镍适用于任何需要生成复杂配置的情况,无论是单个应用程序、机器、整个基础设施还是构建系统。

特别激发使用用例的是

  • Nix包管理器:Nix是一个使用其自身语言指定包的声明式包管理器。镍是Nix语言的演变,同时试图克服其一些限制。
  • 基础设施即代码:基础设施变得越来越复杂,需要严格的部署、修改和配置方法。这正是声明式方法也大放异彩的地方,如TerraformNixOpsKubernetes所采用的方法,都需要可能复杂的配置生成。
  • 构建系统:构建系统(如Bazel)需要依赖图规范。

上述大多数项目都有自己的定制配置语言。参见比较。一般来说,应用特定的语言可能会遭受特性膨胀、缺乏抽象或仅仅感觉是临时的。镍以更少的代价为你带来更多。

镍生态系统

镍生态系统中的相关项目

入门

请按照nickel-lang网站上为镍用户提供的入门指南操作。以下说明要么是为了使本文件自包含,要么是因为它们针对的是对镍解释器本身的黑客攻击(例如,构建nickel-lang-corecrate文档)。

运行

  1. 获取镍二进制文件

    • 使用flake-enabled Nix,可以直接使用nix run github:tweag/nickel运行镍。您可以使用我们的二进制缓存以防止重建大量包。通过在镍中传递额外的参数,如nix run github:tweag/nickel -- repl,
    • 再次使用flake-enabled Nix,您可以使用nix profile install github:tweag/nickel在您的配置文件中安装镍。然后nickel命令就在您的$PATH中,并且可以在任何地方使用。
    • 如果您正在运行macOS,您可以使用Homebrew使用brew install nickel安装镍二进制文件。
    • 没有Nix,您可以在构建后使用cargo run --bin nickel,通过在额外--传递参数,就像这样cargo run --bin nickel -- eval program.ncl
  2. 运行您的第一个程序

    $ nickel eval <<< '["hello", "world"] |> std.string.join ", "'
    "hello, world"
    

    或从文件加载它

    $ echo 'let s = "world" in "hello, %{s}"' > program.ncl
    $ nickel eval program.ncl
    "hello, world"
    
  3. 启动REPL

    $ nickel repl
    nickel> {"hello" = true, "world" = true, "universe" = false}
      |> std.record.to_array
      |> std.array.filter (fun {field, value} => value)
      |> std.array.map (fun {field, value} => field)
      |> std.string.join ", "
    
    "hello, world"
    

    使用:help查看可用命令列表。

  4. 将配置导出到JSON、YAML或TOML

$ nickel export --format json <<< '{content = "hello, world"}'
{
  "content": "hello, world"
}

使用nickel help查看子命令列表,使用nickel help <子命令>查看特定子命令的帮助。

要联系我们,您可以加入我们的Discord服务器。

编辑器设置

Nickel为Vim/Neovim和VSCode提供了语法高亮插件。编辑器诊断、类型提示和自动完成由Nickel语言服务器提供。请按照LSP指南进行设置,以启用语法高亮和NLS。

格式化

要格式化一个或多个Nickel源文件,请使用nickel format

nickel format network.ncl container.ncl api.ncl

Nickel使用Topiary在内部格式化Nickel代码。

请参阅LSP文档中的格式化功能部分,了解如何将Nickel LSP和Topiary连接起来,以在您的代码编辑器中启用格式化。

构建

  1. 下载构建依赖项

    • 使用Nix:如果您已安装Nix

      nix-shell # if you don't use Nix flakes
      nix develop # if you use Nix flakes
      

      您将进入一个shell,准备好进行构建。您可以使用我们的二进制缓存来防止重新构建大量包。

    • 不使用Nix:否则,请按照此指南安装Rust和Cargo。

  2. 构建Nickel

    cargo build -p nickel-lang-cli --release
    

    好了!生成的文件放在target/release中。

    您可以直接使用cargo run构建并运行Nickel二进制文件,并在--后传递参数。

    cargo run --bin nickel -- eval foo.ncl
    

测试

使用以下命令运行测试

cargo test

文档

用户手册可在nickel-lang.org网站上找到,以及在这个存储库中,作为doc/手册中的Markdown文件集合。

要获取nickel-lang代码库的文档

  1. 构建文档

    cargo doc --no-deps
    
  2. 在浏览器中打开文件target/doc/nickel/index.html

示例

您可以在./examples目录中找到示例。

当前状态和路线图

自2023年5月发布的1.0版本以来,语言的核心理念稳定,Nickel可用于现实世界的应用。我们计划要做的下一步是

我们计划要做的下一步是

  • Nix集成:能够无缝使用Nickel编写包和shell(Organist
  • 自定义合并函数(覆盖提案的第二部分)
  • 增量评估:设计一个增量评估模型和缓存机制,以便在配置发生小幅变化时快速重新评估。
  • 性能改进

比较

  • CUE是一种以数据验证为重点的配置语言。它引入了一个新的基于坚实理论的约束系统,确保了代码的强大保证。它允许非常优雅的架构规范。作为回报,需要付出的代价是放弃函数和图灵完备性。Nickel的合并系统受到了CUE的启发,即使Nickel确实有通用函数并且是图灵完备的,但它们必然是不同的。
  • Nix:Nix语言,或称为Nix表达式,是Nickel的主要灵感来源之一。它是一种非常简单但功能强大的惰性函数式语言。我们努力保持这种简单性,同时增加类型化能力、模块化,并将语言与Nix包管理器分离。
  • Dhall是一种静态类型配置语言。它也受到了Nix的启发,并为它增加了一个强大的静态类型系统。然而,这迫使程序员必须为所有代码添加类型注解。
  • Jsonnet是另一种可以被称为“具有函数的JSON”(以及其他事物)的语言。它是一种具有面向对象特征的惰性函数式语言,其中继承类似于Nickel的合并系统。与Nickel的一个重大区别是没有类型。
  • KCL是一种逐步类型化的配置语言,其验证基于可以通过继承进行扩展的对象模式。与上述语言不同,它的评估是严格的。
  • Pulumi本身不是一种语言,而是一种云工具(如Terraform),您可以使用您首选的语言来描述您的基础设施。这是一种不同的方法,具有不同的权衡。
  • StarlarkBazel的语言,它是Python的一种方言。它没有类型,递归被禁止,因此不是图灵完备的。

请参阅RATIONALE.md以了解设计理由以及与这些语言的更详细比较。

与其他配置语言的比较

语言 类型 递归 评估 副作用
镍语言 逐步(动态+静态) 惰性 是(受限制的,计划中的)
Starlark 动态 严格
Nix 动态 惰性 预定义且专门用于包管理
Dhall 静态(需要注解) 受限 惰性
CUE 静态(一切都是类型) 惰性 否,但在分离的脚本层允许
Jsonnet 动态 惰性
KCL 逐步(动态+静态) 严格
JSON 严格
YAML 不适用
TOML 不适用

依赖关系

~27–47MB
~709K SLoC