popup

popup.txt 适用于 Vim 9.2 版本。 最近更新: 2026年2月 VIM 参考手册 by Bram Moolenaar 译者: Willis 在弹出窗口中显示文本。 popup popup-window popupwin 1. 介绍 popup-intro 窗口位置和大小 popup-position 关闭弹出窗口 popup-close 弹出缓冲区和窗口 popup-buffer 弹出窗口中运行终端 popup-terminal 2. 函数 popup-functions 详细说明 popup-function-details 3. 用法 popup-usage popup_create() 参数 popup_create-arguments 弹窗文本属性 popup-props 通过文本属性定位弹窗 popup-textprop-pos 弹窗过滤器 popup-filter 弹窗回调 popup-callback 弹窗滚动条 popup-scrollbar 弹窗不透明度 popup-opacity 弹窗掩码 popup-mask 4. 示例 popup-examples {仅当编译时加入 +popupwin 特性才有效}

1. 介绍 popup-intro

本节所说的弹出窗口,是悬浮在普通窗口上层,由插件全权控制的浮动窗口。不能像普通 窗口一样,直接编辑弹窗文本。 弹窗可用于: - 临时显示信息,不挤占命令行区域 - 弹出交互对话框 - 键入时显示上下文提示信息 - 为自动补全提供额外信息 弹窗文本可用 text-properties 上色。也支持语法高亮。 缺省颜色取自三组高亮组,主体 hl-Popup 、边框 hl-PopupBorder 和标题 hl-PopupTitle 。为后向兼容,这些高亮组缺省都链接到 hl-Pmenu 组。它们可以被 重新定义,调整所有弹窗的外观,与补全弹出菜单有所区分。也可通过 "highlight" 参 数或 'wincolor' 选项单独设置单个弹窗的外观,例如: hi MyPopupColor ctermbg=lightblue guibg=lightblue call setwinvar(winid, '&wincolor', 'MyPopupColor') 弹窗中不显示 'hlsearch' 高亮。 弹窗和其他窗口一样,有自己的窗口 ID,但行为特殊。最大可以铺满整个 Vim 窗口,能 够覆盖其他窗口,弹窗间也能互相堆叠。堆叠层级由 "zindex" 属性控制。 E366 弹窗绑定专属缓冲区,也无法使用普通、可视或插入模式,不会接收键盘焦点。只能用 setbufline() 等函数修改专属缓冲区文本。弹窗及专属缓冲区还有更多有异于普通窗 口及缓冲区的行为,见 popup-buffer 。 如果弹窗功能不合所需,可查阅其他弹出机制: - 弹出菜单,见 popup-menu - 气泡,见 balloon-eval 窗 口 位 置 和 大 小 popup-position 弹窗高度默认等于缓冲区回绕后的行数。可由 "maxheight" 属性限制最大高度。可用插 入空行或 "minheight" 属性增加高度。 弹窗宽度默认等于缓冲区最长可见行长度。可由 "maxwidth" 属性限制最大宽度。可用补 空格或 "minwidth" 属性增加宽度。 缺省置位 'wrap' 选项,保证文本信息不会丢失。否则,如果空间不足,窗口会自动左移 以显示更多内容。右对齐窗口则会自动右移以显示更多内容。可设置 "fixed" 属性关闭 自动移位。 Vim 试图在指定位置显示弹窗。一旦弹窗可能会超出 Vim 主窗口边界,会自动就近显 示。例如, popup_atcursor() 通常在光标正上方显示弹窗,但如果光标靠近 Vim 窗口 顶部,会自动改为在光标下方放置。 Ex 命令输出导致屏幕向上滚动时,弹窗会跟随移动,避免遮挡命令输出。 光标即使被弹窗遮挡,仍然会显示。以便看清光标位置,但无法看到其所在文本。 关 闭 弹 出 窗 口 popup-close 通常逻辑是创建弹窗的插件负责自行关闭窗口。如果弹窗因故滞留,可关闭所有弹窗: call popup_clear(1) 通知等类型的弹窗会在指定时间后自动关闭。可在 popup_create() 中通过 "time" 属 性设置自动关闭时间。 未设置该属性的弹窗可设置 "close" 属性,控制手动关闭方式: 点击右上角 X、或点击 弹窗内部任意位置关闭弹窗。通知类弹窗 (见 popup_notification() ) 缺省已设置此 属性。 弹 出 缓 冲 区 和 窗 口 popup-buffer 调用弹窗创建函数时,如果直接传入文本内容,会创建新缓冲区保存文本与文本属性。此 缓冲区永久绑定本弹窗,且有诸多操作限制: - 无缓冲区名称 - 'buftype' 为 "popup" - 'swapfile' 关闭 - 'bufhidden' 为 "hide" - 'buflisted' 关闭 - 'undolevels' 为 -1: 完全禁用撤销 - 其他缓冲区局部和窗口局部选项均设为 Vim 缺省值。 虽然可以手动修改上列选项,但无法保证工作正常,建议保留原有设置。 弹窗本身具有光标位置,但不会显示。屏幕上显示的仍是底层窗口的光标,就像穿透弹窗 一样,方便用户看到实际文本的操作位置。 要在弹出窗口和缓冲区的上下文中执行命令,可用 win_execute() 。例如: call win_execute(winid, 'syntax enable') 要修改窗口选项,可用 setwinvar() ,例如: call setwinvar(winid, '&wrap', 0) 要修改缓冲区选项,可用 setbufvar() ,例如: call setbufvar(winbufnr(winid), '&filetype', 'java') 另一种方案是用 win_execute() 执行 :setlocal 命令。 弹 出 窗 口 中 运 行 终 端 popup-terminal 在弹窗中运行终端是个特例。许多规则会有变化: E863 - 终端窗口强制占据焦点,无法切换到其他窗口。 - 作业结束后,弹窗停留在终端-普通模式。可用 :q 关闭,或设置 "term_finish" 值 "close" 使作业结束后自动关闭 (见 term_start() )。 - 可用 popup_close() 关闭弹窗,终端缓冲区此时会被隐藏。 - 不可打开第二个终端弹窗。 E861 - 缺省 hl-Pmenu 色彩仅用于边框和内边距。要修改终端内部颜色,必须在创建终端前 先设置 hl-Terminal 高亮组。事后修改 'winhighlight' 也可生效,但需要终端内 程序全屏重绘。 - 缺省最小尺寸为 5 行 20 列;可通过 "minwidth" 和 "minheight" 参数自定义。 - 终端内程序输出文本时终端会自动扩容。可通过 "maxheight" 和 "maxwidth" 参数限 制最大尺寸。 要在弹窗中运行终端,可先创建隐藏终端,再将缓冲区号传给 popup_create()。示例: hi link Terminal Search let buf = term_start(['picker', 'Something'], #{hidden: 1, term_finish: 'close'}) let winid = popup_create(buf, #{minwidth: 50, minheight: 20})

2. 函数 popup-functions

弹窗创建函数: popup_create() 在屏幕中央创建弹窗 popup_atcursor() 在光标正上方创建弹窗,光标移开时自动关闭 popup_beval() 在鼠标位置上 (由 v:beval_ 系列变量记录) 创建弹 窗,鼠标移开时自动关闭 popup_notification() 弹出通知,默认停留三秒 popup_dialog() 创建居中弹窗,自带内边距和边框 popup_menu() 创建弹出菜单,供用户从列表中选择一项 弹窗操作函数: popup_hide() 临时隐藏弹窗 popup_show() 恢复显示之前隐藏的弹窗 popup_move() 修改弹窗位置与大小 popup_setoptions() 覆盖弹窗选项 popup_settext() 替换弹窗缓冲区全部文本 popup_setbuf() 为弹窗绑定新缓冲区 弹窗关闭函数: popup_close() 关闭单个弹窗 popup_clear() 关闭所有弹窗 弹窗过滤函数: popup_filter_menu() 从一列项目中选择 popup_filter_yesno() 等待直到按下 'y' 或 'n' 为止 其他工具函数: popup_getoptions() 获取弹窗当前选项值 popup_getpos() 获取弹窗实际位置和大小 popup_locate() 根据屏幕坐标查找弹出窗口 popup_list() 获取所有弹窗列表 详 细 说 明 popup-function-details popup_atcursor({what}, {options}) popup_atcursor() 在光标正上方创建弹窗显示 {what},光标移开时自动关闭。相当于: call popup_create({what}, #{ \ pos: 'botleft', \ line: 'cursor-1', \ col: 'cursor', \ moved: 'WORD', \ }) 可用 {options} 覆盖缺省属性。 将 "pos" 设为 "topleft" 时,"line" 的缺省自动变为 "cursor+1"。 返回窗口 ID。详见 popup_create() 。 也可用作 method : GetText()->popup_atcursor({}) 返回类型: Number popup_beval({what}, {options}) popup_beval() 在悬停求值 ('ballooneval') 的鼠标位置上方创建弹窗显示 {what}, 鼠标移开时自动关闭。相当于: let pos = screenpos(v:beval_winnr, v:beval_lnum, v:beval_col) call popup_create({what}, #{ \ pos: 'botleft', \ line: pos.row - 1, \ col: pos.col, \ mousemoved: 'WORD', \ }) 可用 {options} 覆盖缺省属性。 示例代码可见 popup_beval_example 。 返回窗口 ID。详见 popup_create() 。 也可用作 method : GetText()->popup_beval({}) 返回类型: Number popup_clear() popup_clear([{force}]) 用于插件异常的紧急方案: 关闭当前标签页内所有弹窗以及全局弹窗。 不调用任何弹窗的关闭回调。 省略 {force} 时,如果当前窗口为弹窗,操作失败。 给出 {force} 且为 TRUE 时,即使当前窗口为弹窗也强制关闭。 弹窗中有仍在运行的终端作业时,也会一并终止。 返回类型: 无 popup_close({id} [, {result}]) popup_close() 关闭弹窗 {id}: 删除窗口。弹窗创建的新缓冲区也会被一并删除。 弹窗删除前,会调用关闭回调 (如有)。可选 {result} 给出时,会作 为传入回调的第二个参数。省略时默认传入零值。 也可用作 method : GetPopup()->popup_close() 返回类型: 无 popup_create({what}, {options}) popup_create() 创建弹出窗口以显示 {what}{what} 支持以下类型: E450 - 已有缓冲区编号 - 字符串 - 字符串列表 - 带文本属性的文本行列表 {what} 不属于缓冲区编号时,会新建 'buftype' 为 "popup" 的专属 缓冲区。弹窗关闭后,该缓冲区会被真正删除。 {what} 是已有缓冲区编号且该缓冲区存在交换文件时,以只读方式静 默打开,相当于 SwapExists 自动命令将 v:swapchoice 设为 'o' 的效果。这是因为设计初衷是弹窗仅用于查看而非修改缓冲区内容。 缓冲区号不允许引用正在关闭的缓冲区。 E1551 {options} 为包含众多配置的字典。见 popup_create-arguments 。 操作成功时,返回窗口 ID,供后续弹窗函数调用。要获取窗口绑定的 缓冲区号,可用 winbufnr() : let winid = popup_create('hello', {}) let bufnr = winbufnr(winid) call setbufline(bufnr, 2, 'second line') 如果处理失败,返回零。 也可用作 method : GetText()->popup_create({}) 返回类型: Number popup_dialog({what}, {options}) popup_dialog() 创建居中对话框,自带内边距和边框。相当于: call popup_create({what}, #{ \ pos: 'center', \ zindex: 200, \ drag: 1, \ border: [], \ padding: [], \ mapping: 0, \}) < 可用 {options} 覆盖缺省属性。例如,将 "filter" 属性设为 'popup_filter_yesno',并设置回调处理按键。示例: call popup_create('do you want to quit (Yes/no)?', #{ \ filter: 'popup_filter_yesno', \ callback: 'QuitCallback', \ }) 返回窗口 ID。详见 popup_create() 。 < 对话框缺省可用鼠标拖动,方便查看下方被遮挡的文本。 也可用作 method : GetText()->popup_dialog({}) 返回类型: Number popup_filter_menu({id}, {key}) popup_filter_menu() 弹出专用按键过滤器。假定缓冲区每行对应一项。支持以下按键: j <Down> <C-N> 选中下一项 k <Up> <C-P> 选中上一项 <Space> <Enter> 确认当前选中项 x Esc CTRL-C 取消菜单 忽略其余按键。 总是返回 v:true 。 选中行会自动使用匹配高亮,见 popup_menu() 。 按下确认键后,调用弹窗关闭回调 "callback",第二个参数为选中项 编号。首项索引为一。 按下取消键后,调用同一回调,第二个参数值为 -1。 要新增快捷键,可参考示例: popup_menu-shortcut-example 返回类型: Number popup_filter_yesno({id}, {key}) popup_filter_yesno() 弹出专用按键过滤器。响应以下按键: 'y'、'Y'、'n' 和 'N'。按键后 调用弹窗关闭回调 "callback",第二个参数当按下 'y' 或 'Y' 时为 1,按下 'n' 或 'N' 时为零。此外,按下 Esc 和 'x' 等同于按下 'n'。而按下 CTRL-C 会使第二个参数值为 -1。忽略其余按键。 示例可见: popup_dialog-example 返回类型: vim9-boolean popup_findecho() popup_findecho() 寻找执行 :echowindow 命令时消息弹窗的 window-ID 。找不到则 返回零。 主要用于获取 ID 后临时隐藏该弹窗。 返回类型: Number popup_findinfo() popup_findinfo() 寻找补全信息弹窗的 window-ID ,见 complete-popup 。信息弹窗 闲置时会自动隐藏,可用 popup_clear()popup_close() 删 除。可用 popup_show() 在弹出菜单对应条目旁重新显示。 找不到则返回零。 返回类型: Number popup_findpreview() popup_findpreview() 寻找预览弹窗的 window-ID 。 找不到则返回零。 返回类型: Number popup_getoptions({id}) popup_getoptions() 以字典形式返回弹窗 {id}{options}。 零值代表对应属性未手动设置。"zindex" 例外,返回非零缺省值。 "moved" 项为包含行号、最小列号和最大列号的列表,未设置时则是 [0, 0, 0]。 "mousemoved" 项为包含屏幕行号,最小屏幕列号,最大屏幕列号的列 表。未设置时则是 [0, 0, 0]。 "firstline" 是弹窗选项里设置的属性,与 popup_getpos() 获取的 "firstline" 不同,后者是窗口顶部实际缓冲区行号。 "border" 和 "padding" 的值全为零时,字典里会省略该项。全为一时 则包含空列表。 "borderhighlight" 的值全为空时,字典里会省略该项。 "scrollbarhighlight" 和 "thumbhighlight" 仅在属性被手动设置时 才会加入字典。 "tabpage" 在全局弹窗上的值为 -1,在当前标签页弹窗上的值为零, 在其他标签页弹窗上的值是正数。 "textprop"、"textpropid" 和 "textpropwin" 仅当弹窗选项里设置 "textprop" 时才存在。 如果找不到弹出窗口 {id},返回空字典。 也可用作 method : GetPopup()->popup_getoptions() 返回类型: dict<any> popup_getpos({id}) popup_getpos() 以字典形式返回弹窗 {id} 的实际位置和大小,包含以下条目: col 弹窗所在屏幕列号,从一开始 line 弹窗所在屏幕行号,从一开始 width 弹窗总宽度 (以屏幕单元格为单位) height 弹窗总高度 (以屏幕单元格为单位) core_col 文本框 (排除边框和内边距) 左上角屏幕列号 core_line 文本框左上角屏幕行号 core_width 文本框总宽度 (以屏幕单元格为单位) core_height 文本框总高度 (以屏幕单元格为单位) firstline 窗口顶部对应缓冲区行号 (除非滚动过,缺省为 1) (和 "firstline" 属性值不同) lastline 窗口底部对应缓冲区行号 (弹窗重绘时会刷新) scrollbar 非零代表显示滚动条 visible 为一代表弹窗可见,为零代表隐藏 注意 以上是实际屏幕位置。经过相关大小和定位自动修正,和 popup_getoptions() 的原始设置值未必一致。 "core_" 条目计算时排除内边距和边框,仅代表文本区域。 如果找不到弹出窗口 {id},返回空字典。 也可用作 method : GetPopup()->popup_getpos() 返回类型: dict<number> 或 dict<any> popup_hide({id}) popup_hide() 弹窗 {id} 当前处于显示状态时,将其临时隐藏。弹窗隐藏期间,暂不 触发已有过滤器。 如果找不到弹出窗口 {id},不作任何处理。如果窗口 {id} 存在但不 是弹窗,报错。 E993 弹窗 {id} 内如果运行终端,无法隐藏并报错 ( popup-terminal )。 也可用作 method : GetPopup()->popup_hide() 返回类型: 无 popup_list() popup_list() 返回当前所有弹窗的 window-ID 列表。 返回类型: list<number> 或 list<any> popup_locate({row}, {col}) popup_locate() 根据屏幕位置 {row}{col} 寻找弹窗 window-ID 。该位置有多个 弹窗堆叠时,返回最高 zindex 的弹窗 ID。如果该位置无弹窗,返回 零。 返回类型: Number popup_menu({what}, {options}) popup_menu() 在光标附近弹出选择列表 {what},用光标键切换条目,用 Space 或 Enter 选中后自动关闭窗口。{what} 应传入多行才能实际发挥作用。 相当于: call popup_create({what}, #{ \ pos: 'center', \ zindex: 200, \ drag: 1, \ wrap: 0, \ border: [], \ cursorline: 1, \ padding: [0,1,0,1], \ filter: 'popup_filter_menu', \ mapping: 0, \ }) 选中行使用 hl-PopupSelected 高亮,缺省链接到 hl-PmenuSel 。 < 可用 {options} 覆盖缺省属性。至少要设置 "callback",以处理选中 结果。示例: func ColorSelected(id, result) " 根据选中条目序号 a:result,进行处理 endfunc call popup_menu(['red', 'green', 'blue'], #{ \ callback: 'ColorSelected', \ }) 返回窗口 ID。详见 popup_create() 。 < 也可用作 method : GetChoices()->popup_menu({}) 返回类型: Number popup_move({id}, {options}) popup_move() 移动弹窗 {id}{options} 指定的位置,也可同时修改弹窗大小。 {options} 可用 popup_create() 里弹窗位置与尺寸的相关属性: line col pos maxheight minheight maxwidth minwidth fixed {id} 相关检查可见 popup_hide() 要设置其他属性,请见 popup_setoptions() 。 也可用作 method : GetPopup()->popup_move(options) 返回类型: 无 popup_notification({what}, {options}) popup_notification() 在 Vim 窗口顶部弹出通知消息 {what},默认停留 3 秒后自动消失。 相当于: call popup_create({what}, #{ \ line: 1, \ col: 10, \ minwidth: 20, \ time: 3000, \ tabpage: -1, \ zindex: 300, \ drag: 1, \ highlight: 'WarningMsg', \ border: [], \ close: 'click', \ padding: [0,1,0,1], \ }) 使用 hl-PopupNotification 高亮,缺省链接到 hl-WarningMsg 。 编译时如果未开启 +timers 特性,弹窗不会自动消失。用户要手动 点击关闭。 弹窗位置会自动微调,避免多条通知互相遮挡。 可用 {options} 覆盖缺省属性。 < 返回窗口 ID。详见 popup_create() 。 也可用作 method : GetText()->popup_notification({}) 返回类型: Number popup_setbuf({id}, {buf}) popup_setbuf() 为弹窗 {id} 绑定新缓冲区 {buf}{buf} 参数用法见 bufname() 函数。 窗口大小和位置会自动适配新缓冲区文本尺寸。 成功更换缓冲区则返回 v:true ,否则返回 v:false 。 也可用作 method : GetPopup()->popup_setbuf(bufnr('foobar')) 返回类型: vim9-boolean popup_setoptions({id}, {options}) popup_setoptions() {options} 字典里的条目覆盖弹窗 {id} 的现有属性。 可修改的属性有: border borderchars borderhighlight callback close cursorline drag filter firstline flip highlight mapping mask moved padding resize scrollbar scrollbarhighlight thumbhighlight time title wrap zindex 也可修改 popup_move() 里的位置和大小属性。 大多数属性设为零或空串时,会复位属性为其缺省值,但有少量例外。 不能直接修改 "hidden",请用 popup_hide()popup_show() 。 不能修改 "tabpage"。 也可用作 method : GetPopup()->popup_setoptions(options) 返回类型: 无 popup_settext({id}, {text}) popup_settext() 更新弹窗 {id} 缓冲区的文本。{text} 为弹窗中要显示的字符串或字 符串列表。 除非因文本内容变化需要,否则不会影响窗口大小或位置。 也可用作 method : GetPopup()->popup_settext('hello') 返回类型: 无 popup_show({id}) popup_show() 重新显示已隐藏弹窗 {id}{id} 来自 popup_create() 的返回值。 弹窗当前处于隐藏状态时,重新显示。要隐藏窗口,可用 popup_hide(){id} 指向补全信息弹窗时,会自动对齐到弹出菜单当前选中项旁。 如果找不到弹出窗口 {id},返回 -1。成功则返回 0。 返回类型: Number

3. 用法 popup-usage

POPUP_CREATE() 参 数 popup_create-arguments popup_create() 的首个参数 (也用于 popup_settext() 的第二个参数) 指定要显示 的弹窗文本,以及可选文本属性。支持四种形式: E1284 - 缓冲区号 - 字符串 - 字符串列表 - 字典列表,其中每个字典项包含以下条目: text 要显示的文本字符串 props 可选文本属性列表。 每个属性项又是字典,格式见 prop_add() 第三个参数,但 本字典中列用 "col" 项指定,见下: popup-props 。 如果要自行创建缓冲区,先用 bufadd() ,再把缓冲区号传给 popup_create()。 popup_create() 的第二个参数为属性字典: line 弹窗定位的屏幕行。支持绝对数值 (首行编号为 1),也可用 "cursor"、"cursor+1" 或 "cursor-1" 来指定光标所在行并 加减行偏移。省略或为零时,弹窗会垂直居中。 给出 "textprop" 时本值为相对于文本属性位置,可为负数。 col 弹窗定位的屏幕列。支持绝对数值 (首列编号为 1),也可用 "cursor"、"cursor+9" 或 "cursor-9" 来指定光标所在列并 加减列偏移。省略或为零时,弹窗会水平居中。 给出 "textprop" 时本值为相对于文本属性位置,可为负数。 pos 可用值 "topleft"、"topright"、"botleft" 或 "botright": 用于定义 "line" 和 "col" 对应弹窗的哪个角。不指定时默 认使用 "topleft"。 此外,还可用 "center" 将弹窗居中在整个 Vim 窗口,此时 忽略 "line" 和 "col"。 posinvert 为 FALSE 时严格遵守 "pos" 值设置。为 TRUE (缺省) 时, 如果弹窗无法在 "pos" 指定一侧完全显示,而在垂直方向另 一侧有更多可用空间,会在 "line" 行另一侧显示弹窗。 textprop 文本属性类型名,给出时弹窗会紧贴该类型的文本属性,并跟 随其移动。设为空串取消绑定。 详见 popup-textprop-pos 。 textpropwin 限定搜索文本属性的窗口。省略或无效值时使用当前窗口。仅 配合 "textprop" 生效。 textpropid 配合 "textprop",用于根据属性 id 精准匹配唯一文本属 性。设为零解除绑定。 clipwindow 仅配合 "textprop" 生效。为 TRUE 时,弹窗被限制在文本属 性所属窗口内: 一旦文本属性滚动到窗口的上、下、左、右边 缘之外,弹窗会在相应边缘处被裁剪,而不是继续绘制到窗口 外。当文本属性完全滚出窗口后,弹窗会被隐藏。 缺省为 FALSE,不裁剪。详见 popup-clipwindow 。 fixed 为 FALSE (缺省) 时,如果: - "pos" 为 "botleft" 或 "topleft",且 - 弹窗在屏幕右侧边缘被截断,那么 弹窗会自动向左平移,保证内容能够完整显示。设为 TRUE 关 闭自动左移。 flip 为 TRUE (缺省) 时,基于光标定位的弹窗会自动翻转到光标 下方或上方,防止和补全菜单 popupmenu-completion 或层 级 "zindex" 更高的弹窗重叠。如果光标上下都没有足够空 间,则把弹窗与补全菜单或其他弹窗并排。 {尚未实现} maxheight 内容最大高度,边框和内边距不计在内。 minheight 内容最小高度,边框和内边距不计在内。 maxwidth 内容最大宽度,边框、内边距和滚动条不计在内。 minwidth 内容最小宽度,边框、内边距和滚动条不计在内。 firstline 窗口顶部显示的缓冲区首行行号。大于一时,效果是文本向上 滚动。如果越界,缓冲区末行会置顶。设为零则保留命令缺省 位置。另见 "scrollbar"。 hidden 为 TRUE 时,弹窗正常创建但缺省隐藏;后续可用 popup_show() 恢复显示。 tabpage 为 -1 时: 全局弹窗,在所有标签页上都可见。 为 0 (缺省) 时: 仅在前标签页上可见。 否则,仅在指定编号的标签页上可见;如果编号非法,创建弹 窗失败且报错。 E997 title 弹窗标题,显示在弹窗首个项目上方的,位于边框顶部。如果 没有顶部边框,会自动新增一行内边距放置标题。建议在标题 首尾手动填充空格调整位置。 给出 "borderhighlight" 时,标题使用顶部边框高亮,其次 检查 'highlight'/'winhighlight' 是否覆盖相应设置,最后 缺省使用 hl-PopupTitle 高亮。 wrap 为 TRUE (缺省) 时,开启行回绕。 drag 为 TRUE 时,可用鼠标拖动弹窗边框。无边框时无效。一旦开 始拖动,如果 "pos" 原本为 "center",会被自动改为 "topleft"。 dragall 为 TRUE 时,窗口任意位置都可用鼠标拖动。此时要在弹窗里 选择文本就会很困难。 resize 为 TRUE 时,可用鼠标拖动右下角调整大小。无边框时无效。 close 为 "button" 时,在窗口右上角绘制关闭按钮 X (该位置可位 于边框、内边距或文本之上)。点击 X 时关闭弹窗。执行回调 函数,第二个参数为 -2。 为 "click" 时,在弹窗上任意点击都可关闭。 为 "none" (缺省) 时,鼠标点击不会关闭。 highlight 文本高亮组名,在 'wincolor' 选项里保存。 highlights 高亮组覆盖,在 'winhighlight' 选项里保存 (格式相同)。 opacity 弹窗的不透明度,取值范围 0 到 100: 0 表示完全透明 (背景文字完全可见) 100 表示完全不透明 (缺省,无透明效果) 中间值会将弹出窗口背景与下方文字混合,实现半透明。 需要开启 'termguicolors' 才能生效。 详见 popup-opacity 。 padding 数值列表,定义弹窗上/右/下/左内边距 (和 CSS 类似)。 空列表等价于四周内边距均为 1。内边距区域包围文本,而在 边框之内。内边距使用 'wincolor' 高亮。 示例: [1, 2, 1, 3] 上方 1 行,右侧 2 列,下方 1 行和左 侧 3 列内边距。 border 数值列表,定义弹窗上/右/下/左边框宽度 (和 CSS 类似)。 目前仅区别零值和非零值。空列表代表四周均有边框。 borderhighlight 边框高亮组名列表。只写一项时,同时用于四边边框。否则应 分别列出上/右/下/左边的高亮组。 示例: ['顶边色', '右边色', '底边色', '左边色'] borderchars 边框字符列表,分别对应上/右/下/左边框字符。可选后跟左 上/右上/右下/左下角字符。 示例: ['-', '|', '-', '|', '┌', '┐', '┘', '└'] 列表只有一个字符时,用于所有边框位置。 列表只有两个字符时,前者用于边框线,后者用于四角。 'encoding' 为 "utf-8" 且 'ambiwidth' 为 "single" 时缺 省使用双线框,否则缺省使用 ASCII 单线字符 ('-'、'|'、 '+')。 scrollbar 为 1 或真 (缺省) 时: 内容溢出时自动显示滚动条。 为零时: 始终不显示滚动条。详见 popup-scrollbar 。 scrollbarhighlight 滚动条高亮组名。只应用其背景色。省略时默认为 hl-PmenuSbar 。 thumbhighlight 滚动条拇指高亮组名。只应用其背景色。省略时默认为 hl-PmenuThumb 。 zindex 弹窗堆叠层级,缺省为 50。最小值是 1,最大值是 32000。 mask 定义弹窗局部透明区域。包含坐标的二维列表。详见 popup-mask 。 time 自动关闭计时,以毫秒为单位。省略时必须手动调用 popup_close() 关闭窗口。 moved 光标移动时触发自动关闭的方式: - "any": 光标有任意移动就关闭 - "word": 光标跳出 <cword> 范围就关闭 - "WORD": 光标跳出 <cWORD> 范围就关闭 - "expr": 光标跳出 <cexpr> 范围就关闭 - [{start}, {end}]: 光标移出当前行 [{start},{end}] 列 范围 (包含) 就关闭 - [{lnum}, {start}, {end}]: 光标移出第 {lnum} 行 [{start},{end}] 列范围 (包含) 就关闭 - [0, 0, 0] (缺省) 光标移动时不触发关闭 光标移动到另一行或另一窗口时也关闭弹窗。 mousemoved 类似 "moved",但指的是鼠标指针位置 cursorline 为 TRUE 时: 高亮当前光标 (选中) 行。自动滚动文本使该行 可见 (仅当 'wrap' 关闭时才能正确工作)。 为零时: 不高亮光标行。 缺省为零,但 popup_menu() 缺省开启。 filter 按键过滤回调 (过滤器),详见 popup-filter 。 mapping 是否支持键映射。为 FALSE 时,如果弹窗可见且绑定 "filter" 时,按键暂时不经映射。缺省值为 TRUE。 filtermode 过滤器生效的模式 (标志位同 hasmapto() ,外加 "a"): n 普通模式 v 可视和选择模式 x 可视模式 s 选择模式 o 操作符等待模式 i 插入模式 l 语言参数模式 ( rft 等) c 命令行模式 a 全部模式 缺省模式是 "a"。 callback 弹窗关闭时触发的回调,配合 popup_filter_menu() 等过 滤器使用。详见 popup-callback 。 弹窗的上下堆叠顺序由 "zindex" 决定。自动补全菜单 ( popup-menu ) 使用固定 zindex 值 100。临时消息通知类弹窗建议使用 zindex 值 1000。 文本缺省打开回绕,{lines} 里单行可能占据多行显示。"wrap" 为 FALSE 时,超出弹窗 宽度或 Vim 窗口边界的文本会被截断,无法显示。 弹 窗 文 本 属 性 popup-props 用法类似 prop_add() 的第三个参数 {props},但有以下区别: - "lnum" 固定为列表的当前行,无须额外填写 - "bufnr" 固定为弹窗绑定的缓冲区 - "col" 固定为当前列,直接写在字典内,无须额外填写 可用字段总结: col 起始列号,以字节为单位,首列编号为一。 length 文本字节长度;可为零 end_lnum 文本结束行号 end_col 文本结束后一列的列号;"length" 给出时,不用此字段;和 "col" 相等代表零宽度文本属性 id 用户定义的属性 ID;省略时默认为零 type 文本属性类型名,需事先通过 prop_type_add() 注册 通 过 文 本 属 性 定 位 弹 窗 popup-textprop-pos 将弹窗绑定文本属性后,窗会紧贴该类型的文本属性,并跟随其移动。弹窗实现工具提示 效果。 具体需要三步: - 注册文本属性类型,定义类型名。 call prop_type_add('popupMarker', {}) - 在所需文本上放置文本属性: let lnum = {文本行号} let col = {文本起始列号} let len = {文本长度} let propId = {自定义属性编号,但必须唯一} call prop_add(lnum, col, #{ \ length: len, \ type: 'popupMarker', \ id: propId, \ }) - 创建弹窗并绑定文本属性: let winid = popup_create('the text', #{ \ pos: 'botleft', \ textprop: 'popupMarker', \ textpropid: propId, \ border: [], \ padding: [0,1,0,1], \ close: 'click', \ }) 弹窗缺省定位锚点在文本属性的一角,和弹窗的 "pos" 属性刚好相反。例如弹窗使用 "botleft" 时,弹窗左下角会对齐文本属性右上角: +----------+ | 弹窗文本 | +----------+ just some 文本属性 as an example 这里 "文本属性" 文本上放置了文本属性。给 popup_create() 传递负 "col" 值可向 左平移弹窗。例如,用 "col: -5" 会得到: +----------+ | 弹窗文本 | +----------+ just some 文本属性 as an example 文本属性完全滚出窗口后,弹窗会被隐藏。定义文本属性的窗口被关闭后,弹窗也会随之 关闭。 目标位置放不下弹窗时,会自动就近显示。 文 本 属 性 弹 窗 宿 主 窗 口 裁 剪 popup-clipwindow 弹窗锚定分割窗口内的文本属性时,缺省以整个屏幕为坐标系绘制,弹窗内容可能会溢出 包含文本属性的窗口 (宿主窗口) 边界。将 "clipwindow" 设为 TRUE 后,弹窗会严格限 制在宿主窗口可视区域内,超出部分直接被裁剪;一旦文本属性完全滚出窗口边界,弹窗 自动隐藏。 示例: 弹窗固定显示在光标上方,禁止向下溢出到下方分割窗口: call popup_create(body, #{ \ textprop: 'marker', \ textpropid: id, \ pos: 'topleft', \ line: -1, col: 0, \ posinvert: v:false, \ clipwindow: v:true, \ }) "posinvert" 缺省开启,空间不足时弹窗会自动翻转到文本属性的另一侧。要强制保持在 指定一侧,关闭 "posinvert" 并依靠 "clipwindow" 裁剪溢出内容。 一些提示: - 为避免和其他插件冲突,文本属性类型名必须唯一。也可配合 "bufnr" 项使属性局部 于指定缓冲区。 - 同一文本属性类型只有一个可见时,可以省略指定属性 ID。 - 弹窗容易干扰用户操作,如上例所示,建议开启点击关闭功能。 - 移除文本属性时,弹窗会自动关闭。用法如下: call prop_remove(#{type: 'popupMarker', id: propId}) 弹 窗 过 滤 器 popup-filter 弹窗显示期间,此回调接收所有键盘输入。弹窗隐藏时不调用过滤器。 过滤返回 TRUE 时,指示按键已经处理完毕,Vim 不再继续处理该按键,而返回 FALSE 时,指示过滤器不处理该按键,交给 Vim 正常处理。多弹窗叠加时,优先调用 zindex 层级最高的弹窗过滤器,如果返回 FALSE 再交给下层弹窗的过滤器。 过滤函数接受两个参数: 弹窗 ID、按键的字符串形式。例如: func MyFilter(winid, key) if a:key == "\<F2>" " 自定义逻辑 return 1 endif if a:key == 'x' call popup_close(a:winid) return 1 endif return 0 endfunc popup-filter-mode "filtermode" 属性指定过滤器捕获按键的模式。缺省是 "a": 全部模式。例如改为 "nvi" 时,排除命令行模式,这样就不会拦截命令行输入。不过,要能正常进入命令行模 式,过滤器不能拦截 ":",同样,要能正常进入可视模式,也不能拦截 "v"。 popup-mapping 按键通常先经过映射,因为如果过滤器决定不处理,按键需要作为正常输入传递。如果过 滤器全权接受所有按键,建议将 "mapping" 属性设为零,避免映射干扰过滤器操作。这 是 popup_menu()popup_dialog() 的缺省行为。 推荐按键设计: x 关闭弹窗 (见下面 备注) 光标键 切换选中条目 Tab 确认选中项 按下 CTRL-C 时会直接关闭弹窗,不会进入过滤器。 鼠标点击对应 <LeftMouse> 按键。鼠标坐标可由 getmousepos() 获取。 Vim 内置标准过滤器 popup_filter_menu()popup_filter_yesno():normal 命令执行的按键不会经过过滤器。可用于在置位 "cursorline" 属性的弹窗中 自动移动光标: call win_execute(winid, 'normal! 10Gzz')feedkeys() 生成的按键则会正常经过过滤器拦截。 备注 "x" 是关闭弹窗的标准方法。不建议改用 Esc,因为众多按键产生以 Esc 键开头的 键序列,Vim 识别 Esc 键可能会有延迟。确实想用 Esc 时,建议将 'ttimeoutlen' 选 项设为 100 并置位 'timeout' 和/或 'ttimeout' popup-filter-errors 如果因为过滤器名有误等原因导致过滤函数无法执行,直接关闭弹窗。如果过滤器执行过 程中出错,等价于返回 FALSE。如果连续报错三次,自动关闭弹窗。而错误调用比例不到 10% 时,弹窗不会关闭。 弹 窗 回 调 popup-callback 弹窗关闭时,触发此回调。 回调接受两个参数: 弹出窗口 ID、结果值,后者可以是弹窗选中行的序号,也可以是调 用 popup_close() 时传入的第二个参数。 如果弹窗被强制关闭 (如光标移动或按下 CTRL-C),第二个参数会是 -1。 示例: func SelectedColor(id, result) echo '选中序号是: ' .. a:result endfunc 弹 窗 滚 动 条 popup-scrollbar 弹窗装不下全部文本时,窗口右侧自动显示滚动条。可通过将 "scrollbar" 属性设为零 关闭滚动条。显示滚动条期间,鼠标悬停在弹窗之上用滚轮可正常上下滚动文本。鼠标点 击滚动条上半部会下滚文本一行。点击滚动条下半部会上滚文本一行。但如果导致弹窗可 能变小会停止滚动。 弹 窗 不 透 明 度 popup-opacity "opacity" 属性可使弹出窗口实现半透明效果。不透明度取值范围为 0 到 100: 0 完全透明 - 弹窗背景不可见,下方文本完全显现。 100 完全不透明 (缺省) - 弹窗无任何透明效果。 1–99 部分透明 - 弹窗背景与下方文本混合显示,两者都能部分看见。 透明效果需要 GUI 版本、开启 'termguicolors' 或支持 256-色的终端环境。在少于 256 色的终端上,本属性无效。 弹窗透明渲染规则: - 弹窗的背景色会与下方文本混合 - 弹窗的文本 (前景色) 保持完全清晰、不混合 - 弹窗下方的文本可透过透明区域看见 - 透明度越高 (数值越小),背景文本看得越清晰 用途: - 创建不完全遮挡内容的悬浮提示 - 显示上下文信息,而不阻挡视线 - 创建视觉效果和现代化界面设计 示例 (50% 不透明度): let winid = popup_create('半透明文本', #{ \ line: 5, \ col: 10, \ opacity: 50, \ }) 可通过 popup_setoptions() 动态修改不透明度: call popup_setoptions(winid, #{opacity: 80}) 弹 窗 掩 码 popup-mask 要尽量减少弹窗对文本的遮挡,可使弹窗局部透明。此行为由 "mask" 属性定义,这是二 维列表,即由多个局部区域组成的列表,每个局部区域为包含以下四个数值的列表: col 起始列,正数从左开始计数,1 是最左边,负数从右开始计数,-1 是 最右边 endcol 结束列,规则同 "col" line 起始行,正数从顶开始计数,1 是最顶行,负数从底开始计数,-1 是 最底行 endline 结束行,规则 "line" 例如,要使最后一行的最后 10 列透明: [[-10, -1, -1, -1]] 要使四个角透明: [[1, 1, 1, 1], [-1, -1, 1, 1], [1, 1, -1, -1], [-1, -1, -1, -1]]

4. 示例 popup-examples

以下例子使用 Vim9 脚本语法。 popup_dialog-example 弹出对话框,提示用户按 y/Y 或 n/N: popup_dialog('是否继续?y/n', { filter: 'popup_filter_yesno', callback: (id, result) => { if result == 1 echomsg "按下 'y' 或 'Y'" else echomsg "_没_按 'y' 或 'Y'" endif }, padding: [2, 4, 2, 4], }) popup_menu-shortcut-example 扩展 popup_filter_menu(),增加快捷键: popup_menu(['保存 (S)', '取消 (C)', '丢弃 (D)'], { callback: (_, result) => { echo '对话框结果是 ' result }, filter: (id, key) => { # 处理快捷键 if key == 'S' || key == 's' popup_close(id, 1) elseif key == 'C' || key == 'c' popup_close(id, 2) elseif key == 'D' || key == 'd' popup_close(id, 3) else # 没有快捷键,传递给通用过滤 return popup_filter_menu(id, key) endif return true }, }) popup_beval_example 'ballooneval' 悬浮提示弹窗示例: set ballooneval balloonevalterm set balloonexpr=BalloonExpr() var winid: number var last_text: string def BalloonExpr(): string # 通过 "v:beval_text" 进行实际查找 var text = v:beval_text if winid > 0 && popup_getpos(winid) != null_dict # 还在显示上次弹窗 if text == last_text # 文本不变,保留原有弹窗 return null_string endif popup_close(winid) endif winid = popup_beval(text, {}) last_text = text return null_string enddef 要异步获取提示文本,表达式函数先返回空串,一旦数据就绪,再调用 popup_beval() 显示悬浮窗。下例用定时器调用模拟异步网络请求: set ballooneval balloonevalterm set balloonexpr=BalloonExpr() var winid: number var last_text: string def BalloonExpr(): string var text = v:beval_text if winid > 0 && popup_getpos(winid) != null_dict # 还在显示上次弹窗 if text == last_text # 文本不变,保留原有弹窗 return null_string endif popup_close(winid) endif # 模拟需半秒异步查询,生成显示文本。 last_text = text timer_start(500, 'ShowPopup') return null_string enddef def ShowPopup(timerid: number) winid = popup_beval('查询结果: ' .. last_text, {}) enddef vim:tw=78:ts=8:noet:ft=help:norl: