First off, there are two very good resources that are required reading in addition to what’s provided in the official documentation. Steve Losh’s Learn Vim the Hard Way is an excellent book and I highly recommend it. The IBM Series by Dr. Damian Conway is another great resource. Without these I would not have been able to do what I have achieved, so thanks to them!
Where I started
When I first wrote vim-bufferline and vim-airline I was very much a newbie Vim scripter and I tried to follow as many existing patterns as possible. It was evident that the community at large had a very “C-like” mentality, in that most things were done with functions declared in the global scope (I don’t know if this still holds true for modern C development, but as an expression I think people will get what I’m saying). Many of the older scripts (pre GitHub) tended to be large, single file plugins which lived under the
plugin folder. For example, EasyGrep is a 3000+ line plugin that helps you search and replace in Vim.
Most tutorials also taught writing functions in this fashion (most likely due to simplicity). For example, this is from part 1 of the IBM developer series:
1 2 3 4 5 6 7 8
We all have to start somewhere, but what I found was that these patterns and practices followed beyond their original intention and into plugins.
I think part of the problem is that Vim has a very unique scoping system, in that you can scope variables to a script, window, or buffer, for example. People ended up using this as a form of encapsulation:
1 2 3 4 5 6 7 8 9
g: variables are your exposed public API, and the
s: variables are private. That’s all good, but everything is still global!
Where I am now
There is nothing particular wrong with the approach of using global variables and functions. Many complex software systems have been designed this way with much success, and often times, they perform much faster than counterparts with “objects” and “polymorphism”.
Nonetheless, everything has pros and cons, and the cost of maintenance goes up when you have a bunch of global variables interacting with each other.
The more VimScript I wrote the more I sought for a way to manage complexity and splitting up my code into smaller, manageable pieces.
Let’s take a look at how we can create an object that is transient, has state, and contains methods you can invoke, like any modern OOP language can do.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
You can even take this concept further and replicate “static” functions:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
_ variables/functions are “private”.
Where from here?
Does this mean we should throw out procedural programming and go full on object oriented? Hell no. This is what happens when you go too far! But we should always take a look at what we’re doing and use the best tool and technique for the job. Sometimes that’s procedural, other times it’s object-oriented. It pays to be flexible.