我想执行以下操作:
autocmd BufAdd * let b:foo = 1
但是正如文档所描述的,此时缓冲区仍然是旧缓冲区,只能由
<abuf>
访问,这是新缓冲区号的作用。注意:执行此自动命令时,当前缓冲区“%”可能与正在创建的缓冲区“
测试表明,就我而言,它永远不是新缓冲区,并且始终为先前缓冲区定义变量。因此,我尝试找出如何使用
<afile>
或<abuf>
设置缓冲区范围的变量。编辑:
从上面的最小示例来看,问题可能还不清楚。设置此变量还有其他条件。因此,并非将要输入的每个缓冲区都获得此变量(因此我能够区分它们)。
编辑2:
因为@DoktorOSwaldo需要更多上下文。
我经常使用预览窗口显示标签等。不幸的是,所有显示的缓冲区都被添加到缓冲区列表中,并且(理论上)浪费了内存的使用。因此,简单的想法是定义一个自动命令,该命令会影响预览窗口中新打开的缓冲区。它必须是新的,因为期望用户自己使用的缓冲区已经打开。如果预览窗口中的缓冲区切换,这些缓冲区将获得不监听的本地选项(
setlocal nobuflisted
),应将其清除。对于工作流情况,尚未打开的缓冲区会在预览窗口中打开,并导致某些情况,用户现在希望编辑该缓冲区并在其他窗口中打开它。如果发生这种情况,我必须将缓冲区设置为再次列出,并且如果不可见就不要擦除。简单检查缓冲区是否已列出的原因,然后也会由许多特殊的缓冲区触发,例如文件浏览器或标签查看器...因此,简单的解决方案应该是将本地变量设置为缓冲区加载到预览窗口中。然后,如果此缓冲区在此窗口之外加载,则可以通过此局部变量对其进行标识。
一些代码行的想法:
augroup PreviewWindow
autocmd!
autocmd BufAdd * if &previewwindow | setlocal nobuflisted |
\ setlocal bufhidden = 'wipe' | let b:preview = v:true | endif
autocmd BufEnter * if ! &previewwindow && exists('b:preview') &&
\ b:preview | setlocal buflisted | setlocal bufhidden = '' |
\ let b:preview = v:false | endif
augroup END
最终解决方案:
这是我的最终实现(现在似乎可以正常运行),通过使用一个标志将两个事件串联在一起。
augroup PreviewWindow
autocmd!
" Global flag for event composition, if a new buffer has been added into the preview window.
let g:new_preview = 0
" -> a buffer is shown in the preview window, that does not exits so far
" In this case the the buffer is not already loaded and setting local variables does not work.
" Set a global flag that mark this event to handle it later on when the buffer is loaded.
autocmd BufAdd * nested if &previewwindow |
\ let g:new_preview = v:true |
\ endif
" -> event that should follow after a (new) buffer has entered to the preview window
" Check if the global flag has been set, that this is a new preview buffer.
" The buffer is now available and local settings and variables can be defined.
" Make sure the buffer gets cleared after it loose its window.
" Set a buffer variable to mark it for further events.
autocmd BufWinEnter * nested if &previewwindow && g:new_preview |
\ let g:new_preview = v:false |
\ setlocal nobuflisted |
\ setlocal bufhidden=wipe |
\ let b:previewonly = v:true |
\ endif
" -> the buffer in the preview window will be opened anywhere else
" In case a buffer is entered, that has the buffer variable to be a 'previewony ' buffer,
" it will be remove from there, added to the buffer list again and will not
" be deleted when not displayed anymore.
autocmd BufEnter * nested
\ try |
\ if b:previewonly |
\ unlet b:previewonly |
\ setlocal buflisted |
\ setlocal bufhidden= |
\ endif |
\ catch |
\ endtry
augroup END
更多背景
由于某些人对于为什么要实现此行为感到困惑,如编辑2中所述,我想对此进行更详尽的解释。也许事实证明我是错的,或者只是一个特别的案例。因此,让我们开始吧:
假设您正在处理三个文件
档案A:
include <File B> as B
include <File C> as C
function main() {
call B.foo()
call B.bar()
}
档案B:
function foo() {
return "foo"
}
文件C:
function bar() {
return "bar"
}
因此,假设我们还有一些工具可以为项目中的每个功能(例如gutentags)生成一个标签。
没想到下面的窗口结构,是什么使得谈论它变得更加容易。
+ ------------------------------------------------- -------------- +
| |
|预览预览
+ ------------------------------ + ------------------ ------------- +
| | |
|档案A文件B
| | |
+ ------------------------------ + ------------------ ------------- +
1.案例
假设使用文件A在左侧窗口中工作。在
foo
函数调用上移动光标,然后在预览窗口中打开光标标签下的单词。由此,文件B显示在预览窗口中,但仍显示在右侧窗口中。对于这种情况,我不想在预览窗口中为缓冲区设置任何属性,因为这会影响我正在积极处理的缓冲区。因此,我的自动命令不应用在预览窗口中打开的新缓冲区。2.案例
继续并对
bar
函数执行相同的操作。因此,将在新缓冲区中打开文件C,该缓冲区将显示在预览窗口中。现在,我想将我的属性应用于此缓冲区。因为文件C的缓冲区不应该在列表中,所以使用bn
或bp
切换缓冲区不会跳转到该缓冲区。此外,我希望该缓冲区在不显示在预览窗口中时立即删除(实际上,在预览窗口中打开其他内容,例如另一个文件中的另一个标签)。这是第二种情况。3.案例
现在的最后一种情况是,如果我使用文件C打开新缓冲区以预览标签并随后确定(它在预览窗口中显示),则必须调整功能
bar
。因此,我手动打开了文件C(在新的拆分中/在文件A / ...的窗口中)。现在,以前隐藏的(不再显示时应删除)将得到我正在处理的“活动”缓冲区。因此,我想决定何时保存此缓冲区,或者关闭或隐藏或...。因此,我必须删除之前添加到该缓冲区的所有属性。另外,我必须承诺使用
CursorHold
事件尝试在光标下方将当前单词作为预览窗口中的标签打开。这是Vims文档/帮助本身的建议,节省了时间,因为它使查找变得更快,并且只有在我停止工作时才生效(例如,考虑当前使用的此函数/对象)。希望这使我的观点更加清楚。
最佳答案
通常,您可以使用expand()
将提到的特殊<afile>
/ <abuf>
转换为缓冲区名称/编号。 setbufvar()
函数可以访问其他缓冲区中的变量。结合起来,这样的事情看起来像是一种可能的方法:
autocmd BufAdd * call setbufvar(expand('<abuf>'), 'foo', 1)
不幸的是,我得到
E94: No matching buffer for 16
;显然,当BufAdd
触发时,尚未为缓冲区变量设置数据结构。备择方案
至少,您获得了缓冲区号,并且可以将其用作(全局)字典中的键来存储您的标志:
let g:foo = {} " Maps buffer numbers to boolean flags
autocmd BufAdd * let g:foo[expand('<abuf>')] = 1
" To check buffer "nr":
if get(g:foo, nr, 0) ...
关于vim - Vim-在自动命令上定义缓冲区变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49492787/