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 在 开发工具 中排名
1.5MB
31K SLoC
镍语言
镍语言是一种低成本的配置语言。
它的目的是自动化生成静态配置文件(例如 JSON、YAML、XML 或您喜欢的数据表示语言),然后将其提供给另一个系统。它设计得简单易懂,核心是具有函数的 JSON。
镍语言的主要特点包括
- 轻量级:镍语言易于嵌入。解释器应易于实现。参考解释器可以从许多编程语言中调用。
- 可组合的代码:计算的基本构建块是函数。它们是一等公民,可以被传递、调用和组合。
- 可组合的数据:数据的基本构建块是记录(在 JSON 中称为“对象”)。在镍语言中,记录可以随意合并,包括相关的元数据(文档、默认值、类型合约等)。
- 类型化,但仅在需要时:静态类型可以提高代码质量,充当文档并早期消除错误。但是,特定应用的自我包含代码始终评估为相同的值,因此类型错误仍然会在运行时出现。某些 JSON 很难类型化。在那里,类型只是一个负担。而可重用的代码(即“函数”)在潜在无限多的不同输入上评估,无法彻底测试。在那里,类型是宝贵的。镍语言有类型,但您可以自己选择是否需要它,并且它安全地处理类型化和非类型化世界之间的交互。
- 按合同设计:与类型系统相辅相成,合约是检查断言的原则性方法。解释器自动在类型化和非类型化代码的边界处插入断言。镍语言允许用户添加任意断言并轻松理解断言失败的原因。
镍的设计宗旨是:
良好的默认值,设计可扩展性
应该存在一条标准、清晰的路径,用于处理常见事物。不应该有任何随意的限制,限制你在需要超越的那一刻所能做的事情。
用例
镍适用于任何需要生成复杂配置的情况,无论是单个应用程序、机器、整个基础设施还是构建系统。
特别激发使用用例的是
- Nix包管理器:Nix是一个使用其自身语言指定包的声明式包管理器。镍是Nix语言的演变,同时试图克服其一些限制。
- 基础设施即代码:基础设施变得越来越复杂,需要严格的部署、修改和配置方法。这正是声明式方法也大放异彩的地方,如Terraform、NixOps或Kubernetes所采用的方法,都需要可能复杂的配置生成。
- 构建系统:构建系统(如Bazel)需要依赖图规范。
上述大多数项目都有自己的定制配置语言。参见比较。一般来说,应用特定的语言可能会遭受特性膨胀、缺乏抽象或仅仅感觉是临时的。镍以更少的代价为你带来更多。
镍生态系统
镍生态系统中的相关项目
- Terraform-Nickel:使用镍编写Terraform配置
- Organist:内置镍的环境
- json-schema-to-nickel:从JSON模式规范生成镍合约
- rules_nickel:在Bazel构建期间使用镍生成配置文件
- nickel-lang组织托管各种较小的项目,包括镍的tree-sitter语法定义和编辑器插件。
入门
请按照nickel-lang网站上为镍用户提供的入门指南操作。以下说明要么是为了使本文件自包含,要么是因为它们针对的是对镍解释器本身的黑客攻击(例如,构建nickel-lang-core
crate文档)。
运行
-
获取镍二进制文件
- 使用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
。
- 使用flake-enabled Nix,可以直接使用
-
运行您的第一个程序
$ nickel eval <<< '["hello", "world"] |> std.string.join ", "' "hello, world"
或从文件加载它
$ echo 'let s = "world" in "hello, %{s}"' > program.ncl $ nickel eval program.ncl "hello, world"
-
启动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
查看可用命令列表。 -
将配置导出到JSON、YAML或TOML
$ nickel export --format json <<< '{content = "hello, world"}'
{
"content": "hello, world"
}
使用nickel help
查看子命令列表,使用nickel help <子命令>
查看特定子命令的帮助。
编辑器设置
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连接起来,以在您的代码编辑器中启用格式化。
构建
-
下载构建依赖项
-
构建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
代码库的文档
-
构建文档
cargo doc --no-deps
-
在浏览器中打开文件
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),您可以使用您首选的语言来描述您的基础设施。这是一种不同的方法,具有不同的权衡。
- Starlark是Bazel的语言,它是Python的一种方言。它没有类型,递归被禁止,因此不是图灵完备的。
请参阅RATIONALE.md以了解设计理由以及与这些语言的更详细比较。
与其他配置语言的比较
语言 | 类型 | 递归 | 评估 | 副作用 |
---|---|---|---|---|
镍语言 | 逐步(动态+静态) | 是 | 惰性 | 是(受限制的,计划中的) |
Starlark | 动态 | 否 | 严格 | 否 |
Nix | 动态 | 是 | 惰性 | 预定义且专门用于包管理 |
Dhall | 静态(需要注解) | 受限 | 惰性 | 否 |
CUE | 静态(一切都是类型) | 否 | 惰性 | 否,但在分离的脚本层允许 |
Jsonnet | 动态 | 是 | 惰性 | 否 |
KCL | 逐步(动态+静态) | 是 | 严格 | 否 |
JSON | 无 | 否 | 严格 | 否 |
YAML | 无 | 否 | 不适用 | 否 |
TOML | 无 | 否 | 不适用 | 否 |
依赖关系
~27–47MB
~709K SLoC