8个版本 (破坏性)
0.8.0 | 2024年6月11日 |
---|---|
0.7.0 | 2024年4月25日 |
0.6.0 | 2024年3月12日 |
0.5.0 | 2024年1月25日 |
0.1.0 | 2023年7月10日 |
878 在 配置 中
每月下载 141 次
在 4 crates 中使用
1.5MB
29K 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的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
安装Nickel的二进制文件。 - 没有Nix,您可以在构建后使用
cargo run --bin nickel
运行程序,并通过额外的--
传递参数,例如cargo run --bin nickel -- eval program.ncl
。
- 使用启用flake的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
构建 Nickle 二进制文件,并在--
后传递参数。cargo run --bin nickel -- eval foo.ncl
测试
使用以下命令运行测试
cargo test
文档
用户手册可在 nickel-lang.org 网站上 获取,以及在此存储库中作为位于 doc/manual
的Markdown文件集合。
要获取 nickel-lang
代码库本身的文档
-
构建文档
cargo doc --no-deps
-
在您的浏览器中打开文件
target/doc/nickel/index.html
。
示例
您可以在 ./examples
目录中找到示例。
当前状态和路线图
自2023年5月发布的1.0版本以来,语言的内核设计已稳定,Nickel可用于实际应用。我们计划下一步工作的步骤是
我们计划下一步工作的步骤是
- 镍集成:能够无缝使用镍来编写包和外壳(Organist)
- 自定义合并函数(覆盖提议的第二部分 overriding proposal)
- 增量评估:设计一个增量评估模型和缓存机制,以便在配置发生微小变化时快速重新评估。
- 性能改进
比较
- CUE 是一种关注数据验证的配置语言。它引入了一个由坚实理论支持的全新约束系统,确保了代码的强保障。它允许进行非常优雅的架构规范。然而,需要付出的代价是放弃函数和 图灵完备性。镍的合并系统受到了 CUE 的启发,尽管镍具有通用函数并且是图灵完备的,但它们必然是不同的。
- Nix:Nix 语言,或 Nix 表达式,是镍的主要灵感之一。它是一种简单而强大的惰性函数式语言。我们努力保持这种简单性,同时添加类型能力、模块化和将语言从 Nix 软件包管理器中分离出来。
- Dhall 是一种静态类型配置语言。它也受到了 Nix 的启发,并添加了一个强大的静态类型系统。然而,这迫使程序员必须对所有代码进行类型注解。
- Jsonnet 是另一种可以被称为“具有函数的 JSON”(以及其它事物)的语言。它是一种具有面向对象功能的惰性函数式语言,其中继承类似于镍的合并系统。与镍的一个重大不同之处在于缺乏类型。
- KCL 是一种逐步类型配置语言,其验证基于可以通过继承扩展的对象模式。与上述语言不同,其评估是严格的。
- Pulumi 不是一个语言本身,而是一个云工具(类似于 Terraform),您可以使用您喜欢的语言来描述您的基础设施。这是一种不同的解决问题的方式,具有不同的权衡。
- Starlark 是 Bazel 的语言,它是 Python 的方言。它没有类型,递归是被禁止的,这使得它不是图灵完备的。
请参阅 RATIONALE.md 了解设计原理以及与这些语言的更详细比较。
与其他配置语言的比较
语言 | 类型 | 递归 | 评估 | 副作用 |
---|---|---|---|---|
镍 | 逐步(动态 + 静态) | 是 | 惰性 | 是(受约束的,计划中的) |
Starlark | 动态 | 否 | 严格 | 否 |
Nix | 动态 | 是 | 惰性 | 预定义且专用于包管理 |
Dhall | 静态(需要注解) | 受限 | 惰性 | 否 |
CUE | 静态(一切都是类型) | 否 | 惰性 | 否,但在分离的脚本层允许 |
Jsonnet | 动态 | 是 | 惰性 | 否 |
KCL | 逐步(动态 + 静态) | 是 | 严格 | 否 |
JSON | 无 | 否 | 严格 | 否 |
YAML | 无 | 否 | 不适用 | 否 |
TOML | 无 | 否 | 不适用 | 否 |
依赖关系
~26–44MB
~652K SLoC