View Single Post
03/13/14, 10:44 AM   #3
inDef
Join Date: Mar 2014
Posts: 16
What is LibStub?

Hi All,

I asked the question "What is LibStub?" in the wrong forum on accident. Since I asked that question, I went and did some research and actually figured it out myself.

I'd like to post here my findings/conclusions so that it may help other people who have the same question I did. If you see anything wrong here, please feel free to correct me.

The following block of code is the exact code of LibStub.lua with detailed explanations of everything that is happening. I use the addon "LibAddonMenu-1.0" as an example throughout these explanations...thanks to Seerah for unknowingly allowing me to use his addon as an example

Lua Code:
  1. -- LibStub is a simple "version control" stub of code that ensures you are using the latest
  2. -- version of all libraries that are registered with it...including itself.
  3. -- Example: Your ESO client is running 2 different add-ons and both of them use the
  4. --          library "LibAddonMenu-1.0".  However, one of the add-ons uses minor version 2
  5. --          and the other minor version 4.  LibStub will ensure that the latest version
  6. --          (version 4) is used by both add-ons.
  7.  
  8. local LIBSTUB_MAJOR, LIBSTUB_MINOR = "LibStub", 1
  9.  
  10. -- the _G table is the Lua "environment" where all Global variables are stored.
  11. -- The point of this statement is to see if "LibStub" already exists in memory,
  12. -- or more specifically, was already loaded by another add-on unknown to your add-on.
  13. -- If LibStub has not been loaded yet anywhere, _G[LIBSTUB_MAJOR] will return nil.
  14.  
  15. local LibStub = _G[LIBSTUB_MAJOR]
  16.  
  17. local strformat = string.format
  18. if not LibStub or LibStub.minor < LIBSTUB_MINOR then
  19.  
  20.     --[[
  21.         If you got here, either LibStub was undefined (nil) or the current LibStub in memory has a lesser
  22.         minor revision number than this one.  Assuming LibStub was undefined since this is version 1,
  23.         the following 3 lines create a table titled 'LibStub' which looks like:
  24.        
  25.         LibStub = {
  26.            
  27.             libs = {}
  28.             minors = {}
  29.             minor = 1
  30.        
  31.         }
  32.        
  33.         and sets the global variable "LibStub" equal to this table.  This global table is now the LibStub definition
  34.         for ALL add-ons that use it.
  35.        
  36.         If a newer version of LibStub exists in an add-on somewhere, that version will get used instead since the global
  37.         table "LibStub" will be set there. 
  38.     --]]
  39.  
  40.     LibStub = LibStub or {libs = {}, minors = {} }
  41.     _G[LIBSTUB_MAJOR] = LibStub
  42.     LibStub.minor = LIBSTUB_MINOR
  43.    
  44.    
  45.     -- Register a new library with LibStub
  46.     function LibStub:NewLibrary(major, minor)
  47.    
  48.         assert(type(major) == "string", "Bad argument #2 to `NewLibrary' (string expected)")
  49.         minor = assert(tonumber(zo_strmatch(minor, "%d+")), "Minor version must either be a number or contain a number.")
  50.        
  51.         -- Example:  major = "LibAddonMenu-1.0" and minor = 4
  52.        
  53.         -- oldminor = LibStub.minors["LibAddonMenu-1.0"]
  54.         -- If a version of LibAddonMenu is already loaded into memory, oldminor will contain it's version number.
  55.         -- Otherwise, oldminor = nil.
  56.         local oldminor = self.minors[major]
  57.        
  58.         -- If a version of LibAddonMenu is already in memory AND it's version number is greater than or equal to
  59.         -- the new library, exit the function and return nil.
  60.         if oldminor and oldminor >= minor then return nil end
  61.        
  62.         -- If you got here, that means either this new library doesn't exist in memory or it's a newer version
  63.         -- Set the minor version number of LibAddonMenu to 4.  If LibStud.libs["LibAddonMenu-1.0"] already exists,
  64.         -- continue to use that library.  Otherwise, set to {}.
  65.         -- LibStub.minors["LibAddonMenu-1.0"] = 4, LibStub.libs["LibAddonMenu-1.0"] = LibStub.libs["LibAddonMenu-1.0"] or {}
  66.         self.minors[major], self.libs[major] = minor, self.libs[major] or {}
  67.        
  68.         -- Return the library table and the oldminor version number.
  69.         -- If this is a brand new library (not in memory already) the library table will be empty.
  70.         return self.libs[major], oldminor
  71.        
  72.     end
  73.    
  74.     -- Grabs a library for you to use.  For example, if you want to use the LibAddonMenu-1.0 library
  75.     -- you would call LAM = LibStub:GetLibrary("LibAddonMenu-1.0").  This returns all definitions
  76.     -- of the library (methods, variables, tables, etc.) into your new object LAM.
  77.     function LibStub:GetLibrary(major, silent)
  78.         if not self.libs[major] and not silent then
  79.             error(("Cannot find a library instance of %q."):strformat(tostring(major)), 2)
  80.         end
  81.         return self.libs[major], self.minors[major]
  82.     end
  83.    
  84.     -- See all libraries currently registered with LibStub in memory
  85.     function LibStub:IterateLibraries() return pairs(self.libs) end
  86.    
  87.     -- Allows a shortcut way to call the GetLibrary function.
  88.     -- These two calls become 100% equivalent:
  89.     --   LAM = LibStub:GetLibrary("LibAddonMenu-1.0")
  90.     --   LAM = LibStub("LibAddonMenu-1.0")
  91.     setmetatable(LibStub, { __call = LibStub.GetLibrary })
  92.    
  93. end

If you have any questions please feel free to ask!

Last edited by inDef : 03/13/14 at 10:56 AM.
  Reply With Quote