I am making a plugin, and it needs to create files and store them and read them back later. Is there a standard folder to do this? If yes, what's that folder and how to get the path for it in the runtime?
1 Answer
There isn't what I'd call a standard place to put files created by your plugin but there are a handful of accepted practices depending on the exact nature of the generated file(s).
Not applicable in your case but worth mentioning is the creation of temporary files. A good idea here is to use methods that are provided by the system for managing such files or, even better, use higher level methods that abstract away the system-specific details (e.g. which directory to store the files in... user's home dir? system wide dir like /tmp
?) Vim provides just such a facility through the tempname()
function. See :help tempname()
if interested.
For non-temporary files one option is to put files in the user's home directory or a newly created subdir thereof. Oftentimes the top level dir name or file name will start with .
so that it is normally hidden in directory listings. You may want to give the user the option of naming this directory/file...or even let them specify any location on disk they'd like to contain the file(s).
The second common approach and one we'll go into a bit more detail on is to store the file(s) in a directory that contains the plugin's own files within Vim's user-specific directory (e.g. ~/.vim
).
We're assuming a typical1 plugin that consists of multiple files packaged in its own directory or directories. Something like this:
vim-myplugin
├── autoload
│ └── myplugin.vim
├── doc
│ └── myplugin.txt
├── plugin
│ └── myplugin.vim
└── README.md
If the user uses one of the common plugin manager's this tree will often be found in a top level directory of the Vim home with a name like "bundle" or "plugin". In any case, we don't want to have to worry about such specifics since they vary from user to user. To allow a dynamic lookup of the plugin location we can use the special keyword <sfile>
.
Let's look at how this is used by an actual plugin, unicode.vim, authored by an esteemed contributor to this site. It provides some nice utilities for managing entry and lookup of Unicode characters. A list of the characters and their codes and definitions is usually downloaded to local disk to allow for quick look-ups of the latest information. The download is done by the autoload script starting with this line
let s:directory = expand("<sfile>:p:h")."/unicode"
That variable will be initialized the first time the script is loaded/sourced. The value of <sfile>
alone would be a path to the script file itself. With the modifiers the value will be the full path (:p
) of the directory containing the script (:h
).
Since that script is in the autoload dir the root of the plugin can be found by adding one more :h
....
let s:pluginroot = expand("<sfile>:p:h:h")
I imagine you can take it from and figure out how to integrate this into your own project.
1 I'd consider single-file plugins less typical and, anyways, not really suited to this use case.
let s:scriptifle = expand("<sfile>")
Whatever file that line of code resides in will be expanded into by<sfile>
.:h :<sfile>
. Put it outside a function and when your plugin code gets source that variable will be initialized