May 24, 2021 Vim
We've written a lot of features for our Potion plug-in, covering what this book is all about. Before we conclude, we'll talk about some very important ways to add to our plug-ins.
The first is to make our plug-ins more efficient with automatic loading.
Currently, when a user loads our plug-in (such as opening a Potion file), all features are loaded. Our plug-ins are still small, so that's probably not a big problem, but for larger plug-ins, loading all the code will result in a perceptible Caton.
Vim solves this problem by using a problem called autoload. A utoload lets you load a portion of your code until you need it. There will be some performance losses, but if the user doesn't always need every line of code for your plug-in, automatic loading will bring a speed leap.
Show me how it works. Take a look at the following command:
:call somefile#Hello()
When you execute this command, Vim behaves a little differently from the usual function calls.
If the function is already loaded, Vim simply calls it as usual.
Otherwise Vim
~/.vim
look for a file called
autoload/somefile.vim
under your
~/.vim/bundles/对应的插件/autoload
plug-in/autoload.
If the file exists, Vim loads/sources the file. Vim then calls it as usual.
In this file, the function should be defined as this:
function somefile#Hello()
" ...
endfunction
You can use more than one s in a
#
to represent a subdirecte.
For example:
:call myplugin#somefile#Hello()
This will
autoload/myplugin/somefile.vim
autoload file.
The functions inside need to be defined using an absolute path that is automatically loaded:
function myplugin#somefile#Hello()
" ...
endfunction
To better understand autoloading, let's experiment.
Create a file
~/.vim/autoload/example.vim
and add the following:
echom "Loading..."
function! example#Hello()
echom "Hello, world!"
endfunction
echom "Done loading."
Save the file and
:call example#Hello()
Vim will output the following:
Loading...
Done loading.
Hello, world!
This little demo proves a few things:
example.vim
through.
It doesn't exist when we turn on Vim, so it can't be loaded at startup.
Don't turn off Vim first, modify the definition of a function like this:
echom "Loading..."
function! example#Hello()
echom "Hello AGAIN, world!"
endfunction
echom "Done loading."
Save the file
and don't close Vim,
:call example#Hello()
Vim will simply output:
Hello, world!
Vim already has
example#Hello
so it no longer needs to reload the file, which means:
Now
:call example#BadFunction()
O
nce again, you'll see the load information, accompanied by an error that doesn't exist for a function. B
ut now try to do
:call example#Hello()
This time you'll see the updated information!
So far you should have a clear idea of how Vim handles function calls of an autoload type:
If you still haven't figured it out, go back to the previous demo and watch where each rule takes effect.
Autoloading is not without defects. With automatic loading set, there will be some (small) running overhead, not to mention you have to tolerate ugly function names in your code.
Because of this, if you're not writing a plug-in that users will use every time they open a Vim conversation, it's a good idea to try to move the functional code to the autoload file. This will reduce the impact of your plug-ins when users start Vim, especially today when more and more plug-ins are installed.
So what can be safely loaded automatically? T hose parts that are not called directly by your users. Maps and custom commands cannot be loaded automatically (because they need to be called by the user), but many other things can be.
Let's see what's in the Potion plug-in that can be loaded automatically.
We'll start with compiling and executing functions.
At the end of the previous chapter,
ftplugin/potion/running.vim
probably like this:
if !exists("g:potion_command")
let g:potion_command = "/Users/sjl/src/potion/potion"
endif
function! PotionCompileAndRunFile()
silent !clear
execute "!" . g:potion_command . " " . bufname("%")
endfunction
function! PotionShowBytecode()
" Get the bytecode.
let bytecode = system(g:potion_command . " -c -V " . bufname("%"))
" Open a new split and set it up.
vsplit __Potion_Bytecode__
normal! ggdG
setlocal filetype=potionbytecode
setlocal buftype=nofile
" Insert the bytecode.
call append(0, split(bytecode, '\v\n'))
endfunction
nnoremap <buffer> <localleader>r :call PotionCompileAndRunFile()<cr>
nnoremap <buffer> <localleader>b :call PotionShowBytecode()<cr>
This file is called only when the Potion file is loaded, so it usually does not affect Vim's startup time. But there may be some users who just don't want these features, so if we can load parts automatically, we can save them milliseconds each time we open a Potion file.
Yes, we won't save much in this case. But you can imagine that there might be a plug-in that includes thousands of lines of code that can be loaded automatically to reduce each load time.
Let's get started. C
reate an
autoload/potion/running.vim
Then move the two functions in and modify their names to make them look like:
echom "Autoloading..."
function! potion#running#PotionCompileAndRunFile()
silent !clear
execute "!" . g:potion_command . " " . bufname("%")
endfunction
function! potion#running#PotionShowBytecode()
" Get the bytecode.
let bytecode = system(g:potion_command . " -c -V " . bufname("%"))
" Open a new split and set it up.
vsplit __Potion_Bytecode__
normal! ggdG
setlocal filetype=potionbytecode
setlocal buftype=nofile
" Insert the bytecode.
call append(0, split(bytecode, '\v\n'))
endfunction
Notice
potion#running
section match the path they are in.
Now modify
ftplugin/potion/running.vim
file like this:
if !exists("g:potion_command")
let g:potion_command = "/Users/sjl/src/potion/potion"
endif
nnoremap <buffer> <localleader>r
\ :call potion#running#PotionCompileAndRunFile()<cr>
nnoremap <buffer> <localleader>b
\ :call potion#running#PotionShowBytecode()<cr>
Save the file, close Vim, and then
factorial.pn
file.
Try these maps to make sure they still work.
Make sure you only see the diagnostic information
Autoloading...
the first time you perform one of the mappings... (
You may need to
:message
to see).
Once you think autoloading works, you can remove that information.
As you can see, we leave
nnoremap
mapping section unchanged.
We can't load them automatically, otherwise users won't be able to trigger autoloads!
You'll see it all in the Vim plug-in: most of the features will be in the
nnoremap
command
s loaded by Vim each time.
Don't forget this every time you write a useful Vim plug-in.
Read
:help autoload
Test it a little and figure out what it's like to load variables automatically.
Suppose you want to force the loading of an autoload file that Vim has already loaded, and it doesn't bother the user. W
hat would you do? Y
ou may want to
:help silent!
(
This should be
:help :silent
But don't do that in real life.