Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .vuepress/configs/sidebar/zh-CN.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export const sidebarZhCN: SidebarConfig = {
'/zh-CN/book/overlays.md',
'/zh-CN/book/sorting.md',
'/zh-CN/book/testing.md',
'/zh-CN/book/debugging.md',
'/zh-CN/book/style_guide.md',
],
},
Expand Down Expand Up @@ -93,6 +94,7 @@ export const sidebarZhCN: SidebarConfig = {
children: [
'/zh-CN/book/coming_from_bash.md',
'/zh-CN/book/coming_from_cmd.md',
'/zh-CN/book/coming_from_powershell.md',
'/zh-CN/book/nushell_map.md',
'/zh-CN/book/nushell_map_imperative.md',
'/zh-CN/book/nushell_map_functional.md',
Expand All @@ -117,6 +119,8 @@ export const sidebarZhCN: SidebarConfig = {
'/zh-CN/book/parallelism.md',
'/zh-CN/book/plugins.md',
'/zh-CN/book/explore.md',
'/zh-CN/book/tui.md',
'/zh-CN/book/mcp.md',
],
},
],
Expand Down
52 changes: 52 additions & 0 deletions tools/i18n-meta.json
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,19 @@
"ru": "-",
"ko": "-"
},
{
"name": "coming_from_powershell.md",
"en": "Completed",
"zh-CN": "e9317a86@passionworkeer",
"fr": "-",
"de": "-",
"tr": "-",
"ja": "-",
"es": "-",
"pt-BR": "-",
"ru": "-",
"ko": "-"
},
{
"name": "coming_to_nu.md",
"en": "In progress",
Expand Down Expand Up @@ -207,6 +220,19 @@
"ru": "-",
"ko": "-"
},
{
"name": "debugging.md",
"en": "Completed",
"zh-CN": "ff1c4786@passionworkeer",
"fr": "-",
"de": "-",
"tr": "-",
"ja": "-",
"es": "-",
"pt-BR": "-",
"ru": "-",
"ko": "-"
},
{
"name": "dataframes.md",
"en": "Completed",
Expand Down Expand Up @@ -376,6 +402,19 @@
"ru": "-",
"ko": "-"
},
{
"name": "mcp.md",
"en": "Completed",
"zh-CN": "ff1c4786@passionworkeer",
"fr": "-",
"de": "-",
"tr": "-",
"ja": "-",
"es": "-",
"pt-BR": "-",
"ru": "-",
"ko": "-"
},
{
"name": "metadata.md",
"en": "Completed",
Expand Down Expand Up @@ -701,6 +740,19 @@
"ru": "-",
"ko": "-"
},
{
"name": "tui.md",
"en": "Completed",
"zh-CN": "ff1c4786@passionworkeer",
"fr": "-",
"de": "-",
"tr": "-",
"ja": "-",
"es": "-",
"pt-BR": "-",
"ru": "-",
"ko": "-"
},
{
"name": "types_of_data.md",
"en": "Completed",
Expand Down
6 changes: 4 additions & 2 deletions zh-CN/book/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ Nushell 中的值包含一些额外的[元数据](metadata.md)。

由于 Nushell 严格的作用域规则,[并行迭代集合](parallelism.md)非常容易,这可以帮助你通过只输入几个字符来加速长时间运行的脚本。

你可以使用 [`explore`](/commands/docs/explore.md) 命令[交互式地探索数据](explore.md)。
你可以使用 [`explore`](/commands/docs/explore.md) 命令[交互式地探索数据](explore.md),也可以通过 `tui` 命令族[构建你专属的终端用户界面](tui.md)(如选择器、对话框和监控仪表盘)。

最后,你可以使用[插件](plugins.md)来扩展 Nushell 的功能。
你可以使用[插件](plugins.md)来扩展 Nushell 的功能。
几乎任何东西都可以成为插件,只要它以 Nushell 理解的协议与 Nushell 通信。

最后,Nushell 可以作为 [MCP 服务器](mcp.md)运行,使 AI Agent 和其他 Model Context Protocol 客户端能够查询其命令并执行 Nushell 代码。
82 changes: 82 additions & 0 deletions zh-CN/book/coming_from_powershell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# 从 PowerShell 到 Nu

::: tip
PowerShell 管道传递的是丰富的 **.NET 对象**,支持通过 `$process.Name` 等语法直接访问属性,或者直接将对象通过管道传递给支持该对象的 cmdlet。

相比之下,Nushell 管道传递的是表格、列表和值等**结构化数据**。
这意味着:

- 不支持 `.PropertyName` 语法访问属性
- 改用 `get column`、`select`、`$it.column` 或表格操作
- 命令始终接收可预测的结构化输入,而非字符串或 .NET 类型
:::

## 等价命令参考:

| PowerShell | Nu | 任务 |
| --------------------------------------------------------------- | -------------------------------------------- | ---------------------------------- |
| `Get-ChildItem` | `ls` | 列出当前目录中的文件 |
| `Get-ChildItem <dir>` | `ls <dir>` | 列出指定目录中的文件 |
| `Get-ChildItem pattern*` | `ls pattern*` | 模式匹配文件 |
| `Get-ChildItem -Force -File -Hidden` | `ls --long --all` 或 `ls -la` | 详细列出文件(包含隐藏文件) |
| `Get-ChildItem \| Where-Object { $_.PSIsContainer }` | `ls \| where type == dir` | 仅列出目录 |
| `Get-ChildItem -Recurse -Filter *.rs` | `ls **/*.rs` | 递归搜索文件 |
| `Get-ChildItem -Recurse Makefile \| Select-Object -Expand Name` | `ls **/Makefile \| get name \| vim ...$in` | 将匹配的文件路径传递给命令 |
| `Set-Location <dir>` | `cd <dir>` | 切换目录 |
| `Set-Location` | `cd` | 返回主目录 |
| `Set-Location -` | `cd -` | 返回上一个目录 |
| `New-Item -ItemType Directory <path>` | `mkdir <path>` | 创建目录 |
| `New-Item test.txt` | `touch test.txt` | 创建文件 |
| `command \| Out-File <path>` | `out> <path>` 或 `o> <path>` | 保存输出到文件(原始文本) |
| `command \| Set-Content <path>` | `\| save <path>` | 保存输出到文件(结构化) |
| `command \| Out-File -Append <path>` | `out>> <path>` 或 `o>> <path>` | 追加输出到文件 |
| | `\| save --append <path>` | 追加结构化输出 |
| `command \| Out-Null` | `\| ignore` | 丢弃输出 |
| `cmd1 \| Tee-Object -FilePath log.txt \| cmd2` | `cmd1 \| tee { save log.txt } \| cmd2` | 将输出同时保存到文件 |
| `command \| Select-Object -First 5` | `command \| first 5` | 限制输出前 N 行 |
| `Get-Content <path>` | `open --raw <path>` | 显示文件内容 |
| `Move-Item <source> <dest>` | `mv <source> <dest>` | 移动文件 |
| `Get-ChildItem *.md \| ForEach-Object { $_.Name }` | `ls *.md \| each { $in.name }` | 遍历列表值 |
| `foreach ($i in 1..10) { $i }` | `for i in 1..10 { print $i }` | 遍历指定范围 |
| `Copy-Item <source> <dest>` | `cp <source> <dest>` | 复制文件 |
| `Copy-Item -Recurse <source> <dest>` | `cp -r <source> <dest>` | 递归复制目录 |
| `Remove-Item <path>` | `rm <path>` | 删除文件 |
| | `rm -t <path>` | 将文件移至回收站 |
| `Remove-Item -Recurse -Force <path>` | `rm -r <path>` | 递归删除目录 |
| `Get-Date "<date>"` | `"<date>" \| into datetime -f <format>` | 解析日期 |
| `"<str>" -replace 'a','b'` | `str replace "a" "b"` | 替换子字符串 |
| `Select-String <pattern>` | `where $it =~ <pattern>` 或 `find <pattern>` | 搜索文本 |
| `Get-Help <command>` | `help <command>` | 查看命令帮助 |
| `Get-Command` | `help commands` | 列出所有命令 |
| `Get-Command "*<string>*"` | `help --find <string>` | 搜索命令 |
| `command1; if ($?) { command2 }` | `command1; command2` | 仅在第一个命令成功时运行第二个命令 |
| `/tmp/$((Get-Random))` | `$"/tmp/(random int)"` | 字符串插值 |
| `$env:Path` | `$env.PATH` 或 `$env.Path` | 显示 PATH |
| `$LASTEXITCODE` | `$env.LAST_EXIT_CODE` | 上一个外部命令的退出码 |
| `$env:PATH += ":/usr/bin"` | `$env.PATH = ($env.PATH \| append /usr/bin)` | 更新 PATH(临时生效) |
| `Get-ChildItem Env:` | `$env` | 列出环境变量 |
| `$env:FOO` | `$env.FOO` | 访问环境变量 |
| `Remove-Item Env:FOO` | `hide-env FOO` | 取消设置环境变量 |
| `Set-Alias s "git status -sb"` | `alias s = git status -sb` | 临时别名 |
| `Get-Command FOO` | `which FOO` | 检查命令 / 别名 / 二进制文件 |
| `powershell -Command "<commands>"` | `nu -c <commands>` | 运行内联管道 |
| `.\script.ps1` | `nu <script file>` | 运行脚本文件 |
| `Get-Location` 或 `$PWD` | `pwd` 或 `$env.PWD` | 显示当前工作目录 |
| `Read-Host` | `let var = input` | 读取用户输入 |
| `Read-Host -AsSecureString` | `let secret = input -s` | 读取私密输入 |

## 按 ESC 键清空命令行缓冲区

在旧版本的 PowerShell 中,支持通过按 ESC 键清空命令行缓冲区。

虽然 Nu 默认并未提供完全一致的按键行为,但你可以在 `config.nu` 中添加快捷键绑定以实现类似的功能:

```nu
$env.config.keybindings ++= [{
name: 'esc_clear'
modifier: 'None'
keycode: 'Esc'
mode: ['Emacs', 'Vi_Normal']
event: {edit: 'Clear'}
}]
```
93 changes: 93 additions & 0 deletions zh-CN/book/debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# 脚本调试

Nushell 内置了脚本调试器。运行 `nu --dap` 会启动一个 [Debug Adapter Protocol](https://microsoft.github.io/debug-adapter-protocol/)(DAP)服务器,VS Code、Neovim 和 Zed 等编辑器正是通过该协议来驱动调试器的。当你的编辑器配置好使用该调试器后,你可以在 `.nu` 文件中设置断点、逐行单步执行脚本并深入管道阶段、查看变量和 `$env`、在脚本暂停时评估表达式,甚至可以沿已执行路径向后单步回溯。

## 配置你的编辑器

编辑器会自行启动 `nu --dap` 并通过进程的标准输入和输出流与其通信,因此它只需知道要运行的命令(`nu`,附带参数 `--dap`)以及要启动哪个脚本。调试器是默认构建的一部分(即 `dap` [Cargo 特性](./installation.md))。

例如,在 Neovim 中配合 [nvim-dap](https://github.com/mfussenegger/nvim-dap) 使用:

```lua
local dap = require('dap')

dap.adapters.nu = {
type = 'executable',
command = 'nu',
args = { '--dap' },
}

dap.configurations.nu = {
{
type = 'nu',
request = 'launch',
name = 'Debug this script',
program = '${file}',
},
}
```

VS Code 则需要一个为 Nushell 注册调试器的扩展,随后从 `launch.json` 中读取相同的启动设置。

调试器在运行脚本前会加载你的 `env.nu` 和 `config.nu`,因此脚本能看到与你的 shell 相同的自定义命令、别名和环境。在参数中添加 `-n`(`args = { '--dap', '-n' }`)可改为从默认配置启动。在解析配置文件期间,[`$nu.is-dap`](./special_variables.md#nu) 的值为 `true`。

### 启动配置项

启动配置支持以下设置项:

| 配置项 | 默认值 | 说明 |
| -------------------- | ------- | -------------------------------------------------------------------------------------------------- |
| `program` | | 待调试的 `.nu` 脚本的绝对路径。必填。 |
| `args` | `[]` | 传递给 `main` 或 `entryPoint` 命令的参数字符串列表。其解析方式与 `nu <script> ...args` 相同。 |
| `cwd` | | 运行脚本的工作目录。 |
| `stopOnEntry` | `false` | 是否在第一行代码运行前暂停。 |
| `entryPoint` | | 在脚本顶层执行完毕后运行的命令,适用于仅定义命令的文件。若未指定且脚本包含 `main`,则运行 `main`。 |
| `timeTravel` | `true` | 记录运行的每一行,以便能够[向后单步回溯](#向后单步回溯)。若为 `false`,则仅记录脚本暂停的位置。 |
| `timeTravelMaxSteps` | `10000` | 保留的记录步数。较早的记录将被丢弃。 |

脚本的运行方式与 `nu <script> ...args` 一致:先执行顶层代码,然后使用 `args` 中的参数执行 `main`,或者执行 `entryPoint` 中指定的命令。

## 断点与单步执行

在某一行设置断点,脚本就会在该行暂停。如果在无法暂停的行(例如注释行)设置断点,断点会自动移至下一行可暂停的代码处。

一行代码通常包含多个步骤。在 `let doubled = ($nums | each {|n| $n * 2 })` 中,`let`、`each` 调用以及闭包体各自独立运行。普通断点会在其中的第一步暂停,随后在闭包体针对每个元素执行时再次暂停。而在特定列设置的*行内断点*(在 VS Code 中为 <kbd>Shift</kbd>+<kbd>F9</kbd>)则仅会在该特定步骤处暂停。

断点还可以是:

- **条件断点**:条件是一个 Nushell 表达式,例如 `$n == 3`,脚本仅在表达式为 `true` 时暂停。
- **日志断点(Logpoints)**:断点不会暂停执行,而是向调试控制台输出一条消息。花括号中的表达式会被求值,例如 `names has {$names | length} items` 会输出 `names has 2 items`。

**运行时错误(Runtime errors)**异常过滤器默认处于开启状态,当某个命令引发错误时(包括会被 `try` 块捕获的错误),调试器会暂停脚本。编辑器会显示该错误的代码和消息。

脚本暂停时,你可以继续执行、单步跳过整行、单步进入命令调用或管道阶段,或者单步跳出当前命令。调用栈(Call Stack)会展示通往当前行的命令和闭包调用层级。

## 检查变量与值

当脚本暂停时,编辑器的变量视图会展示:

- **Locals(局部变量)**:当前作用域内的变量、`$in`,以及 `return`(最后一步的值)。
- **Pipeline(管道值)**:在两个管道阶段的分界处,流入下一个命令的值。
- **Globals(全局变量)**:`$nu` 和 `$env`,包含脚本对环境所做的任何更改。
- **Registers(寄存器)**:求值器的内部工作值,用于查看 Nushell 底层执行细节。
- **Process(进程输出)**:脚本运行的外部命令的最新输出。

嵌套的记录、列表和表格在你展开时会逐级加载,因此在查看内部结构之前,庞大的数据结构不会拖慢任何操作。数据流(Stream)仅作描述而不予读取,因此查看数据流不会消耗其内容。

监视表达式(Watch expressions)、调试控制台以及将鼠标悬停在变量上,都会使用暂停时的值来对 Nushell 表达式求值。它们在脚本状态的副本上运行,因此不会修改脚本的变量。

来自 [`print`](/commands/docs/print.md) 和外部命令的输出会发送到编辑器的调试控制台。脚本没有附加终端,因此外部命令不会接收标准输入。

## 向后单步回溯

Nushell 无法反向执行代码,因此调试器会在每一行记录当时的状态(当 `timeTravel` 开启时,默认开启)。**单步后退(Step Back)**和**反向继续(Reverse Continue)**会沿这些历史记录向后回退,移动到上一行或上一个断点,并展示当时的变量和调用栈。从回退位置向前单步执行会沿着记录向前推进,直至到达最新的执行步骤,随后脚本恢复正常运行。已经执行过的命令不会被撤销:脚本已写入的文件依然保持写入状态。

**重启(Restart)**会在同一个会话中从头再次运行脚本,重新从磁盘读取脚本内容并保留你的断点。

## 使用限制

- 调试器目前只能启动新脚本,无法附加到已在运行的 Nushell 进程。
- 脚本暂停时无法修改变量的值。
- 暂不支持函数断点和命中计数断点。
- 变量视图始终显示最内层的命令或闭包。在调用栈中选择调用方会跳转到其所在行,但变量视图仍保持为最内层帧的状态。
- [`input`](/commands/docs/input.md) 和 [`input list`](/commands/docs/input_list.md) 需要支持调试器提示对话框的客户端。在其他编辑器中,脚本会在提示处等待,并在 10 分钟后失败。`input listen` 在调试器中无法正常工作。
Loading