Hooks

A custom hooks system for your LUA script

Do Action / Add Action

Definitions

doAction(name: string, context: any [, context2 ...]) -> nil
addAction(name: string, callback: function, opt priority: integer) -> nil

Usage example

init.lua
registerForEvent('oninit', function()
    
    -- execute all addAction() using this name
    doAction('my_action', 'init', 'something')
    
end)
my_script.lua
addAction('my_action', function(context, context2)

    -- context  = 'init'
    -- context2 = 'something'
    -- do something
    
end, 10)
my_script_2.lua
addAction('my_action', function(context, context2)

    -- context  = 'init'
    -- context2 = 'something'
    -- do something before (note the priority: 5)
    
end, 5)

Apply Filters / Add Filter

Definitions

applyFilters(name: string, value: any, context: any [, context2 ...]) -> nil
addFilter(name: string, callback: function, opt priority: integer) -> nil

Usage example

init.lua
registerForEvent('oninit', function()

    local myVar = 'yes'
    
    myVar = applyFilters('my_filter', myVar, 'init', 'something')
    
    print(myVar)
    -- no
    
end)
my_script.lua
addFilter('my_filter', function(myVar, context, context2)

    -- myVar    = 'maybe' (set by the other filter with priortiy: 5)
    -- context  = 'init'
    -- context2 = 'something'
    
    -- update myVar to 'no'
    return 'no'
    
end, 10)
my_script_2.lua
addFilter('my_filter', function(myVar, context, context2)
    
    -- myVar    = 'yes' (set by initial applyFilters())
    -- context  = 'init'
    -- context2 = 'something'
    
    -- update myVar to 'maybe' (note the priority: 5)
    return 'maybe'
    
end, 5)

Source Code

local this

this = {

    storage = {
        actions = {},
        filters = {}
    },

    addAction = function(action, callback, priority, context)

        if type(action) == 'string' and type(callback) == 'function' then
            priority = tonumber(priority or 10)

            this._addHook('actions', action, callback, priority, context)
        end

        return this

    end,

    doAction = function(...)
        local args = { ... }
        local action = table.remove(args, 1)

        if type(action) == 'string' then
            this._runHook('actions', action, args)
        end

        return this
    end,

    removeAction = function(action, callback)
        if type(action) == 'string' then
            this._removeHook('actions', action, callback)
        end

        return this
    end,

    addFilter = function(filter, callback, priority, context)
        if type(filter) == 'string' and type(callback) == 'function' then
            priority = tonumber(priority or 10)

            this._addHook('filters', filter, callback, priority, context)
        end

        return this
    end,

    applyFilters = function(...)
        local args = { ... }
        local filter = table.remove(args, 1)

        if type(filter) == 'string' then
            return this._runHook('filters', filter, args)
        end

        return this
    end,

    removeFilter = function(filter, callback)
        if type(filter) == 'string' then
            this._removeHook('filters', filter, callback)
        end

        return this
    end,

    _removeHook = function(type, hook, callback, context)

        if not this.storage[type][hook] then
            return
        end

        if not callback then
            this.storage[type][hook] = {}

        else
            local handlers = this.storage[type][hook]
            --local i

            if not context then
                for i = #handlers, 1, -1 do
                    if handlers[i].callback == callback then
                        table.remove(handlers, i)
                    end
                end
            else
                for i = #handlers, 1, -1 do
                    local handler = handlers[i]

                    if handler.callback == callback and handler.context == context then
                        table.remove(handlers, i)
                    end
                end
            end
        end
    end,

    _addHook = function(type, hook, callback, priority, context)

        local hookObject = {
            callback = callback,
            priority = priority,
            context = context
        }

        local hooks = this.storage[type][hook]

        if hooks then
            table.insert(hooks, hookObject)
            hooks = this._hookInsertSort(hooks)
        else
            hooks = { hookObject }
        end

        this.storage[type][hook] = hooks
    end,

    _hookInsertSort = function(hooks)
        local tmpHook, j, prevHook

        for i = 2, #hooks do
            tmpHook = hooks[i]
            j = i

            prevHook = hooks[j - 1]
            while prevHook and prevHook.priority > tmpHook.priority do
                hooks[j] = hooks[j - 1]
                j = j - 1
                prevHook = hooks[j - 1]
            end

            hooks[j] = tmpHook
        end

        return hooks
    end,

    _runHook = function(type, hook, args)

        local handlers = this.storage[type][hook]

        if not handlers then
            return type == 'filters' and args[1] or false
        end

        local i = 1
        local len = #handlers

        if type == 'filters' then
            for i = 1, len do
                args[1] = handlers[i].callback(unpack(args))
            end
        else
            for i = 1, len do
                handlers[i].callback(unpack(args))
            end
        end

        return type == 'filters' and args[1] or true

    end


}

-- history storage
local actionHistory = {}

addAction = function(...)
    this.addAction(...)
    return this
end

removeAction = function(...)
    this.removeAction(...)
    return this
end

doAction = function(...)
    local args = {...}
    local action = args[1]

    actionHistory[action] = 1
    this.doAction(...)
    actionHistory[action] = 0
    return this
end

doingAction = function(action)
    return actionHistory[action] == 1
end

didAction = function(action)
    return actionHistory[action] ~= nil
end

currentAction = function()
    for k in pairs(actionHistory) do
        if actionHistory[k] then
            return k
        end
    end

    return false
end

addFilter = function(...)
    this.addFilter(...)
    return this
end

removeFilter = function(...)
    this.removeFilter(...)
    return this
end

applyFilters = function(...)
    return this.applyFilters(...)
end

Last updated