最佳实践
本页面是一个工作文档,收集了我们迄今为止发现的语法指南和最佳实践。 本文档的目标是最终确定一个规范的 Nushell 代码风格,但目前仍在进行中,可能会发生变化。我们欢迎讨论和贡献。
请记住,这些指南在外部仓库(非我们的仓库)中使用不是必需的,你可以按自己的方式更改它们,但请保持一致并遵循你的规则。
所有转义序列都不应按字面意思解释,除非另有说明。换句话说, 将 \n
这样的内容视为换行符,而不是字面意义上的斜杠后跟 n
。
格式化
默认值
建议假设默认情况下不允许空格或制表符,但以下规则定义了允许它们的位置。
基本规则
- 建议在管道符号
|
、命令、子命令、它们的选项和参数前后各放一个空格。 - 建议除非它们是字符串的一部分,否则不要放多个连续空格。
- 建议省略列表项之间的逗号。
正确示例:
'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart '0x40c9ff' --fgend '0xe81cff'
错误示例:
# - "|" 后空格过多:2 个而不是 1 个
'Hello, Nushell! This is a gradient.' | ansi gradient --fgstart '0x40c9ff' --fgend '0xe81cff'
单行格式
单行格式是将所有命令写在一行的格式。
建议默认使用此格式:
- 除非你在编写脚本
- 在脚本中用于列表和记录,除非它们:
- 超过 80 个字符长
- 包含嵌套列表或记录
- 对于不包含项目的少于 80 个字符长的管道,应使用长格式
规则:
- 参数:
- 建议在块或闭包参数后的逗号
,
后放一个空格。 - 建议在表示块或闭包参数列表结束的管道符号
|
后放一个空格。
- 建议在块或闭包参数后的逗号
- 块和闭包体:
- 建议如果没有定义显式参数,在开块或闭包大括号
{
后放一个空格。 - 建议在闭块或闭包大括号
}
前放一个空格。
- 建议如果没有定义显式参数,在开块或闭包大括号
- 记录:
- 建议在记录键后的
:
后放一个空格。 - 建议在键值后的逗号
,
后放一个空格。
- 建议在记录键后的
- 列表:
- 建议在列表值后的逗号
,
后放一个空格。
- 建议在列表值后的逗号
- 包围结构:
- 建议如果前一个符号不相同,在开方括号
[
、大括号{
或圆括号(
前放一个空格。 - 建议如果后一个符号不相同,在闭方括号
]
、大括号}
或圆括号)
后放一个空格。
- 建议如果前一个符号不相同,在开方括号
正确示例:
[[status]; [UP] [UP]] | all {|el| $el.status == UP }
[1 2 3 4] | reduce {|elt, acc| $elt + $acc }
[1 2 3 4] | reduce {|elt acc| $elt + $acc }
{x: 1, y: 2}
{x: 1 y: 2}
[1 2] | zip [3 4]
[]
(1 + 2) * 3
错误示例:
# "|el|" 前空格过多:不允许有空格
[[status]; [UP] [UP]] | all { |el| $el.status == UP }
# "," 前空格过多:不允许有空格
[1 2 3 4] | reduce {|elt , acc| $elt + $acc }
# "x" 前空格过多:不允许有空格
{ x: 1, y: 2}
# "[3" 前空格过多:需要一个空格
[1 2] | zip [3 4]
# "]" 前空格过多:不允许有空格
[ ]
# ")" 前空格过多:不允许有空格
(1 + 2 ) * 3
多行格式
多行格式是将所有命令写在多行的格式。它继承了单行格式的所有规则并稍作修改。
建议默认使用此格式:
- 在编写脚本时
- 在脚本中用于列表和记录,当它们:
- 超过 80 个字符长
- 包含嵌套列表或记录
- 对于超过 80 个字符长的管道
规则:
- 一般规则:
- 必须省略尾随空格。
- 块和闭包体:
- 建议将每个主体管道放在单独的行上。
- 记录:
- 建议将每个记录键值对放在单独的行上。
- 列表:
- 建议将每个列表项放在单独的行上。
- 包围结构:
- 建议如果前一个符号不相同,在开方括号
[
、大括号{
或圆括号(
前放一个\n
,且应用此规则会产生带有单个括号的行。 - 建议如果后一个符号不相同,在闭方括号
]
、大括号}
或圆括号)
后放一个\n
,且应用此规则会产生带有单个括号的行。
- 建议如果前一个符号不相同,在开方括号
正确示例:
[[status]; [UP] [UP]] | all {|el|
$el.status == UP
}
[1 2 3 4] | reduce {|elt, acc|
$elt + $acc
}
{x: 1, y: 2}
[
{name: "Teresa", age: 24},
{name: "Thomas", age: 26}
]
let selectedProfile = (for it in ($credentials | transpose name credentials) {
echo $it.name
})
错误示例:
# "|el|" 前空格过多:不允许有空格(如单行格式)
[[status]; [UP] [UP]] | all { |el|
# "}" 前 "\n" 过少:需要一个 "\n"
$el.status == UP}
# "2" 前空格过多:需要一个空格(如单行格式)
[1 2 3 4] | reduce {|elt, acc|
$elt + $acc
}
{
# "x" 前 "\n" 过多:由于不存在嵌套列表或记录,需要单行格式
x: 1,
y: 2
}
# "{" 前 "\n" 过少:由于有两个嵌套记录,需要多行格式
[{name: "Teresa", age: 24},
{name: "Thomas", age: 26}]
let selectedProfile = (
# "foo" 前 "\n" 过多:不允许有 "\n"
for it in ($credentials | transpose name credentials) {
echo $it.name
})
命名约定
缩写和首字母缩略词
建议使用完整的简洁单词而不是缩写和首字母缩略词,除非它们是众所周知的和/或常用的。
正确示例:
query-user --id 123
$user.name | str downcase
错误示例:
qry-usr --id 123
$user.name | string downcase
大小写
命令
建议对多词命令名使用 kebab-case(短横线命名法)。
正确示例:
fetch-user --id 123
错误示例:
fetch_user --id 123
fetchUser --id 123
另见命名命令。
子命令
子命令是在逻辑上分组在父命令下并用空格分隔的命令。 建议对子命令名使用 kebab-case(短横线命名法)。
正确示例:
date now
date list-timezone
def "login basic-auth" [username: string password: string] {
# ...
}
另见命名子命令。
标志
建议对标志名使用 kebab-case(短横线命名法)。
正确示例:
def greet [name: string, --all-caps] {
# ...
}
错误示例:
def greet [name: string, --all_caps] {
# ...
}
变量和命令参数
建议对变量名(包括命令参数)使用 snake_case(蛇形命名法)。
正确示例:
let user_id = 123
def fetch-user [user_id: int] {
# ...
}
错误示例:
let user-id = 123
let userId = 123
def fetch-user [user-id: int] {
# ...
}
环境变量
建议对环境变量名使用 SCREAMING_SNAKE_CASE(全大写蛇形命名法)。
正确示例:
$env.ENVIRONMENT_CODE = "prod"
$env.APP_VERSION = "1.0.0"
错误示例:
$env.ENVIRONMENT-CODE = "prod"
$env.app_version = "1.0.0"
自定义命令的选项和参数
- 建议将所有位置参数的数量保持在 2 个或更少,对于其余输入使用选项。假设命令可以期望源参数和目标参数,如
mv
:源文件或目录和目标文件或目录。 - 建议使用位置参数,除非由于此处列出的规则或技术限制而无法使用。 例如,当有几种类型的可选参数时(但至少应提供一个参数) 使用选项。这方面的一个很好的例子是
ansi gradient
命令,其中必须传递前景色或背景色。 - 建议同时提供长选项和短选项。
文档
- 建议为所有导出的实体(如自定义命令)及其 输入(如自定义命令参数和选项)提供文档。