38

I used to use vim during the last years for editing configs and scripts on remote servers. A couple of weeks ago I decided to take the next step and try to use (Mac)vim as my regular editor besides Sublime Text 2. Now I reached a point where I would like to create my first plugin.

My plugin will define ~16 global variables which could be assigned by an user in order to adjust certain properties of the plugin. I asked myself what would be the most elegant way (might be subjective) to check if an user has already assigned his own value to a certain variable. I inspected various other plugins and the "pattern" I see so far seems to be always:

if !exists("g:pluginname_setting")
    let g:pluginname_setting="default"
endif

That seems to be easy and straight forward. But I would always repeat the same piece of code over and over again. Since vi(m) exists for a pretty long time I'm pretty sure people have tried a lot of ways to write plugins and there has been developed some kind of "best practice", which I assume is the "pattern" I gave above as an example. Nevertheless wouldn't it be more elegant to call a function to populate a dictionary which contains all plugin settings and then iterate over the dictionary in order to check the keys to see if an user has already defined his personal preferences? Would that be a good idea or should I rather just drop the idea and stick to the ìf !exists() approach?

Saucier
  • 4,200
  • 1
  • 25
  • 46

2 Answers2

64

There is an elegant way:

let g:pluginname_setting = get(g:, 'pluginname_setting', "default")

I am surprised this is not widely used in plugin settings.

Jérôme
  • 2,640
  • 3
  • 26
  • 39
  • That's because the third argument for the get() function has been added relatively late. Around 7.3.something and many plugins are a lot older – Christian Brabandt Nov 18 '15 at 10:01
  • That's what I thought first, but I tried with a vim version 7.0 and it worked. – Jérôme Nov 19 '15 at 09:29
  • Hm, looks like you are right. I must have thought of a different patch than. – Christian Brabandt Nov 19 '15 at 09:48
  • How to assign a default value as a dictionary? e.g. let default_pluginname_setting = {'name': 'Testing', 'Dir': '../../'}. I tried doing it, but it didn't work as this let g:pluginname_setting = get(g:, 'pluginname_setting', default_pluginname_setting ) – Rohan Ghige Oct 03 '20 at 05:02
  • This is the fourth time now that I specifically search for this answer to copy that code into a new vim plugin. I hope it becomes a standard way to do it; it's very intuitive. – TamaMcGlinn Nov 18 '21 at 16:00
27

The if exists(...) is indeed the canonical configuration idiom and the way to go. Of course, you can do a little meta-programming to reduce the duplication (something like function! s:SetDefault( varname, default )); some plugins do that.

It's good that you intend to allow a great level of customization, on the other hand, unless your plugin deals with a very complex issue (in a text editor?!), 16 config variables is indeed at the high end. You have to consider the effort of documenting all those and testing the various combinations; maybe it's better to start with a simpler reduced approach first and evolve based on user feedback.

Ingo Karkat
  • 167,457
  • 16
  • 250
  • 324
  • Thanks for your answer. :) The plugin will deal with some highlights. So 2/3 of the available vars are related to visual appereance like colors, fg or bg usage in different situations. – Saucier Apr 07 '13 at 15:49
  • For highlights, the usual approach is to `:hi def pluginGroup guifg=...` a default highlighting; this can then be overridden in .vimrc. – Ingo Karkat Apr 07 '13 at 16:08
  • Even if I would override colors of existing hi groups? – Saucier Apr 07 '13 at 16:13
  • It's hard to advise without knowing your exact use case. But no, that won't work for existing groups. – Ingo Karkat Apr 07 '13 at 19:09