如何在获取vim脚本并对其进行更改后卸载?

时间:2016-10-26 06:16:22

标签: vim plugins vim-plugin

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

每次更改和:source命令后,最新的更改似乎都没有加载/应用,所以我想以某种方式取消 - :source /卸载文件关闭并重新开放VIm。

有没有(更好)的方法呢?在编写VIm插件并尝试新功能时,正确的工作流程应该是什么?

由于

3 个答案:

答案 0 :(得分:7)

为了总结评论。

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

功能和命令:

功能和命令需要定义为banged - > 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()

全局变量

覆盖/重新初始化变量非常简单。只要给它一个新的价值。但是,如果您的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 - :silent的测试在redir中作为vimrunner使用时并非静默。

有时我们不想重新初始化变量但保留以前的值。在这种情况下,写下类似的东西:

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

映射,缩写和菜单

在他们的情况下没有太多事要做,因为它们会被新定义自动覆盖。需要注意的主要事项是,当您为<Plug>mappings提供默认和唯一键绑定来触发它们时。

例如:

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

<unique>对于检测歧义/太多想要绑定到同一个键序列的动作非常有用。

与菜单相同:提供新定义会覆盖前一个定义。但是将动作绑定到新的菜单条目(名称和优先级)就像将映射绑定到新的键序列:旧的键序列没有被删除。最好你暂时(在你的vim会话期间)语义上重载一些触发器&gt;动作定义:有几种方法可以触发语义相同的动作。它通常不那么重要。

其它

我还没有特别针对ftplugins的情况,也没有其他脚本类型。我看到的唯一区别是反重新保护,以及在ftplugin的情况下映射,命令和缩写都是缓冲本地的事实。

答案 1 :(得分:3)

一种可能的解决方案是使用Tim Pope编写的vim-scriptease插件。

该插件提供了一个函数:Disarm。以下是doc关于命令的说法:

  

尝试通过删除运行时文件来禁用它   :map s,:command:autocmd s。接受任何一个   绝对的(〜/ .vim / plugin / scriptease.vim)或   runtime-relative(plugin / scriptease.vim)path。

也许这并不完美,因为它不处理初始化的变量,但仍然有用。

答案 2 :(得分:3)

你可能没有看到你所做的更改,因为插件通常有一个多包含保护形式

if exists('g:loaded_name')
    finish
endif
let g:loaded_name = 1

我的ReloadScript plugin使用简单的:ReloadScript命令绕过通常的包含保护变量。

这仍然无法帮助解决不兼容的映射,重命名的autocmd组等问题。对于这些情况,重新启动Vim比尝试撤消当前会话中的所有更改更容易且更健壮。