broot 动词(Verbs)完全指南:选择参数、用户参数与外部命令执行机制

原创2026-09-21 19:04:421,428 阅读
文章标签:开发工具

broot 动词(Verbs)完全指南:选择参数、用户参数与外部命令执行机制

broot 中几乎所有交互动作都由"动词(Verb)"驱动:无论是切换显示模式、删除文件、聚焦目录,还是运行你自定义的脚本。本篇以官方 verbs.md 为核心骨架,结合仓库源码(src/verb/ 目录与 resources/default-conf/verbs.hjson)深入讲解动词的调用方式、选择参数展开、用户参数解析、感叹号面板技巧与自定义配置,读完后你既能熟练使用内置动词,也能写出带参数、带快捷键、甚至跨面板协作的个人命令。

动词的本质:一条可展开的命令模板

在 broot 中,动词是一组"(调用名, 执行体)"的定义:调用名决定你输入什么,执行体决定 broot 做什么。最简单的动词不含参数、与当前选择无关,你只需敲一个空格(或 :),再输入它的开头几个字母,最后回车即可执行。例如输入 :help 打开帮助页,输入 :quit 退出。

动词也可以与当前选择(selection)绑定。比如输入 :p 会执行 :parent 动词——它的作用是聚焦当前选择项的父目录(聚焦一个目录,意味着把它变成当前树的根节点)。

broot 内置了大量动词,全部可以在帮助页中查到。由于动词很多,当你想确认某个功能"有没有对应的动词、快捷键是什么"时,可以直接在帮助页输入过滤模式。例如想看与 stage(暂存区)相关的动词及其快捷键,可以像下面这样过滤:

在帮助页中用模式过滤筛选出与 stage 相关的动词

相关链接:staging-area 暂存区说明。

基于当前选择的动词:{file}、{parent} 等选择参数

最常用的一类动词会读取当前选择项的信息并展开到命令中。文档中给出的经典例子是 rm:

invocation: "rm"
external: "rm -rf {file}"
invocation = "rm"
external = "rm -rf {file}"

{file} 这类占位符在命令执行前由 broot 自动替换为实际路径。基础的选择参数共有六种:

名称 展开为
{file} 当前选择项的完整路径
{parent} 当前选择项父目录的完整路径
{directory} 最近的目录,即 {file} 或 {parent} 中更贴近的那个
{other-panel-file} 另一个面板中当前选择项的完整路径
{other-panel-parent} 另一个面板中当前选择项父目录的完整路径
{other-panel-directory} 另一个面板中的最近目录({file} 或 {parent})

多个选择参数可以在同一条命令中混用。例如内置动词 :copy_to_panel 就是把当前选择复制到另一个面板所在的目录:

invocation: "copy_to_panel"
external: "cp -r {file} {other-panel-directory}"
invocation = "copy_to_panel"
external = "cp -r {file} {other-panel-directory}"

当你输入一个动词时,broot 会立即用当前选择完成参数展开,并把将要执行的完整命令实时显示在状态栏中:

输入 rm 时状态栏实时显示将被执行的完整命令

与过滤模式一样,按 esc 可以清除当前输入的命令。

选择参数展开的实现原理

从源码看,这些展开发生在 execution_builder.rs 的 get_sel_name_standard_replacement 中:{file} 取 sel.path,{parent} 取 path.parent(),{directory} 通过 path::closest_dir 计算最近目录,{root} 取当前树根、{line} 取预览中的选中行号,而 {other-panel-*} 系列则来自 app_state.other_panel_path。也就是说,"另一个面板"只有在确实打开了双面板时才可用——这正是 verb.rs 中 needs_another_panel 字段的由来:只要执行模板里出现了 {other-panel-file} 之类的组,broot 就会要求存在第二个面板,否则会给出 "This verb needs exactly two panels" 的提示。

多选(staging area)时的执行语义

当你在暂存区选中多个文件并调用一个外部命令动词时,broot 默认会对每个选择分别执行一次命令。这是由 exec_pattern.rs 中的 coarity() 决定的:它遍历执行模板中的参数定义,若存在 space-separated 或 comma-separated 合并标志,则命令的"元数"为 Merged(所有选择合并进同一条命令),否则为 PerSelection(每个选择执行一次)。对于需要离开 broot 执行的命令,多选择会触发 external_execution.rs 中的 MULTI_SELECTION_ERROR:"Only verbs returning to broot on end or merging selections can be executed on multi-selection"。

带用户参数的动词:从 mkdir 到任意参数模板

有些动词不仅依赖选择,还需要你输入一个或多个参数。文档用 mkdir 举例(它现在已经是内置动词,不需要写在配置文件里):

invocation: "mkdir {subpath}"
external: "mkdir -p {directory}/{subpath}"
invocation = "mkdir {subpath}"
external = "mkdir -p {directory}/{subpath}"

它的含义是:你在输入框里键入 c/d(作为 {subpath}),若当前选中的是 /a/b/some_file.rs,则创建出来的目录是 a/b/c/d——注意 {directory} 会先展开为选中文件所在目录 /a/b,再把相对路径拼接上去。

在你尚未输入参数时,broot 会用红色提示参数缺失:

缺少参数时 broot 的红色提示

一旦你开始输入参数,broot 就实时计算并展示最终将执行的命令:

输入参数后命令实时展开预览

上图中你并没有输入 mkdir 或它的前缀,而是输入了 md,因为该动词的定义里还包含一行快捷键:

shortcut: "md"
shortcut = "md"

注意:帮助页会列出全部可用动词,包括你在配置文件里自定义的那些。

调用模式其实是正则表达式

很多人以为 invocation 只是简单模板,实际上它会被编译成一个正则。看 invocation_parser.rs 的实现:InvocationParser::new 会把 {name} 形式的组替换为 (?P<name>.+),并包上 ^...$ 作为参数解析正则。这带来两个推论:

  1. 字面量字符需要按正则语法书写,例如要匹配一个点号必须写成 \\.;
  2. 你可以直接用完整正则控制参数格式,例如用 (?P<type>[^.]+) 限制参数不能包含点号。

下面这个官方例子同时用到了"解构式"的双参数与正则转义,它定义了一个 blop 动词:输入 blop myfile.rs 后,先在 {parent} 下创建 rs 目录,再用 nvim 打开 rs/myfile.rs:

{
    invocation: "blop {name}\\.{type}"
    external: "mkdir {parent}/{type} && nvim {parent}/{type}/{name}.{type}"
    from_shell: true
}
[[verbs]]
invocation = "blop {name}\\.{type}"
external = "mkdir {parent}/{type} && nvim {parent}/{type}/{name}.{type}"
from_shell = true

若不想让 type 包含点号,则改为正则形式:

{
    invocation: "blop {name}\\.(?P<type>[^.]+)"
    external: "mkdir {parent}/{type} && nvim {parent}/{type}/{name}.{type}"
    from_shell: true
}
[[verbs]]
invocation = "blop {name}\\.(?P<type>[^.]+)"
external = "mkdir {parent}/{type} && nvim {parent}/{type}/{name}.{type}"
from_shell = true

参数中的空格、引号与路径规范化

输入参数可以包含空格,broot 会智能判断何时需要给路径加引号、何时需要转义,确保命令能正确执行。它还负责把路径规范化,因此相对路径也能正常工作。这一能力对应 exec_pattern.rs 中的 ExecPattern::from_string——它用 splitty::split_unquoted_whitespace 按"未加引号的空白"切分命令为 token,并在需要时还原引号,这正是 conf_verbs.md 中"转义引号"与"数组写法"两种等价形式都能工作的底层原因。

Tab 补全与 <ctrl>p 路径选择

由于支持前缀匹配,输入动词时通常几个字母就够用了——broot 只要确认没有歧义就会锁定目标。但当你自定义了大量同前缀的动词时,歧义就会出现。此时 tab 键可以帮你补全,或列出几种可能的补全候选。

Tab 补全在输入路径参数时更加实用,它的工作方式非常直觉。另外还有一个省时方案:当你对路径不确定时,按 ctrlp 会打开一个新面板,你可以在其中导航并选中目标,再次按 ctrlp 确认(详见面板文档)。

动词的三种类型:内置、外部命令与命令序列

从实现上看,动词的执行方式分为三大类(在 verb.rs 中以 VerbExecution 枚举承载,完整属性见动词配置参考):

  • 内置行为(internal):调用 broot 内部函数,例如 :toggle_perm 触发 Unix 文件权限的显示与计算;
  • 外部命令(external / shell_command):调用外部程序,例如 rm -rf {file};
  • 命令序列(cmd / sequence):一串按顺序执行的命令。

命令执行后可能有两种结局:离开 broot(例如启动一个程序)或不离开(树会被刷新,如创建文件后立即看到更新)。这个"离开与否"在 external_execution.rs 中对应三种执行模式 ExternalExecutionMode:

  • FromParentShell:在父 shell 中执行(必须用 br 启动 broot),典型场景是 cd 这类 shell 内建命令;
  • LeaveBroot:退出 broot 后由新进程执行;
  • StayInBroot:留在 broot 内执行,结束后根据 refresh_after 决定是否刷新树(默认刷新并清空尺寸缓存)。

默认配置文件 resources/default-conf/verbs.hjson 中内置的 terminal 动词就是"留在 broot"的典型:按 ctrlt 启动 $SHELL,退出 shell 后回到 broot 界面。

感叹号:在新面板中执行

动词名后的感叹号 ! 可以把执行结果打开到新面板,而不是替换当前面板。它可以放在动词之前或之后:

命令 结果
:focus! 在新面板中聚焦当前目录
:!help 把帮助页开到你关心的内容
:!focus ~ 在新面板中显示你的主目录

感叹号同样可以写进配置文件里的动词声明中。

自定义动词:配置文件中的完整属性

动词配置是 broot 配置中最重要的一环。一个完整的自定义动词可以是这样的(Hjson / TOML 两种格式等价):

{
	invocation: edit
	key: F2
	shortcut: e
	apply_to: file
	external: "nvim {file}"
	leave_broot: false
}
[[verbs]]
invocation = "edit"
key = "F2"
shortcut = "e"
apply_to = "file"
external = "nvim {file}"
leave_broot = false

全部可用属性如下(默认值与作用来自 conf_verbs.md):

名称 默认值 作用
apply_to 无 该动词适用的选择类型:"file"、"text_file"、"binary_file"、"directory" 或 "any"。可以声明两个同 key 动词,让第一个只作用于文本文件或目录
auto_exec true 通过按键触发时是否立即执行(否则等待 enter)
cmd 无 一段以分号分隔的命令序列,类似传给 --cmd 启动参数的序列
extensions 无 允许的文件扩展名数组,用于按扩展名过滤
external 无 执行体,当动词基于外部命令时使用
run_in_parent_shell false 是否必须在父 shell 中执行(需要 br)。因为是在 broot 退出后执行,所以与 leave_broot = false 不兼容
impacted_panel active 动作作用于哪个面板,可以是 left、right、preview
internal 无 执行体,当动词基于预定义的内置动作时使用
invocation 无 用户如何调用该动词,可含参数占位符
key 无 触发执行的单个按键
keys 无 触发执行的多个按键
leave_broot true 执行时是否退出 broot
panels 全部 可在其中调用该动词的面板类型列表,默认 [tree, fs, preview, help, stage]
set_working_dir false 是否把进程工作目录设为当前选中目录(等价于 working_dir: "{directory}")
shell_command 无 通过 shell 执行(Unix 上为 sh -c,Windows 上为 cmd /C),使 &&、;、管道等语法可用(external 的替代方案)
shortcut 无 调用该动词的别名(不含参数部分)
switch_terminal true 执行期间是否从备用终端切换到普通终端
working_dir 无 外部程序的工作目录,例如 "{directory}"(目录不存在则不设置)

执行体由 internal、external、shell_command 或 cmd 四选一定义(兼容旧版本时也接受 execution,broot 会自动猜测其类型)。

run_in_parent_shell 存在的意义在于:有些动作在子 shell 里毫无用处,例如 cd 是 shell 内建命令,必须在父 shell 中执行。

不离开 broot 的动词

设置 leave_broot = false 后,broot 执行完命令不会退出,而是刷新树。这非常适合创建/移动文件这类改变目录结构的操作,或执行完想回到 broot 的场景。例如默认配置里的 edit 动词就用 nvim {file} 编辑选中文件并留在 broot;默认配置还演示了 git_diff(git difftool -y {file})、create(用 $EDITOR 在目录中新建文本文件)等"留下"型动词。

shell_command 与脚本

external 直接调用可执行文件;如果你想跑 shell 脚本、串联多条命令或使用 shell 特性,必须改用 shell_command,它会把整行命令交给 shell(Unix 为 sh -c,Windows 为 cmd /C)。{directory}、{file} 等占位符仍会先由 broot 填好(含特殊字符的路径会被正确加引号),再交给 shell:

{
    invocation: "mkfile {name}"
    shell_command: "mkdir -p {directory}/foo && touch {directory}/foo/{name}"
    leave_broot: false
}
[[verbs]]
invocation = "mkfile {name}"
shell_command = "mkdir -p {directory}/foo && touch {directory}/foo/{name}"
leave_broot = false

引号的两种写法

如果想让 broot 执行 xterm -e "nvim {file}",可以转义引号,也可以改用数组把各部分分开,二者等价:

{
	invocation: xtv
	external: "xterm -e \"nvim {file}\""
}
[[verbs]]
invocation = "xtv"
external = "xterm -e \"nvim {file}\""
{
	invocation: xtv
	external: ["xterm" "-e" "nvim {file}"]
}
[[verbs]]
invocation = "xtv"
external = ["xterm", "-e", "nvim {file}"]

按扩展名过滤

可以通过 extensions 让同一个按键在不同文件上执行不同动作。例如想让 enter 在大多数情况下保持默认行为,但遇到 rs、js、toml 文件时改用编辑器打开:

{
    name: open-code
    key: enter
    extensions: [
        rs
        js
        toml
    ]
    execution: "$EDITOR +{line} {file}"
    working_dir: "{root}"
    leave_broot: false
}
[[verbs]]
name = "open-code"
key = "enter"
extensions = ["rs", "js", "toml"]
execution = "$EDITOR +{line} {file}"
working_dir = "{root}"
leave_broot = false

动词定义按顺序尝试,先用户定义、后内置,直到某一条被执行——所以你可以同时定义带扩展名过滤的动词和兜底动词。这一点在 verb_store.rs 中得到印证:用户动词先被加入 store,内置动词最后追加,注释明确写着"放在最后以便覆盖它们"。

快捷键与动词查找算法

broot 会取空格或 : 之后的第一个 token 来查找动词,匹配算法如下:

  • 输入内容精确等于某个动词的 shortcut 或名称 → 选中该动词,broot 会提示按 enter 将执行什么;
  • 只有一个动词的名称或 shortcut 以输入内容开头 → 选中它;
  • 有多个动词以输入内容开头 → broot 等待更多输入;
  • 没有任何动词匹配 → broot 提示出错。

理解了这套算法,就能看懂下面这个例子的用意:它给 :parent 起了一个别名 p,从而保证你输入 :p 后按回车时,即使在存在其他 p 开头的动词时也能立即执行:

{
    invocation: p
    internal: ":parent"
}
[[verbs]]
invocation = "p"
internal = ":parent"

常用动词建议配上 shortcut。

按键触发

可以为动词绑定函数键(如 F3)、Ctrl 或 Alt 组合键(如 ctrlT、alta)。也可以纯粹为了给内置动词增加触发键而定义一个动词,例如官方文档中的一组映射:

verbs: [
    {
    	invocation: "root"
    	key: "F9"
    	internal: ":focus /"
    }
    {
    	invocation: "home"
    	key: "ctrl-H"
    	internal: ":focus ~"
    }
    {
    	key: "alt-j"
    	internal: ":line_down"
    }
    {
    	invocation: "top"
    	key: "F6"
    	internal: ":select_first"
    }
    {
    	invocation: "bottom"
    	key: F7
    	internal: ":select_last"
    }
    {
    	invocation: "open"
    	key: ctrl-O
    	internal: ":open_stay"
    }
    {
    	invocation: "edit"
        keys: [
            F2
            ctrl-e
        ]
    	shortcut: "e"
    	external: "$EDITOR +{line} {file}"
    	from_shell: true
    }
]
[[verbs]]
invocation = "root"
key = "F9"
internal = ":focus /"

[[verbs]]
invocation = "home"
key = "ctrl-H"
internal = ":focus ~"

[[verbs]]
key = "alt-j"
internal = ":line_down"

[[verbs]]
invocation = "top"
key = "F6"
internal = ":select_first"

[[verbs]]
invocation = "bottom"
key = "F7"
internal = ":select_last"

[[verbs]]
invocation = "open"
key = "ctrl-O"
internal = ":open_stay"

[[verbs]]
invocation = "edit"
key = [ "F2", "ctrl-e" ]
shortcut = "e"
external = "$EDITOR +{line} {file}"
from_shell = true

效果:altJ 下移选择(注意它连 invocation 都不需要);ctrlH 回到主目录;ctrlO 打开文件但不退出 broot;F7 选中树最后一行;F2 切换到你的编辑器。

需要提醒的是:终端会拦截一部分组合键,很多快捷键在你的终端配置下并不可用;broot 本身也保留了一些按键,例如 enter 在存在输入时总是确认命令,Tab、delete、backspace、esc 均为保留键。按键无效时参见键位组合问题排查。

参数展开全清单:broot 提供的参数

除了选择参数外,broot 还预定义了一批随上下文变化的参数(完整列表见 conf_verbs.md):

名称 展开为
{file} 当前选择项的完整路径
{file-name} 当前选择项的文件名
{file-extension} 当前选择项的扩展名(如 main.rs → rs)
{file-stem} 去掉扩展名后的文件名(如 main.rs → main)
{file-dot-extension} 带点的扩展名(如 .rs),无扩展名则为空串
{line} 预览文件中选中的行号
{parent} 当前选择项父目录的完整路径
{directory} 最近目录,即 {file} 或 {parent}
{other-panel-file} 另一面板中当前选择项的完整路径
{other-panel-parent} 另一面板中当前选择项父目录的完整路径
{other-panel-directory} 另一面板中的最近目录
{root} 当前树根(所显示文件树的顶端)
{initial-root} 启动时的树根
{git-root} 包含当前选择项的 Git 仓库工作目录
{git-name} 当前 Git 仓库工作目录的名称
{file-git-relative} 当前选择项相对其 Git 仓库工作目录的路径;不在仓库中则为绝对路径
{server-name} 启动时 --listen 指定的名字

注意:在帮助页中,{file} 指向配置文件,{directory} 指向配置目录。

这些参数的展开逻辑集中在 execution_builder.rs 的 get_sel_name_standard_replacement 中,{file-stem}、{file-extension}、{file-dot-extension} 分别对应 Rust 的 file_stem()、extension() 等路径 API,{git-root} 则调用 git::workdir 向上查找仓库根。

参数标志:合并选择、锚定路径与主题

参数不仅可以是 {name},还可以带标志写成 {name:flag}。所有可用标志定义在 verb_arg_def.rs 的 VerbArgFlag 中:

  • space-separated / comma-separated:合并标志。在暂存区多选时,把所有选择的值用空格或逗号拼进同一条命令;
  • path-from-directory / path-from-parent:把参数路径锚定到当前目录 / 父目录,用于相对路径解析;
  • theme:参数值为语法高亮主题名。

默认配置里的 zip 动词就是合并标志的实战范例——它要求你输入一个名字,然后把所有暂存的文件/目录用一条命令打包,形如 zip -r some/path/new-archive.zip some/path/file-a some/other/directory:

{
    invocation: "zip {name}"
    external: [
        "zip"
        "-r"
        "{name:path-from-directory}.zip"
        "{file:space-separated}"
    ]
    leave_broot: false
    working_dir: "{root}"
}
[[verbs]]
invocation = "zip {name}"
external = [
    "zip",
    "-r",
    "{name:path-from-directory}.zip",
    "{file:space-separated}",
]
leave_broot = false
working_dir = "{root}"

请求用户输入的动词

动词可以用按键触发,但通过 auto_exec: false 强制用户先输入参数、再按 enter 确认:

{
    name: touch
    key: ctrl-t
    invocation: "touch {new_file}"
    execution: "touch {directory}/{new_file}"
    leave_broot: false
    auto_exec: false
}
[[verbs]]
name = "touch"
key = "ctrl-t"
invocation = "touch {new_file}"
execution = "touch {directory}/{new_file}"
leave_broot = false
auto_exec = false

按 ctrlt 后,broot 会显示调用模式并等待输入。如果调用模式本身不含任何参数、又设置了 auto_exec: false,用户仍必须按 enter 才能执行——这正好用来给破坏性操作加一道确认。默认配置中的 backup 动词(ctrlb)就是 auto_exec: false 的范例。

内置动词(Internals)速查

内置动词是 broot 预定义的动作,你可以为它们添加别名或快捷键,而无需调用外部程序。完整清单见 conf_verbs.md,核心实现在 src/verb/internal.rs 的 Internals! 宏中,每个条目带描述与"是否需要路径"标记。下面按用途归类摘录常用项(默认键位如有则列出):

  • 导航::parent(聚焦父目录)、:up_tree(聚焦当前根的父亲)、:back(left,回到上一状态)、:root_up / :root_down(ctrl↑ / ctrl↓)、:focus
  • 选择移动::line_up / :line_down(↑/↓)、:page_up / :page_down、:select_first / :select_last、:next_dir / :previous_dir、:next_match / :previous_match(tab 绑定 :next_match)、:next_same_depth / :previous_same_depth、:select / :show(按路径选择)
  • 面板::panel_left / :panel_right、:start_end_panel、:toggle_preview、:open_preview、:close_preview、:move_panel_divider、:set_panel_width
  • 打开与执行::open_stay(enter)、:open_leave(altenter)、:open_stay_filter
  • 显示与排序::toggle_files、:toggle_hidden、:toggle_perm、:toggle_counts、:toggle_dates、:toggle_sizes、:toggle_git_status(altg)、:sort_by_size、:sort_by_date、:sort_by_type、:no_sort、:set_max_depth、:set_syntax_theme
  • 暂存区::stage(+)、:unstage(-)、:toggle_stage(ctrlg)、:stage_all_files(ctrla)、:clear_stage、:open_staging_area、:close_staging_area
  • 输出与退出::print_path、:print_relative_path、:print_tree、:copy_path、:quit(ctrlq)、:refresh(F5)、:write_output / :clear_output(写/清空 --verb-output 文件)

需要说明:

  • 任何动词都可以直接用默认 invocation 调用,不强制定义 shortcut;
  • 需要参数(如 {newpath})的动词无法仅靠按键触发。

输入相关的动词

还有一类内部动作直接作用于输入框,只能绑定按键、不能从输入中显式调用:input_clear、input_del_char_left(delete)、input_del_word_left、input_go_to_start(home)、input_go_left(←)等,完整行为见 conf_verbs.md。例如为 Emacs 风格移动光标,可以添加:

{ key: "alt-b", internal: ":input_go_word_left" }
{ key: "alt-f", internal: ":input_go_word_right" }
{ key: "alt-l", internal: ":input_del_word_left" }
{ key: "alt-r", internal: ":input_del_word_right" }
[[verbs]]
key = "alt-b"
internal = ":input_go_word_left"

[[verbs]]
key = "alt-f"
internal = ":input_go_word_right"

[[verbs]]
key = "alt-l"
internal = ":input_del_word_left"

[[verbs]]
key = "alt-r"
internal = ":input_del_word_right"

输入框的粘贴默认绑定 ctrlV,复制与剪切默认不绑定(因为很少在输入框里写长文本),需要时自行添加:

{ key: "ctrl-c", internal: ":input_selection_copy" }
{ key: "ctrl-x", internal: ":input_selection_cut" }
[[verbs]]
key = "ctrl-c"
internal = ":input_selection_copy"
[[verbs]]
key = "ctrl-x"
internal = ":input_selection_cut"

深入 :focus 与 cmd 序列

:focus:万能导航

:focus 用途极广:

  • 不带参数时作用于当前选择,例如 :!focus 等价于 :panel_right(ctrl→ 或 alt→);
  • 带参数时可以直接跳转,例如输入 fo /usr/bin 再回车,不退出 broot 就切到 /usr/bin;
  • 相比 enter,:focus 会保留当前过滤模式;
  • 它还是很多内置命令的基础,例如 :home 的执行体就是 :focus ~(broot 中 ~ 即使在 Windows 上也解释为用户主目录)。

你可以基于它定义自己的导航动词:

{ key: "ctrl-up", internal: ":focus .." }
{ key: "ctrl-d", internal: ":focus ~/dev" }
{
    invocation: "go {path}",
    internal: ":focus {path}"
}
{
    invocation: "gotar {path}",
    internal: ":focus {path}/target"
}
[[verbs]]
key = "ctrl-up"
internal = ":focus .."

[[verbs]]
key = "ctrl-d"
internal = ":focus ~/dev"

cmd:命令序列

cmd 属性可以定义一段序列,类似用 --cmd 启动参数 传入的内容。序列里可以包含搜索、内置动词调用、甚至调用已定义的外部动词。下面这个例子仅对目录生效:复制目录(名字部分来自你的输入),然后在新面板聚焦新目录:

{
    name: "backup"
    invocation: "bu {name}"
    cmd: ":cp {file}-back_{name};:!focus {file}-back_{name}"
    apply_to: directory
}
[[verbs]]
name = "backup"
invocation = "bu {name}"
cmd = ":cp {file}-back_{name};:!focus {file}-back_{name}"
apply_to = "directory"

注意:cmd 执行类型在动词中仍属实验特性,行为可能在未来小版本中调整。

自定义动词的起点:默认配置文件

若想快速上手,直接参考 resources/default-conf/verbs.hjson(默认配置的 verbs 段):其中有可直接使用的 edit、zip、create、git_diff、backup、terminal,以及大量注释掉的示例——tail_lines、touch、用 :trash 覆盖 rm、run_in_parent_shell 的 cpa 与 to_kak、gtr(聚焦当前 Git 仓库根)、Norton Commander 风格的 F5/F6 双面板复制移动等。把它们取消注释、按需修改,就是最好的学习材料。

结语

动词是 broot 强大交互的引擎:选择参数({file}、{parent}、{other-panel-*} 等)让命令天然感知上下文,调用参数({subpath} 等)让命令可交互输入,参数标志(space-separated、path-from-directory 等)处理多选合并与路径锚定,而 internal / external / shell_command / cmd 四种执行体覆盖了从纯内置动作到完整 shell 脚本的全部场景。掌握动词的调用与配置,就等于掌握了 broot 的"可编程操作层"。更多细节可继续阅读动词配置参考与动词查找与快捷键。

登录后查看全文
broot