nuglif / nacl
Nuglif 应用配置语言(NACL)是一种旨在同时适合人类和机器的配置数据语言。
Requires
- php: ^8.0
Requires (Dev)
- ext-json: *
- phpunit/phpunit: ^9.0
- squizlabs/php_codesniffer: @stable
- vimeo/psalm: ^5.6
This package is auto-updated.
Last update: 2024-09-21 15:55:25 UTC
README
NACL 是一种旨在同时适合人类和机器的配置数据语言。虽然它是一个 JSON 扩展,这意味着 JSON 可以用作 NACL 解析器的有效输入,但 NACL 的主要动机是通过表示和解释配置数据,而不是像 JSON 或 YAML 这样的传统数据表示语言,这些语言分别定义为 数据对象表示 和 数据序列化,它们属于通用数据表示语言领域,因此在应用配置领域迅速显示出弱点。
感谢 Vsevolod Stakhov 创建了 UCL,因为他觉得作为配置语言,XML 达不到要求。 NACL 受 Vsevolod Stakhov 的 UCL(通用配置语言)的强烈启发。
此项目包含 NACL 规范及其作为 PHP 库的实现。在 EBNF 中也有详细的 NACL 语法参考。
目录
NACL 快速入门示例
application {
debug off;
buffer 10MB;
mysql {
host .env (default: "127.0.0.1") MYSQL_HOST;
username .env (default: root) MYSQL_USERNAME;
password .env (default: root) MYSQL_PASSWORD;
port .env (default: 3306, type: int) MYSQL_PORT;
}
servers [
"172.28.0.10",
"172.28.0.5"
]
}
NACL 对 JSON 语法的扩展
因为 NACL 是 JSON 的超集,所以我们将简要介绍 JSON 语法本身,并描述语言是如何扩展的。
类型
NACL 允许与 JSON 相同的类型,包括 string、number、object、array、boolean 和 null
值。
根对象
NACL 允许任何一种支持的类型作为配置文件的根本元素。
以下是一些有效的 NACL 示例
"Hello, World!"
true
[ 1000, 2000 ]
{ "foo": "bar" }
然而,与 JSON 不同,NACL 将在两种情况下提供隐式的 {}
根对象:当 NACL 源文件由一个或多个键/值对组成时,例如
"host": "localhost",
"port": 80
将相当于
{"host": "localhost", "port": 80}
或者当 NACL 源是空的 NACL 文件时,这将是 JSON 的等效文件
{}
未引号字符串
NACL 允许未引号字符串用于单词键和值。未引号字符串以 ASCII 字母或下划线开头,后面跟任意数量的 ASCII 字母、ASCII 数字、下划线或破折号。作为一个正则表达式,它将这样表示:^[A-Za-z_][A-Za-z0-9_-]*$
。
例如
host: localhost
将相当于
{"host": "localhost"}
多行字符串
NACL 允许使用 heredoc 语法的多行字符串。
例如
text: <<<END
This is
a multiline
string
END;
将相当于
{"text": "This is\na multiline\nstring"}
注意:如果您有非常长的文本,您可能希望将文本放在单个文件中,并使用 文件宏。
可选值赋值符号
NACL 允许使用列 :
或等号 =
来进行值赋值,但是这个赋值符号是可选的,NACL 允许您完全省略赋值符号。
例如
host: localhost
等同于
host = localhost
也等同于
host localhost
这些都是等效的
{"host": "localhost"}
分隔符号
NACL 语句(数组或对象元素)可以使用 ,
或 ;
分隔,并且 NACL 允许语句终止符,因此您可以在数组或对象的最后一个元素之后安全地使用额外的分隔符。
例如
key1 value1,
key2 value2
等同于
key1 value1,
key2 value2,
这也等同于
key1 value1;
key2 value2;
这些都是等效的
{ "key1": "value1", "key2": "value2" }
变量
可以使用 ${VAR}
语法创建或读取变量。
例如
${TMP_DIR} = "/tmp";
temp_dir = ${TMP_DIR};
temp_file = "${TMP_DIR}/tempfile.txt";
等同于
{ "temp_dir": "/tmp", "temp_file": "/tmp/tempfile.txt" }
PHP 相关说明:PHP 库允许使用 API 注入变量,例如
<?php $parser = Nuglif\Nacl\Nacl::createParser(); $parser->setVariable('TMP_DIR', sys_get_temp_dir()); $config = $parser->parseFile('application.conf');
注释
NACL 允许两种单行注释风格和一种多行注释风格。
- 单行注释可以以
//
或#
开始 - 多行注释必须以
/*
开始并以*/
结束
布尔值
NACL 允许您使用 true
/ false
、yes
/ no
和 on
/ off
来表示布尔值。所有这些都将被解释为布尔值,但是词义的多样性允许您更好地表达布尔配置语句背后的意图。
您可以简单地声明
debug on;
这比
debug true;
甚至更糟
debug 1;
乘数
后缀乘数使 NACL 更具声明性和简洁性,并帮助您避免错误。 NACL 允许使用一些常见的后缀乘数。
在 NACL 中,数字可以后缀以下
k
M
G
前缀为国际单位制(SI)(1000^n)kB
MB
GB
1024^n 字节ms
s
min
h
d
w
y
以秒为单位的数字。
例如
file_max_size 7MB; # 7 * 1024^2 (bytes)
file_ttl 9min; # 9 * 60 (seconds)
等同于
file_max_size 7340032; # 7 * 1024^2 (bytes)
file_ttl 540; # 9 * 60 (seconds)
这等同于
{ "file_max_size": 7340032, "file_ttl": 540 }
NACL 对象结构将合并
NACL 允许在路径上重新声明具有相同键名的对象,具有相同名称的对象键将递归地合并(深度合并)。合并仅适用于对象值,如果非对象值重叠,则最后声明的值将是最终值。
例如
foo {
non-object-value-a true;
non-object-value-b [ 1, 2 ];
object-value { c: "c"}
}
foo {
non-object-value-a false;
non-object-value-b [ 3, 4 ];
object-value { x: "x" }
}
将在存在对象值的地方递归合并,并且结果结构将等同于
{ "foo": { "non-object-value-a": false, "non-object-value-b": [ 3, 4 ], "object-value": { "c": "c", "x": "x" } } }
使用键名进行分层声明
NACL 允许您通过仅使用键作为层次结构路径来设置层次结构中的值,通过在赋值键侧将层次结构的每个键一个接一个地用空格分隔。
例如
development server debug on;
production server url "example.com";
production server port 80;
也将是 NACL 的等效表达式
development {
server {
debug on;
}
}
production {
server {
url "example.com";
port 80;
}
}
这也可以是 NACL 的等效表达式
development {
server {
debug on;
}
}
production {
server {
url "example.com";
}
}
production server {
port 80;
}
这将等同于 JSON
{ "development": { "server": { "debug": true } }, "production": { "server": { "url": "example.com", "port": 80 } } }
NACL 宏
NACL 提供了一些基本宏,如 .ref、.include、.file 和 .env 宏。
为了与键和其他语言元素区分开来,宏名称以点开始。它们期望一个值(可以是基本类型或非基本类型),以及可能的不同可选参数。
例如
.a_macro_name (param1: foo, param2: bar) "the primitive, array or object value"
将是一个通用的 NACL 宏形式表示。
宏规范允许语言通过特定于您的域和实现的自定义宏进行扩展。
.ref 宏(引用)
NACL 提供了 .ref
宏,可以用于在 NACL 树中引用另一个值。您提供的值是一个路径,可以是相对的或绝对的。
例如
foo bar;
baz .ref "foo";
这将等同于
{ "foo": "bar", "baz": "bar" }
.include 宏(已评估的包含)
NACL 提供了 .include
宏,可以用于在其他 NACL 文件中包含和评估 NACL 文件。以下表描述了 .include
宏的三个可选参数。
例如
.include "file.conf";
.include (required: false) "file.override.conf";
.include (glob: true, filenameKey: true) "conf.d/*.conf";
作为另一个示例,如果您有一个名为 file.conf
的文件,其中只包含 foo: "bar";
,那么以下 NACL 示例
.include "file.conf";
baz: "qux";
将等同于
{ "foo": "bar", "baz": "qux" }
作为 glob: true
和 filenameKey: true
的示例用法,假设您有一个名为 person1.conf
的文件,其中包含 "alice";
,还有一个名为 person2.conf
的文件,其中包含 "bob"
,以及以下包含它们的第三个 NACL 文件
.include(glob: true, filenameKey: true) "*.conf";
将等同于
{ "person1": "alice", "person2": "bob" }
.file 宏(未评估的包含)
NACL 提供了 .file
宏,它可以用于在 NACL 文件中包含其他文件而无需对其执行评估。
例如
email {
template .file "welcome.tpl";
}
将 welcome.tpl
文件的内容分配给 template
变量。如果 welcome.tpl
文件只包含 欢迎我的朋友
,则之前的 NACL 示例将变成以下 JSON 等价形式
{ "email": { "template": "Welcome my friend" } }
.env 宏(环境变量)
NACL 提供了 .env
宏,它可以用于评估指定的环境变量。下表描述了 .env
宏的两个可选参数。
例如
port .env (default: 80, type: int) SERVER_PORT;
title .env TITLE;
在 SERVER_PORT
未定义且 TITLE
设置为 "300"
的系统上,之前的 NACL 示例将变成以下 JSON 等价形式
{ "port": 80, "title": "300" }
PHP 库
本项目提供了一个作为 PHP 库实现的 NACL 规范。
安装
使用 composer 安装
composer require nuglif/nacl
此库可在 PHP 7.1 到 8.0 或更高版本上运行。
使用
以下是一个基本用法示例
<?php $config = Nuglif\Nacl\Nacl::parseFile('application.conf');
或者
<?php $parser = Nuglif\Nacl\Nacl::createParser(); $config = $parser->parseFile('application.conf');
使用您的宏扩展 NACL
使用您自己的宏扩展 NACL 非常容易。
key .myMacro someParam;
key .myMacro(optionName: someValue, otherOption: otherValue) {
/* Some content here */
};
要创建您的宏,您必须实现 Nuglif\Nacl\MacroInterface
接口
<?php interface MacroInterface { public function getName(): string; public function execute(mixed $parameter, array $options = []): mixed; }
并使用 Nulig\Nacl\Parser::registerMacro($macro);
方法。
<?php Nuglif\Nacl\Nacl::registerMacro(new MyMacro); $config = Nuglif\Nacl\Nacl::parseFile('application.conf');
或者
<?php $parser = Nuglif\Nacl\Nacl::createParser(); $parser->registerMacro(new MyMacro); $config = $parser->parseFile('application.conf');
作者
- Pierrick Charron (pierrick@adoy.net) - 初始工作
- Charle Demers (charle.demers@gmail.com) - 初始工作
许可
本项目采用 MIT 许可证 - 关于完整版权和许可信息,请查看与此源代码一起分发的 LICENSE 文件。
版权所有 2019 Nuglif (2018) Inc. 保留所有权利。