vim - 如何在获取并更改 vim 脚本后卸载它?

标签 vim plugins vim-plugin

我正在编写一个小的 vim 插件,并在进行增量更改时 :source %-ing .vim 文件。

在每次更改和 :source 命令之后,最新的更改似乎没有被加载/应用,所以我想取消 :source/unload以某种方式无需关闭和重新打开 VIm 即可打开文件。

是否有(更好的)方法来做到这一点?编写 VIm 插件和尝试新功能时正确的工作流程应该是什么?

谢谢

最佳答案

为了总结评论。

  • 明确删除定义需要手动删除。
  • 覆盖以前的定义非常容易。请参阅以下内容。

函数和命令:

需要定义函数和命令 -> function! , command!

自动命令

需要清除自动命令。我通常这样做:

augroup MyPluginNameOrFeature
  au! " <- this clears all autocommands defined in the group MyPluginNameOrFeature
  au Event pattern action
aug END

反再收录守卫

需要绕过反重新收录守卫。例如,我的插件通常是这样定义的:

" plugin/foobar.vim
let s:k_version = '100'
if &cp || (exists("g:loaded_foobar")
      \ && (g:loaded_foobar>= s:k_version)
      \ && !exists('g:force_reload_foobar'))
  finish
endif
let g:loaded_foobar= s:k_version
let s:cpo_save=&cpo
set cpo&vim
... plugin definitions (mappings, commands, autocommand, abbreviation)
... understand that functions are in autoload-plugin which don't have anti-reinclusion guards
let &cpo=s:cpo_save

这意味着您必须在保存和重新加载之前增加版本号,或者您需要设置 g:force_reload_foobar在重新加载脚本之前设置为 1。因此我的 :Reload 命令(它与其他两个答案中提供的相同 - 这个支持相对于 'runtimepath' 选项的命令行自动完成)

对象(带方法的字典)

对于我们可以创建的对象:

function! namespace#make_my_object(args)
   let res = {}
   " don't write the following if you want to be able
   " to override the member function definitions when reloading the script
   " and if you want to be able to decode which function appears in 
   " the callstack
   "    :function! res.foo() abort
   "       code
   "    :endfunction
   " Instead write:
   let res.foo = function('s:foo') " with later vim versions
   let res.foo = function(s:getSNR('s:foo')) " with older vim versions

   return res
endfunction

function! s:foo() dict abort
   code
endfunction

function! s:getSNR(...) abort
  " needed to assure compatibility with old vim versions
  if !exists("s:SNR")
    let s:SNR=matchstr(expand('<sfile>'), '<SNR>\d\+_\zegetSNR$')
  endif
  return s:SNR . (a:0>0 ? (a:1) : '')
endfunction

否则如果你已经提取了:let o = namespace#make_my_object(42) ,重新获取脚本不会更新对象方法的定义。 :Reload plugin/foobar.vim | :call o.foo()

全局变量

覆盖/重新初始化一个变量真的很容易。只是给它一个新的值(value)。但是,如果您的 vim 版本不够新,您将无法更改数据类型。在你这边检查 vim 的行为很容易:

let s:foo = 'bar'
let s:foo = {}

如果最后出现错误,您可能需要添加显式 :silent! unlet s:foo .但是,如果您打算通过 vim-client-server 功能和 vimrunner 在 tracis-CI 中测试它,请不要将它留在您的脚本中,一旦提交。而是测试 if exists('s:foo') |unlet s:foo | endif -- :silentredir 中使用时不是那么安静正如 vimrunner 所做的那样。

有时我们不想重新初始化一个变量,而是希望保留之前的值。在这种情况下,请编写如下内容:

let s:foo = get(s:, 'foo', default_value)
let g:foo = get(g:, 'foo', another_default_value)

映射、缩写和菜单

在它们的情况下没什么可做的,因为它们会自动被新定义覆盖。主要要注意的是当你提供<Plug>mappings使用默认和唯一的键绑定(bind)来触发它们。

例如:

nnoremap <silent> <Plug>(some-feature) TheActionToExecute
if !hasmapto('<Plug>(some-feature)', 'n')
  nmap <silent> <unique> <leader>default-keybinding <Plug>(some-feature)
endif

<unique>对于检测歧义/太多想要绑定(bind)到相同键序列的操作非常有用。

这与菜单相同:提供新的定义会覆盖之前的定义。但是将操作绑定(bind)到新的菜单条目(名称和优先级)就像将映射绑定(bind)到新的键序列:旧的不会被删除。充其量你暂时(在你的 vim session 期间)在语义上重载了一些 trigger->action 定义:有几种方法可以触发语义上相同的 Action 。它通常不是那么重要。

杂项

我没有具体说明 ftplugins 或其他脚本类型的情况。我看到的唯一区别与反重新包含保护有关,并且映射、命令和缩写在 ftplugin 的情况下是本地缓冲区。

关于vim - 如何在获取并更改 vim 脚本后卸载它?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40254993/

相关文章:

mysql - 可以在 mysql 插件中使用 thrift 吗?

javascript - 监控来自 IE BHO 的 ajax 调用

vim - gvim 病原体问题

svn - 如何使用findstr,在gvim中排除svn目录

c++ - Vim 中的自动补全

javascript - 如何在更改时获取ckeditor的内容?

vim - 仅使用 Vim 和 Tabular 插件对齐最右边的列

git - 如何返回:Gblame after selecting a particular commit?的结果

Vim langmap 中断插件 (bépo)

java - 将 Vim 用作 Java IDE 的技巧?