broot 动词(Verbs)完全指南:选择参数、用户参数与外部命令执行机制
broot 动词(Verbs)完全指南:选择参数、用户参数与外部命令执行机制
broot 中几乎所有交互动作都由"动词(Verb)"驱动:无论是切换显示模式、删除文件、聚焦目录,还是运行你自定义的脚本。本篇以官方 verbs.md 为核心骨架,结合仓库源码(src/verb/ 目录与 resources/default-conf/verbs.hjson)深入讲解动词的调用方式、选择参数展开、用户参数解析、感叹号面板技巧与自定义配置,读完后你既能熟练使用内置动词,也能写出带参数、带快捷键、甚至跨面板协作的个人命令。
动词的本质:一条可展开的命令模板
在 broot 中,动词是一组"(调用名, 执行体)"的定义:调用名决定你输入什么,执行体决定 broot 做什么。最简单的动词不含参数、与当前选择无关,你只需敲一个空格(或 :),再输入它的开头几个字母,最后回车即可执行。例如输入 :help 打开帮助页,输入 :quit 退出。
动词也可以与当前选择(selection)绑定。比如输入 :p 会执行 :parent 动词——它的作用是聚焦当前选择项的父目录(聚焦一个目录,意味着把它变成当前树的根节点)。
broot 内置了大量动词,全部可以在帮助页中查到。由于动词很多,当你想确认某个功能"有没有对应的动词、快捷键是什么"时,可以直接在帮助页输入过滤模式。例如想看与 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 会立即用当前选择完成参数展开,并把将要执行的完整命令实时显示在状态栏中:
与过滤模式一样,按 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 就实时计算并展示最终将执行的命令:
上图中你并没有输入 mkdir 或它的前缀,而是输入了 md,因为该动词的定义里还包含一行快捷键:
shortcut: "md"
shortcut = "md"
注意:帮助页会列出全部可用动词,包括你在配置文件里自定义的那些。
调用模式其实是正则表达式
很多人以为 invocation 只是简单模板,实际上它会被编译成一个正则。看 invocation_parser.rs 的实现:InvocationParser::new 会把 {name} 形式的组替换为 (?P<name>.+),并包上 ^...$ 作为参数解析正则。这带来两个推论:
- 字面量字符需要按正则语法书写,例如要匹配一个点号必须写成
\\.; - 你可以直接用完整正则控制参数格式,例如用
(?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 的"可编程操作层"。更多细节可继续阅读动词配置参考与动词查找与快捷键。



