如何覆盖Vim插件中脚本作用域的内部函数?
Great question—this is a common pain point when tweaking Vim plugins for personal use without submitting PRs. Let’s break this down clearly:
First, the hard truth: You can’t directly override a script-scoped s: function from outside its defining script
Vim’s script-scoped functions (prefixed with s:) are intentionally private to the script they’re created in. They aren’t visible or accessible to external files like your ~/.vimrc or other plugins, so you can’t reference or overwrite them using the standard function! syntax. Your attempt to define function! foo() in .vimrc creates a global-scoped function, which is completely separate from the plugin’s s:foo—the plugin will still call its own private s:foo with no change to its behavior.
So what can you do instead? Here are practical workarounds for personal customization:
1. Override the public function that calls s:foo
If the plugin exposes a public function (e.g., in the autoload namespace like plugin#some_public_func()) that internally invokes s:foo, you can overwrite this public function with your own implementation. For example:
Original plugin code (autoload/plugin.vim):
function! plugin#trigger_foo() call s:foo() endfunction function! s:foo() " Original behavior you want to adjust endfunction
Your ~/.vimrc can replace the public function:
function! plugin#trigger_foo() " Your custom logic here instead of calling the original s:foo() echo "My tailored foo behavior!" endfunction
This works because public functions are globally accessible, and the ! suffix lets you overwrite them.
2. Shadow the plugin’s autoload script with your modified version
Vim prioritizes loading scripts from your ~/.vim directory over system-wide or plugin-managed directories. Here’s how to leverage this:
- Copy the original plugin’s
autoload/plugin.vimfile to~/.vim/autoload/plugin.vim - Open your local copy and modify the
s:foofunction directly to match your desired behavior - Vim will load your modified script instead of the original plugin’s version, so all internal calls to
s:foowill use your custom code
Note: Keep in mind that if the plugin updates, your local copy won’t automatically get the changes. You’ll need to merge updates into your modified script manually, or track your changes with a version control system (like Git) to simplify merging later.
3. Check if the plugin supports hooks or custom events
Some plugins offer hooks or user-defined events that trigger before/after functions like s:foo run. If the plugin has this feature, you can register a custom handler to inject your logic. For example, if the plugin emits a User PluginFooPre event before calling s:foo, you can add:
autocmd User PluginFooPre call my_custom_foo_logic()
This depends entirely on the plugin’s design, though—check the plugin’s documentation to see if such hooks exist.
Summary
While you can’t directly overwrite a private s: function from outside its script, you have solid workarounds to achieve your custom behavior. The shadowing method is often the most straightforward for one-off personal changes, while overriding public functions is cleaner if the plugin’s workflow allows it.
内容的提问来源于stack exchange,提问作者weilbith

