Lua Modules

Module Pattern

Creating modules
-- my_module.lua
local M = {}

-- Private (local to file)
local function validate(input)
  return type(input) == "string" and #input > 0
end

-- Public (exported via M)
function M.greet(name)
  if validate(name) then
    return "Hello, " .. name
  end
  return "Hello, stranger"
end

M.VERSION = "1.0.0"

return M
Using modules
-- require caches: second require returns same table
local mymod = require("my_module")
print(mymod.greet("Evan"))
print(mymod.VERSION)

-- Require with subdirectories (dot = path separator)
local utils = require("lib.utils")        -- lib/utils.lua
local log   = require("lib.logging")      -- lib/logging.lua

-- Selective import (Lua idiom)
local greet = require("my_module").greet
greet("Evan")

Module Patterns

Common module architectures
-- Config module with defaults
local Config = {}
Config.__index = Config

local defaults = {
  timeout = 30,
  retries = 3,
  verbose = false,
}

function Config.new(opts)
  opts = opts or {}
  local self = setmetatable({}, Config)
  for k, v in pairs(defaults) do
    self[k] = opts[k] ~= nil and opts[k] or v
  end
  return self
end

return Config
Plugin-style module
-- plugin.lua
local M = {}

M.defaults = {
  enabled = true,
  log_level = "info",
}

function M.setup(opts)
  opts = vim.tbl_deep_extend("force", M.defaults, opts or {})
  -- configure the plugin
  if opts.enabled then
    M._init(opts)
  end
end

function M._init(opts)
  -- private initialization
end

return M

Package System

Package path and loading
-- package.path controls where require() looks
print(package.path)
-- ./?.lua;./?/init.lua;/usr/share/lua/5.4/?.lua

-- Add custom path
package.path = package.path .. ";/home/user/lib/?.lua"

-- package.loaded -- cache of loaded modules
-- Force reload
package.loaded["my_module"] = nil
local fresh = require("my_module")

-- package.searchers -- functions that find modules
-- Default: preload, Lua files, C libraries

-- Neovim-specific paths
-- ~/.config/nvim/lua/?.lua
-- ~/.config/nvim/lua/?/init.lua
-- Runtime path modules via vim.loader

LuaRocks

Lua package manager
# Install
luarocks install luasocket
luarocks install --local penlight        # user-local

# List installed
luarocks list

# Search
luarocks search http

# Use in script
luarocks path --bin                       # show paths to set
eval "$(luarocks path --bin)"            # set LUA_PATH/LUA_CPATH